Merge branch 'master' into release

This commit is contained in:
Dan Brown 2017-10-15 19:27:50 +01:00
commit 5a6d544db7
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
12 changed files with 59 additions and 25 deletions

View File

@ -324,9 +324,10 @@ class PageController extends Controller
$page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug); $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
$book = $page->book; $book = $page->book;
$this->checkOwnablePermission('page-delete', $page); $this->checkOwnablePermission('page-delete', $page);
$this->entityRepo->destroyPage($page);
Activity::addMessage('page_delete', $book->id, $page->name); Activity::addMessage('page_delete', $book->id, $page->name);
session()->flash('success', trans('entities.pages_delete_success')); session()->flash('success', trans('entities.pages_delete_success'));
$this->entityRepo->destroyPage($page);
return redirect($book->getUrl()); return redirect($book->getUrl());
} }

View File

@ -4,6 +4,7 @@ use BookStack\Book;
use BookStack\Chapter; use BookStack\Chapter;
use BookStack\Entity; use BookStack\Entity;
use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotFoundException;
use BookStack\Exceptions\NotifyException;
use BookStack\Page; use BookStack\Page;
use BookStack\PageRevision; use BookStack\PageRevision;
use BookStack\Services\AttachmentService; use BookStack\Services\AttachmentService;
@ -1073,6 +1074,7 @@ class EntityRepo
/** /**
* Destroy a given page along with its dependencies. * Destroy a given page along with its dependencies.
* @param Page $page * @param Page $page
* @throws NotifyException
*/ */
public function destroyPage(Page $page) public function destroyPage(Page $page)
{ {
@ -1084,6 +1086,12 @@ class EntityRepo
$this->permissionService->deleteJointPermissionsForEntity($page); $this->permissionService->deleteJointPermissionsForEntity($page);
$this->searchService->deleteEntityTerms($page); $this->searchService->deleteEntityTerms($page);
// Check if set as custom homepage
$customHome = setting('app-homepage', '0:');
if (intval($page->id) === intval(explode(':', $customHome)[0])) {
throw new NotifyException(trans('errors.page_custom_home_deletion'), $page->getUrl());
}
// Delete Attached Files // Delete Attached Files
$attachmentService = app(AttachmentService::class); $attachmentService = app(AttachmentService::class);
foreach ($page->attachments as $attachment) { foreach ($page->attachments as $attachment) {

View File

@ -382,7 +382,7 @@ class SearchService
protected function generateTermArrayFromText($text, $scoreAdjustment = 1) protected function generateTermArrayFromText($text, $scoreAdjustment = 1)
{ {
$tokenMap = []; // {TextToken => OccurrenceCount} $tokenMap = []; // {TextToken => OccurrenceCount}
$splitChars = " \n\t.,"; $splitChars = " \n\t.,!?:;()[]{}<>`'\"";
$token = strtok($text, $splitChars); $token = strtok($text, $splitChars);
while ($token !== false) { while ($token !== false) {

View File

@ -19,6 +19,7 @@ body.flexbox {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
min-height: 0; min-height: 0;
max-width: 100%;
position: relative; position: relative;
&.rows { &.rows {
flex-direction: row; flex-direction: row;

View File

@ -41,6 +41,7 @@ return [
// Pages // Pages
'page_draft_autosave_fail' => 'Failed to save draft. Ensure you have internet connection before saving this page', 'page_draft_autosave_fail' => 'Failed to save draft. Ensure you have internet connection before saving this page',
'page_custom_home_deletion' => 'Cannot delete a page while it is set as a homepage',
// Entities // Entities
'entity_not_found' => 'Entity not found', 'entity_not_found' => 'Entity not found',

View File

@ -91,7 +91,7 @@
@section('body') @section('body')
<div ng-non-bindable class="container small"> <div class="container small">
<h1>{{$book->name}}</h1> <h1>{{$book->name}}</h1>
<div class="book-content" v-show="!searching"> <div class="book-content" v-show="!searching">
<p class="text-muted" v-pre>{!! nl2br(e($book->description)) !!}</p> <p class="text-muted" v-pre>{!! nl2br(e($book->description)) !!}</p>

View File

@ -1,7 +1,7 @@
@extends('sidebar-layout') @extends('sidebar-layout')
@section('toolbar') @section('toolbar')
<div class="col-sm-6 col-xs-3 faded" ng-non-bindable> <div class="col-sm-6 col-xs-3 faded" v-pre>
@include('chapters._breadcrumbs', ['chapter' => $chapter]) @include('chapters._breadcrumbs', ['chapter' => $chapter])
</div> </div>
<div class="col-sm-6 col-xs-9 faded"> <div class="col-sm-6 col-xs-9 faded">
@ -96,13 +96,13 @@
@section('body') @section('body')
<div class="container small" ng-non-bindable > <div class="container small">
<h1>{{ $chapter->name }}</h1> <h1 v-pre>{{ $chapter->name }}</h1>
<div class="chapter-content" v-show="!searching"> <div class="chapter-content" v-show="!searching">
<p class="text-muted">{!! nl2br(e($chapter->description)) !!}</p> <p v-pre class="text-muted">{!! nl2br(e($chapter->description)) !!}</p>
@if(count($pages) > 0) @if(count($pages) > 0)
<div class="page-list"> <div v-pre class="page-list">
<hr> <hr>
@foreach($pages as $page) @foreach($pages as $page)
@include('pages/list-item', ['page' => $page]) @include('pages/list-item', ['page' => $page])
@ -110,7 +110,7 @@
@endforeach @endforeach
</div> </div>
@else @else
<div class="well"> <div v-pre class="well">
<p class="text-muted italic">{{ trans('entities.chapters_empty') }}</p> <p class="text-muted italic">{{ trans('entities.chapters_empty') }}</p>
<p> <p>
@if(userCan('page-create', $chapter)) @if(userCan('page-create', $chapter))

View File

@ -51,7 +51,7 @@
</div> </div>
{{--Title input--}} {{--Title input--}}
<div class="title-input page-title clearfix" ng-non-bindable> <div class="title-input page-title clearfix" v-pre>
<div class="input"> <div class="input">
@include('form/text', ['name' => 'name', 'placeholder' => trans('entities.pages_title')]) @include('form/text', ['name' => 'name', 'placeholder' => trans('entities.pages_title')])
</div> </div>
@ -63,7 +63,7 @@
{{--WYSIWYG Editor--}} {{--WYSIWYG Editor--}}
@if(setting('app-editor') === 'wysiwyg') @if(setting('app-editor') === 'wysiwyg')
<div wysiwyg-editor class="flex-fill flex"> <div wysiwyg-editor class="flex-fill flex">
<textarea id="html-editor" name="html" rows="5" ng-non-bindable <textarea id="html-editor" name="html" rows="5" v-pre
@if($errors->has('html')) class="neg" @endif>@if(isset($model) || old('html')){{htmlspecialchars( old('html') ? old('html') : $model->html)}}@endif</textarea> @if($errors->has('html')) class="neg" @endif>@if(isset($model) || old('html')){{htmlspecialchars( old('html') ? old('html') : $model->html)}}@endif</textarea>
</div> </div>
@ -74,7 +74,7 @@
{{--Markdown Editor--}} {{--Markdown Editor--}}
@if(setting('app-editor') === 'markdown') @if(setting('app-editor') === 'markdown')
<div ng-non-bindable id="markdown-editor" markdown-editor class="flex-fill flex code-fill"> <div v-pre id="markdown-editor" markdown-editor class="flex-fill flex code-fill">
<div class="markdown-editor-wrap"> <div class="markdown-editor-wrap">
<div class="editor-toolbar"> <div class="editor-toolbar">

View File

@ -7,7 +7,7 @@
</div> </div>
@endif @endif
<div class="right" ng-non-bindable> <div class="right" v-pre>
@if($activity->user) @if($activity->user)
<a href="{{ $activity->user->getProfileUrl() }}">{{ $activity->user->name }}</a> <a href="{{ $activity->user->getProfileUrl() }}">{{ $activity->user->name }}</a>
@else @else

View File

@ -1,4 +1,4 @@
<div class="card book-tree" ng-non-bindable> <div class="card book-tree" v-pre>
<h3><i class="zmdi zmdi-book"></i> {{ trans('entities.books_navigation') }}</h3> <h3><i class="zmdi zmdi-book"></i> {{ trans('entities.books_navigation') }}</h3>
<div class="body"> <div class="body">
<ul class="sidebar-page-list menu"> <ul class="sidebar-page-list menu">

View File

@ -33,13 +33,13 @@ class EntitySearchTest extends TestCase
public function test_searching_accents_and_small_terms() public function test_searching_accents_and_small_terms()
{ {
$page = $this->newPage(['name' => 'My new test quaffleachits', 'html' => 'some áéííúü¿¡ test content {a2 orange dog']); $page = $this->newPage(['name' => 'My new test quaffleachits', 'html' => 'some áéííúü¿¡ test content a2 orange dog']);
$this->asEditor(); $this->asEditor();
$accentSearch = $this->get('/search?term=' . urlencode('áéíí')); $accentSearch = $this->get('/search?term=' . urlencode('áéíí'));
$accentSearch->assertStatus(200)->assertSee($page->name); $accentSearch->assertStatus(200)->assertSee($page->name);
$smallSearch = $this->get('/search?term=' . urlencode('{a')); $smallSearch = $this->get('/search?term=' . urlencode('a2'));
$smallSearch->assertStatus(200)->assertSee($page->name); $smallSearch->assertStatus(200)->assertSee($page->name);
} }

View File

@ -16,7 +16,8 @@ class HomepageTest extends TestCase
$homeVisit->assertSee('Recent Activity'); $homeVisit->assertSee('Recent Activity');
} }
public function test_custom_homepage() { public function test_custom_homepage()
{
$this->asEditor(); $this->asEditor();
$name = 'My custom homepage'; $name = 'My custom homepage';
$content = 'This is the body content of my custom homepage.'; $content = 'This is the body content of my custom homepage.';
@ -30,4 +31,26 @@ class HomepageTest extends TestCase
$homeVisit->assertSee('Recently Updated Pages'); $homeVisit->assertSee('Recently Updated Pages');
$homeVisit->assertSee('Recent Activity'); $homeVisit->assertSee('Recent Activity');
} }
public function test_delete_custom_homepage()
{
$this->asEditor();
$name = 'My custom homepage';
$content = 'This is the body content of my custom homepage.';
$customPage = $this->newPage(['name' => $name, 'html' => $content]);
$this->setSettings(['app-homepage' => $customPage->id]);
$homeVisit = $this->get('/');
$homeVisit->assertSee($name);
$pageDeleteReq = $this->delete($customPage->getUrl());
$pageDeleteReq->assertStatus(302);
$pageDeleteReq->assertRedirect($customPage->getUrl());
$pageDeleteReq->assertSessionHas('error');
$pageDeleteReq->assertSessionMissing('success');
$homeVisit = $this->get('/');
$homeVisit->assertSee($name);
$homeVisit->assertStatus(200);
}
} }