diff options
-rw-r--r-- | application/front/controllers/OpenSearchController.php | 28 | ||||
-rw-r--r-- | index.php | 5 | ||||
-rw-r--r-- | tests/front/controller/OpenSearchControllerTest.php | 92 | ||||
-rw-r--r-- | tpl/default/feed.atom.html | 2 | ||||
-rw-r--r-- | tpl/default/feed.rss.html | 4 | ||||
-rw-r--r-- | tpl/default/includes.html | 3 | ||||
-rw-r--r-- | tpl/vintage/feed.atom.html | 4 | ||||
-rw-r--r-- | tpl/vintage/feed.rss.html | 2 | ||||
-rw-r--r-- | tpl/vintage/includes.html | 3 |
9 files changed, 134 insertions, 9 deletions
diff --git a/application/front/controllers/OpenSearchController.php b/application/front/controllers/OpenSearchController.php new file mode 100644 index 00000000..fa32c5f1 --- /dev/null +++ b/application/front/controllers/OpenSearchController.php | |||
@@ -0,0 +1,28 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller; | ||
6 | |||
7 | use Slim\Http\Request; | ||
8 | use Slim\Http\Response; | ||
9 | |||
10 | /** | ||
11 | * Class OpenSearchController | ||
12 | * | ||
13 | * Slim controller used to render open search template. | ||
14 | * This allows to add Shaarli as a search engine within the browser. | ||
15 | * | ||
16 | * @package front\controllers | ||
17 | */ | ||
18 | class OpenSearchController extends ShaarliController | ||
19 | { | ||
20 | public function index(Request $request, Response $response): Response | ||
21 | { | ||
22 | $response = $response->withHeader('Content-Type', 'application/opensearchdescription+xml; charset=utf-8'); | ||
23 | |||
24 | $this->assignView('serverurl', index_url($this->container->environment)); | ||
25 | |||
26 | return $response->write($this->render('opensearch')); | ||
27 | } | ||
28 | } | ||
@@ -439,9 +439,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM | |||
439 | 439 | ||
440 | // Display opensearch plugin (XML) | 440 | // Display opensearch plugin (XML) |
441 | if ($targetPage == Router::$PAGE_OPENSEARCH) { | 441 | if ($targetPage == Router::$PAGE_OPENSEARCH) { |
442 | header('Content-Type: application/xml; charset=utf-8'); | 442 | header('Location: ./open-search'); |
443 | $PAGE->assign('serverurl', index_url($_SERVER)); | ||
444 | $PAGE->renderPage('opensearch'); | ||
445 | exit; | 443 | exit; |
446 | } | 444 | } |
447 | 445 | ||
@@ -1575,6 +1573,7 @@ $app->group('', function () { | |||
1575 | $this->get('/daily-rss', '\Shaarli\Front\Controller\DailyController:rss')->setName('dailyrss'); | 1573 | $this->get('/daily-rss', '\Shaarli\Front\Controller\DailyController:rss')->setName('dailyrss'); |
1576 | $this->get('/feed-atom', '\Shaarli\Front\Controller\FeedController:atom')->setName('feedatom'); | 1574 | $this->get('/feed-atom', '\Shaarli\Front\Controller\FeedController:atom')->setName('feedatom'); |
1577 | $this->get('/feed-rss', '\Shaarli\Front\Controller\FeedController:rss')->setName('feedrss'); | 1575 | $this->get('/feed-rss', '\Shaarli\Front\Controller\FeedController:rss')->setName('feedrss'); |
1576 | $this->get('/open-search', '\Shaarli\Front\Controller\OpenSearchController:index')->setName('opensearch'); | ||
1578 | 1577 | ||
1579 | $this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\TagController:addTag')->setName('add-tag'); | 1578 | $this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\TagController:addTag')->setName('add-tag'); |
1580 | })->add('\Shaarli\Front\ShaarliMiddleware'); | 1579 | })->add('\Shaarli\Front\ShaarliMiddleware'); |
diff --git a/tests/front/controller/OpenSearchControllerTest.php b/tests/front/controller/OpenSearchControllerTest.php new file mode 100644 index 00000000..7ba0f7df --- /dev/null +++ b/tests/front/controller/OpenSearchControllerTest.php | |||
@@ -0,0 +1,92 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace front\controller; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
9 | use Shaarli\Container\ShaarliContainer; | ||
10 | use Shaarli\Front\Controller\OpenSearchController; | ||
11 | use Shaarli\Plugin\PluginManager; | ||
12 | use Shaarli\Render\PageBuilder; | ||
13 | use Shaarli\Security\LoginManager; | ||
14 | use Slim\Http\Request; | ||
15 | use Slim\Http\Response; | ||
16 | |||
17 | class OpenSearchControllerTest extends TestCase | ||
18 | { | ||
19 | /** @var ShaarliContainer */ | ||
20 | protected $container; | ||
21 | |||
22 | /** @var OpenSearchController */ | ||
23 | protected $controller; | ||
24 | |||
25 | public function setUp(): void | ||
26 | { | ||
27 | $this->container = $this->createMock(ShaarliContainer::class); | ||
28 | $this->controller = new OpenSearchController($this->container); | ||
29 | } | ||
30 | |||
31 | public function testOpenSearchController(): void | ||
32 | { | ||
33 | $this->createValidContainerMockSet(); | ||
34 | |||
35 | $request = $this->createMock(Request::class); | ||
36 | $response = new Response(); | ||
37 | |||
38 | // Save RainTPL assigned variables | ||
39 | $assignedVariables = []; | ||
40 | $this->assignTemplateVars($assignedVariables); | ||
41 | |||
42 | $result = $this->controller->index($request, $response); | ||
43 | |||
44 | static::assertSame(200, $result->getStatusCode()); | ||
45 | static::assertStringContainsString('application/xml', $result->getHeader('Content-Type')[0]); | ||
46 | static::assertSame('opensearch', (string) $result->getBody()); | ||
47 | static::assertSame('http://shaarli', $assignedVariables['serverurl']); | ||
48 | } | ||
49 | |||
50 | protected function createValidContainerMockSet(): void | ||
51 | { | ||
52 | $loginManager = $this->createMock(LoginManager::class); | ||
53 | $this->container->loginManager = $loginManager; | ||
54 | |||
55 | // PageBuilder | ||
56 | $pageBuilder = $this->createMock(PageBuilder::class); | ||
57 | $pageBuilder | ||
58 | ->method('render') | ||
59 | ->willReturnCallback(function (string $template): string { | ||
60 | return $template; | ||
61 | }) | ||
62 | ; | ||
63 | $this->container->pageBuilder = $pageBuilder; | ||
64 | |||
65 | $bookmarkService = $this->createMock(BookmarkServiceInterface::class); | ||
66 | $this->container->bookmarkService = $bookmarkService; | ||
67 | |||
68 | // Plugin Manager | ||
69 | $pluginManager = $this->createMock(PluginManager::class); | ||
70 | $this->container->pluginManager = $pluginManager; | ||
71 | |||
72 | // $_SERVER | ||
73 | $this->container->environment = [ | ||
74 | 'SERVER_NAME' => 'shaarli', | ||
75 | 'SERVER_PORT' => '80', | ||
76 | 'REQUEST_URI' => '/open-search', | ||
77 | ]; | ||
78 | } | ||
79 | |||
80 | protected function assignTemplateVars(array &$variables): void | ||
81 | { | ||
82 | $this->container->pageBuilder | ||
83 | ->expects(static::atLeastOnce()) | ||
84 | ->method('assign') | ||
85 | ->willReturnCallback(function ($key, $value) use (&$variables) { | ||
86 | $variables[$key] = $value; | ||
87 | |||
88 | return $this; | ||
89 | }) | ||
90 | ; | ||
91 | } | ||
92 | } | ||
diff --git a/tpl/default/feed.atom.html b/tpl/default/feed.atom.html index bcfa7012..dd58bd1e 100644 --- a/tpl/default/feed.atom.html +++ b/tpl/default/feed.atom.html | |||
@@ -6,6 +6,8 @@ | |||
6 | <updated>{$last_update}</updated> | 6 | <updated>{$last_update}</updated> |
7 | {/if} | 7 | {/if} |
8 | <link rel="self" href="{$self_link}#" /> | 8 | <link rel="self" href="{$self_link}#" /> |
9 | <link rel="search" type="application/opensearchdescription+xml" href="{$index_url}open-search#" | ||
10 | title="Shaarli search - {$shaarlititle}" /> | ||
9 | {loop="$plugins_feed_header"} | 11 | {loop="$plugins_feed_header"} |
10 | {$value} | 12 | {$value} |
11 | {/loop} | 13 | {/loop} |
diff --git a/tpl/default/feed.rss.html b/tpl/default/feed.rss.html index 66d9a869..85cec7f3 100644 --- a/tpl/default/feed.rss.html +++ b/tpl/default/feed.rss.html | |||
@@ -7,7 +7,9 @@ | |||
7 | <language>{$language}</language> | 7 | <language>{$language}</language> |
8 | <copyright>{$index_url}</copyright> | 8 | <copyright>{$index_url}</copyright> |
9 | <generator>Shaarli</generator> | 9 | <generator>Shaarli</generator> |
10 | <atom:link rel="self" href="{$self_link}" /> | 10 | <atom:link rel="self" href="{$self_link}" /> |
11 | <atom:link rel="search" type="application/opensearchdescription+xml" href="{$index_url}open-search#" | ||
12 | title="Shaarli search - {$shaarlititle}" /> | ||
11 | {loop="$plugins_feed_header"} | 13 | {loop="$plugins_feed_header"} |
12 | {$value} | 14 | {$value} |
13 | {/loop} | 15 | {/loop} |
diff --git a/tpl/default/includes.html b/tpl/default/includes.html index cdbfeea1..07a487bb 100644 --- a/tpl/default/includes.html +++ b/tpl/default/includes.html | |||
@@ -17,7 +17,8 @@ | |||
17 | {if="is_file('data/user.css')"} | 17 | {if="is_file('data/user.css')"} |
18 | <link type="text/css" rel="stylesheet" href="data/user.css#" /> | 18 | <link type="text/css" rel="stylesheet" href="data/user.css#" /> |
19 | {/if} | 19 | {/if} |
20 | <link rel="search" type="application/opensearchdescription+xml" href="./?do=opensearch#" title="Shaarli search - {$shaarlititle}"/> | 20 | <link rel="search" type="application/opensearchdescription+xml" href="./open-search#" |
21 | title="Shaarli search - {$shaarlititle}" /> | ||
21 | {if="! empty($links) && count($links) === 1"} | 22 | {if="! empty($links) && count($links) === 1"} |
22 | {$link=reset($links)} | 23 | {$link=reset($links)} |
23 | <meta property="og:title" content="{$link.title}" /> | 24 | <meta property="og:title" content="{$link.title}" /> |
diff --git a/tpl/vintage/feed.atom.html b/tpl/vintage/feed.atom.html index 0621cb9e..5919bb49 100644 --- a/tpl/vintage/feed.atom.html +++ b/tpl/vintage/feed.atom.html | |||
@@ -6,8 +6,8 @@ | |||
6 | <updated>{$last_update}</updated> | 6 | <updated>{$last_update}</updated> |
7 | {/if} | 7 | {/if} |
8 | <link rel="self" href="{$self_link}#" /> | 8 | <link rel="self" href="{$self_link}#" /> |
9 | <link rel="search" type="application/opensearchdescription+xml" href="{$index_url}?do=opensearch#" | 9 | <link rel="search" type="application/opensearchdescription+xml" href="{$index_url}open-search#" |
10 | title="Shaarli search - {$shaarlititle}" /> | 10 | title="Shaarli search - {$shaarlititle}" /> |
11 | {loop="$feed_plugins_header"} | 11 | {loop="$feed_plugins_header"} |
12 | {$value} | 12 | {$value} |
13 | {/loop} | 13 | {/loop} |
diff --git a/tpl/vintage/feed.rss.html b/tpl/vintage/feed.rss.html index ee3fef88..4be8202f 100644 --- a/tpl/vintage/feed.rss.html +++ b/tpl/vintage/feed.rss.html | |||
@@ -8,7 +8,7 @@ | |||
8 | <copyright>{$index_url}</copyright> | 8 | <copyright>{$index_url}</copyright> |
9 | <generator>Shaarli</generator> | 9 | <generator>Shaarli</generator> |
10 | <atom:link rel="self" href="{$self_link}" /> | 10 | <atom:link rel="self" href="{$self_link}" /> |
11 | <atom:link rel="search" type="application/opensearchdescription+xml" href="{$index_url}?do=opensearch#" | 11 | <atom:link rel="search" type="application/opensearchdescription+xml" href="{$index_url}open-search#" |
12 | title="Shaarli search - {$shaarlititle}" /> | 12 | title="Shaarli search - {$shaarlititle}" /> |
13 | {loop="$feed_plugins_header"} | 13 | {loop="$feed_plugins_header"} |
14 | {$value} | 14 | {$value} |
diff --git a/tpl/vintage/includes.html b/tpl/vintage/includes.html index cf56ca61..61448eaf 100644 --- a/tpl/vintage/includes.html +++ b/tpl/vintage/includes.html | |||
@@ -14,7 +14,8 @@ | |||
14 | <link type="text/css" rel="stylesheet" href="{$value}#"/> | 14 | <link type="text/css" rel="stylesheet" href="{$value}#"/> |
15 | {/loop} | 15 | {/loop} |
16 | {if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="data/user.css#" />{/if} | 16 | {if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="data/user.css#" />{/if} |
17 | <link rel="search" type="application/opensearchdescription+xml" href="./?do=opensearch#" title="Shaarli search - {$shaarlititle|htmlspecialchars}"/> | 17 | <link rel="search" type="application/opensearchdescription+xml" href="./open-search#" |
18 | title="Shaarli search - {$shaarlititle|htmlspecialchars}" /> | ||
18 | {if="! empty($links) && count($links) === 1"} | 19 | {if="! empty($links) && count($links) === 1"} |
19 | {$link=reset($links)} | 20 | {$link=reset($links)} |
20 | <meta property="og:title" content="{$link.title}" /> | 21 | <meta property="og:title" content="{$link.title}" /> |