xref: /plugin/strata/action.php (revision 5153720fcc1dd2b6e63035d45f7c2bc32e429371)
1*5153720fSfkaag71<?php
2*5153720fSfkaag71/**
3*5153720fSfkaag71 * DokuWiki Plugin strata (Action Component)
4*5153720fSfkaag71 *
5*5153720fSfkaag71 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6*5153720fSfkaag71 * @author  Brend Wanders <b.wanders@utwente.nl>
7*5153720fSfkaag71 */
8*5153720fSfkaag71
9*5153720fSfkaag71// must be run within Dokuwiki
10*5153720fSfkaag71if (!defined('DOKU_INC')) die('Meh.');
11*5153720fSfkaag71
12*5153720fSfkaag71/**
13*5153720fSfkaag71 * This action component exists to allow the definition of
14*5153720fSfkaag71 * the type autoloader.
15*5153720fSfkaag71 */
16*5153720fSfkaag71class action_plugin_strata extends DokuWiki_Action_Plugin {
17*5153720fSfkaag71
18*5153720fSfkaag71    /**
19*5153720fSfkaag71     * Register function called by DokuWiki to allow us
20*5153720fSfkaag71     * to register events we're interested in.
21*5153720fSfkaag71     *
22*5153720fSfkaag71     * @param controller object the controller to register with
23*5153720fSfkaag71     */
24*5153720fSfkaag71    public function register(Doku_Event_Handler $controller) {
25*5153720fSfkaag71        $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, '_io_page_write');
26*5153720fSfkaag71        $controller->register_hook('PARSER_METADATA_RENDER', 'BEFORE', $this, '_parser_metadata_render_before');
27*5153720fSfkaag71        $controller->register_hook('STRATA_PREVIEW_METADATA_RENDER', 'BEFORE', $this, '_parser_metadata_render_before');
28*5153720fSfkaag71        $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, '_preview_before');
29*5153720fSfkaag71        $controller->register_hook('TPL_ACT_RENDER', 'AFTER', $this, '_preview_after');
30*5153720fSfkaag71
31*5153720fSfkaag71        $controller->register_hook('PARSER_METADATA_RENDER', 'AFTER', $this, '_parser_metadata_render_after');
32*5153720fSfkaag71        $controller->register_hook('STRATA_PREVIEW_METADATA_RENDER', 'AFTER', $this, '_parser_metadata_render_after');
33*5153720fSfkaag71    }
34*5153720fSfkaag71
35*5153720fSfkaag71
36*5153720fSfkaag71    /**
37*5153720fSfkaag71     * Triggers before preview xhtml render,
38*5153720fSfkaag71     * allows plugins to metadata render on the preview.
39*5153720fSfkaag71     */
40*5153720fSfkaag71    public function _preview_before(&$event, $param) {
41*5153720fSfkaag71        global $ACT;
42*5153720fSfkaag71        global $TEXT;
43*5153720fSfkaag71        global $SUF;
44*5153720fSfkaag71        global $PRE;
45*5153720fSfkaag71        global $ID;
46*5153720fSfkaag71        global $METADATA_RENDERERS;
47*5153720fSfkaag71
48*5153720fSfkaag71        if($ACT == 'preview') {
49*5153720fSfkaag71            $triples =& plugin_load('helper', 'strata_triples');
50*5153720fSfkaag71            $triples->beginPreview();
51*5153720fSfkaag71
52*5153720fSfkaag71            $text = $PRE.$TEXT.$SUF;
53*5153720fSfkaag71            $orig = p_read_metadata($ID);
54*5153720fSfkaag71
55*5153720fSfkaag71            // store the original metadata in the global $METADATA_RENDERERS so p_set_metadata can use it
56*5153720fSfkaag71            $METADATA_RENDERERS[$ID] =& $orig;
57*5153720fSfkaag71
58*5153720fSfkaag71            // add an extra key for the event - to tell event handlers the page whose metadata this is
59*5153720fSfkaag71            $orig['page'] = $ID;
60*5153720fSfkaag71            $evt = new Doku_Event('STRATA_PREVIEW_METADATA_RENDER', $orig);
61*5153720fSfkaag71            if ($evt->advise_before()) {
62*5153720fSfkaag71                // get instructions
63*5153720fSfkaag71                $instructions = p_get_instructions($text);
64*5153720fSfkaag71                if(is_null($instructions)){
65*5153720fSfkaag71                    unset($METADATA_RENDERERS[$ID]);
66*5153720fSfkaag71                    return null; // something went wrong with the instructions
67*5153720fSfkaag71                }
68*5153720fSfkaag71
69*5153720fSfkaag71                // set up the renderer
70*5153720fSfkaag71                $renderer = new renderer_plugin_strata();
71*5153720fSfkaag71                $renderer->meta =& $orig['current'];
72*5153720fSfkaag71                $renderer->persistent =& $orig['persistent'];
73*5153720fSfkaag71
74*5153720fSfkaag71                // loop through the instructions
75*5153720fSfkaag71                foreach ($instructions as $instruction){
76*5153720fSfkaag71                    // execute the callback against the renderer
77*5153720fSfkaag71                    call_user_func_array(array(&$renderer, $instruction[0]), (array) $instruction[1]);
78*5153720fSfkaag71                }
79*5153720fSfkaag71
80*5153720fSfkaag71                $evt->result = array('current'=>&$renderer->meta,'persistent'=>&$renderer->persistent);
81*5153720fSfkaag71            }
82*5153720fSfkaag71            $evt->advise_after();
83*5153720fSfkaag71
84*5153720fSfkaag71            // clean up
85*5153720fSfkaag71            unset($METADATA_RENDERERS[$id]);
86*5153720fSfkaag71        }
87*5153720fSfkaag71    }
88*5153720fSfkaag71
89*5153720fSfkaag71
90*5153720fSfkaag71    public function _preview_after(&$event, $param) {
91*5153720fSfkaag71        global $ACT;
92*5153720fSfkaag71
93*5153720fSfkaag71        if($ACT == 'preview') {
94*5153720fSfkaag71            $triples =& plugin_load('helper', 'strata_triples');
95*5153720fSfkaag71            $triples->endPreview();
96*5153720fSfkaag71        }
97*5153720fSfkaag71    }
98*5153720fSfkaag71
99*5153720fSfkaag71    /**
100*5153720fSfkaag71     * Triggered whenever a page is written. We need to handle
101*5153720fSfkaag71     * this event because metadata is not rendered if a page is removed.
102*5153720fSfkaag71     */
103*5153720fSfkaag71    public function _io_page_write(&$event, $param) {
104*5153720fSfkaag71        // only remove triples if page is a new revision, or if it is removed
105*5153720fSfkaag71        if($event->data[3] == false || $event->data[0][1] == '') {
106*5153720fSfkaag71            $id = ltrim($event->data[1].':'.$event->data[2],':');
107*5153720fSfkaag71            $this->_purge_data($id);
108*5153720fSfkaag71        }
109*5153720fSfkaag71    }
110*5153720fSfkaag71
111*5153720fSfkaag71    /**
112*5153720fSfkaag71     * Triggered before metadata is going to be rendered. We
113*5153720fSfkaag71     * remove triples previously generated by the page that is going to
114*5153720fSfkaag71     * be rendered so we don't get duplicate entries.
115*5153720fSfkaag71     */
116*5153720fSfkaag71    public function _parser_metadata_render_before(&$event, $param) {
117*5153720fSfkaag71        $this->_purge_data($event->data['page']);
118*5153720fSfkaag71    }
119*5153720fSfkaag71
120*5153720fSfkaag71    /**
121*5153720fSfkaag71     * Triggered after metadata has been rendered.
122*5153720fSfkaag71     * We check the fixTitle flag, and if it is present, we
123*5153720fSfkaag71     * add the entry title.
124*5153720fSfkaag71     */
125*5153720fSfkaag71    public function _parser_metadata_render_after(&$event, $param) {
126*5153720fSfkaag71        $id = $event->data['page'];
127*5153720fSfkaag71
128*5153720fSfkaag71        $current =& $event->data['current'];
129*5153720fSfkaag71
130*5153720fSfkaag71        if(isset($current['strata']['fixTitle']) && $current['strata']['fixTitle']) {
131*5153720fSfkaag71            // get helpers
132*5153720fSfkaag71            $triples =& plugin_load('helper', 'strata_triples');
133*5153720fSfkaag71            $util =& plugin_load('helper', 'strata_util');
134*5153720fSfkaag71
135*5153720fSfkaag71            $title = $current['title'];
136*5153720fSfkaag71            if(!$title) {
137*5153720fSfkaag71                $title = noNS($id);
138*5153720fSfkaag71            }
139*5153720fSfkaag71
140*5153720fSfkaag71            $title = $util->loadType('text')->normalize($title,'');
141*5153720fSfkaag71
142*5153720fSfkaag71            $triples->addTriple($id, $util->getTitleKey(), $title, $id);
143*5153720fSfkaag71        }
144*5153720fSfkaag71    }
145*5153720fSfkaag71
146*5153720fSfkaag71    /**
147*5153720fSfkaag71     * Purges the data for a single page id.
148*5153720fSfkaag71     *
149*5153720fSfkaag71     * @param id string the page that needs to be purged
150*5153720fSfkaag71     */
151*5153720fSfkaag71    private function _purge_data($id) {
152*5153720fSfkaag71        // get triples helper
153*5153720fSfkaag71        $triples =& plugin_load('helper', 'strata_triples');
154*5153720fSfkaag71
155*5153720fSfkaag71        // remove all triples defined in this graph
156*5153720fSfkaag71        $triples->removeTriples(null,null,null,$id);
157*5153720fSfkaag71    }
158*5153720fSfkaag71}
159*5153720fSfkaag71
160*5153720fSfkaag71/**
161*5153720fSfkaag71 * Strata 'pluggable' autoloader. This function is responsible
162*5153720fSfkaag71 * for autoloading classes that should be pluggable by external
163*5153720fSfkaag71 * plugins.
164*5153720fSfkaag71 *
165*5153720fSfkaag71 * @param fullname string the name of the class to load
166*5153720fSfkaag71 */
167*5153720fSfkaag71function plugin_strata_autoload($fullname) {
168*5153720fSfkaag71    static $classes = null;
169*5153720fSfkaag71    if(is_null($classes)) $classes = array(
170*5153720fSfkaag71        'strata_exception'         => DOKU_PLUGIN.'strata/lib/strata_exception.php',
171*5153720fSfkaag71        'strata_querytree_visitor' => DOKU_PLUGIN.'strata/lib/strata_querytree_visitor.php',
172*5153720fSfkaag71        'plugin_strata_type'       => DOKU_PLUGIN.'strata/lib/strata_type.php',
173*5153720fSfkaag71        'plugin_strata_aggregate'  => DOKU_PLUGIN.'strata/lib/strata_aggregate.php',
174*5153720fSfkaag71   );
175*5153720fSfkaag71
176*5153720fSfkaag71    if(isset($classes[$fullname])) {
177*5153720fSfkaag71        require_once($classes[$fullname]);
178*5153720fSfkaag71        return;
179*5153720fSfkaag71    }
180*5153720fSfkaag71
181*5153720fSfkaag71    // only load matching components
182*5153720fSfkaag71    if(preg_match('/^plugin_strata_(type|aggregate)_(.*)$/',$fullname, $matches)) {
183*5153720fSfkaag71        // use descriptive names
184*5153720fSfkaag71        list(,$kind,$name) = $matches;
185*5153720fSfkaag71
186*5153720fSfkaag71        // glob to find the required file
187*5153720fSfkaag71        $filenames = glob(DOKU_PLUGIN."*/{$kind}s/{$name}.php");
188*5153720fSfkaag71        if($filenames === false || count($filenames) == 0) {
189*5153720fSfkaag71            // if we have no file, fake an implementation
190*5153720fSfkaag71            eval("class $fullname extends plugin_strata_{$kind} { };");
191*5153720fSfkaag71        } else {
192*5153720fSfkaag71            // include the file
193*5153720fSfkaag71            require_once $filenames[0];
194*5153720fSfkaag71            // If the class still does not exist, the required file does not define the class, so we fall back
195*5153720fSfkaag71            // to the default
196*5153720fSfkaag71            if(!class_exists($fullname)) {
197*5153720fSfkaag71                eval("class $fullname extends plugin_strata_{$kind} { };");
198*5153720fSfkaag71            }
199*5153720fSfkaag71        }
200*5153720fSfkaag71
201*5153720fSfkaag71        return;
202*5153720fSfkaag71    }
203*5153720fSfkaag71}
204*5153720fSfkaag71
205*5153720fSfkaag71// register autoloader with SPL loader stack
206*5153720fSfkaag71spl_autoload_register('plugin_strata_autoload');
207