diff --git a/routing/page_loader.php b/routing/page_loader.php index 800a025..7760479 100644 --- a/routing/page_loader.php +++ b/routing/page_loader.php @@ -3,78 +3,39 @@ * * Pages extension for the phpBB Forum Software package. * - * @copyright (c) 2015 phpBB Limited + * @copyright (c) 2025 phpBB Limited * @license GNU General Public License, version 2 (GPL-2.0) * */ +// phpcs:disable PSR1.Files.SideEffects namespace phpbb\pages\routing; -use phpbb\db\driver\driver_interface; -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; +use ReflectionMethod; +use Symfony\Component\Config\Loader\LoaderInterface; /** - * Loads routes defined in Page's database. + * This code determines which page_loader class to use based on the phpBB version. + * It checks if the Symfony LoaderInterface::load() method has a return type, + * which indicates Symfony 7+ (phpBB4), otherwise falls back to phpBB3 compatibility. + * The conditional is mandatory to ensure we only define the class if it does not + * already exist in this request. + * + * @noinspection PhpMultipleClassDeclarationsInspection */ -class page_loader extends Loader +if (!class_exists(page_loader::class, false)) { - /** @var driver_interface */ - protected $db; - - /** @var string */ - protected $pages_table; - - /** - * Constructor - * - * @param driver_interface $db Database connection - * @param string $pages_table Table name - * @access public - */ - public function __construct(driver_interface $db, $pages_table) - { - $this->db = $db; - $this->pages_table = $pages_table; - } + $method = new ReflectionMethod(LoaderInterface::class, 'load'); - /** - * Loads routes defined in Page's database. - * - * @param string $resource Resource (not used, but required by parent interface) - * @param string|null $type The resource type - * - * @return RouteCollection A RouteCollection instance - * - * @api - */ - public function load($resource, $type = null) + // phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses + if ($method->hasReturnType()) { - $collection = new RouteCollection(); - - $sql = 'SELECT page_id, page_route - FROM ' . $this->pages_table; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - $route = new Route('/' . $row['page_route']); - $route->setDefault('_controller', 'phpbb.pages.controller:display'); - $route->setDefault('route', $row['page_route']); - $collection->add('phpbb_pages_dynamic_route_' . $row['page_id'], $route); - } - $this->db->sql_freeresult(); - - return $collection; + class page_loader extends page_loader_phpbb4 {} } - - /** - * {@inheritdoc} - * - * @api - */ - public function supports($resource, $type = null) + else { - return $type === 'phpbb_pages_route'; + class page_loader extends page_loader_phpbb3 {} } + // phpcs:enable PSR1.Classes.ClassDeclaration.MultipleClasses } +// phpcs:enable PSR1.Files.SideEffects diff --git a/routing/page_loader_core.php b/routing/page_loader_core.php new file mode 100644 index 0000000..b932008 --- /dev/null +++ b/routing/page_loader_core.php @@ -0,0 +1,76 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + */ + +namespace phpbb\pages\routing; + +use phpbb\db\driver\driver_interface; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * Core loader logic for loading routes from the database. + */ +class page_loader_core +{ + /** @var driver_interface */ + protected $db; + + /** @var string */ + protected $pages_table; + + /** + * Constructor for the page_loader_core class. + * + * @param driver_interface $db The database driver instance. + * @param string $pages_table The name of the pages table in the database. + */ + public function __construct(driver_interface $db, string $pages_table) + { + $this->db = $db; + $this->pages_table = $pages_table; + } + + /** + * Loads routes defined in Page's database. + * + * @return RouteCollection A RouteCollection instance + * + * @api + */ + public function loadRoutes(): RouteCollection + { + $collection = new RouteCollection(); + + $sql = 'SELECT page_id, page_route + FROM ' . $this->pages_table; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $route = new Route('/' . $row['page_route']); + $route->setDefault('_controller', 'phpbb.pages.controller:display'); + $route->setDefault('route', $row['page_route']); + $collection->add('phpbb_pages_dynamic_route_' . $row['page_id'], $route); + } + $this->db->sql_freeresult(); + + return $collection; + } + + /** + * Checks if the loader supports the specified type. + * + * @param mixed $type The type to check support for. + * @return bool True if the type is supported, false otherwise. + */ + public function supportsType($type): bool + { + return $type === 'phpbb_pages_route'; + } +} diff --git a/routing/page_loader_phpbb3.php b/routing/page_loader_phpbb3.php new file mode 100644 index 0000000..3ccb620 --- /dev/null +++ b/routing/page_loader_phpbb3.php @@ -0,0 +1,64 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + */ + +namespace phpbb\pages\routing; + +use InvalidArgumentException; +use phpbb\db\driver\driver_interface; +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Routing\RouteCollection; + +/** + * phpBB 3 and Symfony 3 through 6 adapter for page loader. + */ +class page_loader_phpbb3 extends Loader +{ + /** @var page_loader_core */ + protected $core; + + /** + * Constructor for the page_loader_phpbb3 class. + * + * @param driver_interface $db The database driver instance. + * @param string $pages_table The name of the pages table in the database. + */ + public function __construct(driver_interface $db, string $pages_table) + { + $this->core = new page_loader_core($db, $pages_table); + } + + /** + * Loads routes from the database. + * + * @param mixed $resource The resource to load routes from. + * @param string|null $type The type of the resource, or null if not specified. + * @return RouteCollection The collection of loaded routes. + */ + public function load($resource, $type = null) + { + if (!is_string($type) && $type !== null) + { + throw new InvalidArgumentException('Type must be string or null'); + } + return $this->core->loadRoutes(); + } + + /** + * Determines if the given resource is supported based on its type. + * + * @param mixed $resource The resource to be checked. + * @param string|null $type The type of the resource, or null for default processing. + * @return bool True if the resource type is supported, false otherwise. + */ + public function supports($resource, $type = null): bool + { + return $this->core->supportsType($type); + } +} diff --git a/routing/page_loader_phpbb4.php b/routing/page_loader_phpbb4.php new file mode 100644 index 0000000..ecbc49d --- /dev/null +++ b/routing/page_loader_phpbb4.php @@ -0,0 +1,60 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + */ + +namespace phpbb\pages\routing; + +use phpbb\db\driver\driver_interface; +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Routing\RouteCollection; + +/** + * phpbb 4 and Symfony 7 adapter for page loader. + */ +class page_loader_phpbb4 extends Loader +{ + /** @var page_loader_core */ + protected page_loader_core $core; + + /** + * Constructor for the page_loader_phpbb4 class. + * + * @param driver_interface $db The database driver instance. + * @param string $pages_table The name of the pages table in the database. + */ + public function __construct(driver_interface $db, string $pages_table) + { + $this->core = new page_loader_core($db, $pages_table); + parent::__construct(); + } + + /** + * Loads a set of routes from a specified resource. + * + * @param mixed $resource The resource to load routes from. + * @param string|null $type The type of the resource, or null if not specified. + * @return RouteCollection The collection of loaded routes. + */ + public function load(mixed $resource, ?string $type = null): RouteCollection + { + return $this->core->loadRoutes(); + } + + /** + * Checks if the loader supports the specified resource and type. + * + * @param mixed $resource The resource to check support for. + * @param string|null $type The type of the resource, or null if not specified. + * @return bool True if the loader supports the resource and type, false otherwise. + */ + public function supports(mixed $resource, string $type = null): bool + { + return $this->core->supportsType($type); + } +}