aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.htaccess18
-rw-r--r--application/container/ContainerBuilder.php4
-rw-r--r--application/container/ShaarliContainer.php9
-rw-r--r--application/front/controller/admin/PluginsController.php1
-rw-r--r--application/front/controller/visitor/ErrorNotFoundController.php29
-rw-r--r--application/plugin/PluginManager.php29
-rw-r--r--tests/PluginManagerTest.php44
-rw-r--r--tests/container/ContainerBuilderTest.php2
-rw-r--r--tests/front/controller/admin/PluginsControllerTest.php5
-rw-r--r--tests/front/controller/visitor/ErrorNotFoundControllerTest.php81
-rw-r--r--tests/front/controller/visitor/FrontControllerMockHelper.php1
-rw-r--r--tests/plugins/test/test.php3
12 files changed, 173 insertions, 53 deletions
diff --git a/.htaccess b/.htaccess
index 8876e346..af2dc5a7 100644
--- a/.htaccess
+++ b/.htaccess
@@ -16,23 +16,7 @@ RewriteCond %{REQUEST_FILENAME} !-f
16RewriteCond %{REQUEST_FILENAME} !-d 16RewriteCond %{REQUEST_FILENAME} !-d
17RewriteRule ^ index.php [QSA,L] 17RewriteRule ^ index.php [QSA,L]
18 18
19<Limit GET POST PUT DELETE OPTIONS> 19<LimitExcept GET POST PUT DELETE PATCH OPTIONS>
20 <IfModule version_module>
21 <IfVersion >= 2.4>
22 Require all granted
23 </IfVersion>
24 <IfVersion < 2.4>
25 Allow from all
26 Deny from none
27 </IfVersion>
28 </IfModule>
29
30 <IfModule !version_module>
31 Require all granted
32 </IfModule>
33</Limit>
34
35<LimitExcept GET POST PUT DELETE OPTIONS>
36 <IfModule version_module> 20 <IfModule version_module>
37 <IfVersion >= 2.4> 21 <IfVersion >= 2.4>
38 Require all denied 22 Require all denied
diff --git a/application/container/ContainerBuilder.php b/application/container/ContainerBuilder.php
index 58067c99..55bb51b5 100644
--- a/application/container/ContainerBuilder.php
+++ b/application/container/ContainerBuilder.php
@@ -10,6 +10,7 @@ use Shaarli\Config\ConfigManager;
10use Shaarli\Feed\FeedBuilder; 10use Shaarli\Feed\FeedBuilder;
11use Shaarli\Formatter\FormatterFactory; 11use Shaarli\Formatter\FormatterFactory;
12use Shaarli\Front\Controller\Visitor\ErrorController; 12use Shaarli\Front\Controller\Visitor\ErrorController;
13use Shaarli\Front\Controller\Visitor\ErrorNotFoundController;
13use Shaarli\History; 14use Shaarli\History;
14use Shaarli\Http\HttpAccess; 15use Shaarli\Http\HttpAccess;
15use Shaarli\Netscape\NetscapeBookmarkUtils; 16use Shaarli\Netscape\NetscapeBookmarkUtils;
@@ -149,6 +150,9 @@ class ContainerBuilder
149 ); 150 );
150 }; 151 };
151 152
153 $container['notFoundHandler'] = function (ShaarliContainer $container): ErrorNotFoundController {
154 return new ErrorNotFoundController($container);
155 };
152 $container['errorHandler'] = function (ShaarliContainer $container): ErrorController { 156 $container['errorHandler'] = function (ShaarliContainer $container): ErrorController {
153 return new ErrorController($container); 157 return new ErrorController($container);
154 }; 158 };
diff --git a/application/container/ShaarliContainer.php b/application/container/ShaarliContainer.php
index 9a9a974a..66e669aa 100644
--- a/application/container/ShaarliContainer.php
+++ b/application/container/ShaarliContainer.php
@@ -24,21 +24,22 @@ use Slim\Container;
24/** 24/**
25 * Extension of Slim container to document the injected objects. 25 * Extension of Slim container to document the injected objects.
26 * 26 *
27 * @property string $basePath Shaarli's instance base path (e.g. `/shaarli/`) 27 * @property string $basePath Shaarli's instance base path (e.g. `/shaarli/`)
28 * @property BookmarkServiceInterface $bookmarkService 28 * @property BookmarkServiceInterface $bookmarkService
29 * @property CookieManager $cookieManager 29 * @property CookieManager $cookieManager
30 * @property ConfigManager $conf 30 * @property ConfigManager $conf
31 * @property mixed[] $environment $_SERVER automatically injected by Slim 31 * @property mixed[] $environment $_SERVER automatically injected by Slim
32 * @property callable $errorHandler Overrides default Slim exception display 32 * @property callable $errorHandler Overrides default Slim exception display
33 * @property FeedBuilder $feedBuilder 33 * @property FeedBuilder $feedBuilder
34 * @property FormatterFactory $formatterFactory 34 * @property FormatterFactory $formatterFactory
35 * @property History $history 35 * @property History $history
36 * @property HttpAccess $httpAccess 36 * @property HttpAccess $httpAccess
37 * @property LoginManager $loginManager 37 * @property LoginManager $loginManager
38 * @property NetscapeBookmarkUtils $netscapeBookmarkUtils 38 * @property NetscapeBookmarkUtils $netscapeBookmarkUtils
39 * @property callable $notFoundHandler Overrides default Slim exception display
39 * @property PageBuilder $pageBuilder 40 * @property PageBuilder $pageBuilder
40 * @property PageCacheManager $pageCacheManager 41 * @property PageCacheManager $pageCacheManager
41 * @property callable $phpErrorHandler Overrides default Slim PHP error display 42 * @property callable $phpErrorHandler Overrides default Slim PHP error display
42 * @property PluginManager $pluginManager 43 * @property PluginManager $pluginManager
43 * @property SessionManager $sessionManager 44 * @property SessionManager $sessionManager
44 * @property Thumbnailer $thumbnailer 45 * @property Thumbnailer $thumbnailer
diff --git a/application/front/controller/admin/PluginsController.php b/application/front/controller/admin/PluginsController.php
index 0e09116e..8e059681 100644
--- a/application/front/controller/admin/PluginsController.php
+++ b/application/front/controller/admin/PluginsController.php
@@ -62,6 +62,7 @@ class PluginsController extends ShaarliAdminController
62 62
63 if (isset($parameters['parameters_form'])) { 63 if (isset($parameters['parameters_form'])) {
64 unset($parameters['parameters_form']); 64 unset($parameters['parameters_form']);
65 unset($parameters['token']);
65 foreach ($parameters as $param => $value) { 66 foreach ($parameters as $param => $value) {
66 $this->container->conf->set('plugins.'. $param, escape($value)); 67 $this->container->conf->set('plugins.'. $param, escape($value));
67 } 68 }
diff --git a/application/front/controller/visitor/ErrorNotFoundController.php b/application/front/controller/visitor/ErrorNotFoundController.php
new file mode 100644
index 00000000..758dd83b
--- /dev/null
+++ b/application/front/controller/visitor/ErrorNotFoundController.php
@@ -0,0 +1,29 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use Slim\Http\Request;
8use Slim\Http\Response;
9
10/**
11 * Controller used to render the 404 error page.
12 */
13class ErrorNotFoundController extends ShaarliVisitorController
14{
15 public function __invoke(Request $request, Response $response): Response
16 {
17 // Request from the API
18 if (false !== strpos($request->getRequestTarget(), '/api/v1')) {
19 return $response->withStatus(404);
20 }
21
22 // This is required because the middleware is ignored if the route is not found.
23 $this->container->basePath = rtrim($request->getUri()->getBasePath(), '/');
24
25 $this->assignView('error_message', t('Requested page could not be found.'));
26
27 return $response->withStatus(404)->write($this->render('404'));
28 }
29}
diff --git a/application/plugin/PluginManager.php b/application/plugin/PluginManager.php
index 7881e3be..1b2197c9 100644
--- a/application/plugin/PluginManager.php
+++ b/application/plugin/PluginManager.php
@@ -100,20 +100,17 @@ class PluginManager
100 */ 100 */
101 public function executeHooks($hook, &$data, $params = array()) 101 public function executeHooks($hook, &$data, $params = array())
102 { 102 {
103 if (!empty($params['target'])) { 103 $metadataParameters = [
104 $data['_PAGE_'] = $params['target']; 104 'target' => '_PAGE_',
105 } 105 'loggedin' => '_LOGGEDIN_',
106 106 'basePath' => '_BASE_PATH_',
107 if (isset($params['loggedin'])) { 107 'bookmarkService' => '_BOOKMARK_SERVICE_',
108 $data['_LOGGEDIN_'] = $params['loggedin']; 108 ];
109 } 109
110 110 foreach ($metadataParameters as $parameter => $metaKey) {
111 if (isset($params['basePath'])) { 111 if (array_key_exists($parameter, $params)) {
112 $data['_BASE_PATH_'] = $params['basePath']; 112 $data[$metaKey] = $params[$parameter];
113 } 113 }
114
115 if (isset($params['bookmarkService'])) {
116 $data['_BOOKMARK_SERVICE_'] = $params['bookmarkService'];
117 } 114 }
118 115
119 foreach ($this->loadedPlugins as $plugin) { 116 foreach ($this->loadedPlugins as $plugin) {
@@ -128,6 +125,10 @@ class PluginManager
128 } 125 }
129 } 126 }
130 } 127 }
128
129 foreach ($metadataParameters as $metaKey) {
130 unset($data[$metaKey]);
131 }
131 } 132 }
132 133
133 /** 134 /**
diff --git a/tests/PluginManagerTest.php b/tests/PluginManagerTest.php
index a5d5dbe9..3018999c 100644
--- a/tests/PluginManagerTest.php
+++ b/tests/PluginManagerTest.php
@@ -41,17 +41,31 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
41 41
42 $this->assertTrue(function_exists('hook_test_random')); 42 $this->assertTrue(function_exists('hook_test_random'));
43 43
44 $data = array(0 => 'woot'); 44 $data = [0 => 'woot'];
45 $this->pluginManager->executeHooks('random', $data); 45 $this->pluginManager->executeHooks('random', $data);
46 $this->assertEquals('woot', $data[1]);
47 46
48 $data = array(0 => 'woot'); 47 static::assertCount(2, $data);
48 static::assertSame('woot', $data[1]);
49
50 $data = [0 => 'woot'];
49 $this->pluginManager->executeHooks('random', $data, array('target' => 'test')); 51 $this->pluginManager->executeHooks('random', $data, array('target' => 'test'));
50 $this->assertEquals('page test', $data[1]);
51 52
52 $data = array(0 => 'woot'); 53 static::assertCount(2, $data);
54 static::assertSame('page test', $data[1]);
55
56 $data = [0 => 'woot'];
53 $this->pluginManager->executeHooks('random', $data, array('loggedin' => true)); 57 $this->pluginManager->executeHooks('random', $data, array('loggedin' => true));
54 $this->assertEquals('loggedin', $data[1]); 58
59 static::assertCount(2, $data);
60 static::assertEquals('loggedin', $data[1]);
61
62 $data = [0 => 'woot'];
63 $this->pluginManager->executeHooks('random', $data, array('loggedin' => null));
64
65 static::assertCount(3, $data);
66 static::assertEquals('loggedin', $data[1]);
67 static::assertArrayHasKey(2, $data);
68 static::assertNull($data[2]);
55 } 69 }
56 70
57 /** 71 /**
@@ -78,8 +92,8 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
78 */ 92 */
79 public function testPluginNotFound(): void 93 public function testPluginNotFound(): void
80 { 94 {
81 $this->pluginManager->load(array()); 95 $this->pluginManager->load([]);
82 $this->pluginManager->load(array('nope', 'renope')); 96 $this->pluginManager->load(['nope', 'renope']);
83 $this->addToAssertionCount(1); 97 $this->addToAssertionCount(1);
84 } 98 }
85 99
@@ -89,18 +103,18 @@ class PluginManagerTest extends \PHPUnit\Framework\TestCase
89 public function testGetPluginsMeta(): void 103 public function testGetPluginsMeta(): void
90 { 104 {
91 PluginManager::$PLUGINS_PATH = self::$pluginPath; 105 PluginManager::$PLUGINS_PATH = self::$pluginPath;
92 $this->pluginManager->load(array(self::$pluginName)); 106 $this->pluginManager->load([self::$pluginName]);
93 107
94 $expectedParameters = array( 108 $expectedParameters = [
95 'pop' => array( 109 'pop' => [
96 'value' => '', 110 'value' => '',
97 'desc' => 'pop description', 111 'desc' => 'pop description',
98 ), 112 ],
99 'hip' => array( 113 'hip' => [
100 'value' => '', 114 'value' => '',
101 'desc' => '', 115 'desc' => '',
102 ), 116 ],
103 ); 117 ];
104 $meta = $this->pluginManager->getPluginsMeta(); 118 $meta = $this->pluginManager->getPluginsMeta();
105 $this->assertEquals('test plugin', $meta[self::$pluginName]['description']); 119 $this->assertEquals('test plugin', $meta[self::$pluginName]['description']);
106 $this->assertEquals($expectedParameters, $meta[self::$pluginName]['parameters']); 120 $this->assertEquals($expectedParameters, $meta[self::$pluginName]['parameters']);
diff --git a/tests/container/ContainerBuilderTest.php b/tests/container/ContainerBuilderTest.php
index c08010ae..2047a63a 100644
--- a/tests/container/ContainerBuilderTest.php
+++ b/tests/container/ContainerBuilderTest.php
@@ -10,6 +10,7 @@ use Shaarli\Config\ConfigManager;
10use Shaarli\Feed\FeedBuilder; 10use Shaarli\Feed\FeedBuilder;
11use Shaarli\Formatter\FormatterFactory; 11use Shaarli\Formatter\FormatterFactory;
12use Shaarli\Front\Controller\Visitor\ErrorController; 12use Shaarli\Front\Controller\Visitor\ErrorController;
13use Shaarli\Front\Controller\Visitor\ErrorNotFoundController;
13use Shaarli\History; 14use Shaarli\History;
14use Shaarli\Http\HttpAccess; 15use Shaarli\Http\HttpAccess;
15use Shaarli\Netscape\NetscapeBookmarkUtils; 16use Shaarli\Netscape\NetscapeBookmarkUtils;
@@ -75,6 +76,7 @@ class ContainerBuilderTest extends TestCase
75 static::assertInstanceOf(PageBuilder::class, $container->pageBuilder); 76 static::assertInstanceOf(PageBuilder::class, $container->pageBuilder);
76 static::assertInstanceOf(PageCacheManager::class, $container->pageCacheManager); 77 static::assertInstanceOf(PageCacheManager::class, $container->pageCacheManager);
77 static::assertInstanceOf(ErrorController::class, $container->phpErrorHandler); 78 static::assertInstanceOf(ErrorController::class, $container->phpErrorHandler);
79 static::assertInstanceOf(ErrorNotFoundController::class, $container->notFoundHandler);
78 static::assertInstanceOf(PluginManager::class, $container->pluginManager); 80 static::assertInstanceOf(PluginManager::class, $container->pluginManager);
79 static::assertInstanceOf(SessionManager::class, $container->sessionManager); 81 static::assertInstanceOf(SessionManager::class, $container->sessionManager);
80 static::assertInstanceOf(Thumbnailer::class, $container->thumbnailer); 82 static::assertInstanceOf(Thumbnailer::class, $container->thumbnailer);
diff --git a/tests/front/controller/admin/PluginsControllerTest.php b/tests/front/controller/admin/PluginsControllerTest.php
index 5b59285c..9526474c 100644
--- a/tests/front/controller/admin/PluginsControllerTest.php
+++ b/tests/front/controller/admin/PluginsControllerTest.php
@@ -32,7 +32,7 @@ class PluginsControllerTest extends TestCase
32 array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES); 32 array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES);
33 } 33 }
34 34
35 public function tearDown() 35 public function tearDown(): void
36 { 36 {
37 $path = __DIR__ . '/folder'; 37 $path = __DIR__ . '/folder';
38 array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES); 38 array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES);
@@ -125,6 +125,7 @@ class PluginsControllerTest extends TestCase
125 'parameters_form' => true, 125 'parameters_form' => true,
126 'parameter1' => 'blip', 126 'parameter1' => 'blip',
127 'parameter2' => 'blop', 127 'parameter2' => 'blop',
128 'token' => 'this parameter should not be saved'
128 ]; 129 ];
129 130
130 $request = $this->createMock(Request::class); 131 $request = $this->createMock(Request::class);
@@ -143,7 +144,7 @@ class PluginsControllerTest extends TestCase
143 ->with('save_plugin_parameters', $parameters) 144 ->with('save_plugin_parameters', $parameters)
144 ; 145 ;
145 $this->container->conf 146 $this->container->conf
146 ->expects(static::atLeastOnce()) 147 ->expects(static::exactly(2))
147 ->method('set') 148 ->method('set')
148 ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop']) 149 ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop'])
149 ; 150 ;
diff --git a/tests/front/controller/visitor/ErrorNotFoundControllerTest.php b/tests/front/controller/visitor/ErrorNotFoundControllerTest.php
new file mode 100644
index 00000000..625467b1
--- /dev/null
+++ b/tests/front/controller/visitor/ErrorNotFoundControllerTest.php
@@ -0,0 +1,81 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Slim\Http\Request;
9use Slim\Http\Response;
10use Slim\Http\Uri;
11
12class ErrorNotFoundControllerTest extends TestCase
13{
14 use FrontControllerMockHelper;
15
16 /** @var ErrorNotFoundController */
17 protected $controller;
18
19 public function setUp(): void
20 {
21 $this->createContainer();
22
23 $this->controller = new ErrorNotFoundController($this->container);
24 }
25
26 /**
27 * Test displaying 404 error
28 */
29 public function testDisplayNotFoundError(): void
30 {
31 $request = $this->createMock(Request::class);
32 $request->expects(static::once())->method('getRequestTarget')->willReturn('/');
33 $request->method('getUri')->willReturnCallback(function (): Uri {
34 $uri = $this->createMock(Uri::class);
35 $uri->method('getBasePath')->willReturn('/subfolder');
36
37 return $uri;
38 });
39
40 $response = new Response();
41
42 // Save RainTPL assigned variables
43 $assignedVariables = [];
44 $this->assignTemplateVars($assignedVariables);
45
46 $result = ($this->controller)(
47 $request,
48 $response
49 );
50
51 static::assertSame(404, $result->getStatusCode());
52 static::assertSame('404', (string) $result->getBody());
53 static::assertSame('Requested page could not be found.', $assignedVariables['error_message']);
54 }
55
56 /**
57 * Test displaying 404 error from REST API
58 */
59 public function testDisplayNotFoundErrorFromAPI(): void
60 {
61 $request = $this->createMock(Request::class);
62 $request->expects(static::once())->method('getRequestTarget')->willReturn('/sufolder/api/v1/links');
63 $request->method('getUri')->willReturnCallback(function (): Uri {
64 $uri = $this->createMock(Uri::class);
65 $uri->method('getBasePath')->willReturn('/subfolder');
66
67 return $uri;
68 });
69
70 $response = new Response();
71
72 // Save RainTPL assigned variables
73 $assignedVariables = [];
74 $this->assignTemplateVars($assignedVariables);
75
76 $result = ($this->controller)($request, $response);
77
78 static::assertSame(404, $result->getStatusCode());
79 static::assertSame([], $assignedVariables);
80 }
81}
diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php
index fe6ac9b0..6c53289b 100644
--- a/tests/front/controller/visitor/FrontControllerMockHelper.php
+++ b/tests/front/controller/visitor/FrontControllerMockHelper.php
@@ -95,7 +95,6 @@ trait FrontControllerMockHelper
95 protected function assignTemplateVars(array &$variables): void 95 protected function assignTemplateVars(array &$variables): void
96 { 96 {
97 $this->container->pageBuilder 97 $this->container->pageBuilder
98 ->expects(static::atLeastOnce())
99 ->method('assign') 98 ->method('assign')
100 ->willReturnCallback(function ($key, $value) use (&$variables) { 99 ->willReturnCallback(function ($key, $value) use (&$variables) {
101 $variables[$key] = $value; 100 $variables[$key] = $value;
diff --git a/tests/plugins/test/test.php b/tests/plugins/test/test.php
index ae5032dd..03be4f4e 100644
--- a/tests/plugins/test/test.php
+++ b/tests/plugins/test/test.php
@@ -13,6 +13,9 @@ function hook_test_random($data)
13 $data[1] = 'page test'; 13 $data[1] = 'page test';
14 } elseif (isset($data['_LOGGEDIN_']) && $data['_LOGGEDIN_'] === true) { 14 } elseif (isset($data['_LOGGEDIN_']) && $data['_LOGGEDIN_'] === true) {
15 $data[1] = 'loggedin'; 15 $data[1] = 'loggedin';
16 } elseif (array_key_exists('_LOGGEDIN_', $data)) {
17 $data[1] = 'loggedin';
18 $data[2] = $data['_LOGGEDIN_'];
16 } else { 19 } else {
17 $data[1] = $data[0]; 20 $data[1] = $data[0];
18 } 21 }