diff options
18 files changed, 426 insertions, 0 deletions
diff --git a/phpBB/includes/extension/controller_interface.php b/phpBB/includes/extension/controller_interface.php new file mode 100644 index 0000000000..bcc8972db4 --- /dev/null +++ b/phpBB/includes/extension/controller_interface.php @@ -0,0 +1,31 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* The interface that extension classes have to implement to run front pages +* +* @package extension +*/ +interface phpbb_extension_controller_interface +{ + /** + * handle the request to display a page from an extension + * + * @return null + */ + public function handle(); +} diff --git a/phpBB/includes/extension/manager.php b/phpBB/includes/extension/manager.php index dac0e5f947..537c19aff8 100644 --- a/phpBB/includes/extension/manager.php +++ b/phpBB/includes/extension/manager.php @@ -432,6 +432,28 @@ class phpbb_extension_manager } return $disabled; } + + /** + * Check to see if a given extension is available on the filesystem + * + * @param string $name Extension name to check NOTE: Can be user input + * @return bool Depending on whether or not the extension is available + */ + public function available($name) + { + return file_exists($this->get_extension_path($name, true)); + } + + /** + * Check to see if a given extension is enabled + * + * @param string $name Extension name to check + * @return bool Depending on whether or not the extension is enabled + */ + public function enabled($name) + { + return isset($this->extensions[$name]) && $this->extensions[$name]['ext_active']; + } /** * Instantiates a phpbb_extension_finder. diff --git a/phpBB/index.php b/phpBB/index.php index f1243bb336..d71878a885 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -24,6 +24,39 @@ $user->session_begin(); $auth->acl($user->data); $user->setup('viewforum'); +// Handle the display of extension front pages +if ($ext = $request->variable('ext', '')) +{ + $class = 'phpbb_ext_' . str_replace('/', '_', $ext) . '_controller'; + + if (!$phpbb_extension_manager->available($ext)) + { + send_status_line(404, 'Not Found'); + trigger_error($user->lang('EXTENSION_DOES_NOT_EXIST', $ext)); + } + else if (!$phpbb_extension_manager->enabled($ext)) + { + send_status_line(404, 'Not Found'); + trigger_error($user->lang('EXTENSION_DISABLED', $ext)); + } + else if (!class_exists($class)) + { + send_status_line(404, 'Not Found'); + trigger_error($user->lang('EXTENSION_CONTROLLER_MISSING', $ext)); + } + + $controller = new $class; + + if (!($controller instanceof phpbb_extension_controller_interface)) + { + send_status_line(500, 'Internal Server Error'); + trigger_error($user->lang('EXTENSION_CLASS_WRONG_TYPE', $class)); + } + + $controller->handle(); + exit_handler(); +} + display_forums('', $config['load_moderators']); $order_legend = ($config['legend_sort_groupname']) ? 'group_name' : 'group_legend'; diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 7741ff8d1f..94edddc6f5 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -185,7 +185,11 @@ $lang = array_merge($lang, array( 'ERR_WRONG_PATH_TO_PHPBB' => 'The phpBB path specified appears to be invalid.', 'EXPAND_VIEW' => 'Expand view', 'EXTENSION' => 'Extension', + 'EXTENSION_CONTROLLER_MISSING' => 'The extension <strong>%s</strong> is missing a controller class and cannot be accessed through the front-end.', + 'EXTENSION_CLASS_WRONG_TYPE' => 'The extension controller class <strong>%s</strong> is not an instance of the phpbb_extension_controller_interface.', + 'EXTENSION_DISABLED' => 'The extension <strong>%s</strong> is not enabled.', 'EXTENSION_DISABLED_AFTER_POSTING' => 'The extension <strong>%s</strong> has been deactivated and can no longer be displayed.', + 'EXTENSION_DOES_NOT_EXIST' => 'The extension <strong>%s</strong> does not exist.', 'FAQ' => 'FAQ', 'FAQ_EXPLAIN' => 'Frequently Asked Questions', diff --git a/tests/functional/extension_controller_test.php b/tests/functional/extension_controller_test.php new file mode 100644 index 0000000000..4ee0e68718 --- /dev/null +++ b/tests/functional/extension_controller_test.php @@ -0,0 +1,153 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @group functional +*/ +class phpbb_functional_extension_controller_test extends phpbb_functional_test_case +{ + protected $phpbb_extension_manager; + /** + * This should only be called once before the tests are run. + * This is used to copy the fixtures to the phpBB install + */ + static public function setUpBeforeClass() + { + global $phpbb_root_path; + parent::setUpBeforeClass(); + + // these directories need to be created before the files can be copied + $directories = array( + $phpbb_root_path . 'ext/error/class/', + $phpbb_root_path . 'ext/error/classtype/', + $phpbb_root_path . 'ext/error/disabled/', + $phpbb_root_path . 'ext/foo/bar/', + $phpbb_root_path . 'ext/foo/bar/styles/prosilver/template/', + $phpbb_root_path . 'ext/foobar/', + $phpbb_root_path . 'ext/foobar/styles/prosilver/template/', + ); + + foreach ($directories as $dir) + { + if (!is_dir($dir)) + { + mkdir($dir, 0777, true); + } + } + + $fixtures = array( + 'error/class/controller.php', + 'error/class/ext.php', + 'error/classtype/controller.php', + 'error/classtype/ext.php', + 'error/disabled/controller.php', + 'error/disabled/ext.php', + 'foo/bar/controller.php', + 'foo/bar/ext.php', + 'foo/bar/styles/prosilver/template/foobar_body.html', + 'foobar/controller.php', + 'foobar/ext.php', + 'foobar/styles/prosilver/template/foobar_body.html', + ); + + foreach ($fixtures as $fixture) + { + if (!copy("tests/functional/fixtures/ext/$fixture", "{$phpbb_root_path}ext/$fixture")) + { + echo 'Could not copy file ' . $fixture; + } + } + } + + public static function tearDownAfterClass() + { + $phpbb_root_path = self::$config['phpbb_functional_path']; + + // @todo delete the fixtures from the $phpbb_root_path board + // Note that it might be best to find a public domain function + // and port it into here instead of writing it from scratch + } + + public function setUp() + { + parent::setUp(); + + $this->phpbb_extension_manager = $this->get_extension_manager(); + + $this->purge_cache(); + } + + /** + * Check an extension at ./ext/foobar/ which should have the class + * phpbb_ext_foobar_controller + */ + public function test_foobar() + { + $this->phpbb_extension_manager->enable('foobar'); + $crawler = $this->request('GET', 'index.php?ext=foobar'); + $this->assertContains("This is for testing purposes.", $crawler->filter('#page-body')->text()); + $this->phpbb_extension_manager->purge('foobar'); + } + + /** + * Check an extension at ./ext/foo/bar/ which should have the class + * phpbb_ext_foo_bar_controller + */ + public function test_foo_bar() + { + $this->phpbb_extension_manager->enable('foo/bar'); + $crawler = $this->request('GET', 'index.php?ext=foo/bar'); + $this->assertContains("This is for testing purposes.", $crawler->filter('#page-body')->text()); + $this->phpbb_extension_manager->purge('foo/bar'); + } + + /** + * Check the error produced by extension at ./ext/error/class which has class + * phpbb_ext_foobar_controller + */ + public function test_error_class_name() + { + $this->phpbb_extension_manager->enable('error/class'); + $crawler = $this->request('GET', 'index.php?ext=error/class'); + $this->assertContains("The extension error/class is missing a controller class and cannot be accessed through the front-end.", $crawler->filter('#message')->text()); + $this->phpbb_extension_manager->purge('error/class'); + } + + /** + * Check the error produced by extension at ./ext/error/classtype which has class + * phpbb_ext_error_classtype_controller but does not implement phpbb_extension_controller_interface + */ + public function test_error_class_type() + { + $this->phpbb_extension_manager->enable('error/classtype'); + $crawler = $this->request('GET', 'index.php?ext=error/classtype'); + $this->assertContains("The extension controller class phpbb_ext_error_classtype_controller is not an instance of the phpbb_extension_controller_interface.", $crawler->filter('#message')->text()); + $this->phpbb_extension_manager->purge('error/classtype'); + } + + /** + * Check the error produced by extension at ./ext/error/disabled that is (obviously) + * a disabled extension + */ + public function test_error_ext_disabled() + { + $crawler = $this->request('GET', 'index.php?ext=error/disabled'); + $this->assertContains("The extension error/disabled is not enabled", $crawler->filter('#message')->text()); + } + + /** + * Check the error produced by extension at ./ext/error/404 that is (obviously) + * not existant + */ + public function test_error_ext_missing() + { + $crawler = $this->request('GET', 'index.php?ext=error/404'); + $this->assertContains("The extension error/404 does not exist.", $crawler->filter('#message')->text()); + } +} diff --git a/tests/functional/fixtures/ext/error/class/controller.php b/tests/functional/fixtures/ext/error/class/controller.php new file mode 100644 index 0000000000..eb2ae362a6 --- /dev/null +++ b/tests/functional/fixtures/ext/error/class/controller.php @@ -0,0 +1,17 @@ +<?php + +class phpbb_ext_foobar_controller implements phpbb_extension_controller_interface +{ + public function handle() + { + global $template; + $template->set_ext_dir_prefix($phpbb_root_path . 'ext/error/class/'); + + $template->set_filenames(array( + 'body' => 'index_body.html' + )); + + page_header('Test extension'); + page_footer(); + } +} diff --git a/tests/functional/fixtures/ext/error/class/ext.php b/tests/functional/fixtures/ext/error/class/ext.php new file mode 100644 index 0000000000..f97ad2b838 --- /dev/null +++ b/tests/functional/fixtures/ext/error/class/ext.php @@ -0,0 +1,6 @@ +<?php + +class phpbb_ext_error_class_ext extends phpbb_extension_base +{ + +} diff --git a/tests/functional/fixtures/ext/error/classtype/controller.php b/tests/functional/fixtures/ext/error/classtype/controller.php new file mode 100644 index 0000000000..2276548b55 --- /dev/null +++ b/tests/functional/fixtures/ext/error/classtype/controller.php @@ -0,0 +1,17 @@ +<?php + +class phpbb_ext_error_classtype_controller +{ + public function handle() + { + global $template; + $template->set_ext_dir_prefix($phpbb_root_path . 'ext/error/classtype/'); + + $template->set_filenames(array( + 'body' => 'index_body.html' + )); + + page_header('Test extension'); + page_footer(); + } +} diff --git a/tests/functional/fixtures/ext/error/classtype/ext.php b/tests/functional/fixtures/ext/error/classtype/ext.php new file mode 100644 index 0000000000..35b1cd15a2 --- /dev/null +++ b/tests/functional/fixtures/ext/error/classtype/ext.php @@ -0,0 +1,6 @@ +<?php + +class phpbb_ext_error_classtype_ext extends phpbb_extension_base +{ + +} diff --git a/tests/functional/fixtures/ext/error/disabled/controller.php b/tests/functional/fixtures/ext/error/disabled/controller.php new file mode 100644 index 0000000000..b83a949020 --- /dev/null +++ b/tests/functional/fixtures/ext/error/disabled/controller.php @@ -0,0 +1,17 @@ +<?php + +class phpbb_ext_error_disabled_controller implements phpbb_extension_controller_interface +{ + public function handle() + { + global $template; + $template->set_ext_dir_prefix($phpbb_root_path . 'ext/error/disabled/'); + + $template->set_filenames(array( + 'body' => 'index_body.html' + )); + + page_header('Test extension'); + page_footer(); + } +} diff --git a/tests/functional/fixtures/ext/error/disabled/ext.php b/tests/functional/fixtures/ext/error/disabled/ext.php new file mode 100644 index 0000000000..aec8051848 --- /dev/null +++ b/tests/functional/fixtures/ext/error/disabled/ext.php @@ -0,0 +1,6 @@ +<?php + +class phpbb_ext_error_disabled_ext extends phpbb_extension_base +{ + +} diff --git a/tests/functional/fixtures/ext/foo/bar/controller.php b/tests/functional/fixtures/ext/foo/bar/controller.php new file mode 100644 index 0000000000..24d218c412 --- /dev/null +++ b/tests/functional/fixtures/ext/foo/bar/controller.php @@ -0,0 +1,17 @@ +<?php + +class phpbb_ext_foo_bar_controller implements phpbb_extension_controller_interface +{ + public function handle() + { + global $template; + $template->set_ext_dir_prefix($phpbb_root_path . 'ext/foo/bar/'); + + $template->set_filenames(array( + 'body' => 'foobar_body.html' + )); + + page_header('Test extension'); + page_footer(); + } +} diff --git a/tests/functional/fixtures/ext/foo/bar/ext.php b/tests/functional/fixtures/ext/foo/bar/ext.php new file mode 100644 index 0000000000..3a2068631e --- /dev/null +++ b/tests/functional/fixtures/ext/foo/bar/ext.php @@ -0,0 +1,6 @@ +<?php + +class phpbb_ext_foo_bar_ext extends phpbb_extension_base +{ + +} diff --git a/tests/functional/fixtures/ext/foo/bar/styles/prosilver/template/foobar_body.html b/tests/functional/fixtures/ext/foo/bar/styles/prosilver/template/foobar_body.html new file mode 100644 index 0000000000..4addf2666f --- /dev/null +++ b/tests/functional/fixtures/ext/foo/bar/styles/prosilver/template/foobar_body.html @@ -0,0 +1,5 @@ +<!-- INCLUDE overall_header.html --> + +<div id="welcome">This is for testing purposes.</div> + +<!-- INCLUDE overall_footer.html --> diff --git a/tests/functional/fixtures/ext/foobar/controller.php b/tests/functional/fixtures/ext/foobar/controller.php new file mode 100644 index 0000000000..bf8d8139ae --- /dev/null +++ b/tests/functional/fixtures/ext/foobar/controller.php @@ -0,0 +1,17 @@ +<?php + +class phpbb_ext_foobar_controller implements phpbb_extension_controller_interface +{ + public function handle() + { + global $template; + $template->set_ext_dir_prefix($phpbb_root_path . 'ext/foobar/'); + + $template->set_filenames(array( + 'body' => 'foobar_body.html' + )); + + page_header('Test extension'); + page_footer(); + } +} diff --git a/tests/functional/fixtures/ext/foobar/ext.php b/tests/functional/fixtures/ext/foobar/ext.php new file mode 100644 index 0000000000..7cf443d369 --- /dev/null +++ b/tests/functional/fixtures/ext/foobar/ext.php @@ -0,0 +1,6 @@ +<?php + +class phpbb_ext_foobar_ext extends phpbb_extension_base +{ + +} diff --git a/tests/functional/fixtures/ext/foobar/styles/prosilver/template/foobar_body.html b/tests/functional/fixtures/ext/foobar/styles/prosilver/template/foobar_body.html new file mode 100644 index 0000000000..4addf2666f --- /dev/null +++ b/tests/functional/fixtures/ext/foobar/styles/prosilver/template/foobar_body.html @@ -0,0 +1,5 @@ +<!-- INCLUDE overall_header.html --> + +<div id="welcome">This is for testing purposes.</div> + +<!-- INCLUDE overall_footer.html --> diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index b5e6f7e377..69c62af297 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -14,6 +14,10 @@ class phpbb_functional_test_case extends phpbb_test_case protected $client; protected $root_url; + protected $cache = null; + protected $db = null; + protected $extension_manager = null; + static protected $config = array(); static protected $already_installed = false; @@ -66,6 +70,60 @@ class phpbb_functional_test_case extends phpbb_test_case } } + protected function get_db() + { + global $phpbb_root_path, $phpEx; + // so we don't reopen an open connection + if (!($this->db instanceof dbal)) + { + if (!class_exists('dbal_' . self::$config['dbms'])) + { + include($phpbb_root_path . 'includes/db/' . self::$config['dbms'] . ".$phpEx"); + } + $sql_db = 'dbal_' . self::$config['dbms']; + $this->db = new $sql_db(); + $this->db->sql_connect(self::$config['dbhost'], self::$config['dbuser'], self::$config['dbpasswd'], self::$config['dbname'], self::$config['dbport']); + } + return $this->db; + } + + protected function get_cache_driver() + { + if (!$this->cache) + { + $this->cache = new phpbb_cache_driver_file; + } + + return $this->cache; + } + + protected function purge_cache() + { + $cache = $this->get_cache_driver(); + + $cache->purge(); + $cache->unload(); + $cache->load(); + } + + protected function get_extension_manager() + { + global $phpbb_root_path, $phpEx; + + if (!$this->extension_manager) + { + $this->extension_manager = new phpbb_extension_manager( + $this->get_db(), + self::$config['table_prefix'] . 'ext', + $phpbb_root_path, + ".$phpEx", + $this->get_cache_driver() + ); + } + + return $this->extension_manager; + } + protected function install_board() { global $phpbb_root_path, $phpEx; |