xref: /plugin/approve/action/approve.php (revision 55f447f4b2c788699fdccdbce99e3ff91d5d0e1c)
1<?php
2
3if(!defined('DOKU_INC')) die();
4define(APPROVED, 'Approved');
5
6define(METADATA_VERSIONS_KEY, 'plugin_approve_versions');
7
8class action_plugin_approve_approve extends DokuWiki_Action_Plugin {
9
10    private $hlp;
11    function __construct(){
12        $this->hlp = plugin_load('helper', 'approve');
13    }
14
15    function register(Doku_Event_Handler $controller) {
16
17        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_approve', array());
18        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_viewer', array());
19        $controller->register_hook('TPL_ACT_RENDER', 'AFTER', $this, 'handle_diff_accept', array());
20        $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'handle_display_banner', array());
21        $controller->register_hook('HTML_SHOWREV_OUTPUT', 'BEFORE', $this, 'handle_showrev', array());
22        // ensure a page revision is created when summary changes:
23        $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'handle_pagesave_before');
24        $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handle_pagesave_after');
25    }
26
27	function handle_diff_accept(Doku_Event $event, $param) {
28		global $ID;
29
30		if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID)) return;
31
32		if ($event->data == 'diff' && isset($_GET['approve'])) {
33			ptln('<a href="'.DOKU_URL.'doku.php?id='.$_GET['id'].'&approve=approve">'.$this->getLang('approve').'</a>');
34		}
35	}
36
37	function handle_showrev(Doku_Event $event, $param) {
38		global $REV;
39
40		$last = $this->find_lastest_approved();
41		if ($last == $REV)
42			$event->preventDefault();
43	}
44
45	function can_approve() {
46		global $ID;
47		return auth_quickaclcheck($ID) >= AUTH_DELETE;
48	}
49
50	function handle_approve(Doku_Event $event, $param) {
51		global $ID;
52
53		if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID)) return;
54
55		if ($event->data == 'show' && isset($_GET['approve'])) {
56		    if ( ! $this->can_approve()) return;
57
58		    //create new page revison
59            saveWikiText($ID, rawWiki($ID), APPROVED);
60
61			header('Location: ?id='.$ID);
62		}
63	}
64
65    function handle_viewer(Doku_Event $event, $param) {
66        global $REV, $ID;
67        if ($event->data != 'show') return;
68        if (auth_quickaclcheck($ID) > AUTH_READ || ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID))) return;
69
70	    $last = $this->find_lastest_approved();
71	    //no page is approved
72		if ($last == -1) return;
73		//approved page is the newest page
74		if ($last == 0) return;
75
76		//if we are viewing lastest revision, show last approved
77		if ($REV == 0) header("Location: ?id=$ID&rev=$last");
78	}
79
80	function find_lastest_approved() {
81		global $ID;
82		$m = p_get_metadata($ID);
83		$sum = $m['last_change']['sum'];
84		if ($sum == APPROVED)
85			return 0;
86
87		$changelog = new PageChangeLog($ID);
88		//wyszukaj najnowszej zatwierdzonej
89		//poszukaj w dół
90		$chs = $changelog->getRevisions(0, 10000);
91		foreach ($chs as $rev) {
92			$ch = $changelog->getRevisionInfo($rev);
93			if ($ch['sum'] == APPROVED)
94				return $rev;
95		}
96		return -1;
97	}
98
99    function handle_display_banner(Doku_Event $event, $param) {
100		global $ID, $REV, $INFO;
101
102		if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID)) return;
103        if ($event->data != 'show') return;
104		if (!$INFO['exists']) return;
105
106		$sum = $this->hlp->page_sum($ID, $REV);
107
108
109		$classes = array();
110		if ($this->getConf('prettyprint')) {
111		    $classes[] = 'plugin__approve_noprint';
112        }
113
114        if ($sum == APPROVED) {
115		    $classes[] = 'plugin__approve_green';
116        } else {
117            $classes[] = 'plugin__approve_red';
118        }
119
120		ptln('<div id="plugin__approve" class="' . implode(' ', $classes) . '">');
121
122		tpl_pageinfo();
123		ptln(' | ');
124		$last_approved_rev = $this->find_lastest_approved();
125		if ($sum == APPROVED) {
126		    $versions = p_get_metadata($ID, METADATA_VERSIONS_KEY);
127		    if (!$versions) {
128                $versions = $this->render_metadata_for_approved_page($ID);
129            }
130            if (empty($REV)) {
131                $version = $versions[0];
132            } else {
133                $version = $versions[$REV];
134            }
135
136			ptln('<strong>'.$this->getLang('approved').'</strong> (' . $this->getLang('version') .  ': ' . $version
137                 . ')');
138			if ($REV != 0 && auth_quickaclcheck($ID) > AUTH_READ) {
139				ptln('<a href="'.wl($ID).'">');
140				ptln($this->getLang(p_get_metadata($ID, 'last_change sum') == APPROVED ? 'newest_approved' : 'newest_draft'));
141				ptln('</a>');
142			} else if ($REV != 0 && $REV != $last_approved_rev) {
143				ptln('<a href="'.wl($ID).'">');
144				ptln($this->getLang('newest_approved'));
145				ptln('</a>');
146			}
147		} else {
148			ptln('<span>'.$this->getLang('draft').'</span>');
149
150			if ($last_approved_rev == -1) {
151			    if ($REV != 0) {
152				    ptln('<a href="'.wl($ID).'">');
153				    	ptln($this->getLang('newest_draft'));
154				    ptln('</a>');
155				}
156			} else {
157				if ($last_approved_rev != 0)
158					ptln('<a href="'.wl($ID, array('rev' => $last_approved_rev)).'">');
159				else
160					ptln('<a href="'.wl($ID).'">');
161
162					ptln($this->getLang('newest_approved'));
163				ptln('</a>');
164			}
165
166			//można zatwierdzać tylko najnowsze strony
167			if ($REV == 0 && $this->can_approve()) {
168				ptln('<a href="'.wl($ID, array('rev' => $last_approved_rev, 'do' => 'diff',
169				'approve' => 'approve')).'">');
170					ptln($this->getLang('approve'));
171				ptln('</a>');
172			}
173		}
174		ptln('</div>');
175	}
176
177    /**
178     * Check if the page has to be changed
179     *
180     * @param Doku_Event $event  event object by reference
181     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
182     *                           handler was registered]
183     * @return void
184     */
185    public function handle_pagesave_before(Doku_Event $event, $param) {
186        global $REV;
187        $id = $event->data['id'];
188        if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $id)) return;
189
190        //save page if summary is provided
191        if($event->data['summary'] == APPROVED) {
192            $event->data['contentChanged'] = true;
193        }
194    }
195
196    /**
197     * @param Doku_Event $event
198     * @param            $param
199     */
200    public function handle_pagesave_after(Doku_Event $event, $param) {
201        global $REV;
202        $id = $event->data['id'];
203        if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $id)) return;
204
205        //save page if summary is provided
206        if($event->data['summary'] == APPROVED) {
207
208            $versions = p_get_metadata($id, METADATA_VERSIONS_KEY);
209            //calculate versions
210            if (!$versions) {
211                $this->render_metadata_for_approved_page($id, $event->data['newRevision']);
212            } else {
213                $curver = $versions[0] + 1;
214                $versions[0] = $curver;
215                $versions[$event->data['newRevision']] = $curver;
216                p_set_metadata($id, array(METADATA_VERSIONS_KEY => $versions));
217            }
218        }
219    }
220
221
222    /**
223     * Calculate current version
224     *
225     * @param $id
226     * @return int
227     */
228    protected function render_metadata_for_approved_page($id, $currev=false) {
229        if (!$currev) $currev = @filemtime(wikiFN($id));
230
231        $version = $this->approved($id);
232        //version for current page
233        $curver = $version + 1;
234        $versions = array(0 => $curver, $currev => $curver);
235
236        $changelog = new PageChangeLog($id);
237        $first = 0;
238        $num = 100;
239        while (count($revs = $changelog->getRevisions($first, $num)) > 0) {
240            foreach ($revs as $rev) {
241                $revInfo = $changelog->getRevisionInfo($rev);
242                if ($revInfo['sum'] == APPROVED) {
243                    $versions[$rev] = $version;
244                    $version -= 1;
245                }
246            }
247            $first += $num;
248        }
249
250        p_set_metadata($id, array(METADATA_VERSIONS_KEY => $versions));
251
252        return $versions;
253    }
254
255    /**
256     * Get the number of approved pages
257     * @param $id
258     * @return int
259     */
260    protected function approved($id) {
261        $count = 0;
262
263        $changelog = new PageChangeLog($id);
264        $first = 0;
265        $num = 100;
266        while (count($revs = $changelog->getRevisions($first, $num)) > 0) {
267            foreach ($revs as $rev) {
268                $revInfo = $changelog->getRevisionInfo($rev);
269                if ($revInfo['sum'] == APPROVED) {
270                    $count += 1;
271                }
272            }
273            $first += $num;
274        }
275
276        return $count;
277    }
278}
279