aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--application/front/controllers/OpenSearchController.php28
-rw-r--r--index.php5
-rw-r--r--tests/front/controller/OpenSearchControllerTest.php92
-rw-r--r--tpl/default/feed.atom.html2
-rw-r--r--tpl/default/feed.rss.html4
-rw-r--r--tpl/default/includes.html3
-rw-r--r--tpl/vintage/feed.atom.html4
-rw-r--r--tpl/vintage/feed.rss.html2
-rw-r--r--tpl/vintage/includes.html3
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
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller;
6
7use Slim\Http\Request;
8use 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 */
18class 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}
diff --git a/index.php b/index.php
index c3e0a5bf..04ec0d73 100644
--- a/index.php
+++ b/index.php
@@ -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
3declare(strict_types=1);
4
5namespace front\controller;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\BookmarkServiceInterface;
9use Shaarli\Container\ShaarliContainer;
10use Shaarli\Front\Controller\OpenSearchController;
11use Shaarli\Plugin\PluginManager;
12use Shaarli\Render\PageBuilder;
13use Shaarli\Security\LoginManager;
14use Slim\Http\Request;
15use Slim\Http\Response;
16
17class 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}" />