PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.3.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.3.1
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Application / Kernel / PluginList.php
matomo / app / core / Application / Kernel Last commit date
EnvironmentValidator.php 6 years ago GlobalSettingsProvider.php 6 years ago PluginList.php 6 years ago
PluginList.php
198 lines
1 <?php
2 /**
3 * Piwik - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 */
8
9 namespace Piwik\Application\Kernel;
10
11 use Piwik\Plugin\MetadataLoader;
12
13 /**
14 * Lists the currently activated plugins. Used when setting up Piwik's environment before
15 * initializing the DI container.
16 *
17 * Uses the [Plugins] section in Piwik's INI config to get the activated plugins.
18 *
19 * Depends on GlobalSettingsProvider being used.
20 *
21 * TODO: parts of Plugin\Manager edit the plugin list; maybe PluginList implementations should be mutable?
22 */
23 class PluginList
24 {
25 /**
26 * @var GlobalSettingsProvider
27 */
28 private $settings;
29
30 /**
31 * Plugins bundled with core package, disabled by default
32 * @var array
33 */
34 private $corePluginsDisabledByDefault = array(
35 'DBStats',
36 'ExamplePlugin',
37 'ExampleCommand',
38 'ExampleSettingsPlugin',
39 'ExampleUI',
40 'ExampleVisualization',
41 'ExamplePluginTemplate',
42 'ExampleTracker',
43 'ExampleLogTables',
44 'ExampleReport',
45 'ExampleAPI',
46 'MobileAppMeasurable',
47 'Provider',
48 'TagManager'
49 );
50
51 // Themes bundled with core package, disabled by default
52 private $coreThemesDisabledByDefault = array(
53 'ExampleTheme'
54 );
55
56 public function __construct(GlobalSettingsProvider $settings)
57 {
58 $this->settings = $settings;
59 }
60
61 /**
62 * Returns the list of plugins that should be loaded. Used by the container factory to
63 * load plugin specific DI overrides.
64 *
65 * @return string[]
66 */
67 public function getActivatedPlugins()
68 {
69 $section = $this->settings->getSection('Plugins');
70 $plugins = @$section['Plugins'] ?: array();
71
72 return $plugins;
73 }
74
75 /**
76 * Returns the list of plugins that are bundled with Piwik.
77 *
78 * @return string[]
79 */
80 public function getPluginsBundledWithPiwik()
81 {
82 $pathGlobal = $this->settings->getPathGlobal();
83
84 $section = $this->settings->getIniFileChain()->getFrom($pathGlobal, 'Plugins');
85 return $section['Plugins'];
86 }
87
88 /**
89 * Returns the plugins bundled with core package that are disabled by default.
90 *
91 * @return string[]
92 */
93 public function getCorePluginsDisabledByDefault()
94 {
95 return array_merge($this->corePluginsDisabledByDefault, $this->coreThemesDisabledByDefault);
96 }
97
98 /**
99 * Sorts an array of plugins in the order they should be loaded. We cannot use DI here as DI is not initialized
100 * at this stage.
101 *
102 * @params string[] $plugins
103 * @return \string[]
104 */
105 public function sortPlugins(array $plugins)
106 {
107 $global = $this->getPluginsBundledWithPiwik();
108 if (empty($global)) {
109 return $plugins;
110 }
111
112 // we need to make sure a possibly disabled plugin will be still loaded before any 3rd party plugin
113 $global = array_merge($global, $this->corePluginsDisabledByDefault);
114
115 $global = array_values($global);
116 $plugins = array_values($plugins);
117
118 $defaultPluginsLoadedFirst = array_intersect($global, $plugins);
119
120 $otherPluginsToLoadAfterDefaultPlugins = array_diff($plugins, $defaultPluginsLoadedFirst);
121
122 // sort by name to have a predictable order for those extra plugins
123 natcasesort($otherPluginsToLoadAfterDefaultPlugins);
124
125 $sorted = array_merge($defaultPluginsLoadedFirst, $otherPluginsToLoadAfterDefaultPlugins);
126
127 return $sorted;
128 }
129
130 /**
131 * Sorts an array of plugins in the order they should be saved in config.ini.php. This basically influences
132 * the order of the plugin config.php and which config will be loaded first. We want to make sure to require the
133 * config or a required plugin first before loading the plugin that requires it.
134 *
135 * We do not sort using this logic on each request since it is much slower than `sortPlugins()`. The order
136 * of plugins in config.ini.php is only important for the ContainerFactory. During a regular request it is otherwise
137 * fine to load the plugins in the order of `sortPlugins()` since we will make sure that required plugins will be
138 * loaded first in plugin manager.
139 *
140 * @param string[] $plugins
141 * @param array[] $pluginJsonCache For internal testing only
142 * @return \string[]
143 */
144 public function sortPluginsAndRespectDependencies(array $plugins, $pluginJsonCache = array())
145 {
146 $global = $this->getPluginsBundledWithPiwik();
147
148 if (empty($global)) {
149 return $plugins;
150 }
151
152 // we need to make sure a possibly disabled plugin will be still loaded before any 3rd party plugin
153 $global = array_merge($global, $this->corePluginsDisabledByDefault);
154
155 $global = array_values($global);
156 $plugins = array_values($plugins);
157
158 $defaultPluginsLoadedFirst = array_intersect($global, $plugins);
159
160 $otherPluginsToLoadAfterDefaultPlugins = array_diff($plugins, $defaultPluginsLoadedFirst);
161
162 // we still want to sort alphabetically by default
163 natcasesort($otherPluginsToLoadAfterDefaultPlugins);
164
165 $sorted = array();
166 foreach ($otherPluginsToLoadAfterDefaultPlugins as $pluginName) {
167 $sorted = $this->sortRequiredPlugin($pluginName, $pluginJsonCache, $otherPluginsToLoadAfterDefaultPlugins, $sorted);
168 }
169
170 $sorted = array_merge($defaultPluginsLoadedFirst, $sorted);
171
172 return $sorted;
173 }
174
175 private function sortRequiredPlugin($pluginName, &$pluginJsonCache, $toBeSorted, $sorted)
176 {
177 if (!isset($pluginJsonCache[$pluginName])) {
178 $loader = new MetadataLoader($pluginName);
179 $pluginJsonCache[$pluginName] = $loader->loadPluginInfoJson();
180 }
181
182 if (!empty($pluginJsonCache[$pluginName]['require'])) {
183 $dependencies = $pluginJsonCache[$pluginName]['require'];
184 foreach ($dependencies as $possiblePluginName => $key) {
185 if (in_array($possiblePluginName, $toBeSorted, true) && !in_array($possiblePluginName, $sorted, true)) {
186 $sorted = $this->sortRequiredPlugin($possiblePluginName, $pluginJsonCache, $toBeSorted, $sorted);
187 }
188 }
189 }
190
191 if (!in_array($pluginName, $sorted, true)) {
192 $sorted[] = $pluginName;
193 }
194
195 return $sorted;
196 }
197 }
198