1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-07-30 04:23:11 +03:00

Merge branch 'v0.11'

This commit is contained in:
Dan Brown
2016-08-14 13:09:44 +01:00
90 changed files with 563 additions and 462 deletions

View File

@ -7,11 +7,15 @@ class Book extends Entity
/**
* Get the url for this book.
* @param string|bool $path
* @return string
*/
public function getUrl()
public function getUrl($path = false)
{
return '/books/' . $this->slug;
if ($path !== false) {
return baseUrl('/books/' . $this->slug . '/' . trim($path, '/'));
}
return baseUrl('/books/' . $this->slug);
}
/*

View File

@ -25,12 +25,16 @@ class Chapter extends Entity
/**
* Get the url of this chapter.
* @param string|bool $path
* @return string
*/
public function getUrl()
public function getUrl($path = false)
{
$bookSlug = $this->getAttribute('bookSlug') ? $this->getAttribute('bookSlug') : $this->book->slug;
return '/books/' . $bookSlug. '/chapter/' . $this->slug;
if ($path !== false) {
return baseUrl('/books/' . $bookSlug. '/chapter/' . $this->slug . '/' . trim($path, '/'));
}
return baseUrl('/books/' . $bookSlug. '/chapter/' . $this->slug);
}
/**

View File

@ -48,8 +48,8 @@ class Handler extends ExceptionHandler
// Handle notify exceptions which will redirect to the
// specified location then show a notification message.
if ($e instanceof NotifyException) {
\Session::flash('error', $e->message);
return response()->redirectTo($e->redirectLocation);
session()->flash('error', $e->message);
return redirect($e->redirectLocation);
}
// Handle pretty exceptions which will show a friendly application-fitting page

View File

@ -1,9 +1,6 @@
<?php
namespace BookStack\Http\Controllers\Auth;
<?php namespace BookStack\Http\Controllers\Auth;
use BookStack\Exceptions\AuthException;
use BookStack\Exceptions\PrettyException;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Http\Request;
use BookStack\Exceptions\SocialSignInException;
@ -36,7 +33,6 @@ class AuthController extends Controller
protected $redirectAfterLogout = '/login';
protected $username = 'email';
protected $socialAuthService;
protected $emailConfirmationService;
protected $userRepo;
@ -53,6 +49,8 @@ class AuthController extends Controller
$this->socialAuthService = $socialAuthService;
$this->emailConfirmationService = $emailConfirmationService;
$this->userRepo = $userRepo;
$this->redirectPath = baseUrl('/');
$this->redirectAfterLogout = baseUrl('/login');
$this->username = config('auth.method') === 'standard' ? 'email' : 'username';
parent::__construct();
}

View File

@ -412,7 +412,7 @@ class PageController extends Controller
*/
public function showRecentlyCreated()
{
$pages = $this->pageRepo->getRecentlyCreatedPaginated(20);
$pages = $this->pageRepo->getRecentlyCreatedPaginated(20)->setPath(baseUrl('/pages/recently-created'));
return view('pages/detailed-listing', [
'title' => 'Recently Created Pages',
'pages' => $pages
@ -425,7 +425,7 @@ class PageController extends Controller
*/
public function showRecentlyUpdated()
{
$pages = $this->pageRepo->getRecentlyUpdatedPaginated(20);
$pages = $this->pageRepo->getRecentlyUpdatedPaginated(20)->setPath(baseUrl('/pages/recently-updated'));
return view('pages/detailed-listing', [
'title' => 'Recently Updated Pages',
'pages' => $pages

View File

@ -33,7 +33,7 @@ class Authenticate
public function handle($request, Closure $next)
{
if ($this->auth->check() && setting('registration-confirmation') && !$this->auth->user()->email_confirmed) {
return redirect()->guest('/register/confirm/awaiting');
return redirect()->guest(baseUrl('/register/confirm/awaiting'));
}
if ($this->auth->guest() && !setting('app-public')) {

View File

@ -56,14 +56,20 @@ class Page extends Entity
/**
* Get the url for this page.
* @param string|bool $path
* @return string
*/
public function getUrl()
public function getUrl($path = false)
{
$bookSlug = $this->getAttribute('bookSlug') ? $this->getAttribute('bookSlug') : $this->book->slug;
$midText = $this->draft ? '/draft/' : '/page/';
$idComponent = $this->draft ? $this->id : $this->slug;
return '/books/' . $bookSlug . $midText . $idComponent;
if ($path !== false) {
return baseUrl('/books/' . $bookSlug . $midText . $idComponent . '/' . trim($path, '/'));
}
return baseUrl('/books/' . $bookSlug . $midText . $idComponent);
}
/**

View File

@ -0,0 +1,30 @@
<?php namespace BookStack\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator;
class PaginationServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
Paginator::currentPathResolver(function () {
return baseUrl($this->app['request']->path());
});
Paginator::currentPageResolver(function ($pageName = 'page') {
$page = $this->app['request']->input($pageName);
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int) $page >= 1) {
return $page;
}
return 1;
});
}
}

View File

@ -216,12 +216,10 @@ class BookRepo extends EntityRepo
*/
public function findSuitableSlug($name, $currentId = false)
{
$originalSlug = Str::slug($name);
$slug = $originalSlug;
$count = 2;
$slug = Str::slug($name);
if ($slug === "") $slug = substr(md5(rand(1, 500)), 0, 5);
while ($this->doesSlugExist($slug, $currentId)) {
$slug = $originalSlug . '-' . $count;
$count++;
$slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
}
return $slug;
}
@ -229,7 +227,7 @@ class BookRepo extends EntityRepo
/**
* Get all child objects of a book.
* Returns a sorted collection of Pages and Chapters.
* Loads the bookslug onto child elements to prevent access database access for getting the slug.
* Loads the book slug onto child elements to prevent access database access for getting the slug.
* @param Book $book
* @param bool $filterDrafts
* @return mixed
@ -245,7 +243,7 @@ class BookRepo extends EntityRepo
$pages = $pageQuery->get();
$chapterQuery = $book->chapters()->with(['pages' => function($query) use ($filterDrafts) {
$chapterQuery = $book->chapters()->with(['pages' => function ($query) use ($filterDrafts) {
$this->permissionService->enforcePageRestrictions($query, 'view');
if ($filterDrafts) $query->where('draft', '=', false);
}]);
@ -263,7 +261,7 @@ class BookRepo extends EntityRepo
$child->pages->each(function ($page) use ($bookSlug) {
$page->setAttribute('bookSlug', $bookSlug);
});
$child->pages = $child->pages->sortBy(function($child, $key) {
$child->pages = $child->pages->sortBy(function ($child, $key) {
$score = $child->priority;
if ($child->draft) $score -= 100;
return $score;
@ -272,7 +270,7 @@ class BookRepo extends EntityRepo
});
// Sort items with drafts first then by priority.
return $children->sortBy(function($child, $key) {
return $children->sortBy(function ($child, $key) {
$score = $child->priority;
if ($child->isA('page') && $child->draft) $score -= 100;
return $score;

View File

@ -81,7 +81,7 @@ class ChapterRepo extends EntityRepo
{
$pages = $this->permissionService->enforcePageRestrictions($chapter->pages())->get();
// Sort items with drafts first then by priority.
return $pages->sortBy(function($child, $key) {
return $pages->sortBy(function ($child, $key) {
$score = $child->priority;
if ($child->draft) $score -= 100;
return $score;
@ -151,6 +151,7 @@ class ChapterRepo extends EntityRepo
public function findSuitableSlug($name, $bookId, $currentId = false)
{
$slug = Str::slug($name);
if ($slug === "") $slug = substr(md5(rand(1, 500)), 0, 5);
while ($this->doesSlugExist($slug, $bookId, $currentId)) {
$slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
}

View File

@ -13,7 +13,7 @@ class ImageRepo
protected $image;
protected $imageService;
protected $restictionService;
protected $restrictionService;
protected $page;
/**
@ -27,7 +27,7 @@ class ImageRepo
{
$this->image = $image;
$this->imageService = $imageService;
$this->restictionService = $permissionService;
$this->restrictionService = $permissionService;
$this->page = $page;
}
@ -52,7 +52,7 @@ class ImageRepo
*/
private function returnPaginated($query, $page = 0, $pageSize = 24)
{
$images = $this->restictionService->filterRelatedPages($query, 'images', 'uploaded_to');
$images = $this->restrictionService->filterRelatedPages($query, 'images', 'uploaded_to');
$images = $images->orderBy('created_at', 'desc')->skip($pageSize * $page)->take($pageSize + 1)->get();
$hasMore = count($images) > $pageSize;

View File

@ -599,14 +599,15 @@ class PageRepo extends EntityRepo
/**
* Gets a suitable slug for the resource
* @param $name
* @param $bookId
* @param string $name
* @param int $bookId
* @param bool|false $currentId
* @return string
*/
public function findSuitableSlug($name, $bookId, $currentId = false)
{
$slug = Str::slug($name);
if ($slug === "") $slug = substr(md5(rand(1, 500)), 0, 5);
while ($this->doesSlugExist($slug, $bookId, $currentId)) {
$slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
}

View File

@ -273,7 +273,7 @@ class ImageService
$this->storageUrl = $storageUrl;
}
return ($this->storageUrl == false ? '' : rtrim($this->storageUrl, '/')) . $filePath;
return ($this->storageUrl == false ? rtrim(baseUrl(''), '/') : rtrim($this->storageUrl, '/')) . $filePath;
}

View File

@ -113,20 +113,20 @@ class SocialAuthService
if ($isLoggedIn && $socialAccount === null) {
$this->fillSocialAccount($socialDriver, $socialUser);
$currentUser->socialAccounts()->save($this->socialAccount);
\Session::flash('success', title_case($socialDriver) . ' account was successfully attached to your profile.');
session()->flash('success', title_case($socialDriver) . ' account was successfully attached to your profile.');
return redirect($currentUser->getEditUrl());
}
// When a user is logged in and the social account exists and is already linked to the current user.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id === $currentUser->id) {
\Session::flash('error', 'This ' . title_case($socialDriver) . ' account is already attached to your profile.');
session()->flash('error', 'This ' . title_case($socialDriver) . ' account is already attached to your profile.');
return redirect($currentUser->getEditUrl());
}
// When a user is logged in, A social account exists but the users do not match.
// Change the user that the social account is assigned to.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id != $currentUser->id) {
\Session::flash('success', 'This ' . title_case($socialDriver) . ' account is already used by another user.');
session()->flash('success', 'This ' . title_case($socialDriver) . ' account is already used by another user.');
return redirect($currentUser->getEditUrl());
}
@ -135,6 +135,7 @@ class SocialAuthService
if (setting('registration-enabled')) {
$message .= ' or, If you do not yet have an account, You can register an account using the ' . $socialDriver . ' option';
}
throw new SocialSignInException($message . '.', '/login');
}

View File

@ -138,8 +138,8 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public function getAvatar($size = 50)
{
if ($this->image_id === 0 || $this->image_id === '0' || $this->image_id === null) return '/user_avatar.png';
return $this->avatar->getThumb($size, $size, false);
if ($this->image_id === 0 || $this->image_id === '0' || $this->image_id === null) return baseUrl('/user_avatar.png');
return baseUrl($this->avatar->getThumb($size, $size, false));
}
/**
@ -157,7 +157,16 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public function getEditUrl()
{
return '/settings/users/' . $this->id;
return baseUrl('/settings/users/' . $this->id);
}
/**
* Get the url that links to this user's profile.
* @return mixed
*/
public function getProfileUrl()
{
return baseUrl('/user/' . $this->id);
}
/**

View File

@ -20,11 +20,11 @@ if (!function_exists('versioned_asset')) {
}
if (isset($manifest[$file])) {
return '/' . $manifest[$file];
return baseUrl($manifest[$file]);
}
if (file_exists(public_path($file))) {
return '/' . $file;
return baseUrl($file);
}
throw new InvalidArgumentException("File {$file} not defined in asset manifest.");
@ -62,6 +62,40 @@ function setting($key, $default = false)
return $settingService->get($key, $default);
}
/**
* Helper to create url's relative to the applications root path.
* @param $path
* @return string
*/
function baseUrl($path)
{
if (strpos($path, 'http') === 0) return $path;
$path = trim($path, '/');
return rtrim(config('app.url'), '/') . '/' . $path;
}
/**
* Get an instance of the redirector.
* Overrides the default laravel redirect helper.
* Ensures it redirects even when the app is in a subdirectory.
*
* @param string|null $to
* @param int $status
* @param array $headers
* @param bool $secure
* @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
*/
function redirect($to = null, $status = 302, $headers = [], $secure = null)
{
if (is_null($to)) {
return app('redirect');
}
$to = baseUrl($to);
return app('redirect')->to($to, $status, $headers, $secure);
}
/**
* Generate a url with multiple parameters for sorting purposes.
* Works out the logic to set the correct sorting direction
@ -91,5 +125,5 @@ function sortUrl($path, $data, $overrideData = [])
if (count($queryStringSections) === 0) return $path;
return $path . '?' . implode('&', $queryStringSections);
return baseUrl($path . '?' . implode('&', $queryStringSections));
}