Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
common_ext_ExtensionsManager
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 16
1722
0.00% covered (danger)
0.00%
0 / 1
 singleton
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getInstalledExtensionsIds
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getInstalledExtensions
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 loadExtensions
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
30
 getAvailableExtensions
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
72
 getModelsToLoad
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 getExtensionById
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 isEnabled
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 isInstalled
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getInstalledVersion
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 setEnabled
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 getEnabledExtensions
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 registerExtension
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 unregisterExtension
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 updateVersion
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getAvailablePackages
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2008-2010 (original work) Deutsche Institut für Internationale Pädagogische Forschung
19 *                         (under the project TAO-TRANSFER);
20 *               2009-2012 (update and modification) Public Research Centre Henri Tudor
21 *                         (under the project TAO-SUSTAIN & TAO-DEV);
22 *
23 */
24
25use oat\oatbox\service\ConfigurableService;
26use oat\oatbox\service\ServiceManager;
27use oat\oatbox\extension\exception\ManifestException;
28use oat\oatbox\extension\ComposerInfo;
29use oat\oatbox\cache\SimpleCache;
30
31/**
32 * The ExtensionsManager class is dedicated to Extensions Management. It provides
33 * methods to know if an extension is enabled/disabled, obtain the list of currently
34 * available/installed extensions, the models that have to be loaded to run the extensions,
35 * obtain a reference on a particular test case.
36 *
37 * @access public
38 * @authorlionel@taotesting.com
39 * @package generis
40 * @see @license  GNU General Public (GPL) Version 2 http://www.opensource.org/licenses/gpl-2.0.php
41 */
42class common_ext_ExtensionsManager extends ConfigurableService
43{
44    public const EXTENSIONS_CONFIG_KEY = 'installation';
45
46    public const SERVICE_ID = 'generis/extensionManager';
47
48    public static $RESERVED_WORDS = [
49        'config', 'data', 'vendor', 'tests'
50    ];
51
52    /**
53     * The extensions currently loaded. The array contains
54     * references on common_ext_Extension class instances.
55     *
56     * @access private
57     * @var array
58     */
59    private $extensions = [];
60
61    /**
62     * @deprecated Use ServiceManager::get(\common_ext_ExtensionsManager::SERVICE_ID) instead
63     *
64     * Obtain a reference on a unique common_ext_ExtensionsManager
65     * class instance.
66     *
67     * @access public
68     * @author Joel Bout, <joel@taotesting.com>
69     * @return common_ext_ExtensionsManager
70     */
71    public static function singleton()
72    {
73        return ServiceManager::getServiceManager()->get(self::class);
74    }
75
76    /**
77     * Get list of ids of installed extensions
78     * @return mixed
79     */
80    public function getInstalledExtensionsIds()
81    {
82        $installData = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
83        return is_array($installData) ? array_keys($installData) : [];
84    }
85
86    /**
87     * Get the set of currently installed extensions. This method
88     * returns an array of common_ext_Extension.
89     *
90     * @access public
91     * @author Joel Bout, <joel@taotesting.com>
92     * @return array
93     */
94    public function getInstalledExtensions()
95    {
96        $returnValue = [];
97        foreach ($this->getInstalledExtensionsIds() as $extId) {
98            $returnValue[$extId] = $this->getExtensionById($extId);
99        }
100        return $returnValue;
101    }
102
103    /**
104     * Load all extensions that have to be loaded
105     *
106     * @access public
107     * @author Joel Bout, <joel@taotesting.com>
108     */
109    public function loadExtensions()
110    {
111        foreach ($this->extensions as $extension) {
112            //handle dependances requirement
113            foreach ($extension->getManifest()->getDependencies() as $ext => $version) {
114                if (!array_key_exists($ext, $this->extensions) && $ext != 'generis') {
115                    throw new common_ext_ExtensionException('Required Extension is Missing : ' . $ext);
116                }
117            }
118            $extension->load();
119        }
120    }
121
122    /**
123     * Call a service to retrieve list of extensions that may be installed.
124     * This method returns an array of common_ext_Extension.
125     *
126     * @access public
127     * @author Joel Bout, <joel@taotesting.com>
128     * @return array
129     */
130    public function getAvailableExtensions()
131    {
132        $returnValue = [];
133        $dir = new DirectoryIterator(ROOT_PATH);
134        foreach ($dir as $fileinfo) {
135            if ($fileinfo->isDir() && !$fileinfo->isDot() && substr($fileinfo->getBasename(), 0, 1) != '.') {
136                $extId = $fileinfo->getBasename();
137                if (!in_array($extId, self::$RESERVED_WORDS) && !$this->isInstalled($extId)) {
138                    try {
139                        $ext = $this->getExtensionById($extId);
140                        $returnValue[] = $ext;
141                    } catch (common_ext_ExtensionException $exception) {
142                        common_Logger::d(sprintf('%s  is not an extension (%s)', $extId, $exception->getMessage()));
143                    }
144                }
145            }
146        }
147
148        return $returnValue;
149    }
150
151    /**
152     * Short description of method getModelsToLoad
153     *
154     * @access public
155     * @author Joel Bout, <joel@taotesting.com>
156     * @return array
157     */
158    public function getModelsToLoad()
159    {
160        $returnValue = [];
161
162        foreach ($this->getEnabledExtensions() as $ext) {
163            $returnValue = array_merge($returnValue, $ext->getManifest()->getModels());
164        }
165        $returnValue = array_unique($returnValue);
166
167        return (array) $returnValue;
168    }
169
170    /**
171     * Get an extension by Id. If the extension is not yet loaded, it will be
172     * loaded using common_ext_Extension::load.
173     *
174     * @access public
175     * @author Joel Bout, <joel@taotesting.com>
176     * @param  string $id The id of the extension.
177     * @return common_ext_Extension A common_ext_Extension instance or null if it does not exist.
178     * @throws common_ext_ExtensionException If the provided id is empty.
179     */
180    public function getExtensionById($id)
181    {
182        if (! is_string($id) || strlen($id) == 0) {
183            throw new common_ext_ExtensionException('No id specified for getExtensionById()');
184        }
185        if (! isset($this->extensions[$id])) {
186            $extension = new common_ext_Extension($id);
187            $this->propagate($extension);
188
189            // loads the extension if it hasn't been loaded yet
190            $extension->load();
191            // if successfully loaded add to list
192            $this->extensions[$id] = $extension;
193        }
194
195        return $this->extensions[$id];
196    }
197
198    public function isEnabled($extensionId)
199    {
200        $exts = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
201        return isset($exts[$extensionId]['enabled']) ? $exts[$extensionId]['enabled'] : false;
202    }
203
204    public function isInstalled($extensionId)
205    {
206        $exts = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
207        return isset($exts[$extensionId]);
208    }
209
210    public function getInstalledVersion($extensionId)
211    {
212        $exts = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
213        return isset($exts[$extensionId]) ? $exts[$extensionId]['installed'] : null;
214    }
215
216    public function setEnabled($extensionId, $enabled = true)
217    {
218        $exts = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
219        if (!isset($exts[$extensionId])) {
220            throw new common_exception_Error('Extension ' . $extensionId . ' unkown, cannot enable/disable');
221        }
222        $exts[$extensionId]['enabled'] = (bool) $enabled;
223        return $this->getExtensionById('generis')->setConfig(self::EXTENSIONS_CONFIG_KEY, $exts);
224    }
225
226    /**
227     * Get the set of currently enabled extensions. This method
228     * returns an array of common_ext_Extension.
229     *
230     * @access public
231     * @author Joel Bout, <joel@taotesting.com>
232     * @return array
233     */
234    public function getEnabledExtensions()
235    {
236        $returnValue = [];
237
238        $enabled = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
239        foreach ($this->getInstalledExtensions() as $ext) {
240            if (isset($enabled[$ext->getId()]) && $enabled[$ext->getId()]['enabled']) {
241                $returnValue[$ext->getId()] = $ext;
242            }
243        }
244
245        return (array) $returnValue;
246    }
247
248    /**
249     * Add the end of an installation register the new extension
250     *
251     * @access public
252     * @author Joel Bout, <joel@taotesting.com>
253     * @param common_ext_Extension $extension
254     * @return boolean
255     */
256    public function registerExtension(common_ext_Extension $extension)
257    {
258        $entry = [
259            'installed' => $extension->getManifest()->getVersion(),
260            'enabled' => false
261        ];
262        $extensions = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
263        $extensions[$extension->getId()] = $entry;
264        return $this->getExtensionById('generis')->setConfig(self::EXTENSIONS_CONFIG_KEY, $extensions);
265    }
266
267    /**
268     * Add the end of an uninstallation unregister the extension
269     *
270     * @access public
271     * @author Joel Bout, <joel@taotesting.com>
272     * @param common_ext_Extension $extension
273     * @return boolean
274     */
275    public function unregisterExtension(common_ext_Extension $extension)
276    {
277        $extensions = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
278        unset($extensions[$extension->getId()]);
279        $this->getExtensionById('generis')->setConfig(self::EXTENSIONS_CONFIG_KEY, $extensions);
280    }
281
282    public function updateVersion(common_ext_Extension $extension, $version)
283    {
284        $extensions = $this->getExtensionById('generis')->getConfig(self::EXTENSIONS_CONFIG_KEY);
285        $extensions[$extension->getId()]['installed'] = $version;
286        $this->getExtensionById('generis')->setConfig(self::EXTENSIONS_CONFIG_KEY, $extensions);
287    }
288
289    /**
290     * Call a service to retrieve a map array of all available extensions
291     * with extension package id as a key and extension id as a value
292     * @return array
293     */
294    public function getAvailablePackages()
295    {
296        $composer = new ComposerInfo();
297        //During installation list of packages is needed but cache service is not installed yet.
298        if (!$this->getServiceManager()->has(SimpleCache::SERVICE_ID)) {
299            return $composer->getAvailableTaoExtensions();
300        }
301        /** @var SimpleCache $cache */
302        $cache = $this->getServiceManager()->get(SimpleCache::SERVICE_ID);
303        $key = static::class . '_' . __METHOD__;
304        if (!$cache->has($key)) {
305            $cache->set($key, $composer->getAvailableTaoExtensions());
306        }
307
308        return (array) $cache->get($key);
309    }
310}