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 |
Tag.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\Parser;
009
010 class Tag
011 {
012 /**
013 * Tag type: start tag
014 */
015 const START_TAG = 1;
016
017 /**
018 * Tag type: end tag
019 */
020 const END_TAG = 2;
021
022 /**
023 * Tag type: self-closing tag
024 */
025 const SELF_CLOSING_TAG = self::START_TAG | self::END_TAG;
026
027 /**
028 * @var array Dictionary of attributes
029 */
030 protected $attributes = [];
031
032 /**
033 * @var array List of tags that are invalidated when this tag is invalidated
034 */
035 protected $cascade = [];
036
037 /**
038 * @var Tag End tag that unconditionally ends this start tag
039 */
040 protected $endTag = null;
041
042 /**
043 * @var integer Bitfield of boolean rules that apply to this tag
044 */
045 protected $flags = 0;
046
047 /**
048 * @var bool Whether this tag is be invalid
049 */
050 protected $invalid = false;
051
052 /**
053 * @var integer Length of text consumed by this tag
054 */
055 protected $len;
056
057 /**
058 * @var string Name of this tag
059 */
060 protected $name;
061
062 /**
063 * @var integer Position of this tag in the text
064 */
065 protected $pos;
066
067 /**
068 * @var integer Tiebreaker used when sorting identical tags
069 */
070 protected $sortPriority;
071
072 /**
073 * @var Tag Start tag that is unconditionally closed this end tag
074 */
075 protected $startTag = null;
076
077 /**
078 * @var integer Tag type
079 */
080 protected $type;
081
082 /**
083 * Constructor
084 *
085 * @param integer $type Tag's type
086 * @param string $name Name of the tag
087 * @param integer $pos Position of the tag in the text
088 * @param integer $len Length of text consumed by the tag
089 * @param integer $priority This tag's sorting tiebreaker
090 */
091 public function __construct($type, $name, $pos, $len, $priority = 0)
092 {
093 $this->type = (int) $type;
094 $this->name = $name;
095 $this->pos = (int) $pos;
096 $this->len = (int) $len;
097 $this->sortPriority = (int) $priority;
098 }
099
100 //==========================================================================
101 // Actions
102 //==========================================================================
103
104 /**
105 * Add a set of flags to this tag's
106 *
107 * @param integer $flags
108 * @return void
109 */
110 public function addFlags($flags)
111 {
112 $this->flags |= $flags;
113 }
114
115 /**
116 * Set given tag to be invalidated if this tag is invalidated
117 *
118 * @param Tag $tag
119 * @return void
120 */
121 public function cascadeInvalidationTo(Tag $tag)
122 {
123 $this->cascade[] = $tag;
124
125 // If this tag is already invalid, cascade it now
126 if ($this->invalid)
127 {
128 $tag->invalidate();
129 }
130 }
131
132 /**
133 * Invalidate this tag, as well as tags bound to this tag
134 *
135 * @return void
136 */
137 public function invalidate()
138 {
139 // Only invalidate if this tag is valid to prevent infinite loops
140 if (!$this->invalid)
141 {
142 $this->invalid = true;
143 foreach ($this->cascade as $tag)
144 {
145 $tag->invalidate();
146 }
147 }
148 }
149
150 /**
151 * Pair this tag with given tag
152 *
153 * @param Tag $tag
154 * @return void
155 */
156 public function pairWith(Tag $tag)
157 {
158 if ($this->canBePaired($this, $tag))
159 {
160 $this->endTag = $tag;
161 $tag->startTag = $this;
162
163 $this->cascadeInvalidationTo($tag);
164 }
165 elseif ($this->canBePaired($tag, $this))
166 {
167 $this->startTag = $tag;
168 $tag->endTag = $this;
169 }
170 }
171
172 /**
173 * Test whether two tags can be paired
174 */
175 protected function canBePaired(Tag $startTag, Tag $endTag): bool
176 {
177 return $startTag->name === $endTag->name && $startTag->type === self::START_TAG && $endTag->type === self::END_TAG && $startTag->pos <= $endTag->pos;
178 }
179
180 /**
181 * Remove a set of flags from this tag's
182 *
183 * @param integer $flags
184 * @return void
185 */
186 public function removeFlags($flags)
187 {
188 $this->flags &= ~$flags;
189 }
190
191 /**
192 * Set the bitfield of boolean rules that apply to this tag
193 *
194 * @param integer $flags Bitfield of boolean rules that apply to this tag
195 * @return void
196 */
197 public function setFlags($flags)
198 {
199 $this->flags = $flags;
200 }
201
202 //==========================================================================
203 // Getters
204 //==========================================================================
205
206 /**
207 * Return this tag's attributes
208 *
209 * @return array
210 */
211 public function getAttributes()
212 {
213 return $this->attributes;
214 }
215
216 /**
217 * Return this tag's end tag
218 *
219 * @return Tag|null This tag's end tag, or NULL if none is set
220 */
221 public function getEndTag()
222 {
223 return $this->endTag;
224 }
225
226 /**
227 * Return the bitfield of boolean rules that apply to this tag
228 *
229 * @return integer
230 */
231 public function getFlags()
232 {
233 return $this->flags;
234 }
235
236 /**
237 * Return the length of text consumed by this tag
238 *
239 * @return integer
240 */
241 public function getLen()
242 {
243 return $this->len;
244 }
245
246 /**
247 * Return this tag's name
248 *
249 * @return string
250 */
251 public function getName()
252 {
253 return $this->name;
254 }
255
256 /**
257 * Return this tag's position
258 *
259 * @return integer
260 */
261 public function getPos()
262 {
263 return $this->pos;
264 }
265
266 /**
267 * Return this tag's tiebreaker
268 *
269 * @return integer
270 */
271 public function getSortPriority()
272 {
273 return $this->sortPriority;
274 }
275
276 /**
277 * Return this tag's start tag
278 *
279 * @return Tag|null This tag's start tag, or NULL if none is set
280 */
281 public function getStartTag()
282 {
283 return $this->startTag;
284 }
285
286 /**
287 * Return this tag's type
288 *
289 * @return integer
290 */
291 public function getType()
292 {
293 return $this->type;
294 }
295
296 //==========================================================================
297 // Tag's status
298 //==========================================================================
299
300 /**
301 * Test whether this tag can close given start tag
302 *
303 * @param Tag $startTag A start tag
304 * @return bool
305 */
306 public function canClose(Tag $startTag)
307 {
308 if ($this->invalid
309 || !$this->canBePaired($startTag, $this)
310 || ($this->startTag && $this->startTag !== $startTag)
311 || ($startTag->endTag && $startTag->endTag !== $this))
312 {
313 return false;
314 }
315
316 return true;
317 }
318
319 /**
320 * Test whether this tag is a br tag
321 *
322 * @return bool
323 */
324 public function isBrTag()
325 {
326 return ($this->name === 'br');
327 }
328
329 /**
330 * Test whether this tag is an end tag (self-closing tags inclusive)
331 *
332 * @return bool
333 */
334 public function isEndTag()
335 {
336 return (bool) ($this->type & self::END_TAG);
337 }
338
339 /**
340 * Test whether this tag is an ignore tag
341 *
342 * @return bool
343 */
344 public function isIgnoreTag()
345 {
346 return ($this->name === 'i');
347 }
348
349 /**
350 * Test whether this tag is invalid
351 *
352 * @return bool
353 */
354 public function isInvalid()
355 {
356 return $this->invalid;
357 }
358
359 /**
360 * Test whether this tag represents a paragraph break
361 *
362 * @return bool
363 */
364 public function isParagraphBreak()
365 {
366 return ($this->name === 'pb');
367 }
368
369 /**
370 * Test whether this tag is a self-closing tag
371 *
372 * @return bool
373 */
374 public function isSelfClosingTag()
375 {
376 return ($this->type === self::SELF_CLOSING_TAG);
377 }
378
379 /**
380 * Test whether this tag is a special tag: "br", "i", "pb" or "v"
381 *
382 * @return bool
383 */
384 public function isSystemTag()
385 {
386 return (strpos('br i pb v', $this->name) !== false);
387 }
388
389 /**
390 * Test whether this tag is a start tag (self-closing tags inclusive)
391 *
392 * @return bool
393 */
394 public function isStartTag()
395 {
396 return (bool) ($this->type & self::START_TAG);
397 }
398
399 /**
400 * Test whether this tag represents verbatim text
401 *
402 * @return bool
403 */
404 public function isVerbatim()
405 {
406 return ($this->name === 'v');
407 }
408
409 //==========================================================================
410 // Attributes handling
411 //==========================================================================
412
413 /**
414 * Return the value of given attribute
415 *
416 * @param string $attrName
417 * @return mixed
418 */
419 public function getAttribute($attrName)
420 {
421 return $this->attributes[$attrName];
422 }
423
424 /**
425 * Return whether given attribute is set
426 *
427 * @param string $attrName
428 * @return bool
429 */
430 public function hasAttribute($attrName)
431 {
432 return isset($this->attributes[$attrName]);
433 }
434
435 /**
436 * Remove given attribute
437 *
438 * @param string $attrName
439 * @return void
440 */
441 public function removeAttribute($attrName)
442 {
443 unset($this->attributes[$attrName]);
444 }
445
446 /**
447 * Set the value of an attribute
448 *
449 * @param string $attrName Attribute's name
450 * @param string $attrValue Attribute's value
451 * @return void
452 */
453 public function setAttribute($attrName, $attrValue)
454 {
455 $this->attributes[$attrName] = $attrValue;
456 }
457
458 /**
459 * Set all of this tag's attributes at once
460 *
461 * @param array $attributes
462 * @return void
463 */
464 public function setAttributes(array $attributes)
465 {
466 $this->attributes = $attributes;
467 }
468 }