Completed
Push — master ( 9eae06...a41cb5 )
by mw
16s
created

includes/ContentParser.php (2 issues)

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
namespace SMW;
4
5
use Parser;
6
use ParserOptions;
7
use Revision;
8
use Title;
9
use User;
10
11
/**
12
 * Fetches the ParserOutput either by parsing an invoked text component,
13
 * re-parsing a text revision, or accessing the ContentHandler to generate a
14
 * ParserOutput object
15
 *
16
 * @ingroup SMW
17
 *
18
 * @licence GNU GPL v2+
19
 * @since 1.9
20
 *
21
 * @author mwjames
22
 */
23
class ContentParser {
24
25
	/** @var Title */
26
	protected $title;
27
28
	/** @var Parser */
29
	protected $parser = null;
30
31
	/** @var ParserOutput */
32
	protected $parserOutput = null;
33
34
	/** @var Revision */
35
	protected $revision = null;
36
37
	/** @var array */
38
	protected $errors = array();
39
40
	/**
41
	 * @var boolean
42
	 */
43
	private $enabledToUseContentHandler = true;
44
45
	/**
46
	 * @var boolean
47
	 */
48
	private $skipInTextAnnotationParser = false;
49
50
	/**
51
	 * @note Injecting new Parser() alone will not yield an expected result and
52
	 * doing new Parser( $GLOBALS['wgParserConf'] brings no benefits therefore
53
	 * we stick to the GLOBAL as fallback if no parser is injected.
54
	 *
55
	 * @since 1.9
56
	 *
57
	 * @param Title $title
58
	 * @param Parser|null $parser
59
	 */
60 53
	public function __construct( Title $title, Parser $parser = null ) {
0 ignored issues
show
__construct uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
61 53
		$this->title  = $title;
62 53
		$this->parser = $parser;
63
64 53
		if ( $this->parser === null ) {
65 32
			$this->parser = $GLOBALS['wgParser'];
66
		}
67 53
	}
68
69
	/**
70
	 * @since 2.3
71
	 *
72
	 * @return Parser $parser
73
	 */
74
	public function setParser( Parser $parser ) {
75
		$this->parser = $parser;
76
	}
77
78
	/**
79
	 * @since 1.9.1
80
	 *
81
	 * @return ContentParser
82
	 */
83 10
	public function setRevision( Revision $revision = null ) {
84 10
		$this->revision = $revision;
85 10
		return $this;
86
	}
87
88
	/**
89
	 * @bug 62856 and #212
90
	 *
91
	 * @since 2.0
92
	 */
93 21
	public function forceToUseParser() {
94 21
		$this->enabledToUseContentHandler = false;
95 21
	}
96
97
	/**
98
	 * @since 1.9
99
	 *
100
	 * @return Title
101
	 */
102 52
	public function getTitle() {
103 52
		return $this->title;
104
	}
105
106
	/**
107
	 * @since 1.9
108
	 *
109
	 * @return ParserOutput|null
110
	 */
111 48
	public function getOutput() {
112 48
		return $this->parserOutput;
113
	}
114
115
	/**
116
	 * @since 1.9
117
	 *
118
	 * @return array
119
	 */
120 3
	public function getErrors() {
121 3
		return $this->errors;
122
	}
123
124
	public function skipInTextAnnotationParser() {
125
		return $this->skipInTextAnnotationParser = true;
126
	}
127
128
	/**
129
	 * Generates or fetches the ParserOutput object from an appropriate source
130
	 *
131
	 * @since 1.9
132
	 *
133
	 * @param string|null $text
134
	 *
135
	 * @return ContentParser
136
	 */
137 52
	public function parse( $text = null ) {
138
139 52
		if ( $text !== null ) {
140 16
			return $this->parseText( $text );
141
		}
142
143 36
		if ( $this->hasContentHandler() && $this->enabledToUseContentHandler ) {
144 12
			return $this->fetchFromContent();
145
		}
146
147 24
		return $this->fetchFromParser();
148
	}
149
150 16
	protected function parseText( $text ) {
151
152 16
		$this->parserOutput = $this->parser->parse(
153
			$text,
154 16
			$this->getTitle(),
155 16
			$this->makeParserOptions()
156
		);
157
158 16
		return $this;
159
	}
160
161
	/**
162
	 * @note Revision ID must be passed to the parser output to
163
	 * get revision variables correct
164
	 *
165
	 * @note If no content is available create an empty object
166
	 */
167 12
	protected function fetchFromContent() {
168
169 12
		if ( $this->getRevision() === null ) {
170 2
			return $this->msgForNullRevision();
171
		}
172
173 10
		$content = $this->getRevision()->getContent( Revision::RAW );
174
175 10
		if ( !$content ) {
176 1
			$content = $this->getRevision()->getContentHandler()->makeEmptyContent();
177
		}
178
179 10
		$this->parserOutput = $content->getParserOutput(
180 10
			$this->getTitle(),
181 10
			$this->getRevision()->getId(),
182 10
			null,
183 10
			true
184
		);
185
186 10
		return $this;
187
	}
188
189 24
	protected function fetchFromParser() {
190
191 24
		if ( $this->getRevision() === null ) {
192 2
			return $this->msgForNullRevision();
193
		}
194
195 22
		$this->parserOutput = $this->parser->parse(
196 22
			$this->getRevision()->getText(),
197 22
			$this->getTitle(),
198 22
			$this->makeParserOptions(),
199 22
			true,
200 22
			true,
201 22
			$this->getRevision()->getID()
202
		);
203
204 22
		return $this;
205
	}
206
207 4
	protected function msgForNullRevision( $fname = __METHOD__ ) {
208 4
		$this->errors = array( $fname . " No revision available for {$this->getTitle()->getPrefixedDBkey()}" );
209 4
		return $this;
210
	}
211
212 38
	protected function makeParserOptions() {
213
214 38
		$user = null;
215
216 38
		if ( $this->getRevision() !== null ) {
217 23
			$user = User::newFromId( $this->getRevision()->getUser() );
218
		}
219
220 38
		$parserOptions = new ParserOptions( $user );
221
222
		// Use the InterfaceMessage marker to skip InTextAnnotationParser
223
		// processing
224 38
		$parserOptions->setInterfaceMessage( $this->skipInTextAnnotationParser );
225
226 38
		return $parserOptions;
227
	}
228
229 52
	protected function getRevision() {
230
231 52
		if ( $this->revision instanceof Revision ) {
0 ignored issues
show
The class Revision does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
232 33
			return $this->revision;
233
		}
234
235
		// Revision::READ_NORMAL is not specified in MW 1.19
236 47
		if ( defined( 'Revision::READ_NORMAL' ) ) {
237 47
			$this->revision = Revision::newFromTitle( $this->getTitle(), false, Revision::READ_NORMAL );
238
		} else {
239
			$this->revision = Revision::newFromTitle( $this->getTitle() );
240
		}
241
242 47
		return $this->revision;
243
	}
244
245 29
	protected function hasContentHandler() {
246 29
		return defined( 'CONTENT_MODEL_WIKITEXT' );
247
	}
248
249
}
250