diff --git a/phpmyfaq/admin/instances.php b/phpmyfaq/admin/instances.php index b902c26e36..fc74c130c5 100644 --- a/phpmyfaq/admin/instances.php +++ b/phpmyfaq/admin/instances.php @@ -18,7 +18,7 @@ use phpMyFAQ\Configuration; use phpMyFAQ\Entity\InstanceEntity; use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Filesystem; +use phpMyFAQ\Filesystem\Filesystem; use phpMyFAQ\Filter; use phpMyFAQ\Instance; use phpMyFAQ\Instance\Client; diff --git a/phpmyfaq/src/phpMyFAQ/Controller/Administration/InstanceController.php b/phpmyfaq/src/phpMyFAQ/Controller/Administration/InstanceController.php index 96f7a1fe44..290fb807d9 100644 --- a/phpmyfaq/src/phpMyFAQ/Controller/Administration/InstanceController.php +++ b/phpmyfaq/src/phpMyFAQ/Controller/Administration/InstanceController.php @@ -23,7 +23,7 @@ use phpMyFAQ\Database; use phpMyFAQ\Entity\InstanceEntity; use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Filesystem; +use phpMyFAQ\Filesystem\Filesystem; use phpMyFAQ\Filter; use phpMyFAQ\Instance\Client; use phpMyFAQ\Instance\Setup; diff --git a/phpmyfaq/src/phpMyFAQ/Controller/Administration/UpdateController.php b/phpmyfaq/src/phpMyFAQ/Controller/Administration/UpdateController.php index 1c31856a61..fd20197135 100644 --- a/phpmyfaq/src/phpMyFAQ/Controller/Administration/UpdateController.php +++ b/phpmyfaq/src/phpMyFAQ/Controller/Administration/UpdateController.php @@ -183,9 +183,6 @@ public function downloadPackage(Request $request): JsonResponse return $this->json(['success' => Translation::get('downloadSuccessful')], Response::HTTP_OK); } - /** - * @throws Exception - */ #[Route('admin/api/extract-package')] public function extractPackage(): StreamedResponse { @@ -208,9 +205,6 @@ public function extractPackage(): StreamedResponse }); } - /** - * @throws Exception - */ #[Route('admin/api/create-temporary-backup')] public function createTemporaryBackup(): StreamedResponse { @@ -233,9 +227,6 @@ public function createTemporaryBackup(): StreamedResponse }); } - /** - * @throws Exception - */ #[Route('admin/api/install-package')] public function installPackage(): StreamedResponse { @@ -256,9 +247,6 @@ public function installPackage(): StreamedResponse }); } - /** - * @throws Exception - */ #[Route('admin/api/update-database')] public function updateDatabase(): StreamedResponse { diff --git a/phpmyfaq/src/phpMyFAQ/Filesystem.php b/phpmyfaq/src/phpMyFAQ/Filesystem/Filesystem.php similarity index 98% rename from phpmyfaq/src/phpMyFAQ/Filesystem.php rename to phpmyfaq/src/phpMyFAQ/Filesystem/Filesystem.php index 92c51ebb24..9de539eebc 100644 --- a/phpmyfaq/src/phpMyFAQ/Filesystem.php +++ b/phpmyfaq/src/phpMyFAQ/Filesystem/Filesystem.php @@ -15,7 +15,7 @@ * @since 2012-04-02 */ -namespace phpMyFAQ; +namespace phpMyFAQ\Filesystem; use phpMyFAQ\Core\Exception; @@ -117,7 +117,7 @@ public function moveDirectory(string $sourcePath, string $destinationPath): bool } /** - * Deletes given directory. + * Deletes the given directory. */ public function deleteDirectory(string $pathname): bool { diff --git a/phpmyfaq/src/phpMyFAQ/Instance/Client.php b/phpmyfaq/src/phpMyFAQ/Instance/Client.php index 28e2f8e717..af1372e7ce 100644 --- a/phpmyfaq/src/phpMyFAQ/Instance/Client.php +++ b/phpmyfaq/src/phpMyFAQ/Instance/Client.php @@ -18,9 +18,9 @@ namespace phpMyFAQ\Instance; use phpMyFAQ\Configuration; -use phpMyFAQ\Database; use phpMyFAQ\Core\Exception; -use phpMyFAQ\Filesystem; +use phpMyFAQ\Database; +use phpMyFAQ\Filesystem\Filesystem; use phpMyFAQ\Instance; use phpMyFAQ\Instance\Database as InstanceDatabase; diff --git a/phpmyfaq/src/phpMyFAQ/Setup/EnvironmentConfigurator.php b/phpmyfaq/src/phpMyFAQ/Setup/EnvironmentConfigurator.php new file mode 100644 index 0000000000..c0ca17a6d5 --- /dev/null +++ b/phpmyfaq/src/phpMyFAQ/Setup/EnvironmentConfigurator.php @@ -0,0 +1,90 @@ +rootFilePath = $rootPath; + $this->htaccessPath = $this->rootFilePath . '/.htaccess'; + } + + public function getRootFilePath(): string + { + return $this->rootFilePath; + } + + public function getHtaccessPath(): string + { + return $this->htaccessPath; + } + + public function getServerPath(): string + { + return $this->serverPath = $this->request->getPathInfo(); + } + + /** + * @throws Exception + */ + public function getRewriteBase(): string + { + $file = new SplFileObject($this->htaccessPath); + $parser = new Parser(); + try { + $htaccess = $parser->parse($file); + } catch (SyntaxException $e) { + throw new Exception('Syntax error in .htaccess file: ' . $e->getMessage()); + } catch (\Tivie\HtaccessParser\Exception\Exception $e) { + throw new Exception('Error parsing .htaccess file: ' . $e->getMessage()); + } + $rewriteBase = $htaccess->search('RewriteBase', TOKEN_DIRECTIVE); + + return $rewriteBase->getArguments()[0]; + } + + /** + * Adjusts the RewriteBase in the .htaccess file for the user's environment to avoid errors with controllers. + * Returns true, if the file was successfully changed. + * + * @throws Exception + */ + public function adjustRewriteBaseHtaccess(): bool + { + if (!file_exists($this->htaccessPath)) { + throw new Exception(sprintf('The %s file does not exist!', $this->htaccessPath)); + } + + $file = new SplFileObject($this->htaccessPath); + $parser = new Parser(); + try { + $htaccess = $parser->parse($file); + } catch (SyntaxException $e) { + throw new Exception('Syntax error in .htaccess file: ' . $e->getMessage()); + } catch (\Tivie\HtaccessParser\Exception\Exception $e) { + throw new Exception('Error parsing .htaccess file: ' . $e->getMessage()); + } + $rewriteBase = $htaccess->search('RewriteBase', TOKEN_DIRECTIVE); + + $rewriteBase->removeArgument($this->getRewriteBase()); + $rewriteBase->setArguments((array)$this->getServerPath()); + + $output = (string) $htaccess; + return file_put_contents($this->htaccessPath, $output); + } +} diff --git a/phpmyfaq/src/phpMyFAQ/Setup/Installer.php b/phpmyfaq/src/phpMyFAQ/Setup/Installer.php index ba0e003a7a..cb316a2767 100644 --- a/phpmyfaq/src/phpMyFAQ/Setup/Installer.php +++ b/phpmyfaq/src/phpMyFAQ/Setup/Installer.php @@ -41,6 +41,7 @@ use phpMyFAQ\Link; use phpMyFAQ\System; use phpMyFAQ\User; +use Symfony\Component\HttpFoundation\Request; /** * Class Installer @@ -1142,7 +1143,8 @@ public function startInstall(array|null $setup = null): void } // adjust RewriteBase in .htaccess - $this->adjustRewriteBaseHtaccess($rootDir); + $envConfiguration = new EnvironmentConfigurator($rootDir, Request::createFromGlobals()); + $envConfiguration->adjustRewriteBaseHtaccess(); } /** @@ -1154,37 +1156,6 @@ public function checkMinimumPhpVersion(): bool return version_compare(PHP_VERSION, System::VERSION_MINIMUM_PHP) >= 0; } - /** - * Adjusts the RewriteBase in the .htaccess file for the user's environment to avoid errors with controllers. - * Returns true, if the file was successfully changed. - * - * @throws Exception - */ - public function adjustRewriteBaseHtaccess(string $path): bool - { - $htaccessPath = $path . '/.htaccess'; - - if (!file_exists($htaccessPath)) { - throw new Exception(sprintf('The %s file does not exist!', $htaccessPath)); - } - - $lines = file($htaccessPath); - $newLines = []; - - foreach ($lines as $line) { - if (str_starts_with($line, 'RewriteBase')) { - $requestUri = filter_input(INPUT_SERVER, 'PHP_SELF'); - $rewriteBase = substr((string) $requestUri, 0, strpos((string) $requestUri, 'setup/index.php')); - $rewriteBase = ($rewriteBase === '') ? '/' : $rewriteBase; - $newLines[] = 'RewriteBase ' . $rewriteBase . PHP_EOL; - } else { - $newLines[] = $line; - } - } - - return file_put_contents($htaccessPath, implode('', $newLines)) !== false; - } - public function hasLdapSupport(): bool { return extension_loaded('ldap'); diff --git a/phpmyfaq/src/phpMyFAQ/Setup/Update.php b/phpmyfaq/src/phpMyFAQ/Setup/Update.php index 294b66ecfa..61b1230b5b 100644 --- a/phpmyfaq/src/phpMyFAQ/Setup/Update.php +++ b/phpmyfaq/src/phpMyFAQ/Setup/Update.php @@ -22,7 +22,7 @@ use phpMyFAQ\Database; use phpMyFAQ\Database\DatabaseDriver; use phpMyFAQ\Enums\ReleaseType; -use phpMyFAQ\Filesystem; +use phpMyFAQ\Filesystem\Filesystem; use phpMyFAQ\Forms; use phpMyFAQ\Setup; use phpMyFAQ\System; diff --git a/tests/.htaccess b/tests/.htaccess index 3103ab3dca..096eb92300 100644 --- a/tests/.htaccess +++ b/tests/.htaccess @@ -1 +1 @@ -RewriteBase / +RewriteBase /phpmyfaq-test/ \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 9d039b11b5..90d664df09 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -39,8 +39,8 @@ const IS_VALID_PHPMYFAQ = true; const DEBUG = true; -$_SERVER['HTTP_HOST'] = 'https://localhost/'; -$_SERVER['SERVER_NAME'] = 'https://localhost/'; +$_SERVER['HTTP_HOST'] = 'https://localhost/phpmyfaq-test/'; +$_SERVER['SERVER_NAME'] = 'https://localhost/phpmyfaq-test/'; require PMF_ROOT_DIR . '/content/core/config/constants.php'; @@ -63,7 +63,7 @@ $loader->register(); // -// Delete possible SQLite file first +// Delete a possible SQLite file first // @unlink(PMF_TEST_DIR . '/test.db'); diff --git a/tests/phpMyFAQ/FilesystemTest.php b/tests/phpMyFAQ/Filesystem/FilesystemTest.php similarity index 98% rename from tests/phpMyFAQ/FilesystemTest.php rename to tests/phpMyFAQ/Filesystem/FilesystemTest.php index 659f211b66..3ef8fe827f 100644 --- a/tests/phpMyFAQ/FilesystemTest.php +++ b/tests/phpMyFAQ/Filesystem/FilesystemTest.php @@ -1,6 +1,6 @@ configurator = new EnvironmentConfigurator(dirname(__DIR__, 2)); + } + + protected function tearDown(): void + { + Request::setTrustedProxies([], -1); + Request::setTrustedHosts([]); + + file_put_contents(dirname(__DIR__, 2) . '/.htaccess', 'RewriteBase /phpmyfaq-test/'); + } + + public function testGetRootFilePath(): void + { + $this->assertEquals(dirname(__DIR__, 2), $this->configurator->getRootFilePath()); + } + + public function testGetHtaccessPath(): void + { + $this->assertEquals(dirname(__DIR__, 2) . '/.htaccess', $this->configurator->getHtaccessPath()); + } + + public function testGetServerPath(): void + { + $request = new Request(); + $server = []; + $server['REQUEST_URI'] = '/'; + $request->initialize([], [], [], [], [], $server); + $configurator = new EnvironmentConfigurator('/path/to', $request); + $this->assertEquals('/', $configurator->getServerPath()); + } + + /** + * @throws Exception + */ + public function testGetRewriteBase(): void + { + $request = new Request(); + $server = []; + $server['REQUEST_URI'] = '/phpmyfaq-test/'; + $server['HTTP_HOST'] = 'https://localhost/phpmyfaq-test/'; + $server['SERVER_NAME'] = 'https://localhost/phpmyfaq-test/'; + $request->initialize([], [], [], [], [], $server); + $configurator = new EnvironmentConfigurator(dirname(__DIR__, 2), $request); + $this->assertEquals('/phpmyfaq-test/', $configurator->getRewriteBase()); + } + + public function testGetServerPathWithSubdirectoryPath(): void + { + $request = new Request(); + $server = []; + $server['REQUEST_URI'] = '/path/info'; + $request->initialize([], [], [], [], [], $server); + $configurator = new EnvironmentConfigurator('/path/to', $request); + $this->assertEquals('/path/info', $configurator->getServerPath()); + } + + public function testAdjustRewriteBaseHtaccessThrowsExceptionForMissingFile(): void + { + $configurator = new EnvironmentConfigurator('/path/to'); + $this->expectException(Exception::class); + $this->expectExceptionMessage('The /path/to/.htaccess file does not exist!'); + $configurator->adjustRewriteBaseHtaccess(); + } + + /** + * @throws Exception + */ + public function testAdjustRewriteBaseHtaccess(): void + { + $request = new Request(); + $server = []; + $server['REQUEST_URI'] = '/path/info'; + $request->initialize([], [], [], [], [], $server); + $configurator = new EnvironmentConfigurator(dirname(__DIR__, 2), $request); + $this->assertTrue($configurator->adjustRewriteBaseHtaccess()); + $this->assertEquals('/path/info', $configurator->getRewriteBase()); + } +} diff --git a/tests/phpMyFAQ/Setup/InstallerTest.php b/tests/phpMyFAQ/Setup/InstallerTest.php index 2bd56a5d3d..248d90c810 100644 --- a/tests/phpMyFAQ/Setup/InstallerTest.php +++ b/tests/phpMyFAQ/Setup/InstallerTest.php @@ -51,13 +51,6 @@ public function testCheckBasicStuffThrowsExceptionForAlreadyInstalled(): void $this->installer->checkBasicStuff(); } - public function testAdjustRewriteBaseHtaccessThrowsExceptionForMissingFile(): void - { - $this->expectException(Exception::class); - $this->expectExceptionMessage('The /path/to/.htaccess file does not exist!'); - $this->installer->adjustRewriteBaseHtaccess('/path/to'); - } - public function testHasLdapSupport(): void { if (extension_loaded('ldap')) {