[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / plugins-dist / textwheel / engine / textwheelruleset.php
1 <?php
2
3 /*
4 * TextWheel 0.1
5 *
6 * let's reinvent the wheel one last time
7 *
8 * This library of code is meant to be a fast and universal replacement
9 * for any and all text-processing systems written in PHP
10 *
11 * It is dual-licensed for any use under the GNU/GPL2 and MIT licenses,
12 * as suits you best
13 *
14 * (c) 2009 Fil - fil@rezo.net
15 * Documentation & http://zzz.rezo.net/-TextWheel-
16 *
17 * Usage: $wheel = new TextWheel(); echo $wheel->text($text);
18 *
19 */
20
21 if (!defined('_ECRIRE_INC_VERSION')) {
22 return;
23 }
24
25 require_once dirname(__FILE__) . "/textwheelrule.php";
26
27 abstract class TextWheelDataSet {
28 # list of data
29 protected $data = array();
30
31 /**
32 * file finder : can be overloaded in order to use application dependant
33 * path find method
34 *
35 * @param string $file
36 * @param string $path
37 * @return string
38 */
39 protected function findFile(&$file, $path = '') {
40 static $default_path;
41
42 // absolute file path ?
43 if (file_exists($file)) {
44 return $file;
45 }
46
47 // file embed with texwheels, relative to calling ruleset
48 if ($path and file_exists($f = $path . $file)) {
49 return $f;
50 }
51
52 // textwheel default path ?
53 if (!$default_path) {
54 $default_path = dirname(__FILE__) . '/../wheels/';
55 }
56 if (file_exists($f = $default_path . $file)) {
57 return $f;
58 }
59
60 return false;
61 }
62
63 /**
64 * Load a yaml file describing data
65 *
66 * @param string $file
67 * @param string $default_path
68 * @return array
69 */
70 protected function loadFile(&$file, $default_path = '') {
71 if (!preg_match(',[.]yaml$,i', $file)
72 // external rules
73 or !$file = $this->findFile($file, $default_path)
74 ) {
75 return array();
76 }
77
78 defined('_YAML_EVAL_PHP') || define('_YAML_EVAL_PHP', false);
79 if (!function_exists('yaml_decode')) {
80 if (function_exists('include_spip')) {
81 include_spip('inc/yaml-mini');
82 } else {
83 require_once dirname(__FILE__) . '/../inc/yaml.php';
84 }
85 }
86 $dataset = yaml_decode(file_get_contents($file));
87
88 if (is_null($dataset)) {
89 $dataset = array();
90 }
91 # throw new DomainException('yaml file is empty, unreadable or badly formed: '.$file.var_export($dataset,true));
92
93 // if a php file with same name exists
94 // include it as it contains callback functions
95 if ($f = preg_replace(',[.]yaml$,i', '.php', $file)
96 and file_exists($f)
97 ) {
98 $dataset[] = array('require' => $f, 'priority' => -1000);
99 }
100
101 return $dataset;
102 }
103
104 }
105
106 class TextWheelRuleSet extends TextWheelDataSet {
107 # sort flag
108 protected $sorted = true;
109
110 /**
111 * Constructor
112 *
113 * @param array|string $ruleset
114 * @param string $filepath
115 */
116 public function __construct($ruleset = array(), $filepath = '') {
117 if ($ruleset) {
118 $this->addRules($ruleset, $filepath);
119 }
120 }
121
122 /**
123 * public static loader
124 * can be overloaded to use memoization
125 *
126 * @param array $ruleset
127 * @param string $callback
128 * @param string $class
129 * @return class
130 */
131 public static function &loader($ruleset, $callback = '', $class = 'TextWheelRuleSet') {
132
133 $ruleset = new $class($ruleset);
134 if ($callback) {
135 $callback($ruleset);
136 }
137
138 return $ruleset;
139 }
140
141 /**
142 * Get an existing named rule in order to override it
143 *
144 * @param string $name
145 * @return string
146 */
147 public function &getRule($name) {
148 if (isset($this->data[$name])) {
149 return $this->data[$name];
150 }
151 $result = null;
152
153 return $result;
154 }
155
156 /**
157 * get sorted Rules
158 *
159 * @return array
160 */
161 public function &getRules() {
162 $this->sort();
163
164 return $this->data;
165 }
166
167 /**
168 * add a rule
169 *
170 * @param TextWheelRule $rule
171 */
172 public function addRule($rule) {
173 # cast array-rule to object
174 if (is_array($rule)) {
175 $rule = new TextWheelRule($rule);
176 }
177 $this->data[] = $rule;
178 $this->sorted = false;
179 }
180
181 /**
182 * add an list of rules
183 * can be
184 * - an array of rules
185 * - a string filename
186 * - an array of string filename
187 *
188 * @param array|string $rules
189 * @param string $filepath
190 */
191 public function addRules($rules, $filepath = '') {
192 // rules can be an array of filename
193 if (is_array($rules) and is_string(reset($rules))) {
194 foreach ($rules as $i => $filename) {
195 $this->addRules($filename);
196 }
197
198 return;
199 }
200
201 // rules can be a string : yaml filename
202 if (is_string($rules)) {
203 $file = $rules; // keep the real filename
204 $rules = $this->loadFile($file, $filepath);
205 $filepath = dirname($file) . '/';
206 }
207
208 // rules can be an array of rules
209 if (is_array($rules) and count($rules)) {
210 # cast array-rules to objects
211 foreach ($rules as $i => $rule) {
212 if (is_array($rule)) {
213 $rules[$i] = new TextWheelRule($rule);
214 }
215 // load subwheels when necessary
216 if ($rules[$i]->is_wheel) {
217 // subruleset is of the same class as current ruleset
218 $class = get_class($this);
219 $rules[$i]->replace = new $class($rules[$i]->replace, $filepath);
220 }
221 }
222 $this->data = array_merge($this->data, $rules);
223 $this->sorted = false;
224 }
225 }
226
227 /**
228 * Sort rules according to priority and
229 * purge disabled rules
230 *
231 */
232 protected function sort() {
233 if (!$this->sorted) {
234 $rulz = array();
235 foreach ($this->data as $index => $rule) {
236 if (!$rule->disabled) {
237 $rulz[intval($rule->priority)][$index] = $rule;
238 }
239 }
240 ksort($rulz);
241 $this->data = array();
242 foreach ($rulz as $rules) {
243 $this->data += $rules;
244 }
245
246 $this->sorted = true;
247 }
248 }
249 }