Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
update_extensions
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 5
600
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
6
 run
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
342
 get_step_count
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_task_lang_name
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_extensions
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 *
4 * This file is part of the phpBB Forum Software package.
5 *
6 * @copyright (c) phpBB Limited <https://www.phpbb.com>
7 * @license GNU General Public License, version 2 (GPL-2.0)
8 *
9 * For full copyright and license information, please see
10 * the docs/CREDITS.txt file.
11 *
12 */
13
14namespace phpbb\install\module\update_database\task;
15
16use phpbb\install\exception\resource_limit_reached_exception;
17use phpbb\install\helper\container_factory;
18use phpbb\install\helper\config;
19use phpbb\install\helper\iohandler\iohandler_interface;
20use phpbb\install\helper\update_helper;
21use phpbb\install\task_base;
22use Symfony\Component\Finder\Finder;
23
24/**
25 * Installs extensions that exist in ext folder upon install
26 */
27class update_extensions extends task_base
28{
29    /**
30     * @var \phpbb\cache\driver\driver_interface
31     */
32    protected $cache;
33
34    /**
35     * @var config
36     */
37    protected $install_config;
38
39    /**
40     * @var iohandler_interface
41     */
42    protected $iohandler;
43
44    /** @var update_helper */
45    protected $update_helper;
46
47    /**
48     * @var \phpbb\config\config
49     */
50    protected $config;
51
52    /**
53     * @var \phpbb\log\log_interface
54     */
55    protected $log;
56
57    /**
58     * @var \phpbb\user
59     */
60    protected $user;
61
62    /** @var \phpbb\extension\manager */
63    protected $extension_manager;
64
65    /** @var Finder */
66    protected $finder;
67
68    /** @var string Extension table */
69    protected $extension_table;
70
71    /** @var \phpbb\db\driver\driver_interface */
72    protected $db;
73
74    /**
75     * @var array    List of default extensions to update, grouped by version
76     *                they were added
77     */
78    public static $default_extensions_update = [
79        '3.2.0-RC2' => ['phpbb/viglink']
80    ];
81
82    /**
83     * Constructor
84     *
85     * @param container_factory            $container
86     * @param config                    $install_config
87     * @param iohandler_interface        $iohandler
88     * @param $update_helper            $update_helper
89     * @param string                    $phpbb_root_path phpBB root path
90     */
91    public function __construct(container_factory $container, config $install_config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path)
92    {
93        $this->install_config    = $install_config;
94        $this->iohandler        = $iohandler;
95        $this->extension_table = $container->get_parameter('tables.ext');
96
97        $this->log                = $container->get('log');
98        $this->user                = $container->get('user');
99        $this->extension_manager = $container->get('ext.manager');
100        $this->cache                = $container->get('cache.driver');
101        $this->config            = $container->get('config');
102        $this->db                = $container->get('dbal.conn');
103        $this->update_helper = $update_helper;
104        $this->finder = new Finder();
105        $this->finder->in($phpbb_root_path . 'ext/')
106            ->ignoreUnreadableDirs()
107            ->depth('< 3')
108            ->files()
109            ->name('composer.json');
110
111        // Make sure asset version exists in config. Otherwise we might try to
112        // insert the assets_version setting into the database and cause a
113        // duplicate entry error.
114        if (!$this->config->offsetExists('assets_version'))
115        {
116            $this->config->offsetSet('assets_version', 0);
117        }
118
119        parent::__construct(true);
120    }
121
122    /**
123     * {@inheritdoc}
124     */
125    public function run()
126    {
127        $this->user->session_begin();
128        $this->user->setup(array('common', 'acp/common', 'cli'));
129
130        $update_info = $this->install_config->get('update_info_unprocessed', []);
131        $version_from = !empty($update_info) ? $update_info['version']['from'] : $this->config['version_update_from'];
132
133        if (!empty($version_from))
134        {
135            $update_extensions = $this->iohandler->get_input('update-extensions', []);
136
137            // Create list of default extensions that need to be enabled in update
138            $default_update_extensions = [];
139            foreach (self::$default_extensions_update as $version => $extensions)
140            {
141                if ($this->update_helper->phpbb_version_compare($version_from, $version, '<'))
142                {
143                    $default_update_extensions = array_merge($default_update_extensions, $extensions);
144                }
145            }
146
147            $all_available_extensions = $this->extension_manager->all_available();
148            $i = $this->install_config->get('update_extensions_index', 0);
149            $available_extensions = array_slice($all_available_extensions, $i);
150
151            // Update available extensions
152            foreach ($available_extensions as $ext_name => $ext_path)
153            {
154                // Update extensions if:
155                //    1) Extension is currently enabled
156                //    2) Extension was implicitly defined as needing an update
157                //    3) Extension was newly added as default phpBB extension in
158                //        this update and should be enabled by default.
159                if ($this->extension_manager->is_enabled($ext_name) ||
160                    in_array($ext_name, $update_extensions) ||
161                    in_array($ext_name, $default_update_extensions)
162                )
163                {
164                    try
165                    {
166                        $extension_enabled = $this->extension_manager->is_enabled($ext_name);
167                        if ($extension_enabled)
168                        {
169                            $this->extension_manager->disable($ext_name);
170                        }
171                        $this->extension_manager->enable($ext_name);
172                        $extensions = $this->get_extensions();
173
174                        if (isset($extensions[$ext_name]) && $extensions[$ext_name]['ext_active'])
175                        {
176                            // Create log
177                            $this->log->add('admin', ANONYMOUS, '', 'LOG_EXT_UPDATE', time(), array($ext_name));
178                            $this->iohandler->add_success_message(array('CLI_EXTENSION_UPDATE_SUCCESS', $ext_name));
179                        }
180                        else
181                        {
182                            $this->iohandler->add_log_message('CLI_EXTENSION_UPDATE_FAILURE', array($ext_name));
183                        }
184
185                        // Disable extensions if it was disabled by the admin before
186                        if (!$extension_enabled && !in_array($ext_name, $default_update_extensions))
187                        {
188                            $this->extension_manager->disable($ext_name);
189                        }
190                    }
191                    catch (\Exception $e)
192                    {
193                        // Add fail log and continue
194                        $this->iohandler->add_log_message('CLI_EXTENSION_UPDATE_FAILURE', array($ext_name));
195                    }
196                }
197
198                $i++;
199
200                // Stop execution if resource limit is reached
201                if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0)
202                {
203                    break;
204                }
205            }
206
207            $this->install_config->set('update_extensions_index', $i);
208
209            if ($i < count($all_available_extensions))
210            {
211                throw new resource_limit_reached_exception();
212            }
213        }
214
215        $this->config->delete('version_update_from');
216
217        $this->cache->purge();
218
219        $this->config->increment('assets_version', 1);
220    }
221
222    /**
223     * {@inheritdoc}
224     */
225    public static function get_step_count()
226    {
227        return 1;
228    }
229
230    /**
231     * {@inheritdoc}
232     */
233    public function get_task_lang_name()
234    {
235        return 'TASK_UPDATE_EXTENSIONS';
236    }
237
238    /**
239     * Get extensions from database
240     *
241     * @return array List of extensions
242     */
243    private function get_extensions()
244    {
245        $sql = 'SELECT *
246            FROM ' . $this->extension_table;
247
248        $result = $this->db->sql_query($sql);
249        $extensions_row = $this->db->sql_fetchrowset($result);
250        $this->db->sql_freeresult($result);
251
252        $extensions = array();
253
254        foreach ($extensions_row as $extension)
255        {
256            $extensions[$extension['ext_name']] = $extension;
257        }
258
259        ksort($extensions);
260
261        return $extensions;
262    }
263}