mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-06-04 08:54:33 +08:00
Merge branch 'master' of https://github.com/Abijeet/BookStack
Conflicts: .gitignore
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Comment extends Ownable
|
||||
{
|
||||
@ -32,4 +33,19 @@ class Comment extends Ownable
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function getParentCommentsByPage($pageId, $pageNum = 0, $limit = 0) {
|
||||
$data = ['pageId' => $pageId];
|
||||
$query = static::newQuery();
|
||||
$query->join('users AS u', 'comments.created_by', '=', 'u.id');
|
||||
$query->leftJoin('users AS u1', 'comments.updated_by', '=', 'u1.id');
|
||||
$query->leftJoin('images AS i', 'i.id', '=', 'u.image_id');
|
||||
$query->selectRaw('comments.id, text, html, comments.created_by, comments.updated_by, comments.created_at, comments.updated_at, '
|
||||
. 'u.name AS created_by_name, u1.name AS updated_by_name, '
|
||||
. '(SELECT count(c.id) FROM bookstack.comments c WHERE c.parent_id = comments.id AND page_id = ?) AS cnt_sub_comments, i.url AS avatar ',
|
||||
[$pageId]);
|
||||
$query->whereRaw('page_id = ? AND parent_id IS NULL', [$pageId]);
|
||||
$query->orderBy('created_at');
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
47
app/Console/Commands/ClearActivity.php
Normal file
47
app/Console/Commands/ClearActivity.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Console\Commands;
|
||||
|
||||
use BookStack\Activity;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ClearActivity extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'bookstack:clear-activity';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clear user activity from the system';
|
||||
|
||||
protected $activity;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param Activity $activity
|
||||
*/
|
||||
public function __construct(Activity $activity)
|
||||
{
|
||||
$this->activity = $activity;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->activity->newQuery()->truncate();
|
||||
$this->comment('System activity cleared');
|
||||
}
|
||||
}
|
50
app/Console/Commands/ClearRevisions.php
Normal file
50
app/Console/Commands/ClearRevisions.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Console\Commands;
|
||||
|
||||
use BookStack\PageRevision;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ClearRevisions extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'bookstack:clear-revisions
|
||||
{--a|all : Include active update drafts in deletion}
|
||||
';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clear page revisions';
|
||||
|
||||
protected $pageRevision;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param PageRevision $pageRevision
|
||||
*/
|
||||
public function __construct(PageRevision $pageRevision)
|
||||
{
|
||||
$this->pageRevision = $pageRevision;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$deleteTypes = $this->option('all') ? ['version', 'update_draft'] : ['version'];
|
||||
$this->pageRevision->newQuery()->whereIn('type', $deleteTypes)->delete();
|
||||
$this->comment('Revisions deleted');
|
||||
}
|
||||
}
|
@ -4,21 +4,21 @@ namespace BookStack\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ResetViews extends Command
|
||||
class ClearViews extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'views:reset';
|
||||
protected $signature = 'bookstack:clear-views';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Reset all view-counts for all entities.';
|
||||
protected $description = 'Clear all view-counts for all entities.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
@ -37,5 +37,6 @@ class ResetViews extends Command
|
||||
public function handle()
|
||||
{
|
||||
\Views::resetAll();
|
||||
$this->comment('Views cleared');
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
|
||||
class Inspire extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'inspire';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Display an inspiring quote';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->comment(PHP_EOL.Inspiring::quote().PHP_EOL);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ class RegeneratePermissions extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'permissions:regen';
|
||||
protected $signature = 'bookstack:regenerate-permissions';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -47,5 +47,6 @@ class RegeneratePermissions extends Command
|
||||
public function handle()
|
||||
{
|
||||
$this->permissionService->buildJointPermissions();
|
||||
$this->comment('Permissions regenerated');
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,9 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
\BookStack\Console\Commands\Inspire::class,
|
||||
\BookStack\Console\Commands\ResetViews::class,
|
||||
\BookStack\Console\Commands\ClearViews::class,
|
||||
\BookStack\Console\Commands\ClearActivity::class,
|
||||
\BookStack\Console\Commands\ClearRevisions::class,
|
||||
\BookStack\Console\Commands\RegeneratePermissions::class,
|
||||
];
|
||||
|
||||
@ -26,7 +27,6 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('inspire')
|
||||
->hourly();
|
||||
//
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
use Activity;
|
||||
use BookStack\Repos\EntityRepo;
|
||||
use BookStack\Repos\UserRepo;
|
||||
use BookStack\Services\ExportService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Views;
|
||||
@ -12,16 +13,19 @@ class BookController extends Controller
|
||||
|
||||
protected $entityRepo;
|
||||
protected $userRepo;
|
||||
protected $exportService;
|
||||
|
||||
/**
|
||||
* BookController constructor.
|
||||
* @param EntityRepo $entityRepo
|
||||
* @param UserRepo $userRepo
|
||||
* @param ExportService $exportService
|
||||
*/
|
||||
public function __construct(EntityRepo $entityRepo, UserRepo $userRepo)
|
||||
public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService)
|
||||
{
|
||||
$this->entityRepo = $entityRepo;
|
||||
$this->userRepo = $userRepo;
|
||||
$this->exportService = $exportService;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@ -258,4 +262,49 @@ class BookController extends Controller
|
||||
session()->flash('success', trans('entities.books_permissions_updated'));
|
||||
return redirect($book->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a book as a PDF file.
|
||||
* @param string $bookSlug
|
||||
* @return mixed
|
||||
*/
|
||||
public function exportPdf($bookSlug)
|
||||
{
|
||||
$book = $this->entityRepo->getBySlug('book', $bookSlug);
|
||||
$pdfContent = $this->exportService->bookToPdf($book);
|
||||
return response()->make($pdfContent, 200, [
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . $bookSlug . '.pdf'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a book as a contained HTML file.
|
||||
* @param string $bookSlug
|
||||
* @return mixed
|
||||
*/
|
||||
public function exportHtml($bookSlug)
|
||||
{
|
||||
$book = $this->entityRepo->getBySlug('book', $bookSlug);
|
||||
$htmlContent = $this->exportService->bookToContainedHtml($book);
|
||||
return response()->make($htmlContent, 200, [
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . $bookSlug . '.html'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a book as a plain text file.
|
||||
* @param $bookSlug
|
||||
* @return mixed
|
||||
*/
|
||||
public function exportPlainText($bookSlug)
|
||||
{
|
||||
$book = $this->entityRepo->getBySlug('book', $bookSlug);
|
||||
$htmlContent = $this->exportService->bookToPlainText($book);
|
||||
return response()->make($htmlContent, 200, [
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . $bookSlug . '.txt'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
use Activity;
|
||||
use BookStack\Repos\EntityRepo;
|
||||
use BookStack\Repos\UserRepo;
|
||||
use BookStack\Services\ExportService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Views;
|
||||
@ -12,16 +13,19 @@ class ChapterController extends Controller
|
||||
|
||||
protected $userRepo;
|
||||
protected $entityRepo;
|
||||
protected $exportService;
|
||||
|
||||
/**
|
||||
* ChapterController constructor.
|
||||
* @param EntityRepo $entityRepo
|
||||
* @param UserRepo $userRepo
|
||||
* @param ExportService $exportService
|
||||
*/
|
||||
public function __construct(EntityRepo $entityRepo, UserRepo $userRepo)
|
||||
public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService)
|
||||
{
|
||||
$this->entityRepo = $entityRepo;
|
||||
$this->userRepo = $userRepo;
|
||||
$this->exportService = $exportService;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@ -236,4 +240,52 @@ class ChapterController extends Controller
|
||||
session()->flash('success', trans('entities.chapters_permissions_success'));
|
||||
return redirect($chapter->getUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports a chapter to pdf .
|
||||
* @param string $bookSlug
|
||||
* @param string $chapterSlug
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportPdf($bookSlug, $chapterSlug)
|
||||
{
|
||||
$chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
|
||||
$pdfContent = $this->exportService->chapterToPdf($chapter);
|
||||
return response()->make($pdfContent, 200, [
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . $chapterSlug . '.pdf'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a chapter to a self-contained HTML file.
|
||||
* @param string $bookSlug
|
||||
* @param string $chapterSlug
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportHtml($bookSlug, $chapterSlug)
|
||||
{
|
||||
$chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
|
||||
$containedHtml = $this->exportService->chapterToContainedHtml($chapter);
|
||||
return response()->make($containedHtml, 200, [
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . $chapterSlug . '.html'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export a chapter to a simple plaintext .txt file.
|
||||
* @param string $bookSlug
|
||||
* @param string $chapterSlug
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function exportPlainText($bookSlug, $chapterSlug)
|
||||
{
|
||||
$chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
|
||||
$containedHtml = $this->exportService->chapterToPlainText($chapter);
|
||||
return response()->make($containedHtml, 200, [
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . $chapterSlug . '.txt'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers;
|
||||
<?php namespace BookStack\Http\Controllers;
|
||||
|
||||
use BookStack\Repos\CommentRepo;
|
||||
use BookStack\Repos\EntityRepo;
|
||||
use Illuminate\Http\Request;
|
||||
use Views;
|
||||
|
||||
use BookStack\Http\Requests;
|
||||
|
||||
// delete -checkOwnablePermission \
|
||||
class CommentController extends Controller
|
||||
{
|
||||
|
||||
public function add(Request $request, $pageId) {
|
||||
// $this->checkOwnablePermission('page-view', $page);
|
||||
protected $entityRepo;
|
||||
|
||||
public function __construct(EntityRepo $entityRepo, CommentRepo $commentRepo)
|
||||
{
|
||||
$this->entityRepo = $entityRepo;
|
||||
$this->commentRepo = $commentRepo;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function update(Request $request, $id) {
|
||||
// Check whether its an admin or the comment owner.
|
||||
// $this->checkOwnablePermission('page-view', $page);
|
||||
|
||||
public function save(Request $request, $pageId, $commentId)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'text' => 'required|string',
|
||||
'html' => 'required|string',
|
||||
]);
|
||||
|
||||
try {
|
||||
$page = $this->entityRepo->getById('page', $pageId, true);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return response('Not found', 404);
|
||||
}
|
||||
|
||||
if($page->draft) {
|
||||
// cannot add comments to drafts.
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => trans('errors.cannot_add_comment_to_draft'),
|
||||
], 400);
|
||||
}
|
||||
|
||||
$this->checkOwnablePermission('page-view', $page);
|
||||
if (empty($commentId)) {
|
||||
// create a new comment.
|
||||
$this->checkPermission('comment-create-all');
|
||||
$comment = $this->commentRepo->create($page, $request->only(['text', 'html', 'parent_id']));
|
||||
$respMsg = trans('entities.comment_created');
|
||||
} else {
|
||||
// update existing comment
|
||||
// get comment by ID and check if this user has permission to update.
|
||||
$comment = $this->comment->findOrFail($commentId);
|
||||
$this->checkOwnablePermission('comment-update', $comment);
|
||||
$this->commentRepo->update($comment, $request->all());
|
||||
$respMsg = trans('entities.comment_updated');
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'message' => $respMsg
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function destroy($id) {
|
||||
// Check whether its an admin or the comment owner.
|
||||
// $this->checkOwnablePermission('page-view', $page);
|
||||
$comment = $this->comment->findOrFail($id);
|
||||
$this->checkOwnablePermission('comment-delete', $comment);
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
public function getLastXComments($pageId) {
|
||||
// $this->checkOwnablePermission('page-view', $page);
|
||||
}
|
||||
|
||||
public function getChildComments($pageId, $id) {
|
||||
// $this->checkOwnablePermission('page-view', $page);
|
||||
|
||||
public function getComments($pageId, $commentId = null) {
|
||||
try {
|
||||
$page = $this->entityRepo->getById('page', $pageId, true);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return response('Not found', 404);
|
||||
}
|
||||
|
||||
if($page->draft) {
|
||||
// cannot add comments to drafts.
|
||||
return response()->json([
|
||||
'status' => 'error',
|
||||
'message' => trans('errors.no_comments_for_draft'),
|
||||
], 400);
|
||||
}
|
||||
|
||||
$this->checkOwnablePermission('page-view', $page);
|
||||
|
||||
$comments = $this->commentRepo->getCommentsForPage($pageId, $commentId);
|
||||
|
||||
return response()->json(array('success' => true, 'comments'=> $comments));
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers;
|
||||
<?php namespace BookStack\Http\Controllers;
|
||||
|
||||
use Activity;
|
||||
use BookStack\Repos\EntityRepo;
|
||||
use BookStack\Http\Requests;
|
||||
use Illuminate\Http\Response;
|
||||
use Views;
|
||||
|
||||
@ -63,10 +60,10 @@ class HomeController extends Controller
|
||||
];
|
||||
if ($locale !== 'en') {
|
||||
$enTrans = [
|
||||
'common' => trans('common', [], null, 'en'),
|
||||
'components' => trans('components', [], null, 'en'),
|
||||
'entities' => trans('entities', [], null, 'en'),
|
||||
'errors' => trans('errors', [], null, 'en')
|
||||
'common' => trans('common', [], 'en'),
|
||||
'components' => trans('components', [], 'en'),
|
||||
'entities' => trans('entities', [], 'en'),
|
||||
'errors' => trans('errors', [], 'en')
|
||||
];
|
||||
$translations = array_replace_recursive($enTrans, $translations);
|
||||
}
|
||||
|
@ -369,10 +369,13 @@ class PageController extends Controller
|
||||
public function showRevision($bookSlug, $pageSlug, $revisionId)
|
||||
{
|
||||
$page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
|
||||
$revision = $this->entityRepo->getById('page_revision', $revisionId, false);
|
||||
$revision = $page->revisions()->where('id', '=', $revisionId)->first();
|
||||
if ($revision === null) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$page->fill($revision->toArray());
|
||||
$this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()]));
|
||||
$this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
|
||||
|
||||
return view('pages/revision', [
|
||||
'page' => $page,
|
||||
@ -390,7 +393,10 @@ class PageController extends Controller
|
||||
public function showRevisionChanges($bookSlug, $pageSlug, $revisionId)
|
||||
{
|
||||
$page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
|
||||
$revision = $this->entityRepo->getById('page_revision', $revisionId);
|
||||
$revision = $page->revisions()->where('id', '=', $revisionId)->first();
|
||||
if ($revision === null) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$prev = $revision->getPrevious();
|
||||
$prevContent = ($prev === null) ? '' : $prev->html;
|
||||
@ -423,7 +429,7 @@ class PageController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports a page to pdf format using barryvdh/laravel-dompdf wrapper.
|
||||
* Exports a page to a PDF.
|
||||
* https://github.com/barryvdh/laravel-dompdf
|
||||
* @param string $bookSlug
|
||||
* @param string $pageSlug
|
||||
@ -433,7 +439,6 @@ class PageController extends Controller
|
||||
{
|
||||
$page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug);
|
||||
$pdfContent = $this->exportService->pageToPdf($page);
|
||||
// return $pdfContent;
|
||||
return response()->make($pdfContent, 200, [
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
'Content-Disposition' => 'attachment; filename="' . $pageSlug . '.pdf'
|
||||
@ -585,4 +590,9 @@ class PageController extends Controller
|
||||
return redirect($page->getUrl());
|
||||
}
|
||||
|
||||
public function getLastXComments($pageId)
|
||||
{
|
||||
// $this->checkOwnablePermission('page-view', $page);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ class Kernel extends HttpKernel
|
||||
*/
|
||||
protected $middleware = [
|
||||
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@ -24,8 +26,6 @@ class Kernel extends HttpKernel
|
||||
'web' => [
|
||||
\BookStack\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\BookStack\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\BookStack\Http\Middleware\Localization::class
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php namespace BookStack\Providers;
|
||||
|
||||
use BookStack\Services\SettingService;
|
||||
use BookStack\Setting;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Validator;
|
||||
|
||||
@ -30,6 +32,8 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
$this->app->singleton(SettingService::class, function($app) {
|
||||
return new SettingService($app->make(Setting::class), $app->make('Illuminate\Contracts\Cache\Repository'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php namespace BookStack\Repos;
|
||||
|
||||
use BookStack\Comment;
|
||||
use BookStack\Entity;
|
||||
use BookStack\Page;
|
||||
|
||||
/**
|
||||
* Class TagRepo
|
||||
@ -13,5 +13,39 @@ class CommentRepo {
|
||||
* @var Comment $comment
|
||||
*/
|
||||
protected $comment;
|
||||
|
||||
public function __construct(Comment $comment)
|
||||
{
|
||||
$this->comment = $comment;
|
||||
}
|
||||
|
||||
public function create (Page $page, $data = []) {
|
||||
$userId = user()->id;
|
||||
$comment = $this->comment->newInstance();
|
||||
$comment->fill($data);
|
||||
// new comment
|
||||
$comment->page_id = $page->id;
|
||||
$comment->created_by = $userId;
|
||||
$comment->save();
|
||||
return $comment;
|
||||
}
|
||||
|
||||
public function update($comment, $input) {
|
||||
$userId = user()->id;
|
||||
$comment->updated_by = $userId;
|
||||
$comment->fill($input);
|
||||
$comment->save();
|
||||
return $comment;
|
||||
}
|
||||
|
||||
public function getCommentsForPage($pageId, $commentId, $count = 20) {
|
||||
if (empty($commentId)) {
|
||||
// requesting parent comments
|
||||
$query = $this->comment->getParentCommentsByPage($pageId);
|
||||
return $query->paginate($count);
|
||||
} else {
|
||||
// requesting the child comments.
|
||||
return Comment::whereRaw("page_id = $pageId AND parent_id = $commentId")->get();
|
||||
}
|
||||
}
|
||||
}
|
@ -86,8 +86,7 @@ class EntityRepo
|
||||
$this->entities = [
|
||||
'page' => $this->page,
|
||||
'chapter' => $this->chapter,
|
||||
'book' => $this->book,
|
||||
'page_revision' => $this->pageRevision
|
||||
'book' => $this->book
|
||||
];
|
||||
$this->viewService = $viewService;
|
||||
$this->permissionService = $permissionService;
|
||||
@ -314,11 +313,12 @@ class EntityRepo
|
||||
* Loads the book slug onto child elements to prevent access database access for getting the slug.
|
||||
* @param Book $book
|
||||
* @param bool $filterDrafts
|
||||
* @param bool $renderPages
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBookChildren(Book $book, $filterDrafts = false)
|
||||
public function getBookChildren(Book $book, $filterDrafts = false, $renderPages = false)
|
||||
{
|
||||
$q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts)->get();
|
||||
$q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts, $renderPages)->get();
|
||||
$entities = [];
|
||||
$parents = [];
|
||||
$tree = [];
|
||||
@ -326,6 +326,10 @@ class EntityRepo
|
||||
foreach ($q as $index => $rawEntity) {
|
||||
if ($rawEntity->entity_type === 'BookStack\\Page') {
|
||||
$entities[$index] = $this->page->newFromBuilder($rawEntity);
|
||||
if ($renderPages) {
|
||||
$entities[$index]->html = $rawEntity->description;
|
||||
$entities[$index]->html = $this->renderPage($entities[$index]);
|
||||
};
|
||||
} else if ($rawEntity->entity_type === 'BookStack\\Chapter') {
|
||||
$entities[$index] = $this->chapter->newFromBuilder($rawEntity);
|
||||
$key = $entities[$index]->entity_type . ':' . $entities[$index]->id;
|
||||
@ -1054,7 +1058,7 @@ class EntityRepo
|
||||
public function restorePageRevision(Page $page, Book $book, $revisionId)
|
||||
{
|
||||
$this->savePageRevision($page);
|
||||
$revision = $this->getById('page_revision', $revisionId);
|
||||
$revision = $page->revisions()->where('id', '=', $revisionId)->first();
|
||||
$page->fill($revision->toArray());
|
||||
$page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
|
||||
$page->text = strip_tags($page->html);
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php namespace BookStack\Services;
|
||||
|
||||
use BookStack\Book;
|
||||
use BookStack\Chapter;
|
||||
use BookStack\Page;
|
||||
use BookStack\Repos\EntityRepo;
|
||||
|
||||
@ -25,25 +27,105 @@ class ExportService
|
||||
*/
|
||||
public function pageToContainedHtml(Page $page)
|
||||
{
|
||||
$cssContent = file_get_contents(public_path('/css/export-styles.css'));
|
||||
$pageHtml = view('pages/export', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render();
|
||||
$pageHtml = view('pages/export', [
|
||||
'page' => $page,
|
||||
'pageContent' => $this->entityRepo->renderPage($page)
|
||||
])->render();
|
||||
return $this->containHtml($pageHtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a page to a pdf file.
|
||||
* Convert a chapter to a self-contained HTML file.
|
||||
* @param Chapter $chapter
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function chapterToContainedHtml(Chapter $chapter)
|
||||
{
|
||||
$pages = $this->entityRepo->getChapterChildren($chapter);
|
||||
$pages->each(function($page) {
|
||||
$page->html = $this->entityRepo->renderPage($page);
|
||||
});
|
||||
$html = view('chapters/export', [
|
||||
'chapter' => $chapter,
|
||||
'pages' => $pages
|
||||
])->render();
|
||||
return $this->containHtml($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a book to a self-contained HTML file.
|
||||
* @param Book $book
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function bookToContainedHtml(Book $book)
|
||||
{
|
||||
$bookTree = $this->entityRepo->getBookChildren($book, true, true);
|
||||
$html = view('books/export', [
|
||||
'book' => $book,
|
||||
'bookChildren' => $bookTree
|
||||
])->render();
|
||||
return $this->containHtml($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a page to a PDF file.
|
||||
* @param Page $page
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function pageToPdf(Page $page)
|
||||
{
|
||||
$cssContent = file_get_contents(public_path('/css/export-styles.css'));
|
||||
$pageHtml = view('pages/pdf', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render();
|
||||
// return $pageHtml;
|
||||
$html = view('pages/pdf', [
|
||||
'page' => $page,
|
||||
'pageContent' => $this->entityRepo->renderPage($page)
|
||||
])->render();
|
||||
return $this->htmlToPdf($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a chapter to a PDF file.
|
||||
* @param Chapter $chapter
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function chapterToPdf(Chapter $chapter)
|
||||
{
|
||||
$pages = $this->entityRepo->getChapterChildren($chapter);
|
||||
$pages->each(function($page) {
|
||||
$page->html = $this->entityRepo->renderPage($page);
|
||||
});
|
||||
$html = view('chapters/export', [
|
||||
'chapter' => $chapter,
|
||||
'pages' => $pages
|
||||
])->render();
|
||||
return $this->htmlToPdf($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a book to a PDF file
|
||||
* @param Book $book
|
||||
* @return string
|
||||
*/
|
||||
public function bookToPdf(Book $book)
|
||||
{
|
||||
$bookTree = $this->entityRepo->getBookChildren($book, true, true);
|
||||
$html = view('books/export', [
|
||||
'book' => $book,
|
||||
'bookChildren' => $bookTree
|
||||
])->render();
|
||||
return $this->htmlToPdf($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert normal webpage HTML to a PDF.
|
||||
* @param $html
|
||||
* @return string
|
||||
*/
|
||||
protected function htmlToPdf($html)
|
||||
{
|
||||
$containedHtml = $this->containHtml($html);
|
||||
$useWKHTML = config('snappy.pdf.binary') !== false;
|
||||
$containedHtml = $this->containHtml($pageHtml);
|
||||
if ($useWKHTML) {
|
||||
$pdf = \SnappyPDF::loadHTML($containedHtml);
|
||||
$pdf->setOption('print-media-type', true);
|
||||
} else {
|
||||
$pdf = \PDF::loadHTML($containedHtml);
|
||||
}
|
||||
@ -123,6 +205,40 @@ class ExportService
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a chapter into a plain text string.
|
||||
* @param Chapter $chapter
|
||||
* @return string
|
||||
*/
|
||||
public function chapterToPlainText(Chapter $chapter)
|
||||
{
|
||||
$text = $chapter->name . "\n\n";
|
||||
$text .= $chapter->description . "\n\n";
|
||||
foreach ($chapter->pages as $page) {
|
||||
$text .= $this->pageToPlainText($page);
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a book into a plain text string.
|
||||
* @param Book $book
|
||||
* @return string
|
||||
*/
|
||||
public function bookToPlainText(Book $book)
|
||||
{
|
||||
$bookTree = $this->entityRepo->getBookChildren($book, true, true);
|
||||
$text = $book->name . "\n\n";
|
||||
foreach ($bookTree as $bookChild) {
|
||||
if ($bookChild->isA('chapter')) {
|
||||
$text .= $this->chapterToPlainText($bookChild);
|
||||
} else {
|
||||
$text .= $this->pageToPlainText($bookChild);
|
||||
}
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +41,8 @@ class LdapService
|
||||
// Find user
|
||||
$userFilter = $this->buildFilter($this->config['user_filter'], ['user' => $userName]);
|
||||
$baseDn = $this->config['base_dn'];
|
||||
$users = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $userFilter, ['cn', 'uid', 'dn', 'mail']);
|
||||
$emailAttr = $this->config['email_attribute'];
|
||||
$users = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $userFilter, ['cn', 'uid', 'dn', $emailAttr]);
|
||||
if ($users['count'] === 0) return null;
|
||||
|
||||
$user = $users[0];
|
||||
@ -49,7 +50,7 @@ class LdapService
|
||||
'uid' => (isset($user['uid'])) ? $user['uid'][0] : $user['dn'],
|
||||
'name' => $user['cn'][0],
|
||||
'dn' => $user['dn'],
|
||||
'email' => (isset($user['mail'])) ? $user['mail'][0] : null
|
||||
'email' => (isset($user[$emailAttr])) ? (is_array($user[$emailAttr]) ? $user[$emailAttr][0] : $user[$emailAttr]) : null
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -474,11 +474,13 @@ class PermissionService
|
||||
/**
|
||||
* Get the children of a book in an efficient single query, Filtered by the permission system.
|
||||
* @param integer $book_id
|
||||
* @param bool $filterDrafts
|
||||
* @param bool $filterDrafts
|
||||
* @param bool $fetchPageContent
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function bookChildrenQuery($book_id, $filterDrafts = false) {
|
||||
$pageSelect = $this->db->table('pages')->selectRaw("'BookStack\\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft")->where('book_id', '=', $book_id)->where(function($query) use ($filterDrafts) {
|
||||
public function bookChildrenQuery($book_id, $filterDrafts = false, $fetchPageContent = false) {
|
||||
$pageContentSelect = $fetchPageContent ? 'html' : "''";
|
||||
$pageSelect = $this->db->table('pages')->selectRaw("'BookStack\\\\Page' as entity_type, id, slug, name, text, {$pageContentSelect} as description, book_id, priority, chapter_id, draft")->where('book_id', '=', $book_id)->where(function($query) use ($filterDrafts) {
|
||||
$query->where('draft', '=', 0);
|
||||
if (!$filterDrafts) {
|
||||
$query->orWhere(function($query) {
|
||||
|
@ -16,6 +16,7 @@ class SettingService
|
||||
|
||||
protected $setting;
|
||||
protected $cache;
|
||||
protected $localCache = [];
|
||||
|
||||
protected $cachePrefix = 'setting-';
|
||||
|
||||
@ -40,8 +41,12 @@ class SettingService
|
||||
public function get($key, $default = false)
|
||||
{
|
||||
if ($default === false) $default = config('setting-defaults.' . $key, false);
|
||||
if (isset($this->localCache[$key])) return $this->localCache[$key];
|
||||
|
||||
$value = $this->getValueFromStore($key, $default);
|
||||
return $this->formatValue($value, $default);
|
||||
$formatted = $this->formatValue($value, $default);
|
||||
$this->localCache[$key] = $formatted;
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,9 +76,8 @@ class SettingService
|
||||
|
||||
// Check the cache
|
||||
$cacheKey = $this->cachePrefix . $key;
|
||||
if ($this->cache->has($cacheKey)) {
|
||||
return $this->cache->get($cacheKey);
|
||||
}
|
||||
$cacheVal = $this->cache->get($cacheKey, null);
|
||||
if ($cacheVal !== null) return $cacheVal;
|
||||
|
||||
// Check the database
|
||||
$settingObject = $this->getSettingObjectByKey($key);
|
||||
|
@ -181,14 +181,24 @@ class SocialAuthService
|
||||
public function getActiveDrivers()
|
||||
{
|
||||
$activeDrivers = [];
|
||||
foreach ($this->validSocialDrivers as $driverName) {
|
||||
if ($this->checkDriverConfigured($driverName)) {
|
||||
$activeDrivers[$driverName] = true;
|
||||
foreach ($this->validSocialDrivers as $driverKey) {
|
||||
if ($this->checkDriverConfigured($driverKey)) {
|
||||
$activeDrivers[$driverKey] = $this->getDriverName($driverKey);
|
||||
}
|
||||
}
|
||||
return $activeDrivers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the presentational name for a driver.
|
||||
* @param $driver
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDriverName($driver)
|
||||
{
|
||||
return config('services.' . strtolower($driver) . '.name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $socialDriver
|
||||
* @param \Laravel\Socialite\Contracts\User $socialUser
|
||||
|
@ -37,6 +37,15 @@ function user()
|
||||
return auth()->user() ?: \BookStack\User::getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current user is a signed in user.
|
||||
* @return bool
|
||||
*/
|
||||
function signedInUser()
|
||||
{
|
||||
return auth()->user() && !auth()->user()->isDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user has a permission.
|
||||
* If an ownable element is passed in the jointPermissions are checked against
|
||||
@ -64,7 +73,7 @@ function userCan($permission, Ownable $ownable = null)
|
||||
*/
|
||||
function setting($key = null, $default = false)
|
||||
{
|
||||
$settingService = app(\BookStack\Services\SettingService::class);
|
||||
$settingService = resolve(\BookStack\Services\SettingService::class);
|
||||
if (is_null($key)) return $settingService;
|
||||
return $settingService->get($key, $default);
|
||||
}
|
||||
|
Reference in New Issue
Block a user