update 1.0.8.0

Commits for version update
This commit is contained in:
Manish Verma
2016-10-17 12:02:27 +05:30
parent dec927987b
commit 76e85db070
9674 changed files with 495757 additions and 58922 deletions

View File

@@ -68,7 +68,8 @@
"illuminate/support": "self.version",
"illuminate/translation": "self.version",
"illuminate/validation": "self.version",
"illuminate/view": "self.version"
"illuminate/view": "self.version",
"tightenco/collect": "self.version"
},
"require-dev": {
"aws/aws-sdk-php": "~3.0",
@@ -108,7 +109,7 @@
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).",
"symfony/css-selector": "Required to use some of the crawler integration testing tools (2.8.*|3.0.*).",
"symfony/dom-crawler": "Required to use most of the crawler integration testing tools (2.8.*|3.0.*).",
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)."
"symfony/psr-http-message-bridge": "Required to use psr7 bridging features (0.2.*)."
},
"minimum-stability": "dev"
}

View File

@@ -424,7 +424,7 @@ class Gate implements GateContract
}
/**
* Get a guard instance for the given user.
* Get a gate instance for the given user.
*
* @param \Illuminate\Contracts\Auth\Authenticatable|mixed $user
* @return static

View File

@@ -27,11 +27,10 @@ class RequestGuard implements Guard
* Create a new authentication guard.
*
* @param callable $callback
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Illuminate\Http\Request $request
* @return void
*/
public function __construct(callable $callback,
Request $request)
public function __construct(callable $callback, Request $request)
{
$this->request = $request;
$this->callback = $callback;

View File

@@ -101,6 +101,10 @@ class TokenGuard implements Guard
*/
public function validate(array $credentials = [])
{
if (empty($credentials[$this->inputKey])) {
return false;
}
$credentials = [$this->storageKey => $credentials[$this->inputKey]];
if ($this->provider->retrieveByCredentials($credentials)) {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -9,9 +9,8 @@ use Illuminate\Contracts\Queue\Queue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Bus\QueueingDispatcher;
use Illuminate\Contracts\Bus\Dispatcher as DispatcherContract;
class Dispatcher implements DispatcherContract, QueueingDispatcher
class Dispatcher implements QueueingDispatcher
{
/**
* The container implementation.

View File

@@ -21,7 +21,7 @@ trait Queueable
/**
* The number of seconds before the job should be made available.
*
* @var int|null
* @var \DateTime|int|null
*/
public $delay;

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -50,13 +50,13 @@ class ArrayStore extends TaggableStore implements Store
*/
public function increment($key, $value = 1)
{
$this->storage[$key] = $this->storage[$key] + $value;
$this->storage[$key] = ((int) $this->storage[$key]) + $value;
return $this->storage[$key];
}
/**
* Increment the value of an item in the cache.
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value

View File

@@ -35,7 +35,7 @@ class CacheTableCommand extends Command
protected $composer;
/**
* Create a new session table command instance.
* Create a new cache table command instance.
*
* @param \Illuminate\Filesystem\Filesystem $files
* @param \Illuminate\Support\Composer $composer

View File

@@ -4,6 +4,7 @@ namespace Illuminate\Cache\Console;
use Illuminate\Console\Command;
use Illuminate\Cache\CacheManager;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class ClearCommand extends Command
@@ -47,17 +48,23 @@ class ClearCommand extends Command
*
* @return void
*/
public function fire()
public function handle()
{
$storeName = $this->argument('store');
$tags = array_filter(explode(',', $this->option('tags')));
$this->laravel['events']->fire('cache:clearing', [$storeName]);
$cache = $this->cache->store($store = $this->argument('store'));
$this->cache->store($storeName)->flush();
$this->laravel['events']->fire('cache:clearing', [$store, $tags]);
$this->laravel['events']->fire('cache:cleared', [$storeName]);
if (! empty($tags)) {
$cache->tags($tags)->flush();
} else {
$cache->flush();
}
$this->info('Application cache cleared!');
$this->info('Cache cleared successfully.');
$this->laravel['events']->fire('cache:cleared', [$store, $tags]);
}
/**
@@ -71,4 +78,16 @@ class ClearCommand extends Command
['store', InputArgument::OPTIONAL, 'The name of the store you would like to clear.'],
];
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [
['tags', null, InputOption::VALUE_OPTIONAL, 'The cache tags you would like to clear.', null],
];
}
}

View File

@@ -128,7 +128,7 @@ class DatabaseStore implements Store
}
/**
* Increment the value of an item in the cache.
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value
@@ -165,7 +165,7 @@ class DatabaseStore implements Store
}
$current = $this->encrypter->decrypt($cache->value);
$new = $callback($current, $value);
$new = $callback((int) $current, $value);
if (! is_numeric($current)) {
return false;

View File

@@ -5,7 +5,7 @@ namespace Illuminate\Cache\Events;
class CacheMissed
{
/**
* THe key that was missed.
* The key that was missed.
*
* @var string
*/

View File

@@ -52,7 +52,7 @@ class NullStore extends TaggableStore implements Store
}
/**
* Increment the value of an item in the cache.
* Decrement the value of an item in the cache.
*
* @param string $key
* @param mixed $value

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -33,14 +33,14 @@ class CallbackEvent extends Event
*/
public function __construct($callback, array $parameters = [])
{
$this->callback = $callback;
$this->parameters = $parameters;
if (! is_string($this->callback) && ! is_callable($this->callback)) {
if (! is_string($callback) && ! is_callable($callback)) {
throw new InvalidArgumentException(
'Invalid scheduled callback event. Must be string or callable.'
);
}
$this->callback = $callback;
$this->parameters = $parameters;
}
/**

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -190,8 +190,8 @@ class Container implements ArrayAccess, ContainerContract
}
// If no concrete type was given, we will simply set the concrete type to the
// abstract type. This will allow concrete type to be registered as shared
// without being forced to state their classes in both of the parameter.
// 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)) {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -8,7 +8,6 @@ interface Dispatcher
* Dispatch a command to its appropriate handler.
*
* @param mixed $command
* @param \Closure|null $afterResolving
* @return mixed
*/
public function dispatch($command);
@@ -17,7 +16,6 @@ interface Dispatcher
* Dispatch a command to its appropriate handler in the current process.
*
* @param mixed $command
* @param \Closure|null $afterResolving
* @return mixed
*/
public function dispatchNow($command);

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -33,7 +33,7 @@ class Manager
// Once we have the container setup, we will setup the default configuration
// options in the container "config" binding. This will make the database
// manager behave correctly since all the correct binding are in place.
// manager work correctly out of the box without extreme configuration.
$this->setupDefaultConfiguration();
$this->setupManager();
@@ -135,7 +135,7 @@ class Manager
// If we have an event dispatcher instance, we will go ahead and register it
// with the Eloquent ORM, allowing for model callbacks while creating and
// updating "model" instances; however, if it not necessary to operate.
// updating "model" instances; however, it is not necessary to operate.
if ($dispatcher = $this->getEventDispatcher()) {
Eloquent::setEventDispatcher($dispatcher);
}

View File

@@ -334,11 +334,18 @@ class Connection implements ConnectionInterface
$statement->execute($me->prepareBindings($bindings));
$fetchMode = $me->getFetchMode();
$fetchArgument = $me->getFetchArgument();
$fetchConstructorArgument = $me->getFetchConstructorArgument();
return isset($fetchArgument) ?
$statement->fetchAll($me->getFetchMode(), $fetchArgument, $me->getFetchConstructorArgument()) :
$statement->fetchAll($me->getFetchMode());
if ($fetchMode === PDO::FETCH_CLASS && ! isset($fetchArgument)) {
$fetchArgument = 'StdClass';
$fetchConstructorArgument = null;
}
return isset($fetchArgument)
? $statement->fetchAll($fetchMode, $fetchArgument, $fetchConstructorArgument)
: $statement->fetchAll($fetchMode);
});
}
@@ -359,10 +366,19 @@ class Connection implements ConnectionInterface
$statement = $this->getPdoForSelect($useReadPdo)->prepare($query);
if ($me->getFetchMode() === PDO::FETCH_CLASS) {
$statement->setFetchMode($me->getFetchMode(), 'StdClass');
$fetchMode = $me->getFetchMode();
$fetchArgument = $me->getFetchArgument();
$fetchConstructorArgument = $me->getFetchConstructorArgument();
if ($fetchMode === PDO::FETCH_CLASS && ! isset($fetchArgument)) {
$fetchArgument = 'StdClass';
$fetchConstructorArgument = null;
}
if (isset($fetchArgument)) {
$statement->setFetchMode($fetchMode, $fetchArgument, $fetchConstructorArgument);
} else {
$statement->setFetchMode($me->getFetchMode());
$statement->setFetchMode($fetchMode);
}
$statement->execute($me->prepareBindings($bindings));
@@ -583,7 +599,7 @@ class Connection implements ConnectionInterface
$this->getPdo()->commit();
}
--$this->transactions;
$this->transactions = max(0, $this->transactions - 1);
$this->fireConnectionEvent('committed');
}

View File

@@ -23,7 +23,7 @@ class MySqlConnector extends Connector implements ConnectorInterface
// connection's behavior, and some might be specified by the developers.
$connection = $this->createConnection($dsn, $config, $options);
if (isset($config['database'])) {
if (! empty($config['database'])) {
$connection->exec("use `{$config['database']}`;");
}

View File

@@ -26,7 +26,6 @@ trait DetectsLostConnections
'decryption failed or bad record mac',
'server closed the connection unexpectedly',
'SSL connection has been closed unexpectedly',
'Deadlock found when trying to get lock',
'Error writing data to the connection',
'Resource deadlock avoided',
]);

View File

@@ -482,16 +482,17 @@ class Builder
*/
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$perPage = $perPage ?: $this->model->getPerPage();
$query = $this->toBase();
$total = $query->getCountForPagination();
$this->forPage(
$page = $page ?: Paginator::resolveCurrentPage($pageName),
$perPage = $perPage ?: $this->model->getPerPage()
);
$results = $total ? $this->forPage($page, $perPage)->get($columns) : new Collection;
return new LengthAwarePaginator($this->get($columns), $total, $perPage, $page, [
return new LengthAwarePaginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
@@ -710,7 +711,7 @@ class Builder
* @param string $relation
* @return array
*/
public function nestedRelations($relation)
protected function nestedRelations($relation)
{
$nested = [];
@@ -1142,6 +1143,29 @@ class Builder
return $results;
}
/**
* Add the given scopes to the current builder instance.
*
* @param array $scopes
* @return mixed
*/
public function scopes(array $scopes)
{
$builder = $this;
foreach ($scopes as $scope => $parameters) {
if (is_int($scope)) {
list($scope, $parameters) = [$parameters, []];
}
$builder = $builder->callScope(
[$this->model, 'scope'.ucfirst($scope)], (array) $parameters
);
}
return $builder;
}
/**
* Apply the given scope on the current builder instance.
*
@@ -1275,7 +1299,7 @@ class Builder
/**
* Get the underlying query builder instance.
*
* @return \Illuminate\Database\Query\Builder|static
* @return \Illuminate\Database\Query\Builder
*/
public function getQuery()
{

View File

@@ -521,7 +521,7 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab
$model->setRawAttributes((array) $attributes, true);
$model->setConnection($connection ?: $this->connection);
$model->setConnection($connection ?: $this->getConnectionName());
return $model;
}
@@ -828,11 +828,11 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab
list($type, $id) = $this->getMorphs($name, $type, $id);
// If the type value is null it is probably safe to assume we're eager loading
// the relationship. When that is the case we will pass in a dummy query as
// there are multiple types in the morph and we can't use single queries.
// the relationship. In this case we'll just pass in a dummy query where we
// need to remove any eager loads that may already be defined on a model.
if (empty($class = $this->$type)) {
return new MorphTo(
$this->newQuery(), $this, $id, null, $type, $name
$this->newQuery()->setEagerLoads([]), $this, $id, null, $type, $name
);
}
@@ -2140,6 +2140,23 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab
return $this;
}
/**
* Make the given, typically visible, attributes hidden.
*
* @param array|string $attributes
* @return $this
*/
public function makeHidden($attributes)
{
$attributes = (array) $attributes;
$this->visible = array_diff($this->visible, $attributes);
$this->hidden = array_unique(array_merge($this->hidden, $attributes));
return $this;
}
/**
* Make the given, typically hidden, attributes visible.
*
@@ -2595,10 +2612,14 @@ abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializab
protected function getArrayableItems(array $values)
{
if (count($this->getVisible()) > 0) {
return array_intersect_key($values, array_flip($this->getVisible()));
$values = array_intersect_key($values, array_flip($this->getVisible()));
}
return array_diff_key($values, array_flip($this->getHidden()));
if (count($this->getHidden()) > 0) {
$values = array_diff_key($values, array_flip($this->getHidden()));
}
return $values;
}
/**

View File

@@ -47,12 +47,19 @@ class BelongsToMany extends Relation
protected $pivotColumns = [];
/**
* Any pivot table restrictions.
* Any pivot table restrictions for where clauses.
*
* @var array
*/
protected $pivotWheres = [];
/**
* Any pivot table restrictions for whereIn clauses.
*
* @var array
*/
protected $pivotWhereIns = [];
/**
* The custom pivot table column for the created_at timestamp.
*
@@ -132,7 +139,7 @@ class BelongsToMany extends Relation
*/
public function wherePivotIn($column, $values, $boolean = 'and', $not = false)
{
$this->pivotWheres[] = func_get_args();
$this->pivotWhereIns[] = func_get_args();
return $this->whereIn($this->table.'.'.$column, $values, $boolean, $not);
}
@@ -788,6 +795,17 @@ class BelongsToMany extends Relation
return $instances;
}
/**
* Sync the intermediate tables with a list of IDs without detaching.
*
* @param \Illuminate\Database\Eloquent\Collection|array $ids
* @return array
*/
public function syncWithoutDetaching($ids)
{
return $this->sync($ids, false);
}
/**
* Sync the intermediate tables with a list of IDs or collection of models.
*
@@ -816,7 +834,7 @@ class BelongsToMany extends Relation
// Next, we will take the differences of the currents and given IDs and detach
// all of the entities that exist in the "current" array but are not in the
// the array of the IDs given to the method which will complete the sync.
// array of the new IDs given to the method which will complete the sync.
if ($detaching && count($detach) > 0) {
$this->detach($detach);
@@ -1054,14 +1072,18 @@ class BelongsToMany extends Relation
/**
* Detach models from the relationship.
*
* @param int|array $ids
* @param mixed $ids
* @param bool $touch
* @return int
*/
public function detach($ids = [], $touch = true)
{
if ($ids instanceof Model) {
$ids = (array) $ids->getKey();
$ids = $ids->getKey();
}
if ($ids instanceof Collection) {
$ids = $ids->modelKeys();
}
$query = $this->newPivotQuery();
@@ -1072,7 +1094,7 @@ class BelongsToMany extends Relation
$ids = (array) $ids;
if (count($ids) > 0) {
$query->whereIn($this->otherKey, (array) $ids);
$query->whereIn($this->otherKey, $ids);
}
// Once we have all of the conditions set on the statement, we are ready
@@ -1136,6 +1158,10 @@ class BelongsToMany extends Relation
call_user_func_array([$query, 'where'], $whereArgs);
}
foreach ($this->pivotWhereIns as $whereArgs) {
call_user_func_array([$query, 'whereIn'], $whereArgs);
}
return $query->where($this->foreignKey, $this->parent->getKey());
}

View File

@@ -183,11 +183,9 @@ class MorphTo extends BelongsTo
$key = $instance->getTable().'.'.$instance->getKeyName();
$eagerLoads = $this->getQuery()->nestedRelations($this->relation);
$query = $this->replayMacros($instance->newQuery())
->mergeModelDefinedRelationConstraints($this->getQuery())
->with($eagerLoads);
->with($this->getQuery()->getEagerLoads());
return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
}

View File

@@ -9,7 +9,7 @@ class SoftDeletingScope implements Scope
*
* @var array
*/
protected $extensions = ['ForceDelete', 'Restore', 'WithTrashed', 'OnlyTrashed'];
protected $extensions = ['ForceDelete', 'Restore', 'WithTrashed', 'WithoutTrashed', 'OnlyTrashed'];
/**
* Apply the scope to a given Eloquent query builder.
@@ -100,6 +100,25 @@ class SoftDeletingScope implements Scope
});
}
/**
* Add the without-trashed extension to the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
protected function addWithoutTrashed(Builder $builder)
{
$builder->macro('withoutTrashed', function (Builder $builder) {
$model = $builder->getModel();
$builder->withoutGlobalScope($this)->whereNull(
$model->getQualifiedDeletedAtColumn()
);
return $builder;
});
}
/**
* Add the only-trashed extension to the builder.
*

View File

@@ -4,6 +4,7 @@ namespace Illuminate\Database\Migrations;
use Closure;
use Illuminate\Support\Str;
use InvalidArgumentException;
use Illuminate\Filesystem\Filesystem;
class MigrationCreator
@@ -41,9 +42,12 @@ class MigrationCreator
* @param string $table
* @param bool $create
* @return string
* @throws \Exception
*/
public function create($name, $path, $table = null, $create = false)
{
$this->ensureMigrationDoesntAlreadyExist($name);
$path = $this->getPath($name, $path);
// First we will get the stub file for the migration, which serves as a type
@@ -58,6 +62,21 @@ class MigrationCreator
return $path;
}
/**
* Ensure that a migration with the given name doesn't already exist.
*
* @param string $name
* @return void
*
* @throws \InvalidArgumentException
*/
protected function ensureMigrationDoesntAlreadyExist($name)
{
if (class_exists($className = $this->getClassName($name))) {
throw new InvalidArgumentException("A $className migration already exists.");
}
}
/**
* Get the migration stub file.
*

View File

@@ -195,7 +195,7 @@ class Builder
'&', '|', '^', '<<', '>>',
'rlike', 'regexp', 'not regexp',
'~', '~*', '!~', '!~*', 'similar to',
'not similar to',
'not similar to', 'not ilike', '~~*', '!~~*',
];
/**
@@ -1078,6 +1078,33 @@ class Builder
return $this->whereDate($column, $operator, $value, 'or');
}
/**
* Add a "where time" statement to the query.
*
* @param string $column
* @param string $operator
* @param int $value
* @param string $boolean
* @return \Illuminate\Database\Query\Builder|static
*/
public function whereTime($column, $operator, $value, $boolean = 'and')
{
return $this->addDateBasedWhere('Time', $column, $operator, $value, $boolean);
}
/**
* Add an "or where time" statement to the query.
*
* @param string $column
* @param string $operator
* @param int $value
* @return \Illuminate\Database\Query\Builder|static
*/
public function orWhereTime($column, $operator, $value)
{
return $this->whereTime($column, $operator, $value, 'or');
}
/**
* Add a "where day" statement to the query.
*
@@ -1121,7 +1148,7 @@ class Builder
}
/**
* Add a date based (year, month, day) statement to the query.
* Add a date based (year, month, day, time) statement to the query.
*
* @param string $type
* @param string $column
@@ -1598,7 +1625,7 @@ class Builder
$total = $this->getCountForPagination($columns);
$results = $this->forPage($page, $perPage)->get($columns);
$results = $total ? $this->forPage($page, $perPage)->get($columns) : [];
return new LengthAwarePaginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
@@ -1756,12 +1783,15 @@ class Builder
* @param int $count
* @param callable $callback
* @param string $column
* @param string $alias
* @return bool
*/
public function chunkById($count, callable $callback, $column = 'id')
public function chunkById($count, callable $callback, $column = 'id', $alias = null)
{
$lastId = null;
$alias = $alias ?: $column;
$results = $this->forPageAfterId($count, 0, $column)->get();
while (! empty($results)) {
@@ -1769,7 +1799,7 @@ class Builder
return false;
}
$lastId = last($results)->{$column};
$lastId = last($results)->{$alias};
$results = $this->forPageAfterId($count, $lastId, $column)->get();
}
@@ -1898,7 +1928,7 @@ class Builder
* Retrieve the minimum value of a given column.
*
* @param string $column
* @return float|int
* @return mixed
*/
public function min($column)
{
@@ -1909,7 +1939,7 @@ class Builder
* Retrieve the maximum value of a given column.
*
* @param string $column
* @return float|int
* @return mixed
*/
public function max($column)
{
@@ -1920,20 +1950,18 @@ class Builder
* Retrieve the sum of the values of a given column.
*
* @param string $column
* @return float|int
* @return mixed
*/
public function sum($column)
{
$result = $this->aggregate(__FUNCTION__, [$column]);
return $result ?: 0;
return $this->aggregate(__FUNCTION__, [$column]);
}
/**
* Retrieve the average of the values of a given column.
*
* @param string $column
* @return float|int
* @return mixed
*/
public function avg($column)
{
@@ -1944,7 +1972,7 @@ class Builder
* Alias for the "avg" method.
*
* @param string $column
* @return float|int
* @return mixed
*/
public function average($column)
{
@@ -1956,7 +1984,7 @@ class Builder
*
* @param string $function
* @param array $columns
* @return float|int
* @return mixed
*/
public function aggregate($function, $columns = ['*'])
{
@@ -1983,12 +2011,36 @@ class Builder
$this->bindings['select'] = $previousSelectBindings;
if (isset($results[0])) {
$result = array_change_key_case((array) $results[0]);
return $result['aggregate'];
return array_change_key_case((array) $results[0])['aggregate'];
}
}
/**
* Execute a numeric aggregate function on the database.
*
* @param string $function
* @param array $columns
* @return float|int
*/
public function numericAggregate($function, $columns = ['*'])
{
$result = $this->aggregate($function, $columns);
if (! $result) {
return 0;
}
if (is_int($result) || is_float($result)) {
return $result;
}
if (strpos((string) $result, '.') === false) {
return (int) $result;
}
return (float) $result;
}
/**
* Insert a new record into the database.
*
@@ -2098,6 +2150,10 @@ class Builder
*/
public function increment($column, $amount = 1, array $extra = [])
{
if (! is_numeric($amount)) {
throw new InvalidArgumentException('Non-numeric value passed to increment method.');
}
$wrapped = $this->grammar->wrap($column);
$columns = array_merge([$column => $this->raw("$wrapped + $amount")], $extra);
@@ -2115,6 +2171,10 @@ class Builder
*/
public function decrement($column, $amount = 1, array $extra = [])
{
if (! is_numeric($amount)) {
throw new InvalidArgumentException('Non-numeric value passed to decrement method.');
}
$wrapped = $this->grammar->wrap($column);
$columns = array_merge([$column => $this->raw("$wrapped - $amount")], $extra);

View File

@@ -460,6 +460,18 @@ class Grammar extends BaseGrammar
return $this->dateBasedWhere('date', $query, $where);
}
/**
* Compile a "where time" clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $where
* @return string
*/
protected function whereTime(Builder $query, $where)
{
return $this->dateBasedWhere('time', $query, $where);
}
/**
* Compile a "where day" clause.
*

View File

@@ -197,14 +197,14 @@ class MySqlGrammar extends Grammar
$sql = trim("delete $table from {$table}{$joins} $where");
} else {
$sql = trim("delete from $table $where");
}
if (isset($query->orders)) {
$sql .= ' '.$this->compileOrders($query, $query->orders);
}
if (isset($query->orders)) {
$sql .= ' '.$this->compileOrders($query, $query->orders);
}
if (isset($query->limit)) {
$sql .= ' '.$this->compileLimit($query, $query->limit);
if (isset($query->limit)) {
$sql .= ' '.$this->compileLimit($query, $query->limit);
}
}
return $sql;

View File

@@ -49,42 +49,6 @@ class PostgresGrammar extends Grammar
return $this->wrap($where['column']).'::date '.$where['operator'].' '.$value;
}
/**
* Compile a "where day" clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $where
* @return string
*/
protected function whereDay(Builder $query, $where)
{
return $this->dateBasedWhere('day', $query, $where);
}
/**
* Compile a "where month" clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $where
* @return string
*/
protected function whereMonth(Builder $query, $where)
{
return $this->dateBasedWhere('month', $query, $where);
}
/**
* Compile a "where year" clause.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $where
* @return string
*/
protected function whereYear(Builder $query, $where)
{
return $this->dateBasedWhere('year', $query, $where);
}
/**
* Compile a date based where clause.
*

View File

@@ -17,13 +17,11 @@ class PostgresProcessor extends Processor
*/
public function processInsertGetId(Builder $query, $sql, $values, $sequence = null)
{
$results = $query->getConnection()->selectFromWriteConnection($sql, $values);
$result = $query->getConnection()->selectFromWriteConnection($sql, $values)[0];
$sequence = $sequence ?: 'id';
$result = (array) $results[0];
$id = $result[$sequence];
$id = is_object($result) ? $result->$sequence : $result[$sequence];
return is_numeric($id) ? (int) $id : $id;
}

View File

@@ -39,13 +39,15 @@ class SqlServerProcessor extends Processor
*/
protected function processInsertGetIdForOdbc($connection)
{
$result = $connection->select('SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS int) AS insertid');
$result = $connection->selectFromWriteConnection('SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS int) AS insertid');
if (! $result) {
throw new Exception('Unable to retrieve lastInsertID for ODBC.');
}
return $result[0]->insertid;
$row = $result[0];
return is_object($row) ? $row->insertid : $row['insertid'];
}
/**

View File

@@ -11,7 +11,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -51,14 +51,16 @@ class Filesystem
{
$contents = '';
$handle = fopen($path, 'r');
$handle = fopen($path, 'rb');
if ($handle) {
try {
if (flock($handle, LOCK_SH)) {
while (! feof($handle)) {
$contents .= fread($handle, 1048576);
}
clearstatcache(true, $path);
$contents = fread($handle, $this->size($path) ?: 1);
flock($handle, LOCK_UN);
}
} finally {
fclose($handle);
@@ -388,6 +390,25 @@ class Filesystem
return mkdir($path, $mode, $recursive);
}
/**
* Move a directory.
*
* @param string $from
* @param string $to
* @param bool $overwrite
* @return bool
*/
public function moveDirectory($from, $to, $overwrite = false)
{
if ($overwrite && $this->isDirectory($to)) {
if (! $this->deleteDirectory($to)) {
return false;
}
}
return @rename($from, $to) === true;
}
/**
* Copy a directory from one location to another.
*

View File

@@ -238,6 +238,8 @@ class FilesystemAdapter implements FilesystemContract, CloudFilesystemContract
return $adapter->getClient()->getObjectUrl($adapter->getBucket(), $path);
} elseif ($adapter instanceof LocalAdapter) {
return '/storage/'.$path;
} elseif (method_exists($adapter, 'getUrl')) {
return $adapter->getUrl($path);
} else {
throw new RuntimeException('This driver does not support retrieving URLs.');
}

View File

@@ -255,7 +255,7 @@ class FilesystemManager implements FactoryContract
*/
protected function createFlysystem(AdapterInterface $adapter, array $config)
{
$config = Arr::only($config, ['visibility']);
$config = Arr::only($config, ['visibility', 'disable_asserts']);
return new Flysystem($adapter, count($config) > 0 ? $config : null);
}

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -25,7 +25,7 @@ class Application extends Container implements ApplicationContract, HttpKernelIn
*
* @var string
*/
const VERSION = '5.2.39';
const VERSION = '5.2.45';
/**
* The base path for the Laravel installation.

View File

@@ -16,10 +16,16 @@ trait AuthorizesResources
{
$parameter = $parameter ?: strtolower(class_basename($model));
$middleware = [];
foreach ($this->resourceAbilityMap() as $method => $ability) {
$modelName = in_array($method, ['index', 'create', 'store']) ? $model : $parameter;
$this->middleware("can:{$ability},{$modelName}", $options)->only($method);
$middleware["can:{$ability},{$modelName}"][] = $method;
}
foreach ($middleware as $middlewareName => $methods) {
$this->middleware($middlewareName, $options)->only($methods);
}
}

View File

@@ -58,7 +58,7 @@ class VendorPublishCommand extends Command
$tags = $tags ?: [null];
foreach ($tags as $tag) {
foreach ((array) $tags as $tag) {
$this->publishTag($tag);
}
}

View File

@@ -2,6 +2,7 @@
namespace Illuminate\Foundation\Console;
use RuntimeException;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
@@ -48,9 +49,13 @@ class ViewClearCommand extends Command
*/
public function fire()
{
$views = $this->files->glob($this->laravel['config']['view.compiled'].'/*');
$path = $this->laravel['config']['view.compiled'];
foreach ($views as $view) {
if (! $path) {
throw new RuntimeException('View path not found.');
}
foreach ($this->files->glob("{$path}/*") as $view) {
$this->files->delete($view);
}

View File

@@ -134,7 +134,7 @@ class VerifyCsrfToken
$response->headers->setCookie(
new Cookie(
'XSRF-TOKEN', $request->session()->token(), time() + 60 * 120,
'XSRF-TOKEN', $request->session()->token(), time() + 60 * $config['lifetime'],
$config['path'], $config['domain'], $config['secure'], false
)
);

View File

@@ -2,6 +2,7 @@
namespace Illuminate\Foundation\Testing\Constraints;
use DOMElement;
use Symfony\Component\DomCrawler\Crawler;
class IsSelected extends FormFieldConstraint
@@ -60,17 +61,32 @@ class IsSelected extends FormFieldConstraint
if ($option->nodeName === 'optgroup') {
foreach ($option->childNodes as $child) {
if ($child->hasAttribute('selected')) {
$selected[] = $child->getAttribute('value');
$selected[] = $this->getOptionValue($child);
}
}
} elseif ($option->hasAttribute('selected')) {
$selected[] = $option->getAttribute('value');
$selected[] = $this->getOptionValue($option);
}
}
return $selected;
}
/**
* Get the selected value from an option element.
*
* @param \DOMElement $option
* @return string
*/
protected function getOptionValue(DOMElement $option)
{
if ($option->hasAttribute('value')) {
return $option->getAttribute('value');
}
return $option->textContent;
}
/**
* Get the checked value from a radio group.
*

View File

@@ -94,14 +94,14 @@ abstract class TestCase extends PHPUnit_Framework_TestCase
{
$uses = array_flip(class_uses_recursive(static::class));
if (isset($uses[DatabaseTransactions::class])) {
$this->beginDatabaseTransaction();
}
if (isset($uses[DatabaseMigrations::class])) {
$this->runDatabaseMigrations();
}
if (isset($uses[DatabaseTransactions::class])) {
$this->beginDatabaseTransaction();
}
if (isset($uses[WithoutMiddleware::class])) {
$this->disableMiddlewareForAllTests();
}

View File

@@ -138,7 +138,7 @@ if (! function_exists('auth')) {
* Get the available auth instance.
*
* @param string|null $guard
* @return \Illuminate\Contracts\Auth\Factory
* @return \Illuminate\Contracts\Auth\Factory|\Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
*/
function auth($guard = null)
{

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -72,17 +72,32 @@ class RedirectResponse extends BaseRedirectResponse
{
$input = $input ?: $this->request->input();
$this->session->flashInput($data = array_filter($input, $callback = function (&$value) use (&$callback) {
if (is_array($value)) {
$value = array_filter($value, $callback);
}
return ! $value instanceof SymfonyUploadedFile;
}));
$this->session->flashInput($this->removeFilesFromInput($input));
return $this;
}
/**
* Remove all uploaded files form the given input array.
*
* @param array $input
* @return array
*/
protected function removeFilesFromInput(array $input)
{
foreach ($input as $key => $value) {
if (is_array($value)) {
$input[$key] = $this->removeFilesFromInput($value);
}
if ($value instanceof SymfonyUploadedFile) {
unset($input[$key]);
}
}
return $input;
}
/**
* Flash an array of input to the session.
*

View File

@@ -271,7 +271,7 @@ class Request extends SymfonyRequest implements Arrayable, ArrayAccess
$input = $this->all();
foreach ($keys as $value) {
if (! array_key_exists($value, $input)) {
if (! Arr::has($input, $value)) {
return false;
}
}
@@ -338,7 +338,7 @@ class Request extends SymfonyRequest implements Arrayable, ArrayAccess
}
/**
* Get a subset of the items from the input data.
* Get a subset containing the provided keys with values from the input data.
*
* @param array|mixed $keys
* @return array
@@ -459,7 +459,7 @@ class Request extends SymfonyRequest implements Arrayable, ArrayAccess
*
* @param string $key
* @param mixed $default
* @return \Symfony\Component\HttpFoundation\File\UploadedFile|array|null
* @return \Illuminate\Http\UploadedFile|array|null
*/
public function file($key = null, $default = null)
{

View File

@@ -87,7 +87,7 @@ trait ResponseTrait
/**
* Throws the response in a HttpResponseException instance.
*
* @throws Illuminate\Http\Exception\HttpResponseException;
* @throws \Illuminate\Http\Exception\HttpResponseException
*/
public function throwResponse()
{

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -46,8 +46,8 @@ class MailgunTransport extends Transport
*/
public function __construct(ClientInterface $client, $key, $domain)
{
$this->client = $client;
$this->key = $key;
$this->client = $client;
$this->setDomain($domain);
}

View File

@@ -21,17 +21,26 @@ class SparkPostTransport extends Transport
*/
protected $key;
/**
* Transmission options.
*
* @var array
*/
protected $options = [];
/**
* Create a new SparkPost transport instance.
*
* @param \GuzzleHttp\ClientInterface $client
* @param string $key
* @param array $options
* @return void
*/
public function __construct(ClientInterface $client, $key)
public function __construct(ClientInterface $client, $key, $options = [])
{
$this->client = $client;
$this->key = $key;
$this->client = $client;
$this->options = $options;
}
/**
@@ -57,6 +66,10 @@ class SparkPostTransport extends Transport
],
];
if ($this->options) {
$options['json']['options'] = $this->options;
}
return $this->client->post('https://api.sparkpost.com/api/v1/transmissions', $options);
}

View File

@@ -134,7 +134,9 @@ class TransportManager extends Manager
$config = $this->app['config']->get('services.sparkpost', []);
return new SparkPostTransport(
$this->getHttpClient($config), $config['secret']
$this->getHttpClient($config),
$config['secret'],
Arr::get($config, 'options', [])
);
}

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -4,10 +4,8 @@ namespace Illuminate\Queue;
use DateTime;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Database\Connection;
use Illuminate\Queue\Jobs\DatabaseJob;
use Illuminate\Database\Query\Expression;
use Illuminate\Contracts\Queue\Queue as QueueContract;
class DatabaseQueue extends Queue implements QueueContract
@@ -161,14 +159,10 @@ class DatabaseQueue extends Queue implements QueueContract
{
$queue = $this->getQueue($queue);
if (! is_null($this->expire)) {
$this->releaseJobsThatHaveBeenReservedTooLong($queue);
}
$this->database->beginTransaction();
if ($job = $this->getNextAvailableJob($queue)) {
$this->markJobAsReserved($job->id);
$job = $this->markJobAsReserved($job);
$this->database->commit();
@@ -180,38 +174,6 @@ class DatabaseQueue extends Queue implements QueueContract
$this->database->commit();
}
/**
* Release the jobs that have been reserved for too long.
*
* @param string $queue
* @return void
*/
protected function releaseJobsThatHaveBeenReservedTooLong($queue)
{
if (random_int(1, 10) < 10) {
return;
}
$this->database->beginTransaction();
$stale = $this->database->table($this->table)
->lockForUpdate()
->where('queue', $this->getQueue($queue))
->where('reserved', 1)
->where('reserved_at', '<=', Carbon::now()->subSeconds($this->expire)->getTimestamp())
->get();
$this->database->table($this->table)
->whereIn('id', Collection::make($stale)->pluck('id')->all())
->update([
'reserved' => 0,
'reserved_at' => null,
'attempts' => new Expression('attempts + 1'),
]);
$this->database->commit();
}
/**
* Get the next available job for the queue.
*
@@ -223,8 +185,10 @@ class DatabaseQueue extends Queue implements QueueContract
$job = $this->database->table($this->table)
->lockForUpdate()
->where('queue', $this->getQueue($queue))
->where('reserved', 0)
->where('available_at', '<=', $this->getTime())
->where(function ($query) {
$this->isAvailable($query);
$this->isReservedButExpired($query);
})
->orderBy('id', 'asc')
->first();
@@ -232,16 +196,54 @@ class DatabaseQueue extends Queue implements QueueContract
}
/**
* Mark the given job ID as reserved.
* Modify the query to check for available jobs.
*
* @param string $id
* @param \Illuminate\Database\Query\Builder $query
* @return void
*/
protected function markJobAsReserved($id)
protected function isAvailable($query)
{
$this->database->table($this->table)->where('id', $id)->update([
'reserved' => 1, 'reserved_at' => $this->getTime(),
$query->where(function ($query) {
$query->where('reserved', 0);
$query->where('available_at', '<=', $this->getTime());
});
}
/**
* Modify the query to check for jobs that are reserved but have expired.
*
* @param \Illuminate\Database\Query\Builder $query
* @return void
*/
protected function isReservedButExpired($query)
{
$expiration = Carbon::now()->subSeconds($this->expire)->getTimestamp();
$query->orWhere(function ($query) use ($expiration) {
$query->where('reserved', 1);
$query->where('reserved_at', '<=', $expiration);
});
}
/**
* Mark the given job ID as reserved.
*
* @param \stdClass $job
* @return \stdClass
*/
protected function markJobAsReserved($job)
{
$job->reserved = 1;
$job->attempts = $job->attempts + 1;
$job->reserved_at = $this->getTime();
$this->database->table($this->table)->where('id', $job->id)->update([
'reserved' => $job->reserved,
'reserved_at' => $job->reserved_at,
'attempts' => $job->attempts,
]);
return $job;
}
/**

View File

@@ -37,7 +37,6 @@ class DatabaseJob extends Job implements JobContract
$this->queue = $queue;
$this->database = $database;
$this->container = $container;
$this->job->attempts = $this->job->attempts + 1;
}
/**

View File

@@ -4,11 +4,12 @@ namespace Illuminate\Queue;
use Closure;
use DateTime;
use Exception;
use Illuminate\Support\Arr;
use SuperClosure\Serializer;
use Illuminate\Container\Container;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract;
abstract class Queue
{
@@ -19,6 +20,13 @@ abstract class Queue
*/
protected $container;
/**
* The encrypter implementation.
*
* @var \Illuminate\Contracts\Encryption\Encrypter
*/
protected $encrypter;
/**
* Push a new job onto the queue.
*
@@ -73,7 +81,9 @@ abstract class Queue
{
if ($job instanceof Closure) {
return json_encode($this->createClosurePayload($job, $data));
} elseif (is_object($job)) {
}
if (is_object($job)) {
return json_encode([
'job' => 'Illuminate\Queue\CallQueuedHandler@call',
'data' => ['commandName' => get_class($job), 'command' => serialize(clone $job)],
@@ -144,7 +154,7 @@ abstract class Queue
*/
protected function createClosurePayload($job, $data)
{
$closure = $this->crypt->encrypt((new Serializer)->serialize($job));
$closure = $this->getEncrypter()->encrypt((new Serializer)->serialize($job));
return ['job' => 'IlluminateQueueClosure', 'data' => compact('closure')];
}
@@ -201,13 +211,29 @@ abstract class Queue
}
/**
* Set the encrypter instance.
* Get the encrypter implementation.
*
* @param \Illuminate\Contracts\Encryption\Encrypter $crypt
* @return \Illuminate\Contracts\Encryption\Encrypter
*
* @throws \Exception
*/
protected function getEncrypter()
{
if (is_null($this->encrypter)) {
throw new Exception('No encrypter has been set on the Queue.');
}
return $this->encrypter;
}
/**
* Set the encrypter implementation.
*
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
* @return void
*/
public function setEncrypter(EncrypterContract $crypt)
public function setEncrypter(Encrypter $encrypter)
{
$this->crypt = $crypt;
$this->encrypter = $encrypter;
}
}

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -360,7 +360,7 @@ class ResourceRegistrar
* @param string $base
* @param string $controller
* @param array $options
* @return void
* @return \Illuminate\Routing\Route
*/
protected function addResourceUpdate($name, $base, $controller, $options)
{

View File

@@ -373,9 +373,7 @@ class Route
public function parameters()
{
if (isset($this->parameters)) {
return array_map(function ($value) {
return is_string($value) ? rawurldecode($value) : $value;
}, $this->parameters);
return $this->parameters;
}
throw new LogicException('Route is not bound.');

View File

@@ -192,7 +192,7 @@ class RouteCollection implements Countable, IteratorAggregate
* @param array $methods
* @return \Illuminate\Routing\Route
*
* @throws \Symfony\Component\Routing\Exception\MethodNotAllowedHttpException
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
*/
protected function getRouteForMethods($request, array $methods)
{

View File

@@ -130,15 +130,22 @@ class UrlGenerator implements UrlGeneratorContract
/**
* Get the URL for the previous request.
*
* @param mixed $fallback
* @return string
*/
public function previous()
public function previous($fallback = false)
{
$referrer = $this->request->headers->get('referer');
$url = $referrer ? $this->to($referrer) : $this->getPreviousUrlFromSession();
return $url ?: $this->to('/');
if ($url) {
return $url;
} elseif ($fallback) {
return $this->to($fallback);
} else {
return $this->to('/');
}
}
/**

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -57,6 +57,8 @@ class StartSession
$session = $this->startSession($request);
$request->setSession($session);
$this->collectGarbage($session);
}
$response = $next($request);
@@ -67,8 +69,6 @@ class StartSession
if ($this->sessionConfigured()) {
$this->storeCurrentUrl($request, $session);
$this->collectGarbage($session);
$this->addCookieToResponse($response, $session);
}

View File

@@ -413,6 +413,34 @@ class Store implements SessionInterface
$this->put($key, $array);
}
/**
* Increment the value of an item in the session.
*
* @param string $key
* @param int $amount
* @return mixed
*/
public function increment($key, $amount = 1)
{
$value = $this->get($key, 0) + $amount;
$this->put($key, $value);
return $value;
}
/**
* Decrement the value of an item in the session.
*
* @param string $key
* @param int $amount
* @return int
*/
public function decrement($key, $amount = 1)
{
return $this->increment($key, $amount * -1);
}
/**
* Flash a key / value pair to the session.
*

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -4,6 +4,7 @@ namespace Illuminate\Support;
use Countable;
use ArrayAccess;
use Traversable;
use ArrayIterator;
use CachingIterator;
use JsonSerializable;
@@ -80,6 +81,65 @@ class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate
return $this->avg($key);
}
/**
* Get the median of a given key.
*
* @param null $key
* @return mixed|null
*/
public function median($key = null)
{
$count = $this->count();
if ($count == 0) {
return;
}
$values = with(isset($key) ? $this->pluck($key) : $this)
->sort()->values();
$middle = (int) floor($count / 2);
if ($count % 2) {
return $values->get($middle);
}
return (new static([
$values->get($middle - 1), $values->get($middle),
]))->average();
}
/**
* Get the mode of a given key.
*
* @param null $key
* @return array
*/
public function mode($key = null)
{
$count = $this->count();
if ($count == 0) {
return;
}
$collection = isset($key) ? $this->pluck($key) : $this;
$counts = new self;
$collection->each(function ($value) use ($counts) {
$counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
});
$sorted = $counts->sort();
$highestValue = $sorted->last();
return $sorted->filter(function ($value) use ($highestValue) {
return $value == $highestValue;
})->sort()->keys()->all();
}
/**
* Collapse the collection of items into a single array.
*
@@ -604,6 +664,17 @@ class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate
return $this->slice(($page - 1) * $perPage, $perPage);
}
/**
* Pass the collection to the given callback and return the result.
*
* @param callable $callback
* @return mixed
*/
public function pipe(callable $callback)
{
return $callback($this);
}
/**
* Get and remove the last item from the collection.
*
@@ -766,13 +837,22 @@ class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate
/**
* Shuffle the items in the collection.
*
* @param int $seed
* @return static
*/
public function shuffle()
public function shuffle($seed = null)
{
$items = $this->items;
shuffle($items);
if (is_null($seed)) {
shuffle($items);
} else {
srand($seed);
usort($items, function () {
return rand(-1, 1);
});
}
return new static($items);
}
@@ -1162,6 +1242,8 @@ class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate
return json_decode($items->toJson(), true);
} elseif ($items instanceof JsonSerializable) {
return $items->jsonSerialize();
} elseif ($items instanceof Traversable) {
return iterator_to_array($items);
}
return (array) $items;

View File

@@ -96,14 +96,43 @@ class MessageBag implements Arrayable, Countable, Jsonable, JsonSerializable, Me
}
/**
* Determine if messages exist for a given key.
* Determine if messages exist for all of the given keys.
*
* @param string $key
* @param array|string $key
* @return bool
*/
public function has($key = null)
{
return $this->first($key) !== '';
if (is_null($key)) {
return $this->any();
}
$keys = is_array($key) ? $key : func_get_args();
foreach ($keys as $key) {
if ($this->first($key) === '') {
return false;
}
}
return true;
}
/**
* Determine if messages exist for any of the given keys.
*
* @param array $keys
* @return bool
*/
public function hasAny($keys = [])
{
foreach ($keys as $key) {
if ($this->has($key)) {
return true;
}
}
return false;
}
/**

View File

@@ -32,6 +32,7 @@ class Pluralizer
'nutrition',
'offspring',
'plankton',
'pokemon',
'police',
'rice',
'series',
@@ -50,7 +51,7 @@ class Pluralizer
*/
public static function plural($value, $count = 2)
{
if ($count === 1 || static::uncountable($value)) {
if ((int) $count === 1 || static::uncountable($value)) {
return $value;
}

View File

@@ -48,15 +48,15 @@ trait Macroable
*/
public static function __callStatic($method, $parameters)
{
if (static::hasMacro($method)) {
if (static::$macros[$method] instanceof Closure) {
return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
} else {
return call_user_func_array(static::$macros[$method], $parameters);
}
if (! static::hasMacro($method)) {
throw new BadMethodCallException("Method {$method} does not exist.");
}
throw new BadMethodCallException("Method {$method} does not exist.");
if (static::$macros[$method] instanceof Closure) {
return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
}
return call_user_func_array(static::$macros[$method], $parameters);
}
/**
@@ -70,14 +70,14 @@ trait Macroable
*/
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
if (static::$macros[$method] instanceof Closure) {
return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters);
} else {
return call_user_func_array(static::$macros[$method], $parameters);
}
if (! static::hasMacro($method)) {
throw new BadMethodCallException("Method {$method} does not exist.");
}
throw new BadMethodCallException("Method {$method} does not exist.");
if (static::$macros[$method] instanceof Closure) {
return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters);
}
return call_user_func_array(static::$macros[$method], $parameters);
}
}

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {
@@ -20,6 +20,9 @@
"illuminate/contracts": "5.2.*",
"paragonie/random_compat": "~1.4"
},
"replace": {
"tightenco/collect": "self.version"
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""

View File

@@ -158,8 +158,8 @@ class Translator extends NamespacedItemResolver implements TranslatorInterface
foreach ($replace as $key => $value) {
$line = str_replace(
[':'.Str::upper($key), ':'.Str::ucfirst($key), ':'.$key],
[Str::upper($value), Str::ucfirst($value), $value],
[':'.$key, ':'.Str::upper($key), ':'.Str::ucfirst($key)],
[$value, Str::upper($value), Str::ucfirst($value)],
$line
);
}

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -2,8 +2,8 @@
namespace Illuminate\Validation;
use Illuminate\Contracts\Validation\ValidationException;
use Illuminate\Contracts\Validation\UnauthorizedException;
use Illuminate\Contracts\Validation\ValidationException as ValidationExceptionContract;
/**
* Provides default implementation of ValidatesWhenResolved contract.
@@ -46,7 +46,7 @@ trait ValidatesWhenResolvedTrait
*/
protected function failedValidation(Validator $validator)
{
throw new ValidationException($validator);
throw new ValidationExceptionContract($validator);
}
/**

View File

@@ -498,7 +498,9 @@ class Validator implements ValidatorContract
$this->passes();
}
return array_diff_key($this->data, $this->messages()->toArray());
return array_diff_key(
$this->data, $this->attributesThatHaveMessages()
);
}
/**
@@ -512,7 +514,25 @@ class Validator implements ValidatorContract
$this->passes();
}
return array_intersect_key($this->data, $this->messages()->toArray());
return array_intersect_key(
$this->data, $this->attributesThatHaveMessages()
);
}
/**
* Generate an array of all attributes that have messages.
*
* @return array
*/
protected function attributesThatHaveMessages()
{
$results = [];
foreach ($this->messages()->toArray() as $key => $message) {
$results[] = explode('.', $key)[0];
}
return array_flip(array_unique($results));
}
/**
@@ -1221,6 +1241,12 @@ class Validator implements ValidatorContract
protected function validateIn($attribute, $value, $parameters)
{
if (is_array($value) && $this->hasRule($attribute, 'Array')) {
foreach ($value as $element) {
if (is_array($element)) {
return false;
}
}
return count(array_diff($value, $parameters)) == 0;
}
@@ -1296,6 +1322,10 @@ class Validator implements ValidatorContract
if (strtolower($id) == 'null') {
$id = null;
}
if (filter_var($id, FILTER_VALIDATE_INT) !== false) {
$id = intval($id);
}
}
// The presence verifier is responsible for counting rows within this store
@@ -1504,7 +1534,7 @@ class Validator implements ValidatorContract
(/?|/\S+|\?\S*|\#\S*) # a /, nothing, a / with something, a query or a fragment
$~ixu';
return preg_match($pattern, $value) === 1;
return preg_match($pattern, $value) > 0;
}
/**
@@ -1561,7 +1591,7 @@ class Validator implements ValidatorContract
*/
protected function validateDimensions($attribute, $value, $parameters)
{
if (! $sizeDetails = getimagesize($value->getRealPath())) {
if (! $this->isAValidFileInstance($value) || ! $sizeDetails = getimagesize($value->getRealPath())) {
return false;
}
@@ -1665,7 +1695,7 @@ class Validator implements ValidatorContract
return false;
}
return preg_match('/^[\pL\pM\pN]+$/u', $value);
return preg_match('/^[\pL\pM\pN]+$/u', $value) > 0;
}
/**
@@ -1681,7 +1711,7 @@ class Validator implements ValidatorContract
return false;
}
return preg_match('/^[\pL\pM\pN_-]+$/u', $value);
return preg_match('/^[\pL\pM\pN_-]+$/u', $value) > 0;
}
/**
@@ -1700,7 +1730,7 @@ class Validator implements ValidatorContract
$this->requireParameterCount(1, $parameters, 'regex');
return preg_match($parameters[0], $value);
return preg_match($parameters[0], $value) > 0;
}
/**
@@ -2073,8 +2103,8 @@ class Validator implements ValidatorContract
$value = $this->getAttribute($attribute);
$message = str_replace(
[':ATTRIBUTE', ':Attribute', ':attribute'],
[Str::upper($value), Str::ucfirst($value), $value],
[':attribute', ':ATTRIBUTE', ':Attribute'],
[$value, Str::upper($value), Str::ucfirst($value)],
$message
);

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {

View File

@@ -331,7 +331,7 @@ class BladeCompiler extends Compiler implements CompilerInterface
return isset($match[3]) ? $match[0] : $match[0].$match[2];
};
return preg_replace_callback('/\B@(@?\w+)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', $callback, $value);
return preg_replace_callback('/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', $callback, $value);
}
/**

View File

@@ -2,6 +2,7 @@
namespace Illuminate\View\Compilers;
use InvalidArgumentException;
use Illuminate\Filesystem\Filesystem;
abstract class Compiler
@@ -26,9 +27,15 @@ abstract class Compiler
* @param \Illuminate\Filesystem\Filesystem $files
* @param string $cachePath
* @return void
*
* @throws \InvalidArgumentException
*/
public function __construct(Filesystem $files, $cachePath)
{
if (! $cachePath) {
throw new InvalidArgumentException('Please provide a valid cache path.');
}
$this->files = $files;
$this->cachePath = $cachePath;
}
@@ -57,7 +64,7 @@ abstract class Compiler
// If the compiled file doesn't exist we will indicate that the view is expired
// so that it can be re-compiled. Else, we will verify the last modification
// of the views is less than the modification times of the compiled views.
if (! $this->cachePath || ! $this->files->exists($compiled)) {
if (! $this->files->exists($compiled)) {
return true;
}

View File

@@ -10,7 +10,7 @@
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
"email": "taylor@laravel.com"
}
],
"require": {