diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 4f9f4c480..e7e75cc9f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,11 +1,13 @@ ### For Feature Requests + Desired Feature: ### For Bug Reports -PHP Version: -MySQL Version: +* BookStack Version: +* PHP Version: +* MySQL Version: -Expected Behavior: +##### Expected Behavior -Actual Behavior: +##### Actual Behavior diff --git a/.travis.yml b/.travis.yml index e2eb5f511..0ad753ced 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,9 +17,7 @@ addons: before_script: - mysql -u root -e 'create database `bookstack-test`;' - - composer config -g github-oauth.github.com $GITHUB_ACCESS_TOKEN - phpenv config-rm xdebug.ini - - composer self-update - composer dump-autoload --no-interaction - composer install --prefer-dist --no-interaction - php artisan clear-compiled -n diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index c64f0cd1f..5260eb6cd 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -3,9 +3,9 @@ namespace BookStack\Exceptions; use Exception; -use Illuminate\Contracts\Validation\ValidationException; +use Illuminate\Auth\AuthenticationException; +use Illuminate\Validation\ValidationException; use Illuminate\Database\Eloquent\ModelNotFoundException; -use PhpSpec\Exception\Example\ErrorException; use Symfony\Component\HttpKernel\Exception\HttpException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Auth\Access\AuthorizationException; diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index 57ac486d5..408192ff9 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -208,7 +208,7 @@ class BookController extends Controller } // Update permissions on changed models - $this->entityRepo->buildJointPermissions($updatedModels); + if (count($updatedModels) === 0) $this->entityRepo->buildJointPermissions($updatedModels); return redirect($book->getUrl()); } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 2b6c88fe0..733d5416b 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -4,7 +4,7 @@ namespace BookStack\Http\Controllers; use BookStack\Ownable; use Illuminate\Foundation\Bus\DispatchesJobs; -use Illuminate\Http\Exception\HttpResponseException; +use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Http\Request; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 6ed9fc30c..4ed10d61e 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -158,13 +158,16 @@ class PageController extends Controller $this->checkOwnablePermission('page-view', $page); + $pageContent = $this->entityRepo->renderPage($page); $sidebarTree = $this->entityRepo->getBookChildren($page->book); - $pageNav = $this->entityRepo->getPageNav($page); + $pageNav = $this->entityRepo->getPageNav($pageContent); Views::add($page); $this->setPageTitle($page->getShortName()); - return view('pages/show', ['page' => $page, 'book' => $page->book, - 'current' => $page, 'sidebarTree' => $sidebarTree, 'pageNav' => $pageNav]); + return view('pages/show', [ + 'page' => $page,'book' => $page->book, + 'current' => $page, 'sidebarTree' => $sidebarTree, + 'pageNav' => $pageNav, 'pageContent' => $pageContent]); } /** @@ -430,6 +433,7 @@ class PageController extends Controller { $page = $this->entityRepo->getBySlug('page', $pageSlug, $bookSlug); $pdfContent = $this->exportService->pageToPdf($page); +// return $pdfContent; return response()->make($pdfContent, 200, [ 'Content-Type' => 'application/octet-stream', 'Content-Disposition' => 'attachment; filename="' . $pageSlug . '.pdf' diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index b5184c40a..c98d5f87e 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -1,13 +1,8 @@ - 'min:2', 'email' => 'min:2|email|unique:users,email,' . $id, 'password' => 'min:5|required_with:password_confirm', - 'password-confirm' => 'same:password|required_with:password' + 'password-confirm' => 'same:password|required_with:password', + 'setting' => 'array' ]); $user = $this->user->findOrFail($id); @@ -175,6 +171,13 @@ class UserController extends Controller $user->external_auth_id = $request->get('external_auth_id'); } + // Save an user-specific settings + if ($request->has('setting')) { + foreach ($request->get('setting') as $key => $value) { + setting()->putUser($user, $key, $value); + } + } + $user->save(); session()->flash('success', trans('settings.users_edit_success')); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index f1d95f5c0..c55cc9ab8 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -1,6 +1,4 @@ - [ 'throttle:60,1', diff --git a/app/Http/Middleware/Localization.php b/app/Http/Middleware/Localization.php new file mode 100644 index 000000000..31cb5d9a2 --- /dev/null +++ b/app/Http/Middleware/Localization.php @@ -0,0 +1,23 @@ +getUser(user(), 'language', $defaultLang); + app()->setLocale($locale); + Carbon::setLocale($locale); + return $next($request); + } +} diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 2b3c64695..c27df7af4 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -1,6 +1,4 @@ -getMimeType(), $imageMimes); }); - - Carbon::setLocale(config('app.locale')); } /** diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php index 0515a4cd4..f1428735c 100644 --- a/app/Repos/EntityRepo.php +++ b/app/Repos/EntityRepo.php @@ -139,7 +139,7 @@ class EntityRepo */ public function getById($type, $id, $allowDrafts = false) { - return $this->entityQuery($type, $allowDrafts)->findOrFail($id); + return $this->entityQuery($type, $allowDrafts)->find($id); } /** @@ -318,15 +318,15 @@ class EntityRepo */ public function getBookChildren(Book $book, $filterDrafts = false) { - $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts); + $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts)->get(); $entities = []; $parents = []; $tree = []; foreach ($q as $index => $rawEntity) { - if ($rawEntity->entity_type === 'Bookstack\\Page') { + if ($rawEntity->entity_type === 'BookStack\\Page') { $entities[$index] = $this->page->newFromBuilder($rawEntity); - } else if ($rawEntity->entity_type === 'Bookstack\\Chapter') { + } else if ($rawEntity->entity_type === 'BookStack\\Chapter') { $entities[$index] = $this->chapter->newFromBuilder($rawEntity); $key = $entities[$index]->entity_type . ':' . $entities[$index]->id; $parents[$key] = $entities[$index]; @@ -338,7 +338,7 @@ class EntityRepo foreach ($entities as $entity) { if ($entity->chapter_id === 0) continue; - $parentKey = 'Bookstack\\Chapter:' . $entity->chapter_id; + $parentKey = 'BookStack\\Chapter:' . $entity->chapter_id; $chapter = $parents[$parentKey]; $chapter->pages->push($entity); } @@ -796,6 +796,52 @@ class EntityRepo return $html; } + + /** + * Render the page for viewing, Parsing and performing features such as page transclusion. + * @param Page $page + * @return mixed|string + */ + public function renderPage(Page $page) + { + $content = $page->html; + $matches = []; + preg_match_all("/{{@\s?([0-9].*?)}}/", $content, $matches); + if (count($matches[0]) === 0) return $content; + + foreach ($matches[1] as $index => $includeId) { + $splitInclude = explode('#', $includeId, 2); + $pageId = intval($splitInclude[0]); + if (is_nan($pageId)) continue; + + $page = $this->getById('page', $pageId); + if ($page === null) { + $content = str_replace($matches[0][$index], '', $content); + continue; + } + + if (count($splitInclude) === 1) { + $content = str_replace($matches[0][$index], $page->html, $content); + continue; + } + + $doc = new DOMDocument(); + $doc->loadHTML(mb_convert_encoding('
'.$page->html.'', 'HTML-ENTITIES', 'UTF-8')); + $matchingElem = $doc->getElementById($splitInclude[1]); + if ($matchingElem === null) { + $content = str_replace($matches[0][$index], '', $content); + continue; + } + $innerContent = ''; + foreach ($matchingElem->childNodes as $childNode) { + $innerContent .= $doc->saveHTML($childNode); + } + $content = str_replace($matches[0][$index], trim($innerContent), $content); + } + + return $content; + } + /** * Get a new draft page instance. * @param Book $book @@ -835,19 +881,19 @@ class EntityRepo /** * Parse the headers on the page to get a navigation menu - * @param Page $page - * @return Collection + * @param String $pageContent + * @return array */ - public function getPageNav(Page $page) + public function getPageNav($pageContent) { - if ($page->html == '') return null; + if ($pageContent == '') return []; libxml_use_internal_errors(true); $doc = new DOMDocument(); - $doc->loadHTML(mb_convert_encoding($page->html, 'HTML-ENTITIES', 'UTF-8')); + $doc->loadHTML(mb_convert_encoding($pageContent, 'HTML-ENTITIES', 'UTF-8')); $xPath = new DOMXPath($doc); $headers = $xPath->query("//h1|//h2|//h3|//h4|//h5|//h6"); - if (is_null($headers)) return null; + if (is_null($headers)) return []; $tree = collect([]); foreach ($headers as $header) { @@ -868,7 +914,7 @@ class EntityRepo return $header; }); } - return $tree; + return $tree->toArray(); } /** diff --git a/app/Repos/PermissionsRepo.php b/app/Repos/PermissionsRepo.php index e1c6d87b1..aa58d1718 100644 --- a/app/Repos/PermissionsRepo.php +++ b/app/Repos/PermissionsRepo.php @@ -93,7 +93,7 @@ class PermissionsRepo $permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : []; $this->assignRolePermissions($role, $permissions); - if ($role->name === 'admin') { + if ($role->system_name === 'admin') { $permissions = $this->permission->all()->pluck('id')->toArray(); $role->permissions()->sync($permissions); } diff --git a/app/Services/ExportService.php b/app/Services/ExportService.php index 50ba75c17..880bc54ad 100644 --- a/app/Services/ExportService.php +++ b/app/Services/ExportService.php @@ -1,10 +1,22 @@ entityRepo = $entityRepo; + } + /** * Convert a page to a self-contained HTML file. * Includes required CSS & image content. Images are base64 encoded into the HTML. @@ -14,7 +26,7 @@ class ExportService public function pageToContainedHtml(Page $page) { $cssContent = file_get_contents(public_path('/css/export-styles.css')); - $pageHtml = view('pages/export', ['page' => $page, 'css' => $cssContent])->render(); + $pageHtml = view('pages/export', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render(); return $this->containHtml($pageHtml); } @@ -26,7 +38,8 @@ class ExportService public function pageToPdf(Page $page) { $cssContent = file_get_contents(public_path('/css/export-styles.css')); - $pageHtml = view('pages/pdf', ['page' => $page, 'css' => $cssContent])->render(); + $pageHtml = view('pages/pdf', ['page' => $page, 'pageContent' => $this->entityRepo->renderPage($page), 'css' => $cssContent])->render(); +// return $pageHtml; $useWKHTML = config('snappy.pdf.binary') !== false; $containedHtml = $this->containHtml($pageHtml); if ($useWKHTML) { @@ -59,9 +72,13 @@ class ExportService $pathString = $srcString; } if ($isLocal && !file_exists($pathString)) continue; - $imageContent = file_get_contents($pathString); - $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent); - $newImageString = str_replace($srcString, $imageEncoded, $oldImgString); + try { + $imageContent = file_get_contents($pathString); + $imageEncoded = 'data:image/' . pathinfo($pathString, PATHINFO_EXTENSION) . ';base64,' . base64_encode($imageContent); + $newImageString = str_replace($srcString, $imageEncoded, $oldImgString); + } catch (\ErrorException $e) { + $newImageString = ''; + } $htmlContent = str_replace($oldImgString, $newImageString, $htmlContent); } } @@ -88,14 +105,14 @@ class ExportService /** * Converts the page contents into simple plain text. - * This method filters any bad looking content to - * provide a nice final output. + * This method filters any bad looking content to provide a nice final output. * @param Page $page * @return mixed */ public function pageToPlainText(Page $page) { - $text = $page->text; + $html = $this->entityRepo->renderPage($page); + $text = strip_tags($html); // Replace multiple spaces with single spaces $text = preg_replace('/\ {2,}/', ' ', $text); // Reduce multiple horrid whitespace characters. diff --git a/app/Services/Ldap.php b/app/Services/Ldap.php index 196e46a2f..9c3bec327 100644 --- a/app/Services/Ldap.php +++ b/app/Services/Ldap.php @@ -94,4 +94,4 @@ class Ldap return ldap_bind($ldapConnection, $bindRdn, $bindPassword); } -} \ No newline at end of file +} diff --git a/app/Services/LdapService.php b/app/Services/LdapService.php index 40b24f141..f8a4b88bb 100644 --- a/app/Services/LdapService.php +++ b/app/Services/LdapService.php @@ -112,9 +112,13 @@ class LdapService throw new LdapException(trans('errors.ldap_extension_not_installed')); } - // Get port from server string if specified. + // Get port from server string and protocol if specified. $ldapServer = explode(':', $this->config['server']); - $ldapConnection = $this->ldap->connect($ldapServer[0], count($ldapServer) > 1 ? $ldapServer[1] : 389); + $hasProtocol = preg_match('/^ldaps{0,1}\:\/\//', $this->config['server']) === 1; + if (!$hasProtocol) array_unshift($ldapServer, ''); + $hostName = $ldapServer[0] . ($hasProtocol?':':'') . $ldapServer[1]; + $defaultPort = $ldapServer[0] === 'ldaps' ? 636 : 389; + $ldapConnection = $this->ldap->connect($hostName, count($ldapServer) > 2 ? intval($ldapServer[2]) : $defaultPort); if ($ldapConnection === false) { throw new LdapException(trans('errors.ldap_cannot_connect')); diff --git a/app/Services/PermissionService.php b/app/Services/PermissionService.php index 467bf95da..72a810b6b 100644 --- a/app/Services/PermissionService.php +++ b/app/Services/PermissionService.php @@ -157,7 +157,7 @@ class PermissionService */ public function buildJointPermissionsForEntity(Entity $entity) { - $roles = $this->role->with('jointPermissions')->get(); + $roles = $this->role->get(); $entities = collect([$entity]); if ($entity->isA('book')) { @@ -177,7 +177,7 @@ class PermissionService */ public function buildJointPermissionsForEntities(Collection $entities) { - $roles = $this->role->with('jointPermissions')->get(); + $roles = $this->role->get(); $this->deleteManyJointPermissionsForEntities($entities); $this->createManyJointPermissions($entities, $roles); } @@ -243,13 +243,14 @@ class PermissionService */ protected function deleteManyJointPermissionsForEntities($entities) { + if (count($entities) === 0) return; $query = $this->jointPermission->newQuery(); - foreach ($entities as $entity) { - $query->orWhere(function($query) use ($entity) { - $query->where('entity_id', '=', $entity->id) - ->where('entity_type', '=', $entity->getMorphClass()); - }); - } + foreach ($entities as $entity) { + $query->orWhere(function($query) use ($entity) { + $query->where('entity_id', '=', $entity->id) + ->where('entity_type', '=', $entity->getMorphClass()); + }); + } $query->delete(); } @@ -405,7 +406,7 @@ class PermissionService $action = end($explodedPermission); $this->currentAction = $action; - $nonJointPermissions = ['restrictions']; + $nonJointPermissions = ['restrictions', 'image', 'attachment']; // Handle non entity specific jointPermissions if (in_array($explodedPermission[0], $nonJointPermissions)) { @@ -421,7 +422,6 @@ class PermissionService $this->currentAction = $permission; } - $q = $this->entityRestrictionQuery($baseQuery)->count() > 0; $this->clean(); return $q; @@ -471,49 +471,40 @@ class PermissionService return $q; } + /** + * Get the children of a book in an efficient single query, Filtered by the permission system. + * @param integer $book_id + * @param bool $filterDrafts + * @return \Illuminate\Database\Query\Builder + */ public function bookChildrenQuery($book_id, $filterDrafts = false) { + $pageSelect = $this->db->table('pages')->selectRaw("'BookStack\\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft")->where('book_id', '=', $book_id)->where(function($query) use ($filterDrafts) { + $query->where('draft', '=', 0); + if (!$filterDrafts) { + $query->orWhere(function($query) { + $query->where('draft', '=', 1)->where('created_by', '=', $this->currentUser()->id); + }); + } + }); + $chapterSelect = $this->db->table('chapters')->selectRaw("'BookStack\\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft")->where('book_id', '=', $book_id); + $query = $this->db->query()->select('*')->from($this->db->raw("({$pageSelect->toSql()} UNION {$chapterSelect->toSql()}) AS U")) + ->mergeBindings($pageSelect)->mergeBindings($chapterSelect); - // Draft setup - $params = [ - 'userId' => $this->currentUser()->id, - 'bookIdPage' => $book_id, - 'bookIdChapter' => $book_id - ]; - if (!$filterDrafts) { - $params['userIdDrafts'] = $this->currentUser()->id; + if (!$this->isAdmin()) { + $whereQuery = $this->db->table('joint_permissions as jp')->selectRaw('COUNT(*)') + ->whereRaw('jp.entity_id=U.id')->whereRaw('jp.entity_type=U.entity_type') + ->where('jp.action', '=', 'view')->whereIn('jp.role_id', $this->getRoles()) + ->where(function($query) { + $query->where('jp.has_permission', '=', 1)->orWhere(function($query) { + $query->where('jp.has_permission_own', '=', 1)->where('jp.created_by', '=', $this->currentUser()->id); + }); + }); + $query->whereRaw("({$whereQuery->toSql()}) > 0")->mergeBindings($whereQuery); } - // Role setup - $userRoles = $this->getRoles(); - $roleBindings = []; - $roleValues = []; - foreach ($userRoles as $index => $roleId) { - $roleBindings[':role'.$index] = $roleId; - $roleValues['role'.$index] = $roleId; - } - // TODO - Clean this up, Maybe extract into a nice class for doing these kind of manual things - // Something which will handle the above role crap in a nice clean way - $roleBindingString = implode(',', array_keys($roleBindings)); - $query = "SELECT * from ( -(SELECT 'Bookstack\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft FROM {$this->page->getTable()} - where book_id = :bookIdPage AND ". ($filterDrafts ? '(draft = 0)' : '(draft = 0 OR (draft = 1 AND created_by = :userIdDrafts))') .") -UNION -(SELECT 'Bookstack\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft FROM {$this->chapter->getTable()} WHERE book_id = :bookIdChapter) -) as U WHERE ( - SELECT COUNT(*) FROM {$this->jointPermission->getTable()} jp - WHERE - jp.entity_id=U.id AND - jp.entity_type=U.entity_type AND - jp.action = 'view' AND - jp.role_id IN ({$roleBindingString}) AND - ( - jp.has_permission = 1 OR - (jp.has_permission_own = 1 AND jp.created_by = :userId) - ) -) > 0 -ORDER BY draft desc, priority asc"; + $query->orderBy('draft', 'desc')->orderBy('priority', 'asc'); $this->clean(); - return $this->db->select($query, array_replace($roleValues, $params)); + return $query; } /** @@ -579,6 +570,7 @@ ORDER BY draft desc, priority asc"; }); }); }); + $this->clean(); return $q; } diff --git a/app/Services/SettingService.php b/app/Services/SettingService.php index bf5fa918e..40094a513 100644 --- a/app/Services/SettingService.php +++ b/app/Services/SettingService.php @@ -1,6 +1,7 @@ getValueFromStore($key, $default); return $this->formatValue($value, $default); } + /** + * Get a user-specific setting from the database or cache. + * @param User $user + * @param $key + * @param bool $default + * @return bool|string + */ + public function getUser($user, $key, $default = false) + { + return $this->get($this->userKey($user->id, $key), $default); + } + /** * Gets a setting value from the cache or database. * Looks at the system defaults if not cached or in database. @@ -69,14 +83,6 @@ class SettingService return $value; } - // Check the defaults set in the app config. - $configPrefix = 'setting-defaults.' . $key; - if (config()->has($configPrefix)) { - $value = config($configPrefix); - $this->cache->forever($cacheKey, $value); - return $value; - } - return $default; } @@ -118,6 +124,16 @@ class SettingService return $setting !== null; } + /** + * Check if a user setting is in the database. + * @param $key + * @return bool + */ + public function hasUser($key) + { + return $this->has($this->userKey($key)); + } + /** * Add a setting to the database. * @param $key @@ -135,6 +151,28 @@ class SettingService return true; } + /** + * Put a user-specific setting into the database. + * @param User $user + * @param $key + * @param $value + * @return bool + */ + public function putUser($user, $key, $value) + { + return $this->put($this->userKey($user->id, $key), $value); + } + + /** + * Convert a setting key into a user-specific key. + * @param $key + * @return string + */ + protected function userKey($userId, $key = '') + { + return 'user:' . $userId . ':' . $key; + } + /** * Removes a setting from the database. * @param $key @@ -150,6 +188,16 @@ class SettingService return true; } + /** + * Delete settings for a given user id. + * @param $userId + * @return mixed + */ + public function deleteUserSettings($userId) + { + return $this->setting->where('setting_key', 'like', $this->userKey($userId) . '%')->delete(); + } + /** * Gets a setting model from the database for the given key. * @param $key diff --git a/app/User.php b/app/User.php index b5bb221e8..afcd9af70 100644 --- a/app/User.php +++ b/app/User.php @@ -160,8 +160,16 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon */ public function getAvatar($size = 50) { - if ($this->image_id === 0 || $this->image_id === '0' || $this->image_id === null) return baseUrl('/user_avatar.png'); - return baseUrl($this->avatar->getThumb($size, $size, false)); + $default = baseUrl('/user_avatar.png'); + $imageId = $this->image_id; + if ($imageId === 0 || $imageId === '0' || $imageId === null) return $default; + + try { + $avatar = baseUrl($this->avatar->getThumb($size, $size, false)); + } catch (\Exception $err) { + $avatar = $default; + } + return $avatar; } /** diff --git a/app/helpers.php b/app/helpers.php index b5be0fd11..6decb08e9 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -60,11 +60,12 @@ function userCan($permission, Ownable $ownable = null) * Helper to access system settings. * @param $key * @param bool $default - * @return mixed + * @return bool|string|\BookStack\Services\SettingService */ -function setting($key, $default = false) +function setting($key = null, $default = false) { $settingService = app(\BookStack\Services\SettingService::class); + if (is_null($key)) return $settingService; return $settingService->get($key, $default); } diff --git a/composer.json b/composer.json index 5a8fd67ae..c0543a4ca 100644 --- a/composer.json +++ b/composer.json @@ -6,17 +6,18 @@ "type": "project", "require": { "php": ">=5.6.4", - "laravel/framework": "^5.3.4", + "laravel/framework": "5.4.*", "ext-tidy": "*", "intervention/image": "^2.3", - "laravel/socialite": "^2.0", - "barryvdh/laravel-ide-helper": "^2.1", - "barryvdh/laravel-debugbar": "^2.2.3", + "laravel/socialite": "^3.0", + "barryvdh/laravel-ide-helper": "^2.2.3", + "barryvdh/laravel-debugbar": "^2.3.2", "league/flysystem-aws-s3-v3": "^1.0", "barryvdh/laravel-dompdf": "^0.7", "predis/predis": "^1.1", "gathercontent/htmldiff": "^0.2.1", - "barryvdh/laravel-snappy": "^0.3.1" + "barryvdh/laravel-snappy": "^0.3.1", + "laravel/browser-kit-testing": "^1.0" }, "require-dev": { "fzaninotto/faker": "~1.4", @@ -35,7 +36,8 @@ }, "autoload-dev": { "classmap": [ - "tests/TestCase.php" + "tests/TestCase.php", + "tests/BrowserKitTest.php" ] }, "scripts": { diff --git a/composer.lock b/composer.lock index dcde9d9c6..e06993611 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "2438a2f4a02adbea5f378f9e9408eb29", - "content-hash": "6add8bff71ecc86e0c90858590834a26", + "hash": "c0bb098e9430247688c61ebd66d3d51c", + "content-hash": "3bb8bb2f252327c32aa40c686d1327cc", "packages": [ { "name": "aws/aws-sdk-php", - "version": "3.19.11", + "version": "3.21.4", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "19bac3bdd7988cbf7f89d5ce8e2748d774e2cde8" + "reference": "6408a4904a04eca44461a65ba4a0fae53f80417b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/19bac3bdd7988cbf7f89d5ce8e2748d774e2cde8", - "reference": "19bac3bdd7988cbf7f89d5ce8e2748d774e2cde8", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6408a4904a04eca44461a65ba4a0fae53f80417b", + "reference": "6408a4904a04eca44461a65ba4a0fae53f80417b", "shasum": "" }, "require": { @@ -85,24 +85,24 @@ "s3", "sdk" ], - "time": "2016-09-27 19:38:36" + "time": "2017-01-25 00:43:08" }, { "name": "barryvdh/laravel-debugbar", - "version": "v2.3.0", + "version": "v2.3.2", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "0c87981df959c7c1943abe227baf607c92f204f9" + "reference": "24e4f0261e352d3fd86d0447791b56ae49398674" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/0c87981df959c7c1943abe227baf607c92f204f9", - "reference": "0c87981df959c7c1943abe227baf607c92f204f9", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/24e4f0261e352d3fd86d0447791b56ae49398674", + "reference": "24e4f0261e352d3fd86d0447791b56ae49398674", "shasum": "" }, "require": { - "illuminate/support": "5.1.*|5.2.*|5.3.*", + "illuminate/support": "5.1.*|5.2.*|5.3.*|5.4.*", "maximebf/debugbar": "~1.13.0", "php": ">=5.5.9", "symfony/finder": "~2.7|~3.0" @@ -139,25 +139,25 @@ "profiler", "webprofiler" ], - "time": "2016-09-15 14:05:56" + "time": "2017-01-19 08:19:49" }, { "name": "barryvdh/laravel-dompdf", - "version": "v0.7.0", + "version": "v0.7.1", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "9b8bd179262ad6b200a11edfe7b53516afcfc42a" + "reference": "6cb20d3f397d739163d2d743a4600009e52cd453" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/9b8bd179262ad6b200a11edfe7b53516afcfc42a", - "reference": "9b8bd179262ad6b200a11edfe7b53516afcfc42a", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/6cb20d3f397d739163d2d743a4600009e52cd453", + "reference": "6cb20d3f397d739163d2d743a4600009e52cd453", "shasum": "" }, "require": { "dompdf/dompdf": "^0.7", - "illuminate/support": "5.1.x|5.2.x|5.3.x", + "illuminate/support": "5.1.x|5.2.x|5.3.x|5.4.x", "php": ">=5.5.9" }, "type": "library", @@ -187,27 +187,27 @@ "laravel", "pdf" ], - "time": "2016-08-17 08:17:33" + "time": "2017-01-24 18:12:54" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.2.1", + "version": "v2.2.3", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "28af7cd19ca41cc0c63dd1de2b46c2b84d31c463" + "reference": "a7fc2ec489aada6062d3a63ddc915004a21e38af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/28af7cd19ca41cc0c63dd1de2b46c2b84d31c463", - "reference": "28af7cd19ca41cc0c63dd1de2b46c2b84d31c463", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/a7fc2ec489aada6062d3a63ddc915004a21e38af", + "reference": "a7fc2ec489aada6062d3a63ddc915004a21e38af", "shasum": "" }, "require": { "barryvdh/reflection-docblock": "^2.0.4", - "illuminate/console": "^5.0,<5.4", - "illuminate/filesystem": "^5.0,<5.4", - "illuminate/support": "^5.0,<5.4", + "illuminate/console": "^5.0,<5.5", + "illuminate/filesystem": "^5.0,<5.5", + "illuminate/support": "^5.0,<5.5", "php": ">=5.4.0", "symfony/class-loader": "^2.3|^3.0" }, @@ -253,25 +253,25 @@ "phpstorm", "sublime" ], - "time": "2016-07-04 11:52:48" + "time": "2017-01-05 21:20:42" }, { "name": "barryvdh/laravel-snappy", - "version": "v0.3.1", + "version": "v0.3.2", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-snappy.git", - "reference": "509a4497be63d8ee7ff464a3daf00d9edde08e21" + "reference": "864470e81952f8e568c93754d9d0d2c05145f773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/509a4497be63d8ee7ff464a3daf00d9edde08e21", - "reference": "509a4497be63d8ee7ff464a3daf00d9edde08e21", + "url": "https://api.github.com/repos/barryvdh/laravel-snappy/zipball/864470e81952f8e568c93754d9d0d2c05145f773", + "reference": "864470e81952f8e568c93754d9d0d2c05145f773", "shasum": "" }, "require": { - "illuminate/filesystem": "5.0.x|5.1.x|5.2.x|5.3.x", - "illuminate/support": "5.0.x|5.1.x|5.2.x|5.3.x", + "illuminate/filesystem": "5.0.x|5.1.x|5.2.x|5.3.x|5.4.x", + "illuminate/support": "5.0.x|5.1.x|5.2.x|5.3.x|5.4.x", "knplabs/knp-snappy": "*", "php": ">=5.4.0" }, @@ -305,7 +305,7 @@ "wkhtmltoimage", "wkhtmltopdf" ], - "time": "2016-08-05 13:08:28" + "time": "2017-01-20 06:21:34" }, { "name": "barryvdh/reflection-docblock", @@ -356,60 +356,6 @@ ], "time": "2016-06-13 19:28:20" }, - { - "name": "classpreloader/classpreloader", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/ClassPreloader/ClassPreloader.git", - "reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/9b10b913c2bdf90c3d2e0d726b454fb7f77c552a", - "reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^1.0|^2.0", - "php": ">=5.5.9" - }, - "require-dev": { - "phpunit/phpunit": "^4.8|^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-4": { - "ClassPreloader\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com" - } - ], - "description": "Helps class loading performance by generating a single PHP file containing all of the autoloaded files for a specific use case", - "keywords": [ - "autoload", - "class", - "preload" - ], - "time": "2015-11-09 22:51:51" - }, { "name": "cogpowered/finediff", "version": "0.3.1", @@ -461,39 +407,6 @@ ], "time": "2014-05-19 10:25:02" }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "0.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/265b8593498b997dc2d31e75b89f053b5cc9621a", - "reference": "265b8593498b997dc2d31e75b89f053b5cc9621a", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "@stable" - }, - "type": "project", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "time": "2014-10-24 07:27:01" - }, { "name": "doctrine/inflector", "version": "v1.1.0", @@ -622,6 +535,48 @@ "homepage": "https://github.com/dompdf/dompdf", "time": "2016-05-11 00:36:29" }, + { + "name": "erusev/parsedown", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/20ff8bbb57205368b4b42d094642a3e52dac85fb", + "reference": "20ff8bbb57205368b4b42d094642a3e52dac85fb", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ], + "time": "2016-11-02 15:56:58" + }, { "name": "gathercontent/htmldiff", "version": "0.2.1", @@ -673,16 +628,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.2.1", + "version": "6.2.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", - "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60", + "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60", "shasum": "" }, "require": { @@ -731,32 +686,32 @@ "rest", "web service" ], - "time": "2016-07-15 17:22:37" + "time": "2016-10-08 15:01:37" }, { "name": "guzzlehttp/promises", - "version": "1.2.0", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", - "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", "shasum": "" }, "require": { "php": ">=5.5.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -782,7 +737,7 @@ "keywords": [ "promise" ], - "time": "2016-05-18 16:56:05" + "time": "2016-12-20 10:07:11" }, { "name": "guzzlehttp/psr7", @@ -844,16 +799,16 @@ }, { "name": "intervention/image", - "version": "2.3.8", + "version": "2.3.9", "source": { "type": "git", "url": "https://github.com/Intervention/image.git", - "reference": "4064a980324f6c3bfa2bd981dfb247afa705ec3c" + "reference": "2bce9a59c43b868300b02a7d31a1e4aa67a200ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/4064a980324f6c3bfa2bd981dfb247afa705ec3c", - "reference": "4064a980324f6c3bfa2bd981dfb247afa705ec3c", + "url": "https://api.github.com/repos/Intervention/image/zipball/2bce9a59c43b868300b02a7d31a1e4aa67a200ae", + "reference": "2bce9a59c43b868300b02a7d31a1e4aa67a200ae", "shasum": "" }, "require": { @@ -902,152 +857,7 @@ "thumbnail", "watermark" ], - "time": "2016-09-01 17:04:03" - }, - { - "name": "jakub-onderka/php-console-color", - "version": "0.1", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", - "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", - "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "jakub-onderka/php-code-style": "1.0", - "jakub-onderka/php-parallel-lint": "0.*", - "jakub-onderka/php-var-dump-check": "0.*", - "phpunit/phpunit": "3.7.*", - "squizlabs/php_codesniffer": "1.*" - }, - "type": "library", - "autoload": { - "psr-0": { - "JakubOnderka\\PhpConsoleColor": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "jakub.onderka@gmail.com", - "homepage": "http://www.acci.cz" - } - ], - "time": "2014-04-08 15:00:19" - }, - { - "name": "jakub-onderka/php-console-highlighter", - "version": "v0.3.2", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", - "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", - "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", - "shasum": "" - }, - "require": { - "jakub-onderka/php-console-color": "~0.1", - "php": ">=5.3.0" - }, - "require-dev": { - "jakub-onderka/php-code-style": "~1.0", - "jakub-onderka/php-parallel-lint": "~0.5", - "jakub-onderka/php-var-dump-check": "~0.1", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~1.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JakubOnderka\\PhpConsoleHighlighter": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "acci@acci.cz", - "homepage": "http://www.acci.cz/" - } - ], - "time": "2015-04-20 18:58:01" - }, - { - "name": "jeremeamia/SuperClosure", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/jeremeamia/super_closure.git", - "reference": "29a88be2a4846d27c1613aed0c9071dfad7b5938" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jeremeamia/super_closure/zipball/29a88be2a4846d27c1613aed0c9071dfad7b5938", - "reference": "29a88be2a4846d27c1613aed0c9071dfad7b5938", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^1.2|^2.0", - "php": ">=5.4", - "symfony/polyfill-php56": "^1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0|^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2-dev" - } - }, - "autoload": { - "psr-4": { - "SuperClosure\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia", - "role": "Developer" - } - ], - "description": "Serialize Closure objects, including their context and binding", - "homepage": "https://github.com/jeremeamia/super_closure", - "keywords": [ - "closure", - "function", - "lambda", - "parser", - "serializable", - "serialize", - "tokenizer" - ], - "time": "2015-12-05 17:17:57" + "time": "2017-01-10 14:15:56" }, { "name": "knplabs/knp-snappy", @@ -1115,43 +925,88 @@ "time": "2015-11-17 13:16:27" }, { - "name": "laravel/framework", - "version": "v5.3.11", + "name": "laravel/browser-kit-testing", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/laravel/framework.git", - "reference": "ca48001b95a0543fb39fcd7219de960bbc03eaa5" + "url": "https://github.com/laravel/browser-kit-testing.git", + "reference": "60e038e3dcfef2977347f9610c14b48721802278" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/ca48001b95a0543fb39fcd7219de960bbc03eaa5", - "reference": "ca48001b95a0543fb39fcd7219de960bbc03eaa5", + "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/60e038e3dcfef2977347f9610c14b48721802278", + "reference": "60e038e3dcfef2977347f9610c14b48721802278", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/css-selector": "3.1.*", + "symfony/dom-crawler": "3.1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\BrowserKitTesting\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Provides backwards compatibility for BrowserKit testing in Laravel 5.4.", + "keywords": [ + "laravel", + "testing" + ], + "time": "2017-01-25 13:07:25" + }, + { + "name": "laravel/framework", + "version": "v5.4.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "9fa94bf77272ea7f920292c6f016b0f6e0853f98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/9fa94bf77272ea7f920292c6f016b0f6e0853f98", + "reference": "9fa94bf77272ea7f920292c6f016b0f6e0853f98", "shasum": "" }, "require": { - "classpreloader/classpreloader": "~3.0", "doctrine/inflector": "~1.0", + "erusev/parsedown": "~1.6", "ext-mbstring": "*", "ext-openssl": "*", - "jeremeamia/superclosure": "~2.2", "league/flysystem": "~1.0", "monolog/monolog": "~1.11", "mtdowling/cron-expression": "~1.0", "nesbot/carbon": "~1.20", "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": "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.*", + "swiftmailer/swiftmailer": "~5.4", + "symfony/console": "~3.2", + "symfony/debug": "~3.2", + "symfony/finder": "~3.2", + "symfony/http-foundation": "~3.2", + "symfony/http-kernel": "~3.2", + "symfony/process": "~3.2", + "symfony/routing": "~3.2", + "symfony/var-dumper": "~3.2", + "tijsverkoyen/css-to-inline-styles": "~2.2", "vlucas/phpdotenv": "~2.2" }, "replace": { @@ -1188,31 +1043,34 @@ }, "require-dev": { "aws/aws-sdk-php": "~3.0", + "doctrine/dbal": "~2.5", "mockery/mockery": "~0.9.4", "pda/pheanstalk": "~3.0", - "phpunit/phpunit": "~5.4", + "phpunit/phpunit": "~5.7", "predis/predis": "~1.0", - "symfony/css-selector": "3.1.*", - "symfony/dom-crawler": "3.1.*" + "symfony/css-selector": "~3.2", + "symfony/dom-crawler": "~3.2" }, "suggest": { "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.5).", "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", - "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (~5.3|~6.0).", + "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (~6.0).", + "laravel/tinker": "Required to use the tinker console command (~1.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", + "nexmo/client": "Required to use the Nexmo transport (~1.0).", "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 (3.1.*).", - "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (3.1.*).", + "symfony/css-selector": "Required to use some of the crawler integration testing tools (~3.2).", + "symfony/dom-crawler": "Required to use most of the crawler integration testing tools (~3.2).", "symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.3-dev" + "dev-master": "5.4-dev" } }, "autoload": { @@ -1240,27 +1098,27 @@ "framework", "laravel" ], - "time": "2016-09-28 02:15:37" + "time": "2017-01-25 16:40:49" }, { "name": "laravel/socialite", - "version": "v2.0.18", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "76ee5397fcdea5a062361392abca4eb397e519a3" + "reference": "d3aaffa5e122395e54eb2c26062fde3a848c40fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/76ee5397fcdea5a062361392abca4eb397e519a3", - "reference": "76ee5397fcdea5a062361392abca4eb397e519a3", + "url": "https://api.github.com/repos/laravel/socialite/zipball/d3aaffa5e122395e54eb2c26062fde3a848c40fd", + "reference": "d3aaffa5e122395e54eb2c26062fde3a848c40fd", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "~5.0|~6.0", - "illuminate/contracts": "~5.0", - "illuminate/http": "~5.0", - "illuminate/support": "~5.0", + "guzzlehttp/guzzle": "~6.0", + "illuminate/contracts": "~5.4", + "illuminate/http": "~5.4", + "illuminate/support": "~5.4", "league/oauth1-client": "~1.0", "php": ">=5.4.0" }, @@ -1294,24 +1152,24 @@ "laravel", "oauth" ], - "time": "2016-06-22 12:40:16" + "time": "2017-01-25 17:58:13" }, { "name": "league/flysystem", - "version": "1.0.27", + "version": "1.0.33", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9" + "reference": "5c7f98498b12d47f9de90ec9186a90000125777c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/50e2045ed70a7e75a5e30bc3662904f3b67af8a9", - "reference": "50e2045ed70a7e75a5e30bc3662904f3b67af8a9", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5c7f98498b12d47f9de90ec9186a90000125777c", + "reference": "5c7f98498b12d47f9de90ec9186a90000125777c", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": ">=5.5.9" }, "conflict": { "league/flysystem-sftp": "<1.0.6" @@ -1377,7 +1235,7 @@ "sftp", "storage" ], - "time": "2016-08-10 08:55:11" + "time": "2017-01-23 10:32:09" }, { "name": "league/flysystem-aws-s3-v3", @@ -1491,16 +1349,16 @@ }, { "name": "maximebf/debugbar", - "version": "v1.13.0", + "version": "1.13.1", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "5f49a5ed6cfde81d31d89378806670d77462526e" + "reference": "afee79a236348e39a44cb837106b7c5b4897ac2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/5f49a5ed6cfde81d31d89378806670d77462526e", - "reference": "5f49a5ed6cfde81d31d89378806670d77462526e", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/afee79a236348e39a44cb837106b7c5b4897ac2a", + "reference": "afee79a236348e39a44cb837106b7c5b4897ac2a", "shasum": "" }, "require": { @@ -1548,20 +1406,20 @@ "debug", "debugbar" ], - "time": "2016-09-15 14:01:59" + "time": "2017-01-05 08:46:19" }, { "name": "monolog/monolog", - "version": "1.21.0", + "version": "1.22.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952" + "reference": "bad29cb8d18ab0315e6c477751418a82c850d558" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952", - "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558", + "reference": "bad29cb8d18ab0315e6c477751418a82c850d558", "shasum": "" }, "require": { @@ -1572,7 +1430,7 @@ "psr/log-implementation": "1.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^2.4.9", + "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", "jakub-onderka/php-parallel-lint": "0.9", @@ -1626,20 +1484,20 @@ "logging", "psr-3" ], - "time": "2016-07-29 03:23:52" + "time": "2016-11-26 00:15:39" }, { "name": "mtdowling/cron-expression", - "version": "v1.1.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/mtdowling/cron-expression.git", - "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5" + "reference": "9504fa9ea681b586028adaaa0877db4aecf32bad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/c9ee7886f5a12902b225a1a12f36bb45f9ab89e5", - "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5", + "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/9504fa9ea681b586028adaaa0877db4aecf32bad", + "reference": "9504fa9ea681b586028adaaa0877db4aecf32bad", "shasum": "" }, "require": { @@ -1650,8 +1508,8 @@ }, "type": "library", "autoload": { - "psr-0": { - "Cron": "src/" + "psr-4": { + "Cron\\": "src/Cron/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1670,20 +1528,20 @@ "cron", "schedule" ], - "time": "2016-01-26 21:23:30" + "time": "2017-01-23 04:29:33" }, { "name": "mtdowling/jmespath.php", - "version": "2.3.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "192f93e43c2c97acde7694993ab171b3de284093" + "reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/192f93e43c2c97acde7694993ab171b3de284093", - "reference": "192f93e43c2c97acde7694993ab171b3de284093", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/adcc9531682cf87dfda21e1fd5d0e7a41d292fac", + "reference": "adcc9531682cf87dfda21e1fd5d0e7a41d292fac", "shasum": "" }, "require": { @@ -1725,30 +1583,36 @@ "json", "jsonpath" ], - "time": "2016-01-05 18:25:05" + "time": "2016-12-03 22:08:25" }, { "name": "nesbot/carbon", - "version": "1.21.0", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7" + "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7b08ec6f75791e130012f206e3f7b0e76e18e3d7", - "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", + "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", "shasum": "" }, "require": { "php": ">=5.3.0", - "symfony/translation": "~2.6|~3.0" + "symfony/translation": "~2.6 || ~3.0" }, "require-dev": { - "phpunit/phpunit": "~4.0|~5.0" + "friendsofphp/php-cs-fixer": "~2", + "phpunit/phpunit": "~4.0 || ~5.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.23-dev" + } + }, "autoload": { "psr-4": { "Carbon\\": "src/Carbon/" @@ -1772,71 +1636,20 @@ "datetime", "time" ], - "time": "2015-11-04 20:07:17" - }, - { - "name": "nikic/php-parser", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4dd659edadffdc2143e4753df655d866dbfeedf0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4dd659edadffdc2143e4753df655d866dbfeedf0", - "reference": "4dd659edadffdc2143e4753df655d866dbfeedf0", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.4" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "time": "2016-09-16 12:04:44" + "time": "2017-01-16 07:55:07" }, { "name": "paragonie/random_compat", - "version": "v2.0.2", + "version": "v2.0.4", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf" + "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf", - "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", + "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", "shasum": "" }, "require": { @@ -1871,7 +1684,7 @@ "pseudorandom", "random" ], - "time": "2016-04-03 06:00:07" + "time": "2016-11-07 23:38:38" }, { "name": "phenx/php-font-lib", @@ -2043,16 +1856,16 @@ }, { "name": "psr/log", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "5277094ed527a1c4477177d102fe4c53551953e0" + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/5277094ed527a1c4477177d102fe4c53551953e0", - "reference": "5277094ed527a1c4477177d102fe4c53551953e0", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { @@ -2086,92 +1899,20 @@ "psr", "psr-3" ], - "time": "2016-09-19 16:02:08" - }, - { - "name": "psy/psysh", - "version": "v0.7.2", - "source": { - "type": "git", - "url": "https://github.com/bobthecow/psysh.git", - "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e64e10b20f8d229cac76399e1f3edddb57a0f280", - "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280", - "shasum": "" - }, - "require": { - "dnoegel/php-xdg-base-dir": "0.1", - "jakub-onderka/php-console-highlighter": "0.3.*", - "nikic/php-parser": "^1.2.1|~2.0", - "php": ">=5.3.9", - "symfony/console": "~2.3.10|^2.4.2|~3.0", - "symfony/var-dumper": "~2.7|~3.0" - }, - "require-dev": { - "fabpot/php-cs-fixer": "~1.5", - "phpunit/phpunit": "~3.7|~4.0|~5.0", - "squizlabs/php_codesniffer": "~2.0", - "symfony/finder": "~2.1|~3.0" - }, - "suggest": { - "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", - "ext-pdo-sqlite": "The doc command requires SQLite to work.", - "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", - "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." - }, - "bin": [ - "bin/psysh" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-develop": "0.8.x-dev" - } - }, - "autoload": { - "files": [ - "src/Psy/functions.php" - ], - "psr-4": { - "Psy\\": "src/Psy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" - } - ], - "description": "An interactive shell for modern PHP.", - "homepage": "http://psysh.org", - "keywords": [ - "REPL", - "console", - "interactive", - "shell" - ], - "time": "2016-03-09 05:03:14" + "time": "2016-10-10 12:19:37" }, { "name": "ramsey/uuid", - "version": "3.5.0", + "version": "3.5.2", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "a6d15c8618ea3951fd54d34e326b68d3d0bc0786" + "reference": "5677cfe02397dd6b58c861870dfaa5d9007d3954" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/a6d15c8618ea3951fd54d34e326b68d3d0bc0786", - "reference": "a6d15c8618ea3951fd54d34e326b68d3d0bc0786", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/5677cfe02397dd6b58c861870dfaa5d9007d3954", + "reference": "5677cfe02397dd6b58c861870dfaa5d9007d3954", "shasum": "" }, "require": { @@ -2184,11 +1925,13 @@ "require-dev": { "apigen/apigen": "^4.1", "codeception/aspect-mock": "1.0.0", + "doctrine/annotations": "~1.2.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", + "php-mock/php-mock-phpunit": "^0.3|^1.1", "phpunit/phpunit": "^4.7|>=5.0 <5.4", "satooshi/php-coveralls": "^0.6.1", "squizlabs/php_codesniffer": "^2.3" @@ -2238,27 +1981,28 @@ "identifier", "uuid" ], - "time": "2016-08-02 18:39:32" + "time": "2016-11-22 19:21:44" }, { "name": "swiftmailer/swiftmailer", - "version": "v5.4.3", + "version": "v5.4.5", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153" + "reference": "cd142238a339459b10da3d8234220963f392540c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/4cc92842069c2bbc1f28daaaf1d2576ec4dfe153", - "reference": "4cc92842069c2bbc1f28daaaf1d2576ec4dfe153", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/cd142238a339459b10da3d8234220963f392540c", + "reference": "cd142238a339459b10da3d8234220963f392540c", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "mockery/mockery": "~0.9.1" + "mockery/mockery": "~0.9.1", + "symfony/phpunit-bridge": "~3.2" }, "type": "library", "extra": { @@ -2291,20 +2035,20 @@ "mail", "mailer" ], - "time": "2016-07-08 11:51:25" + "time": "2016-12-29 10:02:40" }, { "name": "symfony/class-loader", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "2d0ba77c46ecc96a6641009a98f72632216811ba" + "reference": "0152f7a47acd564ca62c652975c2b32ac6d613a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/2d0ba77c46ecc96a6641009a98f72632216811ba", - "reference": "2d0ba77c46ecc96a6641009a98f72632216811ba", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/0152f7a47acd564ca62c652975c2b32ac6d613a6", + "reference": "0152f7a47acd564ca62c652975c2b32ac6d613a6", "shasum": "" }, "require": { @@ -2320,7 +2064,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2347,40 +2091,43 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2016-08-23 13:39:15" + "time": "2017-01-10 14:14:38" }, { "name": "symfony/console", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563" + "reference": "4f9e449e76996adf310498a8ca955c6deebe29dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/8ea494c34f0f772c3954b5fbe00bffc5a435e563", - "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563", + "url": "https://api.github.com/repos/symfony/console/zipball/4f9e449e76996adf310498a8ca955c6deebe29dd", + "reference": "4f9e449e76996adf310498a8ca955c6deebe29dd", "shasum": "" }, "require": { "php": ">=5.5.9", + "symfony/debug": "~2.8|~3.0", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { "psr/log": "~1.0", "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/filesystem": "~2.8|~3.0", "symfony/process": "~2.8|~3.0" }, "suggest": { "psr/log": "For using the console logger", "symfony/event-dispatcher": "", + "symfony/filesystem": "", "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2407,20 +2154,73 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2016-08-19 06:48:39" + "time": "2017-01-08 20:47:33" }, { - "name": "symfony/debug", - "version": "v3.1.4", + "name": "symfony/css-selector", + "version": "v3.1.9", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "34f6ac18c2974ca5fce68adf419ee7d15def6f11" + "url": "https://github.com/symfony/css-selector.git", + "reference": "722a87478a72d95dc2a3bcf41dc9c2d13fd4cb2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/34f6ac18c2974ca5fce68adf419ee7d15def6f11", - "reference": "34f6ac18c2974ca5fce68adf419ee7d15def6f11", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/722a87478a72d95dc2a3bcf41dc9c2d13fd4cb2d", + "reference": "722a87478a72d95dc2a3bcf41dc9c2d13fd4cb2d", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2017-01-02 20:31:54" + }, + { + "name": "symfony/debug", + "version": "v3.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "810ba5c1c5352a4ddb15d4719e8936751dff0b05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/810ba5c1c5352a4ddb15d4719e8936751dff0b05", + "reference": "810ba5c1c5352a4ddb15d4719e8936751dff0b05", "shasum": "" }, "require": { @@ -2437,7 +2237,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2464,20 +2264,76 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2016-08-23 13:39:15" + "time": "2017-01-02 20:32:22" }, { - "name": "symfony/event-dispatcher", - "version": "v3.1.4", + "name": "symfony/dom-crawler", + "version": "v3.1.9", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5" + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "a950260ebc947578fba82a3222e2085d90682376" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c0c00c80b3a69132c4e55c3e7db32b4a387615e5", - "reference": "c0c00c80b3a69132c4e55c3e7db32b4a387615e5", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/a950260ebc947578fba82a3222e2085d90682376", + "reference": "a950260ebc947578fba82a3222e2085d90682376", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2017-01-02 20:31:54" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "9137eb3a3328e413212826d63eeeb0217836e2b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9137eb3a3328e413212826d63eeeb0217836e2b6", + "reference": "9137eb3a3328e413212826d63eeeb0217836e2b6", "shasum": "" }, "require": { @@ -2497,7 +2353,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2524,20 +2380,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-07-19 10:45:57" + "time": "2017-01-02 20:32:22" }, { "name": "symfony/finder", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577" + "reference": "8c71141cae8e2957946b403cc71a67213c0380d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/e568ef1784f447a0e54dcb6f6de30b9747b0f577", - "reference": "e568ef1784f447a0e54dcb6f6de30b9747b0f577", + "url": "https://api.github.com/repos/symfony/finder/zipball/8c71141cae8e2957946b403cc71a67213c0380d6", + "reference": "8c71141cae8e2957946b403cc71a67213c0380d6", "shasum": "" }, "require": { @@ -2546,7 +2402,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2573,20 +2429,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2016-08-26 12:04:02" + "time": "2017-01-02 20:32:22" }, { "name": "symfony/http-foundation", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "63592e00fd90632b57ee50220a1ddb29b6bf3bb4" + "reference": "33eb76bf1d833c705433e5361a646c164696394b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/63592e00fd90632b57ee50220a1ddb29b6bf3bb4", - "reference": "63592e00fd90632b57ee50220a1ddb29b6bf3bb4", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/33eb76bf1d833c705433e5361a646c164696394b", + "reference": "33eb76bf1d833c705433e5361a646c164696394b", "shasum": "" }, "require": { @@ -2599,7 +2455,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2626,20 +2482,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2016-08-22 12:11:19" + "time": "2017-01-08 20:47:33" }, { "name": "symfony/http-kernel", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "aeda215d6b01f119508c090d2a09ebb5b0bc61f3" + "reference": "8a898e340a89022246645b1288d295f49c9381e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/aeda215d6b01f119508c090d2a09ebb5b0bc61f3", - "reference": "aeda215d6b01f119508c090d2a09ebb5b0bc61f3", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8a898e340a89022246645b1288d295f49c9381e4", + "reference": "8a898e340a89022246645b1288d295f49c9381e4", "shasum": "" }, "require": { @@ -2647,7 +2503,7 @@ "psr/log": "~1.0", "symfony/debug": "~2.8|~3.0", "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/http-foundation": "~2.8.8|~3.0.8|~3.1.2|~3.2" + "symfony/http-foundation": "~2.8.13|~3.1.6|~3.2" }, "conflict": { "symfony/config": "<2.8" @@ -2667,7 +2523,7 @@ "symfony/stopwatch": "~2.8|~3.0", "symfony/templating": "~2.8|~3.0", "symfony/translation": "~2.8|~3.0", - "symfony/var-dumper": "~2.8|~3.0" + "symfony/var-dumper": "~3.2" }, "suggest": { "symfony/browser-kit": "", @@ -2681,7 +2537,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2708,20 +2564,20 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-09-03 15:28:24" + "time": "2017-01-12 21:36:33" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.2.0", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "dff51f72b0706335131b00a7f49606168c582594" + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", - "reference": "dff51f72b0706335131b00a7f49606168c582594", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", "shasum": "" }, "require": { @@ -2733,7 +2589,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -2767,128 +2623,20 @@ "portable", "shim" ], - "time": "2016-05-18 14:26:46" - }, - { - "name": "symfony/polyfill-php56", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php56.git", - "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/3edf57a8fbf9a927533344cef65ad7e1cf31030a", - "reference": "3edf57a8fbf9a927533344cef65ad7e1cf31030a", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "symfony/polyfill-util": "~1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php56\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "time": "2016-05-18 14:26:46" - }, - { - "name": "symfony/polyfill-util", - "version": "v1.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-util.git", - "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/ef830ce3d218e622b221d6bfad42c751d974bf99", - "reference": "ef830ce3d218e622b221d6bfad42c751d974bf99", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Util\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony utilities for portability of PHP codes", - "homepage": "https://symfony.com", - "keywords": [ - "compat", - "compatibility", - "polyfill", - "shim" - ], - "time": "2016-05-18 14:26:46" + "time": "2016-11-14 01:06:16" }, { "name": "symfony/process", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e64e93041c80e77197ace5ab9385dedb5a143697" + "reference": "350e810019fc52dd06ae844b6a6d382f8a0e8893" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e64e93041c80e77197ace5ab9385dedb5a143697", - "reference": "e64e93041c80e77197ace5ab9385dedb5a143697", + "url": "https://api.github.com/repos/symfony/process/zipball/350e810019fc52dd06ae844b6a6d382f8a0e8893", + "reference": "350e810019fc52dd06ae844b6a6d382f8a0e8893", "shasum": "" }, "require": { @@ -2897,7 +2645,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2924,20 +2672,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2016-08-16 14:58:24" + "time": "2017-01-02 20:32:22" }, { "name": "symfony/routing", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "8edf62498a1a4c57ba317664a4b698339c10cdf6" + "reference": "fda2c67d47ec801726ca888c95d701d31b27b444" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/8edf62498a1a4c57ba317664a4b698339c10cdf6", - "reference": "8edf62498a1a4c57ba317664a4b698339c10cdf6", + "url": "https://api.github.com/repos/symfony/routing/zipball/fda2c67d47ec801726ca888c95d701d31b27b444", + "reference": "fda2c67d47ec801726ca888c95d701d31b27b444", "shasum": "" }, "require": { @@ -2966,7 +2714,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2999,20 +2747,20 @@ "uri", "url" ], - "time": "2016-08-16 14:58:24" + "time": "2017-01-02 20:32:22" }, { "name": "symfony/translation", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "a35edc277513c9bc0f063ca174c36b346f974528" + "reference": "6520f3d4cce604d9dd1e86cac7af954984dd9bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/a35edc277513c9bc0f063ca174c36b346f974528", - "reference": "a35edc277513c9bc0f063ca174c36b346f974528", + "url": "https://api.github.com/repos/symfony/translation/zipball/6520f3d4cce604d9dd1e86cac7af954984dd9bda", + "reference": "6520f3d4cce604d9dd1e86cac7af954984dd9bda", "shasum": "" }, "require": { @@ -3036,7 +2784,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3063,20 +2811,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2016-08-05 08:37:39" + "time": "2017-01-02 20:32:22" }, { "name": "symfony/var-dumper", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "62ee73706c421654a4c840028954510277f7dfc8" + "reference": "b54b23f9a19b465e76fdaac0f6732410467c83b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/62ee73706c421654a4c840028954510277f7dfc8", - "reference": "62ee73706c421654a4c840028954510277f7dfc8", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b54b23f9a19b465e76fdaac0f6732410467c83b2", + "reference": "b54b23f9a19b465e76fdaac0f6732410467c83b2", "shasum": "" }, "require": { @@ -3092,7 +2840,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3126,7 +2874,54 @@ "debug", "dump" ], - "time": "2016-08-31 09:05:42" + "time": "2017-01-03 08:53:57" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "ab03919dfd85a74ae0372f8baf9f3c7d5c03b04b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/ab03919dfd85a74ae0372f8baf9f3c7d5c03b04b", + "reference": "ab03919dfd85a74ae0372f8baf9f3c7d5c03b04b", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7", + "symfony/css-selector": "^2.7|~3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8|5.1.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "time": "2016-09-20 12:50:39" }, { "name": "vlucas/phpdotenv", @@ -3329,16 +3124,16 @@ }, { "name": "mockery/mockery", - "version": "0.9.5", + "version": "0.9.7", "source": { "type": "git", "url": "https://github.com/padraic/mockery.git", - "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2" + "reference": "4de7969f4664da3cef1ccd83866c9f59378c3371" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/4db079511a283e5aba1b3c2fb19037c645e70fc2", - "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2", + "url": "https://api.github.com/repos/padraic/mockery/zipball/4de7969f4664da3cef1ccd83866c9f59378c3371", + "reference": "4de7969f4664da3cef1ccd83866c9f59378c3371", "shasum": "" }, "require": { @@ -3390,20 +3185,20 @@ "test double", "testing" ], - "time": "2016-05-22 21:52:33" + "time": "2016-12-19 14:50:55" }, { "name": "myclabs/deep-copy", - "version": "1.5.4", + "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f" + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f", - "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", "shasum": "" }, "require": { @@ -3432,7 +3227,7 @@ "object", "object graph" ], - "time": "2016-09-16 13:37:59" + "time": "2016-10-31 17:19:45" }, { "name": "phpdocumentor/reflection-common", @@ -3490,16 +3285,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", - "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", "shasum": "" }, "require": { @@ -3531,20 +3326,20 @@ } ], "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" + "time": "2016-09-30 07:12:33" }, { "name": "phpdocumentor/type-resolver", - "version": "0.2", + "version": "0.2.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443" + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443", - "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", "shasum": "" }, "require": { @@ -3578,20 +3373,20 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-06-10 07:14:17" + "time": "2016-11-25 06:54:22" }, { "name": "phpspec/prophecy", - "version": "v1.6.1", + "version": "v1.6.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0" + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0", - "reference": "58a8137754bc24b25740d4281399a4a3596058e0", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", "shasum": "" }, "require": { @@ -3599,10 +3394,11 @@ "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0" + "sebastian/recursion-context": "^1.0|^2.0" }, "require-dev": { - "phpspec/phpspec": "^2.0" + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", "extra": { @@ -3640,20 +3436,20 @@ "spy", "stub" ], - "time": "2016-06-07 08:13:47" + "time": "2016-11-21 14:58:47" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.1", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3" + "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3", - "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", + "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", "shasum": "" }, "require": { @@ -3703,20 +3499,20 @@ "testing", "xunit" ], - "time": "2016-07-26 14:39:29" + "time": "2017-01-20 15:06:43" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { @@ -3750,7 +3546,7 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2016-10-03 07:40:28" }, { "name": "phpunit/php-text-template", @@ -3839,16 +3635,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.8", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { @@ -3884,20 +3680,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2016-11-15 14:06:22" }, { "name": "phpunit/phpunit", - "version": "5.5.5", + "version": "5.7.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a57126dc681b08289fef6ac96a48e30656f84350" + "reference": "caf8141b89691498d91aaac6c82e9cd5f685ae86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a57126dc681b08289fef6ac96a48e30656f84350", - "reference": "a57126dc681b08289fef6ac96a48e30656f84350", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/caf8141b89691498d91aaac6c82e9cd5f685ae86", + "reference": "caf8141b89691498d91aaac6c82e9cd5f685ae86", "shasum": "" }, "require": { @@ -3908,18 +3704,18 @@ "ext-xml": "*", "myclabs/deep-copy": "~1.3", "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "^4.0.1", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "~1.1", + "sebastian/comparator": "~1.2.2", "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3 || ^2.0", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/object-enumerator": "~1.0", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.0 || ^2.0", + "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", "sebastian/version": "~1.0|~2.0", "symfony/yaml": "~2.1|~3.0" @@ -3931,7 +3727,6 @@ "ext-pdo": "*" }, "suggest": { - "ext-tidy": "*", "ext-xdebug": "*", "phpunit/php-invoker": "~1.1" }, @@ -3941,7 +3736,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.5.x-dev" + "dev-master": "5.7.x-dev" } }, "autoload": { @@ -3967,27 +3762,27 @@ "testing", "xunit" ], - "time": "2016-09-21 14:40:13" + "time": "2017-01-22 08:39:59" }, { "name": "phpunit/phpunit-mock-objects", - "version": "3.2.7", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a" + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/546898a2c0c356ef2891b39dd7d07f5d82c8ed0a", - "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.6 || ^7.0", "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2" + "sebastian/exporter": "^1.2 || ^2.0" }, "conflict": { "phpunit/phpunit": "<5.4.0" @@ -4026,7 +3821,7 @@ "mock", "xunit" ], - "time": "2016-09-06 16:07:45" + "time": "2016-12-08 20:27:08" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -4075,22 +3870,22 @@ }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" @@ -4135,7 +3930,7 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2016-11-19 09:18:40" }, { "name": "sebastian/diff", @@ -4191,28 +3986,28 @@ }, { "name": "sebastian/environment", - "version": "1.3.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpunit/phpunit": "^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4237,25 +4032,25 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-11-26 07:53:53" }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", "shasum": "" }, "require": { "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "ext-mbstring": "*", @@ -4264,7 +4059,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4304,7 +4099,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-11-19 08:54:04" }, { "name": "sebastian/global-state", @@ -4359,21 +4154,21 @@ }, { "name": "sebastian/object-enumerator", - "version": "1.0.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", - "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", "shasum": "" }, "require": { "php": ">=5.6", - "sebastian/recursion-context": "~1.0" + "sebastian/recursion-context": "~2.0" }, "require-dev": { "phpunit/phpunit": "~5" @@ -4381,7 +4176,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4401,20 +4196,20 @@ ], "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" + "time": "2016-11-19 07:35:10" }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", "shasum": "" }, "require": { @@ -4426,7 +4221,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4454,7 +4249,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2016-11-19 07:33:16" }, { "name": "sebastian/resource-operations", @@ -4500,16 +4295,16 @@ }, { "name": "sebastian/version", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", - "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { @@ -4539,138 +4334,35 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-02-04 12:56:52" - }, - { - "name": "symfony/css-selector", - "version": "v3.1.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "2851e1932d77ce727776154d659b232d061e816a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/2851e1932d77ce727776154d659b232d061e816a", - "reference": "2851e1932d77ce727776154d659b232d061e816a", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\CssSelector\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony CssSelector Component", - "homepage": "https://symfony.com", - "time": "2016-06-29 05:41:56" - }, - { - "name": "symfony/dom-crawler", - "version": "v3.1.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "bb7395e8b1db3654de82b9f35d019958276de4d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/bb7395e8b1db3654de82b9f35d019958276de4d7", - "reference": "bb7395e8b1db3654de82b9f35d019958276de4d7", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "symfony/css-selector": "~2.8|~3.0" - }, - "suggest": { - "symfony/css-selector": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DomCrawler Component", - "homepage": "https://symfony.com", - "time": "2016-08-05 08:37:39" + "time": "2016-10-03 07:35:21" }, { "name": "symfony/yaml", - "version": "v3.1.4", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d" + "reference": "50eadbd7926e31842893c957eca362b21592a97d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/f291ed25eb1435bddbe8a96caaef16469c2a092d", - "reference": "f291ed25eb1435bddbe8a96caaef16469c2a092d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/50eadbd7926e31842893c957eca362b21592a97d", + "reference": "50eadbd7926e31842893c957eca362b21592a97d", "shasum": "" }, "require": { "php": ">=5.5.9" }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -4697,24 +4389,24 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-09-02 02:12:52" + "time": "2017-01-03 13:51:32" }, { "name": "webmozart/assert", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308" + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308", - "reference": "bb2d123231c095735130cc8f6d31385a44c7b308", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", "shasum": "" }, "require": { - "php": "^5.3.3|^7.0" + "php": "^5.3.3 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^4.6", @@ -4723,7 +4415,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -4747,7 +4439,7 @@ "check", "validate" ], - "time": "2016-08-09 15:02:57" + "time": "2016-11-23 20:04:58" } ], "aliases": [], diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index 3820d5b59..43e214386 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -59,4 +59,14 @@ $factory->define(BookStack\Tag::class, function ($faker) { 'name' => $faker->city, 'value' => $faker->sentence(3) ]; +}); + +$factory->define(BookStack\Image::class, function ($faker) { + return [ + 'name' => $faker->slug . '.jpg', + 'url' => $faker->url, + 'path' => $faker->url, + 'type' => 'gallery', + 'uploaded_to' => 0 + ]; }); \ No newline at end of file diff --git a/database/migrations/2017_01_21_163556_create_cache_table.php b/database/migrations/2017_01_21_163556_create_cache_table.php new file mode 100644 index 000000000..1f7761c2b --- /dev/null +++ b/database/migrations/2017_01_21_163556_create_cache_table.php @@ -0,0 +1,32 @@ +string('key')->unique(); + $table->text('value'); + $table->integer('expiration'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('cache'); + } +} diff --git a/database/migrations/2017_01_21_163602_create_sessions_table.php b/database/migrations/2017_01_21_163602_create_sessions_table.php new file mode 100644 index 000000000..56e76d6df --- /dev/null +++ b/database/migrations/2017_01_21_163602_create_sessions_table.php @@ -0,0 +1,35 @@ +string('id')->unique(); + $table->integer('user_id')->nullable(); + $table->string('ip_address', 45)->nullable(); + $table->text('user_agent')->nullable(); + $table->text('payload'); + $table->integer('last_activity'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('sessions'); + } +} diff --git a/package.json b/package.json index ec5911b93..b0805c918 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "laravel-elixir": "^6.0.0-11", "laravel-elixir-browserify-official": "^0.1.3", "marked": "^0.3.5", - "moment": "^2.12.0", - "zeroclipboard": "^2.2.0" + "moment": "^2.12.0" + }, + "dependencies": { + "clipboard": "^1.5.16" } } diff --git a/public/ZeroClipboard.swf b/public/ZeroClipboard.swf deleted file mode 100644 index 8bad6a3e3..000000000 Binary files a/public/ZeroClipboard.swf and /dev/null differ diff --git a/readme.md b/readme.md index fa5c48fe0..63d43e4b7 100644 --- a/readme.md +++ b/readme.md @@ -40,13 +40,19 @@ php artisan db:seed --class=DummyContentSeeder --database=mysql_testing Once done you can run `phpunit` in the application root directory to run all tests. -## Website and Docs +## Translations -The website and project docs are currently stored in the [BookStackApp/website](https://github.com/BookStackApp/website) repo. The docs are stored as markdown files in the `resources/docs` folder +As part of BookStack v0.14 support for translations has been built in. All text strings can be found in the `resources/lang` folder where each language option has its own folder. To add a new language you should copy the `en` folder to an new folder (eg. `fr` for french) then go through and translate all text strings in those files, leaving the keys and file-names intact. If a language string is missing then the `en` translation will be used. To show the language option in the user preferences language drop-down you will need to add your language to the options found at the bottom of the `resources/lang/en/settings.php` file. A system-wide language can also be set in the `.env` file like so: `APP_LANG=en`. + + Some strings have colon-prefixed variables in such as `:userName`. Leave these values as they are as they will be replaced at run-time. + +## Website, Docs & Blog + +The website project docs & Blog can be found in the [BookStackApp/website](https://github.com/BookStackApp/website) repo. ## License -BookStack is provided under the MIT License. +The BookStack source is provided under the MIT License. ## Attribution diff --git a/resources/assets/js/global.js b/resources/assets/js/global.js index 94462ed64..650919f85 100644 --- a/resources/assets/js/global.js +++ b/resources/assets/js/global.js @@ -61,10 +61,9 @@ Controllers(ngApp, window.Events); // Smooth scrolling jQuery.fn.smoothScrollTo = function () { if (this.length === 0) return; - let scrollElem = document.documentElement.scrollTop === 0 ? document.body : document.documentElement; - $(scrollElem).animate({ + $('html, body').animate({ scrollTop: this.offset().top - 60 // Adjust to change final scroll position top margin - }, 800); // Adjust to change animations speed (ms) + }, 300); // Adjust to change animations speed (ms) return this; }; diff --git a/resources/assets/js/pages/page-form.js b/resources/assets/js/pages/page-form.js index e1c0cfe8f..0f44b3d09 100644 --- a/resources/assets/js/pages/page-form.js +++ b/resources/assets/js/pages/page-form.js @@ -77,7 +77,7 @@ export default function() { extended_valid_elements: 'pre[*]', automatic_uploads: false, valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]", - plugins: "image table textcolor paste link fullscreen imagetools code customhr autosave lists", + plugins: "image table textcolor paste link autolink fullscreen imagetools code customhr autosave lists", imagetools_toolbar: 'imageoptions', 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;}", diff --git a/resources/assets/js/pages/page-show.js b/resources/assets/js/pages/page-show.js index 0cdde790d..0f45e1987 100644 --- a/resources/assets/js/pages/page-show.js +++ b/resources/assets/js/pages/page-show.js @@ -1,13 +1,16 @@ "use strict"; // Configure ZeroClipboard -import zeroClipBoard from "zeroclipboard"; +import Clipboard from "clipboard"; export default window.setupPageShow = function (pageId) { // Set up pointer let $pointer = $('#pointer').detach(); + let pointerShowing = false; let $pointerInner = $pointer.children('div.pointer').first(); let isSelection = false; + let pointerModeLink = true; + let pointerSectionId = ''; // Select all contents on input click $pointer.on('click', 'input', function (e) { @@ -15,19 +18,34 @@ export default window.setupPageShow = function (pageId) { e.stopPropagation(); }); - // Set up copy-to-clipboard - zeroClipBoard.config({ - swfPath: window.baseUrl('/ZeroClipboard.swf') + // Pointer mode toggle + $pointer.on('click', 'span.icon', event => { + let $icon = $(event.currentTarget); + pointerModeLink = !pointerModeLink; + $icon.html(pointerModeLink ? '' : ''); + updatePointerContent(); }); - new zeroClipBoard($pointer.find('button').first()[0]); + + // Set up clipboard + let clipboard = new Clipboard('#pointer button'); // Hide pointer when clicking away - $(document.body).find('*').on('click focus', function (e) { - if (!isSelection) { - $pointer.detach(); - } + $(document.body).find('*').on('click focus', event => { + if (!pointerShowing || isSelection) return; + let target = $(event.target); + if (target.is('.zmdi') || $(event.target).closest('#pointer').length === 1) return; + + $pointer.detach(); + pointerShowing = false; }); + function updatePointerContent() { + let inputText = pointerModeLink ? window.baseUrl(`/link/${pageId}#${pointerSectionId}`) : `{{@${pageId}#${pointerSectionId}}}`; + if (pointerModeLink && inputText.indexOf('http') !== 0) inputText = window.location.protocol + "//" + window.location.host + inputText; + + $pointer.find('input').val(inputText); + } + // Show pointer when selecting a single block of tagged content $('.page-content [id^="bkmrk"]').on('mouseup keyup', function (e) { e.stopPropagation(); @@ -36,12 +54,12 @@ export default window.setupPageShow = function (pageId) { // Show pointer and set link let $elem = $(this); - let link = window.baseUrl('/link/' + pageId + '#' + $elem.attr('id')); - if (link.indexOf('http') !== 0) link = window.location.protocol + "//" + window.location.host + link; - $pointer.find('input').val(link); - $pointer.find('button').first().attr('data-clipboard-text', link); + pointerSectionId = $elem.attr('id'); + updatePointerContent(); + $elem.before($pointer); $pointer.show(); + pointerShowing = true; // Set pointer to sit near mouse-up position let pointerLeftOffset = (e.pageX - $elem.offset().left - ($pointerInner.width() / 2)); @@ -57,10 +75,12 @@ export default window.setupPageShow = function (pageId) { // Go to, and highlight if necessary, the specified text. function goToText(text) { - let idElem = $('.page-content #' + text).first(); - if (idElem.length !== 0) { - idElem.smoothScrollTo(); - idElem.css('background-color', 'rgba(244, 249, 54, 0.25)'); + let idElem = document.getElementById(text); + $('.page-content [data-highlighted]').attr('data-highlighted', '').css('background-color', ''); + if (idElem !== null) { + let $idElem = $(idElem); + let color = $('#custom-styles').attr('data-color-light'); + $idElem.css('background-color', color).attr('data-highlighted', 'true').smoothScrollTo(); } else { $('.page-content').find(':contains("' + text + '")').smoothScrollTo(); } @@ -72,6 +92,11 @@ export default window.setupPageShow = function (pageId) { goToText(text); } + // Sidebar page nav click event + $('.sidebar-page-nav').on('click', 'a', event => { + goToText(event.target.getAttribute('href').substr(1)); + }); + // Make the book-tree sidebar stick in view on scroll let $window = $(window); let $bookTree = $(".book-tree"); diff --git a/resources/assets/sass/_blocks.scss b/resources/assets/sass/_blocks.scss index 7eb595d36..a2023aa37 100644 --- a/resources/assets/sass/_blocks.scss +++ b/resources/assets/sass/_blocks.scss @@ -136,9 +136,6 @@ background-color: #EEE; padding: $-s; display: block; - > * { - display: inline-block; - } &:before { font-family: 'Material-Design-Iconic-Font'; padding-right: $-s; diff --git a/resources/assets/sass/_buttons.scss b/resources/assets/sass/_buttons.scss index 5de889673..791a5bb72 100644 --- a/resources/assets/sass/_buttons.scss +++ b/resources/assets/sass/_buttons.scss @@ -108,5 +108,4 @@ $button-border-radius: 2px; cursor: default; box-shadow: none; } -} - +} \ No newline at end of file diff --git a/resources/assets/sass/_components.scss b/resources/assets/sass/_components.scss index c8fd8bcfa..5328057d9 100644 --- a/resources/assets/sass/_components.scss +++ b/resources/assets/sass/_components.scss @@ -70,9 +70,6 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { #entity-selector-wrap .popup-body .form-group { margin: 0; } -//body.ie #entity-selector-wrap .popup-body .form-group { -// min-height: 60vh; -//} .image-manager-body { min-height: 70vh; diff --git a/resources/assets/sass/_pages.scss b/resources/assets/sass/_pages.scss index 0052a3319..e5334c69c 100755 --- a/resources/assets/sass/_pages.scss +++ b/resources/assets/sass/_pages.scss @@ -138,6 +138,10 @@ font-size: 18px; padding-top: 4px; } + span.icon { + cursor: pointer; + user-select: none; + } .button { line-height: 1; margin: 0 0 0 -4px; diff --git a/resources/assets/sass/_text.scss b/resources/assets/sass/_text.scss index dd2f32e1c..74eb6875a 100644 --- a/resources/assets/sass/_text.scss +++ b/resources/assets/sass/_text.scss @@ -175,6 +175,7 @@ pre code { background-color: transparent; border: 0; font-size: 1em; + display: block; } /* * Text colors diff --git a/resources/assets/sass/export-styles.scss b/resources/assets/sass/export-styles.scss index 60450f3e2..7e1ab4e9e 100644 --- a/resources/assets/sass/export-styles.scss +++ b/resources/assets/sass/export-styles.scss @@ -1,4 +1,4 @@ -//@import "reset"; +@import "reset"; @import "variables"; @import "mixins"; @import "html"; diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 033d9614e..109b6ee2a 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -89,6 +89,7 @@ return [ * Chapters */ 'chapter' => 'Chapter', + 'chapters' => 'Chapters', 'chapters_popular' => 'Popular Chapters', 'chapters_new' => 'New Chapter', 'chapters_create' => 'Create New Chapter', diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index e61df19d9..ed8a0db43 100644 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -1,13 +1,13 @@ 'Settings', 'settings_save' => 'Save Settings', 'settings_save_success' => 'Settings saved', @@ -92,7 +92,7 @@ return [ 'users_password_warning' => 'Only fill the below if you would like to change your password:', 'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.', 'users_delete' => 'Delete User', - 'users_delete_named' => 'Delete ser :userName', + 'users_delete_named' => 'Delete user :userName', 'users_delete_warning' => 'This will fully delete this user with the name \':userName\' from the system.', 'users_delete_confirm' => 'Are you sure you want to delete this user?', 'users_delete_success' => 'Users successfully removed', @@ -101,40 +101,23 @@ return [ 'users_edit_success' => 'User successfully updated', 'users_avatar' => 'User Avatar', 'users_avatar_desc' => 'This image should be approx 256px square.', + 'users_preferred_language' => 'Preferred Language', 'users_social_accounts' => 'Social Accounts', 'users_social_accounts_info' => 'Here you can connect your other accounts for quicker and easier login. Disconnecting an account here does not previously authorized access. Revoke access from your profile settings on the connected social account.', 'users_social_connect' => 'Connect Account', 'users_social_disconnect' => 'Disconnect Account', 'users_social_connected' => ':socialAccount account was successfully attached to your profile.', 'users_social_disconnected' => ':socialAccount account was successfully disconnected from your profile.', + + // Since these labels are already localized this array does not need to be + // translated in the language-specific files. + // DELETE BELOW IF COPIED FROM EN + /////////////////////////////////// + 'language_select' => [ + 'en' => 'English', + 'de' => 'Deutsch', + 'fr' => 'Français', + 'pt_BR' => 'Português do Brasil' + ] + /////////////////////////////////// ]; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/lang/fr/activities.php b/resources/lang/fr/activities.php new file mode 100644 index 000000000..32f225d5d --- /dev/null +++ b/resources/lang/fr/activities.php @@ -0,0 +1,40 @@ + 'a créé la page', + 'page_create_notification' => 'Page créée avec succès', + 'page_update' => 'a modifié la page', + 'page_update_notification' => 'Page modifiée avec succès', + 'page_delete' => 'a supprimé la page', + 'page_delete_notification' => 'Page supprimée avec succès', + 'page_restore' => 'a restauré la page', + 'page_restore_notification' => 'Page réstaurée avec succès', + 'page_move' => 'a déplacé la page', + + // Chapters + 'chapter_create' => 'a créé le chapitre', + 'chapter_create_notification' => 'Chapitre créé avec succès', + 'chapter_update' => 'a modifié le chapitre', + 'chapter_update_notification' => 'Chapitre modifié avec succès', + 'chapter_delete' => 'a supprimé le chapitre', + 'chapter_delete_notification' => 'Chapitre supprimé avec succès', + 'chapter_move' => 'a déplacé le chapitre', + + // Books + 'book_create' => 'a créé le livre', + 'book_create_notification' => 'Livre créé avec succès', + 'book_update' => 'a modifié le livre', + 'book_update_notification' => 'Livre modifié avec succès', + 'book_delete' => 'a supprimé le livre', + 'book_delete_notification' => 'Livre supprimé avec succès', + 'book_sort' => 'a réordonné le livre', + 'book_sort_notification' => 'Livre réordonné avec succès', + +]; diff --git a/resources/lang/fr/auth.php b/resources/lang/fr/auth.php new file mode 100644 index 000000000..41d051c5f --- /dev/null +++ b/resources/lang/fr/auth.php @@ -0,0 +1,74 @@ + 'Ces informations ne correspondent a aucun compte.', + 'throttle' => "Trop d'essais, veuillez réessayer dans :seconds secondes.", + + /** + * Login & Register + */ + 'sign_up' => "S'inscrire", + 'log_in' => 'Se connecter', + 'logout' => 'Se déconnecter', + + 'name' => 'Nom', + 'username' => "Nom d'utilisateur", + 'email' => 'E-mail', + 'password' => 'Mot de passe', + 'password_confirm' => 'Confirmez le mot de passe', + 'password_hint' => 'Doit faire plus de 5 caractères', + 'forgot_password' => 'Mot de passe oublié?', + 'remember_me' => 'Se souvenir de moi', + 'ldap_email_hint' => "Merci d'entrer une adresse e-mail pour ce compte", + 'create_account' => 'Créer un compte', + 'social_login' => 'Social Login', + 'social_registration' => 'Enregistrement Social', + 'social_registration_text' => "S'inscrire et se connecter avec un réseau social", + + 'register_thanks' => 'Merci pour votre enregistrement', + 'register_confirm' => 'Vérifiez vos e-mails et cliquer sur le lien de confirmation pour rejoindre :appName.', + 'registrations_disabled' => "L'inscription est désactivée pour le moment", + 'registration_email_domain_invalid' => 'Cette adresse e-mail ne peux pas adcéder à l\'application', + 'register_success' => 'Merci pour votre inscription. Vous êtes maintenant inscrit(e) et connecté(e)', + + + /** + * Password Reset + */ + 'reset_password' => 'Reset Password', + 'reset_password_send_instructions' => 'Entrez votre adresse e-mail ci-dessous et un e-mail avec un lien de réinitialisation de mot de passe vous sera envoyé', + 'reset_password_send_button' => 'Envoyer un lien de réinitialisation', + 'reset_password_sent_success' => 'Un lien de réinitialisation a été envoyé à :email.', + 'reset_password_success' => 'Votre mot de passe a été réinitialisé avec succès.', + + 'email_reset_subject' => 'Réinitialisez votre mot de passe pour :appName', + 'email_reset_text' => 'Vous recevez cet e-mail parceque nous avons reçu une demande de réinitialisation pour votre compte', + 'email_reset_not_requested' => 'Si vous n\'avez pas effectué cette demande, vous pouvez ignorer cet e-mail.', + + + /** + * Email Confirmation + */ + 'email_confirm_subject' => 'Confirmez votre adresse e-mail pour :appName', + 'email_confirm_greeting' => 'Merci d\'avoir rejoint :appName!', + 'email_confirm_text' => 'Merci de confirmer en cliquant sur le lien ci-dessous:', + 'email_confirm_action' => 'Confirmez votre adresse e-mail', + 'email_confirm_send_error' => 'La confirmation par e-mail est requise mais le système n\'a pas pu envoyer l\'e-mail. Contactez l\'administrateur système.', + 'email_confirm_success' => 'Votre adresse e-mail a été confirmée!', + 'email_confirm_resent' => 'L\'e-mail de confirmation a été ré-envoyé. Vérifiez votre boîte de récéption.', + + 'email_not_confirmed' => 'Adresse e-mail non confirmée', + 'email_not_confirmed_text' => 'Votre adresse e-mail n\'a pas été confirmée.', + 'email_not_confirmed_click_link' => 'Merci de cliquer sur le lien dans l\'e-mail qui vous a été envoyé après l\'enregistrement.', + 'email_not_confirmed_resend' => 'Si vous ne retrouvez plus l\'e-mail, vous pouvez renvoyer un e-mail de confirmation en utilisant le formulaire ci-dessous.', + 'email_not_confirmed_resend_button' => 'Renvoyez l\'e-mail de confirmation', +]; diff --git a/resources/lang/fr/common.php b/resources/lang/fr/common.php new file mode 100644 index 000000000..5eb4b8fa8 --- /dev/null +++ b/resources/lang/fr/common.php @@ -0,0 +1,58 @@ + 'Annuler', + 'confirm' => 'Confirmer', + 'back' => 'Retour', + 'save' => 'Enregistrer', + 'continue' => 'Continuer', + 'select' => 'Selectionner', + + /** + * Form Labels + */ + 'name' => 'Nom', + 'description' => 'Description', + 'role' => 'Rôle', + + /** + * Actions + */ + 'actions' => 'Actions', + 'view' => 'Voir', + 'create' => 'Créer', + 'update' => 'Modifier', + 'edit' => 'Editer', + 'sort' => 'Trier', + 'move' => 'Déplacer', + 'delete' => 'Supprimer', + 'search' => 'Chercher', + 'search_clear' => 'Réinitialiser la recherche', + 'reset' => 'Réinitialiser', + 'remove' => 'Enlever', + + + /** + * Misc + */ + 'deleted_user' => 'Utilisateur supprimé', + 'no_activity' => 'Aucune activité', + 'no_items' => 'Aucun élément', + 'back_to_top' => 'Retour en haut', + 'toggle_details' => 'Afficher les détails', + + /** + * Header + */ + 'view_profile' => 'Voir le profil', + 'edit_profile' => 'Modifier le profil', + + /** + * Email Content + */ + 'email_action_help' => 'Si vous rencontrez des problèmes pour cliquer le bouton ":actionText", copiez et collez l\'adresse ci-dessous dans votre navigateur:', + 'email_rights' => 'Tous droits réservés', +]; diff --git a/resources/lang/fr/components.php b/resources/lang/fr/components.php new file mode 100644 index 000000000..7c9c4cfc0 --- /dev/null +++ b/resources/lang/fr/components.php @@ -0,0 +1,24 @@ + 'Selectionner une image', + 'image_all' => 'Toutes', + 'image_all_title' => 'Voir toutes les images', + 'image_book_title' => 'Voir les images ajoutées à ce livre', + 'image_page_title' => 'Voir les images ajoutées à cette page', + 'image_search_hint' => 'Rechercher par nom d\'image', + 'image_uploaded' => 'Ajoutée le :uploadedDate', + 'image_load_more' => 'Charger plus', + 'image_image_name' => 'Nom de l\'image', + 'image_delete_confirm' => 'Cette image est utilisée dans les pages ci-dessous. Confirmez que vous souhaitez bien supprimer cette image.', + 'image_select_image' => 'Selectionner l\'image', + 'image_dropzone' => 'Glissez les images ici ou cliquez pour les ajouter', + 'images_deleted' => 'Images supprimées', + 'image_preview' => 'Prévisualiser l\'image', + 'image_upload_success' => 'Image ajoutée avec succès', + 'image_update_success' => 'Détails de l\'image mis à jour', + 'image_delete_success' => 'Image supprimée avec succès' +]; diff --git a/resources/lang/fr/entities.php b/resources/lang/fr/entities.php new file mode 100644 index 000000000..941259f80 --- /dev/null +++ b/resources/lang/fr/entities.php @@ -0,0 +1,225 @@ + 'Créé récemment', + 'recently_created_pages' => 'Pages créées récemment', + 'recently_updated_pages' => 'Pages mises à jour récemment', + 'recently_created_chapters' => 'Chapitres créés récemment', + 'recently_created_books' => 'Livres créés récemment', + 'recently_update' => 'Mis à jour récemment', + 'recently_viewed' => 'Vus récemment', + 'recent_activity' => 'Activité récente', + 'create_now' => 'En créer un récemment', + 'revisions' => 'Révisions', + 'meta_created' => 'Créé :timeLength', + 'meta_created_name' => 'Créé :timeLength par :user', + 'meta_updated' => 'Mis à jour :timeLength', + 'meta_updated_name' => 'Mis à jour :timeLength par :user', + 'x_pages' => ':count pages', + 'entity_select' => 'Sélectionner l\'entité', + 'images' => 'Images', + 'my_recent_drafts' => 'Mes brouillons récents', + 'my_recently_viewed' => 'Vus récemment', + 'no_pages_viewed' => 'Vous n\'avez rien visité récemment', + 'no_pages_recently_created' => 'Aucune page créée récemment', + 'no_pages_recently_updated' => 'Aucune page mise à jour récemment', + + /** + * Permissions and restrictions + */ + 'permissions' => 'Permissions', + 'permissions_intro' => 'Une fois activées ces permission prendont la priorité sur tous les sets de permissions pré-existants.', + 'permissions_enable' => 'Activer les permissions personnalisées', + 'permissions_save' => 'Enregistrer les permissions', + + /** + * Search + */ + 'search_results' => 'Résultats de recherche', + 'search_results_page' => 'Résultats de recherche des pages', + 'search_results_chapter' => 'Résultats de recherche des chapitres', + 'search_results_book' => 'Résultats de recherche des livres', + 'search_clear' => 'Réinitialiser la recherche', + 'search_view_pages' => 'Voir toutes les pages correspondantes', + 'search_view_chapters' => 'Voir tous les chapitres correspondants', + 'search_view_books' => 'Voir tous les livres correspondants', + 'search_no_pages' => 'Aucune page correspondant à cette recherche', + 'search_for_term' => 'recherche pour :term', + 'search_page_for_term' => 'Recherche de page pour :term', + 'search_chapter_for_term' => 'Recherche de chapitre pour :term', + 'search_book_for_term' => 'Recherche de livres pour :term', + + /** + * Books + */ + 'book' => 'Livre', + 'books' => 'Livres', + 'books_empty' => 'Aucun livre n\'a été créé', + 'books_popular' => 'Livres populaires', + 'books_recent' => 'Livres récents', + 'books_popular_empty' => 'Les livres les plus populaires apparaîtront ici.', + 'books_create' => 'Créer un nouveau livre', + 'books_delete' => 'Supprimer un livre', + 'books_delete_named' => 'Supprimer le livre :bookName', + 'books_delete_explain' => 'Ceci va supprimer le livre nommé \':bookName\', Tous les chapitres et pages seront supprimés.', + 'books_delete_confirmation' => 'Êtes-vous sûr(e) de vouloir supprimer ce livre?', + 'books_edit' => 'Modifier le livre', + 'books_edit_named' => 'Modifier le livre :bookName', + 'books_form_book_name' => 'Nom du livre', + 'books_save' => 'Enregistrer le livre', + 'books_permissions' => 'Permissions du livre', + 'books_permissions_updated' => 'Permissions du livre mises à jour', + 'books_empty_contents' => 'Aucune page ou chapitre n\'a été ajouté à ce livre.', + 'books_empty_create_page' => 'Créer une nouvelle page', + 'books_empty_or' => 'ou', + 'books_empty_sort_current_book' => 'Trier les pages du livre', + 'books_empty_add_chapter' => 'Ajouter un chapitre', + 'books_permissions_active' => 'Permissions personnalisées activées', + 'books_search_this' => 'Chercher dans le livre', + 'books_navigation' => 'Navigation dans le livre', + 'books_sort' => 'Trier les contenus du livre', + 'books_sort_named' => 'Trier le livre :bookName', + 'books_sort_show_other' => 'Afficher d\'autres livres', + 'books_sort_save' => 'Enregistrer l\'ordre', + + /** + * Chapters + */ + 'chapter' => 'Chapitre', + 'chapters' => 'Chapitres', + 'chapters_popular' => 'Chapitres populaires', + 'chapters_new' => 'Nouveau chapitre', + 'chapters_create' => 'Créer un nouveau chapitre', + 'chapters_delete' => 'Supprimer le chapitre', + 'chapters_delete_named' => 'Supprimer le chapitre :chapterName', + 'chapters_delete_explain' => 'Ceci va supprimer le chapitre \':chapterName\', Toutes les pages seront déplacée dans le livre parent.', + 'chapters_delete_confirm' => 'Etes-vous sûr(e) de vouloir supprimer ce chapitre?', + 'chapters_edit' => 'Modifier le chapitre', + 'chapters_edit_named' => 'Modifier le chapitre :chapterName', + 'chapters_save' => 'Enregistrer le chapitre', + 'chapters_move' => 'Déplace le chapitre', + 'chapters_move_named' => 'Déplacer le chapitre :chapterName', + 'chapter_move_success' => 'Chapitre déplacé dans :bookName', + 'chapters_permissions' => 'Permissions du chapitre', + 'chapters_empty' => 'Il n\'y a pas de pages dans ce chapitre actuellement.', + 'chapters_permissions_active' => 'Permissions du chapitre activées', + 'chapters_permissions_success' => 'Permissions du chapitres mises à jour', + + /** + * Pages + */ + 'page' => 'Page', + 'pages' => 'Pages', + 'pages_popular' => 'Pages populaires', + 'pages_new' => 'Nouvelle page', + 'pages_attachments' => 'Fichiers joints', + 'pages_navigation' => 'Navigation des pages', + 'pages_delete' => 'Supprimer la page', + 'pages_delete_named' => 'Supprimer la page :pageName', + 'pages_delete_draft_named' => 'supprimer le brouillon de la page :pageName', + 'pages_delete_draft' => 'Supprimer le brouillon', + 'pages_delete_success' => 'Page supprimée', + 'pages_delete_draft_success' => 'Brouillon supprimé', + 'pages_delete_confirm' => 'Êtes-vous sûr(e) de vouloir supprimer cette page?', + 'pages_delete_draft_confirm' => 'Êtes-vous sûr(e) de vouloir supprimer ce brouillon?', + 'pages_editing_named' => 'Modification de la page :pageName', + 'pages_edit_toggle_header' => 'Afficher/cacher l\'en-tête', + 'pages_edit_save_draft' => 'Enregistrer le brouillon', + 'pages_edit_draft' => 'Modifier le brouillon', + 'pages_editing_draft' => 'Modification du brouillon', + 'pages_editing_page' => 'Modification de la page', + 'pages_edit_draft_save_at' => 'Brouillon sauvé le ', + 'pages_edit_delete_draft' => 'Supprimer le brouillon', + 'pages_edit_discard_draft' => 'Ecarter le brouillon', + 'pages_edit_set_changelog' => 'Remplir le journal des changements', + 'pages_edit_enter_changelog_desc' => 'Entrez une brève description des changements effectués', + 'pages_edit_enter_changelog' => 'Entrez dans le journal des changements', + 'pages_save' => 'Enregistrez la page', + 'pages_title' => 'Titre de la page', + 'pages_name' => 'Nom de la page', + 'pages_md_editor' => 'Editeur', + 'pages_md_preview' => 'Prévisualisation', + 'pages_md_insert_image' => 'Insérer une image', + 'pages_md_insert_link' => 'Insérer un lien', + 'pages_not_in_chapter' => 'La page n\'est pas dans un chanpitre', + 'pages_move' => 'Déplacer la page', + 'pages_move_success' => 'Page déplacée à ":parentName"', + 'pages_permissions' => 'Permissions de la page', + 'pages_permissions_success' => 'Permissions de la page mises à jour', + 'pages_revisions' => 'Révisions de la page', + 'pages_revisions_named' => 'Révisions pour :pageName', + 'pages_revision_named' => 'Révision pour :pageName', + 'pages_revisions_created_by' => 'Créé par', + 'pages_revisions_date' => 'Date de révision', + 'pages_revisions_changelog' => 'Journal des changements', + 'pages_revisions_changes' => 'Changements', + 'pages_revisions_current' => 'Version courante', + 'pages_revisions_preview' => 'Prévisualisation', + 'pages_revisions_restore' => 'Restaurer', + 'pages_revisions_none' => 'Cette page n\'a aucune révision', + 'pages_export' => 'Exporter', + 'pages_export_html' => 'Fichiers web', + 'pages_export_pdf' => 'Fichier PDF', + 'pages_export_text' => 'Document texte', + 'pages_copy_link' => 'Copier le lien', + 'pages_permissions_active' => 'Permissions de page actives', + 'pages_initial_revision' => 'Publication initiale', + 'pages_initial_name' => 'Nouvelle page', + 'pages_editing_draft_notification' => 'Vous éditez actuellement un brouillon qui a été sauvé :timeDiff.', + 'pages_draft_edited_notification' => 'La page a été mise à jour depuis votre dernière visit. Vous devriez écarter ce brouillon.', + 'pages_draft_edit_active' => [ + 'start_a' => ':count utilisateurs ont commencé a éditer cette page', + 'start_b' => ':userName a commencé à éditer cette page', + 'time_a' => 'depuis la dernière sauvegarde', + 'time_b' => 'dans les :minCount dernières minutes', + 'message' => ':start :time. Attention a ne pas écraser les mises à jour de quelqu\'un d\'autre!', + ], + 'pages_draft_discarded' => 'Brouuillon écarté, la page est dans sa version actuelle.', + + /** + * Editor sidebar + */ + 'page_tags' => 'Mots-clés de la page', + 'tag' => 'Mot-clé', + 'tags' => 'Mots-clé', + 'tag_value' => 'Valeur du mot-clé (Optionnel)', + 'tags_explain' => "Ajouter des mot-clés pour catégoriser votre contenu.", + 'tags_add' => 'Ajouter un autre mot-clé', + 'attachments' => 'Fichiers joints', + 'attachments_explain' => 'Ajouter des fichiers ou des liens pour les afficher sur votre page. Ils seront affichés dans la barre latérale', + 'attachments_explain_instant_save' => 'Ces changements sont enregistrés immédiatement.', + 'attachments_items' => 'Fichiers joints', + 'attachments_upload' => 'Uploader un fichier', + 'attachments_link' => 'Attacher un lien', + 'attachments_set_link' => 'Définir un lien', + 'attachments_delete_confirm' => 'Cliquer une seconde fois sur supprimer pour valider la suppression.', + 'attachments_dropzone' => 'Glissez des fichiers ou cliquez ici pour attacher des fichiers', + 'attachments_no_files' => 'Aucun fichier ajouté', + 'attachments_explain_link' => 'Vous pouvez attacher un lien si vous ne souhaitez pas uploader un fichier.', + 'attachments_link_name' => 'Nom du lien', + 'attachment_link' => 'Lien de l\'attachement', + 'attachments_link_url' => 'Lien sur un fichier', + 'attachments_link_url_hint' => 'URL du site ou du fichier', + 'attach' => 'Attacher', + 'attachments_edit_file' => 'Modifier le fichier', + 'attachments_edit_file_name' => 'Nom du fichier', + 'attachments_edit_drop_upload' => 'Glissez un fichier ou cliquer pour mettre à jour le fichier', + 'attachments_order_updated' => 'Ordre des fichiers joints mis à jour', + 'attachments_updated_success' => 'Détails des fichiers joints mis à jour', + 'attachments_deleted' => 'Fichier joint supprimé', + 'attachments_file_uploaded' => 'Fichier ajouté avec succès', + 'attachments_file_updated' => 'Fichier mis à jour avec succès', + 'attachments_link_attached' => 'Lien attaché à la page avec succès', + + /** + * Profile View + */ + 'profile_user_for_x' => 'Utilisateur depuis :time', + 'profile_created_content' => 'Contenu créé', + 'profile_not_created_pages' => ':userName n\'a pas créé de pages', + 'profile_not_created_chapters' => ':userName n\'a pas créé de chapitres', + 'profile_not_created_books' => ':userName n\'a pas créé de livres', +]; diff --git a/resources/lang/fr/errors.php b/resources/lang/fr/errors.php new file mode 100644 index 000000000..72af89f7f --- /dev/null +++ b/resources/lang/fr/errors.php @@ -0,0 +1,70 @@ + 'Vous n\'avez pas les droits pour accéder à cette page.', + 'permissionJson' => 'Vous n\'avez pas les droits pour exécuter cette action.', + + // Auth + 'error_user_exists_different_creds' => 'Un utilisateur avec l\'adresse :email existe déjà.', + 'email_already_confirmed' => 'Cet e-mail a déjà été validé, vous pouvez vous connecter.', + 'email_confirmation_invalid' => 'Cette confirmation est invalide. Veuillez essayer de vous inscrire à nouveau.', + 'email_confirmation_expired' => 'Le jeton de confirmation est perimé. Un nouvel e-mail vous a été envoyé.', + 'ldap_fail_anonymous' => 'L\'accès LDAP anonyme n\'a pas abouti', + 'ldap_fail_authed' => 'L\'accès LDAP n\'a pas abouti avec cet utilisateur et ce mot de passe', + 'ldap_extension_not_installed' => 'L\'extention LDAP PHP n\'est pas installée', + 'ldap_cannot_connect' => 'Cannot connect to ldap server, Initial connection failed', + 'social_no_action_defined' => 'No action defined', + 'social_account_in_use' => 'Cet compte :socialAccount est déjà utilisé. Essayez de vous connecter via :socialAccount.', + 'social_account_email_in_use' => 'L\'email :email Est déjà utilisé. Si vous avez déjà un compte :socialAccount, vous pouvez le joindre à votre profil existant.', + 'social_account_existing' => 'Ce compte :socialAccount est déjà rattaché à votre profil.', + 'social_account_already_used_existing' => 'Ce compte :socialAccount est déjà utilisé par un autre utilisateur.', + 'social_account_not_used' => 'Ce compte :socialAccount n\'est lié à aucun utilisateur. ', + 'social_account_register_instructions' => 'Si vous n\'avez pas encore de compte, vous pouvez le lier avec l\'option :socialAccount.', + 'social_driver_not_found' => 'Social driver not found', + 'social_driver_not_configured' => 'Your :socialAccount social settings are not configured correctly.', + + // System + 'path_not_writable' => 'File path :filePath could not be uploaded to. Ensure it is writable to the server.', + 'cannot_get_image_from_url' => 'Impossible de récupérer l\'image depuis :url', + 'cannot_create_thumbs' => 'Le serveur ne peux pas créer de miniatures, vérifier que l\extensions GD PHP est installée.', + 'server_upload_limit' => 'La taille du fichier est trop grande.', + 'image_upload_error' => 'Une erreur est survenue pendant l\'envoi de l\'image', + + // Attachments + 'attachment_page_mismatch' => 'Page mismatch during attachment update', + + // Pages + 'page_draft_autosave_fail' => 'Le brouillon n\'a pas pu être sauvé. Vérifiez votre connexion internet', + + // Entities + 'entity_not_found' => 'Entité non trouvée', + 'book_not_found' => 'Livre non trouvé', + 'page_not_found' => 'Page non trouvée', + 'chapter_not_found' => 'Chapitre non trouvé', + 'selected_book_not_found' => 'Ce livre n\'a pas été trouvé', + 'selected_book_chapter_not_found' => 'Ce livre ou chapitre n\'a pas été trouvé', + 'guests_cannot_save_drafts' => 'Les invités ne peuvent pas sauver de brouillons', + + // Users + 'users_cannot_delete_only_admin' => 'Vous ne pouvez pas supprimer le dernier admin', + 'users_cannot_delete_guest' => 'Vous ne pouvez pas supprimer l\'utilisateur invité', + + // Roles + 'role_cannot_be_edited' => 'Ce rôle ne peut pas être modifié', + 'role_system_cannot_be_deleted' => 'Ceci est un rôle du système et on ne peut pas le supprimer', + 'role_registration_default_cannot_delete' => 'Ce rôle ne peut pas être supprimé tant qu\'il est le rôle par défaut', + + // Error pages + '404_page_not_found' => 'Page non trouvée', + 'sorry_page_not_found' => 'Désolé, cette page n\'a pas pu être trouvée.', + 'return_home' => 'Retour à l\'accueil', + 'error_occurred' => 'Une erreur est survenue', + 'app_down' => ':appName n\'est pas en service pour le moment', + 'back_soon' => 'Nous serons bientôt de retour.', +]; diff --git a/resources/lang/fr/pagination.php b/resources/lang/fr/pagination.php new file mode 100644 index 000000000..9f07a5f93 --- /dev/null +++ b/resources/lang/fr/pagination.php @@ -0,0 +1,19 @@ + '« Précédent', + 'next' => 'Suivant »', + +]; diff --git a/resources/lang/fr/passwords.php b/resources/lang/fr/passwords.php new file mode 100644 index 000000000..7be81da23 --- /dev/null +++ b/resources/lang/fr/passwords.php @@ -0,0 +1,22 @@ + 'Les mots de passe doivent faire au moins 6 caractères et correspondre à la confirmation.', + 'user' => "Nous n'avons pas trouvé d'utilisateur avec cette adresse.", + 'token' => 'Le jeton de réinitialisation est invalide.', + 'sent' => 'Nous vous avons envoyé un lien de réinitialisation de mot de passe!', + 'reset' => 'Votre mot de passe a été réinitialisé!', + +]; diff --git a/resources/lang/fr/settings.php b/resources/lang/fr/settings.php new file mode 100644 index 000000000..8a3756527 --- /dev/null +++ b/resources/lang/fr/settings.php @@ -0,0 +1,112 @@ + 'Préférences', + 'settings_save' => 'Enregistrer les préférences', + 'settings_save_success' => 'Préférences enregistrées', + + /** + * App settings + */ + + 'app_settings' => 'Préférences de l\'application', + 'app_name' => 'Nom de l\'application', + 'app_name_desc' => 'Ce nom est affiché dans l\'en-tête et les e-mails.', + 'app_name_header' => 'Afficher le nom dans l\'en-tête?', + 'app_public_viewing' => 'Accepter le visionnage public des pages?', + 'app_secure_images' => 'Activer l\'ajout d\'image sécurisé?', + 'app_secure_images_desc' => 'Pour des questions de performances, toutes les images sont publiques. Cette option ajoute une chaîne aléatoire difficile à deviner dans les URLs des images.', + 'app_editor' => 'Editeur des pages', + 'app_editor_desc' => 'Sélectionnez l\'éditeur qui sera utilisé pour modifier les pages.', + 'app_custom_html' => 'HTML personnalisé dans l\'en-tête', + 'app_custom_html_desc' => 'Le contenu inséré ici sera jouté en bas de la balise de toutes les pages. Vous pouvez l\'utiliser pour ajouter du CSS personnalisé ou un tracker analytique.', + 'app_logo' => 'Logo de l\'Application', + 'app_logo_desc' => 'Cette image doit faire 43px de hauteur.Hello, This is a test
This is a second block of content
"; + $secondPage->save(); + + $this->asAdmin()->visit($page->getUrl()) + ->dontSee('Hello, This is a test'); + + $originalHtml = $page->html; + $page->html .= "{{@{$secondPage->id}}}"; + $page->save(); + + $this->asAdmin()->visit($page->getUrl()) + ->see('Hello, This is a test') + ->see('This is a second block of content'); + + $page->html = $originalHtml . " Well {{@{$secondPage->id}#section2}}"; + $page->save(); + + $this->asAdmin()->visit($page->getUrl()) + ->dontSee('Hello, This is a test') + ->see('Well This is a second block of content'); + } + +} diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php index 233f300ee..de875c3f3 100644 --- a/tests/Entity/PageDraftTest.php +++ b/tests/Entity/PageDraftTest.php @@ -1,7 +1,7 @@ merge(factory(Tag::class, 5)->make(['name' => 'color'])); $page = $this->getPageWithTags($attrs); - $this->asAdmin()->get('/ajax/tags/suggest?search=co')->seeJsonEquals(['color', 'country']); - $this->asEditor()->get('/ajax/tags/suggest?search=co')->seeJsonEquals(['color', 'country']); + $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']); + $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']); // Set restricted permission the page $page->restricted = true; $page->save(); $permissionService->buildJointPermissionsForEntity($page); - $this->asAdmin()->get('/ajax/tags/suggest?search=co')->seeJsonEquals(['color', 'country']); - $this->asEditor()->get('/ajax/tags/suggest?search=co')->seeJsonEquals([]); - } - - public function test_entity_tag_updating() - { - $page = $this->getPageWithTags(); - - $testJsonData = [ - ['name' => 'color', 'value' => 'red'], - ['name' => 'color', 'value' => ' blue '], - ['name' => 'city', 'value' => 'London '], - ['name' => 'country', 'value' => ' England'], - ]; - $testResponseJsonData = [ - ['name' => 'color', 'value' => 'red'], - ['name' => 'color', 'value' => 'blue'], - ['name' => 'city', 'value' => 'London'], - ['name' => 'country', 'value' => 'England'], - ]; - - // Do update request - $this->asAdmin()->json("POST", "/ajax/tags/update/page/" . $page->id, ['tags' => $testJsonData]); - $updateData = json_decode($this->response->getContent()); - // Check data is correct - $testDataCorrect = true; - foreach ($updateData->tags as $data) { - $testItem = ['name' => $data->name, 'value' => $data->value]; - if (!in_array($testItem, $testResponseJsonData)) $testDataCorrect = false; - } - $testMessage = "Expected data was not found in the response.\nExpected Data: %s\nRecieved Data: %s"; - $this->assertTrue($testDataCorrect, sprintf($testMessage, json_encode($testResponseJsonData), json_encode($updateData))); - $this->assertTrue(isset($updateData->message), "No message returned in tag update response"); - - // Do get request - $this->asAdmin()->get("/ajax/tags/get/page/" . $page->id); - $getResponseData = json_decode($this->response->getContent()); - // Check counts - $this->assertTrue(count($getResponseData) === count($testJsonData), "The received tag count is incorrect"); - // Check data is correct - $testDataCorrect = true; - foreach ($getResponseData as $data) { - $testItem = ['name' => $data->name, 'value' => $data->value]; - if (!in_array($testItem, $testResponseJsonData)) $testDataCorrect = false; - } - $testMessage = "Expected data was not found in the response.\nExpected Data: %s\nRecieved Data: %s"; - $this->assertTrue($testDataCorrect, sprintf($testMessage, json_encode($testResponseJsonData), json_encode($getResponseData))); + $this->asAdmin()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals(['color', 'country']); + $this->asEditor()->get('/ajax/tags/suggest/names?search=co')->seeJsonEquals([]); } } diff --git a/tests/ImageTest.php b/tests/ImageTest.php index 9da12d36b..debde848c 100644 --- a/tests/ImageTest.php +++ b/tests/ImageTest.php @@ -1,6 +1,6 @@ see('Cannot be deleted'); } + + + public function test_image_delete_own_permission() + { + $this->giveUserPermissions($this->user, ['image-update-all']); + $page = \BookStack\Page::first(); + $image = factory(\BookStack\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]); + + $this->actingAs($this->user)->json('delete', '/images/' . $image->id) + ->seeStatusCode(403); + + $this->giveUserPermissions($this->user, ['image-delete-own']); + + $this->actingAs($this->user)->json('delete', '/images/' . $image->id) + ->seeStatusCode(200) + ->dontSeeInDatabase('images', ['id' => $image->id]); + } + + public function test_image_delete_all_permission() + { + $this->giveUserPermissions($this->user, ['image-update-all']); + $admin = $this->getAdmin(); + $page = \BookStack\Page::first(); + $image = factory(\BookStack\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); + + $this->actingAs($this->user)->json('delete', '/images/' . $image->id) + ->seeStatusCode(403); + + $this->giveUserPermissions($this->user, ['image-delete-own']); + + $this->actingAs($this->user)->json('delete', '/images/' . $image->id) + ->seeStatusCode(403); + + $this->giveUserPermissions($this->user, ['image-delete-all']); + + $this->actingAs($this->user)->json('delete', '/images/' . $image->id) + ->seeStatusCode(200) + ->dontSeeInDatabase('images', ['id' => $image->id]); + } + } diff --git a/tests/PublicActionTest.php b/tests/PublicActionTest.php index 2ea5fbfed..6127e1cd4 100644 --- a/tests/PublicActionTest.php +++ b/tests/PublicActionTest.php @@ -1,6 +1,6 @@ make(Illuminate\Contracts\Console\Kernel::class)->bootstrap(); + $app->make(Kernel::class)->bootstrap(); return $app; } - - /** - * Set the current user context to be an admin. - * @return $this - */ - public function asAdmin() - { - return $this->actingAs($this->getAdmin()); - } - - /** - * Get the current admin user. - * @return mixed - */ - public function getAdmin() { - if($this->admin === null) { - $adminRole = \BookStack\Role::getRole('admin'); - $this->admin = $adminRole->users->first(); - } - return $this->admin; - } - - /** - * Set the current editor context to be an editor. - * @return $this - */ - public function asEditor() - { - if($this->editor === null) { - $this->editor = $this->getEditor(); - } - return $this->actingAs($this->editor); - } - - /** - * Get a user that's not a system user such as the guest user. - */ - public function getNormalUser() - { - return \BookStack\User::where('system_name', '=', null)->get()->last(); - } - - /** - * Quickly sets an array of settings. - * @param $settingsArray - */ - protected function setSettings($settingsArray) - { - $settings = app('BookStack\Services\SettingService'); - foreach ($settingsArray as $key => $value) { - $settings->put($key, $value); - } - } - - /** - * Create a group of entities that belong to a specific user. - * @param $creatorUser - * @param $updaterUser - * @return array - */ - protected function createEntityChainBelongingToUser($creatorUser, $updaterUser = false) - { - if ($updaterUser === false) $updaterUser = $creatorUser; - $book = factory(BookStack\Book::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]); - $chapter = factory(BookStack\Chapter::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]); - $page = factory(BookStack\Page::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id]); - $book->chapters()->saveMany([$chapter]); - $chapter->pages()->saveMany([$page]); - $restrictionService = $this->app[\BookStack\Services\PermissionService::class]; - $restrictionService->buildJointPermissionsForEntity($book); - return [ - 'book' => $book, - 'chapter' => $chapter, - 'page' => $page - ]; - } - - /** - * Quick way to create a new user - * @param array $attributes - * @return mixed - */ - protected function getEditor($attributes = []) - { - $user = factory(\BookStack\User::class)->create($attributes); - $role = \BookStack\Role::getRole('editor'); - $user->attachRole($role);; - return $user; - } - - /** - * Quick way to create a new user without any permissions - * @param array $attributes - * @return mixed - */ - protected function getNewBlankUser($attributes = []) - { - $user = factory(\BookStack\User::class)->create($attributes); - return $user; - } - - /** - * Assert that a given string is seen inside an element. - * - * @param bool|string|null $element - * @param integer $position - * @param string $text - * @param bool $negate - * @return $this - */ - protected function seeInNthElement($element, $position, $text, $negate = false) - { - $method = $negate ? 'assertNotRegExp' : 'assertRegExp'; - - $rawPattern = preg_quote($text, '/'); - - $escapedPattern = preg_quote(e($text), '/'); - - $content = $this->crawler->filter($element)->eq($position)->html(); - - $pattern = $rawPattern == $escapedPattern - ? $rawPattern : "({$rawPattern}|{$escapedPattern})"; - - $this->$method("/$pattern/i", $content); - - return $this; - } - - /** - * Assert that the current page matches a given URI. - * - * @param string $uri - * @return $this - */ - protected function seePageUrlIs($uri) - { - $this->assertEquals( - $uri, $this->currentUri, "Did not land on expected page [{$uri}].\n" - ); - - return $this; - } - - /** - * Do a forced visit that does not error out on exception. - * @param string $uri - * @param array $parameters - * @param array $cookies - * @param array $files - * @return $this - */ - protected function forceVisit($uri, $parameters = [], $cookies = [], $files = []) - { - $method = 'GET'; - $uri = $this->prepareUrlForRequest($uri); - $this->call($method, $uri, $parameters, $cookies, $files); - $this->clearInputs()->followRedirects(); - $this->currentUri = $this->app->make('request')->fullUrl(); - $this->crawler = new Crawler($this->response->getContent(), $uri); - return $this; - } - - /** - * Click the text within the selected element. - * @param $parentElement - * @param $linkText - * @return $this - */ - protected function clickInElement($parentElement, $linkText) - { - $elem = $this->crawler->filter($parentElement); - $link = $elem->selectLink($linkText); - $this->visit($link->link()->getUri()); - return $this; - } - - /** - * Check if the page contains the given element. - * @param string $selector - * @return bool - */ - protected function pageHasElement($selector) - { - $elements = $this->crawler->filter($selector); - $this->assertTrue(count($elements) > 0, "The page does not contain an element matching " . $selector); - return $this; - } - - /** - * Check if the page contains the given element. - * @param string $selector - * @return bool - */ - protected function pageNotHasElement($selector) - { - $elements = $this->crawler->filter($selector); - $this->assertFalse(count($elements) > 0, "The page contains " . count($elements) . " elements matching " . $selector); - return $this; - } } diff --git a/tests/UserProfileTest.php b/tests/UserProfileTest.php index 9543adc1d..a448e3a9f 100644 --- a/tests/UserProfileTest.php +++ b/tests/UserProfileTest.php @@ -1,6 +1,6 @@