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