diff --git a/app/Exceptions/ConfirmationEmailException.php b/app/Exceptions/ConfirmationEmailException.php index f343eff82..8736422c4 100644 --- a/app/Exceptions/ConfirmationEmailException.php +++ b/app/Exceptions/ConfirmationEmailException.php @@ -1,7 +1,4 @@ <?php namespace BookStack\Exceptions; -class ConfirmationEmailException extends NotifyException -{ - -} \ No newline at end of file +class ConfirmationEmailException extends NotifyException {} \ No newline at end of file diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 84f38e8f5..73a316953 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -5,6 +5,7 @@ namespace BookStack\Exceptions; use Exception; use Illuminate\Contracts\Validation\ValidationException; use Illuminate\Database\Eloquent\ModelNotFoundException; +use PhpSpec\Exception\Example\ErrorException; use Symfony\Component\HttpKernel\Exception\HttpException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Auth\Access\AuthorizationException; @@ -38,17 +39,26 @@ class Handler extends ExceptionHandler /** * Render an exception into an HTTP response. * - * @param \Illuminate\Http\Request $request - * @param \Exception $e + * @param \Illuminate\Http\Request $request + * @param \Exception $e * @return \Illuminate\Http\Response */ public function render($request, Exception $e) { - if($e instanceof NotifyException) { + // 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); } + // Handle pretty exceptions which will show a friendly application-fitting page + // Which will include the basic message to point the user roughly to the cause. + if (($e instanceof PrettyException || $e->getPrevious() instanceof PrettyException) && !config('app.debug')) { + $message = ($e instanceof PrettyException) ? $e->getMessage() : $e->getPrevious()->getMessage(); + return response()->view('errors/500', ['message' => $message], 500); + } + return parent::render($request, $e); } } diff --git a/app/Exceptions/ImageUploadException.php b/app/Exceptions/ImageUploadException.php index 205bdd4ff..6f4c73037 100644 --- a/app/Exceptions/ImageUploadException.php +++ b/app/Exceptions/ImageUploadException.php @@ -1,6 +1,3 @@ <?php namespace BookStack\Exceptions; - -use Exception; - -class ImageUploadException extends Exception {} \ No newline at end of file +class ImageUploadException extends PrettyException {} \ No newline at end of file diff --git a/app/Exceptions/LdapException.php b/app/Exceptions/LdapException.php index acdb24302..405520166 100644 --- a/app/Exceptions/LdapException.php +++ b/app/Exceptions/LdapException.php @@ -1,9 +1,3 @@ <?php namespace BookStack\Exceptions; - -use Exception; - -class LdapException extends Exception -{ - -} \ No newline at end of file +class LdapException extends PrettyException {} \ No newline at end of file diff --git a/app/Exceptions/PrettyException.php b/app/Exceptions/PrettyException.php new file mode 100644 index 000000000..d92acf831 --- /dev/null +++ b/app/Exceptions/PrettyException.php @@ -0,0 +1,5 @@ +<?php namespace BookStack\Exceptions; + +use Exception; + +class PrettyException extends Exception {} \ No newline at end of file diff --git a/app/Exceptions/SocialDriverNotConfigured.php b/app/Exceptions/SocialDriverNotConfigured.php index 6e1b76226..20a26c4c9 100644 --- a/app/Exceptions/SocialDriverNotConfigured.php +++ b/app/Exceptions/SocialDriverNotConfigured.php @@ -1,6 +1,4 @@ <?php namespace BookStack\Exceptions; -class SocialDriverNotConfigured extends \Exception -{ -} \ No newline at end of file +class SocialDriverNotConfigured extends PrettyException {} \ No newline at end of file diff --git a/app/Exceptions/SocialSignInException.php b/app/Exceptions/SocialSignInException.php index 1f5ad18af..fa78ca85f 100644 --- a/app/Exceptions/SocialSignInException.php +++ b/app/Exceptions/SocialSignInException.php @@ -1,7 +1,4 @@ <?php namespace BookStack\Exceptions; -class SocialSignInException extends NotifyException -{ - -} \ No newline at end of file +class SocialSignInException extends NotifyException {} \ No newline at end of file diff --git a/app/Exceptions/UserRegistrationException.php b/app/Exceptions/UserRegistrationException.php index cb1e32517..13a5ec1c3 100644 --- a/app/Exceptions/UserRegistrationException.php +++ b/app/Exceptions/UserRegistrationException.php @@ -1,7 +1,4 @@ <?php namespace BookStack\Exceptions; -class UserRegistrationException extends NotifyException -{ - -} \ No newline at end of file +class UserRegistrationException extends NotifyException {} \ No newline at end of file diff --git a/app/Services/ImageService.php b/app/Services/ImageService.php index 9d8aeea51..47c27cd0a 100644 --- a/app/Services/ImageService.php +++ b/app/Services/ImageService.php @@ -4,6 +4,7 @@ use BookStack\Exceptions\ImageUploadException; use BookStack\Image; use BookStack\User; use Exception; +use Intervention\Image\Exception\NotSupportedException; use Intervention\Image\ImageManager; use Illuminate\Contracts\Filesystem\Factory as FileSystem; use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance; @@ -119,10 +120,12 @@ class ImageService * Checks the cache then storage to avoid creating / accessing the filesystem on every check. * * @param Image $image - * @param int $width - * @param int $height - * @param bool $keepRatio + * @param int $width + * @param int $height + * @param bool $keepRatio * @return string + * @throws Exception + * @throws ImageUploadException */ public function getThumbnail(Image $image, $width = 220, $height = 220, $keepRatio = false) { @@ -139,8 +142,16 @@ class ImageService return $this->getPublicUrl($thumbFilePath); } - // Otherwise create the thumbnail - $thumb = $this->imageTool->make($storage->get($image->path)); + try { + $thumb = $this->imageTool->make($storage->get($image->path)); + } catch (Exception $e) { + if ($e instanceof \ErrorException || $e instanceof NotSupportedException) { + throw new ImageUploadException('The server cannot create thumbnails. Please check you have the GD PHP extension installed.'); + } else { + throw $e; + } + } + if ($keepRatio) { $thumb->resize($width, null, function ($constraint) { $constraint->aspectRatio(); diff --git a/readme.md b/readme.md index b2f909efb..a191e1694 100644 --- a/readme.md +++ b/readme.md @@ -17,19 +17,13 @@ A platform to create documentation/wiki content. General information about BookS ## Requirements -BookStack has similar requirements to Laravel. On top of those are some front-end build tools which are only required when developing. +BookStack has similar requirements to Laravel: * PHP >= 5.5.9, Will need to be usable from the command line. -* OpenSSL PHP Extension -* PDO PHP Extension -* MBstring PHP Extension -* Tokenizer PHP Extension +* PHP Extensions: `OpenSSL`, `PDO`, `MBstring`, `Tokenizer`, `GD` * MySQL >= 5.6 * Git (Not strictly required but helps manage updates) * [Composer](https://getcomposer.org/) -* [Node.js](https://nodejs.org/en/) **Development Only** -* [Gulp](http://gulpjs.com/) **Development Only** - ## Installation @@ -144,7 +138,14 @@ A user in BookStack will be linked to a LDAP user via a 'uid'. If a LDAP user ui You may find that you cannot log in with your initial Admin account after changing the `AUTH_METHOD` to `ldap`. To get around this set the `AUTH_METHOD` to `standard`, login with your admin account then change it back to `ldap`. You get then edit your profile and add your LDAP uid under the 'External Authentication ID' field. You will then be able to login in with that ID. -## Testing +## Development & Testing + +All development on BookStack is currently done on the master branch. When it's time for a release the master branch is merged into release with built & minified CSS & JS then tagged at it's version. Here are the current development requirements: + +* [Node.js](https://nodejs.org/en/) **Development Only** +* [Gulp](http://gulpjs.com/) **Development Only** + +SASS is used to help the CSS development and the JavaScript is run through browserify/babel to allow for writing ES6 code. Both of these are done using gulp. BookStack has many integration tests that use Laravel's built-in testing capabilities which makes use of PHPUnit. To use you will need PHPUnit installed and accessible via command line. There is a `mysql_testing` database defined within the app config which is what is used by PHPUnit. This database is set with the following database name, user name and password defined as `bookstack-test`. You will have to create that database and credentials before testing. diff --git a/resources/views/errors/500.blade.php b/resources/views/errors/500.blade.php new file mode 100644 index 000000000..47dcb88c7 --- /dev/null +++ b/resources/views/errors/500.blade.php @@ -0,0 +1,11 @@ +@extends('base') + +@section('content') + + + <div class="container"> + <h1 class="text-muted">An Error Occurred</h1> + <p>{{ $message }}</p> + </div> + +@stop \ No newline at end of file