diff --git a/phpBB/adm/style/acp_storage.html b/phpBB/adm/style/acp_storage.html index bb9940554b..63f52a276e 100644 --- a/phpBB/adm/style/acp_storage.html +++ b/phpBB/adm/style/acp_storage.html @@ -61,34 +61,23 @@
{{ lang('STORAGE_' ~ storage.get_name | upper ~ '_TITLE') }} - {{ lang('STORAGE_ADAPTER_' ~ provider.get_name | upper ~ '_NAME') }} {% for name, options in provider.get_options %} - {% set title = 'STORAGE_ADAPTER_' ~ provider.get_name | upper ~ '_OPTION_' ~ name | upper %} - {% set description = 'STORAGE_ADAPTER_' ~ provider.get_name | upper ~ '_OPTION_' ~ name | upper ~ '_EXPLAIN' %} - {% set input_id = storage.get_name ~ '_' ~ provider.get_name ~ '_' ~ name %} - {% set input_type = options['type'] %} - {% set input_name = storage.get_name ~ '[' ~ name ~ ']' %} - {% set input_value = attribute(config, 'storage\\' ~ storage.get_name ~ '\\config\\' ~ name) %}
- + {% set title = 'STORAGE_ADAPTER_' ~ provider.get_name | upper ~ '_OPTION_' ~ name | upper %} + {% set description = 'STORAGE_ADAPTER_' ~ provider.get_name | upper ~ '_OPTION_' ~ name | upper ~ '_EXPLAIN' %} + {% if lang_defined(description) %}
{{ lang(description) }} {% endif %}
- {% if input_type in ['text', 'password', 'email'] %} - - {% elseif input_type == 'textarea' %} - - {% elseif input_type == 'radio' %} - {% for option_name, option_value in options['options'] %} - {{ lang(option_name) }} - {% endfor %} - {% elseif input_type == 'select' %} - + {% set input_name = storage.get_name ~ '[' ~ name ~ ']' %} + {% set input_value = attribute(config, 'storage\\' ~ storage.get_name ~ '\\config\\' ~ name) %} + + {% if options['type'] in ['text', 'password', 'email'] %} + {{ FormsBuildTemplate(options | merge({"name": input_name, "value": input_value})) }} + {% elseif options['type'] == 'textarea' %} + {{ FormsBuildTemplate(options | merge({"name": input_name, "content": input_value})) }} {% endif %}
diff --git a/phpBB/adm/style/acp_storage_update_inprogress.html b/phpBB/adm/style/acp_storage_update_inprogress.html index 9c4b9fd804..5f7614cb2c 100644 --- a/phpBB/adm/style/acp_storage_update_inprogress.html +++ b/phpBB/adm/style/acp_storage_update_inprogress.html @@ -4,27 +4,27 @@

{{ lang('STORAGE_TITLE') }}

- +

{{ lang('STORAGE_TITLE_EXPLAIN') }}

-

{{ lang('CONTINUE_EXPLAIN') }}

- -
-
+ +
{{ lang('SUBMIT') }} -   - + + {% if CONTINUE_PROGRESS %} +
+
+
+ {{ CONTINUE_PROGRESS.PERCENTAGE|number_format(2) ~ ' %' }} +
+ {% endif %} + +

+   + +

{{ S_FORM_TOKEN }}
diff --git a/phpBB/adm/style/acp_storage_update_progress.html b/phpBB/adm/style/acp_storage_update_progress.html new file mode 100644 index 0000000000..17ba67a037 --- /dev/null +++ b/phpBB/adm/style/acp_storage_update_progress.html @@ -0,0 +1,20 @@ +{% include 'overall_header.html' %} + + + +
+

{{ INDEXING_TITLE }}

+

+ {{ INDEXING_EXPLAIN }} + {% if INDEXING_PROGRESS_BAR %} +
+
+ {{ INDEXING_PROGRESS_BAR.PERCENTAGE|number_format(2) ~ ' %' }} + {% endif %} +

+
+ +{% include 'overall_footer.html' %} diff --git a/phpBB/includes/acp/acp_storage.php b/phpBB/includes/acp/acp_storage.php index 2e28ef9a50..e11a778278 100644 --- a/phpBB/includes/acp/acp_storage.php +++ b/phpBB/includes/acp/acp_storage.php @@ -16,6 +16,7 @@ use phpbb\di\service_collection; use phpbb\language\language; use phpbb\log\log_interface; use phpbb\request\request; +use phpbb\storage\exception\storage_exception; use phpbb\storage\helper; use phpbb\storage\state_helper; use phpbb\storage\update_type; @@ -77,6 +78,9 @@ class acp_storage /** @var helper */ private $storage_helper; + /** @var string */ + private $storage_table; + /** * @param string $id * @param string $mode @@ -97,6 +101,7 @@ class acp_storage $this->phpbb_root_path = $phpbb_root_path; $this->state_helper = $phpbb_container->get('storage.state_helper'); $this->storage_helper = $phpbb_container->get('storage.helper'); + $this->storage_table = $phpbb_container->getParameter('tables.storage'); // Add necessary language files $this->lang->add_lang(['acp/storage']); @@ -128,10 +133,6 @@ class acp_storage { switch ($action) { - case 'progress_bar': - $this->display_progress_bar(); - break; - case 'update': $this->update_action(); break; @@ -151,7 +152,7 @@ class acp_storage // There is an updating in progress, show the form to continue or cancel if ($this->state_helper->is_action_in_progress()) { - $this->update_inprogress($id, $mode); + $this->update_inprogress(); } else { @@ -162,8 +163,6 @@ class acp_storage private function update_action(): void { - // Probably it has sense to disable the forum while this is in progress - if (!check_link_hash($this->request->variable('hash', ''), 'acp_storage')) { trigger_error($this->lang->lang('FORM_INVALID') . adm_back_link($this->u_action), E_USER_WARNING); @@ -182,7 +181,7 @@ class acp_storage } $sql = 'SELECT file_id, file_path - FROM ' . STORAGE_TABLE . " + FROM ' . $this->storage_table . " WHERE storage = '" . $this->db->sql_escape($storage_name) . "' AND file_id > " . $this->state_helper->file_index(); $result = $this->db->sql_query($sql); @@ -192,9 +191,8 @@ class acp_storage if (!still_on_time()) { $this->db->sql_freeresult($result); - meta_refresh(1, append_sid($this->u_action . '&action=update&hash=' . generate_link_hash('acp_storage'))); - // Here could be included the current file compared with the number of total files too - trigger_error($this->lang->lang('STORAGE_UPDATE_REDIRECT', $this->lang->lang('STORAGE_' . strtoupper($storage_name) . '_TITLE'), $i + 1, count($this->state_helper->storages()))); + $this->display_progress_page(); + return; } // Copy file from old adapter to the new one @@ -223,7 +221,7 @@ class acp_storage } $sql = 'SELECT file_id, file_path - FROM ' . STORAGE_TABLE . " + FROM ' . $this->storage_table . " WHERE storage = '" . $this->db->sql_escape($storage_name) . "' AND file_id > " . $this->state_helper->file_index(); $result = $this->db->sql_query($sql); @@ -233,8 +231,8 @@ class acp_storage if (!still_on_time()) { $this->db->sql_freeresult($result); - meta_refresh(1, append_sid($this->u_action . '&action=update&hash=' . generate_link_hash('acp_storage'))); - trigger_error($this->lang->lang('STORAGE_UPDATE_REMOVE_REDIRECT', $this->lang->lang('STORAGE_' . strtoupper($storage_name) . '_TITLE'), $i + 1, count($this->state_helper->storages()))); + $this->display_progress_page(); + return; } // remove file from old (current) adapter @@ -262,10 +260,10 @@ class acp_storage $storages = $this->state_helper->storages(); $this->state_helper->clear_state(); $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_STORAGE_UPDATE', false, [implode(', ', $storages)]); - trigger_error($this->lang->lang('STORAGE_UPDATE_SUCCESSFUL') . adm_back_link($this->u_action) . $this->close_popup_js()); + trigger_error($this->lang->lang('STORAGE_UPDATE_SUCCESSFUL') . adm_back_link($this->u_action)); } - private function update_inprogress(string $id, string $mode): void + private function update_inprogress(): void { // Template from adm/style $this->tpl_name = 'acp_storage_update_inprogress'; @@ -274,10 +272,8 @@ class acp_storage $this->page_title = 'STORAGE_TITLE'; $this->template->assign_vars(array( - 'UA_PROGRESS_BAR' => addslashes(append_sid($this->u_action, "action=progress_bar")), - 'U_CONTINUE_UPDATING' => $this->u_action . '&action=update&hash=' . generate_link_hash('acp_storage'), - 'L_CONTINUE' => $this->lang->lang('CONTINUE_UPDATING'), - 'L_CONTINUE_EXPLAIN' => $this->lang->lang('CONTINUE_UPDATING_EXPLAIN'), + 'U_ACTION' => $this->u_action . '&action=update&hash=' . generate_link_hash('acp_storage'), + 'CONTINUE_PROGRESS' => $this->get_storage_update_progress(), )); } @@ -308,27 +304,14 @@ class acp_storage trigger_error(implode('
', $messages) . adm_back_link($this->u_action), E_USER_WARNING); } - // Start process and show form + // Start process and show progress if (!empty($modified_storages)) { // Create state $this->state_helper->init(update_type::from((int) $this->request->variable('update_type', update_type::CONFIG->value)), $modified_storages, $this->request); - // Show the confirmation form to start the process - $this->template->assign_vars(array( - 'UA_PROGRESS_BAR' => addslashes(append_sid($this->u_action, "action=progress_bar")), - 'S_CONTINUE_UPDATING' => true, - 'U_CONTINUE_UPDATING' => $this->u_action . '&action=update&hash=' . generate_link_hash('acp_storage'), - 'L_CONTINUE' => $this->lang->lang('START_UPDATING'), - 'L_CONTINUE_EXPLAIN' => $this->lang->lang('START_UPDATING_EXPLAIN'), - )); - - // Template from adm/style - $this->tpl_name = 'acp_storage_update_inprogress'; - - // Set page title - $this->page_title = 'STORAGE_TITLE'; - + // Start displaying progress on first submit + $this->display_progress_page(); return; } @@ -413,7 +396,7 @@ class acp_storage { $free_space = get_formatted_filesize($storage->free_space()); } - catch (\phpbb\storage\exception\storage_exception $e) + catch (storage_exception $e) { $free_space = $this->lang->lang('STORAGE_UNKNOWN'); } @@ -432,33 +415,60 @@ class acp_storage } /** - * Display progress bar + * Display progress page */ - protected function display_progress_bar() : void + protected function display_progress_page() : void { + $u_action = append_sid($this->u_action . '&action=update&hash=' . generate_link_hash('acp_storage')); + meta_refresh(1, $u_action); + adm_page_header($this->lang->lang('STORAGE_UPDATE_IN_PROGRESS')); - $this->template->set_filenames(array( - 'body' => 'progress_bar.html') - ); - $this->template->assign_vars(array( - 'L_PROGRESS' => $this->lang->lang('STORAGE_UPDATE_IN_PROGRESS'), - 'L_PROGRESS_EXPLAIN' => $this->lang->lang('STORAGE_UPDATE_IN_PROGRESS_EXPLAIN')) - ); + $this->template->set_filenames([ + 'body' => 'acp_storage_update_progress.html' + ]); + + $this->template->assign_vars([ + 'INDEXING_TITLE' => $this->lang->lang('STORAGE_UPDATE_IN_PROGRESS'), + 'INDEXING_EXPLAIN' => $this->lang->lang('STORAGE_UPDATE_IN_PROGRESS_EXPLAIN'), + 'INDEXING_PROGRESS_BAR' => $this->get_storage_update_progress(), + ]); adm_page_footer(); } - /** - * Get JS code for closing popup - * - * @return string Popup JS code - */ - function close_popup_js() : string + protected function get_storage_update_progress(): array { - return "\n"; + $file_index = $this->state_helper->file_index(); + $stage_is_copy = $this->state_helper->storage_index() < count($this->state_helper->storages()); + $storage_name = $this->state_helper->storages()[$stage_is_copy ? $this->state_helper->storage_index() : $this->state_helper->remove_storage_index()]; + + $sql = 'SELECT COUNT(file_id) as done_count + FROM ' . $this->storage_table . ' + WHERE file_id <= ' . $file_index . " + AND storage = '" . $this->db->sql_escape($storage_name) . "'"; + $result = $this->db->sql_query($sql); + $done_count = (int) $this->db->sql_fetchfield('done_count'); + $this->db->sql_freeresult($result); + + $sql = 'SELECT COUNT(file_id) as remain_count + FROM ' . $this->storage_table . " + WHERE file_id > ' . $file_index . ' + AND storage = '" . $this->db->sql_escape($storage_name) . "'"; + $result = $this->db->sql_query($sql); + $remain_count = (int) $this->db->sql_fetchfield('remain_count'); + $this->db->sql_freeresult($result); + + $total_count = $done_count + $remain_count; + $percent = $done_count / $total_count; + + $steps = $this->state_helper->storage_index() + $this->state_helper->remove_storage_index() + $percent; + $multiplier = $this->state_helper->update_type() === update_type::MOVE ? 2 : 1; + $steps_total = count($this->state_helper->storages()) * $multiplier; + + return [ + 'VALUE' => $steps, + 'TOTAL' => $steps_total, + 'PERCENTAGE' => $steps / $steps_total * 100, + ]; } /** diff --git a/phpBB/language/en/acp/storage.php b/phpBB/language/en/acp/storage.php index 2ed3a1b2a5..9f928ee58e 100644 --- a/phpBB/language/en/acp/storage.php +++ b/phpBB/language/en/acp/storage.php @@ -36,7 +36,7 @@ if (empty($lang) || !is_array($lang)) // equally where a string contains only two placeholders which are used to wrap text // in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine -$lang = array_merge($lang, array( +$lang = array_merge($lang, [ // Template 'STORAGE_TITLE' => 'Storage Settings', @@ -52,12 +52,6 @@ $lang = array_merge($lang, array( 'STORAGE_UPDATE_TYPE_CONFIG' => 'Update configuration only', 'STORAGE_UPDATE_TYPE_COPY' => 'Update configuration and copy files', 'STORAGE_UPDATE_TYPE_MOVE' => 'Update configuration and move files', - 'START_UPDATING' => 'Start update process', - 'START_UPDATING_EXPLAIN' => 'Start the storage update process', - 'CONTINUE_UPDATING' => 'Continue previous update process', - 'CONTINUE_UPDATING_EXPLAIN' => 'An update process has been started. In order to access the storage settings page you will have to complete it or cancel it.', - 'STORAGE_UPDATE_REDIRECT' => 'Files of %1$s (%2$d/%3$d) are being moved.
', - 'STORAGE_UPDATE_REMOVE_REDIRECT' => 'Files of old %1$s (%2$d/%3$d) are being removed.
', // Template progress bar 'STORAGE_UPDATE_IN_PROGRESS' => 'Storage update in progress', @@ -83,4 +77,4 @@ $lang = array_merge($lang, array( 'STORAGE_PATH_NOT_EXISTS' => 'ā€œ%1$sā€ path does not exist or is not writable.', 'STORAGE_PATH_NOT_SET' => 'ā€œ%1$sā€ path is not set.', -)); +]); diff --git a/phpBB/phpbb/storage/adapter_factory.php b/phpBB/phpbb/storage/adapter_factory.php index b358328525..62e51f66ae 100644 --- a/phpBB/phpbb/storage/adapter_factory.php +++ b/phpBB/phpbb/storage/adapter_factory.php @@ -15,6 +15,7 @@ namespace phpbb\storage; use phpbb\config\config; use phpbb\di\service_collection; +use phpbb\storage\adapter\adapter_interface; use phpbb\storage\exception\storage_exception; class adapter_factory @@ -53,9 +54,24 @@ class adapter_factory * * @param string $storage_name * - * @return \phpbb\storage\adapter\adapter_interface + * @return adapter_interface */ - public function get($storage_name) + public function get(string $storage_name) + { + $provider_class = $this->config['storage\\' . $storage_name . '\\provider']; + $provider = $this->providers->get_by_class($provider_class); + + $options = []; + foreach (array_keys($provider->get_options()) as $definition) + { + /** @psalm-suppress InvalidArrayOffset */ + $options[$definition] = $this->config['storage\\' . $storage_name . '\\config\\' . $definition]; + } + + return $this->get_with_options($storage_name, $options); + } + + public function get_with_options(string $storage_name, array $options) { $provider_class = $this->config['storage\\' . $storage_name . '\\provider']; $provider = $this->providers->get_by_class($provider_class); @@ -66,28 +82,8 @@ class adapter_factory } $adapter = $this->adapters->get_by_class($provider->get_adapter_class()); - $adapter->configure($this->build_options($storage_name, $provider->get_options())); + $adapter->configure($options); return $adapter; } - - /** - * Obtains configuration for a given storage - * - * @param string $storage_name - * @param array $definitions - * - * @return array Returns storage configuration values - */ - public function build_options($storage_name, array $definitions) - { - $options = []; - - foreach (array_keys($definitions) as $definition) - { - $options[$definition] = $this->config['storage\\' . $storage_name . '\\config\\' . $definition]; - } - - return $options; - } } diff --git a/phpBB/phpbb/storage/helper.php b/phpBB/phpbb/storage/helper.php index 6a5e2cc28c..de75ab337c 100644 --- a/phpBB/phpbb/storage/helper.php +++ b/phpBB/phpbb/storage/helper.php @@ -45,12 +45,12 @@ class helper /** * Get adapter definitions from a provider * - * @param string $provider Provider class + * @param string $provider_class Provider class * @return array Adapter definitions */ - public function get_provider_options(string $provider) : array + public function get_provider_options(string $provider_class) : array { - return $this->provider_collection->get_by_class($provider)->get_options(); + return $this->provider_collection->get_by_class($provider_class)->get_options(); } /** @@ -108,21 +108,16 @@ class helper if (!isset($adapters[$storage_name])) { - $provider = $this->state_helper->new_provider($storage_name); - $provider_class = $this->provider_collection->get_by_class($provider); - - $adapter = $this->adapter_collection->get_by_class($provider_class->get_adapter_class()); - $definitions = $this->get_provider_options($provider); + $provider_class = $this->state_helper->new_provider($storage_name); + $definitions = array_keys($this->get_provider_options($provider_class)); $options = []; - foreach (array_keys($definitions) as $definition) + foreach ($definitions as $definition) { $options[$definition] = $this->state_helper->new_definition_value($storage_name, $definition); } - $adapter->configure($options); - - $adapters[$storage_name] = $adapter; + $adapters[$storage_name] = $this->adapter_factory->get_with_options($storage_name, $options); } return $adapters[$storage_name]; diff --git a/phpBB/phpbb/storage/provider/local.php b/phpBB/phpbb/storage/provider/local.php index 3bec0c5ce5..c6338e0c31 100644 --- a/phpBB/phpbb/storage/provider/local.php +++ b/phpBB/phpbb/storage/provider/local.php @@ -37,7 +37,10 @@ class local implements provider_interface public function get_options() { return [ - 'path' => ['type' => 'text'], + 'path' => [ + 'tag' => 'input', + 'type' => 'text', + ], ]; } diff --git a/phpBB/phpbb/storage/state_helper.php b/phpBB/phpbb/storage/state_helper.php index cc9de6dff3..aa48c3377c 100644 --- a/phpBB/phpbb/storage/state_helper.php +++ b/phpBB/phpbb/storage/state_helper.php @@ -163,6 +163,7 @@ class state_helper foreach (array_keys($options) as $definition) { + /** @psalm-suppress InvalidArrayOffset */ $state['storages'][$storage_name]['config'][$definition] = $request->variable([$storage_name, $definition], ''); } } diff --git a/phpBB/phpbb/storage/storage.php b/phpBB/phpbb/storage/storage.php index af0c9f0c67..e99d046a54 100644 --- a/phpBB/phpbb/storage/storage.php +++ b/phpBB/phpbb/storage/storage.php @@ -15,6 +15,7 @@ namespace phpbb\storage; use phpbb\cache\driver\driver_interface as cache; use phpbb\db\driver\driver_interface as db; +use phpbb\storage\adapter\adapter_interface; use phpbb\storage\exception\storage_exception; /** @@ -23,7 +24,7 @@ use phpbb\storage\exception\storage_exception; class storage { /** - * @var \phpbb\storage\adapter\adapter_interface + * @var adapter_interface */ protected $adapter; @@ -39,7 +40,7 @@ class storage protected $cache; /** - * @var \phpbb\storage\adapter_factory + * @var adapter_factory */ protected $factory; @@ -58,7 +59,7 @@ class storage * * @param db $db * @param cache $cache - * @param \phpbb\storage\adapter_factory $factory + * @param adapter_factory $factory * @param string $storage_name * @param string $storage_table */ @@ -84,7 +85,7 @@ class storage /** * Returns an adapter instance * - * @return \phpbb\storage\adapter\adapter_interface + * @return adapter_interface */ protected function get_adapter() {