]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Merge pull request #1539 from ArthurHoaro/feature/manual-root-url
authorArthurHoaro <arthur@hoa.ro>
Tue, 22 Sep 2020 12:08:54 +0000 (14:08 +0200)
committerGitHub <noreply@github.com>
Tue, 22 Sep 2020 12:08:54 +0000 (14:08 +0200)
12 files changed:
.htaccess
application/container/ContainerBuilder.php
application/container/ShaarliContainer.php
application/front/controller/admin/PluginsController.php
application/front/controller/visitor/ErrorNotFoundController.php [new file with mode: 0644]
application/plugin/PluginManager.php
tests/PluginManagerTest.php
tests/container/ContainerBuilderTest.php
tests/front/controller/admin/PluginsControllerTest.php
tests/front/controller/visitor/ErrorNotFoundControllerTest.php [new file with mode: 0644]
tests/front/controller/visitor/FrontControllerMockHelper.php
tests/plugins/test/test.php

index 8876e346ce70bf3ff951a5ed3e2fe682de837535..af2dc5a7ff24a244d731a5d2382dc496f62d1eda 100644 (file)
--- a/.htaccess
+++ b/.htaccess
@@ -16,23 +16,7 @@ RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteRule ^ index.php [QSA,L]
 
-<Limit GET POST PUT DELETE OPTIONS>
-  <IfModule version_module>
-    <IfVersion >= 2.4>
-       Require all granted
-    </IfVersion>
-    <IfVersion < 2.4>
-       Allow from all
-       Deny from none
-    </IfVersion>
-  </IfModule>
-
-  <IfModule !version_module>
-    Require all granted
-  </IfModule>
-</Limit>
-
-<LimitExcept GET POST PUT DELETE OPTIONS>
+<LimitExcept GET POST PUT DELETE PATCH OPTIONS>
   <IfModule version_module>
     <IfVersion >= 2.4>
        Require all denied
index 58067c9945319d7d7bb664d37c0589fe71b8d377..55bb51b5b46506f95b2d79280796c694cc1e9fc9 100644 (file)
@@ -10,6 +10,7 @@ use Shaarli\Config\ConfigManager;
 use Shaarli\Feed\FeedBuilder;
 use Shaarli\Formatter\FormatterFactory;
 use Shaarli\Front\Controller\Visitor\ErrorController;
+use Shaarli\Front\Controller\Visitor\ErrorNotFoundController;
 use Shaarli\History;
 use Shaarli\Http\HttpAccess;
 use Shaarli\Netscape\NetscapeBookmarkUtils;
@@ -149,6 +150,9 @@ class ContainerBuilder
             );
         };
 
+        $container['notFoundHandler'] = function (ShaarliContainer $container): ErrorNotFoundController {
+            return new ErrorNotFoundController($container);
+        };
         $container['errorHandler'] = function (ShaarliContainer $container): ErrorController {
             return new ErrorController($container);
         };
index 9a9a974a6785bce8077e818607dc75e5dbee7e63..66e669aaed3fd6760c966d0fbfd1689696c74f20 100644 (file)
@@ -24,21 +24,22 @@ use Slim\Container;
 /**
  * Extension of Slim container to document the injected objects.
  *
- * @property string                   $basePath             Shaarli's instance base path (e.g. `/shaarli/`)
+ * @property string                   $basePath              Shaarli's instance base path (e.g. `/shaarli/`)
  * @property BookmarkServiceInterface $bookmarkService
  * @property CookieManager            $cookieManager
  * @property ConfigManager            $conf
- * @property mixed[]                  $environment          $_SERVER automatically injected by Slim
- * @property callable                 $errorHandler         Overrides default Slim exception display
+ * @property mixed[]                  $environment           $_SERVER automatically injected by Slim
+ * @property callable                 $errorHandler          Overrides default Slim exception display
  * @property FeedBuilder              $feedBuilder
  * @property FormatterFactory         $formatterFactory
  * @property History                  $history
  * @property HttpAccess               $httpAccess
  * @property LoginManager             $loginManager
  * @property NetscapeBookmarkUtils    $netscapeBookmarkUtils
+ * @property callable                 $notFoundHandler       Overrides default Slim exception display
  * @property PageBuilder              $pageBuilder
  * @property PageCacheManager         $pageCacheManager
- * @property callable                 $phpErrorHandler      Overrides default Slim PHP error display
+ * @property callable                 $phpErrorHandler       Overrides default Slim PHP error display
  * @property PluginManager            $pluginManager
  * @property SessionManager           $sessionManager
  * @property Thumbnailer              $thumbnailer
index 0e09116e98ddb4ca334455c1db2d69d3b5d3eb69..8e05968199df9e099b61d16c7a3c9494a6e3a672 100644 (file)
@@ -62,6 +62,7 @@ class PluginsController extends ShaarliAdminController
 
             if (isset($parameters['parameters_form'])) {
                 unset($parameters['parameters_form']);
+                unset($parameters['token']);
                 foreach ($parameters as $param => $value) {
                     $this->container->conf->set('plugins.'. $param, escape($value));
                 }
diff --git a/application/front/controller/visitor/ErrorNotFoundController.php b/application/front/controller/visitor/ErrorNotFoundController.php
new file mode 100644 (file)
index 0000000..758dd83
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shaarli\Front\Controller\Visitor;
+
+use Slim\Http\Request;
+use Slim\Http\Response;
+
+/**
+ * Controller used to render the 404 error page.
+ */
+class ErrorNotFoundController extends ShaarliVisitorController
+{
+    public function __invoke(Request $request, Response $response): Response
+    {
+        // Request from the API
+        if (false !== strpos($request->getRequestTarget(), '/api/v1')) {
+            return $response->withStatus(404);
+        }
+
+        // This is required because the middleware is ignored if the route is not found.
+        $this->container->basePath = rtrim($request->getUri()->getBasePath(), '/');
+
+        $this->assignView('error_message', t('Requested page could not be found.'));
+
+        return $response->withStatus(404)->write($this->render('404'));
+    }
+}
index 7881e3bea1675ad02b5d255fca316792cdd81f00..1b2197c9d8d0aa1af56d44842ed18c3fa4f619de 100644 (file)
@@ -100,20 +100,17 @@ class PluginManager
      */
     public function executeHooks($hook, &$data, $params = array())
     {
-        if (!empty($params['target'])) {
-            $data['_PAGE_'] = $params['target'];
-        }
-
-        if (isset($params['loggedin'])) {
-            $data['_LOGGEDIN_'] = $params['loggedin'];
-        }
-
-        if (isset($params['basePath'])) {
-            $data['_BASE_PATH_'] = $params['basePath'];
-        }
-
-        if (isset($params['bookmarkService'])) {
-            $data['_BOOKMARK_SERVICE_'] = $params['bookmarkService'];
+        $metadataParameters = [
+            'target' => '_PAGE_',
+            'loggedin' => '_LOGGEDIN_',
+            'basePath' => '_BASE_PATH_',
+            'bookmarkService' => '_BOOKMARK_SERVICE_',
+        ];
+
+        foreach ($metadataParameters as $parameter => $metaKey) {
+            if (array_key_exists($parameter, $params)) {
+                $data[$metaKey] = $params[$parameter];
+            }
         }
 
         foreach ($this->loadedPlugins as $plugin) {
@@ -128,6 +125,10 @@ class PluginManager
                 }
             }
         }
+
+        foreach ($metadataParameters as $metaKey) {
+            unset($data[$metaKey]);
+        }
     }
 
     /**
index a5d5dbe988ea22ad525ed74a71b5c3d421c2d7ec..3018999c81ec60e4f80a2bc4dc7478f815d6ed59 100644 (file)
@@ -41,17 +41,31 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
 
         $this->assertTrue(function_exists('hook_test_random'));
 
-        $data = array(0 => 'woot');
+        $data = [0 => 'woot'];
         $this->pluginManager->executeHooks('random', $data);
-        $this->assertEquals('woot', $data[1]);
 
-        $data = array(0 => 'woot');
+        static::assertCount(2, $data);
+        static::assertSame('woot', $data[1]);
+
+        $data = [0 => 'woot'];
         $this->pluginManager->executeHooks('random', $data, array('target' => 'test'));
-        $this->assertEquals('page test', $data[1]);
 
-        $data = array(0 => 'woot');
+        static::assertCount(2, $data);
+        static::assertSame('page test', $data[1]);
+
+        $data = [0 => 'woot'];
         $this->pluginManager->executeHooks('random', $data, array('loggedin' => true));
-        $this->assertEquals('loggedin', $data[1]);
+
+        static::assertCount(2, $data);
+        static::assertEquals('loggedin', $data[1]);
+
+        $data = [0 => 'woot'];
+        $this->pluginManager->executeHooks('random', $data, array('loggedin' => null));
+
+        static::assertCount(3, $data);
+        static::assertEquals('loggedin', $data[1]);
+        static::assertArrayHasKey(2, $data);
+        static::assertNull($data[2]);
     }
 
     /**
@@ -78,8 +92,8 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
      */
     public function testPluginNotFound(): void
     {
-        $this->pluginManager->load(array());
-        $this->pluginManager->load(array('nope', 'renope'));
+        $this->pluginManager->load([]);
+        $this->pluginManager->load(['nope', 'renope']);
         $this->addToAssertionCount(1);
     }
 
@@ -89,18 +103,18 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
     public function testGetPluginsMeta(): void
     {
         PluginManager::$PLUGINS_PATH = self::$pluginPath;
-        $this->pluginManager->load(array(self::$pluginName));
+        $this->pluginManager->load([self::$pluginName]);
 
-        $expectedParameters = array(
-            'pop' => array(
+        $expectedParameters = [
+            'pop' => [
                 'value' => '',
                 'desc'  => 'pop description',
-            ),
-            'hip' => array(
+            ],
+            'hip' => [
                 'value' => '',
                 'desc' => '',
-            ),
-        );
+            ],
+        ];
         $meta = $this->pluginManager->getPluginsMeta();
         $this->assertEquals('test plugin', $meta[self::$pluginName]['description']);
         $this->assertEquals($expectedParameters, $meta[self::$pluginName]['parameters']);
index c08010ae915a778e161a424d0ead26a097b20d5e..2047a63adf1bd6143609d854b5d47b44669ea55d 100644 (file)
@@ -10,6 +10,7 @@ use Shaarli\Config\ConfigManager;
 use Shaarli\Feed\FeedBuilder;
 use Shaarli\Formatter\FormatterFactory;
 use Shaarli\Front\Controller\Visitor\ErrorController;
+use Shaarli\Front\Controller\Visitor\ErrorNotFoundController;
 use Shaarli\History;
 use Shaarli\Http\HttpAccess;
 use Shaarli\Netscape\NetscapeBookmarkUtils;
@@ -75,6 +76,7 @@ class ContainerBuilderTest extends TestCase
         static::assertInstanceOf(PageBuilder::class, $container->pageBuilder);
         static::assertInstanceOf(PageCacheManager::class, $container->pageCacheManager);
         static::assertInstanceOf(ErrorController::class, $container->phpErrorHandler);
+        static::assertInstanceOf(ErrorNotFoundController::class, $container->notFoundHandler);
         static::assertInstanceOf(PluginManager::class, $container->pluginManager);
         static::assertInstanceOf(SessionManager::class, $container->sessionManager);
         static::assertInstanceOf(Thumbnailer::class, $container->thumbnailer);
index 5b59285c9916486bdb5719f54c69fcfb94332127..9526474c906e454d6c9672c2e61c8294a7a61326 100644 (file)
@@ -32,7 +32,7 @@ class PluginsControllerTest extends TestCase
         array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES);
     }
 
-    public function tearDown()
+    public function tearDown(): void
     {
         $path = __DIR__ . '/folder';
         array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES);
@@ -125,6 +125,7 @@ class PluginsControllerTest extends TestCase
             'parameters_form' => true,
             'parameter1' => 'blip',
             'parameter2' => 'blop',
+            'token' => 'this parameter should not be saved'
         ];
 
         $request = $this->createMock(Request::class);
@@ -143,7 +144,7 @@ class PluginsControllerTest extends TestCase
             ->with('save_plugin_parameters', $parameters)
         ;
         $this->container->conf
-            ->expects(static::atLeastOnce())
+            ->expects(static::exactly(2))
             ->method('set')
             ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop'])
         ;
diff --git a/tests/front/controller/visitor/ErrorNotFoundControllerTest.php b/tests/front/controller/visitor/ErrorNotFoundControllerTest.php
new file mode 100644 (file)
index 0000000..625467b
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shaarli\Front\Controller\Visitor;
+
+use PHPUnit\Framework\TestCase;
+use Slim\Http\Request;
+use Slim\Http\Response;
+use Slim\Http\Uri;
+
+class ErrorNotFoundControllerTest extends TestCase
+{
+    use FrontControllerMockHelper;
+
+    /** @var ErrorNotFoundController */
+    protected $controller;
+
+    public function setUp(): void
+    {
+        $this->createContainer();
+
+        $this->controller = new ErrorNotFoundController($this->container);
+    }
+
+    /**
+     * Test displaying 404 error
+     */
+    public function testDisplayNotFoundError(): void
+    {
+        $request = $this->createMock(Request::class);
+        $request->expects(static::once())->method('getRequestTarget')->willReturn('/');
+        $request->method('getUri')->willReturnCallback(function (): Uri {
+            $uri = $this->createMock(Uri::class);
+            $uri->method('getBasePath')->willReturn('/subfolder');
+
+            return $uri;
+        });
+
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        $result = ($this->controller)(
+            $request,
+            $response
+        );
+
+        static::assertSame(404, $result->getStatusCode());
+        static::assertSame('404', (string) $result->getBody());
+        static::assertSame('Requested page could not be found.', $assignedVariables['error_message']);
+    }
+
+    /**
+     * Test displaying 404 error from REST API
+     */
+    public function testDisplayNotFoundErrorFromAPI(): void
+    {
+        $request = $this->createMock(Request::class);
+        $request->expects(static::once())->method('getRequestTarget')->willReturn('/sufolder/api/v1/links');
+        $request->method('getUri')->willReturnCallback(function (): Uri {
+            $uri = $this->createMock(Uri::class);
+            $uri->method('getBasePath')->willReturn('/subfolder');
+
+            return $uri;
+        });
+
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        $result = ($this->controller)($request, $response);
+
+        static::assertSame(404, $result->getStatusCode());
+        static::assertSame([], $assignedVariables);
+    }
+}
index fe6ac9b0c246241d16053d7a77546d5daed234e3..6c53289bd01c83ba018003e2bf4dc32a27da1139 100644 (file)
@@ -95,7 +95,6 @@ trait FrontControllerMockHelper
     protected function assignTemplateVars(array &$variables): void
     {
         $this->container->pageBuilder
-            ->expects(static::atLeastOnce())
             ->method('assign')
             ->willReturnCallback(function ($key, $value) use (&$variables) {
                 $variables[$key] = $value;
index ae5032dd36a5b19fc999c387c008ff781481c70c..03be4f4e8c997bd9eb875ad1f42a65bf4d294eb7 100644 (file)
@@ -13,6 +13,9 @@ function hook_test_random($data)
         $data[1] = 'page test';
     } elseif (isset($data['_LOGGEDIN_']) && $data['_LOGGEDIN_'] === true) {
         $data[1] = 'loggedin';
+    } elseif (array_key_exists('_LOGGEDIN_', $data)) {
+        $data[1] = 'loggedin';
+        $data[2] = $data['_LOGGEDIN_'];
     } else {
         $data[1] = $data[0];
     }