updated-packages
This commit is contained in:
205
vendor/laravel/dusk/CHANGELOG.md
vendored
205
vendor/laravel/dusk/CHANGELOG.md
vendored
@@ -1,4 +1,203 @@
|
||||
# Release Notes for 1.0.x
|
||||
# Release Notes
|
||||
|
||||
## [Unreleased](https://github.com/laravel/dusk/compare/v5.11.0...5.0)
|
||||
|
||||
|
||||
## [v5.11.0 (2020-03-24)](https://github.com/laravel/dusk/compare/v5.10.0...v5.11.0)
|
||||
|
||||
### Added
|
||||
- Add assert attribute methods ([#751](https://github.com/laravel/dusk/pull/751))
|
||||
|
||||
### Fixed
|
||||
- Fix Call to undefined method ([#750](https://github.com/laravel/dusk/pull/750))
|
||||
- Avoid throwing exception on production ([#755](https://github.com/laravel/dusk/pull/755))
|
||||
|
||||
|
||||
## [v5.10.0 (2020-03-17)](https://github.com/laravel/dusk/compare/v5.9.2...v5.10.0)
|
||||
|
||||
### Added
|
||||
- Adds `typeSlowly` & `appendSlowly` ([#748](https://github.com/laravel/dusk/pull/748))
|
||||
|
||||
|
||||
## [v5.9.2 (2020-02-18)](https://github.com/laravel/dusk/compare/v5.9.1...v5.9.2)
|
||||
|
||||
### Fixed
|
||||
- Bugfix quoting for `InteractsWithElements::value` ([#735](https://github.com/laravel/dusk/pull/735))
|
||||
- Remove php-webdriver constraints ([#737](https://github.com/laravel/dusk/pull/737))
|
||||
|
||||
|
||||
## [v5.9.1 (2020-02-12)](https://github.com/laravel/dusk/compare/v5.9.0...v5.9.1)
|
||||
|
||||
### Fixed
|
||||
- Adds the missing import for `InteractsWithMouse@clickAtXPath` ([#728](https://github.com/laravel/dusk/pull/728))
|
||||
- Size sanity check at fitContent ([#730](https://github.com/laravel/dusk/pull/730))
|
||||
- Lock php-webdriver constraints for now ([#733](https://github.com/laravel/dusk/pull/733))
|
||||
|
||||
|
||||
## [v5.9.0 (2020-01-28)](https://github.com/laravel/dusk/compare/v5.8.2...v5.9.0)
|
||||
|
||||
### Added
|
||||
- Add `clickAtXPath` ([#723](https://github.com/laravel/dusk/pull/723), [effe73d](https://github.com/laravel/dusk/commit/effe73d6eb61b4bd77f88814bcd679e4fceb6f25))
|
||||
- Add `ProvidesBrowser::getCallerName()` ([#725](https://github.com/laravel/dusk/pull/725))
|
||||
|
||||
### Fixed
|
||||
- Fit content to `<html>` instead of `<body>` ([#726](https://github.com/laravel/dusk/pull/726))
|
||||
|
||||
|
||||
## [v5.8.2 (2020-01-21)](https://github.com/laravel/dusk/compare/v5.8.1...v5.8.2)
|
||||
|
||||
### Changed
|
||||
- Rename php-webdriver package ([#720](https://github.com/laravel/dusk/pull/720))
|
||||
- Update jQuery file ([#721](https://github.com/laravel/dusk/pull/721))
|
||||
|
||||
### Fixed
|
||||
- Update `fitContent()` ([#717](https://github.com/laravel/dusk/pull/717))
|
||||
|
||||
|
||||
## [v5.8.1 (2020-01-07)](https://github.com/laravel/dusk/compare/v5.8.0...v5.8.1)
|
||||
|
||||
### Fixed
|
||||
- Cast boolean values to appropriate string ([#713](https://github.com/laravel/dusk/pull/713))
|
||||
|
||||
|
||||
## [v5.8.0 (2019-12-30)](https://github.com/laravel/dusk/compare/v5.7.0...v5.8.0)
|
||||
|
||||
### Added
|
||||
- Add "waitUntilMissingText" ([#706](https://github.com/laravel/dusk/pull/706))
|
||||
- Add ability to store source from browser ([#707](https://github.com/laravel/dusk/pull/707), [9c90e2a](https://github.com/laravel/dusk/commit/9c90e2a716030c9a36e6306c3f67d606a254bbb7), [1d5bc20](https://github.com/laravel/dusk/commit/1d5bc203b67ffc5a17eb1b89f3e22547e3ea174b))
|
||||
|
||||
|
||||
## [v5.7.0 (2019-12-17)](https://github.com/laravel/dusk/compare/v5.6.3...v5.7.0)
|
||||
|
||||
### Added
|
||||
- Automatically fit content on failures ([#704](https://github.com/laravel/dusk/pull/704))
|
||||
|
||||
|
||||
## [v5.6.3 (2019-12-03)](https://github.com/laravel/dusk/compare/v5.6.2...v5.6.3)
|
||||
|
||||
### Added
|
||||
- Support phpdotenv v4 ([#699](https://github.com/laravel/dusk/pull/699))
|
||||
|
||||
### Fixed
|
||||
- scrollTo: add support for selectors with quotes ([#697](https://github.com/laravel/dusk/pull/697))
|
||||
|
||||
|
||||
## [v5.6.2 (2019-11-26)](https://github.com/laravel/dusk/compare/v5.6.1...v5.6.2)
|
||||
|
||||
### Changed
|
||||
- Allow for Symfony 5 ([#696](https://github.com/laravel/dusk/pull/696))
|
||||
|
||||
|
||||
## [v5.6.1 (2019-11-12)](https://github.com/laravel/dusk/compare/v5.6.0...v5.6.1)
|
||||
|
||||
### Fixed
|
||||
- Ensure jQuery for scrollTo ([#686](https://github.com/laravel/dusk/pull/686))
|
||||
- Added missing return statement in withDuskEnvironment ([#691](https://github.com/laravel/dusk/pull/691))
|
||||
- Prevent using pcntl when not installed ([#692](https://github.com/laravel/dusk/pull/692))
|
||||
|
||||
|
||||
## [v5.6.0 (2019-10-29)](https://github.com/laravel/dusk/compare/v5.5.2...v5.6.0)
|
||||
|
||||
### Added
|
||||
- Add scrollTo method ([#684](https://github.com/laravel/dusk/pull/684))
|
||||
|
||||
### Fixed
|
||||
- Add graceful handler for `SIGINT` for .env restoration ([#682](https://github.com/laravel/dusk/pull/682), [f843b8a](https://github.com/laravel/dusk/commit/f843b8a51ae96933cefcc74dec515377d3135611))
|
||||
|
||||
|
||||
## [v5.5.2 (2019-09-24)](https://github.com/laravel/dusk/compare/v5.5.1...v5.5.2)
|
||||
|
||||
### Fixed
|
||||
- Improve detection of latest stable ChromeDriver release ([#677](https://github.com/laravel/dusk/pull/677))
|
||||
|
||||
|
||||
## [v5.5.1 (2019-09-12)](https://github.com/laravel/dusk/compare/v5.5.0...v5.5.1)
|
||||
|
||||
### Fixed
|
||||
- Update regular expression base on website changes ([#674](https://github.com/laravel/dusk/pull/674))
|
||||
|
||||
|
||||
## [v5.5.0 (2019-08-06)](https://github.com/laravel/dusk/compare/v5.4.0...v5.5.0)
|
||||
|
||||
### Added
|
||||
- Allow saving screenshots in a subdirectory ([#662](https://github.com/laravel/dusk/pull/662))
|
||||
|
||||
|
||||
## [v5.4.0 (2019-07-30)](https://github.com/laravel/dusk/compare/v5.3.0...v5.4.0)
|
||||
|
||||
### Added
|
||||
- Add assertion checks if a button is disabled or enabled ([#661](https://github.com/laravel/dusk/pull/661))
|
||||
|
||||
### Fixed
|
||||
- Update constraints for Laravel 6.0 ([e4b4d63](https://github.com/laravel/dusk/commit/e4b4d63c179bb1f228db22852bd776db750d1ec6))
|
||||
|
||||
|
||||
## [v5.3.0 (2019-07-11)](https://github.com/laravel/dusk/compare/v5.2.0...v5.3.0)
|
||||
|
||||
### Added
|
||||
- Add proxy support to the `dusk:install` command ([#659](https://github.com/laravel/dusk/pull/659))
|
||||
|
||||
|
||||
## [v5.2.0 (2019-06-25)](https://github.com/laravel/dusk/compare/v5.1.1...v5.2.0)
|
||||
|
||||
### Added
|
||||
- Add option to fullsize the browser ([#655](https://github.com/laravel/dusk/pull/655))
|
||||
|
||||
|
||||
## [v5.1.1 (2019-06-14)](https://github.com/laravel/dusk/compare/v5.1.0...v5.1.1)
|
||||
|
||||
### Fixed
|
||||
- Add latest version of Facebook Webdriver ([#654](https://github.com/laravel/dusk/pull/654))
|
||||
|
||||
|
||||
## [v5.1.0 (2019-05-02)](https://github.com/laravel/dusk/compare/v5.0.3...v5.1.0)
|
||||
|
||||
### Added
|
||||
- Implement ChromeDriverCommand ([#643](https://github.com/laravel/dusk/pull/643), [60339a5](https://github.com/laravel/dusk/commit/60339a521a1b05e55af7c90b3151557100a0db4d), [#644](https://github.com/laravel/dusk/pull/644))
|
||||
|
||||
|
||||
## [v5.0.3 (2019-04-02)](https://github.com/laravel/dusk/compare/v5.0.2...v5.0.3)
|
||||
|
||||
### Fixed
|
||||
- Fix `assertVueContains` and `assertVueDoesNotContain` ([#638](https://github.com/laravel/dusk/pull/638))
|
||||
|
||||
|
||||
## [v5.0.2 (2019-03-12)](https://github.com/laravel/dusk/compare/v5.0.1...v5.0.2)
|
||||
|
||||
### Fixed
|
||||
- Fix cookies with falsey values ([#617](https://github.com/laravel/dusk/pull/617))
|
||||
- Fix `with()` and page assertions ([#625](https://github.com/laravel/dusk/pull/625))
|
||||
- Avoid deprecation messages on PHPUnit 8 ([#620](https://github.com/laravel/dusk/pull/620))
|
||||
|
||||
|
||||
## [v5.0.1 (2019-02-27)](https://github.com/laravel/dusk/compare/v5.0.0...v5.0.1)
|
||||
|
||||
### Added
|
||||
- Added support for `phpunit.dusk.xml.dist` ([#610](https://github.com/laravel/dusk/pull/610))
|
||||
- Use custom DISPLAY variable when set on Linux ([#613](https://github.com/laravel/dusk/pull/613), [2480495](https://github.com/laravel/dusk/commit/24804953c5b521415a717afbf82ff4b938c10535))
|
||||
|
||||
### Fixed
|
||||
- Added missing dependencies ([98eccfd](https://github.com/laravel/dusk/commit/98eccfd56e9b2b23b093b801f62c766aaf67589f))
|
||||
- Fix installation of Dotenv on Laravel 5.8 ([1f67bf2](https://github.com/laravel/dusk/commit/1f67bf204fab65a212975683b5391c2f55dd3bcf))
|
||||
|
||||
|
||||
## [v5.0.0 (2019-02-12)](https://github.com/laravel/dusk/compare/v4.0.5...v5.0.0)
|
||||
|
||||
### Added
|
||||
- Support PHPUnit 8 ([788e79c](https://github.com/laravel/dusk/commit/788e79c4713a5706eeafaf7270986a71a4ed43be))
|
||||
- Support Carbon 2 ([85cfc50](https://github.com/laravel/dusk/commit/85cfc50e126a3835428577052cc0660d1c3b639e))
|
||||
- Support Laravel 5.8 ([5b2e9aa](https://github.com/laravel/dusk/commit/5b2e9aa9e4a124f4c4878f65fb644101de1644e7))
|
||||
|
||||
### Changed
|
||||
- Update minimum Laravel version ([fcb2226](https://github.com/laravel/dusk/commit/fcb2226a524f47b51b9b49316d87bc51738733d7))
|
||||
- Update Symfony dependencies to latest version ([788e79c](https://github.com/laravel/dusk/commit/788e79c4713a5706eeafaf7270986a71a4ed43be))
|
||||
- Prefer stable dependencies ([fdb2fd4](https://github.com/laravel/dusk/commit/fdb2fd4b2a2e787b08cf44649c4eef84837324ca))
|
||||
|
||||
|
||||
## [v4.0.0 (2018-08-11)](https://github.com/laravel/dusk/compare/v3.0.10...v4.0.0)
|
||||
|
||||
Dusk 4.0.0 disables cookie serialization and is intended for use with Laravel 5.6.30 or later. If you are using a previous version of Laravel, please continue using Dusk 3.0.0.
|
||||
|
||||
|
||||
## v1.0.13 (2017-04-20)
|
||||
|
||||
@@ -16,6 +215,7 @@
|
||||
- Use `getAttribute('value')` instead of `getText()` for `textarea` elements ([#237](https://github.com/laravel/dusk/pull/237))
|
||||
- Fixed bug when giving strings with apostrophe to `clickLink()` ([#228](https://github.com/laravel/dusk/pull/228))
|
||||
|
||||
|
||||
## v1.0.12 (2017-04-07)
|
||||
|
||||
### Added
|
||||
@@ -38,6 +238,3 @@
|
||||
- Updated ChromeDriver to v2.28 so that it works with Chrome 57 ([#199](https://github.com/laravel/dusk/pull/199))
|
||||
- Comparison to `option` inside `select` will no longer be strict ([#178](https://github.com/laravel/dusk/pull/178))
|
||||
- Type-hint Browser for auto-complete support ([#174](https://github.com/laravel/dusk/pull/174))
|
||||
|
||||
|
||||
## v1.0.10 (2017-03-03)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<p align="center"><img src="https://laravel.com/assets/img/components/logo-dusk.svg"></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/laravel/dusk"><img src="https://travis-ci.org/laravel/dusk.svg" alt="Build Status"></a>
|
||||
<a href="https://github.com/laravel/dusk/actions"><img src="https://github.com/laravel/dusk/workflows/tests/badge.svg" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/laravel/dusk"><img src="https://poser.pugx.org/laravel/dusk/d/total.svg" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/laravel/dusk"><img src="https://poser.pugx.org/laravel/dusk/v/stable.svg" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/laravel/dusk"><img src="https://poser.pugx.org/laravel/dusk/license.svg" alt="License"></a>
|
||||
@@ -13,8 +13,20 @@ Laravel Dusk provides an expressive, easy-to-use browser automation and testing
|
||||
|
||||
## Official Documentation
|
||||
|
||||
Documentation for Dusk can be found on the [Laravel website](https://laravel.com/docs/master/dusk).
|
||||
Documentation for Dusk can be found on the [Laravel website](https://laravel.com/docs/dusk).
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to Dusk! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
Please review [our security policy](https://github.com/laravel/dusk/security/policy) on how to report security vulnerabilities.
|
||||
|
||||
## License
|
||||
|
||||
Laravel Dusk is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
||||
Laravel Dusk is open-sourced software licensed under the [MIT license](LICENSE.md).
|
17
vendor/laravel/dusk/UPGRADE.md
vendored
Normal file
17
vendor/laravel/dusk/UPGRADE.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Upgrade Guide
|
||||
|
||||
## Upgrading To 5.0 From 4.0
|
||||
|
||||
### PHPUnit 8
|
||||
|
||||
Dusk now provides optional support for PHPUnit 8, which requires PHP >= 7.2 Please read through the entire list of changes in [the PHPUnit 8 release announcement](https://phpunit.de/announcements/phpunit-8.html). Using PHPUnit 8 will require Laravel 5.8, which will be released at the end of February 2019.
|
||||
|
||||
You may also continue using PHPUnit 7, which requires a minimum of PHP 7.1.
|
||||
|
||||
### Minimum Laravel version
|
||||
|
||||
Laravel 5.7 is now the minimum supported version of the framework and you should upgrade to continue using Dusk.
|
||||
|
||||
### `setUp` and `tearDown` changes
|
||||
|
||||
The `setUp` and `tearDown` methods now require the `void` return type. If you were overwriting these methods you should add it to the method signatures.
|
BIN
vendor/laravel/dusk/bin/chromedriver-linux
vendored
BIN
vendor/laravel/dusk/bin/chromedriver-linux
vendored
Binary file not shown.
BIN
vendor/laravel/dusk/bin/chromedriver-mac
vendored
BIN
vendor/laravel/dusk/bin/chromedriver-mac
vendored
Binary file not shown.
BIN
vendor/laravel/dusk/bin/chromedriver-win.exe
vendored
BIN
vendor/laravel/dusk/bin/chromedriver-win.exe
vendored
Binary file not shown.
6
vendor/laravel/dusk/bin/jquery.js
vendored
6
vendor/laravel/dusk/bin/jquery.js
vendored
File diff suppressed because one or more lines are too long
36
vendor/laravel/dusk/composer.json
vendored
36
vendor/laravel/dusk/composer.json
vendored
@@ -11,25 +11,37 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"facebook/webdriver": "~1.3",
|
||||
"nesbot/carbon": "~1.20",
|
||||
"illuminate/console": "~5.6",
|
||||
"illuminate/support": "~5.6",
|
||||
"symfony/console": "~4.0",
|
||||
"symfony/process": "~4.0"
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"php-webdriver/webdriver": "^1.8.1",
|
||||
"nesbot/carbon": "^1.20|^2.0",
|
||||
"illuminate/console": "~5.7.0|~5.8.0|^6.0|^7.0",
|
||||
"illuminate/support": "~5.7.0|~5.8.0|^6.0|^7.0",
|
||||
"symfony/console": "^4.0|^5.0",
|
||||
"symfony/finder": "^4.0|^5.0",
|
||||
"symfony/process": "^4.0|^5.0",
|
||||
"vlucas/phpdotenv": "^2.2|^3.0|^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~1.0",
|
||||
"phpunit/phpunit": "~7.0"
|
||||
"mockery/mockery": "^1.0",
|
||||
"phpunit/phpunit": "^7.5|^8.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pcntl": "Used to gracefully terminate Dusk when tests are running."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Dusk\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Laravel\\Dusk\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0-dev"
|
||||
"dev-master": "5.0-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
@@ -37,5 +49,9 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
|
27
vendor/laravel/dusk/phpunit.xml.dist
vendored
27
vendor/laravel/dusk/phpunit.xml.dist
vendored
@@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
beStrictAboutTestsThatDoNotTestAnything="false"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
processIsolation="false"
|
||||
stopOnError="false"
|
||||
stopOnFailure="false"
|
||||
verbose="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Laravel Dusk Test Suite">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
164
vendor/laravel/dusk/src/Browser.php
vendored
164
vendor/laravel/dusk/src/Browser.php
vendored
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Closure;
|
||||
use BadMethodCallException;
|
||||
use Closure;
|
||||
use Facebook\WebDriver\Remote\WebDriverBrowserType;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Facebook\WebDriver\WebDriverDimension;
|
||||
use Facebook\WebDriver\WebDriverPoint;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Facebook\WebDriver\WebDriverDimension;
|
||||
use Facebook\WebDriver\Remote\WebDriverBrowserType;
|
||||
|
||||
class Browser
|
||||
{
|
||||
@@ -17,6 +19,7 @@ class Browser
|
||||
Concerns\InteractsWithJavascript,
|
||||
Concerns\InteractsWithMouse,
|
||||
Concerns\MakesAssertions,
|
||||
Concerns\MakesUrlAssertions,
|
||||
Concerns\WaitsForElements,
|
||||
Macroable {
|
||||
__call as macroCall;
|
||||
@@ -43,6 +46,13 @@ class Browser
|
||||
*/
|
||||
public static $storeConsoleLogAt;
|
||||
|
||||
/**
|
||||
* The directory where source code snapshots will be stored.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $storeSourceAt;
|
||||
|
||||
/**
|
||||
* The browsers that support retrieving logs.
|
||||
*
|
||||
@@ -77,7 +87,7 @@ class Browser
|
||||
/**
|
||||
* The element resolver instance.
|
||||
*
|
||||
* @var ElementResolver
|
||||
* @var \Laravel\Dusk\ElementResolver
|
||||
*/
|
||||
public $resolver;
|
||||
|
||||
@@ -95,11 +105,18 @@ class Browser
|
||||
*/
|
||||
public $component;
|
||||
|
||||
/**
|
||||
* Indicates that the browser should be resized to fit the entire "body" before screenshotting failures.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $fitOnFailure = true;
|
||||
|
||||
/**
|
||||
* Create a browser instance.
|
||||
*
|
||||
* @param \Facebook\WebDriver\Remote\RemoteWebDriver $driver
|
||||
* @param ElementResolver $resolver
|
||||
* @param \Laravel\Dusk\ElementResolver $resolver
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($driver, $resolver = null)
|
||||
@@ -164,6 +181,21 @@ class Browser
|
||||
* @return $this
|
||||
*/
|
||||
public function on($page)
|
||||
{
|
||||
$this->onWithoutAssert($page);
|
||||
|
||||
$page->assert($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current page object without executing the assertions.
|
||||
*
|
||||
* @param mixed $page
|
||||
* @return $this
|
||||
*/
|
||||
public function onWithoutAssert($page)
|
||||
{
|
||||
$this->page = $page;
|
||||
|
||||
@@ -174,8 +206,6 @@ class Browser
|
||||
$page::siteElements(), $page->elements()
|
||||
));
|
||||
|
||||
$page->assert($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -231,6 +261,81 @@ class Browser
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the browser window as large as the content.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fitContent()
|
||||
{
|
||||
$this->driver->switchTo()->defaultContent();
|
||||
|
||||
$html = $this->driver->findElement(WebDriverBy::tagName('html'));
|
||||
|
||||
if (! empty($html) && ($html->getSize()->getWidth() <= 0 || $html->getSize()->getHeight() <= 0)) {
|
||||
$this->resize($html->getSize()->getWidth(), $html->getSize()->getHeight());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable fit on failures.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function disableFitOnFailure()
|
||||
{
|
||||
$this->fitOnFailure = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable fit on failures.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function enableFitOnFailure()
|
||||
{
|
||||
$this->fitOnFailure = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the browser window.
|
||||
*
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @return $this
|
||||
*/
|
||||
public function move($x, $y)
|
||||
{
|
||||
$this->driver->manage()->window()->setPosition(
|
||||
new WebDriverPoint($x, $y)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll screen to element at the given selector.
|
||||
*
|
||||
* @param string $selector
|
||||
* @return $this
|
||||
*/
|
||||
public function scrollTo($selector)
|
||||
{
|
||||
$this->ensurejQueryIsAvailable();
|
||||
|
||||
$selector = addslashes($this->resolver->format($selector));
|
||||
|
||||
$this->driver->executeScript("jQuery(\"html, body\").animate({scrollTop: jQuery(\"$selector\").offset().top}, 0);");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a screenshot and store it with the given name.
|
||||
*
|
||||
@@ -239,9 +344,15 @@ class Browser
|
||||
*/
|
||||
public function screenshot($name)
|
||||
{
|
||||
$this->driver->takeScreenshot(
|
||||
sprintf('%s/%s.png', rtrim(static::$storeScreenshotsAt, '/'), $name)
|
||||
);
|
||||
$filePath = sprintf('%s/%s.png', rtrim(static::$storeScreenshotsAt, '/'), $name);
|
||||
|
||||
$directoryPath = dirname($filePath);
|
||||
|
||||
if (! is_dir($directoryPath)) {
|
||||
mkdir($directoryPath, 0777, true);
|
||||
}
|
||||
|
||||
$this->driver->takeScreenshot($filePath);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -257,10 +368,9 @@ class Browser
|
||||
if (in_array($this->driver->getCapabilities()->getBrowserName(), static::$supportsRemoteLogs)) {
|
||||
$console = $this->driver->manage()->getLog('browser');
|
||||
|
||||
if (!empty($console)) {
|
||||
if (! empty($console)) {
|
||||
file_put_contents(
|
||||
sprintf('%s/%s.log', rtrim(static::$storeConsoleLogAt, '/'), $name)
|
||||
, json_encode($console, JSON_PRETTY_PRINT)
|
||||
sprintf('%s/%s.log', rtrim(static::$storeConsoleLogAt, '/'), $name), json_encode($console, JSON_PRETTY_PRINT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -269,9 +379,29 @@ class Browser
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a specified frame in the browser.
|
||||
* Store a snapshot of the page's current source code with the given name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function storeSource($name)
|
||||
{
|
||||
$source = $this->driver->getPageSource();
|
||||
|
||||
if (! empty($source)) {
|
||||
file_put_contents(
|
||||
sprintf('%s/%s.txt', rtrim(static::$storeSourceAt, '/'), $name), $source
|
||||
);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a specified frame in the browser and execute the given callback.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function withinFrame($selector, Closure $callback)
|
||||
@@ -311,7 +441,7 @@ class Browser
|
||||
);
|
||||
|
||||
if ($this->page) {
|
||||
$browser->on($this->page);
|
||||
$browser->onWithoutAssert($this->page);
|
||||
}
|
||||
|
||||
if ($selector instanceof Component) {
|
||||
@@ -355,7 +485,7 @@ class Browser
|
||||
*/
|
||||
public function ensurejQueryIsAvailable()
|
||||
{
|
||||
if ($this->driver->executeScript("return window.jQuery == null")) {
|
||||
if ($this->driver->executeScript('return window.jQuery == null')) {
|
||||
$this->driver->executeScript(file_get_contents(__DIR__.'/../bin/jquery.js'));
|
||||
}
|
||||
}
|
||||
@@ -439,6 +569,8 @@ class Browser
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
|
38
vendor/laravel/dusk/src/Chrome/ChromeProcess.php
vendored
38
vendor/laravel/dusk/src/Chrome/ChromeProcess.php
vendored
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Laravel\Dusk\Chrome;
|
||||
|
||||
use Laravel\Dusk\OperatingSystem;
|
||||
use RuntimeException;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class ChromeProcess
|
||||
@@ -11,7 +11,7 @@ class ChromeProcess
|
||||
/**
|
||||
* The path to the Chromedriver.
|
||||
*
|
||||
* @var String
|
||||
* @var string
|
||||
*/
|
||||
protected $driver;
|
||||
|
||||
@@ -20,6 +20,8 @@ class ChromeProcess
|
||||
*
|
||||
* @param string $driver
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct($driver = null)
|
||||
{
|
||||
@@ -33,37 +35,37 @@ class ChromeProcess
|
||||
/**
|
||||
* Build the process to run Chromedriver.
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \Symfony\Component\Process\Process
|
||||
*/
|
||||
public function toProcess()
|
||||
public function toProcess(array $arguments = [])
|
||||
{
|
||||
if ($this->driver) {
|
||||
return $this->process();
|
||||
return $this->process($arguments);
|
||||
}
|
||||
|
||||
if ($this->onWindows()) {
|
||||
$this->driver = realpath(__DIR__.'/../../bin/chromedriver-win.exe');
|
||||
|
||||
return $this->process();
|
||||
} elseif ($this->onMac()) {
|
||||
$this->driver = realpath(__DIR__.'/../../bin/chromedriver-mac');
|
||||
} else {
|
||||
$this->driver = realpath(__DIR__.'/../../bin/chromedriver-linux');
|
||||
}
|
||||
|
||||
$this->driver = $this->onMac()
|
||||
? realpath(__DIR__.'/../../bin/chromedriver-mac')
|
||||
: realpath(__DIR__.'/../../bin/chromedriver-linux');
|
||||
|
||||
return $this->process();
|
||||
return $this->process($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Chromedriver with Symfony Process.
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \Symfony\Component\Process\Process
|
||||
*/
|
||||
protected function process()
|
||||
protected function process(array $arguments = [])
|
||||
{
|
||||
return (new Process(
|
||||
[realpath($this->driver)], null, $this->chromeEnvironment()
|
||||
));
|
||||
return new Process(
|
||||
array_merge([realpath($this->driver)], $arguments), null, $this->chromeEnvironment()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +79,7 @@ class ChromeProcess
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['DISPLAY' => ':0'];
|
||||
return ['DISPLAY' => $_ENV['DISPLAY'] ?? ':0'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +89,7 @@ class ChromeProcess
|
||||
*/
|
||||
protected function onWindows()
|
||||
{
|
||||
return PHP_OS === 'WINNT' || Str::contains(php_uname(), 'Microsoft');
|
||||
return OperatingSystem::onWindows();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,6 +99,6 @@ class ChromeProcess
|
||||
*/
|
||||
protected function onMac()
|
||||
{
|
||||
return PHP_OS === 'Darwin';
|
||||
return OperatingSystem::onMac();
|
||||
}
|
||||
}
|
||||
|
@@ -21,13 +21,14 @@ trait SupportsChrome
|
||||
/**
|
||||
* Start the Chromedriver process.
|
||||
*
|
||||
* @throws \RuntimeException if the driver file path doesn't exist.
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function startChromeDriver()
|
||||
public static function startChromeDriver(array $arguments = [])
|
||||
{
|
||||
static::$chromeProcess = static::buildChromeProcess();
|
||||
static::$chromeProcess = static::buildChromeProcess($arguments);
|
||||
|
||||
static::$chromeProcess->start();
|
||||
|
||||
@@ -51,13 +52,14 @@ trait SupportsChrome
|
||||
/**
|
||||
* Build the process to run the Chromedriver.
|
||||
*
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \Symfony\Component\Process\Process
|
||||
* @throws \RuntimeException if the driver file path doesn't exist.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected static function buildChromeProcess()
|
||||
protected static function buildChromeProcess(array $arguments = [])
|
||||
{
|
||||
return (new ChromeProcess(static::$chromeDriver))->toProcess();
|
||||
return (new ChromeProcess(static::$chromeDriver))->toProcess($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -21,7 +21,7 @@ trait InteractsWithAuthentication
|
||||
* Log into the application using a given user ID or email.
|
||||
*
|
||||
* @param object|string $userId
|
||||
* @param string $guard
|
||||
* @param string $guard
|
||||
* @return $this
|
||||
*/
|
||||
public function loginAs($userId, $guard = null)
|
||||
|
@@ -17,12 +17,12 @@ trait InteractsWithCookies
|
||||
*/
|
||||
public function cookie($name, $value = null, $expiry = null, array $options = [])
|
||||
{
|
||||
if ($value) {
|
||||
if (! is_null($value)) {
|
||||
return $this->addCookie($name, $value, $expiry, $options);
|
||||
}
|
||||
|
||||
if ($cookie = $this->driver->manage()->getCookieNamed($name)) {
|
||||
return decrypt(rawurldecode($cookie['value']));
|
||||
return decrypt(rawurldecode($cookie['value']), $unserialize = false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ trait InteractsWithCookies
|
||||
*/
|
||||
public function plainCookie($name, $value = null, $expiry = null, array $options = [])
|
||||
{
|
||||
if ($value) {
|
||||
if (! is_null($value)) {
|
||||
return $this->addCookie($name, $value, $expiry, $options, false);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ trait InteractsWithCookies
|
||||
public function addCookie($name, $value, $expiry = null, array $options = [], $encrypt = true)
|
||||
{
|
||||
if ($encrypt) {
|
||||
$value = encrypt($value);
|
||||
$value = encrypt($value, $serialize = false);
|
||||
}
|
||||
|
||||
if ($expiry instanceof DateTimeInterface) {
|
||||
|
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Facebook\WebDriver\Interactions\WebDriverActions;
|
||||
use Facebook\WebDriver\Remote\LocalFileDetector;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Facebook\WebDriver\WebDriverKeys;
|
||||
use Facebook\WebDriver\Remote\LocalFileDetector;
|
||||
use Facebook\WebDriver\Interactions\WebDriverActions;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait InteractsWithElements
|
||||
{
|
||||
@@ -39,11 +39,11 @@ trait InteractsWithElements
|
||||
* @param string $element
|
||||
* @return $this
|
||||
*/
|
||||
public function clickLink($link, $element = "a")
|
||||
public function clickLink($link, $element = 'a')
|
||||
{
|
||||
$this->ensurejQueryIsAvailable();
|
||||
|
||||
$selector = addslashes(trim($this->resolver->format("{$element}:contains({$link})")));
|
||||
$selector = addslashes(trim($this->resolver->format("{$element}:contains({$link}):visible")));
|
||||
|
||||
$this->driver->executeScript("jQuery.find(\"{$selector}\")[0].click();");
|
||||
|
||||
@@ -66,7 +66,7 @@ trait InteractsWithElements
|
||||
$selector = $this->resolver->format($selector);
|
||||
|
||||
$this->driver->executeScript(
|
||||
"document.querySelector('{$selector}').value = '{$value}';"
|
||||
'document.querySelector('.json_encode($selector).').value = '.json_encode($value).';'
|
||||
);
|
||||
|
||||
return $this;
|
||||
@@ -144,6 +144,21 @@ trait InteractsWithElements
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type the given value in the given field slowly.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param int $pause
|
||||
* @return $this
|
||||
*/
|
||||
public function typeSlowly($field, $value, $pause = 100)
|
||||
{
|
||||
$this->clear($field)->appendSlowly($field, $value, $pause);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type the given value in the given field without clearing it.
|
||||
*
|
||||
@@ -158,6 +173,23 @@ trait InteractsWithElements
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type the given value in the given field slowly without clearing it.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param int $pause
|
||||
* @return $this
|
||||
*/
|
||||
public function appendSlowly($field, $value, $pause = 100)
|
||||
{
|
||||
foreach (str_split($value) as $char) {
|
||||
$this->append($field, $char)->pause($pause);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the given field.
|
||||
*
|
||||
@@ -182,11 +214,15 @@ trait InteractsWithElements
|
||||
{
|
||||
$element = $this->resolver->resolveForSelection($field);
|
||||
|
||||
$options = $element->findElements(WebDriverBy::tagName('option'));
|
||||
$options = $element->findElements(WebDriverBy::cssSelector('option:not([disabled])'));
|
||||
|
||||
if (is_null($value)) {
|
||||
$options[array_rand($options)]->click();
|
||||
} else {
|
||||
if (is_bool($value)) {
|
||||
$value = $value ? '1' : '0';
|
||||
}
|
||||
|
||||
foreach ($options as $option) {
|
||||
if ((string) $option->getAttribute('value') === (string) $value) {
|
||||
$option->click();
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Facebook\WebDriver\Interactions\WebDriverActions;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
|
||||
trait InteractsWithMouse
|
||||
{
|
||||
@@ -54,6 +55,21 @@ trait InteractsWithMouse
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the element at the given XPath expression.
|
||||
*
|
||||
* @param string $selector
|
||||
* @return $this
|
||||
*/
|
||||
public function clickAtXPath($expression)
|
||||
{
|
||||
$this->driver
|
||||
->findElement(WebDriverBy::xpath($expression))
|
||||
->click();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a mouse click and hold the mouse button down.
|
||||
*
|
||||
|
378
vendor/laravel/dusk/src/Concerns/MakesAssertions.php
vendored
378
vendor/laravel/dusk/src/Concerns/MakesAssertions.php
vendored
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Facebook\WebDriver\Exception\NoSuchElementException;
|
||||
use Facebook\WebDriver\Remote\RemoteWebElement;
|
||||
use Illuminate\Support\Str;
|
||||
use PHPUnit\Framework\Assert as PHPUnit;
|
||||
use Facebook\WebDriver\Remote\RemoteWebElement;
|
||||
use Facebook\WebDriver\Exception\NoSuchElementException;
|
||||
|
||||
trait MakesAssertions
|
||||
{
|
||||
@@ -41,233 +41,6 @@ trait MakesAssertions
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL matches the given URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function assertUrlIs($url)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($url, '/'));
|
||||
|
||||
$segments = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
$currentUrl = sprintf(
|
||||
'%s://%s%s%s',
|
||||
$segments['scheme'],
|
||||
$segments['host'],
|
||||
array_get($segments, 'port', '') ? ':'.$segments['port'] : '',
|
||||
array_get($segments, 'path', '')
|
||||
);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $currentUrl,
|
||||
"Actual URL [{$this->driver->getCurrentURL()}] does not equal expected URL [{$url}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given pattern.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIs($path)
|
||||
{
|
||||
$pattern = preg_quote($path, '/');
|
||||
|
||||
$pattern = str_replace('\*', '.*', $pattern);
|
||||
|
||||
$actualPath = parse_url($this->driver->getCurrentURL())['path'];
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actualPath,
|
||||
"Actual path [{$actualPath}] does not equal expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path begins with given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathBeginsWith($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL())['path'];
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$path, $actualPath,
|
||||
"Actual path [{$actualPath}] does not begin with expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path does not match the given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIsNot($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL())['path'];
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$path, $actualPath,
|
||||
"Path [{$path}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment matches the given pattern.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIs($fragment)
|
||||
{
|
||||
$pattern = preg_quote($fragment, '/');
|
||||
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.str_replace('\*', '.*', $pattern).'$/u', $actualFragment,
|
||||
"Actual fragment [{$actualFragment}] does not equal expected fragment [{$fragment}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment begins with given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentBeginsWith($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$fragment, $actualFragment,
|
||||
"Actual fragment [$actualFragment] does not begin with expected fragment [$fragment]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment does not match the given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIsNot($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$fragment, $actualFragment,
|
||||
"Fragment [{$fragment}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function assertRouteIs($route, $parameters = [])
|
||||
{
|
||||
return $this->assertPathIs(route($route, $parameters, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a query string parameter is present and has a given value.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringHas($name, $value = null)
|
||||
{
|
||||
$output = $this->assertHasQueryStringParameter($name);
|
||||
|
||||
if (is_null($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
PHPUnit::assertEquals(
|
||||
$value, $output[$name],
|
||||
"Query string parameter [{$name}] had value [{$output[$name]}], but expected [{$value}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is missing.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringMissing($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
if (! array_key_exists('query', $parsedUrl)) {
|
||||
PHPUnit::assertTrue(true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayNotHasKey(
|
||||
$name, $output,
|
||||
"Found unexpected query string parameter [{$name}] in [".$this->driver->getCurrentURL()."]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is present.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function assertHasQueryStringParameter($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
'query', $parsedUrl,
|
||||
"Did not see expected query string in [".$this->driver->getCurrentURL()."]."
|
||||
);
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
$name, $output,
|
||||
"Did not see expected query string parameter [{$name}] in [".$this->driver->getCurrentURL()."]."
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given cookie is present.
|
||||
*
|
||||
@@ -432,8 +205,8 @@ trait MakesAssertions
|
||||
*/
|
||||
public function assertSourceHas($code)
|
||||
{
|
||||
PHPUnit::assertContains(
|
||||
$code, $this->driver->getPageSource(),
|
||||
PHPUnit::assertTrue(
|
||||
Str::contains($this->driver->getPageSource(), $code),
|
||||
"Did not find expected source code [{$code}]"
|
||||
);
|
||||
|
||||
@@ -448,8 +221,8 @@ trait MakesAssertions
|
||||
*/
|
||||
public function assertSourceMissing($code)
|
||||
{
|
||||
PHPUnit::assertNotContains(
|
||||
$code, $this->driver->getPageSource(),
|
||||
PHPUnit::assertFalse(
|
||||
Str::contains($this->driver->getPageSource(), $code),
|
||||
"Found unexpected source code [{$code}]"
|
||||
);
|
||||
|
||||
@@ -682,8 +455,8 @@ JS;
|
||||
/**
|
||||
* Assert that the given array of values are available to be selected.
|
||||
*
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectHasOptions($field, array $values)
|
||||
@@ -696,7 +469,7 @@ JS;
|
||||
|
||||
PHPUnit::assertCount(
|
||||
count($values), $options,
|
||||
"Expected options [".implode(',', $values)."] for selection field [{$field}] to be available."
|
||||
'Expected options ['.implode(',', $values)."] for selection field [{$field}] to be available."
|
||||
);
|
||||
|
||||
return $this;
|
||||
@@ -705,15 +478,15 @@ JS;
|
||||
/**
|
||||
* Assert that the given array of values are not available to be selected.
|
||||
*
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectMissingOptions($field, array $values)
|
||||
{
|
||||
PHPUnit::assertCount(
|
||||
0, $this->resolver->resolveSelectOptions($field, $values),
|
||||
"Unexpected options [".implode(',', $values)."] for selection field [{$field}]."
|
||||
'Unexpected options ['.implode(',', $values)."] for selection field [{$field}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
@@ -722,8 +495,8 @@ JS;
|
||||
/**
|
||||
* Assert that the given value is available to be selected on the given field.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectHasOption($field, $value)
|
||||
@@ -734,8 +507,8 @@ JS;
|
||||
/**
|
||||
* Assert that the given value is not available to be selected on the given field.
|
||||
*
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSelectMissingOption($field, $value)
|
||||
@@ -752,9 +525,11 @@ JS;
|
||||
*/
|
||||
public function selected($field, $value)
|
||||
{
|
||||
$element = $this->resolver->resolveForSelection($field);
|
||||
$options = $this->resolver->resolveSelectOptions($field, (array) $value);
|
||||
|
||||
return (string) $element->getAttribute('value') === (string) $value;
|
||||
return collect($options)->contains(function (RemoteWebElement $option) {
|
||||
return $option->isSelected();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -773,6 +548,59 @@ JS;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element at the given selector has the given attribute value.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertAttribute($selector, $attribute, $value)
|
||||
{
|
||||
$fullSelector = $this->resolver->format($selector);
|
||||
|
||||
$actual = $this->resolver->findOrFail($selector)->getAttribute($attribute);
|
||||
|
||||
PHPUnit::assertNotNull(
|
||||
$actual,
|
||||
"Did not see expected attribute [{$attribute}] within element [{$fullSelector}]."
|
||||
);
|
||||
|
||||
PHPUnit::assertEquals(
|
||||
$value, $actual,
|
||||
"Expected '$attribute' attribute [{$value}] does not equal actual value [$actual]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element at the given selector has the given data attribute value.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertDataAttribute($selector, $attribute, $value)
|
||||
{
|
||||
return $this->assertAttribute($selector, 'data-'.$attribute, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element at the given selector has the given aria attribute value.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertAriaAttribute($selector, $attribute, $value)
|
||||
{
|
||||
return $this->assertAttribute($selector, 'aria-'.$attribute, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the element with the given selector is visible.
|
||||
*
|
||||
@@ -854,7 +682,8 @@ JS;
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertEnabled($field) {
|
||||
public function assertEnabled($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertTrue(
|
||||
@@ -871,7 +700,8 @@ JS;
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertDisabled($field) {
|
||||
public function assertDisabled($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertFalse(
|
||||
@@ -882,13 +712,50 @@ JS;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given button is enabled.
|
||||
*
|
||||
* @param string $button
|
||||
* @return $this
|
||||
*/
|
||||
public function assertButtonEnabled($button)
|
||||
{
|
||||
$element = $this->resolver->resolveForButtonPress($button);
|
||||
|
||||
PHPUnit::assertTrue(
|
||||
$element->isEnabled(),
|
||||
"Expected button [{$button}] to be enabled, but it wasn't."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given button is disabled.
|
||||
*
|
||||
* @param string $button
|
||||
* @return $this
|
||||
*/
|
||||
public function assertButtonDisabled($button)
|
||||
{
|
||||
$element = $this->resolver->resolveForButtonPress($button);
|
||||
|
||||
PHPUnit::assertFalse(
|
||||
$element->isEnabled(),
|
||||
"Expected button [{$button}] to be disabled, but it wasn't."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given field is focused.
|
||||
*
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFocused($field) {
|
||||
public function assertFocused($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertTrue(
|
||||
@@ -905,7 +772,8 @@ JS;
|
||||
* @param string $field
|
||||
* @return $this
|
||||
*/
|
||||
public function assertNotFocused($field) {
|
||||
public function assertNotFocused($field)
|
||||
{
|
||||
$element = $this->resolver->resolveForField($field);
|
||||
|
||||
PHPUnit::assertFalse(
|
||||
@@ -958,7 +826,10 @@ JS;
|
||||
*/
|
||||
public function assertVueContains($key, $value, $componentSelector = null)
|
||||
{
|
||||
PHPUnit::assertContains($value, $this->vueAttribute($componentSelector, $key));
|
||||
$attribute = $this->vueAttribute($componentSelector, $key);
|
||||
|
||||
PHPUnit::assertIsArray($attribute, "The attribute for key [$key] is not an array.");
|
||||
PHPUnit::assertContains($value, $attribute);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -974,7 +845,10 @@ JS;
|
||||
*/
|
||||
public function assertVueDoesNotContain($key, $value, $componentSelector = null)
|
||||
{
|
||||
PHPUnit::assertNotContains($value, $this->vueAttribute($componentSelector, $key));
|
||||
$attribute = $this->vueAttribute($componentSelector, $key);
|
||||
|
||||
PHPUnit::assertIsArray($attribute, "The attribute for key [$key] is not an array.");
|
||||
PHPUnit::assertNotContains($value, $attribute);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -991,7 +865,7 @@ JS;
|
||||
$fullSelector = $this->resolver->format($componentSelector);
|
||||
|
||||
return $this->driver->executeScript(
|
||||
"return document.querySelector('" . $fullSelector . "').__vue__." . $key
|
||||
"return document.querySelector('".$fullSelector."').__vue__.".$key
|
||||
);
|
||||
}
|
||||
}
|
||||
|
353
vendor/laravel/dusk/src/Concerns/MakesUrlAssertions.php
vendored
Normal file
353
vendor/laravel/dusk/src/Concerns/MakesUrlAssertions.php
vendored
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use PHPUnit\Framework\Assert as PHPUnit;
|
||||
|
||||
trait MakesUrlAssertions
|
||||
{
|
||||
/**
|
||||
* Assert that the current URL matches the given URL.
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function assertUrlIs($url)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($url, '/'));
|
||||
|
||||
$segments = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
$currentUrl = sprintf(
|
||||
'%s://%s%s%s',
|
||||
$segments['scheme'],
|
||||
$segments['host'],
|
||||
Arr::get($segments, 'port', '') ? ':'.$segments['port'] : '',
|
||||
Arr::get($segments, 'path', '')
|
||||
);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $currentUrl,
|
||||
"Actual URL [{$this->driver->getCurrentURL()}] does not equal expected URL [{$url}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current scheme matches the given scheme.
|
||||
*
|
||||
* @param string $scheme
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSchemeIs($scheme)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($scheme, '/'));
|
||||
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_SCHEME) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actual,
|
||||
"Actual scheme [{$actual}] does not equal expected scheme [{$pattern}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current scheme does not match the given scheme.
|
||||
*
|
||||
* @param string $scheme
|
||||
* @return $this
|
||||
*/
|
||||
public function assertSchemeIsNot($scheme)
|
||||
{
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_SCHEME) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$scheme, $actual,
|
||||
"Scheme [{$scheme}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current host matches the given host.
|
||||
*
|
||||
* @param string $host
|
||||
* @return $this
|
||||
*/
|
||||
public function assertHostIs($host)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($host, '/'));
|
||||
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_HOST) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actual,
|
||||
"Actual host [{$actual}] does not equal expected host [{$pattern}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current host does not match the given host.
|
||||
*
|
||||
* @param string $host
|
||||
* @return $this
|
||||
*/
|
||||
public function assertHostIsNot($host)
|
||||
{
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_HOST) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$host, $actual,
|
||||
"Host [{$host}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current port matches the given port.
|
||||
*
|
||||
* @param string $port
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPortIs($port)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($port, '/'));
|
||||
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_PORT) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actual,
|
||||
"Actual port [{$actual}] does not equal expected port [{$pattern}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current host does not match the given host.
|
||||
*
|
||||
* @param string $port
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPortIsNot($port)
|
||||
{
|
||||
$actual = parse_url($this->driver->getCurrentURL(), PHP_URL_PORT) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$port, $actual,
|
||||
"Port [{$port}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given pattern.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIs($path)
|
||||
{
|
||||
$pattern = str_replace('\*', '.*', preg_quote($path, '/'));
|
||||
|
||||
$actualPath = parse_url($this->driver->getCurrentURL(), PHP_URL_PATH) ?? '';
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.$pattern.'$/u', $actualPath,
|
||||
"Actual path [{$actualPath}] does not equal expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path begins with given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathBeginsWith($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL(), PHP_URL_PATH) ?? '';
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$path, $actualPath,
|
||||
"Actual path [{$actualPath}] does not begin with expected path [{$path}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path does not match the given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function assertPathIsNot($path)
|
||||
{
|
||||
$actualPath = parse_url($this->driver->getCurrentURL(), PHP_URL_PATH) ?? '';
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$path, $actualPath,
|
||||
"Path [{$path}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment matches the given pattern.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIs($fragment)
|
||||
{
|
||||
$pattern = preg_quote($fragment, '/');
|
||||
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertRegExp(
|
||||
'/^'.str_replace('\*', '.*', $pattern).'$/u', $actualFragment,
|
||||
"Actual fragment [{$actualFragment}] does not equal expected fragment [{$fragment}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment begins with given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentBeginsWith($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertStringStartsWith(
|
||||
$fragment, $actualFragment,
|
||||
"Actual fragment [$actualFragment] does not begin with expected fragment [$fragment]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL fragment does not match the given fragment.
|
||||
*
|
||||
* @param string $fragment
|
||||
* @return $this
|
||||
*/
|
||||
public function assertFragmentIsNot($fragment)
|
||||
{
|
||||
$actualFragment = (string) parse_url($this->driver->executeScript('return window.location.href;'), PHP_URL_FRAGMENT);
|
||||
|
||||
PHPUnit::assertNotEquals(
|
||||
$fragment, $actualFragment,
|
||||
"Fragment [{$fragment}] should not equal the actual value."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current URL path matches the given route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function assertRouteIs($route, $parameters = [])
|
||||
{
|
||||
return $this->assertPathIs(route($route, $parameters, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a query string parameter is present and has a given value.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringHas($name, $value = null)
|
||||
{
|
||||
$output = $this->assertHasQueryStringParameter($name);
|
||||
|
||||
if (is_null($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$parsedOutputName = is_array($output[$name]) ? implode(',', $output[$name]) : $output[$name];
|
||||
|
||||
$parsedValue = is_array($value) ? implode(',', $value) : $value;
|
||||
|
||||
PHPUnit::assertEquals(
|
||||
$value, $output[$name],
|
||||
"Query string parameter [{$name}] had value [{$parsedOutputName}], but expected [{$parsedValue}]."
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is missing.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function assertQueryStringMissing($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
if (! array_key_exists('query', $parsedUrl)) {
|
||||
PHPUnit::assertTrue(true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayNotHasKey(
|
||||
$name, $output,
|
||||
"Found unexpected query string parameter [{$name}] in [".$this->driver->getCurrentURL().'].'
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given query string parameter is present.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function assertHasQueryStringParameter($name)
|
||||
{
|
||||
$parsedUrl = parse_url($this->driver->getCurrentURL());
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
'query', $parsedUrl,
|
||||
'Did not see expected query string in ['.$this->driver->getCurrentURL().'].'
|
||||
);
|
||||
|
||||
parse_str($parsedUrl['query'], $output);
|
||||
|
||||
PHPUnit::assertArrayHasKey(
|
||||
$name, $output,
|
||||
"Did not see expected query string parameter [{$name}] in [".$this->driver->getCurrentURL().'].'
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
@@ -4,10 +4,10 @@ namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use ReflectionFunction;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Support\Collection;
|
||||
use Laravel\Dusk\Browser;
|
||||
use ReflectionFunction;
|
||||
use Throwable;
|
||||
|
||||
trait ProvidesBrowser
|
||||
{
|
||||
@@ -56,6 +56,7 @@ trait ProvidesBrowser
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return \Laravel\Dusk\Browser|void
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
@@ -85,6 +86,7 @@ trait ProvidesBrowser
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return array
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function createBrowsersFor(Closure $callback)
|
||||
@@ -118,6 +120,7 @@ trait ProvidesBrowser
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return int
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function browsersNeededFor(Closure $callback)
|
||||
@@ -134,7 +137,11 @@ trait ProvidesBrowser
|
||||
protected function captureFailuresFor($browsers)
|
||||
{
|
||||
$browsers->each(function ($browser, $key) {
|
||||
$name = str_replace('\\', '_', get_class($this)).'_'.$this->getName(false);
|
||||
if (property_exists($browser, 'fitOnFailure') && $browser->fitOnFailure) {
|
||||
$browser->fitContent();
|
||||
}
|
||||
|
||||
$name = $this->getCallerName();
|
||||
|
||||
$browser->screenshot('failure-'.$name.'-'.$key);
|
||||
});
|
||||
@@ -149,7 +156,7 @@ trait ProvidesBrowser
|
||||
protected function storeConsoleLogsFor($browsers)
|
||||
{
|
||||
$browsers->each(function ($browser, $key) {
|
||||
$name = str_replace('\\', '_', get_class($this)).'_'.$this->getName(false);
|
||||
$name = $this->getCallerName();
|
||||
|
||||
$browser->storeConsoleLog($name.'-'.$key);
|
||||
});
|
||||
@@ -184,6 +191,7 @@ trait ProvidesBrowser
|
||||
* Create the remote web driver instance.
|
||||
*
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebDriver
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function createWebDriver()
|
||||
@@ -193,6 +201,16 @@ trait ProvidesBrowser
|
||||
}, 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the browser caller name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCallerName()
|
||||
{
|
||||
return str_replace('\\', '_', get_class($this)).'_'.$this->getName(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the RemoteWebDriver instance.
|
||||
*
|
||||
|
@@ -2,13 +2,14 @@
|
||||
|
||||
namespace Laravel\Dusk\Concerns;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
use Facebook\WebDriver\Exception\TimeOutException;
|
||||
use Facebook\WebDriver\Exception\NoSuchElementException;
|
||||
use Facebook\WebDriver\Exception\TimeOutException;
|
||||
use Facebook\WebDriver\WebDriverExpectedCondition;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait WaitsForElements
|
||||
{
|
||||
@@ -16,9 +17,10 @@ trait WaitsForElements
|
||||
* Execute the given callback in a scoped browser once the selector is available.
|
||||
*
|
||||
* @param string $selector
|
||||
* @param Closure $callback
|
||||
* @param \Closure $callback
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function whenAvailable($selector, Closure $callback, $seconds = null)
|
||||
@@ -32,13 +34,16 @@ trait WaitsForElements
|
||||
* @param string $selector
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitFor($selector, $seconds = null)
|
||||
{
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for selector', $selector);
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($selector) {
|
||||
return $this->resolver->findOrFail($selector)->isDisplayed();
|
||||
}, "Waited %s seconds for selector [{$selector}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,10 +52,13 @@ trait WaitsForElements
|
||||
* @param string $selector
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUntilMissing($selector, $seconds = null)
|
||||
{
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for removal of selector', $selector);
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($selector) {
|
||||
try {
|
||||
$missing = ! $this->resolver->findOrFail($selector)->isDisplayed();
|
||||
@@ -59,22 +67,47 @@ trait WaitsForElements
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}, "Waited %s seconds for removal of selector [{$selector}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the given text to be removed.
|
||||
*
|
||||
* @param string $text
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUntilMissingText($text, $seconds = null)
|
||||
{
|
||||
$text = Arr::wrap($text);
|
||||
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for removal of text', implode("', '", $text));
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($text) {
|
||||
return ! Str::contains($this->resolver->findOrFail('')->getText(), $text);
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the given text to be visible.
|
||||
*
|
||||
* @param string $text
|
||||
* @param array|string $text
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForText($text, $seconds = null)
|
||||
{
|
||||
$text = Arr::wrap($text);
|
||||
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for text', implode("', '", $text));
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($text) {
|
||||
return Str::contains($this->resolver->findOrFail('')->getText(), $text);
|
||||
}, "Waited %s seconds for text [{$text}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,13 +116,16 @@ trait WaitsForElements
|
||||
* @param string $link
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForLink($link, $seconds = null)
|
||||
{
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for link', $link);
|
||||
|
||||
return $this->waitUsing($seconds, 100, function () use ($link) {
|
||||
return $this->seeLink($link);
|
||||
}, "Waited %s seconds for link [{$link}].");
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,11 +134,14 @@ trait WaitsForElements
|
||||
* @param string $path
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForLocation($path, $seconds = null)
|
||||
{
|
||||
return $this->waitUntil("window.location.pathname == '{$path}'", $seconds, "Waited %s seconds for location [{$path}].");
|
||||
$message = $this->formatTimeOutMessage('Waited %s seconds for location', $path);
|
||||
|
||||
return $this->waitUntil("window.location.pathname == '{$path}'", $seconds, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,6 +151,7 @@ trait WaitsForElements
|
||||
* @param array $parameters
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForRoute($route, $parameters = [], $seconds = null)
|
||||
@@ -126,6 +166,7 @@ trait WaitsForElements
|
||||
* @param int $seconds
|
||||
* @param string $message
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUntil($script, $seconds = null, $message = null)
|
||||
@@ -143,6 +184,40 @@ trait WaitsForElements
|
||||
}, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the Vue component's attribute at the given key has the given value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param string|null $componentSelector
|
||||
* @return $this
|
||||
*/
|
||||
public function waitUntilVue($key, $value, $componentSelector = null, $seconds = null)
|
||||
{
|
||||
$this->waitUsing($seconds, 100, function () use ($key, $value, $componentSelector) {
|
||||
return $value == $this->vueAttribute($componentSelector, $key);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the Vue component's attribute at the given key does not have the given value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param string|null $componentSelector
|
||||
* @return $this
|
||||
*/
|
||||
public function waitUntilVueIsNot($key, $value, $componentSelector = null, $seconds = null)
|
||||
{
|
||||
$this->waitUsing($seconds, 100, function () use ($key, $value, $componentSelector) {
|
||||
return $value != $this->vueAttribute($componentSelector, $key);
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a JavaScript dialog to open.
|
||||
*
|
||||
@@ -163,14 +238,15 @@ trait WaitsForElements
|
||||
/**
|
||||
* Wait for the current page to reload.
|
||||
*
|
||||
* @param Closure $callback
|
||||
* @param \Closure $callback
|
||||
* @param int $seconds
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitForReload($callback = null, $seconds = null)
|
||||
{
|
||||
$token = str_random();
|
||||
$token = Str::random();
|
||||
|
||||
$this->driver->executeScript("window['{$token}'] = {};");
|
||||
|
||||
@@ -188,9 +264,10 @@ trait WaitsForElements
|
||||
*
|
||||
* @param int $seconds
|
||||
* @param int $interval
|
||||
* @param Closure $callback
|
||||
* @param \Closure $callback
|
||||
* @param string|null $message
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Facebook\WebDriver\Exception\TimeOutException
|
||||
*/
|
||||
public function waitUsing($seconds, $interval, Closure $callback, $message = null)
|
||||
@@ -222,4 +299,16 @@ trait WaitsForElements
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare custom TimeOutException message for sprintf().
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $expected
|
||||
* @return string
|
||||
*/
|
||||
protected function formatTimeOutMessage($message, $expected)
|
||||
{
|
||||
return $message.' ['.str_replace('%', '%%', $expected).'].';
|
||||
}
|
||||
}
|
||||
|
251
vendor/laravel/dusk/src/Console/ChromeDriverCommand.php
vendored
Normal file
251
vendor/laravel/dusk/src/Console/ChromeDriverCommand.php
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Laravel\Dusk\OperatingSystem;
|
||||
use ZipArchive;
|
||||
|
||||
/**
|
||||
* @copyright Originally created by Jonas Staudenmeir: https://github.com/staudenmeir/dusk-updater
|
||||
*/
|
||||
class ChromeDriverCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'dusk:chrome-driver {version?}
|
||||
{--all : Install a ChromeDriver binary for every OS}
|
||||
{--proxy= : The proxy to download the binary through (example: "tcp://127.0.0.1:9000")}
|
||||
{--ssl-no-verify : Bypass SSL certificate verification when installing through a proxy}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Install the ChromeDriver binary';
|
||||
|
||||
/**
|
||||
* URL to the latest stable release version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $latestVersionUrl = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE';
|
||||
|
||||
/**
|
||||
* URL to the latest release version for a major Chrome version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $versionUrl = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE_%d';
|
||||
|
||||
/**
|
||||
* URL to the ChromeDriver download.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $downloadUrl = 'https://chromedriver.storage.googleapis.com/%s/chromedriver_%s.zip';
|
||||
|
||||
/**
|
||||
* Download slugs for the available operating systems.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $slugs = [
|
||||
'linux' => 'linux64',
|
||||
'mac' => 'mac64',
|
||||
'win' => 'win32',
|
||||
];
|
||||
|
||||
/**
|
||||
* The legacy versions for the ChromeDriver.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $legacyVersions = [
|
||||
43 => '2.20',
|
||||
44 => '2.20',
|
||||
45 => '2.20',
|
||||
46 => '2.21',
|
||||
47 => '2.21',
|
||||
48 => '2.21',
|
||||
49 => '2.22',
|
||||
50 => '2.22',
|
||||
51 => '2.23',
|
||||
52 => '2.24',
|
||||
53 => '2.26',
|
||||
54 => '2.27',
|
||||
55 => '2.28',
|
||||
56 => '2.29',
|
||||
57 => '2.29',
|
||||
58 => '2.31',
|
||||
59 => '2.32',
|
||||
60 => '2.33',
|
||||
61 => '2.34',
|
||||
62 => '2.35',
|
||||
63 => '2.36',
|
||||
64 => '2.37',
|
||||
65 => '2.38',
|
||||
66 => '2.40',
|
||||
67 => '2.41',
|
||||
68 => '2.42',
|
||||
69 => '2.44',
|
||||
];
|
||||
|
||||
/**
|
||||
* Path to the bin directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $directory = __DIR__.'/../../bin/';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$version = $this->version();
|
||||
|
||||
$all = $this->option('all');
|
||||
|
||||
$currentOS = OperatingSystem::id();
|
||||
|
||||
foreach ($this->slugs as $os => $slug) {
|
||||
if ($all || ($os === $currentOS)) {
|
||||
$archive = $this->download($version, $slug);
|
||||
|
||||
$binary = $this->extract($archive);
|
||||
|
||||
$this->rename($binary, $os);
|
||||
}
|
||||
}
|
||||
|
||||
$message = 'ChromeDriver %s successfully installed for version %s.';
|
||||
|
||||
$this->info(sprintf($message, $all ? 'binaries' : 'binary', $version));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the desired ChromeDriver version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function version()
|
||||
{
|
||||
$version = $this->argument('version');
|
||||
|
||||
if (! $version) {
|
||||
return $this->latestVersion();
|
||||
}
|
||||
|
||||
if (! ctype_digit($version)) {
|
||||
return $version;
|
||||
}
|
||||
|
||||
$version = (int) $version;
|
||||
|
||||
if ($version < 70) {
|
||||
return $this->legacyVersions[$version];
|
||||
}
|
||||
|
||||
return trim($this->getUrl(
|
||||
sprintf($this->versionUrl, $version)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest stable ChromeDriver version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function latestVersion()
|
||||
{
|
||||
return trim(file_get_contents($this->latestVersionUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the ChromeDriver archive.
|
||||
*
|
||||
* @param string $version
|
||||
* @param string $slug
|
||||
* @return string
|
||||
*/
|
||||
protected function download($version, $slug)
|
||||
{
|
||||
$url = sprintf($this->downloadUrl, $version, $slug);
|
||||
|
||||
file_put_contents(
|
||||
$archive = $this->directory.'chromedriver.zip',
|
||||
$this->getUrl($url)
|
||||
);
|
||||
|
||||
return $archive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the ChromeDriver binary from the archive and delete the archive.
|
||||
*
|
||||
* @param string $archive
|
||||
* @return string
|
||||
*/
|
||||
protected function extract($archive)
|
||||
{
|
||||
$zip = new ZipArchive;
|
||||
|
||||
$zip->open($archive);
|
||||
|
||||
$zip->extractTo($this->directory);
|
||||
|
||||
$binary = $zip->getNameIndex(0);
|
||||
|
||||
$zip->close();
|
||||
|
||||
unlink($archive);
|
||||
|
||||
return $binary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename the ChromeDriver binary and make it executable.
|
||||
*
|
||||
* @param string $binary
|
||||
* @param string $os
|
||||
* @return void
|
||||
*/
|
||||
protected function rename($binary, $os)
|
||||
{
|
||||
$newName = str_replace('chromedriver', 'chromedriver-'.$os, $binary);
|
||||
|
||||
rename($this->directory.$binary, $this->directory.$newName);
|
||||
|
||||
chmod($this->directory.$newName, 0755);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contents of a URL using the 'proxy' and 'ssl-no-verify' command options.
|
||||
*
|
||||
* @param string $url
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function getUrl(string $url)
|
||||
{
|
||||
$contextOptions = [];
|
||||
|
||||
if ($this->option('proxy')) {
|
||||
$contextOptions['http'] = ['proxy' => $this->option('proxy'), 'request_fulluri' => true];
|
||||
}
|
||||
|
||||
if ($this->option('ssl-no-verify')) {
|
||||
$contextOptions['ssl'] = ['verify_peer' => false];
|
||||
}
|
||||
|
||||
$streamContext = stream_context_create($contextOptions);
|
||||
|
||||
return file_get_contents($url, false, $streamContext);
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ComponentCommand extends GeneratorCommand
|
||||
{
|
||||
@@ -45,7 +46,7 @@ class ComponentCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace_first($this->rootNamespace(), '', $name);
|
||||
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
|
||||
|
||||
return $this->laravel->basePath().'/tests'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
154
vendor/laravel/dusk/src/Console/DuskCommand.php
vendored
154
vendor/laravel/dusk/src/Console/DuskCommand.php
vendored
@@ -3,11 +3,12 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessSignaledException;
|
||||
use Symfony\Component\Process\Exception\RuntimeException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class DuskCommand extends Command
|
||||
{
|
||||
@@ -28,7 +29,7 @@ class DuskCommand extends Command
|
||||
/**
|
||||
* Indicates if the project has its own PHPUnit configuration.
|
||||
*
|
||||
* @var boolean
|
||||
* @var bool
|
||||
*/
|
||||
protected $hasPhpUnitConfiguration = false;
|
||||
|
||||
@@ -68,9 +69,15 @@ class DuskCommand extends Command
|
||||
$this->output->writeln('Warning: '.$e->getMessage());
|
||||
}
|
||||
|
||||
return $process->run(function ($type, $line) {
|
||||
$this->output->write($line);
|
||||
});
|
||||
try {
|
||||
return $process->run(function ($type, $line) {
|
||||
$this->output->write($line);
|
||||
});
|
||||
} catch (ProcessSignaledException $e) {
|
||||
if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -81,6 +88,10 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function binary()
|
||||
{
|
||||
if ('phpdbg' === PHP_SAPI) {
|
||||
return [PHP_BINARY, '-qrr', 'vendor/phpunit/phpunit/phpunit'];
|
||||
}
|
||||
|
||||
return [PHP_BINARY, 'vendor/phpunit/phpunit/phpunit'];
|
||||
}
|
||||
|
||||
@@ -96,18 +107,28 @@ class DuskCommand extends Command
|
||||
return ! Str::startsWith($option, '--env=');
|
||||
}));
|
||||
|
||||
return array_merge(['-c', base_path('phpunit.dusk.xml')], $options);
|
||||
if (! file_exists($file = base_path('phpunit.dusk.xml'))) {
|
||||
$file = base_path('phpunit.dusk.xml.dist');
|
||||
}
|
||||
|
||||
return array_merge(['-c', $file], $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge the failure screenshots
|
||||
* Purge the failure screenshots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function purgeScreenshots()
|
||||
{
|
||||
$path = base_path('tests/Browser/screenshots');
|
||||
|
||||
if (! is_dir($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = Finder::create()->files()
|
||||
->in(base_path('tests/Browser/screenshots'))
|
||||
->in($path)
|
||||
->name('failure-*');
|
||||
|
||||
foreach ($files as $file) {
|
||||
@@ -122,8 +143,14 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function purgeConsoleLogs()
|
||||
{
|
||||
$path = base_path('tests/Browser/console');
|
||||
|
||||
if (! is_dir($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = Finder::create()->files()
|
||||
->in(base_path('tests/Browser/console'))
|
||||
->in($path)
|
||||
->name('*.log');
|
||||
|
||||
foreach ($files as $file) {
|
||||
@@ -138,6 +165,22 @@ class DuskCommand extends Command
|
||||
* @return mixed
|
||||
*/
|
||||
protected function withDuskEnvironment($callback)
|
||||
{
|
||||
$this->setupDuskEnvironment();
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
$this->teardownDuskEnviroment();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the Dusk environment.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupDuskEnvironment()
|
||||
{
|
||||
if (file_exists(base_path($this->duskFile()))) {
|
||||
if (file_get_contents(base_path('.env')) !== file_get_contents(base_path($this->duskFile()))) {
|
||||
@@ -149,13 +192,7 @@ class DuskCommand extends Command
|
||||
|
||||
$this->writeConfiguration();
|
||||
|
||||
return tap($callback(), function () {
|
||||
$this->removeConfiguration();
|
||||
|
||||
if (file_exists(base_path($this->duskFile())) && file_exists(base_path('.env.backup'))) {
|
||||
$this->restoreEnvironment();
|
||||
}
|
||||
});
|
||||
$this->setupSignalHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,18 +207,6 @@ class DuskCommand extends Command
|
||||
copy(base_path($this->duskFile()), base_path('.env'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the backed-up environment file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function restoreEnvironment()
|
||||
{
|
||||
copy(base_path('.env.backup'), base_path('.env'));
|
||||
|
||||
unlink(base_path('.env.backup'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the current environment variables.
|
||||
*
|
||||
@@ -189,7 +214,21 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function refreshEnvironment()
|
||||
{
|
||||
(new Dotenv(base_path()))->overload();
|
||||
// BC fix to support Dotenv ^2.2...
|
||||
if (! method_exists(Dotenv::class, 'create')) {
|
||||
(new Dotenv(base_path()))->overload();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// BC fix to support Dotenv ^3.0...
|
||||
if (! method_exists(Dotenv::class, 'createMutable')) {
|
||||
Dotenv::create(base_path())->overload();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Dotenv::createMutable(base_path())->load();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,10 +238,43 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function writeConfiguration()
|
||||
{
|
||||
if (! file_exists($file = base_path('phpunit.dusk.xml'))) {
|
||||
if (! file_exists($file = base_path('phpunit.dusk.xml')) &&
|
||||
! file_exists(base_path('phpunit.dusk.xml.dist'))) {
|
||||
copy(realpath(__DIR__.'/../../stubs/phpunit.xml'), $file);
|
||||
} else {
|
||||
$this->hasPhpUnitConfiguration = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->hasPhpUnitConfiguration = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the SIGINT signal handler for CTRL+C exits.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupSignalHandler()
|
||||
{
|
||||
if (extension_loaded('pcntl')) {
|
||||
pcntl_async_signals(true);
|
||||
|
||||
pcntl_signal(SIGINT, function () {
|
||||
$this->teardownDuskEnviroment();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the original environment.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function teardownDuskEnviroment()
|
||||
{
|
||||
$this->removeConfiguration();
|
||||
|
||||
if (file_exists(base_path($this->duskFile())) && file_exists(base_path('.env.backup'))) {
|
||||
$this->restoreEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +285,23 @@ class DuskCommand extends Command
|
||||
*/
|
||||
protected function removeConfiguration()
|
||||
{
|
||||
if (! $this->hasPhpUnitConfiguration) {
|
||||
unlink(base_path('phpunit.dusk.xml'));
|
||||
if (! $this->hasPhpUnitConfiguration && file_exists($file = base_path('phpunit.dusk.xml'))) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the backed-up environment file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function restoreEnvironment()
|
||||
{
|
||||
copy(base_path('.env.backup'), base_path('.env'));
|
||||
|
||||
unlink(base_path('.env.backup'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the Dusk file for the environment.
|
||||
*
|
||||
|
33
vendor/laravel/dusk/src/Console/DuskFailsCommand.php
vendored
Normal file
33
vendor/laravel/dusk/src/Console/DuskFailsCommand.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
class DuskFailsCommand extends DuskCommand
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'dusk:fails {--without-tty : Disable output to TTY}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the failing Dusk tests from the last run and stop on failure';
|
||||
|
||||
/**
|
||||
* Get the array of arguments for running PHPUnit.
|
||||
*
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function phpunitArguments($options)
|
||||
{
|
||||
return array_unique(array_merge(parent::phpunitArguments($options), [
|
||||
'--cache-result', '--order-by=defects', '--stop-on-failure',
|
||||
]));
|
||||
}
|
||||
}
|
@@ -11,7 +11,9 @@ class InstallCommand extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'dusk:install';
|
||||
protected $signature = 'dusk:install
|
||||
{--proxy= : The proxy to download the binary through (example: "tcp://127.0.0.1:9000")}
|
||||
{--ssl-no-verify : Bypass SSL certificate verification when installing through a proxy}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -20,16 +22,6 @@ class InstallCommand extends Command
|
||||
*/
|
||||
protected $description = 'Install Dusk into the application';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
@@ -67,6 +59,20 @@ class InstallCommand extends Command
|
||||
}
|
||||
|
||||
$this->info('Dusk scaffolding installed successfully.');
|
||||
|
||||
$this->comment('Downloading ChromeDriver binaries...');
|
||||
|
||||
$driverCommandArgs = ['--all' => true];
|
||||
|
||||
if ($this->option('proxy')) {
|
||||
$driverCommandArgs['--proxy'] = $this->option('proxy');
|
||||
}
|
||||
|
||||
if ($this->option('ssl-no-verify')) {
|
||||
$driverCommandArgs['--ssl-no-verify'] = true;
|
||||
}
|
||||
|
||||
$this->call('dusk:chrome-driver', $driverCommandArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MakeCommand extends GeneratorCommand
|
||||
{
|
||||
@@ -45,7 +46,7 @@ class MakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace_first($this->rootNamespace(), '', $name);
|
||||
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
|
||||
|
||||
return $this->laravel->basePath().'/tests'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Console;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PageCommand extends GeneratorCommand
|
||||
{
|
||||
@@ -45,7 +46,7 @@ class PageCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace_first($this->rootNamespace(), '', $name);
|
||||
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
|
||||
|
||||
return $this->laravel->basePath().'/tests'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
4
vendor/laravel/dusk/src/Dusk.php
vendored
4
vendor/laravel/dusk/src/Dusk.php
vendored
@@ -24,6 +24,8 @@ class Dusk
|
||||
*
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected static function duskEnvironment($options)
|
||||
{
|
||||
@@ -36,7 +38,7 @@ class Dusk
|
||||
}
|
||||
|
||||
if (! is_array($options['environments'])) {
|
||||
throw new InvalidArgumentException("Dusk environments must be listed as an array.");
|
||||
throw new InvalidArgumentException('Dusk environments must be listed as an array.');
|
||||
}
|
||||
|
||||
return app()->environment(...$options['environments']);
|
||||
|
36
vendor/laravel/dusk/src/DuskServiceProvider.php
vendored
36
vendor/laravel/dusk/src/DuskServiceProvider.php
vendored
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
@@ -15,41 +14,42 @@ class DuskServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Route::get('/_dusk/login/{userId}/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@login',
|
||||
]);
|
||||
if (! $this->app->environment('production')) {
|
||||
Route::get('/_dusk/login/{userId}/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@login',
|
||||
]);
|
||||
|
||||
Route::get('/_dusk/logout/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@logout',
|
||||
]);
|
||||
Route::get('/_dusk/logout/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@logout',
|
||||
]);
|
||||
|
||||
Route::get('/_dusk/user/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@user',
|
||||
]);
|
||||
Route::get('/_dusk/user/{guard?}', [
|
||||
'middleware' => 'web',
|
||||
'uses' => 'Laravel\Dusk\Http\Controllers\UserController@user',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register any package services.
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
if ($this->app->environment('production')) {
|
||||
throw new Exception('It is unsafe to run Dusk in production.');
|
||||
}
|
||||
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
Console\InstallCommand::class,
|
||||
Console\DuskCommand::class,
|
||||
Console\DuskFailsCommand::class,
|
||||
Console\MakeCommand::class,
|
||||
Console\PageCommand::class,
|
||||
Console\ComponentCommand::class,
|
||||
Console\ChromeDriverCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
45
vendor/laravel/dusk/src/ElementResolver.php
vendored
45
vendor/laravel/dusk/src/ElementResolver.php
vendored
@@ -3,10 +3,10 @@
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class ElementResolver
|
||||
{
|
||||
@@ -43,7 +43,7 @@ class ElementResolver
|
||||
'findButtonBySelector',
|
||||
'findButtonByName',
|
||||
'findButtonByValue',
|
||||
'findButtonByText'
|
||||
'findButtonByText',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -77,6 +77,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForTyping($field)
|
||||
@@ -86,7 +87,7 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[name='{$field}']", "textarea[name='{$field}']"
|
||||
$field, "input[name='{$field}']", "textarea[name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -95,6 +96,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForSelection($field)
|
||||
@@ -104,16 +106,17 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "select[name='{$field}']"
|
||||
$field, "select[name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all the options with the given value on the select field.
|
||||
*
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement[]
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveSelectOptions($field, array $values)
|
||||
@@ -136,7 +139,9 @@ class ElementResolver
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function resolveForRadioSelection($field, $value = null)
|
||||
{
|
||||
@@ -151,16 +156,17 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[type=radio][name='{$field}'][value='{$value}']"
|
||||
$field, "input[type=radio][name='{$field}'][value='{$value}']",
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the element for a given checkbox "field".
|
||||
*
|
||||
* @param string $field
|
||||
* @param string|null $field
|
||||
* @param string $value
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForChecking($field, $value = null)
|
||||
@@ -169,14 +175,18 @@ class ElementResolver
|
||||
return $element;
|
||||
}
|
||||
|
||||
$selector = "input[type=checkbox][name='{$field}']";
|
||||
$selector = 'input[type=checkbox]';
|
||||
|
||||
if (! is_null($field)) {
|
||||
$selector .= "[name='{$field}']";
|
||||
}
|
||||
|
||||
if (! is_null($value)) {
|
||||
$selector .= "[value='{$value}']";
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, $selector
|
||||
$field, $selector,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -185,6 +195,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForAttachment($field)
|
||||
@@ -194,7 +205,7 @@ class ElementResolver
|
||||
}
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[type=file][name='{$field}']"
|
||||
$field, "input[type=file][name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -203,6 +214,7 @@ class ElementResolver
|
||||
*
|
||||
* @param string $field
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function resolveForField($field)
|
||||
@@ -213,7 +225,7 @@ class ElementResolver
|
||||
|
||||
return $this->firstOrFail([
|
||||
$field, "input[name='{$field}']", "textarea[name='{$field}']",
|
||||
"select[name='{$field}']", "button[name='{$field}']"
|
||||
"select[name='{$field}']", "button[name='{$field}']",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -222,6 +234,8 @@ class ElementResolver
|
||||
*
|
||||
* @param string $button
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function resolveForButtonPress($button)
|
||||
{
|
||||
@@ -272,7 +286,7 @@ class ElementResolver
|
||||
*/
|
||||
protected function findButtonByValue($button)
|
||||
{
|
||||
foreach ($this->all("input[type=submit]") as $element) {
|
||||
foreach ($this->all('input[type=submit]') as $element) {
|
||||
if ($element->getAttribute('value') === $button) {
|
||||
return $element;
|
||||
}
|
||||
@@ -327,6 +341,7 @@ class ElementResolver
|
||||
*
|
||||
* @param array $selectors
|
||||
* @return \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function firstOrFail($selectors)
|
||||
@@ -394,7 +409,7 @@ class ElementResolver
|
||||
array_keys($sortedElements), array_values($sortedElements), $originalSelector = $selector
|
||||
);
|
||||
|
||||
if (starts_with($selector, '@') && $selector === $originalSelector) {
|
||||
if (Str::startsWith($selector, '@') && $selector === $originalSelector) {
|
||||
$selector = '[dusk="'.explode('@', $selector)[1].'"]';
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Laravel\Dusk\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserController
|
||||
{
|
||||
@@ -31,6 +32,7 @@ class UserController
|
||||
*
|
||||
* @param string $userId
|
||||
* @param string $guard
|
||||
* @return void
|
||||
*/
|
||||
public function login($userId, $guard = null)
|
||||
{
|
||||
@@ -38,7 +40,7 @@ class UserController
|
||||
|
||||
$provider = Auth::guard($guard)->getProvider();
|
||||
|
||||
$user = str_contains($userId, '@')
|
||||
$user = Str::contains($userId, '@')
|
||||
? $provider->retrieveByCredentials(['email' => $userId])
|
||||
: $provider->retrieveById($userId);
|
||||
|
||||
@@ -49,6 +51,7 @@ class UserController
|
||||
* Log the user out of the application.
|
||||
*
|
||||
* @param string $guard
|
||||
* @return void
|
||||
*/
|
||||
public function logout($guard = null)
|
||||
{
|
||||
|
38
vendor/laravel/dusk/src/OperatingSystem.php
vendored
Normal file
38
vendor/laravel/dusk/src/OperatingSystem.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class OperatingSystem
|
||||
{
|
||||
/**
|
||||
* Returns the current OS identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function id()
|
||||
{
|
||||
return static::onWindows() ? 'win' : (static::onMac() ? 'mac' : 'linux');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the operating system is Windows or Windows Subsystem for Linux.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function onWindows()
|
||||
{
|
||||
return PHP_OS === 'WINNT' || Str::contains(php_uname(), 'Microsoft');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the operating system is macOS.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function onMac()
|
||||
{
|
||||
return PHP_OS === 'Darwin';
|
||||
}
|
||||
}
|
15
vendor/laravel/dusk/src/TestCase.php
vendored
15
vendor/laravel/dusk/src/TestCase.php
vendored
@@ -3,22 +3,22 @@
|
||||
namespace Laravel\Dusk;
|
||||
|
||||
use Exception;
|
||||
use Laravel\Dusk\Chrome\SupportsChrome;
|
||||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||||
use Facebook\WebDriver\Remote\DesiredCapabilities;
|
||||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||||
use Illuminate\Foundation\Testing\TestCase as FoundationTestCase;
|
||||
use Laravel\Dusk\Chrome\SupportsChrome;
|
||||
use Laravel\Dusk\Concerns\ProvidesBrowser;
|
||||
|
||||
abstract class TestCase extends FoundationTestCase
|
||||
{
|
||||
use Concerns\ProvidesBrowser,
|
||||
SupportsChrome;
|
||||
use ProvidesBrowser, SupportsChrome;
|
||||
|
||||
/**
|
||||
* Register the base URL with Dusk.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setUp()
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
@@ -28,6 +28,8 @@ abstract class TestCase extends FoundationTestCase
|
||||
|
||||
Browser::$storeConsoleLogAt = base_path('tests/Browser/console');
|
||||
|
||||
Browser::$storeSourceAt = base_path('tests/Browser/source');
|
||||
|
||||
Browser::$userResolver = function () {
|
||||
return $this->user();
|
||||
};
|
||||
@@ -59,10 +61,11 @@ abstract class TestCase extends FoundationTestCase
|
||||
* Return the default user to authenticate.
|
||||
*
|
||||
* @return \App\User|int|null
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function user()
|
||||
{
|
||||
throw new Exception("User resolver has not been set.");
|
||||
throw new Exception('User resolver has not been set.');
|
||||
}
|
||||
}
|
||||
|
7
vendor/laravel/dusk/stubs/DuskTestCase.stub
vendored
7
vendor/laravel/dusk/stubs/DuskTestCase.stub
vendored
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Laravel\Dusk\TestCase as BaseTestCase;
|
||||
use Facebook\WebDriver\Chrome\ChromeOptions;
|
||||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||||
use Facebook\WebDriver\Remote\DesiredCapabilities;
|
||||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||||
use Laravel\Dusk\TestCase as BaseTestCase;
|
||||
|
||||
abstract class DuskTestCase extends BaseTestCase
|
||||
{
|
||||
@@ -31,7 +31,8 @@ abstract class DuskTestCase extends BaseTestCase
|
||||
{
|
||||
$options = (new ChromeOptions)->addArguments([
|
||||
'--disable-gpu',
|
||||
'--headless'
|
||||
'--headless',
|
||||
'--window-size=1920,1080',
|
||||
]);
|
||||
|
||||
return RemoteWebDriver::create(
|
||||
|
4
vendor/laravel/dusk/stubs/ExampleTest.stub
vendored
4
vendor/laravel/dusk/stubs/ExampleTest.stub
vendored
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace Tests\Browser;
|
||||
|
||||
use Tests\DuskTestCase;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Tests\DuskTestCase;
|
||||
|
||||
class ExampleTest extends DuskTestCase
|
||||
{
|
||||
|
2
vendor/laravel/dusk/stubs/HomePage.stub
vendored
2
vendor/laravel/dusk/stubs/HomePage.stub
vendored
@@ -19,7 +19,7 @@ class HomePage extends Page
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @param \Laravel\Dusk\Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
|
4
vendor/laravel/framework/README.md
vendored
4
vendor/laravel/framework/README.md
vendored
@@ -20,7 +20,7 @@ Laravel is a web application framework with expressive, elegant syntax. We belie
|
||||
- [Robust background job processing](https://laravel.com/docs/queues).
|
||||
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
|
||||
|
||||
Laravel is accessible, yet powerful, providing tools needed for large, robust applications. A superb combination of simplicity, elegance, and innovation gives you a complete toolset required to build any application with which you are tasked
|
||||
Laravel is accessible, yet powerful, providing tools needed for large, robust applications. A superb combination of simplicity, elegance, and innovation gives you a complete toolset required to build any application with which you are tasked.
|
||||
|
||||
## Learning Laravel
|
||||
|
||||
@@ -38,7 +38,7 @@ In order to ensure that the Laravel community is welcoming to all, please review
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
|
||||
Please review [our security policy](https://github.com/laravel/framework/security/policy) on how to report security vulnerabilities.
|
||||
|
||||
## License
|
||||
|
||||
|
102
vendor/laravel/framework/SECURITY.md
vendored
Normal file
102
vendor/laravel/framework/SECURITY.md
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
# Security Policy
|
||||
|
||||
**PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, [SEE BELOW](#reporting-a-vulnerability).**
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Version | Security Fixes Until
|
||||
--- | ---
|
||||
5.8 | February 26th, 2020
|
||||
5.7 | September 4th, 2019
|
||||
5.6 | February 7th, 2019
|
||||
5.5 (LTS) | August 30th, 2020
|
||||
5.4 | January 24th, 2018
|
||||
5.3 | August 23rd, 2017
|
||||
5.2 | December 21st, 2016
|
||||
5.1 (LTS) | June 9th, 2018
|
||||
5.0 | February 4th, 2016
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you discover a security vulnerability within Laravel, please send an email to Taylor Otwell at taylor@laravel.com. All security vulnerabilities will be promptly addressed.
|
||||
|
||||
### Public PGP Key
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: OpenPGP v2.0.8
|
||||
Comment: https://sela.io/pgp/
|
||||
|
||||
xsFNBFugFSQBEACxEKhIY9IoJzcouVTIYKJfWFGvwFgbRjQWBiH3QdHId5vCrbWo
|
||||
s2l+4Rv03gMG+yHLJ3rWElnNdRaNdQv59+lShrZF7Bvu7Zvc0mMNmFOM/mQ/K2Lt
|
||||
OK/8bh6iwNNbEuyOhNQlarEy/w8hF8Yf55hBeu/rajGtcyURJDloQ/vNzcx4RWGK
|
||||
G3CLr8ka7zPYIjIFUvHLt27mcYFF9F4/G7b4HKpn75ICKC4vPoQSaYNAHlHQBLFb
|
||||
Jg/WPl93SySHLugU5F58sICs+fBZadXYQG5dWmbaF5OWB1K2XgRs45BQaBzf/8oS
|
||||
qq0scN8wVhAdBeYlVFf0ImDOxGlZ2suLK1BKJboR6zCIkBAwufKss4NV1R9KSUMv
|
||||
YGn3mq13PGme0QoIkvQkua5VjTwWfQx7wFDxZ3VQSsjIlbVyRL/Ac/hq71eAmiIR
|
||||
t6ZMNMPFpuSwBfYimrXqqb4EOffrfsTzRenG1Cxm4jNZRzX/6P4an7F/euoqXeXZ
|
||||
h37TiC7df+eHKcBI4mL+qOW4ibBqg8WwWPJ+jvuhANyQpRVzf3NNEOwJYCNbQPM/
|
||||
PbqYvMruAH+gg7uyu9u0jX3o/yLSxJMV7kF4x/SCDuBKIxSSUI4cgbjIlnxWLXZC
|
||||
wl7KW4xAKkerO3wgIPnxNfxQoiYiEKA1c3PShWRA0wHIMt3rVRJxwGM4CwARAQAB
|
||||
zRJ0YXlsb3JAbGFyYXZlbC5jb23CwXAEEwEKABoFAlugFSQCGy8DCwkHAxUKCAIe
|
||||
AQIXgAIZAQAKCRDKAI7r/Ml7Zo0SD/9zwu9K87rbqXbvZ3TVu7TnN+z7mPvVBzl+
|
||||
SFEK360TYq8a4GosghZuGm4aNEyZ90CeUjPQwc5fHwa26tIwqgLRppsG21B/mZwu
|
||||
0m8c5RaBFRFX/mCTEjlpvBkOwMJZ8f05nNdaktq6W98DbMN03neUwnpWlNSLeoNI
|
||||
u4KYZmJopNFLEax5WGaaDpmqD1J+WDr/aPHx39MUAg2ZVuC3Gj/IjYZbD1nCh0xD
|
||||
a09uDODje8a9uG33cKRBcKKPRLZjWEt5SWReLx0vsTuqJSWhCybHRBl9BQTc/JJR
|
||||
gJu5V4X3f1IYMTNRm9GggxcXrlOAiDCjE2J8ZTUt0cSxedQFnNyGfKxe/l94oTFP
|
||||
wwFHbdKhsSDZ1OyxPNIY5OHlMfMvvJaNbOw0xPPAEutPwr1aqX9sbgPeeiJwAdyw
|
||||
mPw2x/wNQvKJITRv6atw56TtLxSevQIZGPHCYTSlsIoi9jqh9/6vfq2ruMDYItCq
|
||||
+8uzei6TyH6w+fUpp/uFmcwZdrDwgNVqW+Ptu+pD2WmthqESF8UEQVoOv7OPgA5E
|
||||
ofOMaeH2ND74r2UgcXjPxZuUp1RkhHE2jJeiuLtbvOgrWwv3KOaatyEbVl+zHA1e
|
||||
1RHdJRJRPK+S7YThxxduqfOBX7E03arbbhHdS1HKhPwMc2e0hNnQDoNxQcv0GQp4
|
||||
2Y6UyCRaus7ATQRboBUkAQgA0h5j3EO2HNvp8YuT1t/VF00uUwbQaz2LIoZogqgC
|
||||
14Eb77diuIPM9MnuG7bEOnNtPVMFXxI5UYBIlzhLMxf7pfbrsoR4lq7Ld+7KMzdm
|
||||
eREqJRgUNfjZhtRZ9Z+jiFPr8AGpYxwmJk4v387uQGh1GC9JCc3CCLJoI62I9t/1
|
||||
K2b25KiOzW/FVZ/vYFj1WbISRd5GqS8SEFh4ifU79LUlJ/nEsFv4JxAXN9RqjU0e
|
||||
H4S/m1Nb24UCtYAv1JKymcf5O0G7kOzvI0w06uKxk0hNwspjDcOebD8Vv9IdYtGl
|
||||
0bn7PpBlVO1Az3s8s6Xoyyw+9Us+VLNtVka3fcrdaV/n0wARAQABwsKEBBgBCgAP
|
||||
BQJboBUkBQkPCZwAAhsuASkJEMoAjuv8yXtmwF0gBBkBCgAGBQJboBUkAAoJEA1I
|
||||
8aTLtYHmjpIH/A1ZKwTGetHFokJxsd2omvbqv+VtpAjnUbvZEi5g3yZXn+dHJV+K
|
||||
UR/DNlfGxLWEcY6datJ3ziNzzD5u8zcPp2CqeTlCxOky8F74FjEL9tN/EqUbvvmR
|
||||
td2LXsSFjHnLJRK5lYfZ3rnjKA5AjqC9MttILBovY2rI7lyVt67kbS3hMHi8AZl8
|
||||
EgihnHRJxGZjEUxyTxcB13nhfjAvxQq58LOj5754Rpe9ePSKbT8DNMjHbGpLrESz
|
||||
cmyn0VzDMLfxg8AA9uQFMwdlKqve7yRZXzeqvy08AatUpJaL7DsS4LKOItwvBub6
|
||||
tHbCE3mqrUw5lSNyUahO3vOcMAHnF7fd4W++eA//WIQKnPX5t3CwCedKn8Qkb3Ow
|
||||
oj8xUNl2T6kEtQJnO85lKBFXaMOUykopu6uB9EEXEr0ShdunOKX/UdDbkv46F2AB
|
||||
7TtltDSLB6s/QeHExSb8Jo3qra86JkDUutWdJxV7DYFUttBga8I0GqdPu4yRRoc/
|
||||
0irVXsdDY9q7jz6l7fw8mSeJR96C0Puhk70t4M1Vg/tu/ONRarXQW7fJ8kl21PcD
|
||||
UKNWWa242gji/+GLRI8AIpGMsBiX7pHhqmMMth3u7+ne5BZGGJz0uX+CzWboOHyq
|
||||
kWgfY4a62t3hM0vwnUkl/D7VgSGy4LiKQrapd3LvU2uuEfFsMu3CDicZBRXPqoXj
|
||||
PBjkkPKhwUTNlwEQrGF3QsZhNe0M9ptM2fC34qtxZtMIMB2NLvE4S621rmQ05oQv
|
||||
sT0B9WgUL3GYRKdx700+ojHEuwZ79bcLgo1dezvkfPtu/++2CXtieFthDlWHy8x5
|
||||
XJJjI1pDfGO+BgX0rS3QrQEYlF/uPQynKwxe6cGI62eZ0ug0hNrPvKEcfMLVqBQv
|
||||
w4VH6iGp9yNKMUOgAECLCs4YCxK+Eka9Prq/Gh4wuqjWiX8m66z8YvKf27sFL3fR
|
||||
OwGaz3LsnRSxbk/8oSiZuOVLfn44XRcxsHebteZat23lwD93oq54rtKnlJgmZHJY
|
||||
4vMgk1jpS4laGnvhZj7OwE0EW6AVJAEIAKJSrUvXRyK3XQnLp3Kfj82uj0St8Dt2
|
||||
h8BMeVbrAbg38wCN8XQZzVR9+bRZRR+aCzpKSqwhEQVtH7gdKgfdNdGNhG2DFAVk
|
||||
SihMhQz190FKttUZgwY00enzD7uaaA5VwNAZzRIr8skwiASB7UoO+lIhrAYgcQCA
|
||||
LpwCSMrUNB3gY1IVa2xi9FljEbS2uMABfOsTfl7z4L4T4DRv/ovDf+ihyZOXsXiH
|
||||
RVoUTIpN8ZILCZiiKubE1sMj4fSQwCs06UyDy17HbOG5/dO9awR/LHW53O3nZCxE
|
||||
JbCqr5iHa2MdHMC12+luxWJKD9DbVB01LiiPZCTkuKUDswCyi7otpVEAEQEAAcLC
|
||||
hAQYAQoADwUCW6AVJAUJDwmcAAIbLgEpCRDKAI7r/Ml7ZsBdIAQZAQoABgUCW6AV
|
||||
JAAKCRDxrCjKN7eORjt2B/9EnKVJ9lwB1JwXcQp6bZgJ21r6ghyXBssv24N9UF+v
|
||||
5QDz/tuSkTsKK1UoBrBDEinF/xTP2z+xXIeyP4c3mthMHsYdMl7AaGpcCwVJiL62
|
||||
fZvd+AiYNX3C+Bepwnwoziyhx4uPaqoezSEMD8G2WQftt6Gqttmm0Di5RVysCECF
|
||||
EyhkHwvCcbpXb5Qq+4XFzCUyaIZuGpe+oeO7U8B1CzOC16hEUu0Uhbk09Xt6dSbS
|
||||
ZERoxFjrGU+6bk424MkZkKvNS8FdTN2s3kQuHoNmhbMY+fRzKX5JNrcQ4dQQufiB
|
||||
zFcc2Ba0JVU0nYAMftTeT5ALakhwSqr3AcdD2avJZp3EYfYP/3smPGTeg1cDJV3E
|
||||
WIlCtSlhbwviUjvWEWJUE+n9MjhoUNU0TJtHIliUYUajKMG/At5wJZTXJaKVUx32
|
||||
UCWr4ioKfSzlbp1ngBuFlvU7LgZRcKbBZWvKj/KRYpxpfvPyPElmegCjAk6oiZYV
|
||||
LOV+jFfnMkk9PnR91ZZfTNx/bK+BwjOnO+g7oE8V2g2bA90vHdeSUHR52SnaVN/b
|
||||
9ytt07R0f+YtyKojuPmlNsbyAaUYUtJ1o+XNCwdVxzarYEuUabhAfDiVTu9n8wTr
|
||||
YVvnriSFOjNvOY9wdLAa56n7/qM8bzuGpoBS5SilXgJvITvQfWPvg7I9C3QhwK1S
|
||||
F6B1uquQGbBSze2wlnMbKXmhyGLlv9XpOqpkkejQo3o58B+Sqj4B8DuYixSjoknr
|
||||
pRbj8gqgqBKlcpf1wD5X9qCrl9vq19asVOHaKhiFZGxZIVbBpBOdvAKaMj4p/uln
|
||||
yklN3YFIfgmGPYbL0elvXVn7XfvwSV1mCQV5LtMbLHsFf0VsA16UsG8A/tLWtwgt
|
||||
0antzftRHXb+DI4qr+qEYKFkv9F3oCOXyH4QBhPA42EzKqhMXByEkEK9bu6skioL
|
||||
mHhDQ7yHjTWcxstqQjkUQ0T/IF9ls+Sm5u7rVXEifpyI7MCb+76kSCDawesvInKt
|
||||
WBGOG/qJGDlNiqBYYt2xNqzHCJoC
|
||||
=zXOv
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
93
vendor/laravel/framework/composer.json
vendored
93
vendor/laravel/framework/composer.json
vendored
@@ -16,28 +16,31 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"doctrine/inflector": "~1.1",
|
||||
"dragonmantank/cron-expression": "~2.0",
|
||||
"erusev/parsedown": "~1.7",
|
||||
"doctrine/inflector": "^1.1",
|
||||
"dragonmantank/cron-expression": "^2.0",
|
||||
"egulias/email-validator": "^2.0",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"league/flysystem": "^1.0.8",
|
||||
"monolog/monolog": "~1.12",
|
||||
"nesbot/carbon": "1.25.*",
|
||||
"psr/container": "~1.0",
|
||||
"monolog/monolog": "^1.12",
|
||||
"nesbot/carbon": "^1.26.3 || ^2.0",
|
||||
"opis/closure": "^3.1",
|
||||
"psr/container": "^1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"ramsey/uuid": "^3.7",
|
||||
"swiftmailer/swiftmailer": "~6.0",
|
||||
"symfony/console": "~4.0",
|
||||
"symfony/debug": "~4.0",
|
||||
"symfony/finder": "~4.0",
|
||||
"symfony/http-foundation": "~4.0",
|
||||
"symfony/http-kernel": "~4.0",
|
||||
"symfony/process": "~4.0",
|
||||
"symfony/routing": "~4.0",
|
||||
"symfony/var-dumper": "~4.0",
|
||||
"swiftmailer/swiftmailer": "^6.0",
|
||||
"symfony/console": "^4.2",
|
||||
"symfony/debug": "^4.2",
|
||||
"symfony/finder": "^4.2",
|
||||
"symfony/http-foundation": "^4.2",
|
||||
"symfony/http-kernel": "^4.2",
|
||||
"symfony/process": "^4.2",
|
||||
"symfony/routing": "^4.2",
|
||||
"symfony/var-dumper": "^4.2",
|
||||
"tijsverkoyen/css-to-inline-styles": "^2.2.1",
|
||||
"vlucas/phpdotenv": "~2.2"
|
||||
"vlucas/phpdotenv": "^3.3"
|
||||
},
|
||||
"replace": {
|
||||
"illuminate/auth": "self.version",
|
||||
@@ -73,18 +76,20 @@
|
||||
"tightenco/collect": "<5.5.33"
|
||||
},
|
||||
"require-dev": {
|
||||
"aws/aws-sdk-php": "~3.0",
|
||||
"doctrine/dbal": "~2.6",
|
||||
"aws/aws-sdk-php": "^3.0",
|
||||
"doctrine/dbal": "^2.6",
|
||||
"filp/whoops": "^2.1.4",
|
||||
"league/flysystem-cached-adapter": "~1.0",
|
||||
"mockery/mockery": "~1.0",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"mockery/mockery": "^1.0",
|
||||
"moontoast/math": "^1.1",
|
||||
"orchestra/testbench-core": "3.6.*",
|
||||
"pda/pheanstalk": "~3.0",
|
||||
"phpunit/phpunit": "~7.0",
|
||||
"orchestra/testbench-core": "3.8.*",
|
||||
"pda/pheanstalk": "^4.0",
|
||||
"phpunit/phpunit": "^7.5|^8.0",
|
||||
"predis/predis": "^1.1.1",
|
||||
"symfony/css-selector": "~4.0",
|
||||
"symfony/dom-crawler": "~4.0"
|
||||
"symfony/css-selector": "^4.2",
|
||||
"symfony/dom-crawler": "^4.2",
|
||||
"true/punycode": "^2.1"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
@@ -105,28 +110,32 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.6-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().",
|
||||
"ext-pcntl": "Required to use all features of the queue worker.",
|
||||
"ext-posix": "Required to use all features of the queue worker.",
|
||||
"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.6).",
|
||||
"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 (~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-cached-adapter": "Required to use the Flysystem cache (~1.0).",
|
||||
"league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).",
|
||||
"league/flysystem-sftp": "Required to use the Flysystem SFTP 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 (~3.0).",
|
||||
"symfony/css-selector": "Required to use some of the crawler integration testing tools (~4.0).",
|
||||
"symfony/dom-crawler": "Required to use most of the crawler integration testing tools (~4.0).",
|
||||
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (~1.0)."
|
||||
"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.6).",
|
||||
"filp/whoops": "Required for friendly error pages in development (^2.1.4).",
|
||||
"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 (^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-cached-adapter": "Required to use the Flysystem cache (^1.0).",
|
||||
"league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (^1.0).",
|
||||
"league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).",
|
||||
"moontoast/math": "Required to use ordered UUIDs (^1.1).",
|
||||
"nexmo/client": "Required to use the Nexmo transport (^1.0).",
|
||||
"pda/pheanstalk": "Required to use the beanstalk queue driver (^4.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 (^3.0).",
|
||||
"symfony/css-selector": "Required to use some of the crawler integration testing tools (^4.2).",
|
||||
"symfony/dom-crawler": "Required to use most of the crawler integration testing tools (^4.2).",
|
||||
"symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^1.1).",
|
||||
"wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)."
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
|
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace Illuminate\Auth\Access;
|
||||
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunction;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
@@ -54,6 +57,20 @@ class Gate implements GateContract
|
||||
*/
|
||||
protected $afterCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the defined abilities using class@method notation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $stringCallbacks = [];
|
||||
|
||||
/**
|
||||
* The callback to be used to guess policy names.
|
||||
*
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $guessPolicyNamesUsingCallback;
|
||||
|
||||
/**
|
||||
* Create a new gate instance.
|
||||
*
|
||||
@@ -63,10 +80,12 @@ class Gate implements GateContract
|
||||
* @param array $policies
|
||||
* @param array $beforeCallbacks
|
||||
* @param array $afterCallbacks
|
||||
* @param callable|null $guessPolicyNamesUsingCallback
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container, callable $userResolver, array $abilities = [],
|
||||
array $policies = [], array $beforeCallbacks = [], array $afterCallbacks = [])
|
||||
array $policies = [], array $beforeCallbacks = [], array $afterCallbacks = [],
|
||||
callable $guessPolicyNamesUsingCallback = null)
|
||||
{
|
||||
$this->policies = $policies;
|
||||
$this->container = $container;
|
||||
@@ -74,6 +93,7 @@ class Gate implements GateContract
|
||||
$this->userResolver = $userResolver;
|
||||
$this->afterCallbacks = $afterCallbacks;
|
||||
$this->beforeCallbacks = $beforeCallbacks;
|
||||
$this->guessPolicyNamesUsingCallback = $guessPolicyNamesUsingCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +128,9 @@ class Gate implements GateContract
|
||||
{
|
||||
if (is_callable($callback)) {
|
||||
$this->abilities[$ability] = $callback;
|
||||
} elseif (is_string($callback) && Str::contains($callback, '@')) {
|
||||
} elseif (is_string($callback)) {
|
||||
$this->stringCallbacks[$ability] = $callback;
|
||||
|
||||
$this->abilities[$ability] = $this->buildAbilityCallback($ability, $callback);
|
||||
} else {
|
||||
throw new InvalidArgumentException("Callback must be a callable or a 'Class@method' string.");
|
||||
@@ -128,10 +150,11 @@ class Gate implements GateContract
|
||||
public function resource($name, $class, array $abilities = null)
|
||||
{
|
||||
$abilities = $abilities ?: [
|
||||
'view' => 'view',
|
||||
'create' => 'create',
|
||||
'update' => 'update',
|
||||
'delete' => 'delete',
|
||||
'viewAny' => 'viewAny',
|
||||
'view' => 'view',
|
||||
'create' => 'create',
|
||||
'update' => 'update',
|
||||
'delete' => 'delete',
|
||||
];
|
||||
|
||||
foreach ($abilities as $ability => $method) {
|
||||
@@ -151,7 +174,11 @@ class Gate implements GateContract
|
||||
protected function buildAbilityCallback($ability, $callback)
|
||||
{
|
||||
return function () use ($ability, $callback) {
|
||||
list($class, $method) = Str::parseCallback($callback);
|
||||
if (Str::contains($callback, '@')) {
|
||||
[$class, $method] = Str::parseCallback($callback);
|
||||
} else {
|
||||
$class = $callback;
|
||||
}
|
||||
|
||||
$policy = $this->resolvePolicy($class);
|
||||
|
||||
@@ -167,7 +194,9 @@ class Gate implements GateContract
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $policy->{$method}(...func_get_args());
|
||||
return isset($method)
|
||||
? $policy->{$method}(...func_get_args())
|
||||
: $policy(...func_get_args());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -267,6 +296,18 @@ class Gate implements GateContract
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if all of the given abilities should be denied for the current user.
|
||||
*
|
||||
* @param iterable|string $abilities
|
||||
* @param array|mixed $arguments
|
||||
* @return bool
|
||||
*/
|
||||
public function none($abilities, $arguments = [])
|
||||
{
|
||||
return ! $this->any($abilities, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given ability should be granted for the current user.
|
||||
*
|
||||
@@ -294,14 +335,12 @@ class Gate implements GateContract
|
||||
* @param array|mixed $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
protected function raw($ability, $arguments = [])
|
||||
public function raw($ability, $arguments = [])
|
||||
{
|
||||
if (! $user = $this->resolveUser()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$arguments = Arr::wrap($arguments);
|
||||
|
||||
$user = $this->resolveUser();
|
||||
|
||||
// First we will call the "before" callbacks for the Gate. If any of these give
|
||||
// back a non-null response, we will immediately return that result in order
|
||||
// to let the developers override all checks for some authorization cases.
|
||||
@@ -316,17 +355,95 @@ class Gate implements GateContract
|
||||
// After calling the authorization callback, we will call the "after" callbacks
|
||||
// that are registered with the Gate, which allows a developer to do logging
|
||||
// if that is required for this application. Then we'll return the result.
|
||||
$this->callAfterCallbacks(
|
||||
return $this->callAfterCallbacks(
|
||||
$user, $ability, $arguments, $result
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
/**
|
||||
* Determine whether the callback/method can be called with the given user.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
|
||||
* @param \Closure|string|array $class
|
||||
* @param string|null $method
|
||||
* @return bool
|
||||
*/
|
||||
protected function canBeCalledWithUser($user, $class, $method = null)
|
||||
{
|
||||
if (! is_null($user)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! is_null($method)) {
|
||||
return $this->methodAllowsGuests($class, $method);
|
||||
}
|
||||
|
||||
if (is_array($class)) {
|
||||
$className = is_string($class[0]) ? $class[0] : get_class($class[0]);
|
||||
|
||||
return $this->methodAllowsGuests($className, $class[1]);
|
||||
}
|
||||
|
||||
return $this->callbackAllowsGuests($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given class method allows guests.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
protected function methodAllowsGuests($class, $method)
|
||||
{
|
||||
try {
|
||||
$reflection = new ReflectionClass($class);
|
||||
|
||||
$method = $reflection->getMethod($method);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($method) {
|
||||
$parameters = $method->getParameters();
|
||||
|
||||
return isset($parameters[0]) && $this->parameterAllowsGuests($parameters[0]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the callback allows guests.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return bool
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function callbackAllowsGuests($callback)
|
||||
{
|
||||
$parameters = (new ReflectionFunction($callback))->getParameters();
|
||||
|
||||
return isset($parameters[0]) && $this->parameterAllowsGuests($parameters[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given parameter allows guests.
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @return bool
|
||||
*/
|
||||
protected function parameterAllowsGuests($parameter)
|
||||
{
|
||||
return ($parameter->getClass() && $parameter->allowsNull()) ||
|
||||
($parameter->isDefaultValueAvailable() && is_null($parameter->getDefaultValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve and call the appropriate authorization callback.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
|
||||
* @param string $ability
|
||||
* @param array $arguments
|
||||
* @return bool
|
||||
@@ -341,17 +458,19 @@ class Gate implements GateContract
|
||||
/**
|
||||
* Call all of the before callbacks and return if a result is given.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
|
||||
* @param string $ability
|
||||
* @param array $arguments
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function callBeforeCallbacks($user, $ability, array $arguments)
|
||||
{
|
||||
$arguments = array_merge([$user, $ability], [$arguments]);
|
||||
|
||||
foreach ($this->beforeCallbacks as $before) {
|
||||
if (! is_null($result = $before(...$arguments))) {
|
||||
if (! $this->canBeCalledWithUser($user, $before)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! is_null($result = $before($user, $ability, $arguments))) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -364,21 +483,27 @@ class Gate implements GateContract
|
||||
* @param string $ability
|
||||
* @param array $arguments
|
||||
* @param bool $result
|
||||
* @return void
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function callAfterCallbacks($user, $ability, array $arguments, $result)
|
||||
{
|
||||
$arguments = array_merge([$user, $ability, $result], [$arguments]);
|
||||
|
||||
foreach ($this->afterCallbacks as $after) {
|
||||
$after(...$arguments);
|
||||
if (! $this->canBeCalledWithUser($user, $after)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$afterResult = $after($user, $ability, $result, $arguments);
|
||||
|
||||
$result = $result ?? $afterResult;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the callable for the given ability and arguments.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
|
||||
* @param string $ability
|
||||
* @param array $arguments
|
||||
* @return callable
|
||||
@@ -391,12 +516,20 @@ class Gate implements GateContract
|
||||
return $callback;
|
||||
}
|
||||
|
||||
if (isset($this->abilities[$ability])) {
|
||||
if (isset($this->stringCallbacks[$ability])) {
|
||||
[$class, $method] = Str::parseCallback($this->stringCallbacks[$ability]);
|
||||
|
||||
if ($this->canBeCalledWithUser($user, $class, $method ?: '__invoke')) {
|
||||
return $this->abilities[$ability];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->abilities[$ability]) &&
|
||||
$this->canBeCalledWithUser($user, $this->abilities[$ability])) {
|
||||
return $this->abilities[$ability];
|
||||
}
|
||||
|
||||
return function () {
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -420,6 +553,12 @@ class Gate implements GateContract
|
||||
return $this->resolvePolicy($this->policies[$class]);
|
||||
}
|
||||
|
||||
foreach ($this->guessPolicyName($class) as $guessedPolicy) {
|
||||
if (class_exists($guessedPolicy)) {
|
||||
return $this->resolvePolicy($guessedPolicy);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->policies as $expected => $policy) {
|
||||
if (is_subclass_of($class, $expected)) {
|
||||
return $this->resolvePolicy($policy);
|
||||
@@ -427,11 +566,43 @@ class Gate implements GateContract
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the policy name for the given class.
|
||||
*
|
||||
* @param string $class
|
||||
* @return array
|
||||
*/
|
||||
protected function guessPolicyName($class)
|
||||
{
|
||||
if ($this->guessPolicyNamesUsingCallback) {
|
||||
return Arr::wrap(call_user_func($this->guessPolicyNamesUsingCallback, $class));
|
||||
}
|
||||
|
||||
$classDirname = str_replace('/', '\\', dirname(str_replace('\\', '/', $class)));
|
||||
|
||||
return [$classDirname.'\\Policies\\'.class_basename($class).'Policy'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a callback to be used to guess policy names.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function guessPolicyNamesUsing(callable $callback)
|
||||
{
|
||||
$this->guessPolicyNamesUsingCallback = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a policy class instance of the given type.
|
||||
*
|
||||
* @param object|string $class
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function resolvePolicy($class)
|
||||
{
|
||||
@@ -468,18 +639,9 @@ class Gate implements GateContract
|
||||
return $result;
|
||||
}
|
||||
|
||||
$ability = $this->formatAbilityToMethod($ability);
|
||||
$method = $this->formatAbilityToMethod($ability);
|
||||
|
||||
// If this first argument is a string, that means they are passing a class name
|
||||
// to the policy. We will remove the first argument from this argument array
|
||||
// because this policy already knows what type of models it can authorize.
|
||||
if (isset($arguments[0]) && is_string($arguments[0])) {
|
||||
array_shift($arguments);
|
||||
}
|
||||
|
||||
return is_callable([$policy, $ability])
|
||||
? $policy->{$ability}($user, ...$arguments)
|
||||
: false;
|
||||
return $this->callPolicyMethod($policy, $method, $user, $arguments);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -494,11 +656,42 @@ class Gate implements GateContract
|
||||
*/
|
||||
protected function callPolicyBefore($policy, $user, $ability, $arguments)
|
||||
{
|
||||
if (method_exists($policy, 'before')) {
|
||||
if (! method_exists($policy, 'before')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->canBeCalledWithUser($user, $policy, 'before')) {
|
||||
return $policy->before($user, $ability, ...$arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the appropriate method on the given policy.
|
||||
*
|
||||
* @param mixed $policy
|
||||
* @param string $method
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
|
||||
* @param array $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
protected function callPolicyMethod($policy, $method, $user, array $arguments)
|
||||
{
|
||||
// If this first argument is a string, that means they are passing a class name
|
||||
// to the policy. We will remove the first argument from this argument array
|
||||
// because this policy already knows what type of models it can authorize.
|
||||
if (isset($arguments[0]) && is_string($arguments[0])) {
|
||||
array_shift($arguments);
|
||||
}
|
||||
|
||||
if (! is_callable([$policy, $method])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->canBeCalledWithUser($user, $policy, $method)) {
|
||||
return $policy->{$method}($user, ...$arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the policy ability into a method name.
|
||||
*
|
||||
@@ -524,7 +717,8 @@ class Gate implements GateContract
|
||||
|
||||
return new static(
|
||||
$this->container, $callback, $this->abilities,
|
||||
$this->policies, $this->beforeCallbacks, $this->afterCallbacks
|
||||
$this->policies, $this->beforeCallbacks, $this->afterCallbacks,
|
||||
$this->guessPolicyNamesUsingCallback
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -35,10 +35,10 @@ class Response
|
||||
/**
|
||||
* Get the string representation of the message.
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->message();
|
||||
return (string) $this->message();
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ class AuthManager implements FactoryContract
|
||||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Foundation\Application
|
||||
* @var \Illuminate\Contracts\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
@@ -43,7 +43,7 @@ class AuthManager implements FactoryContract
|
||||
/**
|
||||
* Create a new Auth manager instance.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($app)
|
||||
@@ -58,7 +58,7 @@ class AuthManager implements FactoryContract
|
||||
/**
|
||||
* Attempt to get the guard from the local cache.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
public function guard($name = null)
|
||||
@@ -94,7 +94,9 @@ class AuthManager implements FactoryContract
|
||||
return $this->{$driverMethod}($name, $config);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Auth driver [{$config['driver']}] for guard [{$name}] is not defined.");
|
||||
throw new InvalidArgumentException(
|
||||
"Auth driver [{$config['driver']}] for guard [{$name}] is not defined."
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,7 +156,10 @@ class AuthManager implements FactoryContract
|
||||
// user in the database or another persistence layer where users are.
|
||||
$guard = new TokenGuard(
|
||||
$this->createUserProvider($config['provider'] ?? null),
|
||||
$this->app['request']
|
||||
$this->app['request'],
|
||||
$config['input_key'] ?? 'api_token',
|
||||
$config['storage_key'] ?? 'api_token',
|
||||
$config['hash'] ?? false
|
||||
);
|
||||
|
||||
$this->app->refresh('request', $guard, 'setRequest');
|
||||
|
@@ -17,12 +17,10 @@ class AuthServiceProvider extends ServiceProvider
|
||||
public function register()
|
||||
{
|
||||
$this->registerAuthenticator();
|
||||
|
||||
$this->registerUserResolver();
|
||||
|
||||
$this->registerAccessGate();
|
||||
|
||||
$this->registerRequestRebindHandler();
|
||||
$this->registerEventRebindHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +73,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a resolver for the authenticated user.
|
||||
* Handle the re-binding of the request binding.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -87,4 +85,22 @@ class AuthServiceProvider extends ServiceProvider
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the re-binding of the event dispatcher binding.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerEventRebindHandler()
|
||||
{
|
||||
$this->app->rebinding('events', function ($app, $dispatcher) {
|
||||
if (! $app->resolved('auth')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (method_exists($guard = $app['auth']->guard(), 'setDispatcher')) {
|
||||
$guard->setDispatcher($dispatcher);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -13,18 +13,27 @@ class AuthenticationException extends Exception
|
||||
*/
|
||||
protected $guards;
|
||||
|
||||
/**
|
||||
* The path the user should be redirected to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo;
|
||||
|
||||
/**
|
||||
* Create a new authentication exception.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $guards
|
||||
* @param string|null $redirectTo
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = 'Unauthenticated.', array $guards = [])
|
||||
public function __construct($message = 'Unauthenticated.', array $guards = [], $redirectTo = null)
|
||||
{
|
||||
parent::__construct($message);
|
||||
|
||||
$this->guards = $guards;
|
||||
$this->redirectTo = $redirectTo;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,4 +45,14 @@ class AuthenticationException extends Exception
|
||||
{
|
||||
return $this->guards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path the user should be redirected to.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function redirectTo()
|
||||
{
|
||||
return $this->redirectTo;
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ class AuthMakeCommand extends Command
|
||||
protected $views = [
|
||||
'auth/login.stub' => 'auth/login.blade.php',
|
||||
'auth/register.stub' => 'auth/register.blade.php',
|
||||
'auth/verify.stub' => 'auth/verify.blade.php',
|
||||
'auth/passwords/email.stub' => 'auth/passwords/email.blade.php',
|
||||
'auth/passwords/reset.stub' => 'auth/passwords/reset.blade.php',
|
||||
'layouts/app.stub' => 'layouts/app.blade.php',
|
||||
@@ -73,11 +74,11 @@ class AuthMakeCommand extends Command
|
||||
*/
|
||||
protected function createDirectories()
|
||||
{
|
||||
if (! is_dir($directory = resource_path('views/layouts'))) {
|
||||
if (! is_dir($directory = $this->getViewPath('layouts'))) {
|
||||
mkdir($directory, 0755, true);
|
||||
}
|
||||
|
||||
if (! is_dir($directory = resource_path('views/auth/passwords'))) {
|
||||
if (! is_dir($directory = $this->getViewPath('auth/passwords'))) {
|
||||
mkdir($directory, 0755, true);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +91,7 @@ class AuthMakeCommand extends Command
|
||||
protected function exportViews()
|
||||
{
|
||||
foreach ($this->views as $key => $value) {
|
||||
if (file_exists($view = resource_path('views/'.$value)) && ! $this->option('force')) {
|
||||
if (file_exists($view = $this->getViewPath($value)) && ! $this->option('force')) {
|
||||
if (! $this->confirm("The [{$value}] view already exists. Do you want to replace it?")) {
|
||||
continue;
|
||||
}
|
||||
@@ -116,4 +117,17 @@ class AuthMakeCommand extends Command
|
||||
file_get_contents(__DIR__.'/stubs/make/controllers/HomeController.stub')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full view path relative to the app's configured view path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
protected function getViewPath($path)
|
||||
{
|
||||
return implode(DIRECTORY_SEPARATOR, [
|
||||
config('view.paths')[0] ?? resource_path('views'), $path,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ class HomeController extends Controller
|
||||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\Support\Renderable
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
@@ -8,20 +8,20 @@
|
||||
<div class="card-header">{{ __('Login') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('login') }}" aria-label="{{ __('Login') }}">
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="email" class="col-sm-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
|
||||
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required autofocus>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
|
||||
@if ($errors->has('email'))
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
|
||||
|
||||
@if ($errors->has('password'))
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,9 +57,11 @@
|
||||
{{ __('Login') }}
|
||||
</button>
|
||||
|
||||
<a class="btn btn-link" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot Your Password?') }}
|
||||
</a>
|
||||
@if (Route::has('password.request'))
|
||||
<a class="btn btn-link" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot Your Password?') }}
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -14,20 +14,20 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('password.email') }}" aria-label="{{ __('Reset Password') }}">
|
||||
<form method="POST" action="{{ route('password.email') }}">
|
||||
@csrf
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
|
||||
@if ($errors->has('email'))
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('password.request') }}" aria-label="{{ __('Reset Password') }}">
|
||||
<form method="POST" action="{{ route('password.update') }}">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="token" value="{{ $token }}">
|
||||
@@ -17,13 +17,13 @@
|
||||
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ $email ?? old('email') }}" required autofocus>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>
|
||||
|
||||
@if ($errors->has('email'))
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
|
||||
|
||||
@if ($errors->has('password'))
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -8,20 +8,20 @@
|
||||
<div class="card-header">{{ __('Register') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('register') }}" aria-label="{{ __('Register') }}">
|
||||
<form method="POST" action="{{ route('register') }}">
|
||||
@csrf
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="name" type="text" class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}" name="name" value="{{ old('name') }}" required autofocus>
|
||||
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>
|
||||
|
||||
@if ($errors->has('name'))
|
||||
@error('name')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required>
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">
|
||||
|
||||
@if ($errors->has('email'))
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,13 +43,13 @@
|
||||
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
|
||||
|
||||
@if ($errors->has('password'))
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
24
vendor/laravel/framework/src/Illuminate/Auth/Console/stubs/make/views/auth/verify.stub
vendored
Normal file
24
vendor/laravel/framework/src/Illuminate/Auth/Console/stubs/make/views/auth/verify.stub
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Verify Your Email Address') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
@if (session('resent'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ __('A fresh verification link has been sent to your email address.') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{ __('Before proceeding, please check your email for a verification link.') }}
|
||||
{{ __('If you did not receive the email') }}, <a href="{{ route('verification.resend') }}">{{ __('click here to request another') }}</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
@@ -2,7 +2,6 @@
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- CSRF Token -->
|
||||
@@ -14,15 +13,15 @@
|
||||
<script src="{{ asset('js/app.js') }}" defer></script>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">
|
||||
<link rel="dns-prefetch" href="//fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
|
||||
|
||||
<!-- Styles -->
|
||||
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<nav class="navbar navbar-expand-md navbar-light navbar-laravel">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{{ url('/') }}">
|
||||
{{ config('app.name', 'Laravel') }}
|
||||
@@ -44,9 +43,11 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
|
||||
</li>
|
||||
@if (Route::has('register'))
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
|
||||
</li>
|
||||
@endif
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
||||
|
@@ -47,9 +47,9 @@ class EloquentUserProvider implements UserProvider
|
||||
{
|
||||
$model = $this->createModel();
|
||||
|
||||
return $model->newQuery()
|
||||
->where($model->getAuthIdentifierName(), $identifier)
|
||||
->first();
|
||||
return $this->newModelQuery($model)
|
||||
->where($model->getAuthIdentifierName(), $identifier)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,21 +63,24 @@ class EloquentUserProvider implements UserProvider
|
||||
{
|
||||
$model = $this->createModel();
|
||||
|
||||
$model = $model->where($model->getAuthIdentifierName(), $identifier)->first();
|
||||
$retrievedModel = $this->newModelQuery($model)->where(
|
||||
$model->getAuthIdentifierName(), $identifier
|
||||
)->first();
|
||||
|
||||
if (! $model) {
|
||||
return null;
|
||||
if (! $retrievedModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rememberToken = $model->getRememberToken();
|
||||
$rememberToken = $retrievedModel->getRememberToken();
|
||||
|
||||
return $rememberToken && hash_equals($rememberToken, $token) ? $model : null;
|
||||
return $rememberToken && hash_equals($rememberToken, $token)
|
||||
? $retrievedModel : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the "remember me" token for the given user in storage.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|\Illuminate\Database\Eloquent\Model $user
|
||||
* @param string $token
|
||||
* @return void
|
||||
*/
|
||||
@@ -104,14 +107,14 @@ class EloquentUserProvider implements UserProvider
|
||||
{
|
||||
if (empty($credentials) ||
|
||||
(count($credentials) === 1 &&
|
||||
array_key_exists('password', $credentials))) {
|
||||
Str::contains($this->firstCredentialKey($credentials), 'password'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First we will add each credential element to the query as a where clause.
|
||||
// Then we can execute the query and, if we found a user, return it in a
|
||||
// Eloquent User "model" that will be utilized by the Guard instances.
|
||||
$query = $this->createModel()->newQuery();
|
||||
$query = $this->newModelQuery();
|
||||
|
||||
foreach ($credentials as $key => $value) {
|
||||
if (Str::contains($key, 'password')) {
|
||||
@@ -128,6 +131,19 @@ class EloquentUserProvider implements UserProvider
|
||||
return $query->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first key from the credential array.
|
||||
*
|
||||
* @param array $credentials
|
||||
* @return string|null
|
||||
*/
|
||||
protected function firstCredentialKey(array $credentials)
|
||||
{
|
||||
foreach ($credentials as $key => $value) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a user against the given credentials.
|
||||
*
|
||||
@@ -142,6 +158,19 @@ class EloquentUserProvider implements UserProvider
|
||||
return $this->hasher->check($plain, $user->getAuthPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query builder for the model instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model|null $model
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function newModelQuery($model = null)
|
||||
{
|
||||
return is_null($model)
|
||||
? $this->createModel()->newQuery()
|
||||
: $model->newQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the model.
|
||||
*
|
||||
|
@@ -4,6 +4,13 @@ namespace Illuminate\Auth\Events;
|
||||
|
||||
class Attempting
|
||||
{
|
||||
/**
|
||||
* The authentication guard name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $guard;
|
||||
|
||||
/**
|
||||
* The credentials for the user.
|
||||
*
|
||||
@@ -21,12 +28,14 @@ class Attempting
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $guard
|
||||
* @param array $credentials
|
||||
* @param bool $remember
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($credentials, $remember)
|
||||
public function __construct($guard, $credentials, $remember)
|
||||
{
|
||||
$this->guard = $guard;
|
||||
$this->remember = $remember;
|
||||
$this->credentials = $credentials;
|
||||
}
|
||||
|
@@ -8,6 +8,13 @@ class Authenticated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The authentication guard name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $guard;
|
||||
|
||||
/**
|
||||
* The authenticated user.
|
||||
*
|
||||
@@ -18,11 +25,13 @@ class Authenticated
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $guard
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($user)
|
||||
public function __construct($guard, $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->guard = $guard;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,13 @@ namespace Illuminate\Auth\Events;
|
||||
|
||||
class Failed
|
||||
{
|
||||
/**
|
||||
* The authentication guard name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $guard;
|
||||
|
||||
/**
|
||||
* The user the attempter was trying to authenticate as.
|
||||
*
|
||||
@@ -21,13 +28,15 @@ class Failed
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $guard
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
|
||||
* @param array $credentials
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($user, $credentials)
|
||||
public function __construct($guard, $user, $credentials)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->guard = $guard;
|
||||
$this->credentials = $credentials;
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,13 @@ class Login
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The authentication guard name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $guard;
|
||||
|
||||
/**
|
||||
* The authenticated user.
|
||||
*
|
||||
@@ -25,13 +32,15 @@ class Login
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $guard
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param bool $remember
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($user, $remember)
|
||||
public function __construct($guard, $user, $remember)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->guard = $guard;
|
||||
$this->remember = $remember;
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,13 @@ class Logout
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The authentication guard name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $guard;
|
||||
|
||||
/**
|
||||
* The authenticated user.
|
||||
*
|
||||
@@ -18,11 +25,13 @@ class Logout
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $guard
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($user)
|
||||
public function __construct($guard, $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->guard = $guard;
|
||||
}
|
||||
}
|
||||
|
37
vendor/laravel/framework/src/Illuminate/Auth/Events/OtherDeviceLogout.php
vendored
Normal file
37
vendor/laravel/framework/src/Illuminate/Auth/Events/OtherDeviceLogout.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Auth\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class OtherDeviceLogout
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The authentication guard name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $guard;
|
||||
|
||||
/**
|
||||
* The authenticated user.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Authenticatable
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $guard
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($guard, $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->guard = $guard;
|
||||
}
|
||||
}
|
28
vendor/laravel/framework/src/Illuminate/Auth/Events/Verified.php
vendored
Normal file
28
vendor/laravel/framework/src/Illuminate/Auth/Events/Verified.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Auth\Events;
|
||||
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class Verified
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The verified user.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\MustVerifyEmail
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\MustVerifyEmail $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
@@ -25,7 +25,7 @@ trait GuardHelpers
|
||||
protected $provider;
|
||||
|
||||
/**
|
||||
* Determine if the current user is authenticated.
|
||||
* Determine if current user is authenticated. If not, throw an exception.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\Authenticatable
|
||||
*
|
||||
|
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) <Taylor Otwell>
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
22
vendor/laravel/framework/src/Illuminate/Auth/Listeners/SendEmailVerificationNotification.php
vendored
Normal file
22
vendor/laravel/framework/src/Illuminate/Auth/Listeners/SendEmailVerificationNotification.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Auth\Listeners;
|
||||
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
|
||||
class SendEmailVerificationNotification
|
||||
{
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \Illuminate\Auth\Events\Registered $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Registered $event)
|
||||
{
|
||||
if ($event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()) {
|
||||
$event->user->sendEmailVerificationNotification();
|
||||
}
|
||||
}
|
||||
}
|
@@ -38,7 +38,7 @@ class Authenticate
|
||||
*/
|
||||
public function handle($request, Closure $next, ...$guards)
|
||||
{
|
||||
$this->authenticate($guards);
|
||||
$this->authenticate($request, $guards);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@@ -46,15 +46,16 @@ class Authenticate
|
||||
/**
|
||||
* Determine if the user is logged in to any of the given guards.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param array $guards
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Auth\AuthenticationException
|
||||
*/
|
||||
protected function authenticate(array $guards)
|
||||
protected function authenticate($request, array $guards)
|
||||
{
|
||||
if (empty($guards)) {
|
||||
return $this->auth->authenticate();
|
||||
$guards = [null];
|
||||
}
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
@@ -63,6 +64,19 @@ class Authenticate
|
||||
}
|
||||
}
|
||||
|
||||
throw new AuthenticationException('Unauthenticated.', $guards);
|
||||
throw new AuthenticationException(
|
||||
'Unauthenticated.', $guards, $this->redirectTo($request)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path the user should be redirected to when they are not authenticated.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string
|
||||
*/
|
||||
protected function redirectTo($request)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
@@ -31,10 +31,15 @@ class AuthenticateWithBasicAuth
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $guard
|
||||
* @param string|null $field
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
|
||||
*/
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
public function handle($request, Closure $next, $guard = null, $field = null)
|
||||
{
|
||||
return $this->auth->guard($guard)->basic() ?: $next($request);
|
||||
$this->auth->guard($guard)->basic($field ?: 'email');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
@@ -5,17 +5,9 @@ namespace Illuminate\Auth\Middleware;
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Contracts\Auth\Access\Gate;
|
||||
use Illuminate\Contracts\Auth\Factory as Auth;
|
||||
|
||||
class Authorize
|
||||
{
|
||||
/**
|
||||
* The authentication factory instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Auth\Factory
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* The gate instance.
|
||||
*
|
||||
@@ -26,13 +18,11 @@ class Authorize
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Factory $auth
|
||||
* @param \Illuminate\Contracts\Auth\Access\Gate $gate
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Auth $auth, Gate $gate)
|
||||
public function __construct(Gate $gate)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
$this->gate = $gate;
|
||||
}
|
||||
|
||||
@@ -50,8 +40,6 @@ class Authorize
|
||||
*/
|
||||
public function handle($request, Closure $next, $ability, ...$models)
|
||||
{
|
||||
$this->auth->authenticate();
|
||||
|
||||
$this->gate->authorize($ability, $this->getGateArguments($request, $models));
|
||||
|
||||
return $next($request);
|
||||
@@ -84,7 +72,12 @@ class Authorize
|
||||
*/
|
||||
protected function getModel($request, $model)
|
||||
{
|
||||
return $this->isClassName($model) ? $model : $request->route($model);
|
||||
if ($this->isClassName($model)) {
|
||||
return trim($model);
|
||||
} else {
|
||||
return $request->route($model, null) ?:
|
||||
((preg_match("/^['\"](.*)['\"]$/", trim($model), $matches)) ? $matches[1] : null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
31
vendor/laravel/framework/src/Illuminate/Auth/Middleware/EnsureEmailIsVerified.php
vendored
Normal file
31
vendor/laravel/framework/src/Illuminate/Auth/Middleware/EnsureEmailIsVerified.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Auth\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
|
||||
class EnsureEmailIsVerified
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $redirectToRoute
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle($request, Closure $next, $redirectToRoute = null)
|
||||
{
|
||||
if (! $request->user() ||
|
||||
($request->user() instanceof MustVerifyEmail &&
|
||||
! $request->user()->hasVerifiedEmail())) {
|
||||
return $request->expectsJson()
|
||||
? abort(403, 'Your email address is not verified.')
|
||||
: Redirect::route($redirectToRoute ?: 'verification.notice');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
38
vendor/laravel/framework/src/Illuminate/Auth/MustVerifyEmail.php
vendored
Normal file
38
vendor/laravel/framework/src/Illuminate/Auth/MustVerifyEmail.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Auth;
|
||||
|
||||
trait MustVerifyEmail
|
||||
{
|
||||
/**
|
||||
* Determine if the user has verified their email address.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasVerifiedEmail()
|
||||
{
|
||||
return ! is_null($this->email_verified_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the given user's email as verified.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function markEmailAsVerified()
|
||||
{
|
||||
return $this->forceFill([
|
||||
'email_verified_at' => $this->freshTimestamp(),
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the email verification notification.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendEmailVerificationNotification()
|
||||
{
|
||||
$this->notify(new Notifications\VerifyEmail);
|
||||
}
|
||||
}
|
@@ -59,7 +59,8 @@ class ResetPassword extends Notification
|
||||
return (new MailMessage)
|
||||
->subject(Lang::getFromJson('Reset Password Notification'))
|
||||
->line(Lang::getFromJson('You are receiving this email because we received a password reset request for your account.'))
|
||||
->action(Lang::getFromJson('Reset Password'), url(config('app.url').route('password.reset', $this->token, false)))
|
||||
->action(Lang::getFromJson('Reset Password'), url(config('app.url').route('password.reset', ['token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset()], false)))
|
||||
->line(Lang::getFromJson('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]))
|
||||
->line(Lang::getFromJson('If you did not request a password reset, no further action is required.'));
|
||||
}
|
||||
|
||||
|
78
vendor/laravel/framework/src/Illuminate/Auth/Notifications/VerifyEmail.php
vendored
Normal file
78
vendor/laravel/framework/src/Illuminate/Auth/Notifications/VerifyEmail.php
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Auth\Notifications;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class VerifyEmail extends Notification
|
||||
{
|
||||
/**
|
||||
* The callback that should be used to build the mail message.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
public static $toMailCallback;
|
||||
|
||||
/**
|
||||
* Get the notification's channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array|string
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$verificationUrl = $this->verificationUrl($notifiable);
|
||||
|
||||
if (static::$toMailCallback) {
|
||||
return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl);
|
||||
}
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(Lang::getFromJson('Verify Email Address'))
|
||||
->line(Lang::getFromJson('Please click the button below to verify your email address.'))
|
||||
->action(Lang::getFromJson('Verify Email Address'), $verificationUrl)
|
||||
->line(Lang::getFromJson('If you did not create an account, no further action is required.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the verification URL for the given notifiable.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return string
|
||||
*/
|
||||
protected function verificationUrl($notifiable)
|
||||
{
|
||||
return URL::temporarySignedRoute(
|
||||
'verification.verify',
|
||||
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
|
||||
['id' => $notifiable->getKey()]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that should be used when building the notification mail message.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function toMailUsing($callback)
|
||||
{
|
||||
static::$toMailCallback = $callback;
|
||||
}
|
||||
}
|
@@ -146,7 +146,7 @@ class PasswordBroker implements PasswordBrokerContract
|
||||
public function validateNewPassword(array $credentials)
|
||||
{
|
||||
if (isset($this->passwordValidator)) {
|
||||
list($password, $confirm) = [
|
||||
[$password, $confirm] = [
|
||||
$credentials['password'],
|
||||
$credentials['password_confirmation'],
|
||||
];
|
||||
@@ -167,12 +167,12 @@ class PasswordBroker implements PasswordBrokerContract
|
||||
*/
|
||||
protected function validatePasswordWithDefaults(array $credentials)
|
||||
{
|
||||
list($password, $confirm) = [
|
||||
[$password, $confirm] = [
|
||||
$credentials['password'],
|
||||
$credentials['password_confirmation'],
|
||||
];
|
||||
|
||||
return $password === $confirm && mb_strlen($password) >= 6;
|
||||
return $password === $confirm && mb_strlen($password) >= 8;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -14,7 +14,7 @@ class PasswordBrokerManager implements FactoryContract
|
||||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Foundation\Application
|
||||
* @var \Illuminate\Contracts\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
@@ -28,7 +28,7 @@ class PasswordBrokerManager implements FactoryContract
|
||||
/**
|
||||
* Create a new PasswordBroker manager instance.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($app)
|
||||
@@ -46,9 +46,7 @@ class PasswordBrokerManager implements FactoryContract
|
||||
{
|
||||
$name = $name ?: $this->getDefaultDriver();
|
||||
|
||||
return isset($this->brokers[$name])
|
||||
? $this->brokers[$name]
|
||||
: $this->brokers[$name] = $this->resolve($name);
|
||||
return $this->brokers[$name] ?? ($this->brokers[$name] = $this->resolve($name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -3,16 +3,10 @@
|
||||
namespace Illuminate\Auth\Passwords;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
|
||||
class PasswordResetServiceProvider extends ServiceProvider
|
||||
class PasswordResetServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = true;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
|
@@ -83,6 +83,6 @@ class Recaller
|
||||
{
|
||||
$segments = explode('|', $this->recaller);
|
||||
|
||||
return count($segments) == 3 && trim($segments[0]) !== '' && trim($segments[1]) !== '';
|
||||
return count($segments) === 3 && trim($segments[0]) !== '' && trim($segments[1]) !== '';
|
||||
}
|
||||
}
|
||||
|
@@ -135,9 +135,7 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
|
||||
// pull the user data on that cookie which serves as a remember cookie on
|
||||
// the application. Once we have a user we can return it to the caller.
|
||||
$recaller = $this->recaller();
|
||||
|
||||
if (is_null($this->user) && ! is_null($recaller)) {
|
||||
if (is_null($this->user) && ! is_null($recaller = $this->recaller())) {
|
||||
$this->user = $this->userFromRecaller($recaller);
|
||||
|
||||
if ($this->user) {
|
||||
@@ -329,6 +327,7 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
* Get the response for basic authentication.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
|
||||
*/
|
||||
protected function failedBasicResponse()
|
||||
@@ -488,12 +487,12 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
// listening for anytime a user signs out of this application manually.
|
||||
$this->clearUserDataFromStorage();
|
||||
|
||||
if (! is_null($this->user)) {
|
||||
if (! is_null($this->user) && ! empty($user->getRememberToken())) {
|
||||
$this->cycleRememberToken($user);
|
||||
}
|
||||
|
||||
if (isset($this->events)) {
|
||||
$this->events->dispatch(new Events\Logout($user));
|
||||
$this->events->dispatch(new Events\Logout($this->name, $user));
|
||||
}
|
||||
|
||||
// Once we have fired the logout event we will clear the users out of memory
|
||||
@@ -551,7 +550,12 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
$attribute => Hash::make($password),
|
||||
]))->save();
|
||||
|
||||
$this->queueRecallerCookie($this->user());
|
||||
if ($this->recaller() ||
|
||||
$this->getCookieJar()->hasQueued($this->getRecallerName())) {
|
||||
$this->queueRecallerCookie($this->user());
|
||||
}
|
||||
|
||||
$this->fireOtherDeviceLogoutEvent($this->user());
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -580,7 +584,7 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
{
|
||||
if (isset($this->events)) {
|
||||
$this->events->dispatch(new Events\Attempting(
|
||||
$credentials, $remember
|
||||
$this->name, $credentials, $remember
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -595,7 +599,9 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
protected function fireLoginEvent($user, $remember = false)
|
||||
{
|
||||
if (isset($this->events)) {
|
||||
$this->events->dispatch(new Events\Login($user, $remember));
|
||||
$this->events->dispatch(new Events\Login(
|
||||
$this->name, $user, $remember
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,7 +614,24 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
protected function fireAuthenticatedEvent($user)
|
||||
{
|
||||
if (isset($this->events)) {
|
||||
$this->events->dispatch(new Events\Authenticated($user));
|
||||
$this->events->dispatch(new Events\Authenticated(
|
||||
$this->name, $user
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the other device logout event if the dispatcher is set.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return void
|
||||
*/
|
||||
protected function fireOtherDeviceLogoutEvent($user)
|
||||
{
|
||||
if (isset($this->events)) {
|
||||
$this->events->dispatch(new Events\OtherDeviceLogout(
|
||||
$this->name, $user
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,7 +645,9 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
protected function fireFailedEvent($user, array $credentials)
|
||||
{
|
||||
if (isset($this->events)) {
|
||||
$this->events->dispatch(new Events\Failed($user, $credentials));
|
||||
$this->events->dispatch(new Events\Failed(
|
||||
$this->name, $user, $credentials
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,13 @@ class TokenGuard implements Guard
|
||||
*/
|
||||
protected $storageKey;
|
||||
|
||||
/**
|
||||
* Indicates if the API token is hashed in storage.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $hash = false;
|
||||
|
||||
/**
|
||||
* Create a new authentication guard.
|
||||
*
|
||||
@@ -38,10 +45,17 @@ class TokenGuard implements Guard
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $inputKey
|
||||
* @param string $storageKey
|
||||
* @param bool $hash
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(UserProvider $provider, Request $request, $inputKey = 'api_token', $storageKey = 'api_token')
|
||||
public function __construct(
|
||||
UserProvider $provider,
|
||||
Request $request,
|
||||
$inputKey = 'api_token',
|
||||
$storageKey = 'api_token',
|
||||
$hash = false)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
$this->request = $request;
|
||||
$this->provider = $provider;
|
||||
$this->inputKey = $inputKey;
|
||||
@@ -67,9 +81,9 @@ class TokenGuard implements Guard
|
||||
$token = $this->getTokenForRequest();
|
||||
|
||||
if (! empty($token)) {
|
||||
$user = $this->provider->retrieveByCredentials(
|
||||
[$this->storageKey => $token]
|
||||
);
|
||||
$user = $this->provider->retrieveByCredentials([
|
||||
$this->storageKey => $this->hash ? hash('sha256', $token) : $token,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->user = $user;
|
||||
|
@@ -15,10 +15,10 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"illuminate/contracts": "5.6.*",
|
||||
"illuminate/http": "5.6.*",
|
||||
"illuminate/queue": "5.6.*",
|
||||
"illuminate/support": "5.6.*"
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/http": "5.8.*",
|
||||
"illuminate/queue": "5.8.*",
|
||||
"illuminate/support": "5.8.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -27,13 +27,13 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.6-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/console": "Required to use the auth:clear-resets command (5.6.*).",
|
||||
"illuminate/queue": "Required to fire login / logout events (5.6.*).",
|
||||
"illuminate/session": "Required to use the session based guard (5.6.*)."
|
||||
"illuminate/console": "Required to use the auth:clear-resets command (5.8.*).",
|
||||
"illuminate/queue": "Required to fire login / logout events (5.8.*).",
|
||||
"illuminate/session": "Required to use the session based guard (5.8.*)."
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
|
@@ -16,6 +16,10 @@ class BroadcastController extends Controller
|
||||
*/
|
||||
public function authenticate(Request $request)
|
||||
{
|
||||
if ($request->hasSession()) {
|
||||
$request->session()->reflash();
|
||||
}
|
||||
|
||||
return Broadcast::auth($request);
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ class BroadcastManager implements FactoryContract
|
||||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Foundation\Application
|
||||
* @var \Illuminate\Contracts\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
@@ -42,7 +42,7 @@ class BroadcastManager implements FactoryContract
|
||||
/**
|
||||
* Create a new manager instance.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($app)
|
||||
@@ -132,7 +132,7 @@ class BroadcastManager implements FactoryContract
|
||||
/**
|
||||
* Get a driver instance.
|
||||
*
|
||||
* @param string $driver
|
||||
* @param string|null $driver
|
||||
* @return mixed
|
||||
*/
|
||||
public function connection($driver = null)
|
||||
@@ -165,7 +165,7 @@ class BroadcastManager implements FactoryContract
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given store.
|
||||
* Resolve the given broadcaster.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Contracts\Broadcasting\Broadcaster
|
||||
@@ -176,10 +176,6 @@ class BroadcastManager implements FactoryContract
|
||||
{
|
||||
$config = $this->getConfig($name);
|
||||
|
||||
if (is_null($config)) {
|
||||
throw new InvalidArgumentException("Broadcaster [{$name}] is not defined.");
|
||||
}
|
||||
|
||||
if (isset($this->customCreators[$config['driver']])) {
|
||||
return $this->callCustomCreator($config);
|
||||
}
|
||||
@@ -212,10 +208,16 @@ class BroadcastManager implements FactoryContract
|
||||
*/
|
||||
protected function createPusherDriver(array $config)
|
||||
{
|
||||
return new PusherBroadcaster(
|
||||
new Pusher($config['key'], $config['secret'],
|
||||
$config['app_id'], $config['options'] ?? [])
|
||||
$pusher = new Pusher(
|
||||
$config['key'], $config['secret'],
|
||||
$config['app_id'], $config['options'] ?? []
|
||||
);
|
||||
|
||||
if ($config['log'] ?? false) {
|
||||
$pusher->setLogger($this->app->make(LoggerInterface::class));
|
||||
}
|
||||
|
||||
return new PusherBroadcaster($pusher);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,7 +265,11 @@ class BroadcastManager implements FactoryContract
|
||||
*/
|
||||
protected function getConfig($name)
|
||||
{
|
||||
return $this->app['config']["broadcasting.connections.{$name}"];
|
||||
if (! is_null($name) && $name !== 'null') {
|
||||
return $this->app['config']["broadcasting.connections.{$name}"];
|
||||
}
|
||||
|
||||
return ['driver' => 'null'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -3,18 +3,12 @@
|
||||
namespace Illuminate\Broadcasting;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
use Illuminate\Contracts\Broadcasting\Factory as BroadcastingFactory;
|
||||
use Illuminate\Contracts\Broadcasting\Broadcaster as BroadcasterContract;
|
||||
|
||||
class BroadcastServiceProvider extends ServiceProvider
|
||||
class BroadcastServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = true;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
|
@@ -5,6 +5,7 @@ namespace Illuminate\Broadcasting\Broadcasters;
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunction;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Routing\UrlRoutable;
|
||||
@@ -21,10 +22,17 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
*/
|
||||
protected $channels = [];
|
||||
|
||||
/**
|
||||
* The registered channel options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $channelOptions = [];
|
||||
|
||||
/**
|
||||
* The binding registrar instance.
|
||||
*
|
||||
* @var BindingRegistrar
|
||||
* @var \Illuminate\Contracts\Routing\BindingRegistrar
|
||||
*/
|
||||
protected $bindingRegistrar;
|
||||
|
||||
@@ -33,12 +41,15 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
*
|
||||
* @param string $channel
|
||||
* @param callable|string $callback
|
||||
* @param array $options
|
||||
* @return $this
|
||||
*/
|
||||
public function channel($channel, $callback)
|
||||
public function channel($channel, $callback, $options = [])
|
||||
{
|
||||
$this->channels[$channel] = $callback;
|
||||
|
||||
$this->channelOptions[$channel] = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -48,12 +59,13 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $channel
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
protected function verifyUserCanAccessChannel($request, $channel)
|
||||
{
|
||||
foreach ($this->channels as $pattern => $callback) {
|
||||
if (! Str::is(preg_replace('/\{(.*?)\}/', '*', $pattern), $channel)) {
|
||||
if (! $this->channelNameMatchesPattern($channel, $pattern)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -61,7 +73,7 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
|
||||
$handler = $this->normalizeChannelHandlerToCallable($callback);
|
||||
|
||||
if ($result = $handler($request->user(), ...$parameters)) {
|
||||
if ($result = $handler($this->retrieveUser($request, $channel), ...$parameters)) {
|
||||
return $this->validAuthenticationResponse($request, $result);
|
||||
}
|
||||
}
|
||||
@@ -93,6 +105,7 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @return \ReflectionParameter[]
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function extractParameters($callback)
|
||||
@@ -111,6 +124,7 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
*
|
||||
* @param string $callback
|
||||
* @return \ReflectionParameter[]
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function extractParametersFromClass($callback)
|
||||
@@ -180,6 +194,7 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
* @param mixed $value
|
||||
* @param array $callbackParameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
protected function resolveImplicitBindingIfPossible($key, $value, $callbackParameters)
|
||||
@@ -256,4 +271,59 @@ abstract class Broadcaster implements BroadcasterContract
|
||||
->join(...$args);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the authenticated user using the configured guard (if any).
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $channel
|
||||
* @return mixed
|
||||
*/
|
||||
protected function retrieveUser($request, $channel)
|
||||
{
|
||||
$options = $this->retrieveChannelOptions($channel);
|
||||
|
||||
$guards = $options['guards'] ?? null;
|
||||
|
||||
if (is_null($guards)) {
|
||||
return $request->user();
|
||||
}
|
||||
|
||||
foreach (Arr::wrap($guards) as $guard) {
|
||||
if ($user = $request->user($guard)) {
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve options for a certain channel.
|
||||
*
|
||||
* @param string $channel
|
||||
* @return array
|
||||
*/
|
||||
protected function retrieveChannelOptions($channel)
|
||||
{
|
||||
foreach ($this->channelOptions as $pattern => $options) {
|
||||
if (! $this->channelNameMatchesPattern($channel, $pattern)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if channel name from request match a pattern from registered channels.
|
||||
*
|
||||
* @param string $channel
|
||||
* @param string $pattern
|
||||
* @return bool
|
||||
*/
|
||||
protected function channelNameMatchesPattern($channel, $pattern)
|
||||
{
|
||||
return Str::is(preg_replace('/\{(.*?)\}/', '*', $pattern), $channel);
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,8 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
class PusherBroadcaster extends Broadcaster
|
||||
{
|
||||
use UsePusherChannelConventions;
|
||||
|
||||
/**
|
||||
* The Pusher SDK instance.
|
||||
*
|
||||
@@ -33,19 +35,18 @@ class PusherBroadcaster extends Broadcaster
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
public function auth($request)
|
||||
{
|
||||
if (Str::startsWith($request->channel_name, ['private-', 'presence-']) &&
|
||||
! $request->user()) {
|
||||
$channelName = $this->normalizeChannelName($request->channel_name);
|
||||
|
||||
if ($this->isGuardedChannel($request->channel_name) &&
|
||||
! $this->retrieveUser($request, $channelName)) {
|
||||
throw new AccessDeniedHttpException;
|
||||
}
|
||||
|
||||
$channelName = Str::startsWith($request->channel_name, 'private-')
|
||||
? Str::replaceFirst('private-', '', $request->channel_name)
|
||||
: Str::replaceFirst('presence-', '', $request->channel_name);
|
||||
|
||||
return parent::verifyUserCanAccessChannel(
|
||||
$request, $channelName
|
||||
);
|
||||
@@ -66,11 +67,13 @@ class PusherBroadcaster extends Broadcaster
|
||||
);
|
||||
}
|
||||
|
||||
$channelName = $this->normalizeChannelName($request->channel_name);
|
||||
|
||||
return $this->decodePusherResponse(
|
||||
$request,
|
||||
$this->pusher->presence_auth(
|
||||
$request->channel_name, $request->socket_id,
|
||||
$request->user()->getAuthIdentifier(), $result
|
||||
$this->retrieveUser($request, $channelName)->getAuthIdentifier(), $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@@ -3,12 +3,13 @@
|
||||
namespace Illuminate\Broadcasting\Broadcasters;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Redis\Factory as Redis;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
class RedisBroadcaster extends Broadcaster
|
||||
{
|
||||
use UsePusherChannelConventions;
|
||||
|
||||
/**
|
||||
* The Redis instance.
|
||||
*
|
||||
@@ -41,19 +42,18 @@ class RedisBroadcaster extends Broadcaster
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
public function auth($request)
|
||||
{
|
||||
if (Str::startsWith($request->channel_name, ['private-', 'presence-']) &&
|
||||
! $request->user()) {
|
||||
$channelName = $this->normalizeChannelName($request->channel_name);
|
||||
|
||||
if ($this->isGuardedChannel($request->channel_name) &&
|
||||
! $this->retrieveUser($request, $channelName)) {
|
||||
throw new AccessDeniedHttpException;
|
||||
}
|
||||
|
||||
$channelName = Str::startsWith($request->channel_name, 'private-')
|
||||
? Str::replaceFirst('private-', '', $request->channel_name)
|
||||
: Str::replaceFirst('presence-', '', $request->channel_name);
|
||||
|
||||
return parent::verifyUserCanAccessChannel(
|
||||
$request, $channelName
|
||||
);
|
||||
@@ -72,8 +72,10 @@ class RedisBroadcaster extends Broadcaster
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
$channelName = $this->normalizeChannelName($request->channel_name);
|
||||
|
||||
return json_encode(['channel_data' => [
|
||||
'user_id' => $request->user()->getAuthIdentifier(),
|
||||
'user_id' => $this->retrieveUser($request, $channelName)->getAuthIdentifier(),
|
||||
'user_info' => $result,
|
||||
]]);
|
||||
}
|
||||
|
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Broadcasting\Broadcasters;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait UsePusherChannelConventions
|
||||
{
|
||||
/**
|
||||
* Return true if channel is protected by authentication.
|
||||
*
|
||||
* @param string $channel
|
||||
* @return bool
|
||||
*/
|
||||
public function isGuardedChannel($channel)
|
||||
{
|
||||
return Str::startsWith($channel, ['private-', 'presence-']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove prefix from channel name.
|
||||
*
|
||||
* @param string $channel
|
||||
* @return string
|
||||
*/
|
||||
public function normalizeChannelName($channel)
|
||||
{
|
||||
if ($this->isGuardedChannel($channel)) {
|
||||
return Str::startsWith($channel, 'private-')
|
||||
? Str::replaceFirst('private-', '', $channel)
|
||||
: Str::replaceFirst('presence-', '', $channel);
|
||||
}
|
||||
|
||||
return $channel;
|
||||
}
|
||||
}
|
21
vendor/laravel/framework/src/Illuminate/Broadcasting/LICENSE.md
vendored
Normal file
21
vendor/laravel/framework/src/Illuminate/Broadcasting/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@@ -15,11 +15,12 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"psr/log": "~1.0",
|
||||
"illuminate/bus": "5.6.*",
|
||||
"illuminate/contracts": "5.6.*",
|
||||
"illuminate/queue": "5.6.*",
|
||||
"illuminate/support": "5.6.*"
|
||||
"ext-json": "*",
|
||||
"psr/log": "^1.0",
|
||||
"illuminate/bus": "5.8.*",
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/queue": "5.8.*",
|
||||
"illuminate/support": "5.8.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -28,11 +29,11 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.6-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~3.0)."
|
||||
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^3.0)."
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
|
@@ -3,19 +3,13 @@
|
||||
namespace Illuminate\Bus;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
use Illuminate\Contracts\Bus\Dispatcher as DispatcherContract;
|
||||
use Illuminate\Contracts\Queue\Factory as QueueFactoryContract;
|
||||
use Illuminate\Contracts\Bus\QueueingDispatcher as QueueingDispatcherContract;
|
||||
|
||||
class BusServiceProvider extends ServiceProvider
|
||||
class BusServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = true;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
|
21
vendor/laravel/framework/src/Illuminate/Bus/LICENSE.md
vendored
Normal file
21
vendor/laravel/framework/src/Illuminate/Bus/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@@ -15,9 +15,9 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"illuminate/contracts": "5.6.*",
|
||||
"illuminate/pipeline": "5.6.*",
|
||||
"illuminate/support": "5.6.*"
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/pipeline": "5.8.*",
|
||||
"illuminate/support": "5.8.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.6-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
|
@@ -2,9 +2,7 @@
|
||||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
|
||||
class ApcStore extends TaggableStore implements Store
|
||||
class ApcStore extends TaggableStore
|
||||
{
|
||||
use RetrievesMultipleKeys;
|
||||
|
||||
@@ -51,16 +49,16 @@ class ApcStore extends TaggableStore implements Store
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache for a given number of minutes.
|
||||
* Store an item in the cache for a given number of seconds.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $minutes)
|
||||
public function put($key, $value, $seconds)
|
||||
{
|
||||
$this->apc->put($this->prefix.$key, $value, (int) ($minutes * 60));
|
||||
return $this->apc->put($this->prefix.$key, $value, $seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,11 +90,11 @@ class ApcStore extends TaggableStore implements Store
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
$this->put($key, $value, 0);
|
||||
return $this->put($key, $value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
|
||||
class ArrayStore extends TaggableStore implements Store
|
||||
class ArrayStore extends TaggableStore
|
||||
{
|
||||
use RetrievesMultipleKeys;
|
||||
use InteractsWithTime, RetrievesMultipleKeys;
|
||||
|
||||
/**
|
||||
* The array of stored values.
|
||||
@@ -23,20 +23,39 @@ class ArrayStore extends TaggableStore implements Store
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->storage[$key] ?? null;
|
||||
if (! isset($this->storage[$key])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$item = $this->storage[$key];
|
||||
|
||||
$expiresAt = $item['expiresAt'] ?? 0;
|
||||
|
||||
if ($expiresAt !== 0 && $this->currentTime() > $expiresAt) {
|
||||
$this->forget($key);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $item['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache for a given number of minutes.
|
||||
* Store an item in the cache for a given number of seconds.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $minutes)
|
||||
public function put($key, $value, $seconds)
|
||||
{
|
||||
$this->storage[$key] = $value;
|
||||
$this->storage[$key] = [
|
||||
'value' => $value,
|
||||
'expiresAt' => $this->calculateExpiration($seconds),
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,10 +67,15 @@ class ArrayStore extends TaggableStore implements Store
|
||||
*/
|
||||
public function increment($key, $value = 1)
|
||||
{
|
||||
$this->storage[$key] = ! isset($this->storage[$key])
|
||||
? $value : ((int) $this->storage[$key]) + $value;
|
||||
if (! isset($this->storage[$key])) {
|
||||
$this->forever($key, $value);
|
||||
|
||||
return $this->storage[$key];
|
||||
return $this->storage[$key]['value'];
|
||||
}
|
||||
|
||||
$this->storage[$key]['value'] = ((int) $this->storage[$key]['value']) + $value;
|
||||
|
||||
return $this->storage[$key]['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,11 +95,11 @@ class ArrayStore extends TaggableStore implements Store
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
$this->put($key, $value, 0);
|
||||
return $this->put($key, $value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,9 +110,13 @@ class ArrayStore extends TaggableStore implements Store
|
||||
*/
|
||||
public function forget($key)
|
||||
{
|
||||
unset($this->storage[$key]);
|
||||
if (array_key_exists($key, $this->storage)) {
|
||||
unset($this->storage[$key]);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,4 +140,26 @@ class ArrayStore extends TaggableStore implements Store
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the expiration time of the key.
|
||||
*
|
||||
* @param int $seconds
|
||||
* @return int
|
||||
*/
|
||||
protected function calculateExpiration($seconds)
|
||||
{
|
||||
return $this->toTimestamp($seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UNIX timestamp for the given number of seconds.
|
||||
*
|
||||
* @param int $seconds
|
||||
* @return int
|
||||
*/
|
||||
protected function toTimestamp($seconds)
|
||||
{
|
||||
return $seconds > 0 ? $this->availableAt($seconds) : 0;
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,9 @@
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Arr;
|
||||
use InvalidArgumentException;
|
||||
use Aws\DynamoDb\DynamoDbClient;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Contracts\Cache\Factory as FactoryContract;
|
||||
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
|
||||
@@ -16,7 +18,7 @@ class CacheManager implements FactoryContract
|
||||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Foundation\Application
|
||||
* @var \Illuminate\Contracts\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
@@ -37,7 +39,7 @@ class CacheManager implements FactoryContract
|
||||
/**
|
||||
* Create a new Cache manager instance.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($app)
|
||||
@@ -46,7 +48,7 @@ class CacheManager implements FactoryContract
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cache store instance by name.
|
||||
* Get a cache store instance by name, wrapped in a repository.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Contracts\Cache\Repository
|
||||
@@ -62,7 +64,7 @@ class CacheManager implements FactoryContract
|
||||
* Get a cache driver instance.
|
||||
*
|
||||
* @param string|null $driver
|
||||
* @return mixed
|
||||
* @return \Illuminate\Contracts\Cache\Repository
|
||||
*/
|
||||
public function driver($driver = null)
|
||||
{
|
||||
@@ -124,7 +126,7 @@ class CacheManager implements FactoryContract
|
||||
* Create an instance of the APC cache driver.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Cache\ApcStore
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createApcDriver(array $config)
|
||||
{
|
||||
@@ -136,7 +138,7 @@ class CacheManager implements FactoryContract
|
||||
/**
|
||||
* Create an instance of the array cache driver.
|
||||
*
|
||||
* @return \Illuminate\Cache\ArrayStore
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createArrayDriver()
|
||||
{
|
||||
@@ -147,7 +149,7 @@ class CacheManager implements FactoryContract
|
||||
* Create an instance of the file cache driver.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Cache\FileStore
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createFileDriver(array $config)
|
||||
{
|
||||
@@ -158,7 +160,7 @@ class CacheManager implements FactoryContract
|
||||
* Create an instance of the Memcached cache driver.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Cache\MemcachedStore
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createMemcachedDriver(array $config)
|
||||
{
|
||||
@@ -177,7 +179,7 @@ class CacheManager implements FactoryContract
|
||||
/**
|
||||
* Create an instance of the Null cache driver.
|
||||
*
|
||||
* @return \Illuminate\Cache\NullStore
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createNullDriver()
|
||||
{
|
||||
@@ -188,7 +190,7 @@ class CacheManager implements FactoryContract
|
||||
* Create an instance of the Redis cache driver.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Cache\RedisStore
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createRedisDriver(array $config)
|
||||
{
|
||||
@@ -203,7 +205,7 @@ class CacheManager implements FactoryContract
|
||||
* Create an instance of the database cache driver.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Cache\DatabaseStore
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createDatabaseDriver(array $config)
|
||||
{
|
||||
@@ -216,6 +218,38 @@ class CacheManager implements FactoryContract
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the DynamoDB cache driver.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Cache\Repository
|
||||
*/
|
||||
protected function createDynamodbDriver(array $config)
|
||||
{
|
||||
$dynamoConfig = [
|
||||
'region' => $config['region'],
|
||||
'version' => 'latest',
|
||||
'endpoint' => $config['endpoint'] ?? null,
|
||||
];
|
||||
|
||||
if ($config['key'] && $config['secret']) {
|
||||
$dynamoConfig['credentials'] = Arr::only(
|
||||
$config, ['key', 'secret', 'token']
|
||||
);
|
||||
}
|
||||
|
||||
return $this->repository(
|
||||
new DynamoDbStore(
|
||||
new DynamoDbClient($dynamoConfig),
|
||||
$config['table'],
|
||||
$config['attributes']['key'] ?? 'key',
|
||||
$config['attributes']['value'] ?? 'value',
|
||||
$config['attributes']['expiration'] ?? 'expires_at',
|
||||
$this->getPrefix($config)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new cache repository with the given implementation.
|
||||
*
|
||||
@@ -278,10 +312,29 @@ class CacheManager implements FactoryContract
|
||||
$this->app['config']['cache.default'] = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the given driver instances.
|
||||
*
|
||||
* @param array|string|null $name
|
||||
* @return $this
|
||||
*/
|
||||
public function forgetDriver($name = null)
|
||||
{
|
||||
$name = $name ?? $this->getDefaultDriver();
|
||||
|
||||
foreach ((array) $name as $cacheName) {
|
||||
if (isset($this->stores[$cacheName])) {
|
||||
unset($this->stores[$cacheName]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom driver creator Closure.
|
||||
*
|
||||
* @param string $driver
|
||||
* @param string $driver
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
@@ -296,7 +349,7 @@ class CacheManager implements FactoryContract
|
||||
* Dynamically call the default driver instance.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
|
@@ -3,16 +3,10 @@
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
|
||||
class CacheServiceProvider extends ServiceProvider
|
||||
class CacheServiceProvider extends ServiceProvider implements DeferrableProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = true;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
|
@@ -60,15 +60,19 @@ class ClearCommand extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->laravel['events']->fire(
|
||||
$this->laravel['events']->dispatch(
|
||||
'cache:clearing', [$this->argument('store'), $this->tags()]
|
||||
);
|
||||
|
||||
$this->cache()->flush();
|
||||
$successful = $this->cache()->flush();
|
||||
|
||||
$this->flushFacades();
|
||||
|
||||
$this->laravel['events']->fire(
|
||||
if (! $successful) {
|
||||
return $this->error('Failed to clear cache. Make sure you have the appropriate permissions.');
|
||||
}
|
||||
|
||||
$this->laravel['events']->dispatch(
|
||||
'cache:cleared', [$this->argument('store'), $this->tags()]
|
||||
);
|
||||
|
||||
@@ -123,7 +127,7 @@ class ClearCommand extends Command
|
||||
protected function getArguments()
|
||||
{
|
||||
return [
|
||||
['store', InputArgument::OPTIONAL, 'The name of the store you would like to clear.'],
|
||||
['store', InputArgument::OPTIONAL, 'The name of the store you would like to clear'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -135,7 +139,7 @@ class ClearCommand extends Command
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['tags', null, InputOption::VALUE_OPTIONAL, 'The cache tags you would like to clear.', null],
|
||||
['tags', null, InputOption::VALUE_OPTIONAL, 'The cache tags you would like to clear', null],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -4,8 +4,10 @@ namespace Illuminate\Cache;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Illuminate\Database\PostgresConnection;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
|
||||
class DatabaseStore implements Store
|
||||
@@ -78,29 +80,31 @@ class DatabaseStore implements Store
|
||||
return;
|
||||
}
|
||||
|
||||
return unserialize($cache->value);
|
||||
return $this->unserialize($cache->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache for a given number of minutes.
|
||||
* Store an item in the cache for a given number of seconds.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $minutes)
|
||||
public function put($key, $value, $seconds)
|
||||
{
|
||||
$key = $this->prefix.$key;
|
||||
|
||||
$value = serialize($value);
|
||||
$value = $this->serialize($value);
|
||||
|
||||
$expiration = $this->getTime() + (int) ($minutes * 60);
|
||||
$expiration = $this->getTime() + $seconds;
|
||||
|
||||
try {
|
||||
$this->table()->insert(compact('key', 'value', 'expiration'));
|
||||
return $this->table()->insert(compact('key', 'value', 'expiration'));
|
||||
} catch (Exception $e) {
|
||||
$this->table()->where('key', $key)->update(compact('value', 'expiration'));
|
||||
$result = $this->table()->where('key', $key)->update(compact('value', 'expiration'));
|
||||
|
||||
return $result > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +161,7 @@ class DatabaseStore implements Store
|
||||
|
||||
$cache = is_array($cache) ? (object) $cache : $cache;
|
||||
|
||||
$current = unserialize($cache->value);
|
||||
$current = $this->unserialize($cache->value);
|
||||
|
||||
// Here we'll call this callback function that was given to the function which
|
||||
// is used to either increment or decrement the function. We use a callback
|
||||
@@ -172,7 +176,7 @@ class DatabaseStore implements Store
|
||||
// since database cache values are encrypted by default with secure storage
|
||||
// that can't be easily read. We will return the new value after storing.
|
||||
$this->table()->where('key', $prefixed)->update([
|
||||
'value' => serialize($new),
|
||||
'value' => $this->serialize($new),
|
||||
]);
|
||||
|
||||
return $new;
|
||||
@@ -194,11 +198,11 @@ class DatabaseStore implements Store
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
$this->put($key, $value, 5256000);
|
||||
return $this->put($key, $value, 315360000);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +225,9 @@ class DatabaseStore implements Store
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
return (bool) $this->table()->delete();
|
||||
$this->table()->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,4 +259,36 @@ class DatabaseStore implements Store
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function serialize($value)
|
||||
{
|
||||
$result = serialize($value);
|
||||
|
||||
if ($this->connection instanceof PostgresConnection && Str::contains($result, "\0")) {
|
||||
$result = base64_encode($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize the given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function unserialize($value)
|
||||
{
|
||||
if ($this->connection instanceof PostgresConnection && ! Str::contains($value, [':', ';'])) {
|
||||
$value = base64_decode($value);
|
||||
}
|
||||
|
||||
return unserialize($value);
|
||||
}
|
||||
}
|
||||
|
73
vendor/laravel/framework/src/Illuminate/Cache/DynamoDbLock.php
vendored
Normal file
73
vendor/laravel/framework/src/Illuminate/Cache/DynamoDbLock.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
class DynamoDbLock extends Lock
|
||||
{
|
||||
/**
|
||||
* The DynamoDB client instance.
|
||||
*
|
||||
* @var \Illuminate\Cache\DynamoDbStore
|
||||
*/
|
||||
protected $dynamo;
|
||||
|
||||
/**
|
||||
* Create a new lock instance.
|
||||
*
|
||||
* @param \Illuminate\Cache\DynamoDbStore $dynamo
|
||||
* @param string $name
|
||||
* @param int $seconds
|
||||
* @param string|null $owner
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(DynamoDbStore $dynamo, $name, $seconds, $owner = null)
|
||||
{
|
||||
parent::__construct($name, $seconds, $owner);
|
||||
|
||||
$this->dynamo = $dynamo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to acquire the lock.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function acquire()
|
||||
{
|
||||
return $this->dynamo->add(
|
||||
$this->name, $this->owner, $this->seconds
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the lock.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function release()
|
||||
{
|
||||
if ($this->isOwnedByCurrentProcess()) {
|
||||
$this->dynamo->forget($this->name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release this lock in disregard of ownership.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forceRelease()
|
||||
{
|
||||
$this->dynamo->forget($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner value written into the driver for this lock.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getCurrentOwner()
|
||||
{
|
||||
return $this->dynamo->get($this->name);
|
||||
}
|
||||
}
|
525
vendor/laravel/framework/src/Illuminate/Cache/DynamoDbStore.php
vendored
Normal file
525
vendor/laravel/framework/src/Illuminate/Cache/DynamoDbStore.php
vendored
Normal file
@@ -0,0 +1,525 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use RuntimeException;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Aws\DynamoDb\DynamoDbClient;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Illuminate\Contracts\Cache\LockProvider;
|
||||
use Aws\DynamoDb\Exception\DynamoDbException;
|
||||
|
||||
class DynamoDbStore implements Store, LockProvider
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
/**
|
||||
* The DynamoDB client instance.
|
||||
*
|
||||
* @var \Aws\DynamoDb\DynamoDbClient
|
||||
*/
|
||||
protected $dynamo;
|
||||
|
||||
/**
|
||||
* The table name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The name of the attribute that should hold the key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyAttribute;
|
||||
|
||||
/**
|
||||
* The name of the attribute that should hold the value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $valueAttribute;
|
||||
|
||||
/**
|
||||
* The name of the attribute that should hold the expiration timestamp.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $expirationAttribute;
|
||||
|
||||
/**
|
||||
* A string that should be prepended to keys.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* Create a new store instance.
|
||||
*
|
||||
* @param \Aws\DynamoDb\DynamoDbClient $dynamo
|
||||
* @param string $table
|
||||
* @param string $keyAttribute
|
||||
* @param string $valueAttribute
|
||||
* @param string $expirationAttribute
|
||||
* @param string $prefix
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(DynamoDbClient $dynamo,
|
||||
$table,
|
||||
$keyAttribute = 'key',
|
||||
$valueAttribute = 'value',
|
||||
$expirationAttribute = 'expires_at',
|
||||
$prefix = '')
|
||||
{
|
||||
$this->table = $table;
|
||||
$this->dynamo = $dynamo;
|
||||
$this->keyAttribute = $keyAttribute;
|
||||
$this->valueAttribute = $valueAttribute;
|
||||
$this->expirationAttribute = $expirationAttribute;
|
||||
|
||||
$this->setPrefix($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an item from the cache by key.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
$response = $this->dynamo->getItem([
|
||||
'TableName' => $this->table,
|
||||
'ConsistentRead' => false,
|
||||
'Key' => [
|
||||
$this->keyAttribute => [
|
||||
'S' => $this->prefix.$key,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
if (! isset($response['Item'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->isExpired($response['Item'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($response['Item'][$this->valueAttribute])) {
|
||||
return $this->unserialize(
|
||||
$response['Item'][$this->valueAttribute]['S'] ??
|
||||
$response['Item'][$this->valueAttribute]['N'] ??
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve multiple items from the cache by key.
|
||||
*
|
||||
* Items not found in the cache will have a null value.
|
||||
*
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
public function many(array $keys)
|
||||
{
|
||||
$prefixedKeys = array_map(function ($key) {
|
||||
return $this->prefix.$key;
|
||||
}, $keys);
|
||||
|
||||
$response = $this->dynamo->batchGetItem([
|
||||
'RequestItems' => [
|
||||
$this->table => [
|
||||
'ConsistentRead' => false,
|
||||
'Keys' => collect($prefixedKeys)->map(function ($key) {
|
||||
return [
|
||||
$this->keyAttribute => [
|
||||
'S' => $key,
|
||||
],
|
||||
];
|
||||
})->all(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$now = Carbon::now();
|
||||
|
||||
return array_merge(collect(array_flip($keys))->map(function () {
|
||||
})->all(), collect($response['Responses'][$this->table])->mapWithKeys(function ($response) use ($now) {
|
||||
if ($this->isExpired($response, $now)) {
|
||||
$value = null;
|
||||
} else {
|
||||
$value = $this->unserialize(
|
||||
$response[$this->valueAttribute]['S'] ??
|
||||
$response[$this->valueAttribute]['N'] ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
return [Str::replaceFirst($this->prefix, '', $response[$this->keyAttribute]['S']) => $value];
|
||||
})->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given item is expired.
|
||||
*
|
||||
* @param array $item
|
||||
* @param \DateTimeInterface|null $expiration
|
||||
* @return bool
|
||||
*/
|
||||
protected function isExpired(array $item, $expiration = null)
|
||||
{
|
||||
$expiration = $expiration ?: Carbon::now();
|
||||
|
||||
return isset($item[$this->expirationAttribute]) &&
|
||||
$expiration->getTimestamp() >= $item[$this->expirationAttribute]['N'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache for a given number of seconds.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $seconds)
|
||||
{
|
||||
$this->dynamo->putItem([
|
||||
'TableName' => $this->table,
|
||||
'Item' => [
|
||||
$this->keyAttribute => [
|
||||
'S' => $this->prefix.$key,
|
||||
],
|
||||
$this->valueAttribute => [
|
||||
$this->type($value) => $this->serialize($value),
|
||||
],
|
||||
$this->expirationAttribute => [
|
||||
'N' => (string) $this->toTimestamp($seconds),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache for a given number of $seconds.
|
||||
*
|
||||
* @param array $values
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function putMany(array $values, $seconds)
|
||||
{
|
||||
$expiration = $this->toTimestamp($seconds);
|
||||
|
||||
$this->dynamo->batchWriteItem([
|
||||
'RequestItems' => [
|
||||
$this->table => collect($values)->map(function ($value, $key) use ($expiration) {
|
||||
return [
|
||||
'PutRequest' => [
|
||||
'Item' => [
|
||||
$this->keyAttribute => [
|
||||
'S' => $this->prefix.$key,
|
||||
],
|
||||
$this->valueAttribute => [
|
||||
$this->type($value) => $this->serialize($value),
|
||||
],
|
||||
$this->expirationAttribute => [
|
||||
'N' => (string) $expiration,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
})->values()->all(),
|
||||
],
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache if the key doesn't exist.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function add($key, $value, $seconds)
|
||||
{
|
||||
try {
|
||||
$this->dynamo->putItem([
|
||||
'TableName' => $this->table,
|
||||
'Item' => [
|
||||
$this->keyAttribute => [
|
||||
'S' => $this->prefix.$key,
|
||||
],
|
||||
$this->valueAttribute => [
|
||||
$this->type($value) => $this->serialize($value),
|
||||
],
|
||||
$this->expirationAttribute => [
|
||||
'N' => (string) $this->toTimestamp($seconds),
|
||||
],
|
||||
],
|
||||
'ConditionExpression' => 'attribute_not_exists(#key) OR #expires_at < :now',
|
||||
'ExpressionAttributeNames' => [
|
||||
'#key' => $this->keyAttribute,
|
||||
'#expires_at' => $this->expirationAttribute,
|
||||
],
|
||||
'ExpressionAttributeValues' => [
|
||||
':now' => [
|
||||
'N' => (string) Carbon::now()->getTimestamp(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (DynamoDbException $e) {
|
||||
if (Str::contains($e->getMessage(), 'ConditionalCheckFailed')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the value of an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return int|bool
|
||||
*/
|
||||
public function increment($key, $value = 1)
|
||||
{
|
||||
try {
|
||||
$response = $this->dynamo->updateItem([
|
||||
'TableName' => $this->table,
|
||||
'Key' => [
|
||||
$this->keyAttribute => [
|
||||
'S' => $this->prefix.$key,
|
||||
],
|
||||
],
|
||||
'ConditionExpression' => 'attribute_exists(#key) AND #expires_at > :now',
|
||||
'UpdateExpression' => 'SET #value = #value + :amount',
|
||||
'ExpressionAttributeNames' => [
|
||||
'#key' => $this->keyAttribute,
|
||||
'#value' => $this->valueAttribute,
|
||||
'#expires_at' => $this->expirationAttribute,
|
||||
],
|
||||
'ExpressionAttributeValues' => [
|
||||
':now' => [
|
||||
'N' => (string) Carbon::now()->getTimestamp(),
|
||||
],
|
||||
':amount' => [
|
||||
'N' => (string) $value,
|
||||
],
|
||||
],
|
||||
'ReturnValues' => 'UPDATED_NEW',
|
||||
]);
|
||||
|
||||
return (int) $response['Attributes'][$this->valueAttribute]['N'];
|
||||
} catch (DynamoDbException $e) {
|
||||
if (Str::contains($e->getMessage(), 'ConditionalCheckFailed')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the value of an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return int|bool
|
||||
*/
|
||||
public function decrement($key, $value = 1)
|
||||
{
|
||||
try {
|
||||
$response = $this->dynamo->updateItem([
|
||||
'TableName' => $this->table,
|
||||
'Key' => [
|
||||
$this->keyAttribute => [
|
||||
'S' => $this->prefix.$key,
|
||||
],
|
||||
],
|
||||
'ConditionExpression' => 'attribute_exists(#key) AND #expires_at > :now',
|
||||
'UpdateExpression' => 'SET #value = #value - :amount',
|
||||
'ExpressionAttributeNames' => [
|
||||
'#key' => $this->keyAttribute,
|
||||
'#value' => $this->valueAttribute,
|
||||
'#expires_at' => $this->expirationAttribute,
|
||||
],
|
||||
'ExpressionAttributeValues' => [
|
||||
':now' => [
|
||||
'N' => (string) Carbon::now()->getTimestamp(),
|
||||
],
|
||||
':amount' => [
|
||||
'N' => (string) $value,
|
||||
],
|
||||
],
|
||||
'ReturnValues' => 'UPDATED_NEW',
|
||||
]);
|
||||
|
||||
return (int) $response['Attributes'][$this->valueAttribute]['N'];
|
||||
} catch (DynamoDbException $e) {
|
||||
if (Str::contains($e->getMessage(), 'ConditionalCheckFailed')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache indefinitely.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
return $this->put($key, $value, now()->addYears(5)->getTimestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a lock instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param int $seconds
|
||||
* @param string|null $owner
|
||||
* @return \Illuminate\Contracts\Cache\Lock
|
||||
*/
|
||||
public function lock($name, $seconds = 0, $owner = null)
|
||||
{
|
||||
return new DynamoDbLock($this, $this->prefix.$name, $seconds, $owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a lock instance using the owner identifier.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $owner
|
||||
* @return \Illuminate\Contracts\Cache\Lock
|
||||
*/
|
||||
public function restoreLock($name, $owner)
|
||||
{
|
||||
return $this->lock($name, 0, $owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function forget($key)
|
||||
{
|
||||
$this->dynamo->deleteItem([
|
||||
'TableName' => $this->table,
|
||||
'Key' => [
|
||||
$this->keyAttribute => [
|
||||
'S' => $this->prefix.$key,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from the cache.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
throw new RuntimeException('DynamoDb does not support flushing an entire table. Please create a new table.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UNIX timestamp for the given number of seconds.
|
||||
*
|
||||
* @param int $seconds
|
||||
* @return int
|
||||
*/
|
||||
protected function toTimestamp($seconds)
|
||||
{
|
||||
return $seconds > 0
|
||||
? $this->availableAt($seconds)
|
||||
: Carbon::now()->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function serialize($value)
|
||||
{
|
||||
return is_numeric($value) ? (string) $value : serialize($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserialize the value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function unserialize($value)
|
||||
{
|
||||
if (filter_var($value, FILTER_VALIDATE_INT) !== false) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return (float) $value;
|
||||
}
|
||||
|
||||
return unserialize($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DynamoDB type for the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function type($value)
|
||||
{
|
||||
return is_numeric($value) ? 'N' : 'S';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache key prefix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPrefix()
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache key prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return void
|
||||
*/
|
||||
public function setPrefix($prefix)
|
||||
{
|
||||
$this->prefix = ! empty($prefix) ? $prefix.':' : '';
|
||||
}
|
||||
}
|
@@ -12,26 +12,26 @@ class KeyWritten extends CacheEvent
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* The number of minutes the key should be valid.
|
||||
* The number of seconds the key should be valid.
|
||||
*
|
||||
* @var int
|
||||
* @var int|null
|
||||
*/
|
||||
public $minutes;
|
||||
public $seconds;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $minutes
|
||||
* @param int|null $seconds
|
||||
* @param array $tags
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($key, $value, $minutes, $tags = [])
|
||||
public function __construct($key, $value, $seconds = null, $tags = [])
|
||||
{
|
||||
parent::__construct($key, $tags);
|
||||
|
||||
$this->value = $value;
|
||||
$this->minutes = $minutes;
|
||||
$this->seconds = $seconds;
|
||||
}
|
||||
}
|
||||
|
@@ -50,20 +50,22 @@ class FileStore implements Store
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache for a given number of minutes.
|
||||
* Store an item in the cache for a given number of seconds.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $minutes)
|
||||
public function put($key, $value, $seconds)
|
||||
{
|
||||
$this->ensureCacheDirectoryExists($path = $this->path($key));
|
||||
|
||||
$this->files->put(
|
||||
$path, $this->expiration($minutes).serialize($value), true
|
||||
$result = $this->files->put(
|
||||
$path, $this->expiration($seconds).serialize($value), true
|
||||
);
|
||||
|
||||
return $result !== false && $result > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,11 +114,11 @@ class FileStore implements Store
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
$this->put($key, $value, 0);
|
||||
return $this->put($key, $value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,12 +186,18 @@ class FileStore implements Store
|
||||
return $this->emptyPayload();
|
||||
}
|
||||
|
||||
$data = unserialize(substr($contents, 10));
|
||||
try {
|
||||
$data = unserialize(substr($contents, 10));
|
||||
} catch (Exception $e) {
|
||||
$this->forget($key);
|
||||
|
||||
// Next, we'll extract the number of minutes that are remaining for a cache
|
||||
return $this->emptyPayload();
|
||||
}
|
||||
|
||||
// Next, we'll extract the number of seconds that are remaining for a cache
|
||||
// so that we can properly retain the time for things like the increment
|
||||
// operation that may be performed on this cache on a later operation.
|
||||
$time = ($expire - $this->currentTime()) / 60;
|
||||
$time = $expire - $this->currentTime();
|
||||
|
||||
return compact('data', 'time');
|
||||
}
|
||||
@@ -218,16 +226,16 @@ class FileStore implements Store
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the expiration time based on the given minutes.
|
||||
* Get the expiration time based on the given seconds.
|
||||
*
|
||||
* @param float|int $minutes
|
||||
* @param int $seconds
|
||||
* @return int
|
||||
*/
|
||||
protected function expiration($minutes)
|
||||
protected function expiration($seconds)
|
||||
{
|
||||
$time = $this->availableAt((int) ($minutes * 60));
|
||||
$time = $this->availableAt($seconds);
|
||||
|
||||
return $minutes === 0 || $time > 9999999999 ? 9999999999 : (int) $time;
|
||||
return $seconds === 0 || $time > 9999999999 ? 9999999999 : $time;
|
||||
}
|
||||
|
||||
/**
|
||||
|
21
vendor/laravel/framework/src/Illuminate/Cache/LICENSE.md
vendored
Normal file
21
vendor/laravel/framework/src/Illuminate/Cache/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user