Completed
Push — master ( ec8979...2d36c7 )
by mw
15:34
created

SemanticResultFormats::registerHooks()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
cc 1
eloc 12
nc 1
nop 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 22 and the first side effect is on line 9.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
/**
4
 * @see https://github.com/SemanticMediaWiki/SemanticResultFormats/
5
 *
6
 * @defgroup SRF Semantic Result Formats
7
 */
8
if ( !defined( 'MEDIAWIKI' ) ) {
9
	die( 'This file is part of the Semantic Result Formats extension, it is not a valid entry point.' );
10
}
11
12
if ( defined( 'SRF_VERSION' ) ) {
13
	// Do not initialize more than once.
14
	return 1;
15
}
16
17
SemanticResultFormats::load();
18
19
/**
20
 * @codeCoverageIgnore
21
 */
22
class SemanticResultFormats {
23
24
	/**
25
	 * @since 2.5
26
	 *
27
	 * @note It is expected that this function is loaded before LocalSettings.php
28
	 * to ensure that settings and global functions are available by the time
29
	 * the extension is activated.
30
	 */
31
	public static function load() {
0 ignored issues
show
Coding Style introduced by
load 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...
32
33
		if ( is_readable( __DIR__ . '/vendor/autoload.php' ) ) {
34
			include_once __DIR__ . '/vendor/autoload.php';
35
		}
36
37
		// Load DefaultSettings
38
		require_once __DIR__ . '/DefaultSettings.php';
39
40
		// In case extension.json is being used, the succeeding steps are
41
		// expected to be handled by the ExtensionRegistry aka extension.json
42
		self::initExtension();
43
44
		$GLOBALS['wgExtensionFunctions'][] = function() {
45
			self::onExtensionFunction();
46
		};
47
	}
48
49
	/**
50
	 * @since 2.5
51
	 */
52
	public static function initExtension() {
0 ignored issues
show
Coding Style introduced by
initExtension 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...
53
54
		define( 'SRF_VERSION', '3.0.0-alpha' );
55
56
		// Register the extension
57
		$GLOBALS['wgExtensionCredits']['semantic'][] = [
58
			'path' => __FILE__,
59
			'name' => 'Semantic Result Formats',
60
			'version' => SRF_VERSION,
61
			// At least 14 people have contributed formats to this extension, so
62
			// it would be prohibitive to list them all in the credits. Instead,
63
			// the current rule is to list anyone who has created, or contributed
64
			// significantly to, at least three formats, or the overall extension.
65
			'author' => [
66
				'James Hong Kong',
67
				'Stephan Gambke',
68
				'Jeroen De Dauw',
69
				'Yaron Koren',
70
				'...'
71
			],
72
			'url' => 'https://www.semantic-mediawiki.org/wiki/Semantic_Result_Formats',
73
			'descriptionmsg' => 'srf-desc',
74
			'license-name'   => 'GPL-2.0+'
75
		];
76
77
		// Register message files
78
		$GLOBALS['wgMessagesDirs']['SemanticResultFormats'] = __DIR__ . '/i18n';
79
		$GLOBALS['wgExtensionMessagesFiles']['SemanticResultFormats'] = __DIR__ . '/SemanticResultFormats.i18n.php';
80
		$GLOBALS['wgExtensionMessagesFiles']['SemanticResultFormatsMagic'] = __DIR__ . '/SemanticResultFormats.i18n.magic.php';
81
82
		$GLOBALS['srfgIP'] = __DIR__;
83
		$GLOBALS['wgResourceModules'] = array_merge( $GLOBALS['wgResourceModules'], include( __DIR__ . "/Resources.php" ) );
84
85
		self::registerHooks();
86
	}
87
88
	/**
89
	 * @since 2.5
90
	 */
91
	public static function registerHooks() {
0 ignored issues
show
Coding Style introduced by
registerHooks 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...
92
		$formatDir = __DIR__ . '/formats/';
93
94
		unset( $formatDir );
95
96
		$GLOBALS['wgHooks']['ParserFirstCallInit'][] = 'SRFParserFunctions::registerFunctions';
97
		$GLOBALS['wgHooks']['UnitTestsList'][] = 'SRFHooks::registerUnitTests';
98
99
		$GLOBALS['wgHooks']['ResourceLoaderTestModules'][] = 'SRFHooks::registerQUnitTests';
100
		$GLOBALS['wgHooks']['ResourceLoaderGetConfigVars'][] = 'SRFHooks::onResourceLoaderGetConfigVars';
101
102
		// Format hooks
103
		$GLOBALS['wgHooks']['OutputPageParserOutput'][] = 'SRF\Filtered\Hooks::onOutputPageParserOutput';
104
		$GLOBALS['wgHooks']['MakeGlobalVariablesScript'][] = 'SRF\Filtered\Hooks::onMakeGlobalVariablesScript';
105
106
		// register API modules
107
		$GLOBALS['wgAPIModules']['ext.srf.slideshow.show'] = 'SRFSlideShowApi';
108
109
		// User preference
110
		$GLOBALS['wgHooks']['SMW::GetPreferences'][] = 'SRFHooks::onGetPreferences';
111
112
		// Allows last minute changes to the output page, e.g. adding of CSS or JavaScript by extensions
113
		$GLOBALS['wgHooks']['BeforePageDisplay'][] = 'SRFHooks::onBeforePageDisplay';
114
	}
115
116
	/**
117
	 * @since 2.5
118
	 */
119
	public static function doCheckRequirements() {
0 ignored issues
show
Coding Style introduced by
doCheckRequirements 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...
120
121
		if ( version_compare( $GLOBALS[ 'wgVersion' ], '1.23', 'lt' ) ) {
122
			die( '<b>Error:</b> This version of <a href="https://github.com/SemanticMediaWiki/SemanticResultFormats/">Semantic Result Formats</a> is only compatible with MediaWiki 1.23 or above. You need to upgrade MediaWiki first.' );
0 ignored issues
show
Coding Style Compatibility introduced by
The method doCheckRequirements() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
123
		}
124
125
		if ( !defined( 'SMW_VERSION' ) ) {
126
			die( '<b>Error:</b> <a href="https://github.com/SemanticMediaWiki/SemanticResultFormats/">Semantic Result Formats</a> requires the <a href="https://github.com/SemanticMediaWiki/SemanticMediaWiki/">Semantic MediaWiki</a> extension. Please enable or install the extension first.' );
0 ignored issues
show
Coding Style Compatibility introduced by
The method doCheckRequirements() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
127
		}
128
	}
129
130
	/**
131
	 * @since 2.5
132
	 */
133
	public static function onExtensionFunction() {
0 ignored issues
show
Coding Style introduced by
onExtensionFunction 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...
134
135
		// Check requirements after LocalSetting.php has been processed, thid has
136
		// be done here to ensure SMW is loaded in case
137
		// wfLoadExtension( 'SemanticMediaWiki' ) is used
138
		self::doCheckRequirements();
139
140
		// Admin Links hook needs to be called in a delayed way so that it
141
		// will always be called after SMW's Admin Links addition; as of
142
		// SMW 1.9, SMW delays calling all its hook functions.
143
		$GLOBALS['wgHooks']['AdminLinks'][] = 'SRFHooks::addToAdminLinks';
144
145
		$GLOBALS['srfgScriptPath'] = ( $GLOBALS['wgExtensionAssetsPath'] === false ? $GLOBALS['wgScriptPath'] . '/extensions' : $GLOBALS['wgExtensionAssetsPath'] ) . '/SemanticResultFormats';
146
147
		$formatClasses = [
148
			// Assign the Boilerplate class to a format identifier
149
			// 'boilerplate' => 'SRFBoilerplate',
150
			'timeline' => 'SRFTimeline',
151
			'eventline' => 'SRFTimeline',
152
			'vcard' => 'SRFvCard',
153
			'icalendar' => 'SRFiCalendar',
154
			'bibtex' => 'SRFBibTeX',
155
			'calendar' => 'SRFCalendar',
156
			'eventcalendar' => 'SRF\EventCalendar',
157
			'outline' => 'SRFOutline',
158
			'sum' => 'SRFMath',
159
			'product' => 'SRFMath',
160
			'average' => 'SRFMath',
161
			'min' => 'SRFMath',
162
			'max' => 'SRFMath',
163
			'median' => 'SRFMath',
164
			'exhibit' => 'SRFExhibit',
165
			'googlebar' => 'SRFGoogleBar',
166
			'googlepie' => 'SRFGooglePie',
167
			'jitgraph' => 'SRFJitGraph',
168
			'jqplotchart' => 'SRFjqPlotChart',
169
			'jqplotseries' => 'SRFjqPlotSeries',
170
			'graph' => 'SRFGraph',
171
			'process' => 'SRFProcess',
172
			'gallery' => 'SRF\Gallery',
173
			'tagcloud' => 'SRF\TagCloud',
174
			'valuerank' => 'SRFValueRank',
175
			'array' => 'SRFArray',
176
			'hash' => 'SRFHash',
177
			'd3chart' => 'SRFD3Chart',
178
			'tree' => 'SRF\Formats\Tree\TreeResultPrinter',
179
			'ultree' => 'SRF\Formats\Tree\TreeResultPrinter',
180
			'oltree' => 'SRF\Formats\Tree\TreeResultPrinter',
181
			'filtered' => 'SRF\Filtered\Filtered',
182
			'latest' => 'SRFTime',
183
			'earliest' => 'SRFTime',
184
			'slideshow' => 'SRFSlideShow',
185
			'timeseries' => 'SRFTimeseries',
186
			'sparkline' => 'SRFSparkline',
187
			'listwidget' => 'SRFListWidget',
188
			'pagewidget' => 'SRFPageWidget',
189
			'dygraphs' => 'SRFDygraphs',
190
			'incoming' => 'SRFIncoming',
191
			'media' => 'SRF\MediaPlayer',
192
			'excel' => 'SRF\SRFExcel',
193
			'datatables' => 'SRF\DataTables'
194
		];
195
196
		$formatAliases = [
197
			'tagcloud'   => [ 'tag cloud' ],
198
			'datatables'   => [ 'datatable' ],
199
			'valuerank'  => [ 'value rank' ],
200
			'd3chart'    => [ 'd3 chart' ],
201
			'timeseries' =>  [ 'time series' ],
202
			'jqplotchart' => [ 'jqplot chart', 'jqplotpie', 'jqplotbar' ],
203
			'jqplotseries' => [ 'jqplot series' ],
204
		];
205
206
		foreach ( $GLOBALS['srfgFormats'] as $format ) {
0 ignored issues
show
Bug introduced by
The expression $GLOBALS['srfgFormats'] of type string|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
207
			if ( array_key_exists( $format, $formatClasses ) ) {
208
				$GLOBALS['smwgResultFormats'][$format] = $formatClasses[$format];
209
210
				if ( isset( $GLOBALS['smwgResultAliases'] ) && array_key_exists( $format, $formatAliases ) ) {
211
					$GLOBALS['smwgResultAliases'][$format] = $formatAliases[$format];
212
				}
213
			}
214
		}
215
	}
216
217
	/**
218
	 * @since 2.5
219
	 *
220
	 * @return string|null
221
	 */
222
	public static function getVersion() {
223
		return SRF_VERSION;
224
	}
225
226
}
227