Failed Conditions
Push — psr2 ( ffc2cc...de2261 )
by Andreas
05:28
created

inc/parser/parser.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use dokuwiki\Lexer\Lexer;
4
use dokuwiki\ParserMode\Base;
5
use dokuwiki\ParserMode\ModeInterface;
6
7
/**
8
 * Define various types of modes used by the parser - they are used to
9
 * populate the list of modes another mode accepts
10
 */
11
global $PARSER_MODES;
12
$PARSER_MODES = array(
13
    // containers are complex modes that can contain many other modes
14
    // hr breaks the principle but they shouldn't be used in tables / lists
15
    // so they are put here
16
    'container'    => array('listblock','table','quote','hr'),
17
18
    // some mode are allowed inside the base mode only
19
    'baseonly'     => array('header'),
20
21
    // modes for styling text -- footnote behaves similar to styling
22
    'formatting'   => array('strong', 'emphasis', 'underline', 'monospace',
23
                            'subscript', 'superscript', 'deleted', 'footnote'),
24
25
    // modes where the token is simply replaced - they can not contain any
26
    // other modes
27
    'substition'   => array('acronym','smiley','wordblock','entity',
28
                            'camelcaselink', 'internallink','media',
29
                            'externallink','linebreak','emaillink',
30
                            'windowssharelink','filelink','notoc',
31
                            'nocache','multiplyentity','quotes','rss'),
32
33
    // modes which have a start and end token but inside which
34
    // no other modes should be applied
35
    'protected'    => array('preformatted','code','file','php','html','htmlblock','phpblock'),
36
37
    // inside this mode no wiki markup should be applied but lineendings
38
    // and whitespace isn't preserved
39
    'disabled'     => array('unformatted'),
40
41
    // used to mark paragraph boundaries
42
    'paragraphs'   => array('eol')
43
);
44
45
/**
46
 * Sets up the Lexer with modes and points it to the Handler
47
 * For an intro to the Lexer see: wiki:parser
48
 */
49
class Doku_Parser {
50
51
    /** @var Doku_Handler */
52
    protected $handler;
53
54
    /** @var Lexer $lexer */
55
    protected $lexer;
56
57
    /** @var ModeInterface[] $modes */
58
    protected $modes = array();
59
60
    /** @var bool mode connections may only be set up once */
61
    protected $connected = false;
62
63
    /**
64
     * Doku_Parser constructor.
65
     *
66
     * @param Doku_Handler $handler
67
     */
68
    public function __construct(Doku_Handler $handler) {
69
        $this->handler = $handler;
70
    }
71
72
    /**
73
     * Adds the base mode and initialized the lexer
74
     *
75
     * @param Base $BaseMode
76
     */
77
    protected function addBaseMode($BaseMode) {
78
        $this->modes['base'] = $BaseMode;
79
        if ( !$this->lexer ) {
80
            $this->lexer = new Lexer($this->handler, 'base', true);
81
        }
82
        $this->modes['base']->Lexer = $this->lexer;
83
    }
84
85
    /**
86
     * Add a new syntax element (mode) to the parser
87
     *
88
     * PHP preserves order of associative elements
89
     * Mode sequence is important
90
     *
91
     * @param string $name
92
     * @param ModeInterface $Mode
93
     */
94
    public function addMode($name, ModeInterface $Mode) {
95
        if ( !isset($this->modes['base']) ) {
96
            $this->addBaseMode(new Base());
97
        }
98
        $Mode->Lexer = $this->lexer; // FIXME should be done by setter
0 ignored issues
show
Accessing Lexer on the interface dokuwiki\ParserMode\ModeInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
99
        $this->modes[$name] = $Mode;
100
    }
101
102
    /**
103
     * Connect all modes with each other
104
     *
105
     * This is the last step before actually parsing.
106
     */
107
    protected function connectModes() {
108
109
        if ( $this->connected ) {
110
            return;
111
        }
112
113
        foreach ( array_keys($this->modes) as $mode ) {
114
            // Base isn't connected to anything
115
            if ( $mode == 'base' ) {
116
                continue;
117
            }
118
            $this->modes[$mode]->preConnect();
119
120
            foreach ( array_keys($this->modes) as $cm ) {
121
122
                if ( $this->modes[$cm]->accepts($mode) ) {
123
                    $this->modes[$mode]->connectTo($cm);
124
                }
125
126
            }
127
128
            $this->modes[$mode]->postConnect();
129
        }
130
131
        $this->connected = true;
132
    }
133
134
    /**
135
     * Parses wiki syntax to instructions
136
     *
137
     * @param string $doc the wiki syntax text
138
     * @return array instructions
139
     */
140
    public function parse($doc) {
141
        $this->connectModes();
142
        // Normalize CRs and pad doc
143
        $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
144
        $this->lexer->parse($doc);
145
        $this->handler->_finalize();
146
        return $this->handler->calls;
147
    }
148
149
}
150