1<?php
2/**
3 * Simple page modifying action for the bureaucracy plugin
4 *
5 * @author Darren Hemphill <darren@baseline-remove-this-it.co.za>
6 */
7class helper_plugin_pagemod_pagemod extends helper_plugin_bureaucracy_action {
8
9    var $patterns;
10    var $values;
11    protected $template_section_id;
12
13    /**
14     * Handle the user input [required]
15     *
16     * @param helper_plugin_bureaucracy_field[] $fields the list of fields in the form
17     * @param string                            $thanks the thank you message as defined in the form
18     *                                                  or default one. Might be modified by the action
19     *                                                  before returned
20     * @param array                             $argv   additional arguments passed to the action
21     * @return bool|string false on error, $thanks on success
22     */
23    public function run($fields, $thanks, $argv) {
24        global $ID;
25
26        // prepare replacements
27        $this->prepareNamespacetemplateReplacements();
28        $this->prepareDateTimereplacements();
29        $this->prepareLanguagePlaceholder();
30        $this->prepareNoincludeReplacement();
31        $this->prepareFieldReplacements($fields);
32
33        //handle arguments
34        $page_to_modify = array_shift($argv);
35        if($page_to_modify === '_self') {
36            # shortcut to modify the same page as the submitter
37            $page_to_modify = $ID;
38        } else {
39            //resolve against page which contains the form
40            resolve_pageid(getNS($ID), $page_to_modify, $ignored);
41        }
42
43        $template_section_id = cleanID(array_shift($argv));
44
45        if(!page_exists($page_to_modify)) {
46            msg(sprintf($this->getLang('e_pagenotexists'), html_wikilink($page_to_modify)), -1);
47            return false;
48        }
49
50        // check auth
51        //
52        // This is an important point.  In order to be able to modify a page via this method ALL you need is READ access to the page
53        // This is good for admins to be able to only allow people to modify a page via a certain method.  If you want to protect the page
54        // from people to WRITE via this method, deny access to the form page.
55        $auth = $this->aclcheck($page_to_modify); // runas
56        if($auth < AUTH_READ) {
57            msg($this->getLang('e_denied'), -1);
58            return false;
59        }
60
61        // fetch template
62        $template = rawWiki($page_to_modify);
63        if(empty($template)) {
64            msg(sprintf($this->getLang('e_template'), $page_to_modify), -1);
65            return false;
66        }
67
68        // do the replacements
69        $template = $this->updatePage($template, $template_section_id);
70        if(!$template) {
71            msg(sprintf($this->getLang('e_failedtoparse'), $page_to_modify), -1);
72            return false;
73        }
74        // save page
75        saveWikiText($page_to_modify, $template, sprintf($this->getLang('summary'), $ID));
76
77        //thanks message with redirect
78        $link = wl($page_to_modify);
79        return sprintf(
80            $this->getLang('pleasewait'),
81            "<script type='text/javascript' charset='utf-8'>location.replace('$link')</script>", // javascript redirect
82            html_wikilink($page_to_modify) //fallback url
83        );
84    }
85
86    /**
87     * (callback) Returns replacement for meta variabels (value generated at execution time)
88     *
89     * @param $arguments
90     * @return bool|string
91     */
92    public function getMetaValue($arguments) {
93        global $INFO;
94        # this function gets a meta value
95
96        $label = $arguments[1];
97                              //print_r($INFO);
98        if($label == 'date') {
99            return date("d/m/Y");
100
101        } elseif($label == 'datetime') {
102            return date("c");
103
104        } elseif(preg_match('/^date\.format\.(.*)$/', $label, $matches)) {
105            return date($matches[1]);
106
107        } elseif($label == 'user' || $label == 'user.id') {
108            return $INFO['client'];
109
110        } elseif(preg_match('/^user\.(mail|name)$/', $label, $matches)) {
111            return $INFO['userinfo'][$matches[1]];
112
113        } elseif($label == 'page' || $label == 'page.id') {
114            return $INFO['id'];
115
116        } elseif($label == 'page.namespace') {
117            return $INFO['namespace'];
118
119        } elseif($label == 'page.name') {
120            return noNs($INFO['id']);
121        }
122        return '';
123    }
124
125    /**
126     * Update the page with new content
127     *
128     * @param string $template
129     * @param string $template_section_id
130     * @return string
131     */
132    protected function updatePage($template, $template_section_id) {
133        $this->template_section_id = $template_section_id;
134        return preg_replace_callback('/<pagemod (\w+)(?: (.+?))?>(.*?)<\/pagemod>/s', array($this, 'parsePagemod'), $template);
135    }
136
137    /**
138     * (callback) Build replacement that is inserted before of after <pagemod> section
139     *
140     * @param $matches
141     * @return string
142     */
143    public function parsePagemod($matches) {
144        // Get all the parameters
145        $full_text     = $matches[0];
146        $id            = $matches[1];
147        $params_string = $matches[2];
148        $contents      = $matches[3];
149
150        // First parse the parameters
151        $output_before = true;
152        if($params_string) {
153            $params = array_map('trim', explode(",", $params_string));
154            foreach($params as $param) {
155                if($param === 'output_after') {
156                    $output_before = false;
157                }
158            }
159        }
160
161        // We only parse if this template is being matched (Allow multiple forms to update multiple sections of a page)
162        if($id === $this->template_section_id) {
163            //replace meta variables
164            $output = preg_replace_callback('/@@meta\.(.*?)@@/', array($this, 'getMetaValue'), $contents);
165            //replace bureacracy variables
166            $output = $this->replace($output);
167
168            if($output_before) {
169                return $output . $full_text;
170            } else {
171                return $full_text . $output;
172            }
173        } else {
174            return $full_text;
175        }
176    }
177
178}
179// vim:ts=4:sw=4:et:enc=utf-8:
180