1 <?php
  2 
  3 /**
  4  * Class for addons.
  5  *
  6  * @author gharlan
  7  *
  8  * @package redaxo\core\packages
  9  */
 10 class rex_addon extends rex_package implements rex_addon_interface
 11 {
 12     /**
 13      * Array of all addons.
 14      *
 15      * @var rex_addon[]
 16      */
 17     private static $addons = [];
 18 
 19     /**
 20      * Array of all child plugins.
 21      *
 22      * @var rex_plugin[]
 23      */
 24     private $plugins = [];
 25 
 26     /**
 27      * Returns the addon by the given name.
 28      *
 29      * @param string $addon Name of the addon
 30      *
 31      * @throws InvalidArgumentException
 32      *
 33      * @return self
 34      */
 35     public static function get($addon)
 36     {
 37         if (!is_string($addon)) {
 38             throw new InvalidArgumentException('Expecting $addon to be string, but ' . gettype($addon) . ' given!');
 39         }
 40         if (!isset(self::$addons[$addon])) {
 41             return rex_null_addon::getInstance();
 42         }
 43         return self::$addons[$addon];
 44     }
 45 
 46     /**
 47      * Returns if the addon exists.
 48      *
 49      * @param string $addon Name of the addon
 50      *
 51      * @return bool
 52      */
 53     public static function exists($addon)
 54     {
 55         return is_string($addon) && isset(self::$addons[$addon]);
 56     }
 57 
 58     /**
 59      * {@inheritdoc}
 60      */
 61     public function getAddon()
 62     {
 63         return $this;
 64     }
 65 
 66     /**
 67      * {@inheritdoc}
 68      */
 69     public function getPackageId()
 70     {
 71         return $this->getName();
 72     }
 73 
 74     /**
 75      * {@inheritdoc}
 76      */
 77     public function getType()
 78     {
 79         return 'addon';
 80     }
 81 
 82     /**
 83      * {@inheritdoc}
 84      */
 85     public function getPath($file = '')
 86     {
 87         return rex_path::addon($this->getName(), $file);
 88     }
 89 
 90     /**
 91      * {@inheritdoc}
 92      */
 93     public function getAssetsPath($file = '')
 94     {
 95         return rex_path::addonAssets($this->getName(), $file);
 96     }
 97 
 98     /**
 99      * {@inheritdoc}
100      */
101     public function getAssetsUrl($file = '')
102     {
103         return rex_url::addonAssets($this->getName(), $file);
104     }
105 
106     /**
107      * {@inheritdoc}
108      */
109     public function getDataPath($file = '')
110     {
111         return rex_path::addonData($this->getName(), $file);
112     }
113 
114     /**
115      * {@inheritdoc}
116      */
117     public function getCachePath($file = '')
118     {
119         return rex_path::addonCache($this->getName(), $file);
120     }
121 
122     /**
123      * {@inheritdoc}
124      */
125     public function isSystemPackage()
126     {
127         return in_array($this->getPackageId(), rex::getProperty('system_addons'));
128     }
129 
130     /**
131      * {@inheritdoc}
132      */
133     public function i18n($key)
134     {
135         $args = func_get_args();
136         $key = $this->getName() . '_' . $key;
137         if (rex_i18n::hasMsgOrFallback($key)) {
138             $args[0] = $key;
139         }
140         return call_user_func_array('rex_i18n::msg', $args);
141     }
142 
143     /**
144      * {@inheritdoc}
145      */
146     public function getPlugin($plugin)
147     {
148         if (!is_string($plugin)) {
149             throw new InvalidArgumentException('Expecting $plugin to be string, but ' . gettype($plugin) . ' given!');
150         }
151         if (!isset($this->plugins[$plugin])) {
152             return rex_null_plugin::getInstance();
153         }
154         return $this->plugins[$plugin];
155     }
156 
157     /**
158      * {@inheritdoc}
159      */
160     public function pluginExists($plugin)
161     {
162         return is_string($plugin) && isset($this->plugins[$plugin]);
163     }
164 
165     /**
166      * {@inheritdoc}
167      */
168     public function getRegisteredPlugins()
169     {
170         return $this->plugins;
171     }
172 
173     /**
174      * {@inheritdoc}
175      */
176     public function getInstalledPlugins()
177     {
178         return self::filterPackages($this->plugins, 'isInstalled');
179     }
180 
181     /**
182      * {@inheritdoc}
183      */
184     public function getAvailablePlugins()
185     {
186         return self::filterPackages($this->plugins, 'isAvailable');
187     }
188 
189     /**
190      * {@inheritdoc}
191      */
192     public function getSystemPlugins()
193     {
194         if (rex::isSetup() || rex::isSafeMode()) {
195             // in setup and safemode this method is called before the package .lang files are added to rex_i18n
196             // so don't use getProperty(), to avoid loading all properties without translations
197             $properties = rex_file::getConfig($this->getPath(parent::FILE_PACKAGE));
198             $systemPlugins = isset($properties['system_plugins']) ? (array) $properties['system_plugins'] : [];
199         } else {
200             $systemPlugins = (array) $this->getProperty('system_plugins', []);
201         }
202         $plugins = [];
203         foreach ($systemPlugins as $plugin) {
204             if ($this->pluginExists($plugin)) {
205                 $plugins[$plugin] = $this->getPlugin($plugin);
206             }
207         }
208         return $plugins;
209     }
210 
211     /**
212      * Returns the registered addons.
213      *
214      * @return self[]
215      */
216     public static function getRegisteredAddons()
217     {
218         return self::$addons;
219     }
220 
221     /**
222      * Returns the installed addons.
223      *
224      * @return self[]
225      */
226     public static function getInstalledAddons()
227     {
228         return self::filterPackages(self::$addons, 'isInstalled');
229     }
230 
231     /**
232      * Returns the available addons.
233      *
234      * @return self[]
235      */
236     public static function getAvailableAddons()
237     {
238         return self::filterPackages(self::$addons, 'isAvailable');
239     }
240 
241     /**
242      * Returns the setup addons.
243      *
244      * @return self[]
245      */
246     public static function getSetupAddons()
247     {
248         $addons = [];
249         foreach ((array) rex::getProperty('setup_addons', []) as $addon) {
250             if (self::exists($addon)) {
251                 $addons[$addon] = self::get($addon);
252             }
253         }
254         return $addons;
255     }
256 
257     /**
258      * Returns the system addons.
259      *
260      * @return self[]
261      */
262     public static function getSystemAddons()
263     {
264         $addons = [];
265         foreach ((array) rex::getProperty('system_addons', []) as $addon) {
266             if (self::exists($addon)) {
267                 $addons[$addon] = self::get($addon);
268             }
269         }
270         return $addons;
271     }
272 
273     /**
274      * Initializes all packages.
275      */
276     public static function initialize($dbExists = true)
277     {
278         if ($dbExists) {
279             $config = rex::getConfig('package-config', []);
280         } else {
281             $config = [];
282             foreach (rex::getProperty('setup_addons') as $addon) {
283                 $config[$addon]['install'] = false;
284             }
285         }
286         $addons = self::$addons;
287         self::$addons = [];
288         foreach ($config as $addonName => $addonConfig) {
289             $addon = isset($addons[$addonName]) ? $addons[$addonName] : new self($addonName);
290             $addon->setProperty('install', isset($addonConfig['install']) ? $addonConfig['install'] : false);
291             $addon->setProperty('status', isset($addonConfig['status']) ? $addonConfig['status'] : false);
292             self::$addons[$addonName] = $addon;
293             if (!$dbExists && is_array($plugins = $addon->getProperty('system_plugins'))) {
294                 foreach ($plugins as $plugin) {
295                     $config[$addonName]['plugins'][$plugin]['install'] = false;
296                 }
297             }
298             if (isset($config[$addonName]['plugins']) && is_array($config[$addonName]['plugins'])) {
299                 $plugins = $addon->plugins;
300                 $addon->plugins = [];
301                 foreach ($config[$addonName]['plugins'] as $pluginName => $pluginConfig) {
302                     $plugin = isset($plugins[$pluginName]) ? $plugins[$pluginName] : new rex_plugin($pluginName, $addon);
303                     $plugin->setProperty('install', isset($pluginConfig['install']) ? $pluginConfig['install'] : false);
304                     $plugin->setProperty('status', isset($pluginConfig['status']) ? $pluginConfig['status'] : false);
305                     $addon->plugins[$pluginName] = $plugin;
306                 }
307             }
308         }
309     }
310 
311     /**
312      * Filters packages by the given method.
313      *
314      * @param array  $packages Array of packages
315      * @param string $method   A rex_package method
316      *
317      * @return rex_package[]
318      */
319     private static function filterPackages(array $packages, $method)
320     {
321         return array_filter($packages, function (rex_package $package) use ($method) {
322             return $package->$method();
323         });
324     }
325 }
326