1 | <?php |
||
2 | |||
3 | // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps |
||
4 | |||
5 | /** |
||
6 | * DokuWiki Plugin prosemirror (Renderer Component) |
||
7 | * |
||
8 | * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html |
||
9 | * @author Andreas Gohr <[email protected]> |
||
10 | */ |
||
11 | |||
12 | use dokuwiki\plugin\prosemirror\parser\ImageNode; |
||
13 | use dokuwiki\plugin\prosemirror\parser\LocalLinkNode; |
||
14 | use dokuwiki\plugin\prosemirror\parser\InternalLinkNode; |
||
15 | use dokuwiki\plugin\prosemirror\parser\ExternalLinkNode; |
||
16 | use dokuwiki\plugin\prosemirror\parser\InterwikiLinkNode; |
||
17 | use dokuwiki\plugin\prosemirror\parser\EmailLinkNode; |
||
18 | use dokuwiki\plugin\prosemirror\parser\WindowsShareLinkNode; |
||
19 | use dokuwiki\Extension\Event; |
||
0 ignored issues
–
show
|
|||
20 | use dokuwiki\plugin\prosemirror\schema\Mark; |
||
21 | use dokuwiki\plugin\prosemirror\schema\Node; |
||
22 | use dokuwiki\plugin\prosemirror\schema\NodeStack; |
||
23 | |||
24 | class renderer_plugin_prosemirror extends Doku_Renderer |
||
25 | { |
||
26 | /** @var NodeStack */ |
||
27 | public $nodestack; |
||
28 | |||
29 | /** @var NodeStack[] */ |
||
30 | protected $nodestackBackup = []; |
||
31 | |||
32 | /** @var array list of currently active formatting marks */ |
||
33 | protected $marks = []; |
||
34 | |||
35 | /** @var int column counter for table handling */ |
||
36 | protected $colcount = 0; |
||
37 | |||
38 | /** |
||
39 | * The format this renderer produces |
||
40 | */ |
||
41 | public function getFormat() |
||
42 | { |
||
43 | return 'prosemirror'; |
||
44 | } |
||
45 | |||
46 | public function addToNodestackTop(Node $node) |
||
47 | { |
||
48 | $this->nodestack->addTop($node); |
||
49 | } |
||
50 | |||
51 | public function addToNodestack(Node $node) |
||
52 | { |
||
53 | $this->nodestack->add($node); |
||
54 | } |
||
55 | |||
56 | public function dropFromNodeStack($nodeType) |
||
57 | { |
||
58 | $this->nodestack->drop($nodeType); |
||
59 | } |
||
60 | |||
61 | public function getCurrentMarks() |
||
62 | { |
||
63 | return $this->marks; |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * If there is a block scope open, close it. |
||
68 | */ |
||
69 | protected function clearBlock() |
||
70 | { |
||
71 | $parentNode = $this->nodestack->current()->getType(); |
||
72 | if ($parentNode == 'paragraph') { |
||
73 | $this->nodestack->drop($parentNode); |
||
74 | } |
||
75 | } |
||
76 | |||
77 | // FIXME implement all methods of Doku_Renderer here |
||
78 | |||
79 | /** @inheritDoc */ |
||
80 | public function document_start() |
||
81 | { |
||
82 | $this->nodestack = new NodeStack(); |
||
83 | } |
||
84 | |||
85 | /** @inheritDoc */ |
||
86 | public function document_end() |
||
87 | { |
||
88 | if ($this->nodestack->isEmpty()) { |
||
89 | $this->p_open(); |
||
90 | $this->p_close(); |
||
91 | } |
||
92 | $this->doc = json_encode($this->nodestack->doc(), JSON_PRETTY_PRINT); |
||
0 ignored issues
–
show
|
|||
93 | } |
||
94 | |||
95 | public function nocache() |
||
96 | { |
||
97 | $docNode = $this->nodestack->getDocNode(); |
||
98 | $docNode->attr('nocache', true); |
||
99 | } |
||
100 | |||
101 | public function notoc() |
||
102 | { |
||
103 | $docNode = $this->nodestack->getDocNode(); |
||
104 | $docNode->attr('notoc', true); |
||
105 | } |
||
106 | |||
107 | /** @inheritDoc */ |
||
108 | public function p_open() |
||
109 | { |
||
110 | $this->nodestack->addTop(new Node('paragraph')); |
||
111 | } |
||
112 | |||
113 | /** @inheritdoc */ |
||
114 | public function p_close() |
||
115 | { |
||
116 | $this->nodestack->drop('paragraph'); |
||
117 | } |
||
118 | |||
119 | /** @inheritDoc */ |
||
120 | public function quote_open() |
||
121 | { |
||
122 | if ($this->nodestack->current()->getType() === 'paragraph') { |
||
123 | $this->nodestack->drop('paragraph'); |
||
124 | } |
||
125 | $this->nodestack->addTop(new Node('blockquote')); |
||
126 | } |
||
127 | |||
128 | /** @inheritDoc */ |
||
129 | public function quote_close() |
||
130 | { |
||
131 | if ($this->nodestack->current()->getType() === 'paragraph') { |
||
132 | $this->nodestack->drop('paragraph'); |
||
133 | } |
||
134 | $this->nodestack->drop('blockquote'); |
||
135 | } |
||
136 | |||
137 | #region lists |
||
138 | |||
139 | /** @inheritDoc */ |
||
140 | public function listu_open() |
||
141 | { |
||
142 | if ($this->nodestack->current()->getType() === 'paragraph') { |
||
143 | $this->nodestack->drop('paragraph'); |
||
144 | } |
||
145 | |||
146 | $this->nodestack->addTop(new Node('bullet_list')); |
||
147 | } |
||
148 | |||
149 | /** @inheritDoc */ |
||
150 | public function listu_close() |
||
151 | { |
||
152 | $this->nodestack->drop('bullet_list'); |
||
153 | } |
||
154 | |||
155 | /** @inheritDoc */ |
||
156 | public function listo_open() |
||
157 | { |
||
158 | if ($this->nodestack->current()->getType() === 'paragraph') { |
||
159 | $this->nodestack->drop('paragraph'); |
||
160 | } |
||
161 | |||
162 | $this->nodestack->addTop(new Node('ordered_list')); |
||
163 | } |
||
164 | |||
165 | /** @inheritDoc */ |
||
166 | public function listo_close() |
||
167 | { |
||
168 | $this->nodestack->drop('ordered_list'); |
||
169 | } |
||
170 | |||
171 | /** @inheritDoc */ |
||
172 | public function listitem_open($level, $node = false) |
||
173 | { |
||
174 | $this->nodestack->addTop(new Node('list_item')); |
||
175 | |||
176 | $paragraphNode = new Node('paragraph'); |
||
177 | $this->nodestack->addTop($paragraphNode); |
||
178 | } |
||
179 | |||
180 | /** @inheritDoc */ |
||
181 | public function listitem_close() |
||
182 | { |
||
183 | |||
184 | if ($this->nodestack->current()->getType() === 'paragraph') { |
||
185 | $this->nodestack->drop('paragraph'); |
||
186 | } |
||
187 | $this->nodestack->drop('list_item'); |
||
188 | } |
||
189 | |||
190 | #endregion lists |
||
191 | |||
192 | #region table |
||
193 | |||
194 | /** @inheritDoc */ |
||
195 | public function table_open($maxcols = null, $numrows = null, $pos = null) |
||
196 | { |
||
197 | $this->nodestack->addTop(new Node('table')); |
||
198 | } |
||
199 | |||
200 | /** @inheritDoc */ |
||
201 | public function table_close($pos = null) |
||
202 | { |
||
203 | $this->nodestack->drop('table'); |
||
204 | } |
||
205 | |||
206 | /** @inheritDoc */ |
||
207 | public function tablerow_open() |
||
208 | { |
||
209 | $this->nodestack->addTop(new Node('table_row')); |
||
210 | $this->colcount = 0; |
||
211 | } |
||
212 | |||
213 | /** @inheritDoc */ |
||
214 | public function tablerow_close() |
||
215 | { |
||
216 | $node = $this->nodestack->drop('table_row'); |
||
217 | $node->attr('columns', $this->colcount); |
||
218 | } |
||
219 | |||
220 | /** @inheritDoc */ |
||
221 | public function tablecell_open($colspan = 1, $align = null, $rowspan = 1) |
||
222 | { |
||
223 | $this->openTableCell('table_cell', $colspan, $align, $rowspan); |
||
224 | } |
||
225 | |||
226 | /** @inheritdoc */ |
||
227 | public function tablecell_close() |
||
228 | { |
||
229 | $this->closeTableCell('table_cell'); |
||
230 | } |
||
231 | |||
232 | /** @inheritDoc */ |
||
233 | public function tableheader_open($colspan = 1, $align = null, $rowspan = 1) |
||
234 | { |
||
235 | $this->openTableCell('table_header', $colspan, $align, $rowspan); |
||
236 | } |
||
237 | |||
238 | /** @inheritdoc */ |
||
239 | public function tableheader_close() |
||
240 | { |
||
241 | $this->closeTableCell('table_header'); |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Add a new table cell to the top of the stack |
||
246 | * |
||
247 | * @param string $type either table_cell or table_header |
||
248 | * @param int $colspan |
||
249 | * @param string|null $align either null/left, center or right |
||
250 | * @param int $rowspan |
||
251 | */ |
||
252 | protected function openTableCell($type, $colspan, $align, $rowspan) |
||
253 | { |
||
254 | $this->colcount += $colspan; |
||
255 | |||
256 | $node = new Node($type); |
||
257 | $node->attr('colspan', $colspan); |
||
258 | $node->attr('rowspan', $rowspan); |
||
259 | $node->attr('align', $align); |
||
260 | |||
261 | $this->nodestack->addTop($node); |
||
262 | |||
263 | $node = new Node('paragraph'); |
||
264 | $this->nodestack->addTop($node); |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Remove a table cell from the top of the stack |
||
269 | * |
||
270 | * @param string $type either table_cell or table_header |
||
271 | */ |
||
272 | protected function closeTableCell($type) |
||
273 | { |
||
274 | if ($this->nodestack->current()->getType() === 'paragraph') { |
||
275 | $this->nodestack->drop('paragraph'); |
||
276 | } |
||
277 | |||
278 | $curNode = $this->nodestack->current(); |
||
279 | $curNode->trimContentLeft(); |
||
280 | $curNode->trimContentRight(); |
||
281 | |||
282 | $this->nodestack->drop($type); |
||
283 | } |
||
284 | |||
285 | #endregion table |
||
286 | |||
287 | /** @inheritDoc */ |
||
288 | public function header($text, $level, $pos) |
||
289 | { |
||
290 | $node = new Node('heading'); |
||
291 | $node->attr('level', $level); |
||
292 | |||
293 | $tnode = new Node('text'); |
||
294 | $tnode->setText($text); |
||
295 | |||
296 | $node->addChild($tnode); |
||
297 | |||
298 | $this->nodestack->add($node); |
||
299 | } |
||
300 | |||
301 | /** @inheritDoc */ |
||
302 | public function cdata($text) |
||
303 | { |
||
304 | if ($text === '') { |
||
305 | return; |
||
306 | } |
||
307 | |||
308 | $parentNode = $this->nodestack->current()->getType(); |
||
309 | |||
310 | if (in_array($parentNode, ['paragraph', 'footnote'])) { |
||
311 | $text = str_replace("\n", ' ', $text); |
||
312 | } |
||
313 | |||
314 | if ($parentNode === 'list_item') { |
||
315 | $node = new Node('paragraph'); |
||
316 | $this->nodestack->addTop($node); |
||
317 | } |
||
318 | |||
319 | if ($parentNode === 'blockquote') { |
||
320 | $node = new Node('paragraph'); |
||
321 | $this->nodestack->addTop($node); |
||
322 | } |
||
323 | |||
324 | if ($parentNode === 'doc') { |
||
325 | $node = new Node('paragraph'); |
||
326 | $this->nodestack->addTop($node); |
||
327 | } |
||
328 | |||
329 | $node = new Node('text'); |
||
330 | $node->setText($text); |
||
331 | foreach (array_keys($this->marks) as $mark) { |
||
332 | $node->addMark(new Mark($mark)); |
||
333 | } |
||
334 | $this->nodestack->add($node); |
||
335 | } |
||
336 | |||
337 | public function preformatted($text) |
||
338 | { |
||
339 | $this->clearBlock(); |
||
340 | $node = new Node('preformatted'); |
||
341 | $this->nodestack->addTop($node); |
||
342 | $this->cdata($text); |
||
343 | $this->nodestack->drop('preformatted'); |
||
344 | } |
||
345 | |||
346 | public function code($text, $lang = null, $file = null) |
||
347 | { |
||
348 | $this->clearBlock(); |
||
349 | $node = new Node('code_block'); |
||
350 | $node->attr('class', 'code ' . $lang); |
||
351 | $node->attr('data-language', $lang); |
||
352 | $node->attr('data-filename', $file); |
||
353 | |||
354 | $this->nodestack->addTop($node); |
||
355 | $this->cdata(trim($text, "\n")); |
||
356 | $this->nodestack->drop('code_block'); |
||
357 | } |
||
358 | |||
359 | public function file($text, $lang = null, $file = null) |
||
360 | { |
||
361 | $this->code($text, $lang, $file); |
||
362 | } |
||
363 | |||
364 | public function html($text) |
||
365 | { |
||
366 | $node = new Node('html_inline'); |
||
367 | $node->attr('class', 'html_inline'); |
||
368 | |||
369 | $this->nodestack->addTop($node); |
||
370 | $this->cdata(str_replace("\n", ' ', $text)); |
||
371 | $this->nodestack->drop('html_inline'); |
||
372 | } |
||
373 | |||
374 | public function htmlblock($text) |
||
375 | { |
||
376 | $this->clearBlock(); |
||
377 | $node = new Node('html_block'); |
||
378 | $node->attr('class', 'html_block'); |
||
379 | |||
380 | $this->nodestack->addTop($node); |
||
381 | $this->cdata(trim($text, "\n")); |
||
382 | $this->nodestack->drop('html_block'); |
||
383 | } |
||
384 | |||
385 | public function php($text) |
||
386 | { |
||
387 | $node = new Node('php_inline'); |
||
388 | $node->attr('class', 'php_inline'); |
||
389 | |||
390 | $this->nodestack->addTop($node); |
||
391 | $this->cdata(str_replace("\n", ' ', $text)); |
||
392 | $this->nodestack->drop('php_inline'); |
||
393 | } |
||
394 | |||
395 | public function phpblock($text) |
||
396 | { |
||
397 | $this->clearBlock(); |
||
398 | $node = new Node('php_block'); |
||
399 | $node->attr('class', 'php_block'); |
||
400 | |||
401 | $this->nodestack->addTop($node); |
||
402 | $this->cdata(trim($text, "\n")); |
||
403 | $this->nodestack->drop('php_block'); |
||
404 | } |
||
405 | |||
406 | /** |
||
407 | * @inheritDoc |
||
408 | */ |
||
409 | public function rss($url, $params) |
||
410 | { |
||
411 | $this->clearBlock(); |
||
412 | $node = new Node('rss'); |
||
413 | $node->attr('url', hsc($url)); |
||
414 | $node->attr('max', $params['max']); |
||
415 | $node->attr('reverse', (bool)$params['reverse']); |
||
416 | $node->attr('author', (bool)$params['author']); |
||
417 | $node->attr('date', (bool)$params['date']); |
||
418 | $node->attr('details', (bool)$params['details']); |
||
419 | |||
420 | if ($params['refresh'] % 86400 === 0) { |
||
421 | $refresh = $params['refresh'] / 86400 . 'd'; |
||
422 | } elseif ($params['refresh'] % 3600 === 0) { |
||
423 | $refresh = $params['refresh'] / 3600 . 'h'; |
||
424 | } else { |
||
425 | $refresh = $params['refresh'] / 60 . 'm'; |
||
426 | } |
||
427 | |||
428 | $node->attr('refresh', trim($refresh)); |
||
429 | $this->nodestack->add($node); |
||
430 | } |
||
431 | |||
432 | |||
433 | public function footnote_open() |
||
434 | { |
||
435 | $footnoteNode = new Node('footnote'); |
||
436 | $this->nodestack->addTop($footnoteNode); |
||
437 | $this->nodestackBackup[] = $this->nodestack; |
||
438 | $this->nodestack = new NodeStack(); |
||
439 | } |
||
440 | |||
441 | public function footnote_close() |
||
442 | { |
||
443 | $json = json_encode($this->nodestack->doc()); |
||
444 | $this->nodestack = array_pop($this->nodestackBackup); |
||
445 | $this->nodestack->current()->attr('contentJSON', $json); |
||
446 | $this->nodestack->drop('footnote'); |
||
447 | } |
||
448 | |||
449 | /** |
||
450 | * @inheritDoc |
||
451 | */ |
||
452 | public function internalmedia( |
||
453 | $src, |
||
454 | $title = null, |
||
455 | $align = null, |
||
456 | $width = null, |
||
457 | $height = null, |
||
458 | $cache = null, |
||
459 | $linking = null |
||
460 | ) { |
||
461 | |||
462 | // FIXME how do we handle non-images, e.g. pdfs or audio? |
||
463 | ImageNode::render( |
||
464 | $this, |
||
465 | $src, |
||
466 | $title, |
||
467 | $align, |
||
468 | $width, |
||
469 | $height, |
||
470 | $cache, |
||
471 | $linking |
||
472 | ); |
||
473 | } |
||
474 | |||
475 | /** |
||
476 | * @inheritDoc |
||
477 | */ |
||
478 | public function externalmedia( |
||
479 | $src, |
||
480 | $title = null, |
||
481 | $align = null, |
||
482 | $width = null, |
||
483 | $height = null, |
||
484 | $cache = null, |
||
485 | $linking = null |
||
486 | ) { |
||
487 | ImageNode::render( |
||
488 | $this, |
||
489 | $src, |
||
490 | $title, |
||
491 | $align, |
||
492 | $width, |
||
493 | $height, |
||
494 | $cache, |
||
495 | $linking |
||
496 | ); |
||
497 | } |
||
498 | |||
499 | |||
500 | public function locallink($hash, $name = null) |
||
501 | { |
||
502 | LocalLinkNode::render($this, $hash, $name); |
||
503 | } |
||
504 | |||
505 | /** |
||
506 | * @inheritDoc |
||
507 | */ |
||
508 | public function internallink($id, $name = null) |
||
509 | { |
||
510 | InternalLinkNode::render($this, $id, $name); |
||
511 | } |
||
512 | |||
513 | public function externallink($link, $title = null) |
||
514 | { |
||
515 | ExternalLinkNode::render($this, $link, $title); |
||
516 | } |
||
517 | |||
518 | public function interwikilink($link, $title, $wikiName, $wikiUri) |
||
519 | { |
||
520 | InterwikiLinkNode::render($this, $title, $wikiName, $wikiUri); |
||
521 | } |
||
522 | |||
523 | public function emaillink($address, $name = null) |
||
524 | { |
||
525 | EmailLinkNode::render($this, $address, $name); |
||
526 | } |
||
527 | |||
528 | public function windowssharelink($link, $title = null) |
||
529 | { |
||
530 | WindowsShareLinkNode::render($this, $link, $title); |
||
531 | } |
||
532 | |||
533 | /** @inheritDoc */ |
||
534 | public function linebreak() |
||
535 | { |
||
536 | $this->nodestack->add(new Node('hard_break')); |
||
537 | } |
||
538 | |||
539 | /** @inheritDoc */ |
||
540 | public function hr() |
||
541 | { |
||
542 | $this->nodestack->add(new Node('horizontal_rule')); |
||
543 | } |
||
544 | |||
545 | public function plugin($name, $data, $state = '', $match = '') |
||
546 | { |
||
547 | if (empty($match)) { |
||
548 | return; |
||
549 | } |
||
550 | $eventData = [ |
||
551 | 'name' => $name, |
||
552 | 'data' => $data, |
||
553 | 'state' => $state, |
||
554 | 'match' => $match, |
||
555 | 'renderer' => $this, |
||
556 | ]; |
||
557 | $event = new Event('PROSEMIRROR_RENDER_PLUGIN', $eventData); |
||
558 | if ($event->advise_before()) { |
||
559 | if ($this->nodestack->current()->getType() === 'paragraph') { |
||
560 | $nodetype = 'dwplugin_inline'; |
||
561 | } else { |
||
562 | $nodetype = 'dwplugin_block'; |
||
563 | } |
||
564 | $node = new Node($nodetype); |
||
565 | $node->attr('class', 'dwplugin'); |
||
566 | $node->attr('data-pluginname', $name); |
||
567 | $this->nodestack->addTop($node); |
||
568 | $this->cdata($match); |
||
569 | $this->nodestack->drop($nodetype); |
||
570 | } |
||
571 | } |
||
572 | |||
573 | public function smiley($smiley) |
||
574 | { |
||
575 | if (array_key_exists($smiley, $this->smileys)) { |
||
576 | $node = new Node('smiley'); |
||
577 | $node->attr('icon', $this->smileys[$smiley]); |
||
578 | $node->attr('syntax', $smiley); |
||
579 | $this->nodestack->add($node); |
||
580 | } else { |
||
581 | $this->cdata($smiley); |
||
582 | } |
||
583 | } |
||
584 | |||
585 | #region elements with no special WYSIWYG representation |
||
586 | |||
587 | /** @inheritDoc */ |
||
588 | public function entity($entity) |
||
589 | { |
||
590 | $this->cdata($entity); // FIXME should we handle them special? |
||
591 | } |
||
592 | |||
593 | /** @inheritDoc */ |
||
594 | public function multiplyentity($x, $y) |
||
595 | { |
||
596 | $this->cdata($x . 'x' . $y); |
||
597 | } |
||
598 | |||
599 | /** @inheritDoc */ |
||
600 | public function acronym($acronym) |
||
601 | { |
||
602 | $this->cdata($acronym); |
||
603 | } |
||
604 | |||
605 | /** @inheritDoc */ |
||
606 | public function apostrophe() |
||
607 | { |
||
608 | $this->cdata("'"); |
||
609 | } |
||
610 | |||
611 | /** @inheritDoc */ |
||
612 | public function singlequoteopening() |
||
613 | { |
||
614 | $this->cdata("'"); |
||
615 | } |
||
616 | |||
617 | /** @inheritDoc */ |
||
618 | public function singlequoteclosing() |
||
619 | { |
||
620 | $this->cdata("'"); |
||
621 | } |
||
622 | |||
623 | /** @inheritDoc */ |
||
624 | public function doublequoteopening() |
||
625 | { |
||
626 | $this->cdata('"'); |
||
627 | } |
||
628 | |||
629 | /** @inheritDoc */ |
||
630 | public function doublequoteclosing() |
||
631 | { |
||
632 | $this->cdata('"'); |
||
633 | } |
||
634 | |||
635 | /** @inheritDoc */ |
||
636 | public function camelcaselink($link) |
||
637 | { |
||
638 | $this->cdata($link); // FIXME should/could we decorate it? |
||
639 | } |
||
640 | |||
641 | #endregion |
||
642 | |||
643 | #region formatter marks |
||
644 | |||
645 | /** @inheritDoc */ |
||
646 | public function strong_open() |
||
647 | { |
||
648 | $this->marks['strong'] = 1; |
||
649 | } |
||
650 | |||
651 | /** @inheritDoc */ |
||
652 | public function strong_close() |
||
653 | { |
||
654 | if (isset($this->marks['strong'])) { |
||
655 | unset($this->marks['strong']); |
||
656 | } |
||
657 | } |
||
658 | |||
659 | /** @inheritDoc */ |
||
660 | public function emphasis_open() |
||
661 | { |
||
662 | $this->marks['em'] = 1; |
||
663 | } |
||
664 | |||
665 | /** @inheritDoc */ |
||
666 | public function emphasis_close() |
||
667 | { |
||
668 | if (isset($this->marks['em'])) { |
||
669 | unset($this->marks['em']); |
||
670 | } |
||
671 | } |
||
672 | |||
673 | /** @inheritdoc */ |
||
674 | public function subscript_open() |
||
675 | { |
||
676 | $this->marks['subscript'] = 1; |
||
677 | } |
||
678 | |||
679 | /** @inheritDoc */ |
||
680 | public function subscript_close() |
||
681 | { |
||
682 | if (isset($this->marks['subscript'])) { |
||
683 | unset($this->marks['subscript']); |
||
684 | } |
||
685 | } |
||
686 | |||
687 | /** @inheritdoc */ |
||
688 | public function superscript_open() |
||
689 | { |
||
690 | $this->marks['superscript'] = 1; |
||
691 | } |
||
692 | |||
693 | /** @inheritDoc */ |
||
694 | public function superscript_close() |
||
695 | { |
||
696 | if (isset($this->marks['superscript'])) { |
||
697 | unset($this->marks['superscript']); |
||
698 | } |
||
699 | } |
||
700 | |||
701 | /** @inheritDoc */ |
||
702 | public function monospace_open() |
||
703 | { |
||
704 | $this->marks['code'] = 1; |
||
705 | } |
||
706 | |||
707 | /** @inheritDoc */ |
||
708 | public function monospace_close() |
||
709 | { |
||
710 | if (isset($this->marks['code'])) { |
||
711 | unset($this->marks['code']); |
||
712 | } |
||
713 | } |
||
714 | |||
715 | /** @inheritDoc */ |
||
716 | public function deleted_open() |
||
717 | { |
||
718 | $this->marks['deleted'] = 1; |
||
719 | } |
||
720 | |||
721 | /** @inheritDoc */ |
||
722 | public function deleted_close() |
||
723 | { |
||
724 | if (isset($this->marks['deleted'])) { |
||
725 | unset($this->marks['deleted']); |
||
726 | } |
||
727 | } |
||
728 | |||
729 | /** @inheritDoc */ |
||
730 | public function underline_open() |
||
731 | { |
||
732 | $this->marks['underline'] = 1; |
||
733 | } |
||
734 | |||
735 | /** @inheritDoc */ |
||
736 | public function underline_close() |
||
737 | { |
||
738 | if (isset($this->marks['underline'])) { |
||
739 | unset($this->marks['underline']); |
||
740 | } |
||
741 | } |
||
742 | |||
743 | |||
744 | /** @inheritDoc */ |
||
745 | public function unformatted($text) |
||
746 | { |
||
747 | $this->marks['unformatted'] = 1; |
||
748 | parent::unformatted($text); |
||
749 | unset($this->marks['unformatted']); |
||
750 | } |
||
751 | |||
752 | |||
753 | #endregion formatter marks |
||
754 | } |
||
755 |
Let?s assume that you have a directory layout like this:
and let?s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: