]> BookStack Code Mirror - bookstack/commitdiff
Added inbound references listing for pages
authorDan Brown <redacted>
Fri, 19 Aug 2022 12:14:43 +0000 (13:14 +0100)
committerDan Brown <redacted>
Fri, 19 Aug 2022 12:14:43 +0000 (13:14 +0100)
app/Http/Controllers/ReferenceController.php [new file with mode: 0644]
resources/icons/popular.svg
resources/icons/reference.svg [new file with mode: 0644]
resources/lang/en/entities.php
resources/views/pages/references.blade.php [new file with mode: 0644]
routes/web.php

diff --git a/app/Http/Controllers/ReferenceController.php b/app/Http/Controllers/ReferenceController.php
new file mode 100644 (file)
index 0000000..bed2c5f
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+
+namespace BookStack\Http\Controllers;
+
+use BookStack\Auth\Permissions\PermissionApplicator;
+use BookStack\Entities\Models\Page;
+use Illuminate\Database\Eloquent\Relations\Relation;
+
+class ReferenceController extends Controller
+{
+
+    protected PermissionApplicator $permissions;
+
+    public function __construct(PermissionApplicator $permissions)
+    {
+        $this->permissions = $permissions;
+    }
+
+    /**
+     * Display the references to a given page.
+     */
+    public function page(string $bookSlug, string $pageSlug)
+    {
+        /** @var Page $page */
+        $page = Page::visible()->whereSlugs($bookSlug, $pageSlug)->firstOrFail();
+
+        $baseQuery = $page->referencesTo()
+            ->where('from_type', '=', (new Page())->getMorphClass())
+            ->with([
+                'from' => fn(Relation $query) => $query->select(Page::$listAttributes),
+                'from.book' => fn(Relation $query) => $query->scopes('visible'),
+                'from.chapter' => fn(Relation $query) => $query->scopes('visible')
+            ]);
+
+        $references = $this->permissions->restrictEntityRelationQuery(
+            $baseQuery,
+            'references',
+            'from_id',
+            'from_type'
+        )->get();
+
+        return view('pages.references', [
+            'page' => $page,
+            'references' => $references,
+        ]);
+    }
+}
index ba1f918a51274fb920c068bcb9c0259966e4820a..2ac44f151d747c6a9b3813d6940c422c29871c4d 100644 (file)
@@ -1,4 +1,3 @@
 <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
     <path d="M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 17.41 3.8 13.5.67zM11.71 19c-1.78 0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 4.04 0 2.65-2.15 4.8-4.8 4.8z"/>
-    <path d="M0 0h24v24H0z" fill="none"/>
 </svg>
\ No newline at end of file
diff --git a/resources/icons/reference.svg b/resources/icons/reference.svg
new file mode 100644 (file)
index 0000000..560ec5f
--- /dev/null
@@ -0,0 +1,3 @@
+<svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
+ <path d="m24 44.15c-0.4 0-0.79167-0.06667-1.175-0.2-0.38333-0.13333-0.70833-0.33333-0.975-0.6l-17.2-17.2c-0.26667-0.26667-0.46667-0.59167-0.6-0.975s-0.2-0.775-0.2-1.175 0.066667-0.79167 0.2-1.175c0.13333-0.38333 0.33333-0.70833 0.6-0.975l17.2-17.2c0.26667-0.26667 0.59167-0.46667 0.975-0.6s0.775-0.2 1.175-0.2 0.79167 0.066667 1.175 0.2c0.38333 0.13333 0.70833 0.33333 0.975 0.6l17.2 17.2c0.26667 0.26667 0.46667 0.59167 0.6 0.975s0.2 0.775 0.2 1.175-0.06667 0.79167-0.2 1.175c-0.13333 0.38333-0.33333 0.70833-0.6 0.975l-17.2 17.2c-0.26667 0.26667-0.59167 0.46667-0.975 0.6s-0.775 0.2-1.175 0.2zm4.05-18.65-5.15 5.15c-0.3 0.3-0.44167 0.65-0.425 1.05 0.01667 0.4 0.175 0.75 0.475 1.05s0.65833 0.45 1.075 0.45 0.775-0.15 1.075-0.45l7.7-7.7c0.3-0.3 0.45-0.65 0.45-1.05s-0.15-0.75-0.45-1.05l-7.75-7.75c-0.3-0.3-0.65-0.45-1.05-0.45s-0.75 0.15-1.05 0.45-0.45 0.65833-0.45 1.075 0.15 0.775 0.45 1.075l5.1 5.15h-12.4c-0.43333 0-0.79167 0.14167-1.075 0.425s-0.425 0.64167-0.425 1.075 0.14167 0.79167 0.425 1.075 0.64167 0.425 1.075 0.425z"/>
+</svg>
index db1e8027b0bcbbad46eae95c540ebe8dd55cb3bc..a92b465b8192f7d7566a908d83632902162018a2 100644 (file)
@@ -369,4 +369,9 @@ return [
     'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.',
     'convert_chapter' => 'Convert Chapter',
     'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?',
+
+    // References
+    'references' => 'References',
+    'references_none' => 'There are no tracked references to this item.',
+    'references_to_desc' => 'Shown below are all the known pages in the system that link to this item.',
 ];
diff --git a/resources/views/pages/references.blade.php b/resources/views/pages/references.blade.php
new file mode 100644 (file)
index 0000000..3f35a16
--- /dev/null
@@ -0,0 +1,34 @@
+@extends('layouts.simple')
+
+@section('body')
+
+    <div class="container small">
+
+        <div class="my-s">
+            @include('entities.breadcrumbs', ['crumbs' => [
+                $page->book,
+                $page->chapter,
+                $page,
+                $page->getUrl('/references') => [
+                    'text' => trans('entities.references'),
+                    'icon' => 'reference',
+                ]
+            ]])
+        </div>
+
+        <main class="card content-wrap">
+            <h1 class="list-heading">{{ trans('entities.references') }}</h1>
+            <p>{{ trans('entities.references_to_desc') }}</p>
+
+            @if(count($references) > 0)
+                <div class="book-contents">
+                    @include('entities.list', ['entities' => $references->pluck('from'), 'showPath' => true])
+                </div>
+            @else
+                <p class="text-muted italic">{{ trans('entities.references_none') }}</p>
+            @endif
+
+        </main>
+    </div>
+
+@stop
index 00841365a47df8aa40263952c32621602ce041fc..a16960283b15977d0ef7b6e178fbcf55c95dcd4e 100644 (file)
@@ -20,6 +20,7 @@ use BookStack\Http\Controllers\PageExportController;
 use BookStack\Http\Controllers\PageRevisionController;
 use BookStack\Http\Controllers\PageTemplateController;
 use BookStack\Http\Controllers\RecycleBinController;
+use BookStack\Http\Controllers\ReferenceController;
 use BookStack\Http\Controllers\RoleController;
 use BookStack\Http\Controllers\SearchController;
 use BookStack\Http\Controllers\SettingController;
@@ -110,6 +111,7 @@ Route::middleware('auth')->group(function () {
     Route::get('/books/{bookSlug}/draft/{pageId}/delete', [PageController::class, 'showDeleteDraft']);
     Route::get('/books/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'showPermissions']);
     Route::put('/books/{bookSlug}/page/{pageSlug}/permissions', [PageController::class, 'permissions']);
+    Route::get('/books/{bookSlug}/page/{pageSlug}/references', [ReferenceController::class, 'page']);
     Route::put('/books/{bookSlug}/page/{pageSlug}', [PageController::class, 'update']);
     Route::delete('/books/{bookSlug}/page/{pageSlug}', [PageController::class, 'destroy']);
     Route::delete('/books/{bookSlug}/draft/{pageId}', [PageController::class, 'destroyDraft']);