GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( bead6a...6dc797 )
by
unknown
04:30
created

src/BasicBackend.php (13 issues)

Labels
Severity
1
<?php
2
3
/**
4
 * File holding the Lingo\Backend class
5
 *
6
 * This file is part of the MediaWiki extension Lingo.
7
 *
8
 * @copyright 2011 - 2018, Stephan Gambke
9
 * @license   GNU General Public License, version 2 (or any later version)
10
 *
11
 * The Lingo extension is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by the Free
13
 * Software Foundation; either version 2 of the License, or (at your option) any
14
 * later version.
15
 *
16
 * The Lingo extension is distributed in the hope that it will be useful, but
17
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19
 * details.
20
 *
21
 * You should have received a copy of the GNU General Public License along
22
 * with this program. If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 * @author Stephan Gambke
25
 * @file
26
 * @ingroup Lingo
27
 */
28
namespace Lingo;
29
30
use ApprovedRevs;
0 ignored issues
show
The type ApprovedRevs was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
use Hooks;
0 ignored issues
show
The type Hooks was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use Parser;
0 ignored issues
show
The type Parser was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use ParserOptions;
0 ignored issues
show
The type ParserOptions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use Revision;
0 ignored issues
show
The type Revision was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
use TextContent;
0 ignored issues
show
The type TextContent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
36
use Title;
0 ignored issues
show
The type Title was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
37
use User;
0 ignored issues
show
The type User was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
38
use WikiPage;
0 ignored issues
show
The type WikiPage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
40
/**
41
 * The Lingo\BasicBackend class.
42
 *
43
 * @ingroup Lingo
44
 */
45
class BasicBackend extends Backend {
46
47
	protected $mArticleLines = null;
48
49
	/**
50
	 * Lingo\BasicBackend constructor.
51
	 * @param MessageLog|null $messages
52
	 */
53 1
	public function __construct( MessageLog &$messages = null ) {
54 1
		parent::__construct( $messages );
55
56 1
		$this->registerHooks();
57 1
	}
58
59 17
	protected function registerHooks() {
60 17
		Hooks::register( 'ArticlePurge', [ $this, 'purgeCache' ] );
61 17
		Hooks::register( 'PageContentSave', [ $this, 'purgeCache' ] );
62 17
	}
63
64
	/**
65
	 * This function returns the next element. The element is an array of four
66
	 * strings: Term, Definition, Link, Source. For the Lingo\BasicBackend Link
67
	 * and Source are set to null. If there is no next element the function
68
	 * returns null.
69
	 *
70
	 * @return array | null
71
	 * @throws \MWException
72
	 */
73 7
	public function next() {
74 7
		static $term = null;
75 7
		static $definitions = [];
76 7
		static $ret = [];
77
78 7
		$this->collectDictionaryLines();
79
80
		// loop backwards: accumulate definitions until term found
81 7
		while ( ( count( $ret ) === 0 ) && ( $this->mArticleLines ) ) {
82
83 7
			$line = array_pop( $this->mArticleLines );
84
85 7
			if ( $this->isValidGlossaryLine( $line ) ) {
86
87 6
				list( $term, $definitions ) = $this->processNextGlossaryLine( $line, $term, $definitions );
88
89 6
				if ( $term !== null ) {
90 6
					$ret = $this->queueDefinitions( $definitions, $term );
91
				}
92
			}
93
		}
94
95 7
		return array_pop( $ret );
96
	}
97
98
	/**
99
	 * @param string $line
100
	 * @param string $term
101
	 * @param string[] $definitions
102
	 * @return array
103
	 */
104 9
	protected function processNextGlossaryLine( $line, $term, $definitions ) {
105 9
		$chunks = explode( ':', $line, 2 );
106
107
		// found a new definition?
108 9
		if ( count( $chunks ) === 2 ) {
109
110
			// wipe the data if it's a totally new term definition
111 9
			if ( !empty( $term ) && count( $definitions ) > 0 ) {
112 9
				$definitions = [];
113 9
				$term = null;
114
			}
115
116 9
			$definitions[] = trim( $chunks[ 1 ] );
117
		}
118
119
		// found a new term?
120 9
		if ( strlen( trim( $chunks[ 0 ] ) ) > 1 ) {
121 9
			$term = trim( substr( $chunks[ 0 ], 1 ) );
122
		}
123
124 9
		return [ $term, $definitions ];
125
	}
126
127
	/**
128
	 * @param string[] $definitions
129
	 * @param string $term
130
	 * @return array
131
	 */
132 9
	protected function queueDefinitions( $definitions, $term ) {
133 9
		$ret = [];
134
135 9
		foreach ( $definitions as $definition ) {
136 9
			$ret[] = [
137 9
				Element::ELEMENT_TERM       => $term,
138 9
				Element::ELEMENT_DEFINITION => $definition,
139 9
				Element::ELEMENT_LINK       => null,
140 9
				Element::ELEMENT_SOURCE     => null
141
			];
142
		}
143
144 9
		return $ret;
145
	}
146
147
	/**
148
	 * @throws \MWException
149
	 */
150 14
	protected function collectDictionaryLines() {
151 14
		if ( $this->mArticleLines !== null ) {
152 6
			return;
153
		}
154
155
		// Get Terminology page
156 14
		$dictionaryPageName = $this->getLingoPageName();
157 14
		$dictionaryTitle = $this->getTitleFromText( $dictionaryPageName );
158
159 14
		if ( $dictionaryTitle->getInterwiki() !== '' ) {
160 1
			$this->getMessageLog()->addError( wfMessage( 'lingo-terminologypagenotlocal', $dictionaryPageName )->inContentLanguage()->text() );
0 ignored issues
show
The function wfMessage was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

160
			$this->getMessageLog()->addError( /** @scrutinizer ignore-call */ wfMessage( 'lingo-terminologypagenotlocal', $dictionaryPageName )->inContentLanguage()->text() );
Loading history...
161 1
			return;
162
		}
163
164 13
		$rawContent = $this->getRawDictionaryContent( $dictionaryTitle );
165
166
		// Expand templates and variables in the text, producing valid, static
167
		// wikitext. Have to use a new anonymous user to avoid any leakage as
168
		// Lingo is caching only one user-independent glossary
169 13
		$parser = new Parser;
170 13
		$content = $parser->preprocess( $rawContent, $dictionaryTitle, new ParserOptions( new User() ) );
171
172 13
		$this->mArticleLines = explode( "\n", $content );
173 13
	}
174
175
	/**
176
	 * @return string
177
	 */
178 15
	private function getLingoPageName() {
179 15
		global $wgexLingoPage;
180 15
		return $wgexLingoPage ? $wgexLingoPage : wfMessage( 'lingo-terminologypagename' )->inContentLanguage()->text();
0 ignored issues
show
The function wfMessage was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

180
		return $wgexLingoPage ? $wgexLingoPage : /** @scrutinizer ignore-call */ wfMessage( 'lingo-terminologypagename' )->inContentLanguage()->text();
Loading history...
181
	}
182
183
	/**
184
	 * @param Title $dictionaryTitle
185
	 *
186
	 * @return null|string
187
	 */
188 13
	protected function getRawDictionaryContent( Title $dictionaryTitle ) {
189 13
		global $wgRequest;
190
191
		// This is a hack special-casing the submitting of the terminology page
192
		// itself. In this case the Revision is not up to date when we get here,
193
		// i.e. $revision->getText() would return outdated Text. This hack takes the
194
		// text directly out of the data from the web request.
195 13
		if ( $wgRequest->getVal( 'action', 'view' ) === 'submit' &&
196 13
			$this->getTitleFromText( $wgRequest->getVal( 'title' ) )->getArticleID() === $dictionaryTitle->getArticleID()
197
		) {
198
199 1
			return $wgRequest->getVal( 'wpTextbox1' );
200
		}
201
202 12
		$revision = $this->getRevisionFromTitle( $dictionaryTitle );
203
204 12
		if ( $revision !== null ) {
205
206 11
			$content = $revision->getContent();
207
208 11
			if ( is_null( $content ) ) {
209 1
				return '';
210
			}
211
212 10
			if ( $content instanceof TextContent ) {
213 9
				return $content->getNativeData();
214
			}
215
216 1
			$this->getMessageLog()->addError( wfMessage( 'lingo-notatextpage', $dictionaryTitle->getFullText() )->inContentLanguage()->text() );
0 ignored issues
show
The function wfMessage was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

216
			$this->getMessageLog()->addError( /** @scrutinizer ignore-call */ wfMessage( 'lingo-notatextpage', $dictionaryTitle->getFullText() )->inContentLanguage()->text() );
Loading history...
217
218
		} else {
219
220 1
			$this->getMessageLog()->addWarning( wfMessage( 'lingo-noterminologypage', $dictionaryTitle->getFullText() )->inContentLanguage()->text() );
221
		}
222
223 2
		return '';
224
	}
225
226
	/**
227
	 * Returns revision of the terms page.
228
	 *
229
	 * @param Title $title
230
	 * @return null|Revision
231
	 */
232 12
	protected function getRevisionFromTitle( Title $title ) {
233 12
		global $wgexLingoEnableApprovedRevs;
234
235 12
		if ( $wgexLingoEnableApprovedRevs ) {
236
237 2
			if ( defined( 'APPROVED_REVS_VERSION' ) ) {
238 1
				return $this->getApprovedRevisionFromTitle( $title );
239
			}
240
241 1
			$this->getMessageLog()->addWarning( wfMessage( 'lingo-noapprovedrevs' )->inContentLanguage()->text() );
0 ignored issues
show
The function wfMessage was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

241
			$this->getMessageLog()->addWarning( /** @scrutinizer ignore-call */ wfMessage( 'lingo-noapprovedrevs' )->inContentLanguage()->text() );
Loading history...
242
		}
243
244 11
		return $this->getLatestRevisionFromTitle( $title );
245
	}
246
247
	/**
248
	 * Initiates the purging of the cache when the Terminology page was saved or purged.
249
	 *
250
	 * @param WikiPage $wikipage
251
	 * @return Bool
252
	 */
253 1
	public function purgeCache( WikiPage &$wikipage ) {
254 1
		if ( !is_null( $wikipage ) && ( $wikipage->getTitle()->getText() === $this->getLingoPageName() ) ) {
255
256 1
			$this->getLingoParser()->purgeGlossaryFromCache();
257
		}
258
259 1
		return true;
260
	}
261
262
	/**
263
	 * The basic backend is cache-enabled so this function returns true.
264
	 *
265
	 * Actual caching is done by the parser, the backend just calls
266
	 * Lingo\LingoParser::purgeCache when necessary.
267
	 *
268
	 * @return bool
269
	 */
270 1
	public function useCache() {
271 1
		return true;
272
	}
273
274
	/**
275
	 * @codeCoverageIgnore
276
	 * @param $dictionaryPage
277
	 * @return Title
278
	 */
279
	protected function getTitleFromText( $dictionaryPage ) {
280
		return Title::newFromTextThrow( $dictionaryPage );
281
	}
282
283
	/**
284
	 * @codeCoverageIgnore
285
	 * @param Title $title
286
	 * @return null|Revision
287
	 */
288
	protected function getApprovedRevisionFromTitle( Title $title ) {
289
		return Revision::newFromId( ApprovedRevs::getApprovedRevID( $title ) );
290
	}
291
292
	/**
293
	 * @codeCoverageIgnore
294
	 * @param Title $title
295
	 * @return null|Revision
296
	 */
297
	protected function getLatestRevisionFromTitle( Title $title ) {
298
		return Revision::newFromTitle( $title );
299
	}
300
301
	/**
302
	 * @param $line
303
	 * @return bool
304
	 */
305 13
	protected function isValidGlossaryLine( $line ) {
306 13
		return !empty( $line ) && ( $line[ 0 ] === ';' || $line[ 0 ] === ':' );
307
	}
308
309
}
310