diff --git a/phpBB/adm/style/acp_ext_list.html b/phpBB/adm/style/acp_ext_list.html index c5527c14bc..0b63302eed 100644 --- a/phpBB/adm/style/acp_ext_list.html +++ b/phpBB/adm/style/acp_ext_list.html @@ -60,7 +60,7 @@ {L_DETAILS} - title="{enabled.actions.L_ACTION_EXPLAIN}">{enabled.actions.L_ACTION} + style="color: #bc2a4d;" title="{enabled.actions.L_ACTION_EXPLAIN}">{enabled.actions.L_ACTION}  |  @@ -88,7 +88,7 @@ - title="{disabled.actions.L_ACTION_EXPLAIN}">{disabled.actions.L_ACTION} + style="color: #bc2a4d;" title="{disabled.actions.L_ACTION_EXPLAIN}">{disabled.actions.L_ACTION}  |  diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 5bdb381d1b..de98bfadb1 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -838,10 +838,7 @@ class acp_extensions { $this->output_actions('enabled', [ 'UPDATE' => $this->u_catalog_action . '&action=update&extension=' . urlencode($block_vars['META_NAME']), - 'REMOVE' => [ - 'url' => $this->u_catalog_action . '&action=remove&extension=' . urlencode($block_vars['META_NAME']), - 'color' => '#BC2A4D;', - ] + 'REMOVE' => $this->u_catalog_action . '&action=remove&extension=' . urlencode($block_vars['META_NAME']), ]); } } @@ -922,10 +919,7 @@ class acp_extensions { $this->output_actions('disabled', [ 'UPDATE' => $this->u_catalog_action . '&action=update&extension=' . urlencode($block_vars['META_NAME']), - 'REMOVE' => [ - 'url' => $this->u_catalog_action . '&action=remove&extension=' . urlencode($block_vars['META_NAME']), - 'color' => '#BC2A4D;', - ] + 'REMOVE' => $this->u_catalog_action . '&action=remove&extension=' . urlencode($block_vars['META_NAME']), ]); } } @@ -997,6 +991,7 @@ class acp_extensions $this->output_actions('disabled', array( 'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), + 'REMOVE' => $this->u_catalog_action . '&action=remove&extension=' . urlencode($block_vars['META_NAME']), )); } } @@ -1009,11 +1004,12 @@ class acp_extensions */ private function output_actions($block, $actions) { - foreach ($actions as $lang => $url) + foreach ($actions as $action => $url) { $this->template->assign_block_vars($block . '.actions', [ - 'L_ACTION' => $this->user->lang('EXTENSION_' . $lang), - 'L_ACTION_EXPLAIN' => (isset($this->user->lang['EXTENSION_' . $lang . '_EXPLAIN'])) ? $this->user->lang('EXTENSION_' . $lang . '_EXPLAIN') : '', + 'ACTION' => $action, + 'L_ACTION' => $this->user->lang('EXTENSION_' . $action), + 'L_ACTION_EXPLAIN' => (isset($this->user->lang['EXTENSION_' . $action . '_EXPLAIN'])) ? $this->user->lang('EXTENSION_' . $action . '_EXPLAIN') : '', 'U_ACTION' => $url, ]); } diff --git a/phpBB/phpbb/composer/installer.php b/phpBB/phpbb/composer/installer.php index 9910cb5a08..3e6d87d46f 100644 --- a/phpBB/phpbb/composer/installer.php +++ b/phpBB/phpbb/composer/installer.php @@ -152,7 +152,9 @@ class installer { if (!$io) { + $this->restore_cwd(); $io = new null_io(); + $this->move_to_root(); } $this->generate_ext_json_file($packages); @@ -184,6 +186,7 @@ class installer catch (\Exception $e) { $this->restore_ext_json_file(); + $this->restore_cwd(); throw new runtime_exception('COMPOSER_CANNOT_INSTALL', [], $e); } @@ -191,6 +194,7 @@ class installer if ($result !== 0) { $this->restore_ext_json_file(); + $this->restore_cwd(); throw new runtime_exception($io->get_composer_error(), []); } @@ -587,6 +591,7 @@ class installer $repositories[] = [ 'type' => 'composer', 'url' => $repository, + 'canonical' => $this->packagist ? false : true, ]; } } diff --git a/phpBB/phpbb/composer/manager.php b/phpBB/phpbb/composer/manager.php index d5fe8935cf..e36a32d1e9 100644 --- a/phpBB/phpbb/composer/manager.php +++ b/phpBB/phpbb/composer/manager.php @@ -89,7 +89,7 @@ class manager implements manager_interface $managed_packages = array_merge($this->get_all_managed_packages(), $packages); ksort($managed_packages); - $this->installer->install($managed_packages, array_keys($packages), $io); + $this->installer->install($managed_packages, [], $io); $this->post_install($packages, $io); diff --git a/tests/functional/extension_acp_test.php b/tests/functional/extension_acp_test.php index ab02831209..a4d45506f4 100644 --- a/tests/functional/extension_acp_test.php +++ b/tests/functional/extension_acp_test.php @@ -76,7 +76,7 @@ class phpbb_functional_extension_acp_test extends phpbb_functional_test_case $this->login(); $this->admin_login(); - $this->add_lang('acp/extensions'); + $this->add_lang(['acp/common', 'acp/extensions']); } public function test_list() @@ -254,6 +254,7 @@ class phpbb_functional_extension_acp_test extends phpbb_functional_test_case $form = $crawler->selectButton('Submit')->form(); $form['minimum_stability']->select('dev'); + $form['repositories'] = 'https://satis.phpbb.com/'; $crawler = self::submit($form); $this->assertContainsLang('CONFIG_UPDATED', $crawler->filter('div[class="successbox"] > p')->text()); @@ -264,4 +265,114 @@ class phpbb_functional_extension_acp_test extends phpbb_functional_test_case // Ensure catalog has any records in extensions list $this->assertGreaterThan(0, $crawler->filter('tbody > tr > td > strong')->count()); } + + public function test_extensions_catalog_installing_extension() + { + // Lets check page 6 where 'Scroll Page' and 'Scroll To Top' should be listed + $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=catalog&start=100&sid=' . $this->sid); + $this->assertContainsLang('ACP_EXTENSIONS_CATALOG', $this->get_content()); + + // Get Install links for both extensions + $scrollpage_install_link = $crawler->filter('tr')->reduce( + function ($node, $i) + { + return (bool) (strpos($node->text(), 'Scroll Page') !== false); + } + )->selectLink($this->lang('INSTALL'))->link(); + + $scrolltotop_install_link = $crawler->filter('tr')->reduce( + function ($node, $i) + { + return (bool) (strpos($node->text(), 'Scroll To Top') !== false); + } + )->selectLink($this->lang('INSTALL'))->link(); + + // Attempt to install vse/scrollpage extension + $crawler = self::$client->click($scrollpage_install_link); + $this->assertContainsLang('EXTENSIONS_INSTALLED', $crawler->filter('.successbox > p')->text()); + // Assert there's console log output + $this->assertStringContainsString('Installing vse/scrollpage', $crawler->filter('.console-output > pre')->text()); + + // Attempt to install vse/scrolltotop extension + $crawler = self::$client->click($scrolltotop_install_link); + $this->assertContainsLang('EXTENSIONS_INSTALLED', $crawler->filter('.successbox > p')->text()); + // Assert there's console log output + $this->assertStringContainsString('Installing vse/scrolltotop', $crawler->filter('.console-output > pre')->text()); + + // Ensure installed extension appears in available extensions list + $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid); + $this->assertStringContainsString('Scroll To Top', $crawler->filter('strong[title="vse/scrolltotop"]')->text()); + $this->assertStringContainsString('Scroll Page', $crawler->filter('strong[title="vse/scrollpage"]')->text()); + } + + public function test_extensions_catalog_updating_extension() + { + // Enable 'Scroll Page' extension installed earlier + $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid); + $extension_enable_link = $crawler->filter('tr')->reduce( + function ($node, $i) + { + return (bool) (strpos($node->text(), 'Scroll Page') !== false); + } + )->selectLink($this->lang('EXTENSION_ENABLE'))->link(); + $crawler = self::$client->click($extension_enable_link); + $form = $crawler->selectButton($this->lang('EXTENSION_ENABLE'))->form(); + $crawler = self::submit($form); + $this->assertContainsLang('EXTENSION_ENABLE_SUCCESS', $crawler->filter('.successbox')->text()); + + // Update 'Scroll Page' enabled extension + $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid); + $scrollpage_update_link = $crawler->filter('tr')->reduce( + function ($node, $i) + { + return (bool) (strpos($node->text(), 'Scroll Page') !== false); + } + )->selectLink($this->lang('EXTENSION_UPDATE'))->link(); + $crawler = self::$client->click($scrollpage_update_link); + $this->assertContainsLang('EXTENSIONS_UPDATED', $crawler->filter('.successbox > p')->text()); + // Assert there's console log output + $this->assertStringContainsString('Updating packages', $crawler->filter('.console-output > pre')->text()); + + // Ensure installed extension still appears in available extensions list + $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid); + $this->assertStringContainsString('Scroll Page', $crawler->filter('strong[title="vse/scrollpage"]')->text()); + } + + public function test_extensions_catalog_removing_extension() + { + $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid); + + // Check if both enabled and disabled extensions have 'Remove' action available + $scrollpage_remove_link = $crawler->filter('tr')->reduce( + function ($node, $i) + { + return (bool) (strpos($node->text(), 'Scroll Page') !== false); + } + )->selectLink($this->lang('EXTENSION_REMOVE'))->link(); + + $scrolltotop_remove_link = $crawler->filter('tr')->reduce( + function ($node, $i) + { + return (bool) (strpos($node->text(), 'Scroll To Top') !== false); + } + )->selectLink($this->lang('EXTENSION_REMOVE'))->link(); + + // Test extensions removal + // Remove 'Scroll Page' enabled extension + $crawler = self::$client->click($scrollpage_remove_link); + $this->assertContainsLang('EXTENSIONS_REMOVED', $crawler->filter('.successbox > p')->text()); + // Assert there's console log output + $this->assertStringContainsString('Deleting ext/vse/scrollpage', $crawler->filter('.console-output > pre')->text()); + + // Remove 'Scroll To Top' disabled extension + $crawler = self::$client->click($scrolltotop_remove_link); + $this->assertContainsLang('EXTENSIONS_REMOVED', $crawler->filter('.successbox > p')->text()); + // Assert there's console log output + $this->assertStringContainsString('Deleting ext/vse/scrolltotop', $crawler->filter('.console-output > pre')->text()); + + // Ensure removed extensions do not appear in available extensions list + $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&sid=' . $this->sid); + $this->assertStringNotContainsString('Scroll Page', $this->get_content()); + $this->assertStringNotContainsString('Scroll To Top', $this->get_content()); + } }