From 9537e2ae9572f75edc8da7fb23572346c56f101d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=C3=A8s=20EL=20BIACHE?= Date: Thu, 7 Jul 2016 19:42:21 +0200 Subject: [PATCH 01/27] html diff in revision view --- app/Http/Controllers/PageController.php | 13 +- app/PageRevision.php | 21 + composer.json | 3 +- composer.lock | 831 ++++++++++++------- resources/assets/sass/_pages.scss | 12 + resources/views/pages/page-display.blade.php | 6 +- 6 files changed, 589 insertions(+), 297 deletions(-) mode change 100644 => 100755 resources/assets/sass/_pages.scss diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index f35834e62..1844e0c0c 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -12,6 +12,7 @@ use BookStack\Repos\ChapterRepo; use BookStack\Repos\PageRepo; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Views; +use Icap\HtmlDiff\HtmlDiff; class PageController extends Controller { @@ -332,9 +333,19 @@ class PageController extends Controller $book = $this->bookRepo->getBySlug($bookSlug); $page = $this->pageRepo->getBySlug($pageSlug, $book->id); $revision = $this->pageRepo->getRevisionById($revisionId); + + $next = $revision->getNext() ?: $page; + $htmlDiff = new HtmlDiff($revision->html, $next->html, true); + $diff = $htmlDiff->outputDiff()->toString(); + $page->fill($revision->toArray()); $this->setPageTitle('Page Revision For ' . $page->getShortName()); - return view('pages/revision', ['page' => $page, 'book' => $book]); + + return view('pages/revision', [ + 'page' => $page, + 'book' => $book, + 'diff' => $diff, + ]); } /** diff --git a/app/PageRevision.php b/app/PageRevision.php index dae74cd0f..1baf0f8e5 100644 --- a/app/PageRevision.php +++ b/app/PageRevision.php @@ -32,4 +32,25 @@ class PageRevision extends Model return $this->page->getUrl() . '/revisions/' . $this->id; } + /** + * Get previous revision + * @return \BookStack\PageRevision + */ + public function getPrevious() + { + if ($id = PageRevision::where('id', '<', $this->id)->max('id')) { + return PageRevision::find($id); + } + } + + /** + * Get next revision + * @return \BookStack\PageRevision + */ + public function getNext() + { + if ($id = PageRevision::where('id', '>', $this->id)->min('id')) { + return PageRevision::find($id); + } + } } diff --git a/composer.json b/composer.json index 8f375a279..41f1ada5d 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "barryvdh/laravel-debugbar": "^2.0", "league/flysystem-aws-s3-v3": "^1.0", "barryvdh/laravel-dompdf": "0.6.*", - "predis/predis": "^1.0" + "predis/predis": "^1.0", + "icap/html-diff": "^1.1" }, "require-dev": { "fzaninotto/faker": "~1.4", diff --git a/composer.lock b/composer.lock index 63d378753..f97aeb992 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,27 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "eb7c71e9ed116d3fd2a1d0af07f9f134", - "content-hash": "17d2d7fc5fed682f2a290d6588538035", + "hash": "3d8e2dfddefb412055d28ffc922969fd", + "content-hash": "7658fea0b4df71cf7b97bcdf8a29b9eb", "packages": [ { "name": "aws/aws-sdk-php", - "version": "3.17.5", + "version": "3.18.25", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "1cef9b334729b3564c9aef15481a55561c54b53f" + "reference": "37a8ce927a69de3d821c21b64674a2b3b9d1d247" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1cef9b334729b3564c9aef15481a55561c54b53f", - "reference": "1cef9b334729b3564c9aef15481a55561c54b53f", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/37a8ce927a69de3d821c21b64674a2b3b9d1d247", + "reference": "37a8ce927a69de3d821c21b64674a2b3b9d1d247", "shasum": "" }, "require": { "guzzlehttp/guzzle": "~5.3|~6.0.1|~6.1", "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.0", + "guzzlehttp/psr7": "~1.3.1", "mtdowling/jmespath.php": "~2.2", "php": ">=5.5" }, @@ -85,20 +85,20 @@ "s3", "sdk" ], - "time": "2016-04-07 22:44:13" + "time": "2016-07-05 19:25:06" }, { "name": "barryvdh/laravel-debugbar", - "version": "v2.2.0", + "version": "v2.2.2", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "13b7058d2120c8d5af7f1ada21b7c44dd87b666a" + "reference": "c291e58d0a13953e0f68d99182ee77ebc693edc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/13b7058d2120c8d5af7f1ada21b7c44dd87b666a", - "reference": "13b7058d2120c8d5af7f1ada21b7c44dd87b666a", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/c291e58d0a13953e0f68d99182ee77ebc693edc0", + "reference": "c291e58d0a13953e0f68d99182ee77ebc693edc0", "shasum": "" }, "require": { @@ -139,7 +139,7 @@ "profiler", "webprofiler" ], - "time": "2016-02-17 08:32:21" + "time": "2016-05-11 13:54:43" }, { "name": "barryvdh/laravel-dompdf", @@ -191,28 +191,31 @@ }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.1.4", + "version": "v2.2.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "f1ebd847aac9a4545325d35108cafc285fe1605f" + "reference": "28af7cd19ca41cc0c63dd1de2b46c2b84d31c463" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/f1ebd847aac9a4545325d35108cafc285fe1605f", - "reference": "f1ebd847aac9a4545325d35108cafc285fe1605f", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/28af7cd19ca41cc0c63dd1de2b46c2b84d31c463", + "reference": "28af7cd19ca41cc0c63dd1de2b46c2b84d31c463", "shasum": "" }, "require": { - "illuminate/console": "5.0.x|5.1.x|5.2.x", - "illuminate/filesystem": "5.0.x|5.1.x|5.2.x", - "illuminate/support": "5.0.x|5.1.x|5.2.x", + "barryvdh/reflection-docblock": "^2.0.4", + "illuminate/console": "^5.0,<5.4", + "illuminate/filesystem": "^5.0,<5.4", + "illuminate/support": "^5.0,<5.4", "php": ">=5.4.0", - "phpdocumentor/reflection-docblock": "^2.0.4", - "symfony/class-loader": "~2.3|~3.0" + "symfony/class-loader": "^2.3|^3.0" }, "require-dev": { - "doctrine/dbal": "~2.3" + "doctrine/dbal": "~2.3", + "phpunit/phpunit": "4.*", + "scrutinizer/ocular": "~1.1", + "squizlabs/php_codesniffer": "~2.3" }, "suggest": { "doctrine/dbal": "Load information from the database about models for phpdocs (~2.3)" @@ -220,7 +223,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.2-dev" } }, "autoload": { @@ -250,7 +253,56 @@ "phpstorm", "sublime" ], - "time": "2016-03-03 08:45:00" + "time": "2016-07-04 11:52:48" + }, + { + "name": "barryvdh/reflection-docblock", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/ReflectionDocBlock.git", + "reference": "3dcbd98b5d9384a5357266efba8fd29884458e5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/3dcbd98b5d9384a5357266efba8fd29884458e5c", + "reference": "3dcbd98b5d9384a5357266efba8fd29884458e5c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0,<4.5" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Barryvdh": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2016-06-13 19:28:20" }, { "name": "classpreloader/classpreloader", @@ -537,6 +589,7 @@ "rest", "web service" ], + "abandoned": "guzzlehttp/guzzle", "time": "2014-01-28 22:29:15" }, { @@ -603,16 +656,16 @@ }, { "name": "guzzlehttp/promises", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8" + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bb9024c526b22f3fe6ae55a561fd70653d470aa8", - "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", "shasum": "" }, "require": { @@ -650,20 +703,20 @@ "keywords": [ "promise" ], - "time": "2016-03-08 01:15:46" + "time": "2016-05-18 16:56:05" }, { "name": "guzzlehttp/psr7", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", "shasum": "" }, "require": { @@ -679,7 +732,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -708,20 +761,64 @@ "stream", "uri" ], - "time": "2016-02-18 21:54:00" + "time": "2016-06-24 23:00:38" }, { - "name": "intervention/image", - "version": "2.3.6", + "name": "icap/html-diff", + "version": "v1.1.0", "source": { "type": "git", - "url": "https://github.com/Intervention/image.git", - "reference": "e368d262887dbb2fdfaf710880571ede51e9c0e6" + "url": "https://github.com/iCAPLyon1/HtmlDiff.git", + "reference": "f58ddb196292ae585a2efb7692653d015ecc436f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/e368d262887dbb2fdfaf710880571ede51e9c0e6", - "reference": "e368d262887dbb2fdfaf710880571ede51e9c0e6", + "url": "https://api.github.com/repos/iCAPLyon1/HtmlDiff/zipball/f58ddb196292ae585a2efb7692653d015ecc436f", + "reference": "f58ddb196292ae585a2efb7692653d015ecc436f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Icap\\HtmlDiff\\": "src/Icap/HtmlDiff" + } + }, + "notification-url": "https://packagist.org/downloads/", + "authors": [ + { + "name": "Panagiotis Tsavdaris", + "email": "ptsavdar@gmail.com" + }, + { + "name": "ICAP development team", + "homepage": "https://github.com/iCAPLyon1" + } + ], + "description": "A PHP5 library that diffs (compares) HTML files.", + "keywords": [ + "daisy diff", + "html diff" + ], + "time": "2016-02-17 16:35:09" + }, + { + "name": "intervention/image", + "version": "2.3.7", + "source": { + "type": "git", + "url": "https://github.com/Intervention/image.git", + "reference": "22088b04728a039bd1fc32f7e79a89a118b78698" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Intervention/image/zipball/22088b04728a039bd1fc32f7e79a89a118b78698", + "reference": "22088b04728a039bd1fc32f7e79a89a118b78698", "shasum": "" }, "require": { @@ -770,7 +867,7 @@ "thumbnail", "watermark" ], - "time": "2016-02-26 18:18:19" + "time": "2016-04-26 14:08:40" }, { "name": "jakub-onderka/php-console-color", @@ -919,16 +1016,16 @@ }, { "name": "laravel/framework", - "version": "v5.2.29", + "version": "v5.2.39", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e3d644eb131f18c5f3d28ff7bc678bc797091f20" + "reference": "c2a77050269b4e03bd9a735a9f24e573a7598b8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e3d644eb131f18c5f3d28ff7bc678bc797091f20", - "reference": "e3d644eb131f18c5f3d28ff7bc678bc797091f20", + "url": "https://api.github.com/repos/laravel/framework/zipball/c2a77050269b4e03bd9a735a9f24e573a7598b8a", + "reference": "c2a77050269b4e03bd9a735a9f24e573a7598b8a", "shasum": "" }, "require": { @@ -989,7 +1086,7 @@ }, "require-dev": { "aws/aws-sdk-php": "~3.0", - "mockery/mockery": "~0.9.2", + "mockery/mockery": "~0.9.4", "pda/pheanstalk": "~3.0", "phpunit/phpunit": "~4.1", "predis/predis": "~1.0", @@ -1007,7 +1104,8 @@ "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).", "symfony/css-selector": "Required to use some of the crawler integration testing tools (2.8.*|3.0.*).", - "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (2.8.*|3.0.*)." + "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (2.8.*|3.0.*).", + "symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)." }, "type": "library", "extra": { @@ -1043,20 +1141,20 @@ "framework", "laravel" ], - "time": "2016-04-03 01:43:55" + "time": "2016-06-17 19:25:12" }, { "name": "laravel/socialite", - "version": "v2.0.15", + "version": "v2.0.18", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "edd00ab96933e3ef053533cce81e958fb26921af" + "reference": "76ee5397fcdea5a062361392abca4eb397e519a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/edd00ab96933e3ef053533cce81e958fb26921af", - "reference": "edd00ab96933e3ef053533cce81e958fb26921af", + "url": "https://api.github.com/repos/laravel/socialite/zipball/76ee5397fcdea5a062361392abca4eb397e519a3", + "reference": "76ee5397fcdea5a062361392abca4eb397e519a3", "shasum": "" }, "require": { @@ -1069,7 +1167,7 @@ }, "require-dev": { "mockery/mockery": "~0.9", - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.0|~5.0" }, "type": "library", "extra": { @@ -1097,20 +1195,20 @@ "laravel", "oauth" ], - "time": "2016-03-21 14:30:30" + "time": "2016-06-22 12:40:16" }, { "name": "league/flysystem", - "version": "1.0.20", + "version": "1.0.24", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "e87a786e3ae12a25cf78a71bb07b4b384bfaa83a" + "reference": "9aca859a303fdca30370f42b8c611d9cf0dedf4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e87a786e3ae12a25cf78a71bb07b4b384bfaa83a", - "reference": "e87a786e3ae12a25cf78a71bb07b4b384bfaa83a", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/9aca859a303fdca30370f42b8c611d9cf0dedf4b", + "reference": "9aca859a303fdca30370f42b8c611d9cf0dedf4b", "shasum": "" }, "require": { @@ -1180,20 +1278,20 @@ "sftp", "storage" ], - "time": "2016-03-14 21:54:11" + "time": "2016-06-03 19:11:39" }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.9", + "version": "1.0.13", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "595e24678bf78f8107ebc9355d8376ae0eb712c6" + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/595e24678bf78f8107ebc9355d8376ae0eb712c6", - "reference": "595e24678bf78f8107ebc9355d8376ae0eb712c6", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/dc56a8faf3aff0841f9eae04b6af94a50657896c", + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c", "shasum": "" }, "require": { @@ -1227,7 +1325,7 @@ } ], "description": "Flysystem adapter for the AWS S3 SDK v3.x", - "time": "2015-11-19 08:44:16" + "time": "2016-06-21 21:34:35" }, { "name": "league/oauth1-client", @@ -1355,16 +1453,16 @@ }, { "name": "monolog/monolog", - "version": "1.18.2", + "version": "1.20.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "064b38c16790249488e7a8b987acf1c9d7383c09" + "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/064b38c16790249488e7a8b987acf1c9d7383c09", - "reference": "064b38c16790249488e7a8b987acf1c9d7383c09", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037", + "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037", "shasum": "" }, "require": { @@ -1383,8 +1481,8 @@ "php-console/php-console": "^3.1.3", "phpunit/phpunit": "~4.5", "phpunit/phpunit-mock-objects": "2.3.0", - "raven/raven": "^0.13", "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", "swiftmailer/swiftmailer": "~5.3" }, "suggest": { @@ -1396,9 +1494,9 @@ "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "php-console/php-console": "Allow sending log messages to Google Chrome", - "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" }, "type": "library", "extra": { @@ -1429,7 +1527,7 @@ "logging", "psr-3" ], - "time": "2016-04-02 13:12:58" + "time": "2016-07-02 14:02:10" }, { "name": "mtdowling/cron-expression", @@ -1579,16 +1677,16 @@ }, { "name": "nikic/php-parser", - "version": "v2.0.1", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ce5be709d59b32dd8a88c80259028759991a4206" + "reference": "47b254ea51f1d6d5dc04b9b299e88346bf2369e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ce5be709d59b32dd8a88c80259028759991a4206", - "reference": "ce5be709d59b32dd8a88c80259028759991a4206", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/47b254ea51f1d6d5dc04b9b299e88346bf2369e3", + "reference": "47b254ea51f1d6d5dc04b9b299e88346bf2369e3", "shasum": "" }, "require": { @@ -1604,7 +1702,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -1626,7 +1724,7 @@ "parser", "php" ], - "time": "2016-02-28 19:48:28" + "time": "2016-04-19 13:41:41" }, { "name": "paragonie/random_compat", @@ -1710,74 +1808,25 @@ "homepage": "https://github.com/PhenX/php-font-lib", "time": "2014-02-01 15:22:28" }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "phpDocumentor": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" - } - ], - "time": "2015-02-03 12:10:50" - }, { "name": "predis/predis", - "version": "v1.0.3", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/nrk/predis.git", - "reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04" + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/84060b9034d756b4d79641667d7f9efe1aeb8e04", - "reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04", + "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3.9" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8" }, "suggest": { "ext-curl": "Allows access to Webdis when paired with phpiredis", @@ -1800,14 +1849,14 @@ "homepage": "http://clorophilla.net" } ], - "description": "Flexible and feature-complete PHP client library for Redis", + "description": "Flexible and feature-complete Redis client for PHP and HHVM", "homepage": "http://github.com/nrk/predis", "keywords": [ "nosql", "predis", "redis" ], - "time": "2015-07-30 18:34:15" + "time": "2016-06-16 16:22:20" }, { "name": "psr/http-message", @@ -1970,16 +2019,16 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v5.4.1", + "version": "v5.4.2", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421" + "reference": "d8db871a54619458a805229a057ea2af33c753e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/0697e6aa65c83edf97bb0f23d8763f94e3f11421", - "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/d8db871a54619458a805229a057ea2af33c753e8", + "reference": "d8db871a54619458a805229a057ea2af33c753e8", "shasum": "" }, "require": { @@ -2019,20 +2068,20 @@ "mail", "mailer" ], - "time": "2015-06-06 14:19:39" + "time": "2016-05-01 08:45:47" }, { "name": "symfony/class-loader", - "version": "v3.0.4", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "cbb7e6a9c0213a0cffa5d9065ee8214ca4e83877" + "reference": "0d0ac77c336eb73f35bebdf3e1f3695ac741bbc9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/cbb7e6a9c0213a0cffa5d9065ee8214ca4e83877", - "reference": "cbb7e6a9c0213a0cffa5d9065ee8214ca4e83877", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/0d0ac77c336eb73f35bebdf3e1f3695ac741bbc9", + "reference": "0d0ac77c336eb73f35bebdf3e1f3695ac741bbc9", "shasum": "" }, "require": { @@ -2048,7 +2097,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2075,20 +2124,20 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2016-03-30 10:41:14" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/console", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6b1175135bc2a74c08a28d89761272de8beed8cd" + "reference": "a7abb7153f6d1da47f87ec50274844e246b09d9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6b1175135bc2a74c08a28d89761272de8beed8cd", - "reference": "6b1175135bc2a74c08a28d89761272de8beed8cd", + "url": "https://api.github.com/repos/symfony/console/zipball/a7abb7153f6d1da47f87ec50274844e246b09d9f", + "reference": "a7abb7153f6d1da47f87ec50274844e246b09d9f", "shasum": "" }, "require": { @@ -2135,20 +2184,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-03-16 17:00:50" + "time": "2016-06-29 07:02:21" }, { "name": "symfony/debug", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "a06d10888a45afd97534506afb058ec38d9ba35b" + "reference": "c54bc3539c3b87e86799533801e8ae0e971d78c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/a06d10888a45afd97534506afb058ec38d9ba35b", - "reference": "a06d10888a45afd97534506afb058ec38d9ba35b", + "url": "https://api.github.com/repos/symfony/debug/zipball/c54bc3539c3b87e86799533801e8ae0e971d78c2", + "reference": "c54bc3539c3b87e86799533801e8ae0e971d78c2", "shasum": "" }, "require": { @@ -2192,20 +2241,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-03-30 10:41:14" + "time": "2016-06-29 05:40:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.0.4", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9002dcf018d884d294b1ef20a6f968efc1128f39" + "reference": "7f9839ede2070f53e7e2f0849b9bd14748c434c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9002dcf018d884d294b1ef20a6f968efc1128f39", - "reference": "9002dcf018d884d294b1ef20a6f968efc1128f39", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7f9839ede2070f53e7e2f0849b9bd14748c434c5", + "reference": "7f9839ede2070f53e7e2f0849b9bd14748c434c5", "shasum": "" }, "require": { @@ -2225,7 +2274,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2252,20 +2301,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-03-10 10:34:12" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/finder", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "c54e407b35bc098916704e9fd090da21da4c4f52" + "reference": "3eb4e64c6145ef8b92adefb618a74ebdde9e3fe9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/c54e407b35bc098916704e9fd090da21da4c4f52", - "reference": "c54e407b35bc098916704e9fd090da21da4c4f52", + "url": "https://api.github.com/repos/symfony/finder/zipball/3eb4e64c6145ef8b92adefb618a74ebdde9e3fe9", + "reference": "3eb4e64c6145ef8b92adefb618a74ebdde9e3fe9", "shasum": "" }, "require": { @@ -2301,20 +2350,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-03-10 11:13:05" + "time": "2016-06-29 05:40:00" }, { "name": "symfony/http-foundation", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "99f38445a874e7becb8afc4b4a79ee181cf6ec3f" + "reference": "1341139f906d295baa4f4abd55293d07e25a065a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/99f38445a874e7becb8afc4b4a79ee181cf6ec3f", - "reference": "99f38445a874e7becb8afc4b4a79ee181cf6ec3f", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1341139f906d295baa4f4abd55293d07e25a065a", + "reference": "1341139f906d295baa4f4abd55293d07e25a065a", "shasum": "" }, "require": { @@ -2354,20 +2403,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2016-03-27 14:50:32" + "time": "2016-06-29 07:02:21" }, { "name": "symfony/http-kernel", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "579f828489659d7b3430f4bd9b67b4618b387dea" + "reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/579f828489659d7b3430f4bd9b67b4618b387dea", - "reference": "579f828489659d7b3430f4bd9b67b4618b387dea", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/177b63b2d50b63fa6d82ea41359ed9928cc7a1fb", + "reference": "177b63b2d50b63fa6d82ea41359ed9928cc7a1fb", "shasum": "" }, "require": { @@ -2375,7 +2424,7 @@ "psr/log": "~1.0", "symfony/debug": "~2.8|~3.0", "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/http-foundation": "~2.8|~3.0" + "symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2" }, "conflict": { "symfony/config": "<2.8" @@ -2436,20 +2485,20 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-03-25 01:41:20" + "time": "2016-06-30 16:30:17" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" + "reference": "dff51f72b0706335131b00a7f49606168c582594" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", "shasum": "" }, "require": { @@ -2461,7 +2510,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2495,20 +2544,20 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/polyfill-php56", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php56.git", - "reference": "4d891fff050101a53a4caabb03277284942d1ad9" + "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/4d891fff050101a53a4caabb03277284942d1ad9", - "reference": "4d891fff050101a53a4caabb03277284942d1ad9", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/3edf57a8fbf9a927533344cef65ad7e1cf31030a", + "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a", "shasum": "" }, "require": { @@ -2518,7 +2567,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2551,20 +2600,20 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/polyfill-util", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-util.git", - "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4" + "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4", - "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ef830ce3d218e622b221d6bfad42c751d974bf99", + "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99", "shasum": "" }, "require": { @@ -2573,7 +2622,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2603,20 +2652,20 @@ "polyfill", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/process", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e6f1f98bbd355d209a992bfff45e7edfbd4a0776" + "reference": "d7cde1f9d94d87060204f863779389b61c382eeb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e6f1f98bbd355d209a992bfff45e7edfbd4a0776", - "reference": "e6f1f98bbd355d209a992bfff45e7edfbd4a0776", + "url": "https://api.github.com/repos/symfony/process/zipball/d7cde1f9d94d87060204f863779389b61c382eeb", + "reference": "d7cde1f9d94d87060204f863779389b61c382eeb", "shasum": "" }, "require": { @@ -2652,20 +2701,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-03-30 10:41:14" + "time": "2016-06-29 05:40:00" }, { "name": "symfony/routing", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "d061b609f2d0769494c381ec92f5c5cc5e4a20aa" + "reference": "9038984bd9c05ab07280121e9e10f61a7231457b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/d061b609f2d0769494c381ec92f5c5cc5e4a20aa", - "reference": "d061b609f2d0769494c381ec92f5c5cc5e4a20aa", + "url": "https://api.github.com/repos/symfony/routing/zipball/9038984bd9c05ab07280121e9e10f61a7231457b", + "reference": "9038984bd9c05ab07280121e9e10f61a7231457b", "shasum": "" }, "require": { @@ -2727,20 +2776,20 @@ "uri", "url" ], - "time": "2016-03-23 13:23:25" + "time": "2016-06-29 05:40:00" }, { "name": "symfony/translation", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "f7a07af51ea067745a521dab1e3152044a2fb1f2" + "reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/f7a07af51ea067745a521dab1e3152044a2fb1f2", - "reference": "f7a07af51ea067745a521dab1e3152044a2fb1f2", + "url": "https://api.github.com/repos/symfony/translation/zipball/6bf844e1ee3c820c012386c10427a5c67bbefec8", + "reference": "6bf844e1ee3c820c012386c10427a5c67bbefec8", "shasum": "" }, "require": { @@ -2791,20 +2840,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-03-25 01:41:20" + "time": "2016-06-29 05:40:00" }, { "name": "symfony/var-dumper", - "version": "v3.0.4", + "version": "v3.0.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "3841ed86527d18ee2c35fe4afb1b2fc60f8fae79" + "reference": "2f046e9a9d571f22cc8b26783564876713b06579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3841ed86527d18ee2c35fe4afb1b2fc60f8fae79", - "reference": "3841ed86527d18ee2c35fe4afb1b2fc60f8fae79", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2f046e9a9d571f22cc8b26783564876713b06579", + "reference": "2f046e9a9d571f22cc8b26783564876713b06579", "shasum": "" }, "require": { @@ -2854,32 +2903,32 @@ "debug", "dump" ], - "time": "2016-03-10 10:34:12" + "time": "2016-06-29 05:40:00" }, { "name": "vlucas/phpdotenv", - "version": "v2.2.0", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "9caf304153dc2288e4970caec6f1f3b3bc205412" + "reference": "9ca5644c536654e9509b9d257f53c58630eb2a6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/9caf304153dc2288e4970caec6f1f3b3bc205412", - "reference": "9caf304153dc2288e4970caec6f1f3b3bc205412", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/9ca5644c536654e9509b9d257f53c58630eb2a6a", + "reference": "9ca5644c536654e9509b9d257f53c58630eb2a6a", "shasum": "" }, "require": { "php": ">=5.3.9" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.0" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-master": "2.3-dev" } }, "autoload": { @@ -2889,7 +2938,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD" + "BSD-3-Clause-Attribution" ], "authors": [ { @@ -2899,13 +2948,12 @@ } ], "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", - "homepage": "http://github.com/vlucas/phpdotenv", "keywords": [ "dotenv", "env", "environment" ], - "time": "2015-12-29 15:10:30" + "time": "2016-06-14 14:14:52" } ], "packages-dev": [ @@ -2965,33 +3013,29 @@ }, { "name": "fzaninotto/faker", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/fzaninotto/Faker.git", - "reference": "d0190b156bcca848d401fb80f31f504f37141c8d" + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d0190b156bcca848d401fb80f31f504f37141c8d", - "reference": "d0190b156bcca848d401fb80f31f504f37141c8d", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/44f9a286a04b80c76a4e5fb7aad8bb539b920123", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3|^7.0" }, "require-dev": { + "ext-intl": "*", "phpunit/phpunit": "~4.0", "squizlabs/php_codesniffer": "~1.5" }, - "suggest": { - "ext-intl": "*" - }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5.x-dev" - } + "branch-alias": [] }, "autoload": { "psr-4": { @@ -3013,7 +3057,7 @@ "faker", "fixtures" ], - "time": "2015-05-29 06:29:14" + "time": "2016-04-29 12:21:54" }, { "name": "hamcrest/hamcrest-php", @@ -3062,16 +3106,16 @@ }, { "name": "mockery/mockery", - "version": "0.9.4", + "version": "0.9.5", "source": { "type": "git", "url": "https://github.com/padraic/mockery.git", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b" + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b", + "url": "https://api.github.com/repos/padraic/mockery/zipball/4db079511a283e5aba1b3c2fb19037c645e70fc2", + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2", "shasum": "" }, "require": { @@ -3123,7 +3167,153 @@ "test double", "testing" ], - "time": "2015-04-02 19:54:00" + "time": "2016-05-22 21:52:33" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-06-10 09:48:41" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-06-10 07:14:17" }, { "name": "phpspec/php-diff", @@ -3239,32 +3429,32 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.0", + "version": "v1.6.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972" + "reference": "58a8137754bc24b25740d4281399a4a3596058e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1", - "sebastian/recursion-context": "~1.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0" }, "require-dev": { - "phpspec/phpspec": "~2.0" + "phpspec/phpspec": "^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -3297,7 +3487,7 @@ "spy", "stub" ], - "time": "2016-02-15 07:46:21" + "time": "2016-06-07 08:13:47" }, { "name": "phpunit/php-code-coverage", @@ -3451,21 +3641,24 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, "type": "library", "autoload": { "classmap": [ @@ -3488,7 +3681,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2016-05-12 18:03:57" }, { "name": "phpunit/php-token-stream", @@ -3541,16 +3734,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.8.24", + "version": "4.8.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a1066c562c52900a142a0e2bbf0582994671385e" + "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1066c562c52900a142a0e2bbf0582994671385e", - "reference": "a1066c562c52900a142a0e2bbf0582994671385e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74", + "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74", "shasum": "" }, "require": { @@ -3564,7 +3757,7 @@ "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": ">=1.0.6", + "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", @@ -3609,7 +3802,7 @@ "testing", "xunit" ], - "time": "2016-03-14 06:16:08" + "time": "2016-05-17 03:09:28" }, { "name": "phpunit/phpunit-mock-objects", @@ -3785,16 +3978,16 @@ }, { "name": "sebastian/environment", - "version": "1.3.5", + "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", "shasum": "" }, "require": { @@ -3831,20 +4024,20 @@ "environment", "hhvm" ], - "time": "2016-02-26 18:40:46" + "time": "2016-05-17 03:18:57" }, { "name": "sebastian/exporter", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", "shasum": "" }, "require": { @@ -3852,12 +4045,13 @@ "sebastian/recursion-context": "~1.0" }, "require-dev": { + "ext-mbstring": "*", "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -3897,7 +4091,7 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2016-06-17 09:04:28" }, { "name": "sebastian/global-state", @@ -4040,16 +4234,16 @@ }, { "name": "symfony/css-selector", - "version": "v3.0.4", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "65e764f404685f2dc20c057e889b3ad04b2e2db0" + "reference": "2851e1932d77ce727776154d659b232d061e816a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/65e764f404685f2dc20c057e889b3ad04b2e2db0", - "reference": "65e764f404685f2dc20c057e889b3ad04b2e2db0", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/2851e1932d77ce727776154d659b232d061e816a", + "reference": "2851e1932d77ce727776154d659b232d061e816a", "shasum": "" }, "require": { @@ -4058,7 +4252,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4089,20 +4283,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2016-03-04 07:55:57" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/dom-crawler", - "version": "v3.0.4", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "18a06d7a9af41718c20764a674a0ebba3bc40d1f" + "reference": "99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/18a06d7a9af41718c20764a674a0ebba3bc40d1f", - "reference": "18a06d7a9af41718c20764a674a0ebba3bc40d1f", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0", + "reference": "99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0", "shasum": "" }, "require": { @@ -4118,7 +4312,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4145,20 +4339,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2016-03-23 13:23:25" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/yaml", - "version": "v3.0.4", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "0047c8366744a16de7516622c5b7355336afae96" + "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/0047c8366744a16de7516622c5b7355336afae96", - "reference": "0047c8366744a16de7516622c5b7355336afae96", + "url": "https://api.github.com/repos/symfony/yaml/zipball/2884c26ce4c1d61aebf423a8b912950fe7c764de", + "reference": "2884c26ce4c1d61aebf423a8b912950fe7c764de", "shasum": "" }, "require": { @@ -4167,7 +4361,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4194,7 +4388,56 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-03-04 07:55:57" + "time": "2016-06-29 05:41:56" + }, + { + "name": "webmozart/assert", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", + "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2015-08-24 13:29:44" } ], "aliases": [], diff --git a/resources/assets/sass/_pages.scss b/resources/assets/sass/_pages.scss old mode 100644 new mode 100755 index 49b701dda..2a27fadb9 --- a/resources/assets/sass/_pages.scss +++ b/resources/assets/sass/_pages.scss @@ -60,6 +60,18 @@ word-break: break-word; hyphens: auto; } + + // diffs + .diff-html-removed, + .diff-html-added { + text-decoration: none; + } + .diff-html-added { + background: rgba(45, 255, 0, 0.2); + } + .diff-html-removed { + background: rgba(255, 0, 0, 0.2); + } } // Page content pointers diff --git a/resources/views/pages/page-display.blade.php b/resources/views/pages/page-display.blade.php index d0bdcf880..17ac115b8 100644 --- a/resources/views/pages/page-display.blade.php +++ b/resources/views/pages/page-display.blade.php @@ -18,5 +18,9 @@
- {!! $page->html !!} + @if (isset($diff) && $diff) + {!! $diff !!} + @else + {!! $page->html !!} + @endif \ No newline at end of file From c279c6e2af60274871a5e2d3082e8cae444ece18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=C3=A8s=20EL=20BIACHE?= Date: Sun, 10 Jul 2016 11:53:37 +0200 Subject: [PATCH 02/27] replace GPL diff lib with MIT lib replace gpl lib with mit lib --- app/Http/Controllers/PageController.php | 7 +- composer.json | 4 +- composer.lock | 192 ++++++++++++++++++------ resources/assets/sass/_pages.scss | 12 +- 4 files changed, 158 insertions(+), 57 deletions(-) diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 1844e0c0c..fc71292e0 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -12,7 +12,7 @@ use BookStack\Repos\ChapterRepo; use BookStack\Repos\PageRepo; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Views; -use Icap\HtmlDiff\HtmlDiff; +use GatherContent\Htmldiff\Htmldiff; class PageController extends Controller { @@ -334,9 +334,8 @@ class PageController extends Controller $page = $this->pageRepo->getBySlug($pageSlug, $book->id); $revision = $this->pageRepo->getRevisionById($revisionId); - $next = $revision->getNext() ?: $page; - $htmlDiff = new HtmlDiff($revision->html, $next->html, true); - $diff = $htmlDiff->outputDiff()->toString(); + $next = $revision->getNext() ?: $page; + $diff = (new Htmldiff)->diff($revision->html, $next->html); $page->fill($revision->toArray()); $this->setPageTitle('Page Revision For ' . $page->getShortName()); diff --git a/composer.json b/composer.json index 41f1ada5d..d1f99a8f3 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,8 @@ "type": "project", "require": { "php": ">=5.5.9", + "ext-tidy": "*", + "laravel/framework": "5.2.*", "intervention/image": "^2.3", "laravel/socialite": "^2.0", @@ -14,7 +16,7 @@ "league/flysystem-aws-s3-v3": "^1.0", "barryvdh/laravel-dompdf": "0.6.*", "predis/predis": "^1.0", - "icap/html-diff": "^1.1" + "gathercontent/htmldiff": "^0.2.1" }, "require-dev": { "fzaninotto/faker": "~1.4", diff --git a/composer.lock b/composer.lock index f97aeb992..98fb86ce5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "3d8e2dfddefb412055d28ffc922969fd", - "content-hash": "7658fea0b4df71cf7b97bcdf8a29b9eb", + "hash": "097beaeb7ce90384b824d65d9dd36520", + "content-hash": "233ce3d93ee0c9b005c263ff1449ae0f", "packages": [ { "name": "aws/aws-sdk-php", @@ -358,6 +358,57 @@ ], "time": "2015-11-09 22:51:51" }, + { + "name": "cogpowered/finediff", + "version": "0.3.1", + "source": { + "type": "git", + "url": "https://github.com/cogpowered/FineDiff.git", + "reference": "339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cogpowered/FineDiff/zipball/339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8", + "reference": "339ddc8c3afb656efed4f2f0a80e5c3d026f8ea8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "mockery/mockery": "*", + "phpunit/phpunit": "*" + }, + "type": "library", + "autoload": { + "psr-0": { + "cogpowered\\FineDiff": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rob Crowe", + "email": "rob@cogpowered.com" + }, + { + "name": "Raymond Hill" + } + ], + "description": "PHP implementation of a Fine granularity Diff engine", + "homepage": "https://github.com/cogpowered/FineDiff", + "keywords": [ + "diff", + "finediff", + "opcode", + "string", + "text" + ], + "time": "2014-05-19 10:25:02" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "0.1", @@ -499,6 +550,55 @@ "homepage": "https://github.com/dompdf/dompdf", "time": "2015-12-07 04:07:13" }, + { + "name": "gathercontent/htmldiff", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/gathercontent/htmldiff.git", + "reference": "24674a62315f64330134b4a4c5b01a7b59193c93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/gathercontent/htmldiff/zipball/24674a62315f64330134b4a4c5b01a7b59193c93", + "reference": "24674a62315f64330134b4a4c5b01a7b59193c93", + "shasum": "" + }, + "require": { + "cogpowered/finediff": "0.3.1", + "ext-tidy": "*" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "GatherContent\\Htmldiff": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andrew Cairns", + "email": "andrew@gathercontent.com" + }, + { + "name": "Mathew Chapman", + "email": "mat@gathercontent.com" + }, + { + "name": "Peter Legierski", + "email": "peter@gathercontent.com" + } + ], + "description": "Compare two HTML strings", + "time": "2015-04-15 15:39:46" + }, { "name": "guzzle/guzzle", "version": "v3.8.1", @@ -763,50 +863,6 @@ ], "time": "2016-06-24 23:00:38" }, - { - "name": "icap/html-diff", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/iCAPLyon1/HtmlDiff.git", - "reference": "f58ddb196292ae585a2efb7692653d015ecc436f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/iCAPLyon1/HtmlDiff/zipball/f58ddb196292ae585a2efb7692653d015ecc436f", - "reference": "f58ddb196292ae585a2efb7692653d015ecc436f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "php": ">=5.3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Icap\\HtmlDiff\\": "src/Icap/HtmlDiff" - } - }, - "notification-url": "https://packagist.org/downloads/", - "authors": [ - { - "name": "Panagiotis Tsavdaris", - "email": "ptsavdar@gmail.com" - }, - { - "name": "ICAP development team", - "homepage": "https://github.com/iCAPLyon1" - } - ], - "description": "A PHP5 library that diffs (compares) HTML files.", - "keywords": [ - "daisy diff", - "html diff" - ], - "time": "2016-02-17 16:35:09" - }, { "name": "intervention/image", "version": "2.3.7", @@ -3104,6 +3160,50 @@ ], "time": "2015-05-11 14:41:42" }, + { + "name": "icap/html-diff", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/iCAPLyon1/HtmlDiff.git", + "reference": "f58ddb196292ae585a2efb7692653d015ecc436f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/iCAPLyon1/HtmlDiff/zipball/f58ddb196292ae585a2efb7692653d015ecc436f", + "reference": "f58ddb196292ae585a2efb7692653d015ecc436f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Icap\\HtmlDiff\\": "src/Icap/HtmlDiff" + } + }, + "notification-url": "https://packagist.org/downloads/", + "authors": [ + { + "name": "Panagiotis Tsavdaris", + "email": "ptsavdar@gmail.com" + }, + { + "name": "ICAP development team", + "homepage": "https://github.com/iCAPLyon1" + } + ], + "description": "A PHP5 library that diffs (compares) HTML files.", + "keywords": [ + "daisy diff", + "html diff" + ], + "time": "2016-02-17 16:35:09" + }, { "name": "mockery/mockery", "version": "0.9.5", diff --git a/resources/assets/sass/_pages.scss b/resources/assets/sass/_pages.scss index 2a27fadb9..562bc9a47 100755 --- a/resources/assets/sass/_pages.scss +++ b/resources/assets/sass/_pages.scss @@ -62,15 +62,15 @@ } // diffs - .diff-html-removed, - .diff-html-added { + ins, + del { text-decoration: none; } - .diff-html-added { - background: rgba(45, 255, 0, 0.2); + ins { + background: #dbffdb; } - .diff-html-removed { - background: rgba(255, 0, 0, 0.2); + del { + background: #FFECEC; } } From 9dc9724e15bdd6d2bd316f7fa24592da72124bc5 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 17 Sep 2016 18:22:04 +0100 Subject: [PATCH 03/27] Laravel 5.3 upgrade (#189) * Started move to laravel 5.3 * Started updating login & registration flows for laravel 5.3 update * Updated app emails to notification system * Fixed registations bugs and removed email confirmation model * Fixed large portion of laravel post-upgrade issues * Fixed and tested LDAP process --- .gitignore | 3 +- app/EmailConfirmation.php | 16 - app/Events/Event.php | 8 - app/Exceptions/Handler.php | 16 + .../Auth/ForgotPasswordController.php | 33 + app/Http/Controllers/Auth/LoginController.php | 123 ++ ...hController.php => RegisterController.php} | 186 +-- ...roller.php => ResetPasswordController.php} | 11 +- app/Http/Controllers/Controller.php | 23 +- app/Http/Kernel.php | 28 +- app/Http/Middleware/Authenticate.php | 2 +- .../Middleware/RedirectIfAuthenticated.php | 3 +- app/Jobs/Job.php | 21 - app/Listeners/.gitkeep | 0 app/Notifications/ConfirmEmail.php | 48 + app/Notifications/ResetPassword.php | 50 + app/Providers/BroadcastServiceProvider.php | 26 + app/Providers/EventServiceProvider.php | 7 +- app/Providers/PaginationServiceProvider.php | 9 +- app/Providers/RouteServiceProvider.php | 47 +- app/Repos/PageRepo.php | 29 +- app/Services/EmailConfirmationService.php | 63 +- app/Services/PermissionService.php | 106 +- app/User.php | 14 +- app/helpers.php | 8 +- composer.json | 37 +- composer.lock | 1457 ++++++++++------- config/app.php | 3 + ...08_29_105422_add_roles_and_permissions.php | 2 +- phpspec.yml | 5 - resources/lang/en/auth.php | 15 + .../email.blade.php} | 0 .../auth/{ => passwords}/reset.blade.php | 0 .../views/emails/email-confirmation.blade.php | 190 --- resources/views/emails/password.blade.php | 1 - resources/views/users/index.blade.php | 4 +- resources/views/vendor/.gitkeep | 0 .../notifications/email-plain.blade.php | 22 + .../vendor/notifications/email.blade.php | 206 +++ app/Http/routes.php => routes/web.php | 38 +- tests/Auth/AuthTest.php | 34 +- tests/Entity/EntityTest.php | 5 +- tests/Entity/PageDraftTest.php | 2 +- tests/ImageTest.php | 8 +- 44 files changed, 1799 insertions(+), 1110 deletions(-) delete mode 100644 app/EmailConfirmation.php delete mode 100644 app/Events/Event.php create mode 100644 app/Http/Controllers/Auth/ForgotPasswordController.php create mode 100644 app/Http/Controllers/Auth/LoginController.php rename app/Http/Controllers/Auth/{AuthController.php => RegisterController.php} (68%) rename app/Http/Controllers/Auth/{PasswordController.php => ResetPasswordController.php} (82%) delete mode 100644 app/Jobs/Job.php delete mode 100644 app/Listeners/.gitkeep create mode 100644 app/Notifications/ConfirmEmail.php create mode 100644 app/Notifications/ResetPassword.php create mode 100644 app/Providers/BroadcastServiceProvider.php delete mode 100644 phpspec.yml create mode 100644 resources/lang/en/auth.php rename resources/views/auth/{password.blade.php => passwords/email.blade.php} (100%) rename resources/views/auth/{ => passwords}/reset.blade.php (100%) delete mode 100644 resources/views/emails/email-confirmation.blade.php delete mode 100644 resources/views/emails/password.blade.php delete mode 100644 resources/views/vendor/.gitkeep create mode 100644 resources/views/vendor/notifications/email-plain.blade.php create mode 100644 resources/views/vendor/notifications/email.blade.php rename app/Http/routes.php => routes/web.php (84%) diff --git a/.gitignore b/.gitignore index 69f0e2909..7417bbdd8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ Homestead.yaml /public/bower /storage/images _ide_helper.php -/storage/debugbar \ No newline at end of file +/storage/debugbar +.phpstorm.meta.php \ No newline at end of file diff --git a/app/EmailConfirmation.php b/app/EmailConfirmation.php deleted file mode 100644 index e77b754bb..000000000 --- a/app/EmailConfirmation.php +++ /dev/null @@ -1,16 +0,0 @@ -belongsTo(User::class); - } - -} diff --git a/app/Events/Event.php b/app/Events/Event.php deleted file mode 100644 index dfe173828..000000000 --- a/app/Events/Event.php +++ /dev/null @@ -1,8 +0,0 @@ -getPrevious()); return $message; } + + /** + * Convert an authentication exception into an unauthenticated response. + * + * @param \Illuminate\Http\Request $request + * @param \Illuminate\Auth\AuthenticationException $exception + * @return \Illuminate\Http\Response + */ + protected function unauthenticated($request, AuthenticationException $exception) + { + if ($request->expectsJson()) { + return response()->json(['error' => 'Unauthenticated.'], 401); + } + + return redirect()->guest('login'); + } } diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php new file mode 100644 index 000000000..d93854e23 --- /dev/null +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -0,0 +1,33 @@ +middleware('guest'); + parent::__construct(); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php new file mode 100644 index 000000000..0de4a8282 --- /dev/null +++ b/app/Http/Controllers/Auth/LoginController.php @@ -0,0 +1,123 @@ +middleware('guest', ['only' => ['getLogin', 'postLogin']]); + $this->socialAuthService = $socialAuthService; + $this->userRepo = $userRepo; + $this->redirectPath = baseUrl('/'); + $this->redirectAfterLogout = baseUrl('/login'); + parent::__construct(); + } + + public function username() + { + return config('auth.method') === 'standard' ? 'email' : 'username'; + } + + /** + * Overrides the action when a user is authenticated. + * If the user authenticated but does not exist in the user table we create them. + * @param Request $request + * @param Authenticatable $user + * @return \Illuminate\Http\RedirectResponse + * @throws AuthException + */ + protected function authenticated(Request $request, Authenticatable $user) + { + // Explicitly log them out for now if they do no exist. + if (!$user->exists) auth()->logout($user); + + if (!$user->exists && $user->email === null && !$request->has('email')) { + $request->flash(); + session()->flash('request-email', true); + return redirect('/login'); + } + + if (!$user->exists && $user->email === null && $request->has('email')) { + $user->email = $request->get('email'); + } + + if (!$user->exists) { + + // Check for users with same email already + $alreadyUser = $user->newQuery()->where('email', '=', $user->email)->count() > 0; + if ($alreadyUser) { + throw new AuthException('A user with the email ' . $user->email . ' already exists but with different credentials.'); + } + + $user->save(); + $this->userRepo->attachDefaultRole($user); + auth()->login($user); + } + + $path = session()->pull('url.intended', '/'); + $path = baseUrl($path, true); + return redirect($path); + } + + /** + * Show the application login form. + * @return \Illuminate\Http\Response + */ + public function getLogin() + { + $socialDrivers = $this->socialAuthService->getActiveDrivers(); + $authMethod = config('auth.method'); + return view('auth/login', ['socialDrivers' => $socialDrivers, 'authMethod' => $authMethod]); + } + + /** + * Redirect to the relevant social site. + * @param $socialDriver + * @return \Symfony\Component\HttpFoundation\RedirectResponse + */ + public function getSocialLogin($socialDriver) + { + session()->put('social-callback', 'login'); + return $this->socialAuthService->startLogIn($socialDriver); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/RegisterController.php similarity index 68% rename from app/Http/Controllers/Auth/AuthController.php rename to app/Http/Controllers/Auth/RegisterController.php index f2d3b2741..5b3719bc0 100644 --- a/app/Http/Controllers/Auth/AuthController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -1,62 +1,68 @@ -middleware('guest', ['only' => ['getLogin', 'postLogin', 'getRegister', 'postRegister']]); + $this->middleware('guest'); $this->socialAuthService = $socialAuthService; $this->emailConfirmationService = $emailConfirmationService; $this->userRepo = $userRepo; + $this->redirectTo = baseUrl('/'); $this->redirectPath = baseUrl('/'); - $this->redirectAfterLogout = baseUrl('/login'); $this->username = config('auth.method') === 'standard' ? 'email' : 'username'; parent::__construct(); } /** * Get a validator for an incoming registration request. + * * @param array $data * @return \Illuminate\Contracts\Validation\Validator */ @@ -69,6 +75,10 @@ class AuthController extends Controller ]); } + /** + * Check whether or not registrations are allowed in the app settings. + * @throws UserRegistrationException + */ protected function checkRegistrationAllowed() { if (!setting('registration-enabled')) { @@ -78,7 +88,7 @@ class AuthController extends Controller /** * Show the application registration form. - * @return \Illuminate\Http\Response + * @return Response */ public function getRegister() { @@ -89,9 +99,10 @@ class AuthController extends Controller /** * Handle a registration request for the application. - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response + * @param Request|\Illuminate\Http\Request $request + * @return Response * @throws UserRegistrationException + * @throws \Illuminate\Foundation\Validation\ValidationException */ public function postRegister(Request $request) { @@ -108,66 +119,18 @@ class AuthController extends Controller return $this->registerUser($userData); } - /** - * Overrides the action when a user is authenticated. - * If the user authenticated but does not exist in the user table we create them. - * @param Request $request - * @param Authenticatable $user - * @return \Illuminate\Http\RedirectResponse - * @throws AuthException + * Create a new user instance after a valid registration. + * @param array $data + * @return User */ - protected function authenticated(Request $request, Authenticatable $user) + protected function create(array $data) { - // Explicitly log them out for now if they do no exist. - if (!$user->exists) auth()->logout($user); - - if (!$user->exists && $user->email === null && !$request->has('email')) { - $request->flash(); - session()->flash('request-email', true); - return redirect('/login'); - } - - if (!$user->exists && $user->email === null && $request->has('email')) { - $user->email = $request->get('email'); - } - - if (!$user->exists) { - - // Check for users with same email already - $alreadyUser = $user->newQuery()->where('email', '=', $user->email)->count() > 0; - if ($alreadyUser) { - throw new AuthException('A user with the email ' . $user->email . ' already exists but with different credentials.'); - } - - $user->save(); - $this->userRepo->attachDefaultRole($user); - auth()->login($user); - } - - $path = session()->pull('url.intended', '/'); - $path = baseUrl($path, true); - return redirect($path); - } - - /** - * Register a new user after a registration callback. - * @param $socialDriver - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - * @throws UserRegistrationException - */ - protected function socialRegisterCallback($socialDriver) - { - $socialUser = $this->socialAuthService->handleRegistrationCallback($socialDriver); - $socialAccount = $this->socialAuthService->fillSocialAccount($socialDriver, $socialUser); - - // Create an array of the user data to create a new user instance - $userData = [ - 'name' => $socialUser->getName(), - 'email' => $socialUser->getEmail(), - 'password' => str_random(30) - ]; - return $this->registerUser($userData, $socialAccount); + return User::create([ + 'name' => $data['name'], + 'email' => $data['email'], + 'password' => bcrypt($data['password']), + ]); } /** @@ -176,7 +139,7 @@ class AuthController extends Controller * @param bool|false|SocialAccount $socialAccount * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector * @throws UserRegistrationException - * @throws \BookStack\Exceptions\ConfirmationEmailException + * @throws ConfirmationEmailException */ protected function registerUser(array $userData, $socialAccount = false) { @@ -213,18 +176,6 @@ class AuthController extends Controller return view('auth/register-confirm'); } - /** - * View the confirmation email as a standard web page. - * @param $token - * @return \Illuminate\View\View - * @throws UserRegistrationException - */ - public function viewConfirmEmail($token) - { - $confirmation = $this->emailConfirmationService->getEmailConfirmationFromToken($token); - return view('emails/email-confirmation', ['token' => $confirmation->token]); - } - /** * Confirms an email via a token and logs the user into the system. * @param $token @@ -237,7 +188,7 @@ class AuthController extends Controller $user = $confirmation->user; $user->email_confirmed = true; $user->save(); - auth()->login($confirmation->user); + auth()->login($user); session()->flash('success', 'Your email has been confirmed!'); $this->emailConfirmationService->deleteConfirmationsByUser($user); return redirect($this->redirectPath); @@ -269,28 +220,6 @@ class AuthController extends Controller return redirect('/register/confirm'); } - /** - * Show the application login form. - * @return \Illuminate\Http\Response - */ - public function getLogin() - { - $socialDrivers = $this->socialAuthService->getActiveDrivers(); - $authMethod = config('auth.method'); - return view('auth/login', ['socialDrivers' => $socialDrivers, 'authMethod' => $authMethod]); - } - - /** - * Redirect to the relevant social site. - * @param $socialDriver - * @return \Symfony\Component\HttpFoundation\RedirectResponse - */ - public function getSocialLogin($socialDriver) - { - session()->put('social-callback', 'login'); - return $this->socialAuthService->startLogIn($socialDriver); - } - /** * Redirect to the social site for authentication intended to register. * @param $socialDriver @@ -334,4 +263,25 @@ class AuthController extends Controller return $this->socialAuthService->detachSocialAccount($socialDriver); } -} + /** + * Register a new user after a registration callback. + * @param $socialDriver + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws UserRegistrationException + */ + protected function socialRegisterCallback($socialDriver) + { + $socialUser = $this->socialAuthService->handleRegistrationCallback($socialDriver); + $socialAccount = $this->socialAuthService->fillSocialAccount($socialDriver, $socialUser); + + // Create an array of the user data to create a new user instance + $userData = [ + 'name' => $socialUser->getName(), + 'email' => $socialUser->getEmail(), + 'password' => str_random(30) + ]; + return $this->registerUser($userData, $socialAccount); + } + + +} \ No newline at end of file diff --git a/app/Http/Controllers/Auth/PasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php similarity index 82% rename from app/Http/Controllers/Auth/PasswordController.php rename to app/Http/Controllers/Auth/ResetPasswordController.php index 038e444d2..656b8cc42 100644 --- a/app/Http/Controllers/Auth/PasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -5,7 +5,7 @@ namespace BookStack\Http\Controllers\Auth; use BookStack\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; -class PasswordController extends Controller +class ResetPasswordController extends Controller { /* |-------------------------------------------------------------------------- @@ -20,13 +20,14 @@ class PasswordController extends Controller use ResetsPasswords; - protected $redirectTo = '/'; - /** - * Create a new password controller instance. + * Create a new controller instance. + * + * @return void */ public function __construct() { $this->middleware('guest'); + parent::__construct(); } -} +} \ No newline at end of file diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 26eeb3002..43292d941 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -30,17 +30,22 @@ abstract class Controller extends BaseController */ public function __construct() { - // Get a user instance for the current user - $user = auth()->user(); - if (!$user) $user = User::getDefault(); + $this->middleware(function ($request, $next) { - // Share variables with views - view()->share('signedIn', auth()->check()); - view()->share('currentUser', $user); + // Get a user instance for the current user + $user = auth()->user(); + if (!$user) $user = User::getDefault(); - // Share variables with controllers - $this->currentUser = $user; - $this->signedIn = auth()->check(); + // Share variables with views + view()->share('signedIn', auth()->check()); + view()->share('currentUser', $user); + + // Share variables with controllers + $this->currentUser = $user; + $this->signedIn = auth()->check(); + + return $next($request); + }); } /** diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index a1f2a581f..f1d95f5c0 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -9,15 +9,32 @@ class Kernel extends HttpKernel /** * The application's global HTTP middleware stack. * + * These middleware are run during every request to your application. + * * @var array */ protected $middleware = [ \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, - \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, + ]; + + /** + * The application's route middleware groups. + * + * @var array + */ + protected $middlewareGroups = [ + '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, + ], + 'api' => [ + 'throttle:60,1', + 'bindings', + ], ]; /** @@ -26,6 +43,7 @@ class Kernel extends HttpKernel * @var array */ protected $routeMiddleware = [ + 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'auth' => \BookStack\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \BookStack\Http\Middleware\RedirectIfAuthenticated::class, diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 372f30bf6..8461ed0ba 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -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(baseUrl('/register/confirm/awaiting')); + return redirect(baseUrl('/register/confirm/awaiting')); } if ($this->auth->guest() && !setting('app-public')) { diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index ab8ce4d3a..2b3c64695 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -34,7 +34,8 @@ class RedirectIfAuthenticated */ public function handle($request, Closure $next) { - if ($this->auth->check()) { + $requireConfirmation = setting('registration-confirmation'); + if ($this->auth->check() && (!$requireConfirmation || ($requireConfirmation && $this->auth->user()->email_confirmed))) { return redirect('/'); } diff --git a/app/Jobs/Job.php b/app/Jobs/Job.php deleted file mode 100644 index 780af746b..000000000 --- a/app/Jobs/Job.php +++ /dev/null @@ -1,21 +0,0 @@ -token = $token; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage) + ->subject('Confirm your email on ' . session('app-name')) + ->greeting('Thanks for joining ' . setting('app-name') . '!') + ->line('Please confirm your email address by clicking the button below:') + ->action('Confirm Email', baseUrl('/register/confirm/' . $this->token)); + } + +} diff --git a/app/Notifications/ResetPassword.php b/app/Notifications/ResetPassword.php new file mode 100644 index 000000000..646030a10 --- /dev/null +++ b/app/Notifications/ResetPassword.php @@ -0,0 +1,50 @@ +token = $token; + } + + /** + * Get the notification's channels. + * + * @param mixed $notifiable + * @return array|string + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Build the mail representation of the notification. + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail() + { + return (new MailMessage) + ->line('You are receiving this email because we received a password reset request for your account.') + ->action('Reset Password', baseUrl('password/reset/' . $this->token)) + ->line('If you did not request a password reset, no further action is required.'); + } +} diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php new file mode 100644 index 000000000..11e3cc6d2 --- /dev/null +++ b/app/Providers/BroadcastServiceProvider.php @@ -0,0 +1,26 @@ +id === (int) $userId; +// }); + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index f754b87a9..3802f20c0 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -21,13 +21,10 @@ class EventServiceProvider extends ServiceProvider /** * Register any other events for your application. * - * @param \Illuminate\Contracts\Events\Dispatcher $events * @return void */ - public function boot(DispatcherContract $events) + public function boot() { - parent::boot($events); - - // + parent::boot(); } } diff --git a/app/Providers/PaginationServiceProvider.php b/app/Providers/PaginationServiceProvider.php index a0e97f70d..ec41267a4 100644 --- a/app/Providers/PaginationServiceProvider.php +++ b/app/Providers/PaginationServiceProvider.php @@ -1,11 +1,12 @@ app['view']; + }); + Paginator::currentPathResolver(function () { return baseUrl($this->app['request']->path()); }); diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 2d9cd3b85..88ab23526 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -4,6 +4,7 @@ namespace BookStack\Providers; use Illuminate\Routing\Router; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; +use Route; class RouteServiceProvider extends ServiceProvider { @@ -19,26 +20,54 @@ class RouteServiceProvider extends ServiceProvider /** * Define your route model bindings, pattern filters, etc. * - * @param \Illuminate\Routing\Router $router * @return void */ - public function boot(Router $router) + public function boot() { - // - - parent::boot($router); + parent::boot(); } /** * Define the routes for the application. * - * @param \Illuminate\Routing\Router $router * @return void */ - public function map(Router $router) + public function map() { - $router->group(['namespace' => $this->namespace], function ($router) { - require app_path('Http/routes.php'); + $this->mapWebRoutes(); +// $this->mapApiRoutes(); + } + /** + * Define the "web" routes for the application. + * + * These routes all receive session state, CSRF protection, etc. + * + * @return void + */ + protected function mapWebRoutes() + { + Route::group([ + 'middleware' => 'web', + 'namespace' => $this->namespace, + ], function ($router) { + require base_path('routes/web.php'); + }); + } + /** + * Define the "api" routes for the application. + * + * These routes are typically stateless. + * + * @return void + */ + protected function mapApiRoutes() + { + Route::group([ + 'middleware' => 'api', + 'namespace' => $this->namespace, + 'prefix' => 'api', + ], function ($router) { + require base_path('routes/api.php'); }); } } diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php index 235246f82..7255ad05f 100644 --- a/app/Repos/PageRepo.php +++ b/app/Repos/PageRepo.php @@ -110,31 +110,6 @@ class PageRepo extends EntityRepo return $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId)->count(); } - /** - * Save a new page into the system. - * Input validation must be done beforehand. - * @param array $input - * @param Book $book - * @param int $chapterId - * @return Page - */ - public function saveNew(array $input, Book $book, $chapterId = null) - { - $page = $this->newFromInput($input); - $page->slug = $this->findSuitableSlug($page->name, $book->id); - - if ($chapterId) $page->chapter_id = $chapterId; - - $page->html = $this->formatHtml($input['html']); - $page->text = strip_tags($page->html); - $page->created_by = auth()->user()->id; - $page->updated_by = auth()->user()->id; - - $book->pages()->save($page); - return $page; - } - - /** * Publish a draft page to make it a normal page. * Sets the slug and updates the content. @@ -371,7 +346,7 @@ class PageRepo extends EntityRepo */ public function saveRevision(Page $page, $summary = null) { - $revision = $this->pageRevision->fill($page->toArray()); + $revision = $this->pageRevision->newInstance($page->toArray()); if (setting('app-editor') !== 'markdown') $revision->markdown = ''; $revision->page_id = $page->id; $revision->slug = $page->slug; @@ -381,11 +356,13 @@ class PageRepo extends EntityRepo $revision->type = 'version'; $revision->summary = $summary; $revision->save(); + // Clear old revisions if ($this->pageRevision->where('page_id', '=', $page->id)->count() > 50) { $this->pageRevision->where('page_id', '=', $page->id) ->orderBy('created_at', 'desc')->skip(50)->take(5)->delete(); } + return $revision; } diff --git a/app/Services/EmailConfirmationService.php b/app/Services/EmailConfirmationService.php index c3096c654..d4ec1e976 100644 --- a/app/Services/EmailConfirmationService.php +++ b/app/Services/EmailConfirmationService.php @@ -1,30 +1,27 @@ mailer = $mailer; - $this->emailConfirmation = $emailConfirmation; + $this->db = $db; + $this->users = $users; } /** @@ -38,16 +35,28 @@ class EmailConfirmationService if ($user->email_confirmed) { throw new ConfirmationEmailException('Email has already been confirmed, Try logging in.', '/login'); } + $this->deleteConfirmationsByUser($user); + $token = $this->createEmailConfirmation($user); + + $user->notify(new ConfirmEmail($token)); + } + + /** + * Creates a new email confirmation in the database and returns the token. + * @param User $user + * @return string + */ + public function createEmailConfirmation(User $user) + { $token = $this->getToken(); - $this->emailConfirmation->create([ + $this->db->table('email_confirmations')->insert([ 'user_id' => $user->id, - 'token' => $token, + 'token' => $token, + 'created_at' => Carbon::now(), + 'updated_at' => Carbon::now() ]); - $this->mailer->send('emails/email-confirmation', ['token' => $token], function (Message $message) use ($user) { - $appName = setting('app-name', 'BookStack'); - $message->to($user->email, $user->name)->subject('Confirm your email on ' . $appName . '.'); - }); + return $token; } /** @@ -59,22 +68,24 @@ class EmailConfirmationService */ public function getEmailConfirmationFromToken($token) { - $emailConfirmation = $this->emailConfirmation->where('token', '=', $token)->first(); - // If not found + $emailConfirmation = $this->db->table('email_confirmations')->where('token', '=', $token)->first(); + + // If not found show error if ($emailConfirmation === null) { throw new UserRegistrationException('This confirmation token is not valid or has already been used, Please try registering again.', '/register'); } // If more than a day old - if (Carbon::now()->subDay()->gt($emailConfirmation->created_at)) { - $this->sendConfirmation($emailConfirmation->user); + if (Carbon::now()->subDay()->gt(new Carbon($emailConfirmation->created_at))) { + $user = $this->users->getById($emailConfirmation->user_id); + $this->sendConfirmation($user); throw new UserRegistrationException('The confirmation token has expired, A new confirmation email has been sent.', '/register/confirm'); } + $emailConfirmation->user = $this->users->getById($emailConfirmation->user_id); return $emailConfirmation; } - /** * Delete all email confirmations that belong to a user. * @param User $user @@ -82,7 +93,7 @@ class EmailConfirmationService */ public function deleteConfirmationsByUser(User $user) { - return $this->emailConfirmation->where('user_id', '=', $user->id)->delete(); + return $this->db->table('email_confirmations')->where('user_id', '=', $user->id)->delete(); } /** @@ -92,7 +103,7 @@ class EmailConfirmationService protected function getToken() { $token = str_random(24); - while ($this->emailConfirmation->where('token', '=', $token)->exists()) { + while ($this->db->table('email_confirmations')->where('token', '=', $token)->exists()) { $token = str_random(25); } return $token; diff --git a/app/Services/PermissionService.php b/app/Services/PermissionService.php index cee074cd7..341a69edb 100644 --- a/app/Services/PermissionService.php +++ b/app/Services/PermissionService.php @@ -9,14 +9,15 @@ use BookStack\Page; use BookStack\Role; use BookStack\User; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; class PermissionService { - protected $userRoles; - protected $isAdmin; protected $currentAction; - protected $currentUser; + protected $isAdminUser; + protected $userRoles = false; + protected $currentUserModel = false; public $book; public $chapter; @@ -37,12 +38,6 @@ class PermissionService */ public function __construct(JointPermission $jointPermission, Book $book, Chapter $chapter, Page $page, Role $role) { - $this->currentUser = auth()->user(); - $userSet = $this->currentUser !== null; - $this->userRoles = false; - $this->isAdmin = $userSet ? $this->currentUser->hasRole('admin') : false; - if (!$userSet) $this->currentUser = new User(); - $this->jointPermission = $jointPermission; $this->role = $role; $this->book = $book; @@ -117,7 +112,7 @@ class PermissionService } - foreach ($this->currentUser->roles as $role) { + foreach ($this->currentUser()->roles as $role) { $roles[] = $role->id; } return $roles; @@ -389,7 +384,11 @@ class PermissionService */ public function checkOwnableUserAccess(Ownable $ownable, $permission) { - if ($this->isAdmin) return true; + if ($this->isAdmin()) { + $this->clean(); + return true; + } + $explodedPermission = explode('-', $permission); $baseQuery = $ownable->where('id', '=', $ownable->id); @@ -400,10 +399,10 @@ class PermissionService // Handle non entity specific jointPermissions if (in_array($explodedPermission[0], $nonJointPermissions)) { - $allPermission = $this->currentUser && $this->currentUser->can($permission . '-all'); - $ownPermission = $this->currentUser && $this->currentUser->can($permission . '-own'); + $allPermission = $this->currentUser() && $this->currentUser()->can($permission . '-all'); + $ownPermission = $this->currentUser() && $this->currentUser()->can($permission . '-own'); $this->currentAction = 'view'; - $isOwner = $this->currentUser && $this->currentUser->id === $ownable->created_by; + $isOwner = $this->currentUser() && $this->currentUser()->id === $ownable->created_by; return ($allPermission || ($isOwner && $ownPermission)); } @@ -413,7 +412,9 @@ class PermissionService } - return $this->entityRestrictionQuery($baseQuery)->count() > 0; + $q = $this->entityRestrictionQuery($baseQuery)->count() > 0; + $this->clean(); + return $q; } /** @@ -443,7 +444,7 @@ class PermissionService */ protected function entityRestrictionQuery($query) { - return $query->where(function ($parentQuery) { + $q = $query->where(function ($parentQuery) { $parentQuery->whereHas('jointPermissions', function ($permissionQuery) { $permissionQuery->whereIn('role_id', $this->getRoles()) ->where('action', '=', $this->currentAction) @@ -451,11 +452,13 @@ class PermissionService $query->where('has_permission', '=', true) ->orWhere(function ($query) { $query->where('has_permission_own', '=', true) - ->where('created_by', '=', $this->currentUser->id); + ->where('created_by', '=', $this->currentUser()->id); }); }); }); }); + $this->clean(); + return $q; } /** @@ -469,9 +472,9 @@ class PermissionService // Prevent drafts being visible to others. $query = $query->where(function ($query) { $query->where('draft', '=', false); - if ($this->currentUser) { + if ($this->currentUser()) { $query->orWhere(function ($query) { - $query->where('draft', '=', true)->where('created_by', '=', $this->currentUser->id); + $query->where('draft', '=', true)->where('created_by', '=', $this->currentUser()->id); }); } }); @@ -509,7 +512,10 @@ class PermissionService */ public function enforceEntityRestrictions($query, $action = 'view') { - if ($this->isAdmin) return $query; + if ($this->isAdmin()) { + $this->clean(); + return $query; + } $this->currentAction = $action; return $this->entityRestrictionQuery($query); } @@ -524,11 +530,15 @@ class PermissionService */ public function filterRestrictedEntityRelations($query, $tableName, $entityIdColumn, $entityTypeColumn) { - if ($this->isAdmin) return $query; + if ($this->isAdmin()) { + $this->clean(); + return $query; + } + $this->currentAction = 'view'; $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn]; - return $query->where(function ($query) use ($tableDetails) { + $q = $query->where(function ($query) use ($tableDetails) { $query->whereExists(function ($permissionQuery) use (&$tableDetails) { $permissionQuery->select('id')->from('joint_permissions') ->whereRaw('joint_permissions.entity_id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn']) @@ -538,12 +548,12 @@ class PermissionService ->where(function ($query) { $query->where('has_permission', '=', true)->orWhere(function ($query) { $query->where('has_permission_own', '=', true) - ->where('created_by', '=', $this->currentUser->id); + ->where('created_by', '=', $this->currentUser()->id); }); }); }); }); - + return $q; } /** @@ -555,11 +565,15 @@ class PermissionService */ public function filterRelatedPages($query, $tableName, $entityIdColumn) { - if ($this->isAdmin) return $query; + if ($this->isAdmin()) { + $this->clean(); + return $query; + } + $this->currentAction = 'view'; $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn]; - return $query->where(function ($query) use ($tableDetails) { + $q = $query->where(function ($query) use ($tableDetails) { $query->where(function ($query) use (&$tableDetails) { $query->whereExists(function ($permissionQuery) use (&$tableDetails) { $permissionQuery->select('id')->from('joint_permissions') @@ -570,12 +584,50 @@ class PermissionService ->where(function ($query) { $query->where('has_permission', '=', true)->orWhere(function ($query) { $query->where('has_permission_own', '=', true) - ->where('created_by', '=', $this->currentUser->id); + ->where('created_by', '=', $this->currentUser()->id); }); }); }); })->orWhere($tableDetails['entityIdColumn'], '=', 0); }); + $this->clean(); + return $q; + } + + /** + * Check if the current user is an admin. + * @return bool + */ + private function isAdmin() + { + if ($this->isAdminUser === null) { + $this->isAdminUser = ($this->currentUser()->id !== null) ? $this->currentUser()->hasRole('admin') : false; + } + + return $this->isAdminUser; + } + + /** + * Get the current user + * @return User + */ + private function currentUser() + { + if ($this->currentUserModel === false) { + $this->currentUserModel = auth()->user() ? auth()->user() : new User(); + } + + return $this->currentUserModel; + } + + /** + * Clean the cached user elements. + */ + private function clean() + { + $this->currentUserModel = false; + $this->userRoles = false; + $this->isAdminUser = null; } } \ No newline at end of file diff --git a/app/User.php b/app/User.php index 32449971d..8c39d81be 100644 --- a/app/User.php +++ b/app/User.php @@ -1,13 +1,15 @@ notify(new ResetPassword($token)); + } } diff --git a/app/helpers.php b/app/helpers.php index b8abb1006..dd835fbf6 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -63,7 +63,7 @@ function userCan($permission, Ownable $ownable = null) */ function setting($key, $default = false) { - $settingService = app('BookStack\Services\SettingService'); + $settingService = app(\BookStack\Services\SettingService::class); return $settingService->get($key, $default); } @@ -79,11 +79,17 @@ function baseUrl($path, $forceAppDomain = false) if ($isFullUrl && !$forceAppDomain) return $path; $path = trim($path, '/'); + // Remove non-specified domain if forced and we have a domain if ($isFullUrl && $forceAppDomain) { $explodedPath = explode('/', $path); $path = implode('/', array_splice($explodedPath, 3)); } + // Return normal url path if not specified in config + if (config('app.url') === '') { + return url($path); + } + return rtrim(config('app.url'), '/') . '/' . $path; } diff --git a/composer.json b/composer.json index 5c77a68c4..d96037019 100644 --- a/composer.json +++ b/composer.json @@ -5,23 +5,22 @@ "license": "MIT", "type": "project", "require": { - "php": ">=5.5.9", - "laravel/framework": "5.2.*", + "php": ">=5.6.4", + "laravel/framework": "^5.3.4", "intervention/image": "^2.3", "laravel/socialite": "^2.0", "barryvdh/laravel-ide-helper": "^2.1", - "barryvdh/laravel-debugbar": "^2.0", + "barryvdh/laravel-debugbar": "^2.2.3", "league/flysystem-aws-s3-v3": "^1.0", - "barryvdh/laravel-dompdf": "0.6.*", - "predis/predis": "^1.0" + "barryvdh/laravel-dompdf": "^0.7", + "predis/predis": "^1.1" }, "require-dev": { "fzaninotto/faker": "~1.4", "mockery/mockery": "0.9.*", - "phpunit/phpunit": "~4.0", - "phpspec/phpspec": "~2.1", - "symfony/dom-crawler": "~3.0", - "symfony/css-selector": "~3.0" + "phpunit/phpunit": "~5.0", + "symfony/css-selector": "3.1.*", + "symfony/dom-crawler": "3.1.*" }, "autoload": { "classmap": [ @@ -37,21 +36,19 @@ ] }, "scripts": { - "post-install-cmd": [ - "php artisan clear-compiled", - "php artisan optimize" - ], - "pre-update-cmd": [ - "php artisan clear-compiled" - ], - "post-update-cmd": [ - "php artisan optimize" - ], "post-root-package-install": [ - "php -r \"copy('.env.example', '.env');\"" + "php -r \"file_exists('.env') || copy('.env.example', '.env');\"" ], "post-create-project-cmd": [ "php artisan key:generate" + ], + "post-install-cmd": [ + "Illuminate\\Foundation\\ComposerScripts::postInstall", + "php artisan optimize" + ], + "post-update-cmd": [ + "Illuminate\\Foundation\\ComposerScripts::postUpdate", + "php artisan optimize" ] }, "config": { diff --git a/composer.lock b/composer.lock index 63d378753..c1c80e100 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,27 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "eb7c71e9ed116d3fd2a1d0af07f9f134", - "content-hash": "17d2d7fc5fed682f2a290d6588538035", + "hash": "c90a6e41767306ceb3b8cedb91468390", + "content-hash": "3b5d2d6b77fbe71101e7e8eaff0754fe", "packages": [ { "name": "aws/aws-sdk-php", - "version": "3.17.5", + "version": "3.19.6", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "1cef9b334729b3564c9aef15481a55561c54b53f" + "reference": "34060bf0db260031697b17dbb37fa1bbec92f1c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1cef9b334729b3564c9aef15481a55561c54b53f", - "reference": "1cef9b334729b3564c9aef15481a55561c54b53f", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/34060bf0db260031697b17dbb37fa1bbec92f1c4", + "reference": "34060bf0db260031697b17dbb37fa1bbec92f1c4", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "~5.3|~6.0.1|~6.1", + "guzzlehttp/guzzle": "^5.3.1|^6.2.1", "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.0", + "guzzlehttp/psr7": "~1.3.1", "mtdowling/jmespath.php": "~2.2", "php": ">=5.5" }, @@ -85,25 +85,25 @@ "s3", "sdk" ], - "time": "2016-04-07 22:44:13" + "time": "2016-09-08 20:27:15" }, { "name": "barryvdh/laravel-debugbar", - "version": "v2.2.0", + "version": "V2.2.3", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "13b7058d2120c8d5af7f1ada21b7c44dd87b666a" + "reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/13b7058d2120c8d5af7f1ada21b7c44dd87b666a", - "reference": "13b7058d2120c8d5af7f1ada21b7c44dd87b666a", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd", + "reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd", "shasum": "" }, "require": { - "illuminate/support": "5.1.*|5.2.*", - "maximebf/debugbar": "~1.11.0", + "illuminate/support": "5.1.*|5.2.*|5.3.*", + "maximebf/debugbar": "~1.11.0|~1.12.0", "php": ">=5.5.9", "symfony/finder": "~2.7|~3.0" }, @@ -139,31 +139,31 @@ "profiler", "webprofiler" ], - "time": "2016-02-17 08:32:21" + "time": "2016-07-29 15:00:36" }, { "name": "barryvdh/laravel-dompdf", - "version": "v0.6.1", + "version": "v0.7.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "b606788108833f7765801dca35455fb23ce9f869" + "reference": "9b8bd179262ad6b200a11edfe7b53516afcfc42a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/b606788108833f7765801dca35455fb23ce9f869", - "reference": "b606788108833f7765801dca35455fb23ce9f869", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/9b8bd179262ad6b200a11edfe7b53516afcfc42a", + "reference": "9b8bd179262ad6b200a11edfe7b53516afcfc42a", "shasum": "" }, "require": { - "dompdf/dompdf": "0.6.*", - "illuminate/support": "5.0.x|5.1.x|5.2.x", - "php": ">=5.4.0" + "dompdf/dompdf": "^0.7", + "illuminate/support": "5.1.x|5.2.x|5.3.x", + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.6-dev" + "dev-master": "0.7-dev" } }, "autoload": { @@ -187,32 +187,35 @@ "laravel", "pdf" ], - "time": "2015-12-21 19:51:22" + "time": "2016-08-17 08:17:33" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.1.4", + "version": "v2.2.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "f1ebd847aac9a4545325d35108cafc285fe1605f" + "reference": "28af7cd19ca41cc0c63dd1de2b46c2b84d31c463" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/f1ebd847aac9a4545325d35108cafc285fe1605f", - "reference": "f1ebd847aac9a4545325d35108cafc285fe1605f", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/28af7cd19ca41cc0c63dd1de2b46c2b84d31c463", + "reference": "28af7cd19ca41cc0c63dd1de2b46c2b84d31c463", "shasum": "" }, "require": { - "illuminate/console": "5.0.x|5.1.x|5.2.x", - "illuminate/filesystem": "5.0.x|5.1.x|5.2.x", - "illuminate/support": "5.0.x|5.1.x|5.2.x", + "barryvdh/reflection-docblock": "^2.0.4", + "illuminate/console": "^5.0,<5.4", + "illuminate/filesystem": "^5.0,<5.4", + "illuminate/support": "^5.0,<5.4", "php": ">=5.4.0", - "phpdocumentor/reflection-docblock": "^2.0.4", - "symfony/class-loader": "~2.3|~3.0" + "symfony/class-loader": "^2.3|^3.0" }, "require-dev": { - "doctrine/dbal": "~2.3" + "doctrine/dbal": "~2.3", + "phpunit/phpunit": "4.*", + "scrutinizer/ocular": "~1.1", + "squizlabs/php_codesniffer": "~2.3" }, "suggest": { "doctrine/dbal": "Load information from the database about models for phpdocs (~2.3)" @@ -220,7 +223,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.2-dev" } }, "autoload": { @@ -250,7 +253,56 @@ "phpstorm", "sublime" ], - "time": "2016-03-03 08:45:00" + "time": "2016-07-04 11:52:48" + }, + { + "name": "barryvdh/reflection-docblock", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/ReflectionDocBlock.git", + "reference": "3dcbd98b5d9384a5357266efba8fd29884458e5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/3dcbd98b5d9384a5357266efba8fd29884458e5c", + "reference": "3dcbd98b5d9384a5357266efba8fd29884458e5c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0,<4.5" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Barryvdh": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2016-06-13 19:28:20" }, { "name": "classpreloader/classpreloader", @@ -408,30 +460,46 @@ }, { "name": "dompdf/dompdf", - "version": "v0.6.2", + "version": "v0.7.0", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "cc06008f75262510ee135b8cbb14e333a309f651" + "reference": "5c98652b1a5beb7e3cc8ec35419b2828dd63ab14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/cc06008f75262510ee135b8cbb14e333a309f651", - "reference": "cc06008f75262510ee135b8cbb14e333a309f651", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/5c98652b1a5beb7e3cc8ec35419b2828dd63ab14", + "reference": "5c98652b1a5beb7e3cc8ec35419b2828dd63ab14", "shasum": "" }, "require": { - "phenx/php-font-lib": "0.2.*" + "ext-dom": "*", + "ext-gd": "*", + "ext-mbstring": "*", + "phenx/php-font-lib": "0.4.*", + "phenx/php-svg-lib": "0.1.*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.7-dev" + } + }, "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, "classmap": [ - "include/" + "lib/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL" + "LGPL-2.1" ], "authors": [ { @@ -441,127 +509,39 @@ { "name": "Brian Sweeney", "email": "eclecticgeek@gmail.com" + }, + { + "name": "Gabriel Bull", + "email": "me@gabrielbull.com" } ], "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", "homepage": "https://github.com/dompdf/dompdf", - "time": "2015-12-07 04:07:13" - }, - { - "name": "guzzle/guzzle", - "version": "v3.8.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba", - "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.3.3", - "symfony/event-dispatcher": ">=2.1" - }, - "replace": { - "guzzle/batch": "self.version", - "guzzle/cache": "self.version", - "guzzle/common": "self.version", - "guzzle/http": "self.version", - "guzzle/inflection": "self.version", - "guzzle/iterator": "self.version", - "guzzle/log": "self.version", - "guzzle/parser": "self.version", - "guzzle/plugin": "self.version", - "guzzle/plugin-async": "self.version", - "guzzle/plugin-backoff": "self.version", - "guzzle/plugin-cache": "self.version", - "guzzle/plugin-cookie": "self.version", - "guzzle/plugin-curlauth": "self.version", - "guzzle/plugin-error-response": "self.version", - "guzzle/plugin-history": "self.version", - "guzzle/plugin-log": "self.version", - "guzzle/plugin-md5": "self.version", - "guzzle/plugin-mock": "self.version", - "guzzle/plugin-oauth": "self.version", - "guzzle/service": "self.version", - "guzzle/stream": "self.version" - }, - "require-dev": { - "doctrine/cache": "*", - "monolog/monolog": "1.*", - "phpunit/phpunit": "3.7.*", - "psr/log": "1.0.*", - "symfony/class-loader": "*", - "zendframework/zend-cache": "<2.3", - "zendframework/zend-log": "<2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.8-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle": "src/", - "Guzzle\\Tests": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Guzzle Community", - "homepage": "https://github.com/guzzle/guzzle/contributors" - } - ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2014-01-28 22:29:15" + "time": "2016-05-11 00:36:29" }, { "name": "guzzlehttp/guzzle", - "version": "6.2.0", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "d094e337976dff9d8e2424e8485872194e768662" + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662", - "reference": "d094e337976dff9d8e2424e8485872194e768662", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", "shasum": "" }, "require": { - "guzzlehttp/promises": "~1.0", - "guzzlehttp/psr7": "~1.1", - "php": ">=5.5.0" + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.3.1", + "php": ">=5.5" }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "~4.0", - "psr/log": "~1.0" + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" }, "type": "library", "extra": { @@ -599,20 +579,20 @@ "rest", "web service" ], - "time": "2016-03-21 20:02:09" + "time": "2016-07-15 17:22:37" }, { "name": "guzzlehttp/promises", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8" + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bb9024c526b22f3fe6ae55a561fd70653d470aa8", - "reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", "shasum": "" }, "require": { @@ -650,20 +630,20 @@ "keywords": [ "promise" ], - "time": "2016-03-08 01:15:46" + "time": "2016-05-18 16:56:05" }, { "name": "guzzlehttp/psr7", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", - "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", "shasum": "" }, "require": { @@ -679,7 +659,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -708,20 +688,20 @@ "stream", "uri" ], - "time": "2016-02-18 21:54:00" + "time": "2016-06-24 23:00:38" }, { "name": "intervention/image", - "version": "2.3.6", + "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/Intervention/image.git", - "reference": "e368d262887dbb2fdfaf710880571ede51e9c0e6" + "reference": "4064a980324f6c3bfa2bd981dfb247afa705ec3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/e368d262887dbb2fdfaf710880571ede51e9c0e6", - "reference": "e368d262887dbb2fdfaf710880571ede51e9c0e6", + "url": "https://api.github.com/repos/Intervention/image/zipball/4064a980324f6c3bfa2bd981dfb247afa705ec3c", + "reference": "4064a980324f6c3bfa2bd981dfb247afa705ec3c", "shasum": "" }, "require": { @@ -770,7 +750,7 @@ "thumbnail", "watermark" ], - "time": "2016-02-26 18:18:19" + "time": "2016-09-01 17:04:03" }, { "name": "jakub-onderka/php-console-color", @@ -919,16 +899,16 @@ }, { "name": "laravel/framework", - "version": "v5.2.29", + "version": "v5.3.9", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e3d644eb131f18c5f3d28ff7bc678bc797091f20" + "reference": "f6fbb481672f8dc4bc6882d5d654bbfa3588c8ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e3d644eb131f18c5f3d28ff7bc678bc797091f20", - "reference": "e3d644eb131f18c5f3d28ff7bc678bc797091f20", + "url": "https://api.github.com/repos/laravel/framework/zipball/f6fbb481672f8dc4bc6882d5d654bbfa3588c8ec", + "reference": "f6fbb481672f8dc4bc6882d5d654bbfa3588c8ec", "shasum": "" }, "require": { @@ -941,20 +921,20 @@ "monolog/monolog": "~1.11", "mtdowling/cron-expression": "~1.0", "nesbot/carbon": "~1.20", - "paragonie/random_compat": "~1.4", - "php": ">=5.5.9", + "paragonie/random_compat": "~1.4|~2.0", + "php": ">=5.6.4", "psy/psysh": "0.7.*", + "ramsey/uuid": "~3.0", "swiftmailer/swiftmailer": "~5.1", - "symfony/console": "2.8.*|3.0.*", - "symfony/debug": "2.8.*|3.0.*", - "symfony/finder": "2.8.*|3.0.*", - "symfony/http-foundation": "2.8.*|3.0.*", - "symfony/http-kernel": "2.8.*|3.0.*", - "symfony/polyfill-php56": "~1.0", - "symfony/process": "2.8.*|3.0.*", - "symfony/routing": "2.8.*|3.0.*", - "symfony/translation": "2.8.*|3.0.*", - "symfony/var-dumper": "2.8.*|3.0.*", + "symfony/console": "3.1.*", + "symfony/debug": "3.1.*", + "symfony/finder": "3.1.*", + "symfony/http-foundation": "3.1.*", + "symfony/http-kernel": "3.1.*", + "symfony/process": "3.1.*", + "symfony/routing": "3.1.*", + "symfony/translation": "3.1.*", + "symfony/var-dumper": "3.1.*", "vlucas/phpdotenv": "~2.2" }, "replace": { @@ -985,16 +965,17 @@ "illuminate/support": "self.version", "illuminate/translation": "self.version", "illuminate/validation": "self.version", - "illuminate/view": "self.version" + "illuminate/view": "self.version", + "tightenco/collect": "self.version" }, "require-dev": { "aws/aws-sdk-php": "~3.0", - "mockery/mockery": "~0.9.2", + "mockery/mockery": "~0.9.4", "pda/pheanstalk": "~3.0", - "phpunit/phpunit": "~4.1", + "phpunit/phpunit": "~5.4", "predis/predis": "~1.0", - "symfony/css-selector": "2.8.*|3.0.*", - "symfony/dom-crawler": "2.8.*|3.0.*" + "symfony/css-selector": "3.1.*", + "symfony/dom-crawler": "3.1.*" }, "suggest": { "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", @@ -1006,19 +987,17 @@ "pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).", "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).", - "symfony/css-selector": "Required to use some of the crawler integration testing tools (2.8.*|3.0.*).", - "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (2.8.*|3.0.*)." + "symfony/css-selector": "Required to use some of the crawler integration testing tools (3.1.*).", + "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (3.1.*).", + "symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.2-dev" + "dev-master": "5.3-dev" } }, "autoload": { - "classmap": [ - "src/Illuminate/Queue/IlluminateQueueClosure.php" - ], "files": [ "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Support/helpers.php" @@ -1034,29 +1013,29 @@ "authors": [ { "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" + "email": "taylor@laravel.com" } ], "description": "The Laravel Framework.", - "homepage": "http://laravel.com", + "homepage": "https://laravel.com", "keywords": [ "framework", "laravel" ], - "time": "2016-04-03 01:43:55" + "time": "2016-09-12 14:08:29" }, { "name": "laravel/socialite", - "version": "v2.0.15", + "version": "v2.0.18", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "edd00ab96933e3ef053533cce81e958fb26921af" + "reference": "76ee5397fcdea5a062361392abca4eb397e519a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/edd00ab96933e3ef053533cce81e958fb26921af", - "reference": "edd00ab96933e3ef053533cce81e958fb26921af", + "url": "https://api.github.com/repos/laravel/socialite/zipball/76ee5397fcdea5a062361392abca4eb397e519a3", + "reference": "76ee5397fcdea5a062361392abca4eb397e519a3", "shasum": "" }, "require": { @@ -1069,7 +1048,7 @@ }, "require-dev": { "mockery/mockery": "~0.9", - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.0|~5.0" }, "type": "library", "extra": { @@ -1097,20 +1076,20 @@ "laravel", "oauth" ], - "time": "2016-03-21 14:30:30" + "time": "2016-06-22 12:40:16" }, { "name": "league/flysystem", - "version": "1.0.20", + "version": "1.0.27", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "e87a786e3ae12a25cf78a71bb07b4b384bfaa83a" + "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e87a786e3ae12a25cf78a71bb07b4b384bfaa83a", - "reference": "e87a786e3ae12a25cf78a71bb07b4b384bfaa83a", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/50e2045ed70a7e75a5e30bc3662904f3b67af8a9", + "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9", "shasum": "" }, "require": { @@ -1123,7 +1102,7 @@ "ext-fileinfo": "*", "mockery/mockery": "~0.9", "phpspec/phpspec": "^2.2", - "phpunit/phpunit": "~4.8 || ~5.0" + "phpunit/phpunit": "~4.8" }, "suggest": { "ext-fileinfo": "Required for MimeType", @@ -1180,20 +1159,20 @@ "sftp", "storage" ], - "time": "2016-03-14 21:54:11" + "time": "2016-08-10 08:55:11" }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.9", + "version": "1.0.13", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "595e24678bf78f8107ebc9355d8376ae0eb712c6" + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/595e24678bf78f8107ebc9355d8376ae0eb712c6", - "reference": "595e24678bf78f8107ebc9355d8376ae0eb712c6", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/dc56a8faf3aff0841f9eae04b6af94a50657896c", + "reference": "dc56a8faf3aff0841f9eae04b6af94a50657896c", "shasum": "" }, "require": { @@ -1227,30 +1206,30 @@ } ], "description": "Flysystem adapter for the AWS S3 SDK v3.x", - "time": "2015-11-19 08:44:16" + "time": "2016-06-21 21:34:35" }, { "name": "league/oauth1-client", - "version": "1.6.1", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth1-client.git", - "reference": "cef3ceda13c78f89c323e4d5e6301c0eb7cea422" + "reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/cef3ceda13c78f89c323e4d5e6301c0eb7cea422", - "reference": "cef3ceda13c78f89c323e4d5e6301c0eb7cea422", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/fca5f160650cb74d23fc11aa570dd61f86dcf647", + "reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647", "shasum": "" }, "require": { - "guzzle/guzzle": "3.*", - "php": ">=5.3.0" + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0" }, "require-dev": { - "mockery/mockery": "~0.9", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "mockery/mockery": "^0.9", + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.0" }, "type": "library", "extra": { @@ -1290,20 +1269,20 @@ "tumblr", "twitter" ], - "time": "2015-10-23 04:02:07" + "time": "2016-08-17 00:36:58" }, { "name": "maximebf/debugbar", - "version": "v1.11.1", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "d9302891c1f0a0ac5a4f66725163a00537c6359f" + "reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/d9302891c1f0a0ac5a4f66725163a00537c6359f", - "reference": "d9302891c1f0a0ac5a4f66725163a00537c6359f", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988", + "reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988", "shasum": "" }, "require": { @@ -1322,7 +1301,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1351,20 +1330,20 @@ "debug", "debugbar" ], - "time": "2016-01-22 12:22:23" + "time": "2016-05-15 13:11:34" }, { "name": "monolog/monolog", - "version": "1.18.2", + "version": "1.21.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "064b38c16790249488e7a8b987acf1c9d7383c09" + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/064b38c16790249488e7a8b987acf1c9d7383c09", - "reference": "064b38c16790249488e7a8b987acf1c9d7383c09", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", "shasum": "" }, "require": { @@ -1383,8 +1362,8 @@ "php-console/php-console": "^3.1.3", "phpunit/phpunit": "~4.5", "phpunit/phpunit-mock-objects": "2.3.0", - "raven/raven": "^0.13", "ruflin/elastica": ">=0.90 <3.0", + "sentry/sentry": "^0.13", "swiftmailer/swiftmailer": "~5.3" }, "suggest": { @@ -1396,9 +1375,9 @@ "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "php-console/php-console": "Allow sending log messages to Google Chrome", - "raven/raven": "Allow sending log messages to a Sentry server", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server", + "sentry/sentry": "Allow sending log messages to a Sentry server" }, "type": "library", "extra": { @@ -1429,7 +1408,7 @@ "logging", "psr-3" ], - "time": "2016-04-02 13:12:58" + "time": "2016-07-29 03:23:52" }, { "name": "mtdowling/cron-expression", @@ -1579,16 +1558,16 @@ }, { "name": "nikic/php-parser", - "version": "v2.0.1", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ce5be709d59b32dd8a88c80259028759991a4206" + "reference": "47b254ea51f1d6d5dc04b9b299e88346bf2369e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ce5be709d59b32dd8a88c80259028759991a4206", - "reference": "ce5be709d59b32dd8a88c80259028759991a4206", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/47b254ea51f1d6d5dc04b9b299e88346bf2369e3", + "reference": "47b254ea51f1d6d5dc04b9b299e88346bf2369e3", "shasum": "" }, "require": { @@ -1604,7 +1583,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -1626,20 +1605,20 @@ "parser", "php" ], - "time": "2016-02-28 19:48:28" + "time": "2016-04-19 13:41:41" }, { "name": "paragonie/random_compat", - "version": "v1.4.1", + "version": "v2.0.2", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "c7e26a21ba357863de030f0b9e701c7d04593774" + "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/c7e26a21ba357863de030f0b9e701c7d04593774", - "reference": "c7e26a21ba357863de030f0b9e701c7d04593774", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf", + "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf", "shasum": "" }, "require": { @@ -1674,31 +1653,31 @@ "pseudorandom", "random" ], - "time": "2016-03-18 20:34:03" + "time": "2016-04-03 06:00:07" }, { "name": "phenx/php-font-lib", - "version": "0.2.2", + "version": "0.4", "source": { "type": "git", "url": "https://github.com/PhenX/php-font-lib.git", - "reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82" + "reference": "b8af0cacdc3cbf1e41a586fcb78f506f4121a088" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82", - "reference": "c30c7fc00a6b0d863e9bb4c5d5dd015298b2dc82", + "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/b8af0cacdc3cbf1e41a586fcb78f506f4121a088", + "reference": "b8af0cacdc3cbf1e41a586fcb78f506f4121a088", "shasum": "" }, "type": "library", "autoload": { - "classmap": [ - "classes/" - ] + "psr-0": { + "FontLib\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL" + "LGPL-3.0" ], "authors": [ { @@ -1708,76 +1687,61 @@ ], "description": "A library to read, parse, export and make subsets of different types of font files.", "homepage": "https://github.com/PhenX/php-font-lib", - "time": "2014-02-01 15:22:28" + "time": "2015-05-06 20:02:39" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "2.0.4", + "name": "phenx/php-svg-lib", + "version": "0.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + "url": "https://github.com/PhenX/php-svg-lib.git", + "reference": "b419766515b3426c6da74b0e29e93d71c4f17099" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "url": "https://api.github.com/repos/PhenX/php-svg-lib/zipball/b419766515b3426c6da74b0e29e93d71c4f17099", + "reference": "b419766515b3426c6da74b0e29e93d71c4f17099", "shasum": "" }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-0": { - "phpDocumentor": [ - "src/" - ] + "Svg\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-3.0" ], "authors": [ { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" } ], - "time": "2015-02-03 12:10:50" + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/PhenX/php-svg-lib", + "time": "2015-05-06 18:49:49" }, { "name": "predis/predis", - "version": "v1.0.3", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/nrk/predis.git", - "reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04" + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nrk/predis/zipball/84060b9034d756b4d79641667d7f9efe1aeb8e04", - "reference": "84060b9034d756b4d79641667d7f9efe1aeb8e04", + "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": ">=5.3.9" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8" }, "suggest": { "ext-curl": "Allows access to Webdis when paired with phpiredis", @@ -1800,27 +1764,27 @@ "homepage": "http://clorophilla.net" } ], - "description": "Flexible and feature-complete PHP client library for Redis", + "description": "Flexible and feature-complete Redis client for PHP and HHVM", "homepage": "http://github.com/nrk/predis", "keywords": [ "nosql", "predis", "redis" ], - "time": "2015-07-30 18:34:15" + "time": "2016-06-16 16:22:20" }, { "name": "psr/http-message", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", - "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { @@ -1848,6 +1812,7 @@ } ], "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ "http", "http-message", @@ -1856,7 +1821,7 @@ "request", "response" ], - "time": "2015-05-04 20:22:00" + "time": "2016-08-06 14:39:51" }, { "name": "psr/log", @@ -1969,24 +1934,104 @@ "time": "2016-03-09 05:03:14" }, { - "name": "swiftmailer/swiftmailer", - "version": "v5.4.1", + "name": "ramsey/uuid", + "version": "3.5.0", "source": { "type": "git", - "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421" + "url": "https://github.com/ramsey/uuid.git", + "reference": "a6d15c8618ea3951fd54d34e326b68d3d0bc0786" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/0697e6aa65c83edf97bb0f23d8763f94e3f11421", - "reference": "0697e6aa65c83edf97bb0f23d8763f94e3f11421", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/a6d15c8618ea3951fd54d34e326b68d3d0bc0786", + "reference": "a6d15c8618ea3951fd54d34e326b68d3d0bc0786", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "^1.0|^2.0", + "php": ">=5.4" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "apigen/apigen": "^4.1", + "codeception/aspect-mock": "1.0.0", + "goaop/framework": "1.0.0-alpha.2", + "ircmaxell/random-lib": "^1.1", + "jakub-onderka/php-parallel-lint": "^0.9.0", + "mockery/mockery": "^0.9.4", + "moontoast/math": "^1.1", + "phpunit/phpunit": "^4.7|>=5.0 <5.4", + "satooshi/php-coveralls": "^0.6.1", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", + "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", + "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marijn Huizendveld", + "email": "marijn.huizendveld@gmail.com" + }, + { + "name": "Thibaud Fabre", + "email": "thibaud@aztech.io" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2016-08-02 18:39:32" + }, + { + "name": "swiftmailer/swiftmailer", + "version": "v5.4.3", + "source": { + "type": "git", + "url": "https://github.com/swiftmailer/swiftmailer.git", + "reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/4cc92842069c2bbc1f28daaaf1d2576ec4dfe153", + "reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "mockery/mockery": "~0.9.1,<0.9.4" + "mockery/mockery": "~0.9.1" }, "type": "library", "extra": { @@ -2019,20 +2064,20 @@ "mail", "mailer" ], - "time": "2015-06-06 14:19:39" + "time": "2016-07-08 11:51:25" }, { "name": "symfony/class-loader", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "cbb7e6a9c0213a0cffa5d9065ee8214ca4e83877" + "reference": "2d0ba77c46ecc96a6641009a98f72632216811ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/cbb7e6a9c0213a0cffa5d9065ee8214ca4e83877", - "reference": "cbb7e6a9c0213a0cffa5d9065ee8214ca4e83877", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/2d0ba77c46ecc96a6641009a98f72632216811ba", + "reference": "2d0ba77c46ecc96a6641009a98f72632216811ba", "shasum": "" }, "require": { @@ -2048,7 +2093,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2075,20 +2120,20 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2016-03-30 10:41:14" + "time": "2016-08-23 13:39:15" }, { "name": "symfony/console", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6b1175135bc2a74c08a28d89761272de8beed8cd" + "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6b1175135bc2a74c08a28d89761272de8beed8cd", - "reference": "6b1175135bc2a74c08a28d89761272de8beed8cd", + "url": "https://api.github.com/repos/symfony/console/zipball/8ea494c34f0f772c3954b5fbe00bffc5a435e563", + "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563", "shasum": "" }, "require": { @@ -2108,7 +2153,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2135,20 +2180,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-03-16 17:00:50" + "time": "2016-08-19 06:48:39" }, { "name": "symfony/debug", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "a06d10888a45afd97534506afb058ec38d9ba35b" + "reference": "34f6ac18c2974ca5fce68adf419ee7d15def6f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/a06d10888a45afd97534506afb058ec38d9ba35b", - "reference": "a06d10888a45afd97534506afb058ec38d9ba35b", + "url": "https://api.github.com/repos/symfony/debug/zipball/34f6ac18c2974ca5fce68adf419ee7d15def6f11", + "reference": "34f6ac18c2974ca5fce68adf419ee7d15def6f11", "shasum": "" }, "require": { @@ -2165,7 +2210,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2192,20 +2237,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-03-30 10:41:14" + "time": "2016-08-23 13:39:15" }, { "name": "symfony/event-dispatcher", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9002dcf018d884d294b1ef20a6f968efc1128f39" + "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9002dcf018d884d294b1ef20a6f968efc1128f39", - "reference": "9002dcf018d884d294b1ef20a6f968efc1128f39", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c0c00c80b3a69132c4e55c3e7db32b4a387615e5", + "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5", "shasum": "" }, "require": { @@ -2225,7 +2270,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2252,20 +2297,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-03-10 10:34:12" + "time": "2016-07-19 10:45:57" }, { "name": "symfony/finder", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "c54e407b35bc098916704e9fd090da21da4c4f52" + "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/c54e407b35bc098916704e9fd090da21da4c4f52", - "reference": "c54e407b35bc098916704e9fd090da21da4c4f52", + "url": "https://api.github.com/repos/symfony/finder/zipball/e568ef1784f447a0e54dcb6f6de30b9747b0f577", + "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577", "shasum": "" }, "require": { @@ -2274,7 +2319,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2301,20 +2346,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-03-10 11:13:05" + "time": "2016-08-26 12:04:02" }, { "name": "symfony/http-foundation", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "99f38445a874e7becb8afc4b4a79ee181cf6ec3f" + "reference": "63592e00fd90632b57ee50220a1ddb29b6bf3bb4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/99f38445a874e7becb8afc4b4a79ee181cf6ec3f", - "reference": "99f38445a874e7becb8afc4b4a79ee181cf6ec3f", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/63592e00fd90632b57ee50220a1ddb29b6bf3bb4", + "reference": "63592e00fd90632b57ee50220a1ddb29b6bf3bb4", "shasum": "" }, "require": { @@ -2327,7 +2372,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2354,20 +2399,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2016-03-27 14:50:32" + "time": "2016-08-22 12:11:19" }, { "name": "symfony/http-kernel", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "579f828489659d7b3430f4bd9b67b4618b387dea" + "reference": "aeda215d6b01f119508c090d2a09ebb5b0bc61f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/579f828489659d7b3430f4bd9b67b4618b387dea", - "reference": "579f828489659d7b3430f4bd9b67b4618b387dea", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/aeda215d6b01f119508c090d2a09ebb5b0bc61f3", + "reference": "aeda215d6b01f119508c090d2a09ebb5b0bc61f3", "shasum": "" }, "require": { @@ -2375,7 +2420,7 @@ "psr/log": "~1.0", "symfony/debug": "~2.8|~3.0", "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/http-foundation": "~2.8|~3.0" + "symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2" }, "conflict": { "symfony/config": "<2.8" @@ -2409,7 +2454,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2436,20 +2481,20 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-03-25 01:41:20" + "time": "2016-09-03 15:28:24" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" + "reference": "dff51f72b0706335131b00a7f49606168c582594" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", "shasum": "" }, "require": { @@ -2461,7 +2506,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2495,20 +2540,20 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/polyfill-php56", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php56.git", - "reference": "4d891fff050101a53a4caabb03277284942d1ad9" + "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/4d891fff050101a53a4caabb03277284942d1ad9", - "reference": "4d891fff050101a53a4caabb03277284942d1ad9", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/3edf57a8fbf9a927533344cef65ad7e1cf31030a", + "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a", "shasum": "" }, "require": { @@ -2518,7 +2563,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2551,20 +2596,20 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/polyfill-util", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-util.git", - "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4" + "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4", - "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ef830ce3d218e622b221d6bfad42c751d974bf99", + "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99", "shasum": "" }, "require": { @@ -2573,7 +2618,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2603,20 +2648,20 @@ "polyfill", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/process", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e6f1f98bbd355d209a992bfff45e7edfbd4a0776" + "reference": "e64e93041c80e77197ace5ab9385dedb5a143697" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e6f1f98bbd355d209a992bfff45e7edfbd4a0776", - "reference": "e6f1f98bbd355d209a992bfff45e7edfbd4a0776", + "url": "https://api.github.com/repos/symfony/process/zipball/e64e93041c80e77197ace5ab9385dedb5a143697", + "reference": "e64e93041c80e77197ace5ab9385dedb5a143697", "shasum": "" }, "require": { @@ -2625,7 +2670,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2652,20 +2697,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-03-30 10:41:14" + "time": "2016-08-16 14:58:24" }, { "name": "symfony/routing", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "d061b609f2d0769494c381ec92f5c5cc5e4a20aa" + "reference": "8edf62498a1a4c57ba317664a4b698339c10cdf6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/d061b609f2d0769494c381ec92f5c5cc5e4a20aa", - "reference": "d061b609f2d0769494c381ec92f5c5cc5e4a20aa", + "url": "https://api.github.com/repos/symfony/routing/zipball/8edf62498a1a4c57ba317664a4b698339c10cdf6", + "reference": "8edf62498a1a4c57ba317664a4b698339c10cdf6", "shasum": "" }, "require": { @@ -2694,7 +2739,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2727,20 +2772,20 @@ "uri", "url" ], - "time": "2016-03-23 13:23:25" + "time": "2016-08-16 14:58:24" }, { "name": "symfony/translation", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "f7a07af51ea067745a521dab1e3152044a2fb1f2" + "reference": "a35edc277513c9bc0f063ca174c36b346f974528" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/f7a07af51ea067745a521dab1e3152044a2fb1f2", - "reference": "f7a07af51ea067745a521dab1e3152044a2fb1f2", + "url": "https://api.github.com/repos/symfony/translation/zipball/a35edc277513c9bc0f063ca174c36b346f974528", + "reference": "a35edc277513c9bc0f063ca174c36b346f974528", "shasum": "" }, "require": { @@ -2764,7 +2809,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2791,20 +2836,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-03-25 01:41:20" + "time": "2016-08-05 08:37:39" }, { "name": "symfony/var-dumper", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "3841ed86527d18ee2c35fe4afb1b2fc60f8fae79" + "reference": "62ee73706c421654a4c840028954510277f7dfc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3841ed86527d18ee2c35fe4afb1b2fc60f8fae79", - "reference": "3841ed86527d18ee2c35fe4afb1b2fc60f8fae79", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/62ee73706c421654a4c840028954510277f7dfc8", + "reference": "62ee73706c421654a4c840028954510277f7dfc8", "shasum": "" }, "require": { @@ -2820,7 +2865,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -2854,32 +2899,32 @@ "debug", "dump" ], - "time": "2016-03-10 10:34:12" + "time": "2016-08-31 09:05:42" }, { "name": "vlucas/phpdotenv", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "9caf304153dc2288e4970caec6f1f3b3bc205412" + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/9caf304153dc2288e4970caec6f1f3b3bc205412", - "reference": "9caf304153dc2288e4970caec6f1f3b3bc205412", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", "shasum": "" }, "require": { "php": ">=5.3.9" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.0" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-master": "2.4-dev" } }, "autoload": { @@ -2889,7 +2934,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD" + "BSD-3-Clause-Attribution" ], "authors": [ { @@ -2899,13 +2944,12 @@ } ], "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", - "homepage": "http://github.com/vlucas/phpdotenv", "keywords": [ "dotenv", "env", "environment" ], - "time": "2015-12-29 15:10:30" + "time": "2016-09-01 10:05:43" } ], "packages-dev": [ @@ -2965,33 +3009,29 @@ }, { "name": "fzaninotto/faker", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/fzaninotto/Faker.git", - "reference": "d0190b156bcca848d401fb80f31f504f37141c8d" + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d0190b156bcca848d401fb80f31f504f37141c8d", - "reference": "d0190b156bcca848d401fb80f31f504f37141c8d", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/44f9a286a04b80c76a4e5fb7aad8bb539b920123", + "reference": "44f9a286a04b80c76a4e5fb7aad8bb539b920123", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3|^7.0" }, "require-dev": { + "ext-intl": "*", "phpunit/phpunit": "~4.0", "squizlabs/php_codesniffer": "~1.5" }, - "suggest": { - "ext-intl": "*" - }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5.x-dev" - } + "branch-alias": [] }, "autoload": { "psr-4": { @@ -3013,7 +3053,7 @@ "faker", "fixtures" ], - "time": "2015-05-29 06:29:14" + "time": "2016-04-29 12:21:54" }, { "name": "hamcrest/hamcrest-php", @@ -3062,16 +3102,16 @@ }, { "name": "mockery/mockery", - "version": "0.9.4", + "version": "0.9.5", "source": { "type": "git", "url": "https://github.com/padraic/mockery.git", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b" + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b", + "url": "https://api.github.com/repos/padraic/mockery/zipball/4db079511a283e5aba1b3c2fb19037c645e70fc2", + "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2", "shasum": "" }, "require": { @@ -3123,90 +3163,81 @@ "test double", "testing" ], - "time": "2015-04-02 19:54:00" + "time": "2016-05-22 21:52:33" }, { - "name": "phpspec/php-diff", - "version": "v1.0.2", + "name": "myclabs/deep-copy", + "version": "1.5.2", "source": { "type": "git", - "url": "https://github.com/phpspec/php-diff.git", - "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "da8529775f14f4fdae33f916eb0cf65f6afbddbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/php-diff/zipball/30e103d19519fe678ae64a60d77884ef3d71b28a", - "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/da8529775f14f4fdae33f916eb0cf65f6afbddbc", + "reference": "da8529775f14f4fdae33f916eb0cf65f6afbddbc", "shasum": "" }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, "type": "library", "autoload": { - "psr-0": { - "Diff": "lib/" + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "authors": [ - { - "name": "Chris Boulton", - "homepage": "http://github.com/chrisboulton", - "role": "Original developer" - } + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" ], - "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", - "time": "2013-11-01 13:02:21" + "time": "2016-09-06 16:07:05" }, { - "name": "phpspec/phpspec", - "version": "2.5.0", + "name": "phpdocumentor/reflection-common", + "version": "1.0", "source": { "type": "git", - "url": "https://github.com/phpspec/phpspec.git", - "reference": "385ecb015e97c13818074f1517928b24d4a26067" + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/phpspec/zipball/385ecb015e97c13818074f1517928b24d4a26067", - "reference": "385ecb015e97c13818074f1517928b24d4a26067", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.1", - "ext-tokenizer": "*", - "php": ">=5.3.3", - "phpspec/php-diff": "~1.0.0", - "phpspec/prophecy": "~1.4", - "sebastian/exporter": "~1.0", - "symfony/console": "~2.3|~3.0", - "symfony/event-dispatcher": "~2.1|~3.0", - "symfony/finder": "~2.1|~3.0", - "symfony/process": "^2.6|~3.0", - "symfony/yaml": "~2.1|~3.0" + "php": ">=5.5" }, "require-dev": { - "behat/behat": "^3.0.11", - "bossa/phpspec2-expect": "~1.0", - "phpunit/phpunit": "~4.4", - "symfony/filesystem": "~2.1|~3.0" + "phpunit/phpunit": "^4.6" }, - "suggest": { - "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters" - }, - "bin": [ - "bin/phpspec" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "PhpSpec": "src/" + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -3215,56 +3246,141 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "homepage": "http://marcelloduarte.net/" + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" } ], - "description": "Specification-oriented BDD framework for PHP 5.3+", - "homepage": "http://phpspec.net/", + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", "keywords": [ - "BDD", - "SpecBDD", - "TDD", - "spec", - "specification", - "testing", - "tests" + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" ], - "time": "2016-03-20 20:34:32" + "time": "2015-12-27 11:43:31" }, { - "name": "phpspec/prophecy", - "version": "v1.6.0", + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.0", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972" + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-06-10 09:48:41" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", + "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-06-10 07:14:17" + }, + { + "name": "phpspec/prophecy", + "version": "v1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", + "reference": "58a8137754bc24b25740d4281399a4a3596058e0", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1", - "sebastian/recursion-context": "~1.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0" }, "require-dev": { - "phpspec/phpspec": "~2.0" + "phpspec/phpspec": "^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -3297,43 +3413,44 @@ "spy", "stub" ], - "time": "2016-02-15 07:46:21" + "time": "2016-06-07 08:13:47" }, { "name": "phpunit/php-code-coverage", - "version": "2.2.4", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3", + "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": "^5.6 || ^7.0", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "~1.0|~2.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" + "phpunit/phpunit": "^5.4" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.2.1", + "ext-xdebug": ">=2.4.0", "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { @@ -3359,7 +3476,7 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2016-07-26 14:39:29" }, { "name": "phpunit/php-file-iterator", @@ -3451,21 +3568,24 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, "type": "library", "autoload": { "classmap": [ @@ -3488,7 +3608,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2016-05-12 18:03:57" }, { "name": "phpunit/php-token-stream", @@ -3541,16 +3661,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.8.24", + "version": "5.5.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a1066c562c52900a142a0e2bbf0582994671385e" + "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1066c562c52900a142a0e2bbf0582994671385e", - "reference": "a1066c562c52900a142a0e2bbf0582994671385e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6e88e56c912133de6e99b87728cca7ed70c5f5", + "reference": "3e6e88e56c912133de6e99b87728cca7ed70c5f5", "shasum": "" }, "require": { @@ -3559,21 +3679,27 @@ "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", - "php": ">=5.3.3", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", + "phpunit/php-code-coverage": "^4.0.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": ">=1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", + "sebastian/environment": "^1.3 || ^2.0", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", + "sebastian/object-enumerator": "~1.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" + }, "suggest": { "phpunit/php-invoker": "~1.1" }, @@ -3583,7 +3709,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.8.x-dev" + "dev-master": "5.5.x-dev" } }, "autoload": { @@ -3609,30 +3735,33 @@ "testing", "xunit" ], - "time": "2016-03-14 06:16:08" + "time": "2016-08-26 07:11:44" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", + "version": "3.2.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/546898a2c0c356ef2891b39dd7d07f5d82c8ed0a", + "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^5.4" }, "suggest": { "ext-soap": "*" @@ -3640,7 +3769,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3.x-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { @@ -3665,7 +3794,52 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2016-09-06 16:07:45" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2016-02-13 06:45:14" }, { "name": "sebastian/comparator", @@ -3785,23 +3959,23 @@ }, { "name": "sebastian/environment", - "version": "1.3.5", + "version": "1.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { @@ -3831,20 +4005,20 @@ "environment", "hhvm" ], - "time": "2016-02-26 18:40:46" + "time": "2016-08-18 05:49:44" }, { "name": "sebastian/exporter", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", "shasum": "" }, "require": { @@ -3852,12 +4026,13 @@ "sebastian/recursion-context": "~1.0" }, "require-dev": { + "ext-mbstring": "*", "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -3897,7 +4072,7 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2016-06-17 09:04:28" }, { "name": "sebastian/global-state", @@ -3950,6 +4125,52 @@ ], "time": "2015-10-12 03:26:01" }, + { + "name": "sebastian/object-enumerator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", + "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2016-01-28 13:25:10" + }, { "name": "sebastian/recursion-context", "version": "1.0.2", @@ -4004,20 +4225,70 @@ "time": "2015-11-11 19:50:13" }, { - "name": "sebastian/version", - "version": "1.0.6", + "name": "sebastian/resource-operations", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", "shasum": "" }, + "require": { + "php": ">=5.6.0" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, + { + "name": "sebastian/version", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -4036,20 +4307,20 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2016-02-04 12:56:52" }, { "name": "symfony/css-selector", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "65e764f404685f2dc20c057e889b3ad04b2e2db0" + "reference": "2851e1932d77ce727776154d659b232d061e816a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/65e764f404685f2dc20c057e889b3ad04b2e2db0", - "reference": "65e764f404685f2dc20c057e889b3ad04b2e2db0", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/2851e1932d77ce727776154d659b232d061e816a", + "reference": "2851e1932d77ce727776154d659b232d061e816a", "shasum": "" }, "require": { @@ -4058,7 +4329,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4089,20 +4360,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2016-03-04 07:55:57" + "time": "2016-06-29 05:41:56" }, { "name": "symfony/dom-crawler", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "18a06d7a9af41718c20764a674a0ebba3bc40d1f" + "reference": "bb7395e8b1db3654de82b9f35d019958276de4d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/18a06d7a9af41718c20764a674a0ebba3bc40d1f", - "reference": "18a06d7a9af41718c20764a674a0ebba3bc40d1f", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/bb7395e8b1db3654de82b9f35d019958276de4d7", + "reference": "bb7395e8b1db3654de82b9f35d019958276de4d7", "shasum": "" }, "require": { @@ -4118,7 +4389,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4145,20 +4416,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2016-03-23 13:23:25" + "time": "2016-08-05 08:37:39" }, { "name": "symfony/yaml", - "version": "v3.0.4", + "version": "v3.1.4", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "0047c8366744a16de7516622c5b7355336afae96" + "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/0047c8366744a16de7516622c5b7355336afae96", - "reference": "0047c8366744a16de7516622c5b7355336afae96", + "url": "https://api.github.com/repos/symfony/yaml/zipball/f291ed25eb1435bddbe8a96caaef16469c2a092d", + "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d", "shasum": "" }, "require": { @@ -4167,7 +4438,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -4194,7 +4465,57 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-03-04 07:55:57" + "time": "2016-09-02 02:12:52" + }, + { + "name": "webmozart/assert", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", + "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "shasum": "" + }, + "require": { + "php": "^5.3.3|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-08-09 15:02:57" } ], "aliases": [], @@ -4203,7 +4524,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.5.9" + "php": ">=5.6.4" }, "platform-dev": [] } diff --git a/config/app.php b/config/app.php index 0d6f6f2b0..a5b0d2fe0 100644 --- a/config/app.php +++ b/config/app.php @@ -138,6 +138,7 @@ return [ Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, + Illuminate\Notifications\NotificationServiceProvider::class, Laravel\Socialite\SocialiteServiceProvider::class, /** @@ -156,6 +157,7 @@ return [ BookStack\Providers\AuthServiceProvider::class, BookStack\Providers\AppServiceProvider::class, + BookStack\Providers\BroadcastServiceProvider::class, BookStack\Providers\EventServiceProvider::class, BookStack\Providers\RouteServiceProvider::class, BookStack\Providers\CustomFacadeProvider::class, @@ -194,6 +196,7 @@ return [ 'Lang' => Illuminate\Support\Facades\Lang::class, 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, + 'Notification' => Illuminate\Support\Facades\Notification::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class, diff --git a/database/migrations/2015_08_29_105422_add_roles_and_permissions.php b/database/migrations/2015_08_29_105422_add_roles_and_permissions.php index 763a33fec..47a77e29f 100644 --- a/database/migrations/2015_08_29_105422_add_roles_and_permissions.php +++ b/database/migrations/2015_08_29_105422_add_roles_and_permissions.php @@ -129,7 +129,7 @@ class AddRolesAndPermissions extends Migration // Set all current users as admins // (At this point only the initially create user should be an admin) - $users = DB::table('users')->get(); + $users = DB::table('users')->get()->all(); foreach ($users as $user) { DB::table('role_user')->insert([ 'role_id' => $adminId, diff --git a/phpspec.yml b/phpspec.yml deleted file mode 100644 index 58f1d982e..000000000 --- a/phpspec.yml +++ /dev/null @@ -1,5 +0,0 @@ -suites: - main: - namespace: BookStack - psr4_prefix: BookStack - src_path: app \ No newline at end of file diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php new file mode 100644 index 000000000..cbf4ec7f5 --- /dev/null +++ b/resources/lang/en/auth.php @@ -0,0 +1,15 @@ + 'These credentials do not match our records.', + 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', +]; \ No newline at end of file diff --git a/resources/views/auth/password.blade.php b/resources/views/auth/passwords/email.blade.php similarity index 100% rename from resources/views/auth/password.blade.php rename to resources/views/auth/passwords/email.blade.php diff --git a/resources/views/auth/reset.blade.php b/resources/views/auth/passwords/reset.blade.php similarity index 100% rename from resources/views/auth/reset.blade.php rename to resources/views/auth/passwords/reset.blade.php diff --git a/resources/views/emails/email-confirmation.blade.php b/resources/views/emails/email-confirmation.blade.php deleted file mode 100644 index 6a0dc0378..000000000 --- a/resources/views/emails/email-confirmation.blade.php +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - Confirm Your Email At {{ setting('app-name')}} - - - - - - - - - - - -
- -
- - - - -
-

- Email Confirmation

-

- Thanks for joining {{ setting('app-name')}}.
- Please confirm your email address by clicking the button below.

- - - - -
-

- Confirm - Email

-
-
-
- -
- - - - diff --git a/resources/views/emails/password.blade.php b/resources/views/emails/password.blade.php deleted file mode 100644 index dfd8f3db5..000000000 --- a/resources/views/emails/password.blade.php +++ /dev/null @@ -1 +0,0 @@ - Password Reset From {{ setting('app-name')}}

Password Reset

A password reset was requested for this email address on {{ setting('app-name')}}. If you did not request a password change please ignore this email.

Click here to reset your password

\ No newline at end of file diff --git a/resources/views/users/index.blade.php b/resources/views/users/index.blade.php index e72a9e61a..105fddb5b 100644 --- a/resources/views/users/index.blade.php +++ b/resources/views/users/index.blade.php @@ -22,7 +22,7 @@
- {!! $users->links() !!} + {{ $users->links() }}
@@ -76,7 +76,7 @@
- {!! $users->links() !!} + {{ $users->links() }}
diff --git a/resources/views/vendor/.gitkeep b/resources/views/vendor/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/resources/views/vendor/notifications/email-plain.blade.php b/resources/views/vendor/notifications/email-plain.blade.php new file mode 100644 index 000000000..acefa6523 --- /dev/null +++ b/resources/views/vendor/notifications/email-plain.blade.php @@ -0,0 +1,22 @@ + + + + + + + + + + 'margin: 0; padding: 0; width: 100%; background-color: #F2F4F6;', + 'email-wrapper' => 'width: 100%; margin: 0; padding: 0; background-color: #F2F4F6;', + + /* Masthead ----------------------- */ + + 'email-masthead' => 'padding: 25px 0; text-align: center;', + 'email-masthead_name' => 'font-size: 24px; font-weight: 400; color: #2F3133; text-decoration: none; text-shadow: 0 1px 0 white;', + + 'email-body' => 'width: 100%; margin: 0; padding: 0; border-top: 4px solid '.setting('app-color').'; border-bottom: 1px solid #EDEFF2; background-color: #FFF;', + 'email-body_inner' => 'width: auto; max-width: 100%; margin: 0 auto; padding: 0;', + 'email-body_cell' => 'padding: 35px;', + + 'email-footer' => 'width: auto; max-width: 570px; margin: 0 auto; padding: 0; text-align: center;', + 'email-footer_cell' => 'color: #AEAEAE; padding: 35px; text-align: center;', + + /* Body ------------------------------ */ + + 'body_action' => 'width: 100%; margin: 30px auto; padding: 0; text-align: center;', + 'body_sub' => 'margin-top: 25px; padding-top: 25px; border-top: 1px solid #EDEFF2;', + + /* Type ------------------------------ */ + + 'anchor' => 'color: '.setting('app-color').';overflow-wrap: break-word;word-wrap: break-word;word-break: break-all;word-break:break-word;', + 'header-1' => 'margin-top: 0; color: #2F3133; font-size: 19px; font-weight: bold; text-align: left;', + 'paragraph' => 'margin-top: 0; color: #74787E; font-size: 16px; line-height: 1.5em;', + 'paragraph-sub' => 'margin-top: 0; color: #74787E; font-size: 12px; line-height: 1.5em;', + 'paragraph-center' => 'text-align: center;', + + /* Buttons ------------------------------ */ + + 'button' => 'display: block; display: inline-block; width: 200px; min-height: 20px; padding: 10px; + background-color: #3869D4; border-radius: 3px; color: #ffffff; font-size: 15px; line-height: 25px; + text-align: center; text-decoration: none; -webkit-text-size-adjust: none;', + + 'button--green' => 'background-color: #22BC66;', + 'button--red' => 'background-color: #dc4d2f;', + 'button--blue' => 'background-color: '.setting('app-color').';', +]; +?> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + +
+ + {{ setting('app-name') }} + +
+ + + + +
+ + + @if (!empty($greeting) || $level == 'error') +

+ @if (! empty($greeting)) + {{ $greeting }} + @else + @if ($level == 'error') + Whoops! + @endif + @endif +

+ @endif + + + @foreach ($introLines as $line) +

+ {{ $line }} +

+ @endforeach + + + @if (isset($actionText)) + + + + +
+ + + + {{ $actionText }} + +
+ @endif + + + @foreach ($outroLines as $line) +

+ {{ $line }} +

+ @endforeach + + + + @if (isset($actionText)) + + + + +
+

+ If you’re having trouble clicking the "{{ $actionText }}" button, + copy and paste the URL below into your web browser: +

+ +

+ + {{ $actionUrl }} + +

+
+ @endif + +
+
+ + + + +
+

+ © {{ date('Y') }} + {{ setting('app-name') }}. + All rights reserved. +

+
+
+
+
+ + diff --git a/app/Http/routes.php b/routes/web.php similarity index 84% rename from app/Http/routes.php rename to routes/web.php index eb35f2a11..58ceb5f3b 100644 --- a/app/Http/routes.php +++ b/routes/web.php @@ -139,27 +139,27 @@ Route::group(['middleware' => 'auth'], function () { }); -// Login using social authentication -Route::get('/login/service/{socialDriver}', 'Auth\AuthController@getSocialLogin'); -Route::get('/login/service/{socialDriver}/callback', 'Auth\AuthController@socialCallback'); -Route::get('/login/service/{socialDriver}/detach', 'Auth\AuthController@detachSocialAccount'); +// Social auth routes +Route::get('/login/service/{socialDriver}', 'Auth\RegisterController@getSocialLogin'); +Route::get('/login/service/{socialDriver}/callback', 'Auth\RegisterController@socialCallback'); +Route::get('/login/service/{socialDriver}/detach', 'Auth\RegisterController@detachSocialAccount'); +Route::get('/register/service/{socialDriver}', 'Auth\RegisterController@socialRegister'); // Login/Logout routes -Route::get('/login', 'Auth\AuthController@getLogin'); -Route::post('/login', 'Auth\AuthController@postLogin'); -Route::get('/logout', 'Auth\AuthController@getLogout'); -Route::get('/register', 'Auth\AuthController@getRegister'); -Route::get('/register/confirm', 'Auth\AuthController@getRegisterConfirmation'); -Route::get('/register/confirm/awaiting', 'Auth\AuthController@showAwaitingConfirmation'); -Route::post('/register/confirm/resend', 'Auth\AuthController@resendConfirmation'); -Route::get('/register/confirm/{token}', 'Auth\AuthController@confirmEmail'); -Route::get('/register/confirm/{token}/email', 'Auth\AuthController@viewConfirmEmail'); -Route::get('/register/service/{socialDriver}', 'Auth\AuthController@socialRegister'); -Route::post('/register', 'Auth\AuthController@postRegister'); +Route::get('/login', 'Auth\LoginController@getLogin'); +Route::post('/login', 'Auth\LoginController@login'); +Route::get('/logout', 'Auth\LoginController@logout'); +Route::get('/register', 'Auth\RegisterController@getRegister'); +Route::get('/register/confirm', 'Auth\RegisterController@getRegisterConfirmation'); +Route::get('/register/confirm/awaiting', 'Auth\RegisterController@showAwaitingConfirmation'); +Route::post('/register/confirm/resend', 'Auth\RegisterController@resendConfirmation'); +Route::get('/register/confirm/{token}', 'Auth\RegisterController@confirmEmail'); +Route::post('/register', 'Auth\RegisterController@postRegister'); // Password reset link request routes... -Route::get('/password/email', 'Auth\PasswordController@getEmail'); -Route::post('/password/email', 'Auth\PasswordController@postEmail'); +Route::get('/password/email', 'Auth\ForgotPasswordController@showLinkRequestForm'); +Route::post('/password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail'); + // Password reset routes... -Route::get('/password/reset/{token}', 'Auth\PasswordController@getReset'); -Route::post('/password/reset', 'Auth\PasswordController@postReset'); \ No newline at end of file +Route::get('/password/reset/{token}', 'Auth\ResetPasswordController@showResetForm'); +Route::post('/password/reset', 'Auth\ResetPasswordController@reset'); \ No newline at end of file diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php index 306771ed5..0affff799 100644 --- a/tests/Auth/AuthTest.php +++ b/tests/Auth/AuthTest.php @@ -1,6 +1,7 @@ setSettings(['registration-enabled' => 'true', 'registration-confirmation' => 'true']); $user = factory(\BookStack\User::class)->make(); - // Mock Mailer to ensure mail is being sent - $mockMailer = Mockery::mock('Illuminate\Contracts\Mail\Mailer'); - $mockMailer->shouldReceive('send')->with('emails/email-confirmation', Mockery::type('array'), Mockery::type('callable'))->twice(); - $this->app->instance('mailer', $mockMailer); - // Go through registration process $this->visit('/register') ->see('Sign Up') @@ -76,6 +75,10 @@ class AuthTest extends TestCase ->seePageIs('/register/confirm') ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => false]); + // Ensure notification sent + $dbUser = \BookStack\User::where('email', '=', $user->email)->first(); + Notification::assertSentTo($dbUser, ConfirmEmail::class); + // Test access and resend confirmation email $this->login($user->email, $user->password) ->seePageIs('/register/confirm/awaiting') @@ -84,19 +87,18 @@ class AuthTest extends TestCase ->seePageIs('/register/confirm/awaiting') ->press('Resend Confirmation Email'); - // Get confirmation - $user = $user->where('email', '=', $user->email)->first(); - $emailConfirmation = EmailConfirmation::where('user_id', '=', $user->id)->first(); - - - // Check confirmation email button and confirmation activation. - $this->visit('/register/confirm/' . $emailConfirmation->token . '/email') - ->see('Email Confirmation') - ->click('Confirm Email') + // Get confirmation and confirm notification matches + $emailConfirmation = DB::table('email_confirmations')->where('user_id', '=', $dbUser->id)->first(); + Notification::assertSentTo($dbUser, ConfirmEmail::class, function($notification, $channels) use ($emailConfirmation) { + return $notification->token === $emailConfirmation->token; + }); + + // Check confirmation email confirmation activation. + $this->visit('/register/confirm/' . $emailConfirmation->token) ->seePageIs('/') ->see($user->name) ->notSeeInDatabase('email_confirmations', ['token' => $emailConfirmation->token]) - ->seeInDatabase('users', ['name' => $user->name, 'email' => $user->email, 'email_confirmed' => true]); + ->seeInDatabase('users', ['name' => $dbUser->name, 'email' => $dbUser->email, 'email_confirmed' => true]); } public function test_restricted_registration() diff --git a/tests/Entity/EntityTest.php b/tests/Entity/EntityTest.php index 296aa72ed..20721968f 100644 --- a/tests/Entity/EntityTest.php +++ b/tests/Entity/EntityTest.php @@ -236,8 +236,9 @@ class EntityTest extends TestCase ->type('super test page', '#name') ->press('Save Page') // Check redirect - ->seePageIs($newPageUrl) - ->visit($pageUrl) + ->seePageIs($newPageUrl); + + $this->visit($pageUrl) ->seePageIs($newPageUrl); } diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php index 108b7459f..1a46e30bc 100644 --- a/tests/Entity/PageDraftTest.php +++ b/tests/Entity/PageDraftTest.php @@ -86,7 +86,7 @@ class PageDraftTest extends TestCase ->visit($chapter->getUrl() . '/create-page') ->visit($book->getUrl()) ->seeInElement('.page-list', 'New Page'); - + $this->asAdmin() ->visit($book->getUrl()) ->dontSeeInElement('.page-list', 'New Page') diff --git a/tests/ImageTest.php b/tests/ImageTest.php index 806a36acc..d9acd4b71 100644 --- a/tests/ImageTest.php +++ b/tests/ImageTest.php @@ -59,8 +59,10 @@ class ImageTest extends TestCase $this->assertTrue(file_exists(public_path($relPath)), 'Uploaded image exists'); + $this->deleteImage($relPath); + $this->seeInDatabase('images', [ - 'url' => $relPath, + 'url' => $this->baseUrl . $relPath, 'type' => 'gallery', 'uploaded_to' => $page->id, 'path' => $relPath, @@ -69,7 +71,7 @@ class ImageTest extends TestCase 'name' => $imageName ]); - $this->deleteImage($relPath); + } public function test_image_delete() @@ -85,7 +87,7 @@ class ImageTest extends TestCase $this->assertResponseOk(); $this->dontSeeInDatabase('images', [ - 'url' => $relPath, + 'url' => $this->baseUrl . $relPath, 'type' => 'gallery' ]); From e0235fda8bc0659ebca90105d77358511f633569 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 17 Sep 2016 21:33:55 +0100 Subject: [PATCH 04/27] Made registration gravatar/email requests fail gracefully * Extracted any email confirmation text into langs. * Added new notification on confirmation email send fail. Closes #187 --- .../Controllers/Auth/RegisterController.php | 22 +++++++++++++++---- app/Http/Controllers/UserController.php | 12 +++++++--- app/Notifications/ConfirmEmail.php | 9 ++++---- app/Repos/UserRepo.php | 12 +++++++--- app/Services/ImageService.php | 2 +- resources/lang/en/auth.php | 11 ++++++++++ 6 files changed, 53 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 5b3719bc0..6bba6de04 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -8,6 +8,7 @@ use BookStack\Repos\UserRepo; use BookStack\Services\EmailConfirmationService; use BookStack\Services\SocialAuthService; use BookStack\User; +use Exception; use Illuminate\Http\Request; use Illuminate\Http\Response; use Validator; @@ -56,7 +57,6 @@ class RegisterController extends Controller $this->userRepo = $userRepo; $this->redirectTo = baseUrl('/'); $this->redirectPath = baseUrl('/'); - $this->username = config('auth.method') === 'standard' ? 'email' : 'username'; parent::__construct(); } @@ -158,7 +158,13 @@ class RegisterController extends Controller if (setting('registration-confirmation') || setting('registration-restrict')) { $newUser->save(); - $this->emailConfirmationService->sendConfirmation($newUser); + + try { + $this->emailConfirmationService->sendConfirmation($newUser); + } catch (Exception $e) { + session()->flash('error', trans('auth.email_confirm_send_error')); + } + return redirect('/register/confirm'); } @@ -189,7 +195,7 @@ class RegisterController extends Controller $user->email_confirmed = true; $user->save(); auth()->login($user); - session()->flash('success', 'Your email has been confirmed!'); + session()->flash('success', trans('auth.email_confirm_success')); $this->emailConfirmationService->deleteConfirmationsByUser($user); return redirect($this->redirectPath); } @@ -215,8 +221,16 @@ class RegisterController extends Controller 'email' => 'required|email|exists:users,email' ]); $user = $this->userRepo->getByEmail($request->get('email')); + + try { + $this->emailConfirmationService->sendConfirmation($user); + } catch (Exception $e) { + session()->flash('error', trans('auth.email_confirm_send_error')); + return redirect('/register/confirm'); + } + $this->emailConfirmationService->sendConfirmation($user); - session()->flash('success', 'Confirmation email resent, Please check your inbox.'); + session()->flash('success', trans('auth.email_confirm_resent')); return redirect('/register/confirm'); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 053d9ebd5..4c56516dc 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -3,6 +3,7 @@ namespace BookStack\Http\Controllers; use BookStack\Activity; +use Exception; use Illuminate\Http\Request; use Illuminate\Http\Response; @@ -100,9 +101,14 @@ class UserController extends Controller // Get avatar from gravatar and save if (!config('services.disable_services')) { - $avatar = \Images::saveUserGravatar($user); - $user->avatar()->associate($avatar); - $user->save(); + try { + $avatar = \Images::saveUserGravatar($user); + $user->avatar()->associate($avatar); + $user->save(); + } catch (Exception $e) { + \Log::error('Failed to save user gravatar image'); + } + } return redirect('/settings/users'); diff --git a/app/Notifications/ConfirmEmail.php b/app/Notifications/ConfirmEmail.php index bd310d73d..64d9bb9ac 100644 --- a/app/Notifications/ConfirmEmail.php +++ b/app/Notifications/ConfirmEmail.php @@ -38,11 +38,12 @@ class ConfirmEmail extends Notification */ public function toMail($notifiable) { + $appName = ['appName' => setting('app-name')]; return (new MailMessage) - ->subject('Confirm your email on ' . session('app-name')) - ->greeting('Thanks for joining ' . setting('app-name') . '!') - ->line('Please confirm your email address by clicking the button below:') - ->action('Confirm Email', baseUrl('/register/confirm/' . $this->token)); + ->subject(trans('auth.email_confirm_subject', $appName)) + ->greeting(trans('auth.email_confirm_greeting', $appName)) + ->line(trans('auth.email_confirm_text')) + ->action(trans('auth.email_confirm_action'), baseUrl('/register/confirm/' . $this->token)); } } diff --git a/app/Repos/UserRepo.php b/app/Repos/UserRepo.php index 0926f6304..127db9fb5 100644 --- a/app/Repos/UserRepo.php +++ b/app/Repos/UserRepo.php @@ -2,6 +2,7 @@ use BookStack\Role; use BookStack\User; +use Exception; use Setting; class UserRepo @@ -84,9 +85,14 @@ class UserRepo // Get avatar from gravatar and save if (!config('services.disable_services')) { - $avatar = \Images::saveUserGravatar($user); - $user->avatar()->associate($avatar); - $user->save(); + try { + $avatar = \Images::saveUserGravatar($user); + $user->avatar()->associate($avatar); + $user->save(); + } catch (Exception $e) { + $user->save(); + \Log::error('Failed to save user gravatar image'); + } } return $user; diff --git a/app/Services/ImageService.php b/app/Services/ImageService.php index 4401cb230..aa1375487 100644 --- a/app/Services/ImageService.php +++ b/app/Services/ImageService.php @@ -213,7 +213,7 @@ class ImageService public function saveUserGravatar(User $user, $size = 500) { $emailHash = md5(strtolower(trim($user->email))); - $url = 'http://www.gravatar.com/avatar/' . $emailHash . '?s=' . $size . '&d=identicon'; + $url = 'https://www.gravatar.com/avatar/' . $emailHash . '?s=' . $size . '&d=identicon'; $imageName = str_replace(' ', '-', $user->name . '-gravatar.png'); $image = $this->saveNewFromUrl($url, 'user', $imageName); $image->created_by = $user->id; diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php index cbf4ec7f5..ffdb1cf45 100644 --- a/resources/lang/en/auth.php +++ b/resources/lang/en/auth.php @@ -12,4 +12,15 @@ return [ */ 'failed' => 'These credentials do not match our records.', 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', + + /** + * Email Confirmation Text + */ + 'email_confirm_subject' => 'Confirm your email on :appName', + 'email_confirm_greeting' => 'Thanks for joining :appName!', + 'email_confirm_text' => 'Please confirm your email address by clicking the button below:', + 'email_confirm_action' => 'Confirm Email', + 'email_confirm_send_error' => 'Email confirmation required but the system could not send the email. Contact the admin to ensure email is set up correctly.', + 'email_confirm_success' => 'Your email has been confirmed!', + 'email_confirm_resent' => 'Confirmation email resent, Please check your inbox.', ]; \ No newline at end of file From 1d681e53e49bb7b74dee77897571eb5f3ac1ea51 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 18 Sep 2016 14:49:36 +0100 Subject: [PATCH 05/27] Added page navigation and tweaked header styles Changed header selection in editor to be more descriptive and to provide a wider range of styles. Closes #68 --- app/Http/Controllers/PageController.php | 89 ++++++++++--------- app/Repos/PageRepo.php | 30 +++++++ resources/assets/js/pages/page-form.js | 7 +- resources/assets/sass/_lists.scss | 52 ++++++----- resources/assets/sass/_text.scss | 18 +++- resources/views/books/list-item.blade.php | 2 +- resources/views/chapters/list-item.blade.php | 6 +- resources/views/home.blade.php | 12 +-- resources/views/pages/list-item.blade.php | 4 +- resources/views/pages/show.blade.php | 3 +- .../views/pages/sidebar-tree-list.blade.php | 14 +++ 11 files changed, 147 insertions(+), 90 deletions(-) diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 1509ace95..3d6abe5b4 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -42,7 +42,7 @@ class PageController extends Controller /** * Show the form for creating a new page. - * @param $bookSlug + * @param string $bookSlug * @param bool $chapterSlug * @return Response * @internal param bool $pageSlug @@ -61,8 +61,8 @@ class PageController extends Controller /** * Show form to continue editing a draft page. - * @param $bookSlug - * @param $pageId + * @param string $bookSlug + * @param int $pageId * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function editDraft($bookSlug, $pageId) @@ -112,8 +112,8 @@ class PageController extends Controller * Display the specified page. * If the page is not found via the slug the * revisions are searched for a match. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return Response */ public function show($bookSlug, $pageSlug) @@ -131,14 +131,17 @@ class PageController extends Controller $this->checkOwnablePermission('page-view', $page); $sidebarTree = $this->bookRepo->getChildren($book); + $pageNav = $this->pageRepo->getPageNav($page); + Views::add($page); $this->setPageTitle($page->getShortName()); - return view('pages/show', ['page' => $page, 'book' => $book, 'current' => $page, 'sidebarTree' => $sidebarTree]); + return view('pages/show', ['page' => $page, 'book' => $book, + 'current' => $page, 'sidebarTree' => $sidebarTree, 'pageNav' => $pageNav]); } /** * Get page from an ajax request. - * @param $pageId + * @param int $pageId * @return \Illuminate\Http\JsonResponse */ public function getPageAjax($pageId) @@ -149,8 +152,8 @@ class PageController extends Controller /** * Show the form for editing the specified page. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return Response */ public function edit($bookSlug, $pageSlug) @@ -185,8 +188,8 @@ class PageController extends Controller /** * Update the specified page in storage. * @param Request $request - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return Response */ public function update(Request $request, $bookSlug, $pageSlug) @@ -205,7 +208,7 @@ class PageController extends Controller /** * Save a draft update as a revision. * @param Request $request - * @param $pageId + * @param int $pageId * @return \Illuminate\Http\JsonResponse */ public function saveDraft(Request $request, $pageId) @@ -230,7 +233,7 @@ class PageController extends Controller /** * Redirect from a special link url which * uses the page id rather than the name. - * @param $pageId + * @param int $pageId * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ public function redirectFromLink($pageId) @@ -241,8 +244,8 @@ class PageController extends Controller /** * Show the deletion page for the specified page. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return \Illuminate\View\View */ public function showDelete($bookSlug, $pageSlug) @@ -257,8 +260,8 @@ class PageController extends Controller /** * Show the deletion page for the specified page. - * @param $bookSlug - * @param $pageId + * @param string $bookSlug + * @param int $pageId * @return \Illuminate\View\View * @throws NotFoundException */ @@ -273,8 +276,8 @@ class PageController extends Controller /** * Remove the specified page from storage. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return Response * @internal param int $id */ @@ -291,8 +294,8 @@ class PageController extends Controller /** * Remove the specified draft page from storage. - * @param $bookSlug - * @param $pageId + * @param string $bookSlug + * @param int $pageId * @return Response * @throws NotFoundException */ @@ -308,8 +311,8 @@ class PageController extends Controller /** * Shows the last revisions for this page. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return \Illuminate\View\View */ public function showRevisions($bookSlug, $pageSlug) @@ -322,9 +325,9 @@ class PageController extends Controller /** * Shows a preview of a single revision - * @param $bookSlug - * @param $pageSlug - * @param $revisionId + * @param string $bookSlug + * @param string $pageSlug + * @param int $revisionId * @return \Illuminate\View\View */ public function showRevision($bookSlug, $pageSlug, $revisionId) @@ -339,9 +342,9 @@ class PageController extends Controller /** * Restores a page using the content of the specified revision. - * @param $bookSlug - * @param $pageSlug - * @param $revisionId + * @param string $bookSlug + * @param string $pageSlug + * @param int $revisionId * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ public function restoreRevision($bookSlug, $pageSlug, $revisionId) @@ -357,8 +360,8 @@ class PageController extends Controller /** * Exports a page to pdf format using barryvdh/laravel-dompdf wrapper. * https://github.com/barryvdh/laravel-dompdf - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return \Illuminate\Http\Response */ public function exportPdf($bookSlug, $pageSlug) @@ -374,8 +377,8 @@ class PageController extends Controller /** * Export a page to a self-contained HTML file. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return \Illuminate\Http\Response */ public function exportHtml($bookSlug, $pageSlug) @@ -391,8 +394,8 @@ class PageController extends Controller /** * Export a page to a simple plaintext .txt file. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return \Illuminate\Http\Response */ public function exportPlainText($bookSlug, $pageSlug) @@ -434,8 +437,8 @@ class PageController extends Controller /** * Show the Restrictions view. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function showRestrict($bookSlug, $pageSlug) @@ -452,8 +455,8 @@ class PageController extends Controller /** * Show the view to choose a new parent to move a page into. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @return mixed * @throws NotFoundException */ @@ -470,8 +473,8 @@ class PageController extends Controller /** * Does the action of moving the location of a page - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @param Request $request * @return mixed * @throws NotFoundException @@ -513,8 +516,8 @@ class PageController extends Controller /** * Set the permissions for this page. - * @param $bookSlug - * @param $pageSlug + * @param string $bookSlug + * @param string $pageSlug * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php index 7255ad05f..c64da1267 100644 --- a/app/Repos/PageRepo.php +++ b/app/Repos/PageRepo.php @@ -7,6 +7,7 @@ use BookStack\Entity; use BookStack\Exceptions\NotFoundException; use Carbon\Carbon; use DOMDocument; +use DOMXPath; use Illuminate\Support\Str; use BookStack\Page; use BookStack\PageRevision; @@ -158,6 +159,35 @@ class PageRepo extends EntityRepo return $page; } + /** + * Parse te headers on the page to get a navigation menu + * @param Page $page + * @return array + */ + public function getPageNav(Page $page) + { + if ($page->html == '') return null; + libxml_use_internal_errors(true); + $doc = new DOMDocument(); + $doc->loadHTML(mb_convert_encoding($page->html, 'HTML-ENTITIES', 'UTF-8')); + $xPath = new DOMXPath($doc); + $headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6"); + + if (is_null($headers)) return null; + + $tree = []; + foreach ($headers as $header) { + $text = $header->nodeValue; + $tree[] = [ + 'nodeName' => strtolower($header->nodeName), + 'level' => intval(str_replace('h', '', $header->nodeName)), + 'link' => '#' . $header->getAttribute('id'), + 'text' => strlen($text) > 30 ? substr($text, 0, 27) . '...' : $text + ]; + } + return $tree; + } + /** * Formats a page's html to be tagged correctly * within the system. diff --git a/resources/assets/js/pages/page-form.js b/resources/assets/js/pages/page-form.js index 755d558e8..c1e6a92df 100644 --- a/resources/assets/js/pages/page-form.js +++ b/resources/assets/js/pages/page-form.js @@ -81,9 +81,10 @@ var mceOptions = module.exports = { toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image-insert link hr | removeformat code fullscreen", content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}", style_formats: [ - {title: "Header 1", format: "h1"}, - {title: "Header 2", format: "h2"}, - {title: "Header 3", format: "h3"}, + {title: "Header Large", format: "h2"}, + {title: "Header Medium", format: "h3"}, + {title: "Header Small", format: "h4"}, + {title: "Header Tiny", format: "h5"}, {title: "Paragraph", format: "p", exact: true, classes: ''}, {title: "Blockquote", format: "blockquote"}, {title: "Code Block", icon: "code", format: "pre"}, diff --git a/resources/assets/sass/_lists.scss b/resources/assets/sass/_lists.scss index 2658c4689..54fd55dff 100644 --- a/resources/assets/sass/_lists.scss +++ b/resources/assets/sass/_lists.scss @@ -1,5 +1,5 @@ .page-list { - h3 { + h4 { margin: $-l 0 $-xs 0; font-size: 1.666em; } @@ -11,11 +11,13 @@ overflow: hidden; margin-bottom: $-l; } - h4 { + h5 { display: block; margin: $-s 0 0 0; border-left: 5px solid $color-page; padding: $-xs 0 $-xs $-m; + font-size: 1.1em; + font-weight: normal; &.draft { border-left-color: $color-page-draft; } @@ -67,44 +69,39 @@ } } -.page-nav-list { +.sidebar-page-nav { $nav-indent: $-s; - margin-left: 2px; list-style: none; + margin: $-s 0 $-m 2px; + border-left: 2px dotted #BBB; li { - //border-left: 1px solid rgba(0, 0, 0, 0.1); - padding-left: $-xs; - border-left: 2px solid #888; + padding-left: $-s; margin-bottom: 4px; - } - li a { - color: #555; - } - .nav-H2 { - margin-left: $nav-indent; font-size: 0.95em; } - .nav-H3 { + .h1 { + margin-left: -2px; + } + .h2 { + margin-left: -2px; + } + .h3 { + margin-left: $nav-indent; + } + .h4 { margin-left: $nav-indent*2; - font-size: 0.90em } - .nav-H4 { + .h5 { margin-left: $nav-indent*3; - font-size: 0.85em } - .nav-H5 { + .h6 { margin-left: $nav-indent*4; - font-size: 0.80em - } - .nav-H6 { - margin-left: $nav-indent*5; - font-size: 0.75em } } // Sidebar list .book-tree { - padding: $-l 0 0 0; + padding: $-xs 0 0 0; position: relative; right: 0; top: 0; @@ -306,10 +303,10 @@ ul.pagination { } .entity-list { - >div { + > div { padding: $-m 0; } - h3 { + h4 { margin: 0; } p { @@ -327,9 +324,10 @@ ul.pagination { color: $color-page-draft; } } + .entity-list.compact { font-size: 0.6em; - h3, a { + h4, a { line-height: 1.2; } p { diff --git a/resources/assets/sass/_text.scss b/resources/assets/sass/_text.scss index cd81bb4e2..fd993b685 100644 --- a/resources/assets/sass/_text.scss +++ b/resources/assets/sass/_text.scss @@ -15,31 +15,41 @@ h2 { margin-bottom: 0.43137255em; } h3 { - font-size: 1.75em; + font-size: 2.333em; line-height: 1.571428572em; margin-top: 0.78571429em; margin-bottom: 0.43137255em; } h4 { - font-size: 1em; + font-size: 1.666em; line-height: 1.375em; margin-top: 0.78571429em; margin-bottom: 0.43137255em; } -h1, h2, h3, h4 { +h1, h2, h3, h4, h5, h6 { font-weight: 400; position: relative; display: block; color: #555; .subheader { - //display: block; font-size: 0.5em; line-height: 1em; color: lighten($text-dark, 32%); } } +h5 { + font-size: 1.4em; +} + +h5, h6 { + font-weight: 500; + line-height: 1.2em; + margin-top: 0.78571429em; + margin-bottom: 0.66em; +} + /* * Link styling */ diff --git a/resources/views/books/list-item.blade.php b/resources/views/books/list-item.blade.php index 2eefdfbf5..605841f7f 100644 --- a/resources/views/books/list-item.blade.php +++ b/resources/views/books/list-item.blade.php @@ -1,5 +1,5 @@
-

{{$book->name}}

+

{{$book->name}}

@if(isset($book->searchSnippet))

{!! $book->searchSnippet !!}

@else diff --git a/resources/views/chapters/list-item.blade.php b/resources/views/chapters/list-item.blade.php index 35d3a7589..f70e59244 100644 --- a/resources/views/chapters/list-item.blade.php +++ b/resources/views/chapters/list-item.blade.php @@ -1,5 +1,5 @@
-

+

@if (isset($showPath) && $showPath) {{ $chapter->book->name }} @@ -9,7 +9,7 @@ {{ $chapter->name }} -

+ @if(isset($chapter->searchSnippet))

{!! $chapter->searchSnippet !!}

@else @@ -20,7 +20,7 @@

{{ count($chapter->pages) }} Pages

@foreach($chapter->pages as $page) -

{{$page->name}}

+
{{$page->name}}
@endforeach
@endif diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 2529c39c7..2fb4ac855 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -25,14 +25,14 @@
@if(count($draftPages) > 0) -

My Recent Drafts

+

My Recent Drafts

@include('partials/entity-list', ['entities' => $draftPages, 'style' => 'compact']) @endif
@if($signedIn) -

My Recently Viewed

+

My Recently Viewed

@else -

Recent Books

+

Recent Books

@endif @include('partials/entity-list', [ 'entities' => $recents, @@ -42,7 +42,7 @@
-

Recently Created Pages

+

Recently Created Pages

@include('partials/entity-list', [ 'entities' => $recentlyCreatedPages, @@ -51,7 +51,7 @@ ])
-

Recently Updated Pages

+

Recently Updated Pages

@include('partials/entity-list', [ 'entities' => $recentlyUpdatedPages, @@ -62,7 +62,7 @@
-

Recent Activity

+

Recent Activity

@include('partials/activity-list', ['activity' => $activity])
diff --git a/resources/views/pages/list-item.blade.php b/resources/views/pages/list-item.blade.php index 98243f6fa..7aa5d7933 100644 --- a/resources/views/pages/list-item.blade.php +++ b/resources/views/pages/list-item.blade.php @@ -1,7 +1,7 @@
-

+

{{ $page->name }} -

+ @if(isset($page->searchSnippet))

{!! $page->searchSnippet !!}

diff --git a/resources/views/pages/show.blade.php b/resources/views/pages/show.blade.php index 2e6e35476..af85075a2 100644 --- a/resources/views/pages/show.blade.php +++ b/resources/views/pages/show.blade.php @@ -114,7 +114,8 @@ @endif
@endif - @include('pages/sidebar-tree-list', ['book' => $book, 'sidebarTree' => $sidebarTree]) + + @include('pages/sidebar-tree-list', ['book' => $book, 'sidebarTree' => $sidebarTree, 'pageNav' => $pageNav])
diff --git a/resources/views/pages/sidebar-tree-list.blade.php b/resources/views/pages/sidebar-tree-list.blade.php index e40fdbf0f..5fcec8731 100644 --- a/resources/views/pages/sidebar-tree-list.blade.php +++ b/resources/views/pages/sidebar-tree-list.blade.php @@ -1,5 +1,19 @@
+ + @if (isset($pageNav) && $pageNav) +
Page Navigation
+ + + + @endif +
Book Navigation
diff --git a/resources/views/public.blade.php b/resources/views/public.blade.php index 2de4d968a..542d5c867 100644 --- a/resources/views/public.blade.php +++ b/resources/views/public.blade.php @@ -31,7 +31,9 @@ @if(setting('app-logo', '') !== 'none') Logo @endif - {{ setting('app-name') }} + @if (setting('app-name-header')) + {{ setting('app-name') }} + @endif
diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php index 222ff0f69..757729763 100644 --- a/resources/views/settings/index.blade.php +++ b/resources/views/settings/index.blade.php @@ -6,7 +6,7 @@
-

Settings

+

{{ trans('settings.settings') }}

{!! csrf_field() !!} @@ -14,61 +14,70 @@

App Settings

+
- + +

{{ trans('settings.app_name_desc') }}

- + +
+
+
+
- -

For performance reasons, all images are public. This option adds a random, hard-to-guess string in front of image urls. Ensure directory indexes are not enabled to prevent easy access.

+ +

{{ trans('settings.app_secure_images_desc') }}

- -

Select which editor will be used by all users to edit pages.

+ +

{{ trans('settings.app_editor_desc') }}

+
- -

This image should be 43px in height.
Large images will be scaled down.

+ +

{!! trans('settings.app_logo_desc') !!}

- -

This should be a hex value.
Leave empty to reset to the default color.

+ +

{!! trans('settings.app_primary_color_desc') !!}

+
+
- -

Any content added here will be inserted into the bottom of the <head> section of every page. This is handy for overriding styles or adding analytics code.

+ +

{{ trans('settings.app_custom_html_desc') }}


-

Registration Settings

+

{{ trans('settings.reg_settings') }}

- +
- + + +

{!! trans('settings.reg_confirm_restrict_domain_desc') !!}

+
@@ -101,7 +109,7 @@ BookStack @if(strpos($version, 'v') !== 0) version @endif {{ $version }} - +
From 42d8e9e5bda57a26bbaa3f6e4a9e4e5f94a341e7 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 29 Sep 2016 09:13:15 +0100 Subject: [PATCH 08/27] Improved numeric term search capabilities Prevented a quoted term also being added to fuzzy searches and also added check to see if the term is numeric to check if an exact match is required. Closes #200 --- app/Entity.php | 67 +++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/app/Entity.php b/app/Entity.php index 496d20a33..8a15b5aa4 100644 --- a/app/Entity.php +++ b/app/Entity.php @@ -160,44 +160,49 @@ class Entity extends Ownable public function fullTextSearchQuery($fieldsToSearch, $terms, $wheres = []) { $exactTerms = []; - if (count($terms) === 0) { - $search = $this; - $orderBy = 'updated_at'; - } else { - foreach ($terms as $key => $term) { - $term = htmlentities($term, ENT_QUOTES); - $term = preg_replace('/[+\-><\(\)~*\"@]+/', ' ', $term); - if (preg_match('/".*?"/', $term)) { - $term = str_replace('"', '', $term); - $exactTerms[] = '%' . $term . '%'; - $term = '"' . $term . '"'; - } else { - $term = '' . $term . '*'; - } - if ($term !== '*') $terms[$key] = $term; - } - $termString = implode(' ', $terms); - $fields = implode(',', $fieldsToSearch); - $search = static::selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance', [$termString]); - $search = $search->whereRaw('MATCH(' . $fields . ') AGAINST(? IN BOOLEAN MODE)', [$termString]); + $fuzzyTerms = []; + $search = static::newQuery(); - // Ensure at least one exact term matches if in search - if (count($exactTerms) > 0) { - $search = $search->where(function ($query) use ($exactTerms, $fieldsToSearch) { - foreach ($exactTerms as $exactTerm) { - foreach ($fieldsToSearch as $field) { - $query->orWhere($field, 'like', $exactTerm); - } - } - }); + foreach ($terms as $key => $term) { + $term = htmlentities($term, ENT_QUOTES); + $term = preg_replace('/[+\-><\(\)~*\"@]+/', ' ', $term); + if (preg_match('/".*?"/', $term) || is_numeric($term)) { + $term = str_replace('"', '', $term); + $exactTerms[] = '%' . $term . '%'; + } else { + $term = '' . $term . '*'; + if ($term !== '*') $fuzzyTerms[] = $term; } - $orderBy = 'title_relevance'; - }; + } + + $isFuzzy = count($exactTerms) === 0 || count($fuzzyTerms) > 0; + + // Perform fulltext search if relevant terms exist. + if ($isFuzzy) { + $termString = implode(' ', $fuzzyTerms); + $fields = implode(',', $fieldsToSearch); + $search = $search->selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance', [$termString]); + $search = $search->whereRaw('MATCH(' . $fields . ') AGAINST(? IN BOOLEAN MODE)', [$termString]); + } + + // Ensure at least one exact term matches if in search + if (count($exactTerms) > 0) { + $search = $search->where(function ($query) use ($exactTerms, $fieldsToSearch) { + foreach ($exactTerms as $exactTerm) { + foreach ($fieldsToSearch as $field) { + $query->orWhere($field, 'like', $exactTerm); + } + } + }); + } + + $orderBy = $isFuzzy ? 'title_relevance' : 'updated_at'; // Add additional where terms foreach ($wheres as $whereTerm) { $search->where($whereTerm[0], $whereTerm[1], $whereTerm[2]); } + // Load in relations if ($this->isA('page')) { $search = $search->with('book', 'chapter', 'createdBy', 'updatedBy'); From f15cc5bdfad7ce729e61abbd14ebc2807d7bb651 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 29 Sep 2016 10:10:46 +0100 Subject: [PATCH 09/27] Separated revision preview and diff & fixed chosen diff html Closes #8 --- app/Http/Controllers/PageController.php | 29 ++++++++++++++++++++--- app/PageRevision.php | 26 ++++++++------------ app/Repos/PageRepo.php | 2 +- resources/views/pages/revisions.blade.php | 23 ++++++++++-------- routes/web.php | 1 + 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 6081d1b27..033377a4d 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -336,13 +336,36 @@ class PageController extends Controller $book = $this->bookRepo->getBySlug($bookSlug); $page = $this->pageRepo->getBySlug($pageSlug, $book->id); $revision = $this->pageRepo->getRevisionById($revisionId); - - $next = $revision->getNext() ?: $page; - $diff = (new Htmldiff)->diff($revision->html, $next->html); $page->fill($revision->toArray()); $this->setPageTitle('Page Revision For ' . $page->getShortName()); + return view('pages/revision', [ + 'page' => $page, + 'book' => $book, + ]); + } + + /** + * Shows the changes of a single revision + * @param string $bookSlug + * @param string $pageSlug + * @param int $revisionId + * @return \Illuminate\View\View + */ + public function showRevisionChanges($bookSlug, $pageSlug, $revisionId) + { + $book = $this->bookRepo->getBySlug($bookSlug); + $page = $this->pageRepo->getBySlug($pageSlug, $book->id); + $revision = $this->pageRepo->getRevisionById($revisionId); + + $prev = $revision->getPrevious(); + $prevContent = ($prev === null) ? '' : $prev->html; + $diff = (new Htmldiff)->diff($prevContent, $revision->html); + + $page->fill($revision->toArray()); + $this->setPageTitle('Page Revision For ' . $page->getShortName()); + return view('pages/revision', [ 'page' => $page, 'book' => $book, diff --git a/app/PageRevision.php b/app/PageRevision.php index e5721f5aa..ff469f0ed 100644 --- a/app/PageRevision.php +++ b/app/PageRevision.php @@ -25,32 +25,26 @@ class PageRevision extends Model /** * Get the url for this revision. + * @param null|string $path * @return string */ - public function getUrl() + public function getUrl($path = null) { - return $this->page->getUrl() . '/revisions/' . $this->id; + $url = $this->page->getUrl() . '/revisions/' . $this->id; + if ($path) return $url . '/' . trim($path, '/'); + return $url; } /** - * Get previous revision - * @return \BookStack\PageRevision + * Get the previous revision for the same page if existing + * @return \BookStack\PageRevision|null */ public function getPrevious() { - if ($id = PageRevision::where('id', '<', $this->id)->max('id')) { - return PageRevision::find($id); + if ($id = static::where('page_id', '=', $this->page_id)->where('id', '<', $this->id)->max('id')) { + return static::find($id); } + return null; } - /** - * Get next revision - * @return \BookStack\PageRevision - */ - public function getNext() - { - if ($id = PageRevision::where('id', '>', $this->id)->min('id')) { - return PageRevision::find($id); - } - } } diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php index c64da1267..93ff61b62 100644 --- a/app/Repos/PageRepo.php +++ b/app/Repos/PageRepo.php @@ -548,7 +548,7 @@ class PageRepo extends EntityRepo /** * Gets a single revision via it's id. * @param $id - * @return mixed + * @return PageRevision */ public function getRevisionById($id) { diff --git a/resources/views/pages/revisions.blade.php b/resources/views/pages/revisions.blade.php index 926affffc..720e34fea 100644 --- a/resources/views/pages/revisions.blade.php +++ b/resources/views/pages/revisions.blade.php @@ -32,11 +32,11 @@ - - + + - + @foreach($page->revisions as $index => $revision) @@ -49,15 +49,18 @@ - @if ($index !== 0) - - @else - - @endif + Restore + @endif + @endforeach
NameCreated ByNameCreated By Revision Date ChangelogActionsActions
@if($revision->createdBy) {{ $revision->createdBy->name }} @else Deleted User @endif {{ $revision->created_at->format('jS F, Y H:i:s') }}
({{ $revision->created_at->diffForHumans() }})
{{ $revision->summary }} + + Changes +  |  + + @if ($index === 0) + Current Version + @else Preview  |  - Restore - Current Version
diff --git a/routes/web.php b/routes/web.php index 58ceb5f3b..c3fe503d1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -47,6 +47,7 @@ Route::group(['middleware' => 'auth'], function () { // Revisions Route::get('/{bookSlug}/page/{pageSlug}/revisions', 'PageController@showRevisions'); Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}', 'PageController@showRevision'); + Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/changes', 'PageController@showRevisionChanges'); Route::get('/{bookSlug}/page/{pageSlug}/revisions/{revId}/restore', 'PageController@restoreRevision'); // Chapters From 771626b6ecb97158d5903536726431e2b594f783 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 29 Sep 2016 12:43:46 +0100 Subject: [PATCH 10/27] Started work on making the public role/user configurable Create a new 'public' guest user and made the public role visible on role setting screens. --- app/Http/Controllers/ChapterController.php | 2 +- app/Http/Controllers/Controller.php | 11 ++-- app/Http/Controllers/UserController.php | 9 +-- app/Repos/BookRepo.php | 6 +- app/Repos/ChapterRepo.php | 4 +- app/Repos/EntityRepo.php | 3 +- app/Repos/PageRepo.php | 14 ++-- app/Repos/PermissionsRepo.php | 6 +- app/Repos/UserRepo.php | 6 +- app/Services/ActivityService.php | 2 +- app/Services/ImageService.php | 4 +- app/Services/PermissionService.php | 2 +- app/Services/SocialAuthService.php | 6 +- app/Services/ViewService.php | 4 +- app/User.php | 20 ++++-- app/helpers.php | 12 +++- .../2016_09_29_101449_remove_hidden_roles.php | 66 +++++++++++++++++++ resources/views/settings/index.blade.php | 2 +- resources/views/users/forms/system.blade.php | 25 +++++++ 19 files changed, 156 insertions(+), 48 deletions(-) create mode 100644 database/migrations/2016_09_29_101449_remove_hidden_roles.php create mode 100644 resources/views/users/forms/system.blade.php diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php index 03ec2c110..57ca58beb 100644 --- a/app/Http/Controllers/ChapterController.php +++ b/app/Http/Controllers/ChapterController.php @@ -117,7 +117,7 @@ class ChapterController extends Controller $this->checkOwnablePermission('chapter-update', $chapter); $chapter->fill($request->all()); $chapter->slug = $this->chapterRepo->findSuitableSlug($chapter->name, $book->id, $chapter->id); - $chapter->updated_by = auth()->user()->id; + $chapter->updated_by = user()->id; $chapter->save(); Activity::add($chapter, 'chapter_update', $book->id); return redirect($chapter->getUrl()); diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 43292d941..2dabc417b 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -33,17 +33,16 @@ abstract class Controller extends BaseController $this->middleware(function ($request, $next) { // Get a user instance for the current user - $user = auth()->user(); - if (!$user) $user = User::getDefault(); - - // Share variables with views - view()->share('signedIn', auth()->check()); - view()->share('currentUser', $user); + $user = user(); // Share variables with controllers $this->currentUser = $user; $this->signedIn = auth()->check(); + // Share variables with views + view()->share('signedIn', $this->signedIn); + view()->share('currentUser', $user); + return $next($request); }); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 4c56516dc..51c5d25bb 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -57,7 +57,7 @@ class UserController extends Controller { $this->checkPermission('users-manage'); $authMethod = config('auth.method'); - $roles = $this->userRepo->getAssignableRoles(); + $roles = $this->userRepo->getAllRoles(); return view('users/create', ['authMethod' => $authMethod, 'roles' => $roles]); } @@ -126,12 +126,13 @@ class UserController extends Controller return $this->currentUser->id == $id; }); - $authMethod = config('auth.method'); - $user = $this->user->findOrFail($id); + + $authMethod = ($user->system_name) ? 'system' : config('auth.method'); + $activeSocialDrivers = $socialAuthService->getActiveDrivers(); $this->setPageTitle('User Profile'); - $roles = $this->userRepo->getAssignableRoles(); + $roles = $this->userRepo->getAllRoles(); return view('users/edit', ['user' => $user, 'activeSocialDrivers' => $activeSocialDrivers, 'authMethod' => $authMethod, 'roles' => $roles]); } diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php index fdc4dd8d4..1af02035d 100644 --- a/app/Repos/BookRepo.php +++ b/app/Repos/BookRepo.php @@ -132,8 +132,8 @@ class BookRepo extends EntityRepo { $book = $this->book->newInstance($input); $book->slug = $this->findSuitableSlug($book->name); - $book->created_by = auth()->user()->id; - $book->updated_by = auth()->user()->id; + $book->created_by = user()->id; + $book->updated_by = user()->id; $book->save(); $this->permissionService->buildJointPermissionsForEntity($book); return $book; @@ -149,7 +149,7 @@ class BookRepo extends EntityRepo { $book->fill($input); $book->slug = $this->findSuitableSlug($book->name, $book->id); - $book->updated_by = auth()->user()->id; + $book->updated_by = user()->id; $book->save(); $this->permissionService->buildJointPermissionsForEntity($book); return $book; diff --git a/app/Repos/ChapterRepo.php b/app/Repos/ChapterRepo.php index c12a9f0f2..96f5b2d1e 100644 --- a/app/Repos/ChapterRepo.php +++ b/app/Repos/ChapterRepo.php @@ -98,8 +98,8 @@ class ChapterRepo extends EntityRepo { $chapter = $this->chapter->newInstance($input); $chapter->slug = $this->findSuitableSlug($chapter->name, $book->id); - $chapter->created_by = auth()->user()->id; - $chapter->updated_by = auth()->user()->id; + $chapter->created_by = user()->id; + $chapter->updated_by = user()->id; $chapter = $book->chapters()->save($chapter); $this->permissionService->buildJointPermissionsForEntity($chapter); return $chapter; diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php index c94601738..42b0b6b7b 100644 --- a/app/Repos/EntityRepo.php +++ b/app/Repos/EntityRepo.php @@ -132,9 +132,8 @@ class EntityRepo */ public function getUserDraftPages($count = 20, $page = 0) { - $user = auth()->user(); return $this->page->where('draft', '=', true) - ->where('created_by', '=', $user->id) + ->where('created_by', '=', user()->id) ->orderBy('updated_at', 'desc') ->skip($count * $page)->take($count)->get(); } diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php index 93ff61b62..537dd9bd0 100644 --- a/app/Repos/PageRepo.php +++ b/app/Repos/PageRepo.php @@ -148,8 +148,8 @@ class PageRepo extends EntityRepo { $page = $this->page->newInstance(); $page->name = 'New Page'; - $page->created_by = auth()->user()->id; - $page->updated_by = auth()->user()->id; + $page->created_by = user()->id; + $page->updated_by = user()->id; $page->draft = true; if ($chapter) $page->chapter_id = $chapter->id; @@ -330,7 +330,7 @@ class PageRepo extends EntityRepo } // Update with new details - $userId = auth()->user()->id; + $userId = user()->id; $page->fill($input); $page->html = $this->formatHtml($input['html']); $page->text = strip_tags($page->html); @@ -363,7 +363,7 @@ class PageRepo extends EntityRepo $page->fill($revision->toArray()); $page->slug = $this->findSuitableSlug($page->name, $book->id, $page->id); $page->text = strip_tags($page->html); - $page->updated_by = auth()->user()->id; + $page->updated_by = user()->id; $page->save(); return $page; } @@ -381,7 +381,7 @@ class PageRepo extends EntityRepo $revision->page_id = $page->id; $revision->slug = $page->slug; $revision->book_slug = $page->book->slug; - $revision->created_by = auth()->user()->id; + $revision->created_by = user()->id; $revision->created_at = $page->updated_at; $revision->type = 'version'; $revision->summary = $summary; @@ -404,7 +404,7 @@ class PageRepo extends EntityRepo */ public function saveUpdateDraft(Page $page, $data = []) { - $userId = auth()->user()->id; + $userId = user()->id; $drafts = $this->userUpdateDraftsQuery($page, $userId)->get(); if ($drafts->count() > 0) { @@ -535,7 +535,7 @@ class PageRepo extends EntityRepo $query = $this->pageRevision->where('type', '=', 'update_draft') ->where('page_id', '=', $page->id) ->where('updated_at', '>', $page->updated_at) - ->where('created_by', '!=', auth()->user()->id) + ->where('created_by', '!=', user()->id) ->with('createdBy'); if ($minRange !== null) { diff --git a/app/Repos/PermissionsRepo.php b/app/Repos/PermissionsRepo.php index e026d83e8..24497c911 100644 --- a/app/Repos/PermissionsRepo.php +++ b/app/Repos/PermissionsRepo.php @@ -35,7 +35,7 @@ class PermissionsRepo */ public function getAllRoles() { - return $this->role->where('hidden', '=', false)->get(); + return $this->role->all(); } /** @@ -45,7 +45,7 @@ class PermissionsRepo */ public function getAllRolesExcept(Role $role) { - return $this->role->where('id', '!=', $role->id)->where('hidden', '=', false)->get(); + return $this->role->where('id', '!=', $role->id)->get(); } /** @@ -90,8 +90,6 @@ class PermissionsRepo { $role = $this->role->findOrFail($roleId); - if ($role->hidden) throw new PermissionsException("Cannot update a hidden role"); - $permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : []; $this->assignRolePermissions($role, $permissions); diff --git a/app/Repos/UserRepo.php b/app/Repos/UserRepo.php index 127db9fb5..ab3716fca 100644 --- a/app/Repos/UserRepo.php +++ b/app/Repos/UserRepo.php @@ -199,9 +199,9 @@ class UserRepo * Get the roles in the system that are assignable to a user. * @return mixed */ - public function getAssignableRoles() + public function getAllRoles() { - return $this->role->visible(); + return $this->role->all(); } /** @@ -211,7 +211,7 @@ class UserRepo */ public function getRestrictableRoles() { - return $this->role->where('hidden', '=', false)->where('system_name', '=', '')->get(); + return $this->role->where('system_name', '!=', 'admin')->get(); } } \ No newline at end of file diff --git a/app/Services/ActivityService.php b/app/Services/ActivityService.php index f6fea33a1..e41036238 100644 --- a/app/Services/ActivityService.php +++ b/app/Services/ActivityService.php @@ -19,7 +19,7 @@ class ActivityService { $this->activity = $activity; $this->permissionService = $permissionService; - $this->user = auth()->user(); + $this->user = user(); } /** diff --git a/app/Services/ImageService.php b/app/Services/ImageService.php index aa1375487..a56626246 100644 --- a/app/Services/ImageService.php +++ b/app/Services/ImageService.php @@ -108,8 +108,8 @@ class ImageService 'uploaded_to' => $uploadedTo ]; - if (auth()->user() && auth()->user()->id !== 0) { - $userId = auth()->user()->id; + if (user()->id !== 0) { + $userId = user()->id; $imageDetails['created_by'] = $userId; $imageDetails['updated_by'] = $userId; } diff --git a/app/Services/PermissionService.php b/app/Services/PermissionService.php index 341a69edb..bb78f0b0a 100644 --- a/app/Services/PermissionService.php +++ b/app/Services/PermissionService.php @@ -614,7 +614,7 @@ class PermissionService private function currentUser() { if ($this->currentUserModel === false) { - $this->currentUserModel = auth()->user() ? auth()->user() : new User(); + $this->currentUserModel = user(); } return $this->currentUserModel; diff --git a/app/Services/SocialAuthService.php b/app/Services/SocialAuthService.php index b28a97ea4..d76a7231b 100644 --- a/app/Services/SocialAuthService.php +++ b/app/Services/SocialAuthService.php @@ -100,7 +100,7 @@ class SocialAuthService $socialAccount = $this->socialAccount->where('driver_id', '=', $socialId)->first(); $user = $this->userRepo->getByEmail($socialUser->getEmail()); $isLoggedIn = auth()->check(); - $currentUser = auth()->user(); + $currentUser = user(); // When a user is not logged in and a matching SocialAccount exists, // Simply log the user into the application. @@ -214,9 +214,9 @@ class SocialAuthService public function detachSocialAccount($socialDriver) { session(); - auth()->user()->socialAccounts()->where('driver', '=', $socialDriver)->delete(); + user()->socialAccounts()->where('driver', '=', $socialDriver)->delete(); session()->flash('success', title_case($socialDriver) . ' account successfully detached'); - return redirect(auth()->user()->getEditUrl()); + return redirect(user()->getEditUrl()); } } \ No newline at end of file diff --git a/app/Services/ViewService.php b/app/Services/ViewService.php index aac9831f7..1a9ee5f70 100644 --- a/app/Services/ViewService.php +++ b/app/Services/ViewService.php @@ -18,7 +18,7 @@ class ViewService public function __construct(View $view, PermissionService $permissionService) { $this->view = $view; - $this->user = auth()->user(); + $this->user = user(); $this->permissionService = $permissionService; } @@ -84,7 +84,7 @@ class ViewService ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type'); if ($filterModel) $query = $query->where('viewable_type', '=', get_class($filterModel)); - $query = $query->where('user_id', '=', auth()->user()->id); + $query = $query->where('user_id', '=', user()->id); $viewables = $query->with('viewable')->orderBy('updated_at', 'desc') ->skip($count * $page)->take($count)->get()->pluck('viewable'); diff --git a/app/User.php b/app/User.php index 8c39d81be..09b189cbb 100644 --- a/app/User.php +++ b/app/User.php @@ -5,6 +5,7 @@ use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, CanResetPasswordContract @@ -36,21 +37,30 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon protected $permissions; /** - * Returns a default guest user. + * Returns the default public user. + * @return User */ public static function getDefault() { - return new static([ - 'email' => 'guest', - 'name' => 'Guest' - ]); + return static::where('system_name', '=', 'public')->first(); + } + + /** + * Check if the user is the default public user. + * @return bool + */ + public function isDefault() + { + return $this->system_name === 'public'; } /** * The roles that belong to the user. + * @return BelongsToMany */ public function roles() { + if ($this->id === 0) return ; return $this->belongsToMany(Role::class); } diff --git a/app/helpers.php b/app/helpers.php index dd835fbf6..ad1c7dd20 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -36,6 +36,16 @@ function versioned_asset($file = '') throw new InvalidArgumentException("File {$file} not defined in asset manifest."); } +/** + * Helper method to get the current User. + * Defaults to public 'Guest' user if not logged in. + * @return \BookStack\User + */ +function user() +{ + return auth()->user() ?: \BookStack\User::getDefault(); +} + /** * Check if the current user has a permission. * If an ownable element is passed in the jointPermissions are checked against @@ -47,7 +57,7 @@ function versioned_asset($file = '') function userCan($permission, Ownable $ownable = null) { if ($ownable === null) { - return auth()->user() && auth()->user()->can($permission); + return user() && user()->can($permission); } // Check permission on ownable item diff --git a/database/migrations/2016_09_29_101449_remove_hidden_roles.php b/database/migrations/2016_09_29_101449_remove_hidden_roles.php new file mode 100644 index 000000000..f666cad2c --- /dev/null +++ b/database/migrations/2016_09_29_101449_remove_hidden_roles.php @@ -0,0 +1,66 @@ +dropColumn('hidden'); + }); + + // Add column to mark system users + Schema::table('users', function(Blueprint $table) { + $table->string('system_name')->nullable()->index(); + }); + + // Insert our new public system user. + $publicUserId = DB::table('users')->insertGetId([ + 'email' => 'guest@example.com', + 'name' => 'Guest', + 'system_name' => 'public', + 'email_confirmed' => true, + 'created_at' => \Carbon\Carbon::now(), + 'updated_at' => \Carbon\Carbon::now(), + ]); + + // Get the public role + $publicRole = DB::table('roles')->where('system_name', '=', 'public')->first(); + + // Connect the new public user to the public role + DB::table('role_user')->insert([ + 'user_id' => $publicUserId, + 'role_id' => $publicRole->id + ]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('roles', function(Blueprint $table) { + $table->boolean('hidden')->default(false); + $table->index('hidden'); + }); + + DB::table('users')->where('system_name', '=', 'public')->delete(); + + Schema::table('users', function(Blueprint $table) { + $table->dropColumn('system_name'); + }); + + DB::table('roles')->where('system_name', '=', 'public')->update(['hidden' => true]); + } +} diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php index 757729763..ac25eb3b5 100644 --- a/resources/views/settings/index.blade.php +++ b/resources/views/settings/index.blade.php @@ -79,7 +79,7 @@