1<?php
2/**
3 * Creole Helper Plugin, Eventhandler:
4 * Notifies syntax components if a other component has match.
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     LarsDW223
8 */
9
10class creole_syntax_event {
11    protected $state = NULL;
12    protected $clazz = NULL;
13    protected $tag = NULL;
14
15    /**
16     * Constructor.
17     */
18    public function __construct($state, $clazz , $tag) {
19        $this->state = $state;
20        $this->clazz = $clazz;
21        $this->tag = $tag;
22    }
23
24    public function setState($state) {
25        $this->state = $state;
26    }
27
28    public function getState() {
29        return $this->state;
30    }
31
32    public function getClazz() {
33        return $this->clazz;
34    }
35
36    public function getTag() {
37        return $this->tag;
38    }
39
40    public function equal ($other) {
41        if ($other == NULL ) {
42            return false;
43        }
44        $otherState = $other->getState();
45        $otherClazz = $other->getClazz();
46        $otherTag = $other->getTag();
47        return $this->equalToValues ($otherState, $otherClazz, $otherTag);
48    }
49
50    public function equalToValues ($otherState, $otherClazz, $otherTag) {
51        if ( $this->state != NULL && $otherState != NULL &&
52             $this->state != $otherState ) {
53            return false;
54        }
55        if ( $this->clazz != NULL && $otherClazz != NULL &&
56             $this->clazz != $otherClazz ) {
57            return false;
58        }
59        if ( $this->tag != NULL && $otherTag != NULL &&
60             $this->tag != $otherTag ) {
61            return false;
62        }
63        return true;
64    }
65}
66
67class creole_state_callback {
68    protected $event;
69    protected $ownEvent;
70    protected $callback;
71
72    /**
73     * Constructor.
74     */
75    public function __construct($state, $clazz, $tag, $ownState, $ownClazz, $ownTag, $callback) {
76        if ( $state == NULL && $clazz == NULL && $tag == NULL ) {
77            $this->event = NULL;
78        } else {
79            $this->event = new creole_syntax_event ($state, $clazz, $tag);
80        }
81        if ( $ownState == NULL && $ownClazz == NULL && $ownTag == NULL ) {
82            $this->ownEvent = NULL;
83        } else {
84            $this->ownEvent = new creole_syntax_event ($ownState, $ownClazz, $ownTag);
85        }
86        $this->callback = $callback;
87    }
88
89    public function eventMatches (creole_syntax_event $compare) {
90        return $this->event->equal($compare);
91    }
92
93    public function ownEventMatches (creole_syntax_event $compare) {
94        return $this->ownEvent->equal($compare);
95    }
96
97    public function execute ($queuedEvent, $pos, $match, &$handler) {
98        //call_user_func($this->callback, $this->ownEvent, $pos, $match, $handler);
99        call_user_func($this->callback, $queuedEvent, $pos, $match, $handler);
100    }
101
102    public function getOwnEvent () {
103        return $this->ownEvent;
104    }
105}
106
107/**
108 * All DokuWiki plugins to extend the parser/rendering mechanism
109 * need to inherit from this class
110 */
111class helper_plugin_creole_eventhandler extends DokuWiki_Plugin {
112    protected static $queue = array();
113    protected static $callbacks = array();
114    protected static $trace_dump = 'syntax_plugin_creole_base - Trace-Dump:<br/>';
115
116    /**
117     * Constructor.
118     */
119    public function __construct() {
120        self::$queue = array();
121        self::$callbacks = array();
122        self::$trace_dump = 'syntax_plugin_creole_base - Trace-Dump:<br/>';
123    }
124
125    /**
126     * @return array
127     */
128    function getMethods() {
129        $result = array();
130        $result[] = array(
131                'name'   => 'getColorValue',
132                'desc'   => 'returns the color value for a given CSS color name. Returns "#000000" if the name is unknown',
133                'params' => array('name' => 'string'),
134                'return' => array('color value' => 'string'),
135                );
136        return $result;
137    }
138
139    public function addOnNotify ($state, $clazz, $tag, $ownState, $ownClazz, $ownTag, $callback) {
140        self::$callbacks [] = new creole_state_callback
141            ($state, $clazz, $tag, $ownState, $ownClazz, $ownTag, $callback);
142    }
143
144    public function notifyEvent ($state, $clazz, $tag, $pos, $match, $handler) {
145        $state = strtolower($state);
146        $clazz = strtolower($clazz);
147        $tag = strtolower($tag);
148
149        $event = new creole_syntax_event($state, $clazz, $tag);
150
151        // Callback all functions registered for this event,
152        // if they have got an event in the queue.
153        $q_max = count(self::$queue);
154        for ( $q_index = $q_max-1 ; $q_index >= 0 ; $q_index-- ) {
155            for ( $cb_index = 0 ; $cb_index < count (self::$callbacks) ; $cb_index++ ) {
156                if ( self::$queue[$q_index] != NULL &&
157                     self::$callbacks [$cb_index]->eventMatches($event) &&
158                     self::$callbacks [$cb_index]->ownEventMatches(self::$queue[$q_index]) ) {
159                    // Match found, call callback function.
160                    self::$callbacks [$cb_index]->execute(self::$queue [$q_index], $pos, $match, $handler);
161                }
162            }
163        }
164
165        if ( $state == 'open' ) {
166            self::$queue [] = $event;
167        }
168        if ( $state == 'close' ) {
169            // Remove an matching open event from the queue.
170            // Change state of this event to open and search for it.
171            $event->setState('open');
172            for ( $q_index = 0 ; $q_index < count(self::$queue) ; $q_index++ ) {
173                if ( $event->equal(self::$queue [$q_index]) ) {
174                    self::$queue [$q_index] = NULL;
175                }
176            }
177        }
178    }
179
180    public function queuedEventExists ($state, $clazz, $tag) {
181        for ( $q_index = 0 ; $q_index < count(self::$queue) ; $q_index++ ) {
182            if ( self::$queue [$q_index] != NULL &&
183                 self::$queue [$q_index]->equalToValues($state, $clazz, $tag) ) {
184                return true;
185            }
186        }
187        return false;
188    }
189
190    /**
191     * helper function to simplify writing plugin calls to the instruction list
192     * first three arguments are passed to function render as $data
193     */
194    public function writeCall($class, $state, $data1, $data2, $pos, $match, &$handler) {
195        $handler->addPluginCall($class, array($state, $data1, $data2), $state, $pos, $match);
196    }
197
198    public function getTraceDump () {
199        return self::$trace_dump;
200    }
201
202    public function addToTraceDump ($content) {
203        self::$trace_dump .= $content;
204    }
205}
206// vim:ts=4:sw=4:et:enc=utf-8:
207