-
Notifications
You must be signed in to change notification settings - Fork 2
/
PicoDeprecated.php
383 lines (347 loc) · 11.4 KB
/
PicoDeprecated.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
<?php
/**
* This file is part of Pico. It's copyrighted by the contributors recorded
* in the version control history of the file, available from the following
* original location:
*
* <https://github.com/picocms/pico-deprecated/blob/master/PicoDeprecated.php>
*
* The file was previously part of the project's main repository; the version
* control history of the original file applies accordingly, available from
* the following original location:
*
* <https://github.com/picocms/Pico/blob/82a342ba445122182b898a2c1800f03c8d16f18c/plugins/00-PicoDeprecated.php>
*
* SPDX-License-Identifier: MIT
* License-Filename: LICENSE
*/
/**
* Maintain backward compatibility to older Pico releases
*
* `PicoDeprecated`'s purpose is to maintain backward compatibility to older
* versions of Pico, by re-introducing characteristics that were removed from
* Pico's core.
*
* `PicoDeprecated` is basically a mandatory plugin for all Pico installs.
* Without this plugin you can't use plugins which were written for other
* API versions than the one of Pico's core, even when there was just the
* slightest change.
*
* {@see http://picocms.org/plugins/deprecated/} for a full list of features.
*
* @author Daniel Rudolf
* @link http://picocms.org
* @license http://opensource.org/licenses/MIT The MIT License
* @version 2.1
*/
class PicoDeprecated extends AbstractPicoPlugin
{
/**
* API version used by this plugin
*
* @var int
*/
const API_VERSION = 3;
/**
* API version 0, used by Pico 0.9 and earlier
*
* @var int
*/
const API_VERSION_0 = 0;
/**
* API version 1, used by Pico 1.0
*
* @var int
*/
const API_VERSION_1 = 1;
/**
* API version 2, used by Pico 2.0
*
* @var int
*/
const API_VERSION_2 = 2;
/**
* API version 3, used by Pico 2.1
*
* @var int
*/
const API_VERSION_3 = 3;
/**
* Loaded plugins, indexed by API version
*
* @see PicoDeprecated::getPlugins()
*
* @var object[]
*/
protected $plugins = array();
/**
* Loaded compatibility plugins
*
* @see PicoDeprecated::getCompatPlugins()
*
* @var PicoCompatPluginInterface[]
*/
protected $compatPlugins = array();
/**
* {@inheritDoc}
*/
public function __construct(Pico $pico)
{
parent::__construct($pico);
if (is_file(__DIR__ . '/vendor/autoload.php')) {
require(__DIR__ . '/vendor/autoload.php');
}
if (!class_exists('PicoMainCompatPlugin')) {
die(
"Cannot find PicoDeprecated's 'vendor/autoload.php'. If you're using a composer-based Pico install, "
. "run `composer update`. If you're rather trying to use one of PicoDeprecated's pre-built release "
. "packages, make sure to download PicoDeprecated's release package matching Pico's version named "
. "'pico-deprecated-release-v*.tar.gz' (don't download a source code package)."
);
}
if ($pico::API_VERSION !== static::API_VERSION) {
throw new RuntimeException(
'PicoDeprecated requires API version ' . static::API_VERSION . ', '
. 'but Pico is running API version ' . $pico::API_VERSION
);
}
}
/**
* {@inheritDoc}
*/
public function handleEvent($eventName, array $params)
{
parent::handleEvent($eventName, $params);
// trigger events on compatibility plugins
if ($this->isEnabled() || ($eventName === 'onPluginsLoaded')) {
$isCoreEvent = in_array($eventName, $this->getCoreEvents());
foreach ($this->compatPlugins as $plugin) {
if ($isCoreEvent) {
if ($plugin->getApiVersion() === static::API_VERSION) {
$plugin->handleEvent($eventName, $params);
}
} elseif ($plugin instanceof PicoPluginApiCompatPluginInterface) {
$plugin->handleCustomEvent($eventName, $params);
}
}
}
}
/**
* Reads all loaded plugins and indexes them by API level, loads the
* necessary compatibility plugins
*
* @see PicoDeprecated::loadPlugin()
*
* @param object[] $plugins loaded plugin instances
*/
public function onPluginsLoaded(array $plugins)
{
$this->loadCompatPlugin('PicoMainCompatPlugin');
foreach ($plugins as $plugin) {
$this->loadPlugin($plugin);
}
$this->getPico()->triggerEvent('onPicoDeprecated', array($this));
}
/**
* Adds a manually loaded plugin to PicoDeprecated's plugin index, loads
* the necessary compatibility plugins
*
* @see PicoDeprecated::loadPlugin()
*
* @param object $plugin loaded plugin instance
*/
public function onPluginManuallyLoaded($plugin)
{
$this->loadPlugin($plugin);
}
/**
* Loads a compatibility plugin if Pico's theme uses a old theme API
*
* @param string $theme name of current theme
* @param int $themeApiVersion API version of the theme
* @param array $themeConfig config array of the theme
*/
public function onThemeLoaded($theme, $themeApiVersion, array &$themeConfig)
{
$this->loadThemeApiCompatPlugin($themeApiVersion);
}
/**
* Adds a plugin to PicoDeprecated's plugin index
*
* @see PicoDeprecated::onPluginsLoaded()
* @see PicoDeprecated::onPluginManuallyLoaded()
* @see PicoDeprecated::getPlugins()
*
* @param object $plugin loaded plugin instance
*/
protected function loadPlugin($plugin)
{
$pluginName = get_class($plugin);
$apiVersion = $this->getPluginApiVersion($plugin);
if (!isset($this->plugins[$apiVersion])) {
$this->plugins[$apiVersion] = array();
$this->loadPluginApiCompatPlugin($apiVersion);
}
$this->plugins[$apiVersion][$pluginName] = $plugin;
}
/**
* Returns a list of all loaded Pico plugins using the given API level
*
* @param int $apiVersion API version to match plugins
*
* @return object[] loaded plugin instances
*/
public function getPlugins($apiVersion)
{
return isset($this->plugins[$apiVersion]) ? $this->plugins[$apiVersion] : array();
}
/**
* Loads a compatibility plugin
*
* @param PicoCompatPluginInterface|string $plugin either the class name of
* a plugin to instantiate or a plugin instance
*
* @return PicoCompatPluginInterface instance of the loaded plugin
*/
public function loadCompatPlugin($plugin)
{
if (!is_object($plugin)) {
$className = (string) $plugin;
if (class_exists($className)) {
$plugin = new $className($this->getPico(), $this);
} else {
throw new RuntimeException(
"Unable to load PicoDeprecated compatibility plugin '" . $className . "': Class not found"
);
}
}
$className = get_class($plugin);
if (isset($this->compatPlugins[$className])) {
return $this->compatPlugins[$className];
}
if (!($plugin instanceof PicoCompatPluginInterface)) {
throw new RuntimeException(
"Unable to load PicoDeprecated compatibility plugin '" . $className . "': "
. "Compatibility plugins must implement 'PicoCompatPluginInterface'"
);
}
$apiVersion = $plugin->getApiVersion();
$this->loadPluginApiCompatPlugin($apiVersion);
$dependsOn = $plugin->getDependencies();
foreach ($dependsOn as $pluginDependency) {
$this->loadCompatPlugin($pluginDependency);
}
$this->compatPlugins[$className] = $plugin;
return $plugin;
}
/**
* Loads a plugin API compatibility plugin
*
* @param int $apiVersion API version to load the compatibility plugin for
*/
protected function loadPluginApiCompatPlugin($apiVersion)
{
if ($apiVersion !== static::API_VERSION) {
$this->loadCompatPlugin('PicoPluginApi' . $apiVersion . 'CompatPlugin');
}
}
/**
* Loads a theme API compatibility plugin
*
* @param int $apiVersion API version to load the compatibility plugin for
*/
protected function loadThemeApiCompatPlugin($apiVersion)
{
if ($apiVersion !== static::API_VERSION) {
$this->loadCompatPlugin('PicoThemeApi' . $apiVersion . 'CompatPlugin');
}
}
/**
* Returns all loaded compatibility plugins
*
* @return PicoCompatPluginInterface[] list of loaded compatibility plugins
*/
public function getCompatPlugins()
{
return $this->compatPlugins;
}
/**
* Triggers deprecated events on plugins of different API versions
*
* You can use this public method in other plugins to trigger custom events
* on plugins using a particular API version. If you want to trigger a
* custom event on all plugins, no matter their API version (except for
* plugins using API v0, which can't handle custom events), use
* {@see Pico::triggerEvent()} instead.
*
* @see Pico::triggerEvent()
*
* @param int $apiVersion API version of the event
* @param string $eventName event to trigger
* @param array $params optional parameters to pass
*/
public function triggerEvent($apiVersion, $eventName, array $params = array())
{
foreach ($this->getPlugins($apiVersion) as $plugin) {
$plugin->handleEvent($eventName, $params);
}
}
/**
* Returns the API version of a given plugin
*
* @param object $plugin plugin instance
*
* @return int API version used by the plugin
*/
public function getPluginApiVersion($plugin)
{
$pluginApiVersion = self::API_VERSION_0;
if ($plugin instanceof PicoPluginInterface) {
$pluginApiVersion = self::API_VERSION_1;
if (defined(get_class($plugin) . '::API_VERSION')) {
$pluginApiVersion = $plugin::API_VERSION;
}
}
return $pluginApiVersion;
}
/**
* Returns a list of the names of Pico's core events
*
* @return string[] list of Pico's core events
*/
public function getCoreEvents()
{
return array(
'onPluginsLoaded',
'onPluginManuallyLoaded',
'onConfigLoaded',
'onThemeLoading',
'onThemeLoaded',
'onRequestUrl',
'onRequestFile',
'onContentLoading',
'on404ContentLoading',
'on404ContentLoaded',
'onContentLoaded',
'onMetaParsing',
'onMetaParsed',
'onContentParsing',
'onContentPrepared',
'onContentParsed',
'onPagesLoading',
'onSinglePageLoading',
'onSinglePageContent',
'onSinglePageLoaded',
'onPagesDiscovered',
'onPagesLoaded',
'onCurrentPageDiscovered',
'onPageTreeBuilt',
'onPageRendering',
'onPageRendered',
'onMetaHeaders',
'onYamlParserRegistered',
'onParsedownRegistered',
'onTwigRegistered'
);
}
}