Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
Ruleset.php
001 <?php
002
003 /**
004 * @package s9e\TextFormatter
005 * @copyright Copyright (c) 2010-2022 The s9e authors
006 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
007 */
008 namespace s9e\TextFormatter\Configurator\Collections;
009
010 use ArrayAccess;
011 use BadMethodCallException;
012 use InvalidArgumentException;
013 use RuntimeException;
014 use s9e\TextFormatter\Configurator\ConfigProvider;
015 use s9e\TextFormatter\Configurator\JavaScript\Dictionary;
016 use s9e\TextFormatter\Configurator\Validators\TagName;
017 use s9e\TextFormatter\Parser;
018
019 /**
020 * @method void allowChild(string $tagName)
021 * @method void allowDescendant(string $tagName)
022 * @method void autoClose(bool $bool = true)
023 * @method void autoReopen(bool $bool = true)
024 * @method void breakParagraph(bool $bool = true)
025 * @method void closeAncestor(string $tagName)
026 * @method void closeParent(string $tagName)
027 * @method void createChild(string $tagName)
028 * @method void createParagraphs(bool $bool = true)
029 * @method void denyChild(string $tagName)
030 * @method void denyDescendant(string $tagName)
031 * @method void disableAutoLineBreaks(bool $bool = true)
032 * @method void enableAutoLineBreaks(bool $bool = true)
033 * @method void fosterParent(string $tagName)
034 * @method void ignoreSurroundingWhitespace(bool $bool = true)
035 * @method void ignoreTags(bool $bool = true)
036 * @method void ignoreText(bool $bool = true)
037 * @method void isTransparent(bool $bool = true)
038 * @method void preventLineBreaks(bool $bool = true)
039 * @method void requireParent(string $tagName)
040 * @method void requireAncestor(string $tagName)
041 * @method void suspendAutoLineBreaks(bool $bool = true)
042 * @method void trimFirstLine(bool $bool = true)
043 * @see /docs/Rules.md
044 */
045 class Ruleset extends Collection implements ArrayAccess, ConfigProvider
046 {
047 /**
048 * @var array Supported rules and the method used to add them
049 */
050 protected $rules = [
051 'allowChild' => 'addTargetedRule',
052 'allowDescendant' => 'addTargetedRule',
053 'autoClose' => 'addBooleanRule',
054 'autoReopen' => 'addBooleanRule',
055 'breakParagraph' => 'addBooleanRule',
056 'closeAncestor' => 'addTargetedRule',
057 'closeParent' => 'addTargetedRule',
058 'createChild' => 'addTargetedRule',
059 'createParagraphs' => 'addBooleanRule',
060 'denyChild' => 'addTargetedRule',
061 'denyDescendant' => 'addTargetedRule',
062 'disableAutoLineBreaks' => 'addBooleanRule',
063 'enableAutoLineBreaks' => 'addBooleanRule',
064 'fosterParent' => 'addTargetedRule',
065 'ignoreSurroundingWhitespace' => 'addBooleanRule',
066 'ignoreTags' => 'addBooleanRule',
067 'ignoreText' => 'addBooleanRule',
068 'isTransparent' => 'addBooleanRule',
069 'preventLineBreaks' => 'addBooleanRule',
070 'requireParent' => 'addTargetedRule',
071 'requireAncestor' => 'addTargetedRule',
072 'suspendAutoLineBreaks' => 'addBooleanRule',
073 'trimFirstLine' => 'addBooleanRule'
074 ];
075
076 /**
077 * Add a rule to this set
078 *
079 * @param string $methodName Rule name
080 * @param array $args Arguments used to add given rule
081 * @return self
082 */
083 public function __call($methodName, array $args)
084 {
085 if (!isset($this->rules[$methodName]))
086 {
087 throw new BadMethodCallException("Undefined method '" . $methodName . "'");
088 }
089
090 array_unshift($args, $methodName);
091 call_user_func_array([$this, $this->rules[$methodName]], $args);
092
093 return $this;
094 }
095
096 //==========================================================================
097 // ArrayAccess methods
098 //==========================================================================
099
100 /**
101 * Test whether a rule category exists
102 *
103 * @param string $k Rule name, e.g. "allowChild" or "isTransparent"
104 */
105 public function offsetExists($k): bool
106 {
107 return isset($this->items[$k]);
108 }
109
110 /**
111 * Return the content of a rule category
112 *
113 * @param string $k Rule name, e.g. "allowChild" or "isTransparent"
114 * @return mixed
115 */
116 #[\ReturnTypeWillChange]
117 public function offsetGet($k)
118 {
119 return $this->items[$k];
120 }
121
122 /**
123 * Not supported
124 */
125 public function offsetSet($k, $v): void
126 {
127 throw new RuntimeException('Not supported');
128 }
129
130 /**
131 * Clear a subset of the rules
132 *
133 * @see clear()
134 *
135 * @param string $k Rule name, e.g. "allowChild" or "isTransparent"
136 */
137 public function offsetUnset($k): void
138 {
139 $this->remove($k);
140 }
141
142 //==========================================================================
143 // Generic methods
144 //==========================================================================
145
146 /**
147 * {@inheritdoc}
148 */
149 public function asConfig()
150 {
151 $config = $this->items;
152
153 // Remove rules that are not needed at parsing time. All of those are resolved when building
154 // the allowed bitfields
155 unset($config['allowChild']);
156 unset($config['allowDescendant']);
157 unset($config['denyChild']);
158 unset($config['denyDescendant']);
159 unset($config['requireParent']);
160
161 // Pack boolean rules into a bitfield
162 $bitValues = [
163 'autoClose' => Parser::RULE_AUTO_CLOSE,
164 'autoReopen' => Parser::RULE_AUTO_REOPEN,
165 'breakParagraph' => Parser::RULE_BREAK_PARAGRAPH,
166 'createParagraphs' => Parser::RULE_CREATE_PARAGRAPHS,
167 'disableAutoLineBreaks' => Parser::RULE_DISABLE_AUTO_BR,
168 'enableAutoLineBreaks' => Parser::RULE_ENABLE_AUTO_BR,
169 'ignoreSurroundingWhitespace' => Parser::RULE_IGNORE_WHITESPACE,
170 'ignoreTags' => Parser::RULE_IGNORE_TAGS,
171 'ignoreText' => Parser::RULE_IGNORE_TEXT,
172 'isTransparent' => Parser::RULE_IS_TRANSPARENT,
173 'preventLineBreaks' => Parser::RULE_PREVENT_BR,
174 'suspendAutoLineBreaks' => Parser::RULE_SUSPEND_AUTO_BR,
175 'trimFirstLine' => Parser::RULE_TRIM_FIRST_LINE
176 ];
177
178 $bitfield = 0;
179 foreach ($bitValues as $ruleName => $bitValue)
180 {
181 if (!empty($config[$ruleName]))
182 {
183 $bitfield |= $bitValue;
184 }
185
186 unset($config[$ruleName]);
187 }
188
189 // In order to speed up lookups, we use the tag names as keys
190 foreach (['closeAncestor', 'closeParent', 'fosterParent'] as $ruleName)
191 {
192 if (isset($config[$ruleName]))
193 {
194 $targets = array_fill_keys($config[$ruleName], 1);
195 $config[$ruleName] = new Dictionary($targets);
196 }
197 }
198
199 // Add the bitfield to the config
200 $config['flags'] = $bitfield;
201
202 return $config;
203 }
204
205 /**
206 * Merge a set of rules into this collection
207 *
208 * @param array|Ruleset $rules 2D array of rule definitions, or instance of Ruleset
209 * @param bool $overwrite Whether to overwrite scalar rules (e.g. boolean rules)
210 */
211 public function merge($rules, $overwrite = true)
212 {
213 if (!is_array($rules)
214 && !($rules instanceof self))
215 {
216 throw new InvalidArgumentException('merge() expects an array or an instance of Ruleset');
217 }
218
219 foreach ($rules as $action => $value)
220 {
221 if (is_array($value))
222 {
223 foreach ($value as $tagName)
224 {
225 $this->$action($tagName);
226 }
227 }
228 elseif ($overwrite || !isset($this->items[$action]))
229 {
230 $this->$action($value);
231 }
232 }
233 }
234
235 /**
236 * Remove a specific rule, or all the rules of a given type
237 *
238 * @param string $type Type of rules to clear
239 * @param string $tagName Name of the target tag, or none to remove all rules of given type
240 * @return void
241 */
242 public function remove($type, $tagName = null)
243 {
244 if (preg_match('(^default(?:Child|Descendant)Rule)', $type))
245 {
246 throw new InvalidArgumentException('Cannot remove ' . $type);
247 }
248
249 if (isset($tagName))
250 {
251 $tagName = TagName::normalize($tagName);
252
253 if (isset($this->items[$type]))
254 {
255 // Compute the difference between current list and our one tag name
256 $this->items[$type] = array_diff(
257 $this->items[$type],
258 [$tagName]
259 );
260
261 if (empty($this->items[$type]))
262 {
263 // If the list is now empty, keep it neat and unset it
264 unset($this->items[$type]);
265 }
266 else
267 {
268 // If the list still have names, keep it neat and rearrange keys
269 $this->items[$type] = array_values($this->items[$type]);
270 }
271 }
272 }
273 else
274 {
275 unset($this->items[$type]);
276 }
277 }
278
279 //==========================================================================
280 // Rules
281 //==========================================================================
282
283 /**
284 * Add a boolean rule
285 *
286 * @param string $ruleName Name of the rule
287 * @param bool $bool Whether to enable or disable the rule
288 * @return self
289 */
290 protected function addBooleanRule($ruleName, $bool = true)
291 {
292 if (!is_bool($bool))
293 {
294 throw new InvalidArgumentException($ruleName . '() expects a boolean');
295 }
296
297 $this->items[$ruleName] = $bool;
298 }
299
300 /**
301 * Add a targeted rule
302 *
303 * @param string $ruleName Name of the rule
304 * @param string $tagName Name of the target tag
305 * @return self
306 */
307 protected function addTargetedRule($ruleName, $tagName)
308 {
309 $this->items[$ruleName][] = TagName::normalize($tagName);
310 }
311 }