]> BookStack Code Mirror - bookstack/commitdiff
Merge branch 'feature/opensearch' into development
authorDan Brown <redacted>
Mon, 30 Sep 2024 16:21:51 +0000 (17:21 +0100)
committerDan Brown <redacted>
Mon, 30 Sep 2024 16:21:51 +0000 (17:21 +0100)
12 files changed:
app/App/MetaController.php
lang/en/common.php
resources/views/layouts/base.blade.php
resources/views/misc/opensearch.blade.php [new file with mode: 0644]
routes/web.php
tests/Meta/HelpTest.php [moved from tests/HelpTest.php with 94% similarity]
tests/Meta/LicensesTest.php [moved from tests/LicensesTest.php with 94% similarity]
tests/Meta/OpenGraphTest.php [moved from tests/OpenGraphTest.php with 98% similarity]
tests/Meta/OpensearchTest.php [new file with mode: 0644]
tests/Meta/PwaManifestTest.php [moved from tests/PwaManifestTest.php with 98% similarity]
tests/Meta/RobotsTest.php [new file with mode: 0644]
tests/PublicActionTest.php

index 1515b4f7eda6ed550bca45bfd5c0ad47f1a801ef..a94334c585184a45baed6ad24a56cf70b845aca7 100644 (file)
@@ -64,4 +64,14 @@ class MetaController extends Controller
             'jsLibData' => file_get_contents(base_path('dev/licensing/js-library-licenses.txt')),
         ]);
     }
+
+    /**
+     * Show the view for /opensearch.xml.
+     */
+    public function opensearch()
+    {
+        return response()
+            ->view('misc.opensearch')
+            ->header('Content-Type', 'application/opensearchdescription+xml');
+    }
 }
index 266174eed9da6bff8f84c28182ad3c1aa705ea6c..b05169bb2c46211f2341d2f13284f2f74459080a 100644 (file)
@@ -107,4 +107,7 @@ return [
     // Not directly used but available for convenience to users.
     'privacy_policy' => 'Privacy Policy',
     'terms_of_service' => 'Terms of Service',
+
+    // OpenSearch
+    'opensearch_description' => 'Search :appName',
 ];
index 4d4d07dc2ac4312b0dfc8da4ae798ad31342a780..ddecb8e76e144042b72076f0cbb2ed299731583a 100644 (file)
@@ -32,6 +32,9 @@
     <link rel="manifest" href="{{ url('/manifest.json') }}">
     <meta name="mobile-web-app-capable" content="yes">
 
+    <!-- OpenSearch -->
+    <link rel="search" type="application/opensearchdescription+xml" title="{{ setting('app-name') }}" href="{{ url('/opensearch.xml') }}">
+
     @yield('head')
 
     <!-- Custom Styles & Head Content -->
diff --git a/resources/views/misc/opensearch.blade.php b/resources/views/misc/opensearch.blade.php
new file mode 100644 (file)
index 0000000..5c1503f
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>{{ mb_strimwidth(setting('app-name'), 0, 16) }}</ShortName>
+  <Description>{{ trans('common.opensearch_description', ['appName' => setting('app-name')]) }}</Description>
+  <Image width="256" height="256" type="image/png">{{ setting('app-icon') ?: url('/icon.png') }}</Image>
+  <Image width="180" height="180" type="image/png">{{ setting('app-icon-180') ?: url('/icon-180.png') }}</Image>
+  <Image width="128" height="128" type="image/png">{{ setting('app-icon-128') ?: url('/icon-128.png') }}</Image>
+  <Image width="64" height="64" type="image/png">{{ setting('app-icon-64') ?: url('/icon-64.png') }}</Image>
+  <Image width="32" height="32" type="image/png">{{ setting('app-icon-32') ?: url('/icon-32.png') }}</Image>
+  <Url type="text/html" rel="results" template="{{ url('/search') }}?term={searchTerms}"/>
+  <Url type="application/opensearchdescription+xml" rel="self" template="{{ url('/opensearch.xml') }}"/>
+</OpenSearchDescription>
index 58b8f4e543107aec56185e4927460d3ce413442c..81b938f32eccbde217f15ded0f9e572935c122bf 100644 (file)
@@ -23,6 +23,7 @@ Route::get('/robots.txt', [MetaController::class, 'robots']);
 Route::get('/favicon.ico', [MetaController::class, 'favicon']);
 Route::get('/manifest.json', [MetaController::class, 'pwaManifest']);
 Route::get('/licenses', [MetaController::class, 'licenses']);
+Route::get('/opensearch.xml', [MetaController::class, 'opensearch']);
 
 // Authenticated routes...
 Route::middleware('auth')->group(function () {
similarity index 94%
rename from tests/HelpTest.php
rename to tests/Meta/HelpTest.php
index 9cf80717fe088ea43865a67cdddd62d5017b0102..e1de96bc8df76a13a2113ecc8ea6f8aecefa22df 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 
-namespace Tests;
+namespace Tests\Meta;
+
+use Tests\TestCase;
 
 class HelpTest extends TestCase
 {
similarity index 94%
rename from tests/LicensesTest.php
rename to tests/Meta/LicensesTest.php
index a7fb803c087f06301b3d494505e722c2da887203..4bee6f682b9aa1c87d1712aa17c2a8d7d0b6f86a 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 
-namespace Tests;
+namespace Tests\Meta;
+
+use Tests\TestCase;
 
 class LicensesTest extends TestCase
 {
similarity index 98%
rename from tests/OpenGraphTest.php
rename to tests/Meta/OpenGraphTest.php
index 545fa4c864c463d94b7b4091685d65dfa34d5028..96e622da052c25a1794f86ff7e4def3a5f58c595 100644 (file)
@@ -1,11 +1,12 @@
 <?php
 
-namespace Tests;
+namespace Tests\Meta;
 
 use BookStack\Entities\Repos\BaseRepo;
 use BookStack\Entities\Repos\BookRepo;
 use Illuminate\Support\Str;
 use Illuminate\Testing\TestResponse;
+use Tests\TestCase;
 
 class OpenGraphTest extends TestCase
 {
diff --git a/tests/Meta/OpensearchTest.php b/tests/Meta/OpensearchTest.php
new file mode 100644 (file)
index 0000000..38e1587
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+
+namespace Tests\Meta;
+
+use Tests\TestCase;
+
+class OpensearchTest extends TestCase
+{
+    public function test_opensearch_endpoint()
+    {
+        $appName = 'MyAppNameThatsReallyLongLikeThis';
+        setting()->put('app-name', $appName);
+        $resultUrl = url('/search') . '?term={searchTerms}';
+        $selfUrl = url('/opensearch.xml');
+
+        $resp = $this->get('/opensearch.xml');
+        $resp->assertOk();
+
+        $html = $this->withHtml($resp);
+
+        $html->assertElementExists('OpenSearchDescription > ShortName');
+        $html->assertElementContains('OpenSearchDescription > ShortName', mb_strimwidth($appName, 0, 16));
+        $html->assertElementNotContains('OpenSearchDescription > ShortName', $appName);
+
+        $html->assertElementExists('OpenSearchDescription > Description');
+        $html->assertElementContains('OpenSearchDescription > Description', "Search {$appName}");
+        $html->assertElementExists('OpenSearchDescription > Image');
+        $html->assertElementExists('OpenSearchDescription > Url[rel="results"][template="' . htmlspecialchars($resultUrl) . '"]');
+        $html->assertElementExists('OpenSearchDescription > Url[rel="self"][template="' . htmlspecialchars($selfUrl) . '"]');
+    }
+
+    public function test_opensearch_linked_to_from_home()
+    {
+        $appName = setting('app-name');
+        $endpointUrl = url('/opensearch.xml');
+
+        $resp = $this->asViewer()->get('/');
+        $html = $this->withHtml($resp);
+
+        $html->assertElementExists('head > link[rel="search"][type="application/opensearchdescription+xml"][title="' . htmlspecialchars($appName) . '"][href="' . htmlspecialchars($endpointUrl) . '"]');
+    }
+}
similarity index 98%
rename from tests/PwaManifestTest.php
rename to tests/Meta/PwaManifestTest.php
index c66f8b36052b18d1c13e1e83a49b97dd1d363916..fc6d19b5459abde5ad9b0c8993b1a6b953466a5c 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 
-namespace Tests;
+namespace Tests\Meta;
+
+use Tests\TestCase;
 
 class PwaManifestTest extends TestCase
 {
diff --git a/tests/Meta/RobotsTest.php b/tests/Meta/RobotsTest.php
new file mode 100644 (file)
index 0000000..04496c3
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+namespace Tests\Meta;
+
+use Tests\TestCase;
+
+class RobotsTest extends TestCase
+{
+    public function test_robots_effected_by_public_status()
+    {
+        $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
+
+        $this->setSettings(['app-public' => 'true']);
+
+        $resp = $this->get('/robots.txt');
+        $resp->assertSee("User-agent: *\nDisallow:");
+        $resp->assertDontSee('Disallow: /');
+    }
+
+    public function test_robots_effected_by_setting()
+    {
+        $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
+
+        config()->set('app.allow_robots', true);
+
+        $resp = $this->get('/robots.txt');
+        $resp->assertSee("User-agent: *\nDisallow:");
+        $resp->assertDontSee('Disallow: /');
+
+        // Check config overrides app-public setting
+        config()->set('app.allow_robots', false);
+        $this->setSettings(['app-public' => 'true']);
+        $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
+    }
+}
index 875b279a81c381d2394da96d4b7892bc161ee9b6..76745aaac72c999ddfa78eb22284788253c5dd34 100644 (file)
@@ -128,33 +128,6 @@ class PublicActionTest extends TestCase
         $resp->assertDontSee($page->name);
     }
 
-    public function test_robots_effected_by_public_status()
-    {
-        $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
-
-        $this->setSettings(['app-public' => 'true']);
-
-        $resp = $this->get('/robots.txt');
-        $resp->assertSee("User-agent: *\nDisallow:");
-        $resp->assertDontSee('Disallow: /');
-    }
-
-    public function test_robots_effected_by_setting()
-    {
-        $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
-
-        config()->set('app.allow_robots', true);
-
-        $resp = $this->get('/robots.txt');
-        $resp->assertSee("User-agent: *\nDisallow:");
-        $resp->assertDontSee('Disallow: /');
-
-        // Check config overrides app-public setting
-        config()->set('app.allow_robots', false);
-        $this->setSettings(['app-public' => 'true']);
-        $this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
-    }
-
     public function test_default_favicon_file_created_upon_access()
     {
         $faviconPath = public_path('favicon.ico');