updated backend
This commit is contained in:
parent
1fea0f4fe7
commit
11521c2339
3459 changed files with 72735 additions and 168535 deletions
12
pfosten/vendor/laravel/framework/README.md
vendored
12
pfosten/vendor/laravel/framework/README.md
vendored
|
|
@ -20,17 +20,17 @@ 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 give you tools you need 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
|
||||
|
||||
Laravel has the most extensive and thorough documentation and video tutorial library of any modern web application framework. The [Laravel documentation](https://laravel.com/docs) is thorough, complete, and makes it a breeze to get started learning the framework.
|
||||
Laravel has the most extensive and thorough documentation and video tutorial library of any modern web application framework. The [Laravel documentation](https://laravel.com/docs) is in-depth and complete, making it a breeze to get started learning the framework.
|
||||
|
||||
If you're not in the mood to read, [Laracasts](https://laracasts.com) contains over 900 video tutorials covering a range of topics including Laravel, modern PHP, unit testing, JavaScript, and more. Boost the skill level of yourself and your entire team by digging into our comprehensive video library.
|
||||
If you're not in the mood to read, [Laracasts](https://laracasts.com) contains over 1100 video tutorials covering a range of topics including Laravel, modern PHP, unit testing, JavaScript, and more. Boost the skill level of yourself and your entire team by digging into our comprehensive video library.
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](http://laravel.com/docs/contributions).
|
||||
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ 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 at 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
|
||||
|
||||
The Laravel framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
|
||||
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
|
|
|
|||
111
pfosten/vendor/laravel/framework/composer.json
vendored
111
pfosten/vendor/laravel/framework/composer.json
vendored
|
|
@ -15,28 +15,32 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"php": "^7.1.3",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"doctrine/inflector": "~1.1",
|
||||
"erusev/parsedown": "~1.6",
|
||||
"league/flysystem": "~1.0",
|
||||
"monolog/monolog": "~1.11",
|
||||
"mtdowling/cron-expression": "~1.0",
|
||||
"nesbot/carbon": "~1.20",
|
||||
"paragonie/random_compat": "~1.4|~2.0",
|
||||
"ramsey/uuid": "~3.0",
|
||||
"swiftmailer/swiftmailer": "~5.4",
|
||||
"symfony/console": "~3.2",
|
||||
"symfony/debug": "~3.2",
|
||||
"symfony/finder": "~3.2",
|
||||
"symfony/http-foundation": "~3.2",
|
||||
"symfony/http-kernel": "~3.2",
|
||||
"symfony/process": "~3.2",
|
||||
"symfony/routing": "~3.2",
|
||||
"symfony/var-dumper": "~3.2",
|
||||
"tijsverkoyen/css-to-inline-styles": "~2.2",
|
||||
"vlucas/phpdotenv": "~2.2"
|
||||
"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.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.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": "^3.3"
|
||||
},
|
||||
"replace": {
|
||||
"illuminate/auth": "self.version",
|
||||
|
|
@ -51,7 +55,6 @@
|
|||
"illuminate/database": "self.version",
|
||||
"illuminate/encryption": "self.version",
|
||||
"illuminate/events": "self.version",
|
||||
"illuminate/exception": "self.version",
|
||||
"illuminate/filesystem": "self.version",
|
||||
"illuminate/hashing": "self.version",
|
||||
"illuminate/http": "self.version",
|
||||
|
|
@ -67,18 +70,26 @@
|
|||
"illuminate/support": "self.version",
|
||||
"illuminate/translation": "self.version",
|
||||
"illuminate/validation": "self.version",
|
||||
"illuminate/view": "self.version",
|
||||
"tightenco/collect": "self.version"
|
||||
"illuminate/view": "self.version"
|
||||
},
|
||||
"conflict": {
|
||||
"tightenco/collect": "<5.5.33"
|
||||
},
|
||||
"require-dev": {
|
||||
"aws/aws-sdk-php": "~3.0",
|
||||
"doctrine/dbal": "~2.5",
|
||||
"mockery/mockery": "~0.9.4",
|
||||
"pda/pheanstalk": "~3.0",
|
||||
"phpunit/phpunit": "~5.7",
|
||||
"predis/predis": "~1.0",
|
||||
"symfony/css-selector": "~3.2",
|
||||
"symfony/dom-crawler": "~3.2"
|
||||
"aws/aws-sdk-php": "^3.0",
|
||||
"doctrine/dbal": "^2.6",
|
||||
"filp/whoops": "^2.1.4",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"mockery/mockery": "^1.0",
|
||||
"moontoast/math": "^1.1",
|
||||
"orchestra/testbench-core": "3.8.*",
|
||||
"pda/pheanstalk": "^4.0",
|
||||
"phpunit/phpunit": "^7.5|^8.0",
|
||||
"predis/predis": "^1.1.1",
|
||||
"symfony/css-selector": "^4.2",
|
||||
"symfony/dom-crawler": "^4.2",
|
||||
"true/punycode": "^2.1"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
|
|
@ -99,24 +110,32 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).",
|
||||
"doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.5).",
|
||||
"fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).",
|
||||
"guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (~6.0).",
|
||||
"laravel/tinker": "Required to use the tinker console command (~1.0).",
|
||||
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).",
|
||||
"league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).",
|
||||
"nexmo/client": "Required to use the Nexmo transport (~1.0).",
|
||||
"pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).",
|
||||
"predis/predis": "Required to use the redis cache and queue drivers (~1.0).",
|
||||
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).",
|
||||
"symfony/css-selector": "Required to use some of the crawler integration testing tools (~3.2).",
|
||||
"symfony/dom-crawler": "Required to use most of the crawler integration testing tools (~3.2).",
|
||||
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)."
|
||||
"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).",
|
||||
"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,10 @@
|
|||
|
||||
namespace Illuminate\Auth\Access;
|
||||
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunction;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
|
|
@ -53,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.
|
||||
*
|
||||
|
|
@ -62,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;
|
||||
|
|
@ -73,17 +93,26 @@ class Gate implements GateContract
|
|||
$this->userResolver = $userResolver;
|
||||
$this->afterCallbacks = $afterCallbacks;
|
||||
$this->beforeCallbacks = $beforeCallbacks;
|
||||
$this->guessPolicyNamesUsingCallback = $guessPolicyNamesUsingCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given ability has been defined.
|
||||
*
|
||||
* @param string $ability
|
||||
* @param string|array $ability
|
||||
* @return bool
|
||||
*/
|
||||
public function has($ability)
|
||||
{
|
||||
return isset($this->abilities[$ability]);
|
||||
$abilities = is_array($ability) ? $ability : func_get_args();
|
||||
|
||||
foreach ($abilities as $ability) {
|
||||
if (! isset($this->abilities[$ability])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,8 +128,10 @@ class Gate implements GateContract
|
|||
{
|
||||
if (is_callable($callback)) {
|
||||
$this->abilities[$ability] = $callback;
|
||||
} elseif (is_string($callback) && Str::contains($callback, '@')) {
|
||||
$this->abilities[$ability] = $this->buildAbilityCallback($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.");
|
||||
}
|
||||
|
|
@ -113,16 +144,17 @@ class Gate implements GateContract
|
|||
*
|
||||
* @param string $name
|
||||
* @param string $class
|
||||
* @param array $abilities
|
||||
* @param array|null $abilities
|
||||
* @return $this
|
||||
*/
|
||||
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) {
|
||||
|
|
@ -135,15 +167,36 @@ class Gate implements GateContract
|
|||
/**
|
||||
* Create the ability callback for a callback string.
|
||||
*
|
||||
* @param string $ability
|
||||
* @param string $callback
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function buildAbilityCallback($callback)
|
||||
protected function buildAbilityCallback($ability, $callback)
|
||||
{
|
||||
return function () use ($callback) {
|
||||
list($class, $method) = Str::parseCallback($callback);
|
||||
return function () use ($ability, $callback) {
|
||||
if (Str::contains($callback, '@')) {
|
||||
[$class, $method] = Str::parseCallback($callback);
|
||||
} else {
|
||||
$class = $callback;
|
||||
}
|
||||
|
||||
return $this->resolvePolicy($class)->{$method}(...func_get_args());
|
||||
$policy = $this->resolvePolicy($class);
|
||||
|
||||
$arguments = func_get_args();
|
||||
|
||||
$user = array_shift($arguments);
|
||||
|
||||
$result = $this->callPolicyBefore(
|
||||
$policy, $user, $ability, $arguments
|
||||
);
|
||||
|
||||
if (! is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return isset($method)
|
||||
? $policy->{$method}(...func_get_args())
|
||||
: $policy(...func_get_args());
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -212,19 +265,47 @@ class Gate implements GateContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Determine if the given ability should be granted for the current user.
|
||||
* Determine if all of the given abilities should be granted for the current user.
|
||||
*
|
||||
* @param string $ability
|
||||
* @param iterable|string $abilities
|
||||
* @param array|mixed $arguments
|
||||
* @return bool
|
||||
*/
|
||||
public function check($ability, $arguments = [])
|
||||
public function check($abilities, $arguments = [])
|
||||
{
|
||||
try {
|
||||
return (bool) $this->raw($ability, $arguments);
|
||||
} catch (AuthorizationException $e) {
|
||||
return false;
|
||||
}
|
||||
return collect($abilities)->every(function ($ability) use ($arguments) {
|
||||
try {
|
||||
return (bool) $this->raw($ability, $arguments);
|
||||
} catch (AuthorizationException $e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any one of the given abilities should be granted for the current user.
|
||||
*
|
||||
* @param iterable|string $abilities
|
||||
* @param array|mixed $arguments
|
||||
* @return bool
|
||||
*/
|
||||
public function any($abilities, $arguments = [])
|
||||
{
|
||||
return collect($abilities)->contains(function ($ability) use ($arguments) {
|
||||
return $this->check($ability, $arguments);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -254,13 +335,11 @@ 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);
|
||||
|
||||
$arguments = array_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
|
||||
|
|
@ -276,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
|
||||
|
|
@ -301,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -324,39 +483,53 @@ 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
|
||||
*/
|
||||
protected function resolveAuthCallback($user, $ability, array $arguments)
|
||||
{
|
||||
if (isset($arguments[0])) {
|
||||
if (! is_null($policy = $this->getPolicyFor($arguments[0]))) {
|
||||
return $this->resolvePolicyCallback($user, $ability, $arguments, $policy);
|
||||
if (isset($arguments[0]) &&
|
||||
! is_null($policy = $this->getPolicyFor($arguments[0])) &&
|
||||
$callback = $this->resolvePolicyCallback($user, $ability, $arguments, $policy)) {
|
||||
return $callback;
|
||||
}
|
||||
|
||||
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])) {
|
||||
if (isset($this->abilities[$ability]) &&
|
||||
$this->canBeCalledWithUser($user, $this->abilities[$ability])) {
|
||||
return $this->abilities[$ability];
|
||||
}
|
||||
|
||||
return function () {
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -373,13 +546,19 @@ class Gate implements GateContract
|
|||
}
|
||||
|
||||
if (! is_string($class)) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->policies[$class])) {
|
||||
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);
|
||||
|
|
@ -387,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)
|
||||
{
|
||||
|
|
@ -405,10 +616,14 @@ class Gate implements GateContract
|
|||
* @param string $ability
|
||||
* @param array $arguments
|
||||
* @param mixed $policy
|
||||
* @return callable
|
||||
* @return bool|callable
|
||||
*/
|
||||
protected function resolvePolicyCallback($user, $ability, array $arguments, $policy)
|
||||
{
|
||||
if (! is_callable([$policy, $this->formatAbilityToMethod($ability)])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return function () use ($user, $ability, $arguments, $policy) {
|
||||
// This callback will be responsible for calling the policy's before method and
|
||||
// running this policy method if necessary. This is used to when objects are
|
||||
|
|
@ -424,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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -450,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.
|
||||
*
|
||||
|
|
@ -480,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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -503,4 +741,14 @@ class Gate implements GateContract
|
|||
{
|
||||
return $this->abilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the defined policies.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function policies()
|
||||
{
|
||||
return $this->policies;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class Response
|
|||
* Create a new response.
|
||||
*
|
||||
* @param string|null $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = null)
|
||||
{
|
||||
|
|
@ -38,6 +39,6 @@ class Response
|
|||
*/
|
||||
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,16 +58,14 @@ 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)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultDriver();
|
||||
|
||||
return isset($this->guards[$name])
|
||||
? $this->guards[$name]
|
||||
: $this->guards[$name] = $this->resolve($name);
|
||||
return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -96,7 +94,9 @@ class AuthManager implements FactoryContract
|
|||
return $this->{$driverMethod}($name, $config);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Auth guard driver [{$name}] is not defined.");
|
||||
throw new InvalidArgumentException(
|
||||
"Auth driver [{$config['driver']}] for guard [{$name}] is not defined."
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -120,7 +120,7 @@ class AuthManager implements FactoryContract
|
|||
*/
|
||||
public function createSessionDriver($name, $config)
|
||||
{
|
||||
$provider = $this->createUserProvider($config['provider']);
|
||||
$provider = $this->createUserProvider($config['provider'] ?? null);
|
||||
|
||||
$guard = new SessionGuard($name, $provider, $this->app['session.store']);
|
||||
|
||||
|
|
@ -155,8 +155,11 @@ class AuthManager implements FactoryContract
|
|||
// that takes an API token field from the request and matches it to the
|
||||
// user in the database or another persistence layer where users are.
|
||||
$guard = new TokenGuard(
|
||||
$this->createUserProvider($config['provider']),
|
||||
$this->app['request']
|
||||
$this->createUserProvider($config['provider'] ?? null),
|
||||
$this->app['request'],
|
||||
$config['input_key'] ?? 'api_token',
|
||||
$config['storage_key'] ?? 'api_token',
|
||||
$config['hash'] ?? false
|
||||
);
|
||||
|
||||
$this->app->refresh('request', $guard, 'setRequest');
|
||||
|
|
@ -223,7 +226,7 @@ class AuthManager implements FactoryContract
|
|||
public function viaRequest($driver, callable $callback)
|
||||
{
|
||||
return $this->extend($driver, function () use ($callback) {
|
||||
$guard = new RequestGuard($callback, $this->app['request']);
|
||||
$guard = new RequestGuard($callback, $this->app['request'], $this->createUserProvider());
|
||||
|
||||
$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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ trait Authenticatable
|
|||
/**
|
||||
* Get the token value for the "remember me" session.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRememberToken()
|
||||
{
|
||||
if (! empty($this->getRememberTokenName())) {
|
||||
return $this->{$this->getRememberTokenName()};
|
||||
return (string) $this->{$this->getRememberTokenName()};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class ClearResetsCommand extends Command
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
$this->laravel['auth.password']->broker($this->argument('name'))->getRepository()->deleteExpired();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class HomeController extends Controller
|
|||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Contracts\Support\Renderable
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,62 +2,66 @@
|
|||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Login</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Login') }}</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" method="POST" action="{{ route('login') }}">
|
||||
{{ csrf_field() }}
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
|
||||
<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" 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
<label for="password" class="col-md-4 control-label">Password</label>
|
||||
<div class="form-group row">
|
||||
<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" 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> Remember Me
|
||||
<div class="form-group row">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
|
||||
|
||||
<label class="form-check-label" for="remember">
|
||||
{{ __('Remember Me') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-8 col-md-offset-4">
|
||||
<div class="form-group row mb-0">
|
||||
<div class="col-md-8 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Login
|
||||
{{ __('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>
|
||||
|
|
|
|||
|
|
@ -2,39 +2,39 @@
|
|||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Reset Password</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="card-body">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success">
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form class="form-horizontal" method="POST" action="{{ route('password.email') }}">
|
||||
{{ csrf_field() }}
|
||||
<form method="POST" action="{{ route('password.email') }}">
|
||||
@csrf
|
||||
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
|
||||
<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" 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<div class="form-group row mb-0">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Send Password Reset Link
|
||||
{{ __('Send Password Reset Link') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,62 +2,57 @@
|
|||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Reset Password</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" method="POST" action="{{ route('password.request') }}">
|
||||
{{ csrf_field() }}
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('password.update') }}">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="token" value="{{ $token }}">
|
||||
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
|
||||
<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" name="email" value="{{ $email or 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
<label for="password" class="col-md-4 control-label">Password</label>
|
||||
<div class="form-group row">
|
||||
<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" 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
|
||||
<label for="password-confirm" class="col-md-4 control-label">Confirm Password</label>
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
|
||||
<div class="form-group row">
|
||||
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
|
||||
|
||||
@if ($errors->has('password_confirmation'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password_confirmation') }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<div class="form-group row mb-0">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Reset Password
|
||||
{{ __('Reset Password') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,69 +2,69 @@
|
|||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Register</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Register') }}</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" method="POST" action="{{ route('register') }}">
|
||||
{{ csrf_field() }}
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('register') }}">
|
||||
@csrf
|
||||
|
||||
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
|
||||
<label for="name" class="col-md-4 control-label">Name</label>
|
||||
<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" 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
@error('name')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label for="email" class="col-md-4 control-label">E-Mail Address</label>
|
||||
<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" 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
|
||||
<label for="password" class="col-md-4 control-label">Password</label>
|
||||
<div class="form-group row">
|
||||
<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" 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'))
|
||||
<span class="help-block">
|
||||
<strong>{{ $errors->first('password') }}</strong>
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@endif
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password-confirm" class="col-md-4 control-label">Confirm Password</label>
|
||||
<div class="form-group row">
|
||||
<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>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-md-6 col-md-offset-4">
|
||||
<div class="form-group row mb-0">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Register
|
||||
{{ __('Register') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Dashboard</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">Dashboard</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="card-body">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success">
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ app()->getLocale() }}">
|
||||
<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 -->
|
||||
|
|
@ -10,71 +9,72 @@
|
|||
|
||||
<title>{{ config('app.name', 'Laravel') }}</title>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="{{ asset('js/app.js') }}" defer></script>
|
||||
|
||||
<!-- Fonts -->
|
||||
<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-default navbar-static-top">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="{{ url('/') }}">
|
||||
{{ config('app.name', 'Laravel') }}
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- Collapsed Hamburger -->
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#app-navbar-collapse">
|
||||
<span class="sr-only">Toggle Navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
|
||||
<!-- Branding Image -->
|
||||
<a class="navbar-brand" href="{{ url('/') }}">
|
||||
{{ config('app.name', 'Laravel') }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="app-navbar-collapse">
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<!-- Left Side Of Navbar -->
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<ul class="navbar-nav mr-auto">
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- Right Side Of Navbar -->
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<!-- Authentication Links -->
|
||||
@if (Auth::guest())
|
||||
<li><a href="{{ route('login') }}">Login</a></li>
|
||||
<li><a href="{{ route('register') }}">Register</a></li>
|
||||
@guest
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
|
||||
</li>
|
||||
@if (Route::has('register'))
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
|
||||
</li>
|
||||
@endif
|
||||
@else
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
||||
<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>
|
||||
{{ Auth::user()->name }} <span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li>
|
||||
<a href="{{ route('logout') }}"
|
||||
onclick="event.preventDefault();
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="{{ route('logout') }}"
|
||||
onclick="event.preventDefault();
|
||||
document.getElementById('logout-form').submit();">
|
||||
Logout
|
||||
</a>
|
||||
{{ __('Logout') }}
|
||||
</a>
|
||||
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
|
||||
{{ csrf_field() }}
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
|
||||
@csrf
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
@endif
|
||||
@endguest
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@yield('content')
|
||||
<main class="py-4">
|
||||
@yield('content')
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="{{ asset('js/app.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -16,28 +16,45 @@ trait CreatesUserProviders
|
|||
/**
|
||||
* Create the user provider implementation for the driver.
|
||||
*
|
||||
* @param string $provider
|
||||
* @return \Illuminate\Contracts\Auth\UserProvider
|
||||
* @param string|null $provider
|
||||
* @return \Illuminate\Contracts\Auth\UserProvider|null
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function createUserProvider($provider)
|
||||
public function createUserProvider($provider = null)
|
||||
{
|
||||
$config = $this->app['config']['auth.providers.'.$provider];
|
||||
if (is_null($config = $this->getProviderConfiguration($provider))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->customProviderCreators[$config['driver']])) {
|
||||
if (isset($this->customProviderCreators[$driver = ($config['driver'] ?? null)])) {
|
||||
return call_user_func(
|
||||
$this->customProviderCreators[$config['driver']], $this->app, $config
|
||||
$this->customProviderCreators[$driver], $this->app, $config
|
||||
);
|
||||
}
|
||||
|
||||
switch ($config['driver']) {
|
||||
switch ($driver) {
|
||||
case 'database':
|
||||
return $this->createDatabaseProvider($config);
|
||||
case 'eloquent':
|
||||
return $this->createEloquentProvider($config);
|
||||
default:
|
||||
throw new InvalidArgumentException("Authentication user provider [{$config['driver']}] is not defined.");
|
||||
throw new InvalidArgumentException(
|
||||
"Authentication user provider [{$driver}] is not defined."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user provider configuration.
|
||||
*
|
||||
* @param string|null $provider
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getProviderConfiguration($provider)
|
||||
{
|
||||
if ($provider = $provider ?: $this->getDefaultUserProvider()) {
|
||||
return $this->app['config']['auth.providers.'.$provider];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,4 +81,14 @@ trait CreatesUserProviders
|
|||
{
|
||||
return new EloquentUserProvider($this->app['hash'], $config['model']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default user provider name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultUserProvider()
|
||||
{
|
||||
return $this->app['config']['auth.defaults.provider'];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Illuminate\Auth;
|
|||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
|
||||
|
|
@ -68,12 +69,12 @@ class DatabaseUserProvider implements UserProvider
|
|||
*/
|
||||
public function retrieveByToken($identifier, $token)
|
||||
{
|
||||
$user = $this->conn->table($this->table)
|
||||
->where('id', $identifier)
|
||||
->where('remember_token', $token)
|
||||
->first();
|
||||
$user = $this->getGenericUser(
|
||||
$this->conn->table($this->table)->find($identifier)
|
||||
);
|
||||
|
||||
return $this->getGenericUser($user);
|
||||
return $user && $user->getRememberToken() && hash_equals($user->getRememberToken(), $token)
|
||||
? $user : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -86,8 +87,8 @@ class DatabaseUserProvider implements UserProvider
|
|||
public function updateRememberToken(UserContract $user, $token)
|
||||
{
|
||||
$this->conn->table($this->table)
|
||||
->where('id', $user->getAuthIdentifier())
|
||||
->update(['remember_token' => $token]);
|
||||
->where($user->getAuthIdentifierName(), $user->getAuthIdentifier())
|
||||
->update([$user->getRememberTokenName() => $token]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -98,13 +99,25 @@ class DatabaseUserProvider implements UserProvider
|
|||
*/
|
||||
public function retrieveByCredentials(array $credentials)
|
||||
{
|
||||
if (empty($credentials) ||
|
||||
(count($credentials) === 1 &&
|
||||
array_key_exists('password', $credentials))) {
|
||||
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
|
||||
// generic "user" object that will be utilized by the Guard instances.
|
||||
$query = $this->conn->table($this->table);
|
||||
|
||||
foreach ($credentials as $key => $value) {
|
||||
if (! Str::contains($key, 'password')) {
|
||||
if (Str::contains($key, 'password')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value) || $value instanceof Arrayable) {
|
||||
$query->whereIn($key, $value);
|
||||
} else {
|
||||
$query->where($key, $value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Illuminate\Auth;
|
|||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
|
||||
|
||||
|
|
@ -46,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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -62,16 +63,24 @@ class EloquentUserProvider implements UserProvider
|
|||
{
|
||||
$model = $this->createModel();
|
||||
|
||||
return $model->newQuery()
|
||||
->where($model->getAuthIdentifierName(), $identifier)
|
||||
->where($model->getRememberTokenName(), $token)
|
||||
->first();
|
||||
$retrievedModel = $this->newModelQuery($model)->where(
|
||||
$model->getAuthIdentifierName(), $identifier
|
||||
)->first();
|
||||
|
||||
if (! $retrievedModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rememberToken = $retrievedModel->getRememberToken();
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
@ -96,17 +105,25 @@ class EloquentUserProvider implements UserProvider
|
|||
*/
|
||||
public function retrieveByCredentials(array $credentials)
|
||||
{
|
||||
if (empty($credentials)) {
|
||||
if (empty($credentials) ||
|
||||
(count($credentials) === 1 &&
|
||||
array_key_exists('password', $credentials))) {
|
||||
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')) {
|
||||
if (Str::contains($key, 'password')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value) || $value instanceof Arrayable) {
|
||||
$query->whereIn($key, $value);
|
||||
} else {
|
||||
$query->where($key, $value);
|
||||
}
|
||||
}
|
||||
|
|
@ -128,6 +145,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,11 +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,12 +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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Illuminate\Auth;
|
||||
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
||||
|
||||
/**
|
||||
|
|
@ -24,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
|
||||
*
|
||||
|
|
@ -39,6 +40,16 @@ trait GuardHelpers
|
|||
throw new AuthenticationException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the guard has a user instance.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUser()
|
||||
{
|
||||
return ! is_null($this->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the current user is authenticated.
|
||||
*
|
||||
|
|
@ -83,4 +94,25 @@ trait GuardHelpers
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user provider used by the guard.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\UserProvider
|
||||
*/
|
||||
public function getProvider()
|
||||
{
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user provider used by the guard.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\UserProvider $provider
|
||||
* @return void
|
||||
*/
|
||||
public function setProvider(UserProvider $provider)
|
||||
{
|
||||
$this->provider = $provider;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +32,7 @@ class Authorize
|
|||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string $ability
|
||||
* @param array|null $models
|
||||
* @param array|null ...$models
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Auth\AuthenticationException
|
||||
|
|
@ -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);
|
||||
|
|
@ -80,11 +68,16 @@ class Authorize
|
|||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $model
|
||||
* @return string|\Illuminate\Database\Eloquent\Model
|
||||
* @return \Illuminate\Database\Eloquent\Model|string
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Illuminate\Auth\Notifications;
|
||||
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
|
|
@ -14,6 +15,13 @@ class ResetPassword extends Notification
|
|||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* The callback that should be used to build the mail message.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
public static $toMailCallback;
|
||||
|
||||
/**
|
||||
* Create a notification instance.
|
||||
*
|
||||
|
|
@ -44,9 +52,26 @@ class ResetPassword extends Notification
|
|||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
if (static::$toMailCallback) {
|
||||
return call_user_func(static::$toMailCallback, $notifiable, $this->token);
|
||||
}
|
||||
|
||||
return (new MailMessage)
|
||||
->line('You are receiving this email because we received a password reset request for your account.')
|
||||
->action('Reset Password', url(config('app.url').route('password.reset', $this->token, false)))
|
||||
->line('If you did not request a password reset, no further action is required.');
|
||||
->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', ['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.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Illuminate\Auth\Passwords;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
|
||||
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class PasswordBroker implements PasswordBrokerContract
|
|||
* Validate a password reset for the given credentials.
|
||||
*
|
||||
* @param array $credentials
|
||||
* @return \Illuminate\Contracts\Auth\CanResetPassword
|
||||
* @return \Illuminate\Contracts\Auth\CanResetPassword|string
|
||||
*/
|
||||
protected function validateReset(array $credentials)
|
||||
{
|
||||
|
|
@ -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,19 +167,19 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user for the given credentials.
|
||||
*
|
||||
* @param array $credentials
|
||||
* @return \Illuminate\Contracts\Auth\CanResetPassword
|
||||
* @return \Illuminate\Contracts\Auth\CanResetPassword|null
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
|
|
@ -199,7 +199,7 @@ class PasswordBroker implements PasswordBrokerContract
|
|||
/**
|
||||
* Create a new password reset token for the given user.
|
||||
*
|
||||
* @param CanResetPasswordContract $user
|
||||
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
|
||||
* @return string
|
||||
*/
|
||||
public function createToken(CanResetPasswordContract $user)
|
||||
|
|
@ -221,7 +221,7 @@ class PasswordBroker implements PasswordBrokerContract
|
|||
/**
|
||||
* Validate the given password reset token.
|
||||
*
|
||||
* @param CanResetPasswordContract $user
|
||||
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
|
||||
* @param string $token
|
||||
* @return bool
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -39,16 +39,14 @@ class PasswordBrokerManager implements FactoryContract
|
|||
/**
|
||||
* Attempt to get the broker from the local cache.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $name
|
||||
* @return \Illuminate\Contracts\Auth\PasswordBroker
|
||||
*/
|
||||
public function broker($name = null)
|
||||
{
|
||||
$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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -72,7 +70,7 @@ class PasswordBrokerManager implements FactoryContract
|
|||
// aggregate service of sorts providing a convenient interface for resets.
|
||||
return new PasswordBroker(
|
||||
$this->createTokenRepository($config),
|
||||
$this->app['auth']->createUserProvider($config['provider'])
|
||||
$this->app['auth']->createUserProvider($config['provider'] ?? null)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +88,7 @@ class PasswordBrokerManager implements FactoryContract
|
|||
$key = base64_decode(substr($key, 7));
|
||||
}
|
||||
|
||||
$connection = isset($config['connection']) ? $config['connection'] : null;
|
||||
$connection = $config['connection'] ?? null;
|
||||
|
||||
return new DatabaseTokenRepository(
|
||||
$this->app['db']->connection($connection),
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class Recaller
|
|||
*/
|
||||
public function __construct($recaller)
|
||||
{
|
||||
$this->recaller = $recaller;
|
||||
$this->recaller = @unserialize($recaller, ['allowed_classes' => false]) ?: $recaller;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -31,7 +31,7 @@ class Recaller
|
|||
*/
|
||||
public function id()
|
||||
{
|
||||
return explode('|', $this->recaller, 2)[0];
|
||||
return explode('|', $this->recaller, 3)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -41,7 +41,17 @@ class Recaller
|
|||
*/
|
||||
public function token()
|
||||
{
|
||||
return explode('|', $this->recaller, 2)[1];
|
||||
return explode('|', $this->recaller, 3)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password from the recaller.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hash()
|
||||
{
|
||||
return explode('|', $this->recaller, 3)[2];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -51,7 +61,7 @@ class Recaller
|
|||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->properString() && $this->hasBothSegments();
|
||||
return $this->properString() && $this->hasAllSegments();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -65,14 +75,14 @@ class Recaller
|
|||
}
|
||||
|
||||
/**
|
||||
* Determine if the recaller has both segments.
|
||||
* Determine if the recaller has all segments.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasBothSegments()
|
||||
protected function hasAllSegments()
|
||||
{
|
||||
$segments = explode('|', $this->recaller);
|
||||
|
||||
return count($segments) == 2 && trim($segments[0]) !== '' && trim($segments[1]) !== '';
|
||||
return count($segments) === 3 && trim($segments[0]) !== '' && trim($segments[1]) !== '';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace Illuminate\Auth;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
|
||||
class RequestGuard implements Guard
|
||||
{
|
||||
|
|
@ -29,12 +30,14 @@ class RequestGuard implements Guard
|
|||
*
|
||||
* @param callable $callback
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Contracts\Auth\UserProvider|null $provider
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(callable $callback, Request $request)
|
||||
public function __construct(callable $callback, Request $request, UserProvider $provider = null)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->callback = $callback;
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,7 +55,7 @@ class RequestGuard implements Guard
|
|||
}
|
||||
|
||||
return $this->user = call_user_func(
|
||||
$this->callback, $this->request
|
||||
$this->callback, $this->request, $this->getProvider()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +68,7 @@ class RequestGuard implements Guard
|
|||
public function validate(array $credentials = [])
|
||||
{
|
||||
return ! is_null((new static(
|
||||
$this->callback, $credentials['request']
|
||||
$this->callback, $credentials['request'], $this->getProvider()
|
||||
))->user());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace Illuminate\Auth;
|
|||
|
||||
use RuntimeException;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
|
|
@ -13,6 +13,7 @@ use Illuminate\Contracts\Auth\StatefulGuard;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Illuminate\Contracts\Auth\SupportsBasicAuth;
|
||||
use Illuminate\Contracts\Cookie\QueueingFactory as CookieJar;
|
||||
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
||||
|
||||
class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
||||
|
|
@ -90,7 +91,7 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
|||
* @param string $name
|
||||
* @param \Illuminate\Contracts\Auth\UserProvider $provider
|
||||
* @param \Illuminate\Contracts\Session\Session $session
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* @param \Symfony\Component\HttpFoundation\Request|null $request
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name,
|
||||
|
|
@ -127,30 +128,24 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
|||
// First we will try to load the user using the identifier in the session if
|
||||
// one exists. Otherwise we will check for a "remember me" cookie in this
|
||||
// request, and if one exists, attempt to retrieve the user using that.
|
||||
$user = null;
|
||||
|
||||
if (! is_null($id)) {
|
||||
if ($user = $this->provider->retrieveById($id)) {
|
||||
$this->fireAuthenticatedEvent($user);
|
||||
}
|
||||
if (! is_null($id) && $this->user = $this->provider->retrieveById($id)) {
|
||||
$this->fireAuthenticatedEvent($this->user);
|
||||
}
|
||||
|
||||
// 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 = $this->recaller())) {
|
||||
$this->user = $this->userFromRecaller($recaller);
|
||||
|
||||
if (is_null($user) && ! is_null($recaller)) {
|
||||
$user = $this->userFromRecaller($recaller);
|
||||
if ($this->user) {
|
||||
$this->updateSession($this->user->getAuthIdentifier());
|
||||
|
||||
if ($user) {
|
||||
$this->updateSession($user->getAuthIdentifier());
|
||||
|
||||
$this->fireLoginEvent($user, true);
|
||||
$this->fireLoginEvent($this->user, true);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->user = $user;
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -331,11 +326,13 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
|||
/**
|
||||
* Get the response for basic authentication.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @return void
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
|
||||
*/
|
||||
protected function failedBasicResponse()
|
||||
{
|
||||
return new Response('Invalid credentials.', 401, ['WWW-Authenticate' => 'Basic']);
|
||||
throw new UnauthorizedHttpException('Basic', 'Invalid credentials.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -461,7 +458,7 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
|||
protected function queueRecallerCookie(AuthenticatableContract $user)
|
||||
{
|
||||
$this->getCookieJar()->queue($this->createRecaller(
|
||||
$user->getAuthIdentifier().'|'.$user->getRememberToken()
|
||||
$user->getAuthIdentifier().'|'.$user->getRememberToken().'|'.$user->getAuthPassword()
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -490,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
|
||||
|
|
@ -534,6 +531,35 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
|||
$this->provider->updateRememberToken($user, $token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate other sessions for the current user.
|
||||
*
|
||||
* The application must be using the AuthenticateSession middleware.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $attribute
|
||||
* @return bool|null
|
||||
*/
|
||||
public function logoutOtherDevices($password, $attribute = 'password')
|
||||
{
|
||||
if (! $this->user()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = tap($this->user()->forceFill([
|
||||
$attribute => Hash::make($password),
|
||||
]))->save();
|
||||
|
||||
if ($this->recaller() ||
|
||||
$this->getCookieJar()->hasQueued($this->getRecallerName())) {
|
||||
$this->queueRecallerCookie($this->user());
|
||||
}
|
||||
|
||||
$this->fireOtherDeviceLogoutEvent($this->user());
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an authentication attempt event listener.
|
||||
*
|
||||
|
|
@ -558,7 +584,7 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
|||
{
|
||||
if (isset($this->events)) {
|
||||
$this->events->dispatch(new Events\Attempting(
|
||||
$credentials, $remember
|
||||
$this->name, $credentials, $remember
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -573,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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -586,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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -600,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
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -695,34 +742,13 @@ class SessionGuard implements StatefulGuard, SupportsBasicAuth
|
|||
/**
|
||||
* Get the session store used by the guard.
|
||||
*
|
||||
* @return \Illuminate\Session\Store
|
||||
* @return \Illuminate\Contracts\Session\Session
|
||||
*/
|
||||
public function getSession()
|
||||
{
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user provider used by the guard.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\UserProvider
|
||||
*/
|
||||
public function getProvider()
|
||||
{
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user provider used by the guard.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\UserProvider $provider
|
||||
* @return void
|
||||
*/
|
||||
public function setProvider(UserProvider $provider)
|
||||
{
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently cached user.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -31,19 +31,35 @@ 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.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\UserProvider $provider
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $inputKey
|
||||
* @param string $storageKey
|
||||
* @param bool $hash
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(UserProvider $provider, Request $request)
|
||||
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 = 'api_token';
|
||||
$this->storageKey = 'api_token';
|
||||
$this->inputKey = $inputKey;
|
||||
$this->storageKey = $storageKey;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -65,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;
|
||||
|
|
|
|||
|
|
@ -14,12 +14,11 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/contracts": "5.4.*",
|
||||
"illuminate/http": "5.4.*",
|
||||
"illuminate/queue": "5.4.*",
|
||||
"illuminate/support": "5.4.*",
|
||||
"nesbot/carbon": "~1.20"
|
||||
"php": "^7.1.3",
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/http": "5.8.*",
|
||||
"illuminate/queue": "5.8.*",
|
||||
"illuminate/support": "5.8.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -28,13 +27,13 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/console": "Required to use the auth:clear-resets command (5.4.*).",
|
||||
"illuminate/queue": "Required to fire login / logout events (5.4.*).",
|
||||
"illuminate/session": "Required to use the session based guard (5.4.*)."
|
||||
"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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ namespace Illuminate\Broadcasting;
|
|||
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\Job;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Broadcasting\Broadcaster;
|
||||
|
|
@ -44,7 +44,7 @@ class BroadcastEvent implements ShouldQueue
|
|||
? $this->event->broadcastAs() : get_class($this->event);
|
||||
|
||||
$broadcaster->broadcast(
|
||||
array_wrap($this->event->broadcastOn()), $name,
|
||||
Arr::wrap($this->event->broadcastOn()), $name,
|
||||
$this->getPayloadFromEvent($this->event)
|
||||
);
|
||||
}
|
||||
|
|
@ -98,4 +98,14 @@ class BroadcastEvent implements ShouldQueue
|
|||
{
|
||||
return get_class($this->event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the instance for cloning.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->event = clone $this->event;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@
|
|||
|
||||
namespace Illuminate\Broadcasting;
|
||||
|
||||
use Pusher;
|
||||
use Closure;
|
||||
use Illuminate\Support\Arr;
|
||||
use Pusher\Pusher;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Broadcasting\Broadcasters\LogBroadcaster;
|
||||
|
|
@ -22,7 +21,7 @@ class BroadcastManager implements FactoryContract
|
|||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Foundation\Application
|
||||
* @var \Illuminate\Contracts\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
|
|
@ -43,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)
|
||||
|
|
@ -66,7 +65,10 @@ class BroadcastManager implements FactoryContract
|
|||
$attributes = $attributes ?: ['middleware' => ['web']];
|
||||
|
||||
$this->app['router']->group($attributes, function ($router) {
|
||||
$router->post('/broadcasting/auth', BroadcastController::class.'@authenticate');
|
||||
$router->match(
|
||||
['get', 'post'], '/broadcasting/auth',
|
||||
'\\'.BroadcastController::class.'@authenticate'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -84,9 +86,7 @@ class BroadcastManager implements FactoryContract
|
|||
|
||||
$request = $request ?: $this->app['request'];
|
||||
|
||||
if ($request->hasHeader('X-Socket-ID')) {
|
||||
return $request->header('X-Socket-ID');
|
||||
}
|
||||
return $request->header('X-Socket-ID');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -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)
|
||||
|
|
@ -143,7 +143,7 @@ class BroadcastManager implements FactoryContract
|
|||
/**
|
||||
* Get a driver instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function driver($name = null)
|
||||
|
|
@ -161,11 +161,11 @@ class BroadcastManager implements FactoryContract
|
|||
*/
|
||||
protected function get($name)
|
||||
{
|
||||
return isset($this->drivers[$name]) ? $this->drivers[$name] : $this->resolve($name);
|
||||
return $this->drivers[$name] ?? $this->resolve($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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'], Arr::get($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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -227,7 +229,7 @@ class BroadcastManager implements FactoryContract
|
|||
protected function createRedisDriver(array $config)
|
||||
{
|
||||
return new RedisBroadcaster(
|
||||
$this->app->make('redis'), Arr::get($config, 'connection')
|
||||
$this->app->make('redis'), $config['connection'] ?? null
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
namespace Illuminate\Broadcasting\Broadcasters;
|
||||
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunction;
|
||||
use ReflectionParameter;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Contracts\Routing\UrlRoutable;
|
||||
use Illuminate\Contracts\Routing\BindingRegistrar;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Illuminate\Contracts\Broadcasting\Broadcaster as BroadcasterContract;
|
||||
|
||||
abstract class Broadcaster implements BroadcasterContract
|
||||
|
|
@ -20,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;
|
||||
|
||||
|
|
@ -31,13 +40,16 @@ abstract class Broadcaster implements BroadcasterContract
|
|||
* Register a channel authenticator.
|
||||
*
|
||||
* @param string $channel
|
||||
* @param callable $callback
|
||||
* @param callable|string $callback
|
||||
* @param array $options
|
||||
* @return $this
|
||||
*/
|
||||
public function channel($channel, callable $callback)
|
||||
public function channel($channel, $callback, $options = [])
|
||||
{
|
||||
$this->channels[$channel] = $callback;
|
||||
|
||||
$this->channelOptions[$channel] = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -47,22 +59,26 @@ 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;
|
||||
}
|
||||
|
||||
$parameters = $this->extractAuthParameters($pattern, $channel, $callback);
|
||||
|
||||
if ($result = $callback($request->user(), ...$parameters)) {
|
||||
$handler = $this->normalizeChannelHandlerToCallable($callback);
|
||||
|
||||
if ($result = $handler($this->retrieveUser($request, $channel), ...$parameters)) {
|
||||
return $this->validAuthenticationResponse($request, $result);
|
||||
}
|
||||
}
|
||||
|
||||
throw new HttpException(403);
|
||||
throw new AccessDeniedHttpException;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -70,12 +86,12 @@ abstract class Broadcaster implements BroadcasterContract
|
|||
*
|
||||
* @param string $pattern
|
||||
* @param string $channel
|
||||
* @param callable $callback
|
||||
* @param callable|string $callback
|
||||
* @return array
|
||||
*/
|
||||
protected function extractAuthParameters($pattern, $channel, $callback)
|
||||
{
|
||||
$callbackParameters = (new ReflectionFunction($callback))->getParameters();
|
||||
$callbackParameters = $this->extractParameters($callback);
|
||||
|
||||
return collect($this->extractChannelKeys($pattern, $channel))->reject(function ($value, $key) {
|
||||
return is_numeric($key);
|
||||
|
|
@ -84,6 +100,44 @@ abstract class Broadcaster implements BroadcasterContract
|
|||
})->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the parameters out of what the user passed to handle the channel authentication.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @return \ReflectionParameter[]
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function extractParameters($callback)
|
||||
{
|
||||
if (is_callable($callback)) {
|
||||
return (new ReflectionFunction($callback))->getParameters();
|
||||
} elseif (is_string($callback)) {
|
||||
return $this->extractParametersFromClass($callback);
|
||||
}
|
||||
|
||||
throw new Exception('Given channel handler is an unknown type.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the parameters out of a class channel's "join" method.
|
||||
*
|
||||
* @param string $callback
|
||||
* @return \ReflectionParameter[]
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function extractParametersFromClass($callback)
|
||||
{
|
||||
$reflection = new ReflectionClass($callback);
|
||||
|
||||
if (! $reflection->hasMethod('join')) {
|
||||
throw new Exception('Class based channel must define a "join" method.');
|
||||
}
|
||||
|
||||
return $reflection->getMethod('join')->getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the channel keys from the incoming channel name.
|
||||
*
|
||||
|
|
@ -140,6 +194,8 @@ 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)
|
||||
{
|
||||
|
|
@ -148,11 +204,13 @@ abstract class Broadcaster implements BroadcasterContract
|
|||
continue;
|
||||
}
|
||||
|
||||
$model = $parameter->getClass()->newInstance();
|
||||
$instance = $parameter->getClass()->newInstance();
|
||||
|
||||
return $model->where($model->getRouteKeyName(), $value)->firstOr(function () {
|
||||
throw new HttpException(403);
|
||||
});
|
||||
if (! $model = $instance->resolveRouteBinding($value)) {
|
||||
throw new AccessDeniedHttpException;
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
|
@ -162,13 +220,13 @@ abstract class Broadcaster implements BroadcasterContract
|
|||
* Determine if a given key and parameter is implicitly bindable.
|
||||
*
|
||||
* @param string $key
|
||||
* @param ReflectionParameter $parameter
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @return bool
|
||||
*/
|
||||
protected function isImplicitlyBindable($key, $parameter)
|
||||
{
|
||||
return $parameter->name === $key && $parameter->getClass() &&
|
||||
$parameter->getClass()->isSubclassOf(Model::class);
|
||||
$parameter->getClass()->isSubclassOf(UrlRoutable::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -187,7 +245,7 @@ abstract class Broadcaster implements BroadcasterContract
|
|||
/**
|
||||
* Get the model binding registrar instance.
|
||||
*
|
||||
* @return BindingRegistrar
|
||||
* @return \Illuminate\Contracts\Routing\BindingRegistrar
|
||||
*/
|
||||
protected function binder()
|
||||
{
|
||||
|
|
@ -198,4 +256,74 @@ abstract class Broadcaster implements BroadcasterContract
|
|||
|
||||
return $this->bindingRegistrar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the given callback into a callable.
|
||||
*
|
||||
* @param mixed $callback
|
||||
* @return callable|\Closure
|
||||
*/
|
||||
protected function normalizeChannelHandlerToCallable($callback)
|
||||
{
|
||||
return is_callable($callback) ? $callback : function (...$args) use ($callback) {
|
||||
return Container::getInstance()
|
||||
->make($callback)
|
||||
->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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,25 +2,27 @@
|
|||
|
||||
namespace Illuminate\Broadcasting\Broadcasters;
|
||||
|
||||
use Pusher;
|
||||
use Pusher\Pusher;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Broadcasting\BroadcastException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
class PusherBroadcaster extends Broadcaster
|
||||
{
|
||||
use UsePusherChannelConventions;
|
||||
|
||||
/**
|
||||
* The Pusher SDK instance.
|
||||
*
|
||||
* @var \Pusher
|
||||
* @var \Pusher\Pusher
|
||||
*/
|
||||
protected $pusher;
|
||||
|
||||
/**
|
||||
* Create a new broadcaster instance.
|
||||
*
|
||||
* @param \Pusher $pusher
|
||||
* @param \Pusher\Pusher $pusher
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Pusher $pusher)
|
||||
|
|
@ -33,17 +35,17 @@ 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()) {
|
||||
throw new HttpException(403);
|
||||
}
|
||||
$channelName = $this->normalizeChannelName($request->channel_name);
|
||||
|
||||
$channelName = Str::startsWith($request->channel_name, 'private-')
|
||||
? Str::replaceFirst('private-', '', $request->channel_name)
|
||||
: Str::replaceFirst('presence-', '', $request->channel_name);
|
||||
if ($this->isGuardedChannel($request->channel_name) &&
|
||||
! $this->retrieveUser($request, $channelName)) {
|
||||
throw new AccessDeniedHttpException;
|
||||
}
|
||||
|
||||
return parent::verifyUserCanAccessChannel(
|
||||
$request, $channelName
|
||||
|
|
@ -61,25 +63,36 @@ class PusherBroadcaster extends Broadcaster
|
|||
{
|
||||
if (Str::startsWith($request->channel_name, 'private')) {
|
||||
return $this->decodePusherResponse(
|
||||
$this->pusher->socket_auth($request->channel_name, $request->socket_id)
|
||||
$request, $this->pusher->socket_auth($request->channel_name, $request->socket_id)
|
||||
);
|
||||
}
|
||||
|
||||
$channelName = $this->normalizeChannelName($request->channel_name);
|
||||
|
||||
return $this->decodePusherResponse(
|
||||
$request,
|
||||
$this->pusher->presence_auth(
|
||||
$request->channel_name, $request->socket_id, $request->user()->getAuthIdentifier(), $result)
|
||||
$request->channel_name, $request->socket_id,
|
||||
$this->retrieveUser($request, $channelName)->getAuthIdentifier(), $result
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the given Pusher response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $response
|
||||
* @return array
|
||||
*/
|
||||
protected function decodePusherResponse($response)
|
||||
protected function decodePusherResponse($request, $response)
|
||||
{
|
||||
return json_decode($response, true);
|
||||
if (! $request->input('callback', false)) {
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
return response()->json(json_decode($response, true))
|
||||
->withCallback($request->callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -111,7 +124,7 @@ class PusherBroadcaster extends Broadcaster
|
|||
/**
|
||||
* Get the Pusher SDK instance.
|
||||
*
|
||||
* @return \Pusher
|
||||
* @return \Pusher\Pusher
|
||||
*/
|
||||
public function getPusher()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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\HttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
class RedisBroadcaster extends Broadcaster
|
||||
{
|
||||
use UsePusherChannelConventions;
|
||||
|
||||
/**
|
||||
* The Redis instance.
|
||||
*
|
||||
|
|
@ -27,7 +28,7 @@ class RedisBroadcaster extends Broadcaster
|
|||
* Create a new broadcaster instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Redis\Factory $redis
|
||||
* @param string $connection
|
||||
* @param string|null $connection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Redis $redis, $connection = null)
|
||||
|
|
@ -41,17 +42,17 @@ 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()) {
|
||||
throw new HttpException(403);
|
||||
}
|
||||
$channelName = $this->normalizeChannelName($request->channel_name);
|
||||
|
||||
$channelName = Str::startsWith($request->channel_name, 'private-')
|
||||
? Str::replaceFirst('private-', '', $request->channel_name)
|
||||
: Str::replaceFirst('presence-', '', $request->channel_name);
|
||||
if ($this->isGuardedChannel($request->channel_name) &&
|
||||
! $this->retrieveUser($request, $channelName)) {
|
||||
throw new AccessDeniedHttpException;
|
||||
}
|
||||
|
||||
return parent::verifyUserCanAccessChannel(
|
||||
$request, $channelName
|
||||
|
|
@ -71,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,
|
||||
]]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/bus": "5.4.*",
|
||||
"illuminate/contracts": "5.4.*",
|
||||
"illuminate/queue": "5.4.*",
|
||||
"illuminate/support": "5.4.*"
|
||||
"php": "^7.1.3",
|
||||
"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": {
|
||||
|
|
@ -27,11 +29,11 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -71,9 +71,9 @@ class Dispatcher implements QueueingDispatcher
|
|||
{
|
||||
if ($this->queueResolver && $this->commandShouldBeQueued($command)) {
|
||||
return $this->dispatchToQueue($command);
|
||||
} else {
|
||||
return $this->dispatchNow($command);
|
||||
}
|
||||
|
||||
return $this->dispatchNow($command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -145,7 +145,7 @@ class Dispatcher implements QueueingDispatcher
|
|||
*/
|
||||
public function dispatchToQueue($command)
|
||||
{
|
||||
$connection = isset($command->connection) ? $command->connection : null;
|
||||
$connection = $command->connection ?? null;
|
||||
|
||||
$queue = call_user_func($this->queueResolver, $connection);
|
||||
|
||||
|
|
@ -155,9 +155,9 @@ class Dispatcher implements QueueingDispatcher
|
|||
|
||||
if (method_exists($command, 'queue')) {
|
||||
return $command->queue($queue, $command);
|
||||
} else {
|
||||
return $this->pushCommandToQueue($queue, $command);
|
||||
}
|
||||
|
||||
return $this->pushCommandToQueue($queue, $command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -18,13 +18,34 @@ trait Queueable
|
|||
*/
|
||||
public $queue;
|
||||
|
||||
/**
|
||||
* The name of the connection the chain should be sent to.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $chainConnection;
|
||||
|
||||
/**
|
||||
* The name of the queue the chain should be sent to.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $chainQueue;
|
||||
|
||||
/**
|
||||
* The number of seconds before the job should be made available.
|
||||
*
|
||||
* @var \DateTime|int|null
|
||||
* @var \DateTimeInterface|\DateInterval|int|null
|
||||
*/
|
||||
public $delay;
|
||||
|
||||
/**
|
||||
* The jobs that should run if this job is successful.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $chained = [];
|
||||
|
||||
/**
|
||||
* Set the desired connection for the job.
|
||||
*
|
||||
|
|
@ -51,10 +72,38 @@ trait Queueable
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the desired connection for the chain.
|
||||
*
|
||||
* @param string|null $connection
|
||||
* @return $this
|
||||
*/
|
||||
public function allOnConnection($connection)
|
||||
{
|
||||
$this->chainConnection = $connection;
|
||||
$this->connection = $connection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the desired queue for the chain.
|
||||
*
|
||||
* @param string|null $queue
|
||||
* @return $this
|
||||
*/
|
||||
public function allOnQueue($queue)
|
||||
{
|
||||
$this->chainQueue = $queue;
|
||||
$this->queue = $queue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the desired delay for the job.
|
||||
*
|
||||
* @param \DateTime|int|null $delay
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $delay
|
||||
* @return $this
|
||||
*/
|
||||
public function delay($delay)
|
||||
|
|
@ -63,4 +112,39 @@ trait Queueable
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the jobs that should run if this job is successful.
|
||||
*
|
||||
* @param array $chain
|
||||
* @return $this
|
||||
*/
|
||||
public function chain($chain)
|
||||
{
|
||||
$this->chained = collect($chain)->map(function ($job) {
|
||||
return serialize($job);
|
||||
})->all();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the next job on the chain.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dispatchNextJobInChain()
|
||||
{
|
||||
if (! empty($this->chained)) {
|
||||
dispatch(tap(unserialize(array_shift($this->chained)), function ($next) {
|
||||
$next->chained = $this->chained;
|
||||
|
||||
$next->onConnection($next->connection ?: $this->chainConnection);
|
||||
$next->onQueue($next->queue ?: $this->chainQueue);
|
||||
|
||||
$next->chainConnection = $this->chainConnection;
|
||||
$next->chainQueue = $this->chainQueue;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/contracts": "5.4.*",
|
||||
"illuminate/pipeline": "5.4.*",
|
||||
"illuminate/support": "5.4.*"
|
||||
"php": "^7.1.3",
|
||||
"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.4-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,22 +23,39 @@ class ArrayStore extends TaggableStore implements Store
|
|||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->storage)) {
|
||||
return $this->storage[$key];
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -50,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'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -73,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -88,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -114,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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ 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;
|
||||
|
|
@ -17,7 +18,7 @@ class CacheManager implements FactoryContract
|
|||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Foundation\Application
|
||||
* @var \Illuminate\Contracts\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
|
|
@ -38,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)
|
||||
|
|
@ -47,10 +48,10 @@ 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 mixed
|
||||
* @return \Illuminate\Contracts\Cache\Repository
|
||||
*/
|
||||
public function store($name = null)
|
||||
{
|
||||
|
|
@ -62,8 +63,8 @@ class CacheManager implements FactoryContract
|
|||
/**
|
||||
* Get a cache driver instance.
|
||||
*
|
||||
* @param string $driver
|
||||
* @return mixed
|
||||
* @param string|null $driver
|
||||
* @return \Illuminate\Contracts\Cache\Repository
|
||||
*/
|
||||
public function driver($driver = null)
|
||||
{
|
||||
|
|
@ -78,7 +79,7 @@ class CacheManager implements FactoryContract
|
|||
*/
|
||||
protected function get($name)
|
||||
{
|
||||
return isset($this->stores[$name]) ? $this->stores[$name] : $this->resolve($name);
|
||||
return $this->stores[$name] ?? $this->resolve($name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -125,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)
|
||||
{
|
||||
|
|
@ -137,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()
|
||||
{
|
||||
|
|
@ -148,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)
|
||||
{
|
||||
|
|
@ -159,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)
|
||||
{
|
||||
|
|
@ -167,9 +168,9 @@ class CacheManager implements FactoryContract
|
|||
|
||||
$memcached = $this->app['memcached.connector']->connect(
|
||||
$config['servers'],
|
||||
array_get($config, 'persistent_id'),
|
||||
array_get($config, 'options', []),
|
||||
array_filter(array_get($config, 'sasl', []))
|
||||
$config['persistent_id'] ?? null,
|
||||
$config['options'] ?? [],
|
||||
array_filter($config['sasl'] ?? [])
|
||||
);
|
||||
|
||||
return $this->repository(new MemcachedStore($memcached, $prefix));
|
||||
|
|
@ -178,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()
|
||||
{
|
||||
|
|
@ -189,13 +190,13 @@ 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)
|
||||
{
|
||||
$redis = $this->app['redis'];
|
||||
|
||||
$connection = Arr::get($config, 'connection', 'default');
|
||||
$connection = $config['connection'] ?? 'default';
|
||||
|
||||
return $this->repository(new RedisStore($redis, $this->getPrefix($config), $connection));
|
||||
}
|
||||
|
|
@ -204,15 +205,47 @@ 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)
|
||||
{
|
||||
$connection = $this->app['db']->connection(Arr::get($config, 'connection'));
|
||||
$connection = $this->app['db']->connection($config['connection'] ?? null);
|
||||
|
||||
return $this->repository(
|
||||
new DatabaseStore(
|
||||
$connection, $this->app['encrypter'], $config['table'], $this->getPrefix($config)
|
||||
$connection, $config['table'], $this->getPrefix($config)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -244,7 +277,7 @@ class CacheManager implements FactoryContract
|
|||
*/
|
||||
protected function getPrefix(array $config)
|
||||
{
|
||||
return Arr::get($config, 'prefix') ?: $this->app['config']['cache.prefix'];
|
||||
return $config['prefix'] ?? $this->app['config']['cache.prefix'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -279,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
|
||||
*/
|
||||
|
|
@ -297,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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class CacheTableCommand extends Command
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
$fullPath = $this->createBaseMigration();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace Illuminate\Cache\Console;
|
|||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Cache\CacheManager;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
||||
|
|
@ -30,17 +31,26 @@ class ClearCommand extends Command
|
|||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* The filesystem instance.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* Create a new cache clear command instance.
|
||||
*
|
||||
* @param \Illuminate\Cache\CacheManager $cache
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CacheManager $cache)
|
||||
public function __construct(CacheManager $cache, Filesystem $files)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->cache = $cache;
|
||||
$this->files = $files;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -50,13 +60,41 @@ class ClearCommand extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->laravel['events']->fire('cache:clearing', [$this->argument('store'), $this->tags()]);
|
||||
$this->laravel['events']->dispatch(
|
||||
'cache:clearing', [$this->argument('store'), $this->tags()]
|
||||
);
|
||||
|
||||
$this->cache()->flush();
|
||||
$successful = $this->cache()->flush();
|
||||
|
||||
$this->laravel['events']->fire('cache:cleared', [$this->argument('store'), $this->tags()]);
|
||||
$this->flushFacades();
|
||||
|
||||
$this->info('Cache cleared successfully.');
|
||||
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()]
|
||||
);
|
||||
|
||||
$this->info('Application cache cleared!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the real-time facades stored in the cache directory.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function flushFacades()
|
||||
{
|
||||
if (! $this->files->exists($storagePath = storage_path('framework/cache'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->files->files($storagePath) as $file) {
|
||||
if (preg_match('/facade-.*\.php$/', $file)) {
|
||||
$this->files->delete($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -89,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'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -101,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],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class CreateCacheTable extends Migration
|
|||
{
|
||||
Schema::create('cache', function (Blueprint $table) {
|
||||
$table->string('key')->unique();
|
||||
$table->text('value');
|
||||
$table->mediumText('value');
|
||||
$table->integer('expiration');
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,15 @@ namespace Illuminate\Cache;
|
|||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Illuminate\Database\PostgresConnection;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract;
|
||||
|
||||
class DatabaseStore implements Store
|
||||
{
|
||||
use RetrievesMultipleKeys;
|
||||
use InteractsWithTime, RetrievesMultipleKeys;
|
||||
|
||||
/**
|
||||
* The database connection instance.
|
||||
|
|
@ -20,13 +21,6 @@ class DatabaseStore implements Store
|
|||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The encrypter instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||
*/
|
||||
protected $encrypter;
|
||||
|
||||
/**
|
||||
* The name of the cache table.
|
||||
*
|
||||
|
|
@ -45,17 +39,14 @@ class DatabaseStore implements Store
|
|||
* Create a new database store.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionInterface $connection
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
* @param string $table
|
||||
* @param string $prefix
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ConnectionInterface $connection, EncrypterContract $encrypter,
|
||||
$table, $prefix = '')
|
||||
public function __construct(ConnectionInterface $connection, $table, $prefix = '')
|
||||
{
|
||||
$this->table = $table;
|
||||
$this->prefix = $prefix;
|
||||
$this->encrypter = $encrypter;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
|
|
@ -83,38 +74,37 @@ class DatabaseStore implements Store
|
|||
// If this cache expiration date is past the current time, we will remove this
|
||||
// item from the cache. Then we will return a null value since the cache is
|
||||
// expired. We will use "Carbon" to make this comparison with the column.
|
||||
if (Carbon::now()->getTimestamp() >= $cache->expiration) {
|
||||
if ($this->currentTime() >= $cache->expiration) {
|
||||
$this->forget($key);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->encrypter->decrypt($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;
|
||||
|
||||
// All of the cached values in the database are encrypted in case this is used
|
||||
// as a session data store by the consumer. We'll also calculate the expire
|
||||
// time and place that on the table so we will check it on our retrieval.
|
||||
$value = $this->encrypter->encrypt($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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +161,7 @@ class DatabaseStore implements Store
|
|||
|
||||
$cache = is_array($cache) ? (object) $cache : $cache;
|
||||
|
||||
$current = $this->encrypter->decrypt($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
|
||||
|
|
@ -186,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' => $this->encrypter->encrypt($new),
|
||||
'value' => $this->serialize($new),
|
||||
]);
|
||||
|
||||
return $new;
|
||||
|
|
@ -200,7 +190,7 @@ class DatabaseStore implements Store
|
|||
*/
|
||||
protected function getTime()
|
||||
{
|
||||
return Carbon::now()->getTimestamp();
|
||||
return $this->currentTime();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -208,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -235,7 +225,9 @@ class DatabaseStore implements Store
|
|||
*/
|
||||
public function flush()
|
||||
{
|
||||
return (bool) $this->table()->delete();
|
||||
$this->table()->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -258,16 +250,6 @@ class DatabaseStore implements Store
|
|||
return $this->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the encrypter instance.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Encryption\Encrypter
|
||||
*/
|
||||
public function getEncrypter()
|
||||
{
|
||||
return $this->encrypter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache key prefix.
|
||||
*
|
||||
|
|
@ -277,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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@
|
|||
namespace Illuminate\Cache;
|
||||
|
||||
use Exception;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
|
||||
class FileStore implements Store
|
||||
{
|
||||
use RetrievesMultipleKeys;
|
||||
use InteractsWithTime, RetrievesMultipleKeys;
|
||||
|
||||
/**
|
||||
* The Illuminate Filesystem instance.
|
||||
|
|
@ -47,24 +46,26 @@ class FileStore implements Store
|
|||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return Arr::get($this->getPayload($key), 'data');
|
||||
return $this->getPayload($key)['data'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -92,7 +93,7 @@ class FileStore implements Store
|
|||
$raw = $this->getPayload($key);
|
||||
|
||||
return tap(((int) $raw['data']) + $value, function ($newValue) use ($key, $raw) {
|
||||
$this->put($key, $newValue, $raw['time']);
|
||||
$this->put($key, $newValue, $raw['time'] ?? 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -113,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -165,7 +166,7 @@ class FileStore implements Store
|
|||
{
|
||||
$path = $this->path($key);
|
||||
|
||||
// If the file doesn't exists, we obviously can't return the cache so we will
|
||||
// If the file doesn't exist, we obviously cannot return the cache so we will
|
||||
// just return null. Otherwise, we'll get the contents of the file and get
|
||||
// the expiration UNIX timestamps from the start of the file's contents.
|
||||
try {
|
||||
|
|
@ -179,18 +180,24 @@ class FileStore implements Store
|
|||
// If the current time is greater than expiration timestamps we will delete
|
||||
// the file and return null. This helps clean up the old files and keeps
|
||||
// this directory much cleaner for us as old files aren't hanging out.
|
||||
if (Carbon::now()->getTimestamp() >= $expire) {
|
||||
if ($this->currentTime() >= $expire) {
|
||||
$this->forget($key);
|
||||
|
||||
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 - Carbon::now()->getTimestamp()) / 60;
|
||||
$time = $expire - $this->currentTime();
|
||||
|
||||
return compact('data', 'time');
|
||||
}
|
||||
|
|
@ -219,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 = Carbon::now()->getTimestamp() + (int) ($minutes * 60);
|
||||
$time = $this->availableAt($seconds);
|
||||
|
||||
return $minutes === 0 || $time > 9999999999 ? 9999999999 : (int) $time;
|
||||
return $seconds === 0 || $time > 9999999999 ? 9999999999 : $time;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class MemcachedConnector
|
|||
{
|
||||
$memcached = $this->createMemcachedInstance($connectionId);
|
||||
|
||||
if (count($credentials) == 2) {
|
||||
if (count($credentials) === 2) {
|
||||
$this->setCredentials($memcached, $credentials);
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ class MemcachedConnector
|
|||
*/
|
||||
protected function setCredentials($memcached, $credentials)
|
||||
{
|
||||
list($username, $password) = $credentials;
|
||||
[$username, $password] = $credentials;
|
||||
|
||||
$memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@
|
|||
namespace Illuminate\Cache;
|
||||
|
||||
use Memcached;
|
||||
use Carbon\Carbon;
|
||||
use ReflectionMethod;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Illuminate\Contracts\Cache\LockProvider;
|
||||
|
||||
class MemcachedStore extends TaggableStore implements Store
|
||||
class MemcachedStore extends TaggableStore implements LockProvider
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
/**
|
||||
* The Memcached instance.
|
||||
*
|
||||
|
|
@ -91,26 +93,28 @@ class MemcachedStore 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->memcached->set($this->prefix.$key, $value, $this->toTimestamp($minutes));
|
||||
return $this->memcached->set(
|
||||
$this->prefix.$key, $value, $this->calculateExpiration($seconds)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache for a given number of minutes.
|
||||
* Store multiple items in the cache for a given number of seconds.
|
||||
*
|
||||
* @param array $values
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function putMany(array $values, $minutes)
|
||||
public function putMany(array $values, $seconds)
|
||||
{
|
||||
$prefixedValues = [];
|
||||
|
||||
|
|
@ -118,7 +122,9 @@ class MemcachedStore extends TaggableStore implements Store
|
|||
$prefixedValues[$this->prefix.$key] = $value;
|
||||
}
|
||||
|
||||
$this->memcached->setMulti($prefixedValues, $this->toTimestamp($minutes));
|
||||
return $this->memcached->setMulti(
|
||||
$prefixedValues, $this->calculateExpiration($seconds)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -126,12 +132,14 @@ class MemcachedStore extends TaggableStore implements Store
|
|||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param float|int $minutes
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function add($key, $value, $minutes)
|
||||
public function add($key, $value, $seconds)
|
||||
{
|
||||
return $this->memcached->add($this->prefix.$key, $value, $this->toTimestamp($minutes));
|
||||
return $this->memcached->add(
|
||||
$this->prefix.$key, $value, $this->calculateExpiration($seconds)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -163,11 +171,36 @@ class MemcachedStore 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 MemcachedLock($this->memcached, $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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,14 +225,25 @@ class MemcachedStore extends TaggableStore implements Store
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the UNIX timestamp for the given number of minutes.
|
||||
* Get the expiration time of the key.
|
||||
*
|
||||
* @param int $minutes
|
||||
* @param int $seconds
|
||||
* @return int
|
||||
*/
|
||||
protected function toTimestamp($minutes)
|
||||
protected function calculateExpiration($seconds)
|
||||
{
|
||||
return $minutes > 0 ? Carbon::now()->addSeconds($minutes * 60)->getTimestamp() : 0;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
|
||||
class NullStore extends TaggableStore implements Store
|
||||
class NullStore extends TaggableStore
|
||||
{
|
||||
use RetrievesMultipleKeys;
|
||||
|
||||
|
|
@ -23,20 +21,19 @@ class NullStore extends TaggableStore implements Store
|
|||
*/
|
||||
public function get($key)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -44,11 +41,11 @@ class NullStore extends TaggableStore implements Store
|
|||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return int
|
||||
* @return int|bool
|
||||
*/
|
||||
public function increment($key, $value = 1)
|
||||
{
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -56,11 +53,11 @@ class NullStore extends TaggableStore implements Store
|
|||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return int
|
||||
* @return int|bool
|
||||
*/
|
||||
public function decrement($key, $value = 1)
|
||||
{
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -68,22 +65,22 @@ class NullStore extends TaggableStore implements Store
|
|||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function forget($key)
|
||||
{
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Illuminate\Contracts\Cache\Repository as Cache;
|
||||
|
||||
class RateLimiter
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
/**
|
||||
* The cache store implementation.
|
||||
*
|
||||
|
|
@ -30,55 +32,40 @@ class RateLimiter
|
|||
*
|
||||
* @param string $key
|
||||
* @param int $maxAttempts
|
||||
* @param float|int $decayMinutes
|
||||
* @return bool
|
||||
*/
|
||||
public function tooManyAttempts($key, $maxAttempts, $decayMinutes = 1)
|
||||
public function tooManyAttempts($key, $maxAttempts)
|
||||
{
|
||||
if ($this->cache->has($key.':lockout')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->attempts($key) >= $maxAttempts) {
|
||||
$this->lockout($key, $decayMinutes);
|
||||
if ($this->cache->has($key.':timer')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->resetAttempts($key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the lockout key to the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param int $decayMinutes
|
||||
* @return void
|
||||
*/
|
||||
protected function lockout($key, $decayMinutes)
|
||||
{
|
||||
$this->cache->add(
|
||||
$key.':lockout', Carbon::now()->getTimestamp() + ($decayMinutes * 60), $decayMinutes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the counter for a given key for a given decay time.
|
||||
*
|
||||
* @param string $key
|
||||
* @param float|int $decayMinutes
|
||||
* @param int $decaySeconds
|
||||
* @return int
|
||||
*/
|
||||
public function hit($key, $decayMinutes = 1)
|
||||
public function hit($key, $decaySeconds = 60)
|
||||
{
|
||||
$added = $this->cache->add($key, 0, $decayMinutes);
|
||||
$this->cache->add(
|
||||
$key.':timer', $this->availableAt($decaySeconds), $decaySeconds
|
||||
);
|
||||
|
||||
$added = $this->cache->add($key, 0, $decaySeconds);
|
||||
|
||||
$hits = (int) $this->cache->increment($key);
|
||||
|
||||
if (! $added && $hits == 1) {
|
||||
$this->cache->put($key, 1, $decayMinutes);
|
||||
$this->cache->put($key, 1, $decaySeconds);
|
||||
}
|
||||
|
||||
return $hits;
|
||||
|
|
@ -121,7 +108,7 @@ class RateLimiter
|
|||
}
|
||||
|
||||
/**
|
||||
* Clear the hits and lockout for the given key.
|
||||
* Clear the hits and lockout timer for the given key.
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
|
|
@ -130,7 +117,7 @@ class RateLimiter
|
|||
{
|
||||
$this->resetAttempts($key);
|
||||
|
||||
$this->cache->forget($key.':lockout');
|
||||
$this->cache->forget($key.':timer');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -141,6 +128,6 @@ class RateLimiter
|
|||
*/
|
||||
public function availableIn($key)
|
||||
{
|
||||
return $this->cache->get($key.':lockout') - Carbon::now()->getTimestamp();
|
||||
return $this->cache->get($key.':timer') - $this->currentTime();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Contracts\Cache\LockProvider;
|
||||
use Illuminate\Contracts\Redis\Factory as Redis;
|
||||
|
||||
class RedisStore extends TaggableStore implements Store
|
||||
class RedisStore extends TaggableStore implements LockProvider
|
||||
{
|
||||
/**
|
||||
* The Redis factory implementation.
|
||||
|
|
@ -80,36 +80,42 @@ class RedisStore 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->connection()->setex(
|
||||
$this->prefix.$key, (int) max(1, $minutes * 60), $this->serialize($value)
|
||||
return (bool) $this->connection()->setex(
|
||||
$this->prefix.$key, (int) max(1, $seconds), $this->serialize($value)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache for a given number of minutes.
|
||||
* Store multiple items in the cache for a given number of seconds.
|
||||
*
|
||||
* @param array $values
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function putMany(array $values, $minutes)
|
||||
public function putMany(array $values, $seconds)
|
||||
{
|
||||
$this->connection()->multi();
|
||||
|
||||
$manyResult = null;
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$this->put($key, $value, $minutes);
|
||||
$result = $this->put($key, $value, $seconds);
|
||||
|
||||
$manyResult = is_null($manyResult) ? $result : $result && $manyResult;
|
||||
}
|
||||
|
||||
$this->connection()->exec();
|
||||
|
||||
return $manyResult ?: false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,15 +123,15 @@ class RedisStore extends TaggableStore implements Store
|
|||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param float|int $minutes
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function add($key, $value, $minutes)
|
||||
public function add($key, $value, $seconds)
|
||||
{
|
||||
$lua = "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])";
|
||||
|
||||
return (bool) $this->connection()->eval(
|
||||
$lua, 1, $this->prefix.$key, $this->serialize($value), (int) max(1, $minutes * 60)
|
||||
$lua, 1, $this->prefix.$key, $this->serialize($value), (int) max(1, $seconds)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -158,11 +164,36 @@ class RedisStore extends TaggableStore implements Store
|
|||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
$this->connection()->set($this->prefix.$key, $this->serialize($value));
|
||||
return (bool) $this->connection()->set($this->prefix.$key, $this->serialize($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 RedisLock($this->connection(), $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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,41 +22,73 @@ class RedisTaggedCache extends TaggedCache
|
|||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTime|float|int $minutes
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $ttl = null)
|
||||
{
|
||||
if ($ttl === null) {
|
||||
return $this->forever($key, $value);
|
||||
}
|
||||
|
||||
$this->pushStandardKeys($this->tags->getNamespace(), $key);
|
||||
|
||||
return parent::put($key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the value of an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function put($key, $value, $minutes = null)
|
||||
public function increment($key, $value = 1)
|
||||
{
|
||||
$this->pushStandardKeys($this->tags->getNamespace(), $key);
|
||||
|
||||
parent::put($key, $value, $minutes);
|
||||
parent::increment($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the value of an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function decrement($key, $value = 1)
|
||||
{
|
||||
$this->pushStandardKeys($this->tags->getNamespace(), $key);
|
||||
|
||||
parent::decrement($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache indefinitely.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
$this->pushForeverKeys($this->tags->getNamespace(), $key);
|
||||
|
||||
parent::forever($key, $value);
|
||||
return parent::forever($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all items from the cache.
|
||||
*
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$this->deleteForeverKeys();
|
||||
$this->deleteStandardKeys();
|
||||
|
||||
parent::flush();
|
||||
return parent::flush();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,16 +3,17 @@
|
|||
namespace Illuminate\Cache;
|
||||
|
||||
use Closure;
|
||||
use DateTime;
|
||||
use ArrayAccess;
|
||||
use Carbon\Carbon;
|
||||
use DateTimeInterface;
|
||||
use BadMethodCallException;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Cache\Events\CacheHit;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Cache\Events\KeyWritten;
|
||||
use Illuminate\Cache\Events\CacheMissed;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Illuminate\Cache\Events\KeyForgotten;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\Cache\Repository as CacheContract;
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ use Illuminate\Contracts\Cache\Repository as CacheContract;
|
|||
*/
|
||||
class Repository implements CacheContract, ArrayAccess
|
||||
{
|
||||
use InteractsWithTime;
|
||||
use Macroable {
|
||||
__call as macroCall;
|
||||
}
|
||||
|
|
@ -40,11 +42,11 @@ class Repository implements CacheContract, ArrayAccess
|
|||
protected $events;
|
||||
|
||||
/**
|
||||
* The default number of minutes to store items.
|
||||
* The default number of seconds to store items.
|
||||
*
|
||||
* @var float|int
|
||||
* @var int|null
|
||||
*/
|
||||
protected $default = 60;
|
||||
protected $default = 3600;
|
||||
|
||||
/**
|
||||
* Create a new cache repository instance.
|
||||
|
|
@ -68,11 +70,22 @@ class Repository implements CacheContract, ArrayAccess
|
|||
return ! is_null($this->get($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an item doesn't exist in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function missing($key)
|
||||
{
|
||||
return ! $this->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an item from the cache by key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
|
|
@ -116,6 +129,20 @@ class Repository implements CacheContract, ArrayAccess
|
|||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMultiple($keys, $default = null)
|
||||
{
|
||||
$defaults = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$defaults[$key] = $default;
|
||||
}
|
||||
|
||||
return $this->many($defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a result for the "many" method.
|
||||
*
|
||||
|
|
@ -147,12 +174,12 @@ class Repository implements CacheContract, ArrayAccess
|
|||
* Retrieve an item from the cache and delete it.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function pull($key, $default = null)
|
||||
{
|
||||
return tap($this->get($key, $default), function ($value) use ($key) {
|
||||
return tap($this->get($key, $default), function () use ($key) {
|
||||
$this->forget($key);
|
||||
});
|
||||
}
|
||||
|
|
@ -161,71 +188,132 @@ class Repository implements CacheContract, ArrayAccess
|
|||
* Store an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTime|float|int $minutes
|
||||
* @return void
|
||||
* @param mixed $value
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $minutes = null)
|
||||
public function put($key, $value, $ttl = null)
|
||||
{
|
||||
if (is_array($key)) {
|
||||
return $this->putMany($key, $value);
|
||||
}
|
||||
|
||||
if (! is_null($minutes = $this->getMinutes($minutes))) {
|
||||
$this->store->put($this->itemKey($key), $value, $minutes);
|
||||
|
||||
$this->event(new KeyWritten($key, $value, $minutes));
|
||||
if ($ttl === null) {
|
||||
return $this->forever($key, $value);
|
||||
}
|
||||
|
||||
$seconds = $this->getSeconds($ttl);
|
||||
|
||||
if ($seconds <= 0) {
|
||||
return $this->forget($key);
|
||||
}
|
||||
|
||||
$result = $this->store->put($this->itemKey($key), $value, $seconds);
|
||||
|
||||
if ($result) {
|
||||
$this->event(new KeyWritten($key, $value, $seconds));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache for a given number of minutes.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($key, $value, $ttl = null)
|
||||
{
|
||||
return $this->put($key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache for a given number of seconds.
|
||||
*
|
||||
* @param array $values
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @return bool
|
||||
*/
|
||||
public function putMany(array $values, $minutes)
|
||||
public function putMany(array $values, $ttl = null)
|
||||
{
|
||||
if (! is_null($minutes = $this->getMinutes($minutes))) {
|
||||
$this->store->putMany($values, $minutes);
|
||||
if ($ttl === null) {
|
||||
return $this->putManyForever($values);
|
||||
}
|
||||
|
||||
$seconds = $this->getSeconds($ttl);
|
||||
|
||||
if ($seconds <= 0) {
|
||||
return $this->deleteMultiple(array_keys($values));
|
||||
}
|
||||
|
||||
$result = $this->store->putMany($values, $seconds);
|
||||
|
||||
if ($result) {
|
||||
foreach ($values as $key => $value) {
|
||||
$this->event(new KeyWritten($key, $value, $minutes));
|
||||
$this->event(new KeyWritten($key, $value, $seconds));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache indefinitely.
|
||||
*
|
||||
* @param array $values
|
||||
* @return bool
|
||||
*/
|
||||
protected function putManyForever(array $values)
|
||||
{
|
||||
$result = true;
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
if (! $this->forever($key, $value)) {
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMultiple($values, $ttl = null)
|
||||
{
|
||||
return $this->putMany(is_array($values) ? $values : iterator_to_array($values), $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an item in the cache if the key does not exist.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTime|float|int $minutes
|
||||
* @param mixed $value
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @return bool
|
||||
*/
|
||||
public function add($key, $value, $minutes)
|
||||
public function add($key, $value, $ttl = null)
|
||||
{
|
||||
if (is_null($minutes = $this->getMinutes($minutes))) {
|
||||
return false;
|
||||
}
|
||||
if ($ttl !== null) {
|
||||
if ($this->getSeconds($ttl) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the store has an "add" method we will call the method on the store so it
|
||||
// has a chance to override this logic. Some drivers better support the way
|
||||
// this operation should work with a total "atomic" implementation of it.
|
||||
if (method_exists($this->store, 'add')) {
|
||||
return $this->store->add(
|
||||
$this->itemKey($key), $value, $minutes
|
||||
);
|
||||
// If the store has an "add" method we will call the method on the store so it
|
||||
// has a chance to override this logic. Some drivers better support the way
|
||||
// this operation should work with a total "atomic" implementation of it.
|
||||
if (method_exists($this->store, 'add')) {
|
||||
$seconds = $this->getSeconds($ttl);
|
||||
|
||||
return $this->store->add(
|
||||
$this->itemKey($key), $value, $seconds
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If the value did not exist in the cache, we will put the value in the cache
|
||||
// so it exists for subsequent requests. Then, we will return true so it is
|
||||
// easy to know if the value gets added. Otherwise, we will return false.
|
||||
if (is_null($this->get($key))) {
|
||||
$this->put($key, $value, $minutes);
|
||||
|
||||
return true;
|
||||
return $this->put($key, $value, $ttl);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -259,44 +347,48 @@ class Repository implements CacheContract, ArrayAccess
|
|||
* Store an item in the cache indefinitely.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value)
|
||||
{
|
||||
$this->store->forever($this->itemKey($key), $value);
|
||||
$result = $this->store->forever($this->itemKey($key), $value);
|
||||
|
||||
$this->event(new KeyWritten($key, $value, 0));
|
||||
if ($result) {
|
||||
$this->event(new KeyWritten($key, $value));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from the cache, or store the default value.
|
||||
* Get an item from the cache, or execute the given Closure and store the result.
|
||||
*
|
||||
* @param string $key
|
||||
* @param \DateTime|float|int $minutes
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function remember($key, $minutes, Closure $callback)
|
||||
public function remember($key, $ttl, Closure $callback)
|
||||
{
|
||||
$value = $this->get($key);
|
||||
|
||||
// If the item exists in the cache we will just return this immediately and if
|
||||
// not we will execute the given Closure and cache the result of that for a
|
||||
// given number of minutes so it's available for all subsequent requests.
|
||||
// given number of seconds so it's available for all subsequent requests.
|
||||
if (! is_null($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$this->put($key, $value = $callback(), $minutes);
|
||||
$this->put($key, $value = $callback(), $ttl);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from the cache, or store the default value forever.
|
||||
* Get an item from the cache, or execute the given Closure and store the result forever.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $key
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
@ -306,9 +398,9 @@ class Repository implements CacheContract, ArrayAccess
|
|||
}
|
||||
|
||||
/**
|
||||
* Get an item from the cache, or store the default value forever.
|
||||
* Get an item from the cache, or execute the given Closure and store the result forever.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $key
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
@ -316,9 +408,9 @@ class Repository implements CacheContract, ArrayAccess
|
|||
{
|
||||
$value = $this->get($key);
|
||||
|
||||
// If the item exists in the cache we will just return this immediately and if
|
||||
// not we will execute the given Closure and cache the result of that for a
|
||||
// given number of minutes so it's available for all subsequent requests.
|
||||
// If the item exists in the cache we will just return this immediately
|
||||
// and if not we will execute the given Closure and cache the result
|
||||
// of that forever so it is available for all subsequent requests.
|
||||
if (! is_null($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
|
@ -336,11 +428,45 @@ class Repository implements CacheContract, ArrayAccess
|
|||
*/
|
||||
public function forget($key)
|
||||
{
|
||||
return tap($this->store->forget($this->itemKey($key)), function () use ($key) {
|
||||
$this->event(new KeyForgotten($key));
|
||||
return tap($this->store->forget($this->itemKey($key)), function ($result) use ($key) {
|
||||
if ($result) {
|
||||
$this->event(new KeyForgotten($key));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
return $this->forget($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function deleteMultiple($keys)
|
||||
{
|
||||
$result = true;
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if (! $this->forget($key)) {
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
return $this->store->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin executing a new tags operation if the store supports it.
|
||||
*
|
||||
|
|
@ -355,7 +481,7 @@ class Repository implements CacheContract, ArrayAccess
|
|||
throw new BadMethodCallException('This cache store does not support tagging.');
|
||||
}
|
||||
|
||||
$cache = $this->store->tags($names);
|
||||
$cache = $this->store->tags(is_array($names) ? $names : func_get_args());
|
||||
|
||||
if (! is_null($this->events)) {
|
||||
$cache->setEventDispatcher($this->events);
|
||||
|
|
@ -378,7 +504,7 @@ class Repository implements CacheContract, ArrayAccess
|
|||
/**
|
||||
* Get the default cache time.
|
||||
*
|
||||
* @return float|int
|
||||
* @return int
|
||||
*/
|
||||
public function getDefaultCacheTime()
|
||||
{
|
||||
|
|
@ -386,14 +512,14 @@ class Repository implements CacheContract, ArrayAccess
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the default cache time in minutes.
|
||||
* Set the default cache time in seconds.
|
||||
*
|
||||
* @param float|int $minutes
|
||||
* @param int|null $seconds
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefaultCacheTime($minutes)
|
||||
public function setDefaultCacheTime($seconds)
|
||||
{
|
||||
$this->default = $minutes;
|
||||
$this->default = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -478,25 +604,27 @@ class Repository implements CacheContract, ArrayAccess
|
|||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of minutes with the given duration.
|
||||
* Calculate the number of seconds for the given TTL.
|
||||
*
|
||||
* @param \DateTime|float|int $duration
|
||||
* @return float|int|null
|
||||
* @param \DateTimeInterface|\DateInterval|int $ttl
|
||||
* @return int
|
||||
*/
|
||||
protected function getMinutes($duration)
|
||||
protected function getSeconds($ttl)
|
||||
{
|
||||
if ($duration instanceof DateTime) {
|
||||
$duration = Carbon::now()->diffInSeconds(Carbon::instance($duration), false) / 60;
|
||||
$duration = $this->parseDateInterval($ttl);
|
||||
|
||||
if ($duration instanceof DateTimeInterface) {
|
||||
$duration = Carbon::now()->diffInRealSeconds($duration, false);
|
||||
}
|
||||
|
||||
return (int) ($duration * 60) > 0 ? $duration : null;
|
||||
return (int) $duration > 0 ? $duration : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dynamic calls into macros or pass missing methods to the store.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
|
|
|
|||
|
|
@ -24,16 +24,22 @@ trait RetrievesMultipleKeys
|
|||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache for a given number of minutes.
|
||||
* Store multiple items in the cache for a given number of seconds.
|
||||
*
|
||||
* @param array $values
|
||||
* @param float|int $minutes
|
||||
* @return void
|
||||
* @param int $seconds
|
||||
* @return bool
|
||||
*/
|
||||
public function putMany(array $values, $minutes)
|
||||
public function putMany(array $values, $seconds)
|
||||
{
|
||||
$manyResult = null;
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$this->put($key, $value, $minutes);
|
||||
$result = $this->put($key, $value, $seconds);
|
||||
|
||||
$manyResult = is_null($manyResult) ? $result : $result && $manyResult;
|
||||
}
|
||||
|
||||
return $manyResult ?: false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
namespace Illuminate\Cache;
|
||||
|
||||
abstract class TaggableStore
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
|
||||
abstract class TaggableStore implements Store
|
||||
{
|
||||
/**
|
||||
* Begin executing a new tags operation.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ use Illuminate\Contracts\Cache\Store;
|
|||
|
||||
class TaggedCache extends Repository
|
||||
{
|
||||
use RetrievesMultipleKeys;
|
||||
use RetrievesMultipleKeys {
|
||||
putMany as putManyAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tag set instance.
|
||||
|
|
@ -29,11 +31,27 @@ class TaggedCache extends Repository
|
|||
$this->tags = $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store multiple items in the cache for a given number of seconds.
|
||||
*
|
||||
* @param array $values
|
||||
* @param int|null $ttl
|
||||
* @return bool
|
||||
*/
|
||||
public function putMany(array $values, $ttl = null)
|
||||
{
|
||||
if ($ttl === null) {
|
||||
return $this->putManyForever($values);
|
||||
}
|
||||
|
||||
return $this->putManyAlias($values, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the value of an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function increment($key, $value = 1)
|
||||
|
|
@ -42,10 +60,10 @@ class TaggedCache extends Repository
|
|||
}
|
||||
|
||||
/**
|
||||
* Increment the value of an item in the cache.
|
||||
* Decrement the value of an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function decrement($key, $value = 1)
|
||||
|
|
@ -56,11 +74,13 @@ class TaggedCache extends Repository
|
|||
/**
|
||||
* Remove all items from the cache.
|
||||
*
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$this->tags->reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -92,4 +112,14 @@ class TaggedCache extends Repository
|
|||
{
|
||||
parent::event($event->setTags($this->tags->getNames()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag set instance.
|
||||
*
|
||||
* @return \Illuminate\Cache\TagSet
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
return $this->tags;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,9 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/contracts": "5.4.*",
|
||||
"illuminate/support": "5.4.*",
|
||||
"nesbot/carbon": "~1.20"
|
||||
"php": "^7.1.3",
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/support": "5.8.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -26,13 +25,13 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/database": "Required to use the database cache driver (5.4.*).",
|
||||
"illuminate/filesystem": "Required to use the file cache driver (5.4.*).",
|
||||
"illuminate/redis": "Required to use the redis cache driver (5.4.*)."
|
||||
"illuminate/database": "Required to use the database cache driver (5.8.*).",
|
||||
"illuminate/filesystem": "Required to use the file cache driver (5.8.*).",
|
||||
"illuminate/redis": "Required to use the redis cache driver (5.8.*)."
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
|
|
|
|||
|
|
@ -40,15 +40,40 @@ class Repository implements ArrayAccess, ConfigContract
|
|||
/**
|
||||
* Get the specified configuration value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if (is_array($key)) {
|
||||
return $this->getMany($key);
|
||||
}
|
||||
|
||||
return Arr::get($this->items, $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get many configuration values.
|
||||
*
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
public function getMany($keys)
|
||||
{
|
||||
$config = [];
|
||||
|
||||
foreach ($keys as $key => $default) {
|
||||
if (is_numeric($key)) {
|
||||
[$key, $default] = [$default, null];
|
||||
}
|
||||
|
||||
$config[$key] = Arr::get($this->items, $key, $default);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a given configuration value.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/contracts": "5.4.*",
|
||||
"illuminate/support": "5.4.*"
|
||||
"php": "^7.1.3",
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/support": "5.8.*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
|
|
|
|||
|
|
@ -3,15 +3,21 @@
|
|||
namespace Illuminate\Console;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\ProcessUtils;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Symfony\Component\Process\ProcessUtils;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Process\PhpExecutableFinder;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Application as SymfonyApplication;
|
||||
use Symfony\Component\Console\Command\Command as SymfonyCommand;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
use Illuminate\Contracts\Console\Application as ApplicationContract;
|
||||
|
||||
class Application extends SymfonyApplication implements ApplicationContract
|
||||
|
|
@ -37,6 +43,13 @@ class Application extends SymfonyApplication implements ApplicationContract
|
|||
*/
|
||||
protected static $bootstrappers = [];
|
||||
|
||||
/**
|
||||
* The Event Dispatcher.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Events\Dispatcher
|
||||
*/
|
||||
protected $events;
|
||||
|
||||
/**
|
||||
* Create a new Artisan console application.
|
||||
*
|
||||
|
|
@ -50,14 +63,39 @@ class Application extends SymfonyApplication implements ApplicationContract
|
|||
parent::__construct('Laravel Framework', $version);
|
||||
|
||||
$this->laravel = $laravel;
|
||||
$this->events = $events;
|
||||
$this->setAutoExit(false);
|
||||
$this->setCatchExceptions(false);
|
||||
|
||||
$events->dispatch(new Events\ArtisanStarting($this));
|
||||
$this->events->dispatch(new Events\ArtisanStarting($this));
|
||||
|
||||
$this->bootstrap();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function run(InputInterface $input = null, OutputInterface $output = null)
|
||||
{
|
||||
$commandName = $this->getCommandName(
|
||||
$input = $input ?: new ArgvInput
|
||||
);
|
||||
|
||||
$this->events->dispatch(
|
||||
new Events\CommandStarting(
|
||||
$commandName, $input, $output = $output ?: new ConsoleOutput
|
||||
)
|
||||
);
|
||||
|
||||
$exitCode = parent::run($input, $output);
|
||||
|
||||
$this->events->dispatch(
|
||||
new Events\CommandFinished($commandName, $input, $output, $exitCode)
|
||||
);
|
||||
|
||||
return $exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the proper PHP executable.
|
||||
*
|
||||
|
|
@ -127,22 +165,48 @@ class Application extends SymfonyApplication implements ApplicationContract
|
|||
*
|
||||
* @param string $command
|
||||
* @param array $parameters
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $outputBuffer
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface|null $outputBuffer
|
||||
* @return int
|
||||
*
|
||||
* @throws \Symfony\Component\Console\Exception\CommandNotFoundException
|
||||
*/
|
||||
public function call($command, array $parameters = [], $outputBuffer = null)
|
||||
{
|
||||
$parameters = collect($parameters)->prepend($command);
|
||||
[$command, $input] = $this->parseCommand($command, $parameters);
|
||||
|
||||
$this->lastOutput = $outputBuffer ?: new BufferedOutput;
|
||||
if (! $this->has($command)) {
|
||||
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $command));
|
||||
}
|
||||
|
||||
$this->setCatchExceptions(false);
|
||||
return $this->run(
|
||||
$input, $this->lastOutput = $outputBuffer ?: new BufferedOutput
|
||||
);
|
||||
}
|
||||
|
||||
$result = $this->run(new ArrayInput($parameters->toArray()), $this->lastOutput);
|
||||
/**
|
||||
* Parse the incoming Artisan command and its input.
|
||||
*
|
||||
* @param string $command
|
||||
* @param array $parameters
|
||||
* @return array
|
||||
*/
|
||||
protected function parseCommand($command, $parameters)
|
||||
{
|
||||
if (is_subclass_of($command, SymfonyCommand::class)) {
|
||||
$callingClass = true;
|
||||
|
||||
$this->setCatchExceptions(true);
|
||||
$command = $this->laravel->make($command)->getName();
|
||||
}
|
||||
|
||||
return $result;
|
||||
if (! isset($callingClass) && empty($parameters)) {
|
||||
$command = $this->getCommandName($input = new StringInput($command));
|
||||
} else {
|
||||
array_unshift($parameters, $command);
|
||||
|
||||
$input = new ArrayInput($parameters);
|
||||
}
|
||||
|
||||
return [$command, $input ?? null];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -152,7 +216,9 @@ class Application extends SymfonyApplication implements ApplicationContract
|
|||
*/
|
||||
public function output()
|
||||
{
|
||||
return $this->lastOutput ? $this->lastOutput->fetch() : '';
|
||||
return $this->lastOutput && method_exists($this->lastOutput, 'fetch')
|
||||
? $this->lastOutput->fetch()
|
||||
: '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -210,7 +276,7 @@ class Application extends SymfonyApplication implements ApplicationContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the default input definitions for the applications.
|
||||
* Get the default input definition for the application.
|
||||
*
|
||||
* This is used to add the --env option to every available command.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Illuminate\Console;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
|
|
@ -15,6 +17,8 @@ use Symfony\Component\Console\Command\Command as SymfonyCommand;
|
|||
|
||||
class Command extends SymfonyCommand
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* The Laravel application instance.
|
||||
*
|
||||
|
|
@ -105,7 +109,7 @@ class Command extends SymfonyCommand
|
|||
// the command we'll set the arguments and the options on this command.
|
||||
$this->setDescription($this->description);
|
||||
|
||||
$this->setHidden($this->hidden);
|
||||
$this->setHidden($this->isHidden());
|
||||
|
||||
if (! isset($this->signature)) {
|
||||
$this->specifyParameters();
|
||||
|
|
@ -119,20 +123,15 @@ class Command extends SymfonyCommand
|
|||
*/
|
||||
protected function configureUsingFluentDefinition()
|
||||
{
|
||||
list($name, $arguments, $options) = Parser::parse($this->signature);
|
||||
[$name, $arguments, $options] = Parser::parse($this->signature);
|
||||
|
||||
parent::__construct($this->name = $name);
|
||||
|
||||
// After parsing the signature we will spin through the arguments and options
|
||||
// and set them on this command. These will already be changed into proper
|
||||
// instances of these "InputArgument" and "InputOption" Symfony classes.
|
||||
foreach ($arguments as $argument) {
|
||||
$this->getDefinition()->addArgument($argument);
|
||||
}
|
||||
|
||||
foreach ($options as $option) {
|
||||
$this->getDefinition()->addOption($option);
|
||||
}
|
||||
$this->getDefinition()->addArguments($arguments);
|
||||
$this->getDefinition()->addOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -163,8 +162,12 @@ class Command extends SymfonyCommand
|
|||
*/
|
||||
public function run(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->output = $this->laravel->make(
|
||||
OutputStyle::class, ['input' => $input, 'output' => $output]
|
||||
);
|
||||
|
||||
return parent::run(
|
||||
$this->input = $input, $this->output = new OutputStyle($input, $output)
|
||||
$this->input = $input, $this->output
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -177,9 +180,7 @@ class Command extends SymfonyCommand
|
|||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$method = method_exists($this, 'handle') ? 'handle' : 'fire';
|
||||
|
||||
return $this->laravel->call([$this, $method]);
|
||||
return $this->laravel->call([$this, 'handle']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -194,7 +195,7 @@ class Command extends SymfonyCommand
|
|||
$arguments['command'] = $command;
|
||||
|
||||
return $this->getApplication()->find($command)->run(
|
||||
new ArrayInput($arguments), $this->output
|
||||
$this->createInputFromArguments($arguments), $this->output
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -210,10 +211,43 @@ class Command extends SymfonyCommand
|
|||
$arguments['command'] = $command;
|
||||
|
||||
return $this->getApplication()->find($command)->run(
|
||||
new ArrayInput($arguments), new NullOutput
|
||||
$this->createInputFromArguments($arguments), new NullOutput
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an input instance from the given arguments.
|
||||
*
|
||||
* @param array $arguments
|
||||
* @return \Symfony\Component\Console\Input\ArrayInput
|
||||
*/
|
||||
protected function createInputFromArguments(array $arguments)
|
||||
{
|
||||
return tap(new ArrayInput(array_merge($this->context(), $arguments)), function ($input) {
|
||||
if ($input->hasParameterOption(['--no-interaction'], true)) {
|
||||
$input->setInteractive(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the context passed to the command.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function context()
|
||||
{
|
||||
return collect($this->option())->only([
|
||||
'ansi',
|
||||
'no-ansi',
|
||||
'no-interaction',
|
||||
'quiet',
|
||||
'verbose',
|
||||
])->filter()->mapWithKeys(function ($value, $key) {
|
||||
return ["--{$key}" => $value];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given argument is present.
|
||||
*
|
||||
|
|
@ -229,7 +263,7 @@ class Command extends SymfonyCommand
|
|||
* Get the value of a command argument.
|
||||
*
|
||||
* @param string|null $key
|
||||
* @return string|array
|
||||
* @return string|array|null
|
||||
*/
|
||||
public function argument($key = null)
|
||||
{
|
||||
|
|
@ -264,8 +298,8 @@ class Command extends SymfonyCommand
|
|||
/**
|
||||
* Get the value of a command option.
|
||||
*
|
||||
* @param string $key
|
||||
* @return string|array
|
||||
* @param string|null $key
|
||||
* @return string|array|bool|null
|
||||
*/
|
||||
public function option($key = null)
|
||||
{
|
||||
|
|
@ -302,8 +336,8 @@ class Command extends SymfonyCommand
|
|||
* Prompt the user for input.
|
||||
*
|
||||
* @param string $question
|
||||
* @param string $default
|
||||
* @return string
|
||||
* @param string|null $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function ask($question, $default = null)
|
||||
{
|
||||
|
|
@ -315,8 +349,8 @@ class Command extends SymfonyCommand
|
|||
*
|
||||
* @param string $question
|
||||
* @param array $choices
|
||||
* @param string $default
|
||||
* @return string
|
||||
* @param string|null $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function anticipate($question, array $choices, $default = null)
|
||||
{
|
||||
|
|
@ -328,8 +362,8 @@ class Command extends SymfonyCommand
|
|||
*
|
||||
* @param string $question
|
||||
* @param array $choices
|
||||
* @param string $default
|
||||
* @return string
|
||||
* @param string|null $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function askWithCompletion($question, array $choices, $default = null)
|
||||
{
|
||||
|
|
@ -345,7 +379,7 @@ class Command extends SymfonyCommand
|
|||
*
|
||||
* @param string $question
|
||||
* @param bool $fallback
|
||||
* @return string
|
||||
* @return mixed
|
||||
*/
|
||||
public function secret($question, $fallback = true)
|
||||
{
|
||||
|
|
@ -361,9 +395,9 @@ class Command extends SymfonyCommand
|
|||
*
|
||||
* @param string $question
|
||||
* @param array $choices
|
||||
* @param string $default
|
||||
* @param mixed $attempts
|
||||
* @param bool $multiple
|
||||
* @param string|null $default
|
||||
* @param mixed|null $attempts
|
||||
* @param bool|null $multiple
|
||||
* @return string
|
||||
*/
|
||||
public function choice($question, array $choices, $default = null, $attempts = null, $multiple = null)
|
||||
|
|
@ -380,10 +414,11 @@ class Command extends SymfonyCommand
|
|||
*
|
||||
* @param array $headers
|
||||
* @param \Illuminate\Contracts\Support\Arrayable|array $rows
|
||||
* @param string $style
|
||||
* @param string $tableStyle
|
||||
* @param array $columnStyles
|
||||
* @return void
|
||||
*/
|
||||
public function table(array $headers, $rows, $style = 'default')
|
||||
public function table($headers, $rows, $tableStyle = 'default', array $columnStyles = [])
|
||||
{
|
||||
$table = new Table($this->output);
|
||||
|
||||
|
|
@ -391,14 +426,20 @@ class Command extends SymfonyCommand
|
|||
$rows = $rows->toArray();
|
||||
}
|
||||
|
||||
$table->setHeaders($headers)->setRows($rows)->setStyle($style)->render();
|
||||
$table->setHeaders((array) $headers)->setRows($rows)->setStyle($tableStyle);
|
||||
|
||||
foreach ($columnStyles as $columnIndex => $columnStyle) {
|
||||
$table->setColumnStyle($columnIndex, $columnStyle);
|
||||
}
|
||||
|
||||
$table->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string as information output.
|
||||
*
|
||||
* @param string $string
|
||||
* @param null|int|string $verbosity
|
||||
* @param int|string|null $verbosity
|
||||
* @return void
|
||||
*/
|
||||
public function info($string, $verbosity = null)
|
||||
|
|
@ -410,8 +451,8 @@ class Command extends SymfonyCommand
|
|||
* Write a string as standard output.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $style
|
||||
* @param null|int|string $verbosity
|
||||
* @param string|null $style
|
||||
* @param int|string|null $verbosity
|
||||
* @return void
|
||||
*/
|
||||
public function line($string, $style = null, $verbosity = null)
|
||||
|
|
@ -425,7 +466,7 @@ class Command extends SymfonyCommand
|
|||
* Write a string as comment output.
|
||||
*
|
||||
* @param string $string
|
||||
* @param null|int|string $verbosity
|
||||
* @param int|string|null $verbosity
|
||||
* @return void
|
||||
*/
|
||||
public function comment($string, $verbosity = null)
|
||||
|
|
@ -437,7 +478,7 @@ class Command extends SymfonyCommand
|
|||
* Write a string as question output.
|
||||
*
|
||||
* @param string $string
|
||||
* @param null|int|string $verbosity
|
||||
* @param int|string|null $verbosity
|
||||
* @return void
|
||||
*/
|
||||
public function question($string, $verbosity = null)
|
||||
|
|
@ -449,7 +490,7 @@ class Command extends SymfonyCommand
|
|||
* Write a string as error output.
|
||||
*
|
||||
* @param string $string
|
||||
* @param null|int|string $verbosity
|
||||
* @param int|string|null $verbosity
|
||||
* @return void
|
||||
*/
|
||||
public function error($string, $verbosity = null)
|
||||
|
|
@ -461,7 +502,7 @@ class Command extends SymfonyCommand
|
|||
* Write a string as warning output.
|
||||
*
|
||||
* @param string $string
|
||||
* @param null|int|string $verbosity
|
||||
* @param int|string|null $verbosity
|
||||
* @return void
|
||||
*/
|
||||
public function warn($string, $verbosity = null)
|
||||
|
|
@ -483,11 +524,13 @@ class Command extends SymfonyCommand
|
|||
*/
|
||||
public function alert($string)
|
||||
{
|
||||
$this->comment(str_repeat('*', strlen($string) + 12));
|
||||
$this->comment('* '.$string.' *');
|
||||
$this->comment(str_repeat('*', strlen($string) + 12));
|
||||
$length = Str::length(strip_tags($string)) + 12;
|
||||
|
||||
$this->output->writeln('');
|
||||
$this->comment(str_repeat('*', $length));
|
||||
$this->comment('* '.$string.' *');
|
||||
$this->comment(str_repeat('*', $length));
|
||||
|
||||
$this->output->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -504,7 +547,7 @@ class Command extends SymfonyCommand
|
|||
/**
|
||||
* Get the verbosity level in terms of Symfony's OutputInterface level.
|
||||
*
|
||||
* @param string|int $level
|
||||
* @param string|int|null $level
|
||||
* @return int
|
||||
*/
|
||||
protected function parseVerbosity($level = null)
|
||||
|
|
@ -518,6 +561,24 @@ class Command extends SymfonyCommand
|
|||
return $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isHidden()
|
||||
{
|
||||
return $this->hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setHidden($hidden)
|
||||
{
|
||||
parent::setHidden($this->hidden = $hidden);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command arguments.
|
||||
*
|
||||
|
|
@ -541,7 +602,7 @@ class Command extends SymfonyCommand
|
|||
/**
|
||||
* Get the output implementation.
|
||||
*
|
||||
* @return \Symfony\Component\Console\Output\OutputInterface
|
||||
* @return \Illuminate\Console\OutputStyle
|
||||
*/
|
||||
public function getOutput()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ trait ConfirmableTrait
|
|||
$shouldConfirm = $callback instanceof Closure ? call_user_func($callback) : $callback;
|
||||
|
||||
if ($shouldConfirm) {
|
||||
if ($this->option('force')) {
|
||||
if ($this->hasOption('force') && $this->option('force')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ trait ConfirmableTrait
|
|||
protected function getDefaultConfirmCallback()
|
||||
{
|
||||
return function () {
|
||||
return $this->getLaravel()->environment() == 'production';
|
||||
return $this->getLaravel()->environment() === 'production';
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,8 +46,9 @@ abstract class GeneratorCommand extends Command
|
|||
* Execute the console command.
|
||||
*
|
||||
* @return bool|null
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
$name = $this->qualifyClass($this->getNameInput());
|
||||
|
||||
|
|
@ -56,7 +57,9 @@ abstract class GeneratorCommand extends Command
|
|||
// First we will check to see if the class already exists. If it does, we don't want
|
||||
// to create the class and overwrite the user's code. So, we will bail out so the
|
||||
// code is untouched. Otherwise, we will continue generating this class' files.
|
||||
if ($this->alreadyExists($this->getNameInput())) {
|
||||
if ((! $this->hasOption('force') ||
|
||||
! $this->option('force')) &&
|
||||
$this->alreadyExists($this->getNameInput())) {
|
||||
$this->error($this->type.' already exists!');
|
||||
|
||||
return false;
|
||||
|
|
@ -80,6 +83,8 @@ abstract class GeneratorCommand extends Command
|
|||
*/
|
||||
protected function qualifyClass($name)
|
||||
{
|
||||
$name = ltrim($name, '\\/');
|
||||
|
||||
$rootNamespace = $this->rootNamespace();
|
||||
|
||||
if (Str::startsWith($name, $rootNamespace)) {
|
||||
|
|
@ -123,7 +128,7 @@ abstract class GeneratorCommand extends Command
|
|||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace_first($this->rootNamespace(), '', $name);
|
||||
$name = Str::replaceFirst($this->rootNamespace(), '', $name);
|
||||
|
||||
return $this->laravel['path'].'/'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
|
@ -148,6 +153,7 @@ abstract class GeneratorCommand extends Command
|
|||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
protected function buildClass($name)
|
||||
{
|
||||
|
|
@ -166,8 +172,8 @@ abstract class GeneratorCommand extends Command
|
|||
protected function replaceNamespace(&$stub, $name)
|
||||
{
|
||||
$stub = str_replace(
|
||||
['DummyNamespace', 'DummyRootNamespace'],
|
||||
[$this->getNamespace($name), $this->rootNamespace()],
|
||||
['DummyNamespace', 'DummyRootNamespace', 'NamespacedDummyUserModel'],
|
||||
[$this->getNamespace($name), $this->rootNamespace(), $this->userProviderModel()],
|
||||
$stub
|
||||
);
|
||||
|
||||
|
|
@ -219,6 +225,20 @@ abstract class GeneratorCommand extends Command
|
|||
return $this->laravel->getNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model for the default guard's user provider.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function userProviderModel()
|
||||
{
|
||||
$guard = config('auth.defaults.guard');
|
||||
|
||||
$provider = config("auth.guards.{$guard}.provider");
|
||||
|
||||
return config("auth.providers.{$provider}.model");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command arguments.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ class Parser
|
|||
*
|
||||
* @param string $expression
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected static function name($expression)
|
||||
{
|
||||
|
|
@ -80,7 +82,7 @@ class Parser
|
|||
*/
|
||||
protected static function parseArgument($token)
|
||||
{
|
||||
list($token, $description) = static::extractDescription($token);
|
||||
[$token, $description] = static::extractDescription($token);
|
||||
|
||||
switch (true) {
|
||||
case Str::endsWith($token, '?*'):
|
||||
|
|
@ -89,6 +91,8 @@ class Parser
|
|||
return new InputArgument(trim($token, '*'), InputArgument::IS_ARRAY | InputArgument::REQUIRED, $description);
|
||||
case Str::endsWith($token, '?'):
|
||||
return new InputArgument(trim($token, '?'), InputArgument::OPTIONAL, $description);
|
||||
case preg_match('/(.+)\=\*(.+)/', $token, $matches):
|
||||
return new InputArgument($matches[1], InputArgument::IS_ARRAY, $description, preg_split('/,\s?/', $matches[2]));
|
||||
case preg_match('/(.+)\=(.+)/', $token, $matches):
|
||||
return new InputArgument($matches[1], InputArgument::OPTIONAL, $description, $matches[2]);
|
||||
default:
|
||||
|
|
@ -104,7 +108,7 @@ class Parser
|
|||
*/
|
||||
protected static function parseOption($token)
|
||||
{
|
||||
list($token, $description) = static::extractDescription($token);
|
||||
[$token, $description] = static::extractDescription($token);
|
||||
|
||||
$matches = preg_split('/\s*\|\s*/', $token, 2);
|
||||
|
||||
|
|
@ -120,6 +124,8 @@ class Parser
|
|||
return new InputOption(trim($token, '='), $shortcut, InputOption::VALUE_OPTIONAL, $description);
|
||||
case Str::endsWith($token, '=*'):
|
||||
return new InputOption(trim($token, '=*'), $shortcut, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, $description);
|
||||
case preg_match('/(.+)\=\*(.+)/', $token, $matches):
|
||||
return new InputOption($matches[1], $shortcut, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, $description, preg_split('/,\s?/', $matches[2]));
|
||||
case preg_match('/(.+)\=(.+)/', $token, $matches):
|
||||
return new InputOption($matches[1], $shortcut, InputOption::VALUE_OPTIONAL, $description, $matches[2]);
|
||||
default:
|
||||
|
|
@ -137,6 +143,6 @@ class Parser
|
|||
{
|
||||
$parts = preg_split('/\s+:\s+/', trim($token), 2);
|
||||
|
||||
return count($parts) === 2 ? $parts : [$token, null];
|
||||
return count($parts) === 2 ? $parts : [$token, ''];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Illuminate\Console\Scheduling;
|
||||
|
||||
use Illuminate\Contracts\Cache\Repository as Cache;
|
||||
|
||||
class CacheMutex implements Mutex
|
||||
{
|
||||
/**
|
||||
* The cache repository implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Cache\Repository
|
||||
*/
|
||||
public $cache;
|
||||
|
||||
/**
|
||||
* Create a new overlapping strategy.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Cache\Repository $cache
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Cache $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to obtain a mutex for the given event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return bool
|
||||
*/
|
||||
public function create(Event $event)
|
||||
{
|
||||
return $this->cache->add(
|
||||
$event->mutexName(), true, $event->expiresAt
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a mutex exists for the given event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(Event $event)
|
||||
{
|
||||
return $this->cache->has($event->mutexName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the mutex for the given event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return void
|
||||
*/
|
||||
public function forget(Event $event)
|
||||
{
|
||||
$this->cache->forget($event->mutexName());
|
||||
}
|
||||
}
|
||||
|
|
@ -25,14 +25,14 @@ class CallbackEvent extends Event
|
|||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Mutex $mutex
|
||||
* @param \Illuminate\Console\Scheduling\EventMutex $mutex
|
||||
* @param string $callback
|
||||
* @param array $parameters
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(Mutex $mutex, $callback, array $parameters = [])
|
||||
public function __construct(EventMutex $mutex, $callback, array $parameters = [])
|
||||
{
|
||||
if (! is_string($callback) && ! is_callable($callback)) {
|
||||
throw new InvalidArgumentException(
|
||||
|
|
@ -60,17 +60,25 @@ class CallbackEvent extends Event
|
|||
return;
|
||||
}
|
||||
|
||||
register_shutdown_function(function () {
|
||||
$this->removeMutex();
|
||||
$pid = getmypid();
|
||||
|
||||
register_shutdown_function(function () use ($pid) {
|
||||
if ($pid === getmypid()) {
|
||||
$this->removeMutex();
|
||||
}
|
||||
});
|
||||
|
||||
parent::callBeforeCallbacks($container);
|
||||
|
||||
try {
|
||||
$response = $container->call($this->callback, $this->parameters);
|
||||
$response = is_object($this->callback)
|
||||
? $container->call([$this->callback, '__invoke'], $this->parameters)
|
||||
: $container->call($this->callback, $this->parameters);
|
||||
} finally {
|
||||
$this->removeMutex();
|
||||
}
|
||||
|
||||
parent::callAfterCallbacks($container);
|
||||
parent::callAfterCallbacks($container);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
|
@ -82,7 +90,7 @@ class CallbackEvent extends Event
|
|||
*/
|
||||
protected function removeMutex()
|
||||
{
|
||||
if ($this->description) {
|
||||
if ($this->description && $this->withoutOverlapping) {
|
||||
$this->mutex->forget($this);
|
||||
}
|
||||
}
|
||||
|
|
@ -92,6 +100,8 @@ class CallbackEvent extends Event
|
|||
*
|
||||
* @param int $expiresAt
|
||||
* @return $this
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function withoutOverlapping($expiresAt = 1440)
|
||||
{
|
||||
|
|
@ -110,6 +120,26 @@ class CallbackEvent extends Event
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the event to only run on one server for each cron expression.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function onOneServer()
|
||||
{
|
||||
if (! isset($this->description)) {
|
||||
throw new LogicException(
|
||||
"A scheduled event name is required to only run on one server. Use the 'name' method before 'onOneServer'."
|
||||
);
|
||||
}
|
||||
|
||||
$this->onOneServer = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mutex name for the scheduled command.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace Illuminate\Console\Scheduling;
|
||||
|
||||
use Illuminate\Console\Application;
|
||||
use Symfony\Component\Process\ProcessUtils;
|
||||
use Illuminate\Support\ProcessUtils;
|
||||
|
||||
class CommandBuilder
|
||||
{
|
||||
|
|
@ -17,9 +17,9 @@ class CommandBuilder
|
|||
{
|
||||
if ($event->runInBackground) {
|
||||
return $this->buildBackgroundCommand($event);
|
||||
} else {
|
||||
return $this->buildForegroundCommand($event);
|
||||
}
|
||||
|
||||
return $this->buildForegroundCommand($event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
namespace Illuminate\Console\Scheduling;
|
||||
|
||||
use Closure;
|
||||
use Carbon\Carbon;
|
||||
use Cron\CronExpression;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Carbon;
|
||||
use GuzzleHttp\Client as HttpClient;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use Illuminate\Contracts\Mail\Mailer;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
|
|
@ -27,7 +29,7 @@ class Event
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
public $expression = '* * * * * *';
|
||||
public $expression = '* * * * *';
|
||||
|
||||
/**
|
||||
* The timezone the date should be evaluated on.
|
||||
|
|
@ -64,6 +66,13 @@ class Event
|
|||
*/
|
||||
public $withoutOverlapping = false;
|
||||
|
||||
/**
|
||||
* Indicates if the command should only be allowed to run on one server for each cron expression.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $onOneServer = false;
|
||||
|
||||
/**
|
||||
* The amount of time the mutex should be valid.
|
||||
*
|
||||
|
|
@ -128,23 +137,33 @@ class Event
|
|||
public $description;
|
||||
|
||||
/**
|
||||
* The mutex implementation.
|
||||
* The event mutex implementation.
|
||||
*
|
||||
* @var \Illuminate\Console\Scheduling\Mutex
|
||||
* @var \Illuminate\Console\Scheduling\EventMutex
|
||||
*/
|
||||
public $mutex;
|
||||
|
||||
/**
|
||||
* The exit status code of the command.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
public $exitCode;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Mutex $mutex
|
||||
* @param \Illuminate\Console\Scheduling\EventMutex $mutex
|
||||
* @param string $command
|
||||
* @param \DateTimeZone|string|null $timezone
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Mutex $mutex, $command)
|
||||
public function __construct(EventMutex $mutex, $command, $timezone = null)
|
||||
{
|
||||
$this->mutex = $mutex;
|
||||
$this->command = $command;
|
||||
$this->timezone = $timezone;
|
||||
|
||||
$this->output = $this->getDefaultOutput();
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +174,7 @@ class Event
|
|||
*/
|
||||
public function getDefaultOutput()
|
||||
{
|
||||
return (DIRECTORY_SEPARATOR == '\\') ? 'NUL' : '/dev/null';
|
||||
return (DIRECTORY_SEPARATOR === '\\') ? 'NUL' : '/dev/null';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -196,9 +215,7 @@ class Event
|
|||
{
|
||||
$this->callBeforeCallbacks($container);
|
||||
|
||||
(new Process(
|
||||
$this->buildCommand(), base_path(), null, null, null
|
||||
))->run();
|
||||
$this->exitCode = Process::fromShellCommandline($this->buildCommand(), base_path(), null, null, null)->run();
|
||||
|
||||
$this->callAfterCallbacks($container);
|
||||
}
|
||||
|
|
@ -213,9 +230,7 @@ class Event
|
|||
{
|
||||
$this->callBeforeCallbacks($container);
|
||||
|
||||
(new Process(
|
||||
$this->buildCommand(), base_path(), null, null, null
|
||||
))->run();
|
||||
Process::fromShellCommandline($this->buildCommand(), base_path(), null, null, null)->run();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -330,6 +345,18 @@ class Event
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the output is stored on disk in a log file.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function storeOutput()
|
||||
{
|
||||
$this->ensureOutputIsBeingCaptured();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the output of the command to a given location.
|
||||
*
|
||||
|
|
@ -368,9 +395,9 @@ class Event
|
|||
*/
|
||||
public function emailOutputTo($addresses, $onlyIfOutputExists = false)
|
||||
{
|
||||
$this->ensureOutputIsBeingCapturedForEmail();
|
||||
$this->ensureOutputIsBeingCaptured();
|
||||
|
||||
$addresses = is_array($addresses) ? $addresses : [$addresses];
|
||||
$addresses = Arr::wrap($addresses);
|
||||
|
||||
return $this->then(function (Mailer $mailer) use ($addresses, $onlyIfOutputExists) {
|
||||
$this->emailOutput($mailer, $addresses, $onlyIfOutputExists);
|
||||
|
|
@ -391,11 +418,28 @@ class Event
|
|||
}
|
||||
|
||||
/**
|
||||
* Ensure that output is being captured for email.
|
||||
* E-mail the results of the scheduled operation if it fails.
|
||||
*
|
||||
* @param array|mixed $addresses
|
||||
* @return $this
|
||||
*/
|
||||
public function emailOutputOnFailure($addresses)
|
||||
{
|
||||
$this->ensureOutputIsBeingCaptured();
|
||||
|
||||
$addresses = Arr::wrap($addresses);
|
||||
|
||||
return $this->onFailure(function (Mailer $mailer) use ($addresses) {
|
||||
$this->emailOutput($mailer, $addresses, false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the command output is being captured.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function ensureOutputIsBeingCapturedForEmail()
|
||||
protected function ensureOutputIsBeingCaptured()
|
||||
{
|
||||
if (is_null($this->output) || $this->output == $this->getDefaultOutput()) {
|
||||
$this->sendOutputTo(storage_path('logs/schedule-'.sha1($this->mutexName()).'.log'));
|
||||
|
|
@ -434,7 +478,7 @@ class Event
|
|||
return $this->description;
|
||||
}
|
||||
|
||||
return 'Scheduled Job Output';
|
||||
return "Scheduled Job Output For [{$this->command}]";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -450,6 +494,18 @@ class Event
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to ping a given URL before the job runs if the given condition is true.
|
||||
*
|
||||
* @param bool $value
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function pingBeforeIf($value, $url)
|
||||
{
|
||||
return $value ? $this->pingBefore($url) : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to ping a given URL after the job runs.
|
||||
*
|
||||
|
|
@ -463,6 +519,44 @@ class Event
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to ping a given URL after the job runs if the given condition is true.
|
||||
*
|
||||
* @param bool $value
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function thenPingIf($value, $url)
|
||||
{
|
||||
return $value ? $this->thenPing($url) : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to ping a given URL if the operation succeeds.
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function pingOnSuccess($url)
|
||||
{
|
||||
return $this->onSuccess(function () use ($url) {
|
||||
(new HttpClient)->get($url);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to ping a given URL if the operation fails.
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function pingOnFailure($url)
|
||||
{
|
||||
return $this->onFailure(function () use ($url) {
|
||||
(new HttpClient)->get($url);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* State that the command should run in background.
|
||||
*
|
||||
|
|
@ -533,14 +627,13 @@ class Event
|
|||
}
|
||||
|
||||
/**
|
||||
* Register a callback to further filter the schedule.
|
||||
* Allow the event to only run on one server for each cron expression.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function when(Closure $callback)
|
||||
public function onOneServer()
|
||||
{
|
||||
$this->filters[] = $callback;
|
||||
$this->onOneServer = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -548,12 +641,29 @@ class Event
|
|||
/**
|
||||
* Register a callback to further filter the schedule.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param \Closure|bool $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function skip(Closure $callback)
|
||||
public function when($callback)
|
||||
{
|
||||
$this->rejects[] = $callback;
|
||||
$this->filters[] = is_callable($callback) ? $callback : function () use ($callback) {
|
||||
return $callback;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to further filter the schedule.
|
||||
*
|
||||
* @param \Closure|bool $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function skip($callback)
|
||||
{
|
||||
$this->rejects[] = is_callable($callback) ? $callback : function () use ($callback) {
|
||||
return $callback;
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -595,6 +705,36 @@ class Event
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be called if the operation succeeds.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function onSuccess(Closure $callback)
|
||||
{
|
||||
return $this->then(function (Container $container) use ($callback) {
|
||||
if (0 === $this->exitCode) {
|
||||
$container->call($callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be called if the operation fails.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function onFailure(Closure $callback)
|
||||
{
|
||||
return $this->then(function (Container $container) use ($callback) {
|
||||
if (0 !== $this->exitCode) {
|
||||
$container->call($callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the human-friendly description of the event.
|
||||
*
|
||||
|
|
@ -636,16 +776,16 @@ class Event
|
|||
/**
|
||||
* Determine the next due date for an event.
|
||||
*
|
||||
* @param \DateTime|string $currentTime
|
||||
* @param \DateTimeInterface|string $currentTime
|
||||
* @param int $nth
|
||||
* @param bool $allowCurrentDate
|
||||
* @return \Carbon\Carbon
|
||||
* @return \Illuminate\Support\Carbon
|
||||
*/
|
||||
public function nextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
|
||||
{
|
||||
return Carbon::instance($nextDue = CronExpression::factory(
|
||||
return Date::instance(CronExpression::factory(
|
||||
$this->getExpression()
|
||||
)->getNextRunDate($currentTime, $nth, $allowCurrentDate));
|
||||
)->getNextRunDate($currentTime, $nth, $allowCurrentDate, $this->timezone));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -659,12 +799,12 @@ class Event
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the mutex implementation to be used.
|
||||
* Set the event mutex implementation to be used.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Mutex $mutex
|
||||
* @param \Illuminate\Console\Scheduling\EventMutex $mutex
|
||||
* @return $this
|
||||
*/
|
||||
public function preventOverlapsUsing(Mutex $mutex)
|
||||
public function preventOverlapsUsing(EventMutex $mutex)
|
||||
{
|
||||
$this->mutex = $mutex;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Illuminate\Console\Scheduling;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
trait ManagesFrequencies
|
||||
{
|
||||
|
|
@ -61,6 +61,56 @@ trait ManagesFrequencies
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every minute.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyMinute()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every five minutes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyFiveMinutes()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '*/5');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every ten minutes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyTenMinutes()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '*/10');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every fifteen minutes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyFifteenMinutes()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '*/15');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every thirty minutes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyThirtyMinutes()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '0,30');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run hourly.
|
||||
*
|
||||
|
|
@ -74,11 +124,13 @@ trait ManagesFrequencies
|
|||
/**
|
||||
* Schedule the event to run hourly at a given offset in the hour.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param array|int $offset
|
||||
* @return $this
|
||||
*/
|
||||
public function hourlyAt($offset)
|
||||
{
|
||||
$offset = is_array($offset) ? implode(',', $offset) : $offset;
|
||||
|
||||
return $this->spliceIntoPosition(1, $offset);
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +167,7 @@ trait ManagesFrequencies
|
|||
$segments = explode(':', $time);
|
||||
|
||||
return $this->spliceIntoPosition(2, (int) $segments[0])
|
||||
->spliceIntoPosition(1, count($segments) == 2 ? (int) $segments[1] : '0');
|
||||
->spliceIntoPosition(1, count($segments) === 2 ? (int) $segments[1] : '0');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -301,7 +353,7 @@ trait ManagesFrequencies
|
|||
return $this->spliceIntoPosition(1, 0)
|
||||
->spliceIntoPosition(2, 0)
|
||||
->spliceIntoPosition(3, 1)
|
||||
->spliceIntoPosition(4, '*/3');
|
||||
->spliceIntoPosition(4, '1-12/3');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -317,46 +369,6 @@ trait ManagesFrequencies
|
|||
->spliceIntoPosition(4, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every minute.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyMinute()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every five minutes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyFiveMinutes()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '*/5');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every ten minutes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyTenMinutes()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '*/10');
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule the event to run every thirty minutes.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function everyThirtyMinutes()
|
||||
{
|
||||
return $this->spliceIntoPosition(1, '0,30');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the days of the week the command should run on.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Illuminate\Console\Scheduling;
|
||||
|
||||
interface Mutex
|
||||
{
|
||||
/**
|
||||
* Attempt to obtain a mutex for the given event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return bool
|
||||
*/
|
||||
public function create(Event $event);
|
||||
|
||||
/**
|
||||
* Determine if a mutex exists for the given event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return bool
|
||||
*/
|
||||
public function exists(Event $event);
|
||||
|
||||
/**
|
||||
* Clear the mutex for the given event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return void
|
||||
*/
|
||||
public function forget(Event $event);
|
||||
}
|
||||
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
namespace Illuminate\Console\Scheduling;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Console\Application;
|
||||
use Illuminate\Container\Container;
|
||||
use Symfony\Component\Process\ProcessUtils;
|
||||
use Illuminate\Support\ProcessUtils;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class Schedule
|
||||
{
|
||||
|
|
@ -16,37 +18,58 @@ class Schedule
|
|||
protected $events = [];
|
||||
|
||||
/**
|
||||
* The mutex implementation.
|
||||
* The event mutex implementation.
|
||||
*
|
||||
* @var \Illuminate\Console\Scheduling\Mutex
|
||||
* @var \Illuminate\Console\Scheduling\EventMutex
|
||||
*/
|
||||
protected $mutex;
|
||||
protected $eventMutex;
|
||||
|
||||
/**
|
||||
* The scheduling mutex implementation.
|
||||
*
|
||||
* @var \Illuminate\Console\Scheduling\SchedulingMutex
|
||||
*/
|
||||
protected $schedulingMutex;
|
||||
|
||||
/**
|
||||
* The timezone the date should be evaluated on.
|
||||
*
|
||||
* @var \DateTimeZone|string
|
||||
*/
|
||||
protected $timezone;
|
||||
|
||||
/**
|
||||
* Create a new schedule instance.
|
||||
*
|
||||
* @param \DateTimeZone|string|null $timezone
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct($timezone = null)
|
||||
{
|
||||
$this->timezone = $timezone;
|
||||
|
||||
$container = Container::getInstance();
|
||||
|
||||
$this->mutex = $container->bound(Mutex::class)
|
||||
? $container->make(Mutex::class)
|
||||
: $container->make(CacheMutex::class);
|
||||
$this->eventMutex = $container->bound(EventMutex::class)
|
||||
? $container->make(EventMutex::class)
|
||||
: $container->make(CacheEventMutex::class);
|
||||
|
||||
$this->schedulingMutex = $container->bound(SchedulingMutex::class)
|
||||
? $container->make(SchedulingMutex::class)
|
||||
: $container->make(CacheSchedulingMutex::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new callback event to the schedule.
|
||||
*
|
||||
* @param string|callable $callback
|
||||
* @param array $parameters
|
||||
* @param array $parameters
|
||||
* @return \Illuminate\Console\Scheduling\CallbackEvent
|
||||
*/
|
||||
public function call($callback, array $parameters = [])
|
||||
{
|
||||
$this->events[] = $event = new CallbackEvent(
|
||||
$this->mutex, $callback, $parameters
|
||||
$this->eventMutex, $callback, $parameters
|
||||
);
|
||||
|
||||
return $event;
|
||||
|
|
@ -74,12 +97,22 @@ class Schedule
|
|||
* Add a new job callback event to the schedule.
|
||||
*
|
||||
* @param object|string $job
|
||||
* @param string|null $queue
|
||||
* @param string|null $connection
|
||||
* @return \Illuminate\Console\Scheduling\CallbackEvent
|
||||
*/
|
||||
public function job($job)
|
||||
public function job($job, $queue = null, $connection = null)
|
||||
{
|
||||
return $this->call(function () use ($job) {
|
||||
dispatch(is_string($job) ? resolve($job) : $job);
|
||||
return $this->call(function () use ($job, $queue, $connection) {
|
||||
$job = is_string($job) ? resolve($job) : $job;
|
||||
|
||||
if ($job instanceof ShouldQueue) {
|
||||
dispatch($job)
|
||||
->onConnection($connection ?? $job->connection)
|
||||
->onQueue($queue ?? $job->queue);
|
||||
} else {
|
||||
dispatch_now($job);
|
||||
}
|
||||
})->name(is_string($job) ? $job : get_class($job));
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +129,7 @@ class Schedule
|
|||
$command .= ' '.$this->compileParameters($parameters);
|
||||
}
|
||||
|
||||
$this->events[] = $event = new Event($this->mutex, $command);
|
||||
$this->events[] = $event = new Event($this->eventMutex, $command, $this->timezone);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
|
@ -122,11 +155,23 @@ class Schedule
|
|||
})->implode(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the server is allowed to run this event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @param \DateTimeInterface $time
|
||||
* @return bool
|
||||
*/
|
||||
public function serverShouldRun(Event $event, DateTimeInterface $time)
|
||||
{
|
||||
return $this->schedulingMutex->create($event, $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the events on the schedule that are due.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @return array
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function dueEvents($app)
|
||||
{
|
||||
|
|
@ -142,4 +187,23 @@ class Schedule
|
|||
{
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the cache store that should be used to store mutexes.
|
||||
*
|
||||
* @param string $store
|
||||
* @return $this
|
||||
*/
|
||||
public function useCache($store)
|
||||
{
|
||||
if ($this->eventMutex instanceof CacheEventMutex) {
|
||||
$this->eventMutex->useStore($store);
|
||||
}
|
||||
|
||||
if ($this->schedulingMutex instanceof CacheSchedulingMutex) {
|
||||
$this->schedulingMutex->useStore($store);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class ScheduleFinishCommand extends Command
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
collect($this->schedule->events())->filter(function ($value) {
|
||||
return $value->mutexName() == $this->argument('id');
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Illuminate\Console\Scheduling;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
|
||||
class ScheduleRunCommand extends Command
|
||||
{
|
||||
|
|
@ -27,6 +28,20 @@ class ScheduleRunCommand extends Command
|
|||
*/
|
||||
protected $schedule;
|
||||
|
||||
/**
|
||||
* The 24 hour timestamp this scheduler command started running.
|
||||
*
|
||||
* @var \Illuminate\Support\Carbon;
|
||||
*/
|
||||
protected $startedAt;
|
||||
|
||||
/**
|
||||
* Check if any events ran.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $eventsRan = false;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
|
|
@ -37,6 +52,8 @@ class ScheduleRunCommand extends Command
|
|||
{
|
||||
$this->schedule = $schedule;
|
||||
|
||||
$this->startedAt = Date::now();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
|
@ -45,24 +62,54 @@ class ScheduleRunCommand extends Command
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
$eventsRan = false;
|
||||
|
||||
foreach ($this->schedule->dueEvents($this->laravel) as $event) {
|
||||
if (! $event->filtersPass($this->laravel)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->line('<info>Running scheduled command:</info> '.$event->getSummaryForDisplay());
|
||||
if ($event->onOneServer) {
|
||||
$this->runSingleServerEvent($event);
|
||||
} else {
|
||||
$this->runEvent($event);
|
||||
}
|
||||
|
||||
$event->run($this->laravel);
|
||||
|
||||
$eventsRan = true;
|
||||
$this->eventsRan = true;
|
||||
}
|
||||
|
||||
if (! $eventsRan) {
|
||||
if (! $this->eventsRan) {
|
||||
$this->info('No scheduled commands are ready to run.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given single server event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return void
|
||||
*/
|
||||
protected function runSingleServerEvent($event)
|
||||
{
|
||||
if ($this->schedule->serverShouldRun($event, $this->startedAt)) {
|
||||
$this->runEvent($event);
|
||||
} else {
|
||||
$this->line('<info>Skipping command (has already run on another server):</info> '.$event->getSummaryForDisplay());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given event.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Event $event
|
||||
* @return void
|
||||
*/
|
||||
protected function runEvent($event)
|
||||
{
|
||||
$this->line('<info>Running scheduled command:</info> '.$event->getSummaryForDisplay());
|
||||
|
||||
$event->run($this->laravel);
|
||||
|
||||
$this->eventsRan = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/contracts": "5.4.*",
|
||||
"illuminate/support": "5.4.*",
|
||||
"nesbot/carbon": "~1.20",
|
||||
"symfony/console": "~3.2"
|
||||
"php": "^7.1.3",
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/support": "5.8.*",
|
||||
"symfony/console": "^4.2",
|
||||
"symfony/process": "^4.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -27,13 +27,13 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"guzzlehttp/guzzle": "Required to use the ping methods on schedules (~6.0).",
|
||||
"mtdowling/cron-expression": "Required to use scheduling component (~1.0).",
|
||||
"symfony/process": "Required to use scheduling component (~3.2)."
|
||||
"dragonmantank/cron-expression": "Required to use scheduling component (^2.0).",
|
||||
"guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.0).",
|
||||
"illuminate/filesystem": "Required to use the generator command (5.8.*)"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ class BoundMethod
|
|||
* @param array $parameters
|
||||
* @param string|null $defaultMethod
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function call($container, $callback, array $parameters = [], $defaultMethod = null)
|
||||
{
|
||||
|
|
@ -49,7 +52,7 @@ class BoundMethod
|
|||
// We will assume an @ sign is used to delimit the class name from the method
|
||||
// name. We will split on this @ sign and then build a callable array that
|
||||
// we can pass right back into the "call" method for dependency binding.
|
||||
$method = count($segments) == 2
|
||||
$method = count($segments) === 2
|
||||
? $segments[1] : $defaultMethod;
|
||||
|
||||
if (is_null($method)) {
|
||||
|
|
@ -103,10 +106,12 @@ class BoundMethod
|
|||
/**
|
||||
* Get all dependencies for a given method.
|
||||
*
|
||||
* @param \Illuminate\Container\Container
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param callable|string $callback
|
||||
* @param array $parameters
|
||||
* @return array
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected static function getMethodDependencies($container, $callback, array $parameters = [])
|
||||
{
|
||||
|
|
@ -122,8 +127,10 @@ class BoundMethod
|
|||
/**
|
||||
* Get the proper reflection instance for the given callback.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @param callable|string $callback
|
||||
* @return \ReflectionFunctionAbstract
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected static function getCallReflector($callback)
|
||||
{
|
||||
|
|
@ -143,7 +150,7 @@ class BoundMethod
|
|||
* @param \ReflectionParameter $parameter
|
||||
* @param array $parameters
|
||||
* @param array $dependencies
|
||||
* @return mixed
|
||||
* @return void
|
||||
*/
|
||||
protected static function addDependencyForCallParameter($container, $parameter,
|
||||
array &$parameters, &$dependencies)
|
||||
|
|
@ -152,6 +159,10 @@ class BoundMethod
|
|||
$dependencies[] = $parameters[$parameter->name];
|
||||
|
||||
unset($parameters[$parameter->name]);
|
||||
} elseif ($parameter->getClass() && array_key_exists($parameter->getClass()->name, $parameters)) {
|
||||
$dependencies[] = $parameters[$parameter->getClass()->name];
|
||||
|
||||
unset($parameters[$parameter->getClass()->name]);
|
||||
} elseif ($parameter->getClass()) {
|
||||
$dependencies[] = $container->make($parameter->getClass()->name);
|
||||
} elseif ($parameter->isDefaultValueAvailable()) {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
namespace Illuminate\Container;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use ArrayAccess;
|
||||
use LogicException;
|
||||
use ReflectionClass;
|
||||
use ReflectionParameter;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
use Illuminate\Contracts\Container\Container as ContainerContract;
|
||||
|
||||
|
|
@ -22,124 +24,130 @@ class Container implements ArrayAccess, ContainerContract
|
|||
/**
|
||||
* An array of the types that have been resolved.
|
||||
*
|
||||
* @var array
|
||||
* @var bool[]
|
||||
*/
|
||||
protected $resolved = [];
|
||||
|
||||
/**
|
||||
* The container's bindings.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $bindings = [];
|
||||
|
||||
/**
|
||||
* The container's method bindings.
|
||||
*
|
||||
* @var array
|
||||
* @var \Closure[]
|
||||
*/
|
||||
protected $methodBindings = [];
|
||||
|
||||
/**
|
||||
* The container's shared instances.
|
||||
*
|
||||
* @var array
|
||||
* @var object[]
|
||||
*/
|
||||
protected $instances = [];
|
||||
|
||||
/**
|
||||
* The registered type aliases.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* The registered aliases keyed by the abstract name.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $abstractAliases = [];
|
||||
|
||||
/**
|
||||
* The extension closures for services.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $extenders = [];
|
||||
|
||||
/**
|
||||
* All of the registered tags.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $tags = [];
|
||||
|
||||
/**
|
||||
* The stack of concretions currently being built.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $buildStack = [];
|
||||
|
||||
/**
|
||||
* The parameter override stack.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $with = [];
|
||||
|
||||
/**
|
||||
* The contextual binding map.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
public $contextual = [];
|
||||
|
||||
/**
|
||||
* All of the registered rebound callbacks.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $reboundCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the global resolving callbacks.
|
||||
*
|
||||
* @var array
|
||||
* @var \Closure[]
|
||||
*/
|
||||
protected $globalResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the global after resolving callbacks.
|
||||
*
|
||||
* @var array
|
||||
* @var \Closure[]
|
||||
*/
|
||||
protected $globalAfterResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the resolving callbacks by class type.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $resolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the after resolving callbacks by class type.
|
||||
*
|
||||
* @var array
|
||||
* @var array[]
|
||||
*/
|
||||
protected $afterResolvingCallbacks = [];
|
||||
|
||||
/**
|
||||
* Define a contextual binding.
|
||||
*
|
||||
* @param string $concrete
|
||||
* @param array|string $concrete
|
||||
* @return \Illuminate\Contracts\Container\ContextualBindingBuilder
|
||||
*/
|
||||
public function when($concrete)
|
||||
{
|
||||
return new ContextualBindingBuilder($this, $this->getAlias($concrete));
|
||||
$aliases = [];
|
||||
|
||||
foreach (Arr::wrap($concrete) as $c) {
|
||||
$aliases[] = $this->getAlias($c);
|
||||
}
|
||||
|
||||
return new ContextualBindingBuilder($this, $aliases);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -155,6 +163,14 @@ class Container implements ArrayAccess, ContainerContract
|
|||
$this->isAlias($abstract);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($id)
|
||||
{
|
||||
return $this->bound($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given abstract type has been resolved.
|
||||
*
|
||||
|
|
@ -180,7 +196,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
public function isShared($abstract)
|
||||
{
|
||||
return isset($this->instances[$abstract]) ||
|
||||
(isset($this->bindings[$abstract]['shared']) &&
|
||||
(isset($this->bindings[$abstract]['shared']) &&
|
||||
$this->bindings[$abstract]['shared'] === true);
|
||||
}
|
||||
|
||||
|
|
@ -198,18 +214,18 @@ class Container implements ArrayAccess, ContainerContract
|
|||
/**
|
||||
* Register a binding with the container.
|
||||
*
|
||||
* @param string|array $abstract
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @param bool $shared
|
||||
* @return void
|
||||
*/
|
||||
public function bind($abstract, $concrete = null, $shared = false)
|
||||
{
|
||||
$this->dropStaleInstances($abstract);
|
||||
|
||||
// If no concrete type was given, we will simply set the concrete type to the
|
||||
// abstract type. After that, the concrete type to be registered as shared
|
||||
// without being forced to state their classes in both of the parameters.
|
||||
$this->dropStaleInstances($abstract);
|
||||
|
||||
if (is_null($concrete)) {
|
||||
$concrete = $abstract;
|
||||
}
|
||||
|
|
@ -245,7 +261,9 @@ class Container implements ArrayAccess, ContainerContract
|
|||
return $container->build($concrete);
|
||||
}
|
||||
|
||||
return $container->makeWith($concrete, $parameters);
|
||||
return $container->resolve(
|
||||
$concrete, $parameters, $raiseEvents = false
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -263,13 +281,28 @@ class Container implements ArrayAccess, ContainerContract
|
|||
/**
|
||||
* Bind a callback to resolve with Container::call.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array|string $method
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function bindMethod($method, $callback)
|
||||
{
|
||||
$this->methodBindings[$method] = $callback;
|
||||
$this->methodBindings[$this->parseBindMethod($method)] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the method to be bound in class@method format.
|
||||
*
|
||||
* @param array|string $method
|
||||
* @return string
|
||||
*/
|
||||
protected function parseBindMethod($method)
|
||||
{
|
||||
if (is_array($method)) {
|
||||
return $method[0].'@'.$method[1];
|
||||
}
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -315,7 +348,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
/**
|
||||
* Register a shared binding in the container.
|
||||
*
|
||||
* @param string|array $abstract
|
||||
* @param string $abstract
|
||||
* @param \Closure|string|null $concrete
|
||||
* @return void
|
||||
*/
|
||||
|
|
@ -355,7 +388,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
*
|
||||
* @param string $abstract
|
||||
* @param mixed $instance
|
||||
* @return void
|
||||
* @return mixed
|
||||
*/
|
||||
public function instance($abstract, $instance)
|
||||
{
|
||||
|
|
@ -373,6 +406,8 @@ class Container implements ArrayAccess, ContainerContract
|
|||
if ($isBound) {
|
||||
$this->rebound($abstract);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -422,19 +457,19 @@ class Container implements ArrayAccess, ContainerContract
|
|||
* Resolve all of the bindings for a given tag.
|
||||
*
|
||||
* @param string $tag
|
||||
* @return array
|
||||
* @return iterable
|
||||
*/
|
||||
public function tagged($tag)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
if (isset($this->tags[$tag])) {
|
||||
foreach ($this->tags[$tag] as $abstract) {
|
||||
$results[] = $this->make($abstract);
|
||||
}
|
||||
if (! isset($this->tags[$tag])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $results;
|
||||
return new RewindableGenerator(function () use ($tag) {
|
||||
foreach ($this->tags[$tag] as $abstract) {
|
||||
yield $this->make($abstract);
|
||||
}
|
||||
}, count($this->tags[$tag]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -443,9 +478,15 @@ class Container implements ArrayAccess, ContainerContract
|
|||
* @param string $abstract
|
||||
* @param string $alias
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function alias($abstract, $alias)
|
||||
{
|
||||
if ($alias === $abstract) {
|
||||
throw new LogicException("[{$abstract}] is aliased to itself.");
|
||||
}
|
||||
|
||||
$this->aliases[$alias] = $abstract;
|
||||
|
||||
$this->abstractAliases[$abstract][] = $alias;
|
||||
|
|
@ -505,11 +546,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
*/
|
||||
protected function getReboundCallbacks($abstract)
|
||||
{
|
||||
if (isset($this->reboundCallbacks[$abstract])) {
|
||||
return $this->reboundCallbacks[$abstract];
|
||||
}
|
||||
|
||||
return [];
|
||||
return $this->reboundCallbacks[$abstract] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -553,26 +590,45 @@ class Container implements ArrayAccess, ContainerContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Resolve the given type with the given parameter overrides.
|
||||
* An alias function name for make().
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function makeWith($abstract, array $parameters)
|
||||
public function makeWith($abstract, array $parameters = [])
|
||||
{
|
||||
return $this->make($abstract, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given type from the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function make($abstract, array $parameters = [])
|
||||
{
|
||||
return $this->resolve($abstract, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given type from the container.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return mixed
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function make($abstract)
|
||||
public function get($id)
|
||||
{
|
||||
return $this->resolve($abstract);
|
||||
try {
|
||||
return $this->resolve($id);
|
||||
} catch (Exception $e) {
|
||||
if ($this->has($id)) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
throw new EntryNotFoundException($id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -580,9 +636,12 @@ class Container implements ArrayAccess, ContainerContract
|
|||
*
|
||||
* @param string $abstract
|
||||
* @param array $parameters
|
||||
* @param bool $raiseEvents
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function resolve($abstract, $parameters = [])
|
||||
protected function resolve($abstract, $parameters = [], $raiseEvents = true)
|
||||
{
|
||||
$abstract = $this->getAlias($abstract);
|
||||
|
||||
|
|
@ -624,7 +683,9 @@ class Container implements ArrayAccess, ContainerContract
|
|||
$this->instances[$abstract] = $object;
|
||||
}
|
||||
|
||||
$this->fireResolvingCallbacks($abstract, $object);
|
||||
if ($raiseEvents) {
|
||||
$this->fireResolvingCallbacks($abstract, $object);
|
||||
}
|
||||
|
||||
// Before returning, we will also set the resolved flag to "true" and pop off
|
||||
// the parameter overrides for this build. After those two things are done
|
||||
|
|
@ -662,7 +723,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
* Get the contextual concrete binding for the given abstract.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return string|null
|
||||
* @return \Closure|string|null
|
||||
*/
|
||||
protected function getContextualConcrete($abstract)
|
||||
{
|
||||
|
|
@ -688,13 +749,11 @@ class Container implements ArrayAccess, ContainerContract
|
|||
* Find the concrete binding for the given abstract in the contextual binding array.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @return string|null
|
||||
* @return \Closure|string|null
|
||||
*/
|
||||
protected function findInContextualBindings($abstract)
|
||||
{
|
||||
if (isset($this->contextual[end($this->buildStack)][$abstract])) {
|
||||
return $this->contextual[end($this->buildStack)][$abstract];
|
||||
}
|
||||
return $this->contextual[end($this->buildStack)][$abstract] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -729,7 +788,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
$reflector = new ReflectionClass($concrete);
|
||||
|
||||
// If the type is not instantiable, the developer is attempting to resolve
|
||||
// an abstract type such as an Interface of Abstract Class and there is
|
||||
// an abstract type such as an Interface or Abstract Class and there is
|
||||
// no binding registered for the abstractions so we need to bail out.
|
||||
if (! $reflector->isInstantiable()) {
|
||||
return $this->notInstantiable($concrete);
|
||||
|
|
@ -753,9 +812,13 @@ class Container implements ArrayAccess, ContainerContract
|
|||
// Once we have all the constructor's parameters we can create each of the
|
||||
// dependency instances and then use the reflection instances to make a
|
||||
// new instance of this class, injecting the created dependencies in.
|
||||
$instances = $this->resolveDependencies(
|
||||
$dependencies
|
||||
);
|
||||
try {
|
||||
$instances = $this->resolveDependencies($dependencies);
|
||||
} catch (BindingResolutionException $e) {
|
||||
array_pop($this->buildStack);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
array_pop($this->buildStack);
|
||||
|
||||
|
|
@ -767,6 +830,8 @@ class Container implements ArrayAccess, ContainerContract
|
|||
*
|
||||
* @param array $dependencies
|
||||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function resolveDependencies(array $dependencies)
|
||||
{
|
||||
|
|
@ -785,7 +850,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
// If the class is null, it means the dependency is a string or some other
|
||||
// primitive type which we can not resolve since it is not a class and
|
||||
// we will just bomb out with an error since we have no-where to go.
|
||||
$results[] = is_null($class = $dependency->getClass())
|
||||
$results[] = is_null($dependency->getClass())
|
||||
? $this->resolvePrimitive($dependency)
|
||||
: $this->resolveClass($dependency);
|
||||
}
|
||||
|
|
@ -794,7 +859,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Determine if the given dependency has a parameter override from makeWith.
|
||||
* Determine if the given dependency has a parameter override.
|
||||
*
|
||||
* @param \ReflectionParameter $dependency
|
||||
* @return bool
|
||||
|
|
@ -913,7 +978,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
/**
|
||||
* Register a new resolving callback.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|string $abstract
|
||||
* @param \Closure|null $callback
|
||||
* @return void
|
||||
*/
|
||||
|
|
@ -933,8 +998,8 @@ class Container implements ArrayAccess, ContainerContract
|
|||
/**
|
||||
* Register a new after resolving callback for all types.
|
||||
*
|
||||
* @param string $abstract
|
||||
* @param \Closure|null $callback
|
||||
* @param \Closure|string $abstract
|
||||
* @param \Closure|null $callback
|
||||
* @return void
|
||||
*/
|
||||
public function afterResolving($abstract, Closure $callback = null)
|
||||
|
|
@ -1035,8 +1100,6 @@ class Container implements ArrayAccess, ContainerContract
|
|||
*
|
||||
* @param string $abstract
|
||||
* @return string
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function getAlias($abstract)
|
||||
{
|
||||
|
|
@ -1044,10 +1107,6 @@ class Container implements ArrayAccess, ContainerContract
|
|||
return $abstract;
|
||||
}
|
||||
|
||||
if ($this->aliases[$abstract] === $abstract) {
|
||||
throw new LogicException("[{$abstract}] is aliased to itself.");
|
||||
}
|
||||
|
||||
return $this->getAlias($this->aliases[$abstract]);
|
||||
}
|
||||
|
||||
|
|
@ -1061,11 +1120,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
{
|
||||
$abstract = $this->getAlias($abstract);
|
||||
|
||||
if (isset($this->extenders[$abstract])) {
|
||||
return $this->extenders[$abstract];
|
||||
}
|
||||
|
||||
return [];
|
||||
return $this->extenders[$abstract] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1126,7 +1181,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the globally available instance of the container.
|
||||
* Get the globally available instance of the container.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
|
|
@ -1143,7 +1198,7 @@ class Container implements ArrayAccess, ContainerContract
|
|||
* Set the shared instance of the container.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container|null $container
|
||||
* @return static
|
||||
* @return \Illuminate\Contracts\Container\Container|static
|
||||
*/
|
||||
public static function setInstance(ContainerContract $container = null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Illuminate\Container;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Container\ContextualBindingBuilder as ContextualBindingBuilderContract;
|
||||
|
||||
class ContextualBindingBuilder implements ContextualBindingBuilderContract
|
||||
|
|
@ -9,14 +11,14 @@ class ContextualBindingBuilder implements ContextualBindingBuilderContract
|
|||
/**
|
||||
* The underlying container instance.
|
||||
*
|
||||
* @var \Illuminate\Container\Container
|
||||
* @var \Illuminate\Contracts\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The concrete instance.
|
||||
*
|
||||
* @var string
|
||||
* @var string|array
|
||||
*/
|
||||
protected $concrete;
|
||||
|
||||
|
|
@ -30,8 +32,8 @@ class ContextualBindingBuilder implements ContextualBindingBuilderContract
|
|||
/**
|
||||
* Create a new contextual binding builder.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param string $concrete
|
||||
* @param \Illuminate\Contracts\Container\Container $container
|
||||
* @param string|array $concrete
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container, $concrete)
|
||||
|
|
@ -61,8 +63,8 @@ class ContextualBindingBuilder implements ContextualBindingBuilderContract
|
|||
*/
|
||||
public function give($implementation)
|
||||
{
|
||||
$this->container->addContextualBinding(
|
||||
$this->concrete, $this->needs, $implementation
|
||||
);
|
||||
foreach (Arr::wrap($this->concrete) as $concrete) {
|
||||
$this->container->addContextualBinding($concrete, $this->needs, $implementation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/contracts": "5.4.*"
|
||||
"php": "^7.1.3",
|
||||
"illuminate/contracts": "5.8.*",
|
||||
"illuminate/support": "5.8.*",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
|
@ -24,7 +26,7 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "5.8-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
|
|
|
|||
|
|
@ -65,13 +65,22 @@ interface Gate
|
|||
public function denies($ability, $arguments = []);
|
||||
|
||||
/**
|
||||
* Determine if the given ability should be granted.
|
||||
* Determine if all of the given abilities should be granted for the current user.
|
||||
*
|
||||
* @param string $ability
|
||||
* @param iterable|string $abilities
|
||||
* @param array|mixed $arguments
|
||||
* @return bool
|
||||
*/
|
||||
public function check($ability, $arguments = []);
|
||||
public function check($abilities, $arguments = []);
|
||||
|
||||
/**
|
||||
* Determine if any one of the given abilities should be granted for the current user.
|
||||
*
|
||||
* @param iterable|string $abilities
|
||||
* @param array|mixed $arguments
|
||||
* @return bool
|
||||
*/
|
||||
public function any($abilities, $arguments = []);
|
||||
|
||||
/**
|
||||
* Determine if the given ability should be granted for the current user.
|
||||
|
|
@ -84,6 +93,15 @@ interface Gate
|
|||
*/
|
||||
public function authorize($ability, $arguments = []);
|
||||
|
||||
/**
|
||||
* Get the raw result from the authorization callback.
|
||||
*
|
||||
* @param string $ability
|
||||
* @param array|mixed $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public function raw($ability, $arguments = []);
|
||||
|
||||
/**
|
||||
* Get a policy instance for a given class.
|
||||
*
|
||||
|
|
@ -101,4 +119,11 @@ interface Gate
|
|||
* @return static
|
||||
*/
|
||||
public function forUser($user);
|
||||
|
||||
/**
|
||||
* Get all of the defined abilities.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function abilities();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ interface Guard
|
|||
/**
|
||||
* Get the ID for the currently authenticated user.
|
||||
*
|
||||
* @return int|null
|
||||
* @return int|string|null
|
||||
*/
|
||||
public function id();
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ interface UserProvider
|
|||
/**
|
||||
* Retrieve a user by their unique identifier and "remember me" token.
|
||||
*
|
||||
* @param mixed $identifier
|
||||
* @param mixed $identifier
|
||||
* @param string $token
|
||||
* @return \Illuminate\Contracts\Auth\Authenticatable|null
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ interface Factory
|
|||
/**
|
||||
* Get a broadcaster implementation by name.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $name
|
||||
* @return void
|
||||
*/
|
||||
public function connection($name = null);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ interface ShouldBroadcast
|
|||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return array
|
||||
* @return \Illuminate\Broadcasting\Channel|\Illuminate\Broadcasting\Channel[]
|
||||
*/
|
||||
public function broadcastOn();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,22 @@ interface Dispatcher
|
|||
*/
|
||||
public function dispatchNow($command, $handler = null);
|
||||
|
||||
/**
|
||||
* Determine if the given command has a handler.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCommandHandler($command);
|
||||
|
||||
/**
|
||||
* Retrieve the handler for a command.
|
||||
*
|
||||
* @param mixed $command
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function getCommandHandler($command);
|
||||
|
||||
/**
|
||||
* Set the pipes commands should be piped through before dispatching.
|
||||
*
|
||||
|
|
@ -28,4 +44,12 @@ interface Dispatcher
|
|||
* @return $this
|
||||
*/
|
||||
public function pipeThrough(array $pipes);
|
||||
|
||||
/**
|
||||
* Map a command to a handler.
|
||||
*
|
||||
* @param array $map
|
||||
* @return $this
|
||||
*/
|
||||
public function map(array $map);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ interface Factory
|
|||
* Get a cache store instance by name.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return mixed
|
||||
* @return \Illuminate\Contracts\Cache\Repository
|
||||
*/
|
||||
public function store($name = null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,15 @@
|
|||
namespace Illuminate\Contracts\Cache;
|
||||
|
||||
use Closure;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
interface Repository
|
||||
interface Repository extends CacheInterface
|
||||
{
|
||||
/**
|
||||
* Determine if an item exists in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key);
|
||||
|
||||
/**
|
||||
* Retrieve an item from the cache by key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $default = null);
|
||||
|
||||
/**
|
||||
* Retrieve an item from the cache and delete it.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function pull($key, $default = null);
|
||||
|
|
@ -36,21 +20,21 @@ interface Repository
|
|||
* Store an item in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTime|float|int $minutes
|
||||
* @return void
|
||||
* @param mixed $value
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @return bool
|
||||
*/
|
||||
public function put($key, $value, $minutes);
|
||||
public function put($key, $value, $ttl = null);
|
||||
|
||||
/**
|
||||
* Store an item in the cache if the key does not exist.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTime|float|int $minutes
|
||||
* @param mixed $value
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @return bool
|
||||
*/
|
||||
public function add($key, $value, $minutes);
|
||||
public function add($key, $value, $ttl = null);
|
||||
|
||||
/**
|
||||
* Increment the value of an item in the cache.
|
||||
|
|
@ -74,34 +58,34 @@ interface Repository
|
|||
* Store an item in the cache indefinitely.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function forever($key, $value);
|
||||
|
||||
/**
|
||||
* Get an item from the cache, or store the default value.
|
||||
* Get an item from the cache, or execute the given Closure and store the result.
|
||||
*
|
||||
* @param string $key
|
||||
* @param \DateTime|float|int $minutes
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $ttl
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function remember($key, $minutes, Closure $callback);
|
||||
public function remember($key, $ttl, Closure $callback);
|
||||
|
||||
/**
|
||||
* Get an item from the cache, or store the default value forever.
|
||||
* Get an item from the cache, or execute the given Closure and store the result forever.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $key
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function sear($key, Closure $callback);
|
||||
|
||||
/**
|
||||
* Get an item from the cache, or store the default value forever.
|
||||
* Get an item from the cache, or execute the given Closure and store the result forever.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $key
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
@ -114,4 +98,11 @@ interface Repository
|
|||
* @return bool
|
||||
*/
|
||||
public function forget($key);
|
||||
|
||||
/**
|
||||
* Get the cache store implementation.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Cache\Store
|
||||
*/
|
||||
public function getStore();
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue