xref: /plugin/approve/action/approve.php (revision af3e3cd8978d221000bc1a1e65ffc674af729866)
1<?php
2
3if(!defined('DOKU_INC')) die();
4define(APPROVED, 'Approved');
5
6define(METADATA_VERSION_KEY, 'plugin_approve_version');
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('PARSER_METADATA_RENDER', 'AFTER', $this, 'handle_parser_metadata_render');
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 $ID, $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, $REV, $INFO;
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    function handle_viewer(Doku_Event $event, $param) {
65        global $REV, $ID;
66        if ($event->data != 'show') return;
67        if (auth_quickaclcheck($ID) > AUTH_READ || ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID))) return;
68
69	    $last = $this->find_lastest_approved();
70	    //no page is approved
71		if ($last == -1) return;
72		//approved page is the newest page
73		if ($last == 0) return;
74
75		//if we are viewing lastest revision, show last approved
76		if ($REV == 0) header("Location: ?id=$ID&rev=$last");
77	}
78	function find_lastest_approved() {
79		global $ID;
80		$m = p_get_metadata($ID);
81		$sum = $m['last_change']['sum'];
82		if ($sum == APPROVED)
83			return 0;
84
85		$changelog = new PageChangeLog($ID);
86		//wyszukaj najnowszej zatwierdzonej
87		//poszukaj w dół
88		$chs = $changelog->getRevisions(0, 10000);
89		foreach ($chs as $rev) {
90			$ch = $changelog->getRevisionInfo($rev);
91			if ($ch['sum'] == APPROVED)
92				return $rev;
93		}
94		return -1;
95	}
96
97    function handle_display_banner(Doku_Event $event, $param) {
98		global $ID, $REV, $INFO;
99
100		if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID)) return;
101        if ($event->data != 'show') return;
102		if (!$INFO['exists']) return;
103
104		$sum = $this->hlp->page_sum($ID, $REV);
105
106		ptln('<div class="approval '.($sum == APPROVED ? 'approved_yes' : 'approved_no').'">');
107
108		tpl_pageinfo();
109		ptln(' | ');
110		$last_approved_rev = $this->find_lastest_approved();
111		if ($sum == APPROVED) {
112		    $version = p_get_metadata($ID, METADATA_VERSION_KEY);
113
114			ptln('<span>'.$this->getLang('approved').' (' . $this->getLang('version') .  ': ' . $version
115                 . ')</span>');
116			if ($REV != 0 && auth_quickaclcheck($ID) > AUTH_READ) {
117				ptln('<a href="'.wl($ID).'">');
118				ptln($this->getLang(p_get_metadata($ID, 'last_change sum') == APPROVED ? 'newest_approved' : 'newest_draft'));
119				ptln('</a>');
120			} else if ($REV != 0 && $REV != $last_approved_rev) {
121				ptln('<a href="'.wl($ID).'">');
122				ptln($this->getLang('newest_approved'));
123				ptln('</a>');
124			}
125		} else {
126			ptln('<span>'.$this->getLang('draft').'</span>');
127
128			if ($last_approved_rev == -1) {
129			    if ($REV != 0) {
130				    ptln('<a href="'.wl($ID).'">');
131				    	ptln($this->getLang('newest_draft'));
132				    ptln('</a>');
133				}
134			} else {
135				if ($last_approved_rev != 0)
136					ptln('<a href="'.wl($ID, array('rev' => $last_approved_rev)).'">');
137				else
138					ptln('<a href="'.wl($ID).'">');
139
140					ptln($this->getLang('newest_approved'));
141				ptln('</a>');
142			}
143
144			//można zatwierdzać tylko najnowsze strony
145			if ($REV == 0 && $this->can_approve()) {
146				ptln('<a href="'.wl($ID, array('rev' => $last_approved_rev, 'do' => 'diff',
147				'approve' => 'approve')).'">');
148					ptln($this->getLang('approve'));
149				ptln('</a>');
150			}
151		}
152		ptln('</div>');
153	}
154
155    /**
156     * Check if the page has to be changed
157     *
158     * @param Doku_Event $event  event object by reference
159     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
160     *                           handler was registered]
161     * @return void
162     */
163    public function handle_pagesave_before(Doku_Event $event, $param) {
164        $id = $event->data['id'];
165        if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $id)) return;
166
167        //save page if summary is provided
168        if($event->data['summary'] == APPROVED) {
169            $event->data['contentChanged'] = true;
170
171            $version = p_get_metadata($id, METADATA_VERSION_KEY);
172
173            //calculate current version
174            if (!$version) {
175                $version = $this->calculateVersion($id);
176            } else {
177                $version += 1;
178            }
179
180            p_set_metadata($id, array(METADATA_VERSION_KEY => $version));
181        }
182    }
183
184    /**
185     * Check if the page has to be changed
186     *
187     * @param Doku_Event $event  event object by reference
188     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
189     *                           handler was registered]
190     * @return void
191     */
192    public function handle_parser_metadata_render(Doku_Event $event, $param) {
193        global $ID;
194        $id = $ID;
195        if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $id)) return;
196
197        if (!isset($event->data['persistent'][METADATA_VERSION_KEY])) {
198            $event->data['persistent'][METADATA_VERSION_KEY] = $this->calculateVersion($id);
199        }
200
201
202    }
203
204    /**
205     * Calculate current version
206     *
207     * @param $id
208     * @return int
209     */
210    protected function calculateVersion($id) {
211        $version = 1;
212
213        $changelog = new PageChangeLog($id);
214        $first = 0;
215        $num = 100;
216        while (count($revs = $changelog->getRevisions($first, $num)) > 0) {
217            foreach ($revs as $rev) {
218                $revInfo = $changelog->getRevisionInfo($rev);
219                if ($revInfo['sum'] == APPROVED) {
220                    $version += 1;
221                }
222            }
223            $first += $num;
224        }
225
226        return $version;
227    }
228
229}
230