dep: package update

This commit is contained in:
2021-11-08 16:10:01 +09:00
parent 38208750e7
commit 2c533d2ab3
783 changed files with 4581 additions and 20980 deletions
+2 -5
View File
@@ -7,7 +7,6 @@ use Closure;
use Illuminate\Contracts\Queue\Factory as QueueFactory;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Queue\CallQueuedClosure;
use Illuminate\Queue\SerializableClosure;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use JsonSerializable;
@@ -420,7 +419,7 @@ class Batch implements Arrayable, JsonSerializable
/**
* Invoke a batch callback handler.
*
* @param \Illuminate\Queue\SerializableClosure|callable $handler
* @param callable $handler
* @param \Illuminate\Bus\Batch $batch
* @param \Throwable|null $e
* @return void
@@ -428,9 +427,7 @@ class Batch implements Arrayable, JsonSerializable
protected function invokeHandlerCallback($handler, Batch $batch, Throwable $e = null)
{
try {
return $handler instanceof SerializableClosure
? $handler->__invoke($batch, $e)
: call_user_func($handler, $batch, $e);
return $handler($batch, $e);
} catch (Throwable $e) {
if (function_exists('report')) {
report($e);
+4 -4
View File
@@ -6,7 +6,7 @@ use Closure;
use Illuminate\Bus\Events\BatchDispatched;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher as EventDispatcher;
use Illuminate\Queue\SerializableClosure;
use Illuminate\Queue\SerializableClosureFactory;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Throwable;
@@ -78,7 +78,7 @@ class PendingBatch
public function then($callback)
{
$this->options['then'][] = $callback instanceof Closure
? new SerializableClosure($callback)
? SerializableClosureFactory::make($callback)
: $callback;
return $this;
@@ -103,7 +103,7 @@ class PendingBatch
public function catch($callback)
{
$this->options['catch'][] = $callback instanceof Closure
? new SerializableClosure($callback)
? SerializableClosureFactory::make($callback)
: $callback;
return $this;
@@ -128,7 +128,7 @@ class PendingBatch
public function finally($callback)
{
$this->options['finally'][] = $callback instanceof Closure
? new SerializableClosure($callback)
? SerializableClosureFactory::make($callback)
: $callback;
return $this;
+1 -2
View File
@@ -4,7 +4,6 @@ namespace Illuminate\Bus;
use Closure;
use Illuminate\Queue\CallQueuedClosure;
use Illuminate\Queue\SerializableClosure;
use Illuminate\Support\Arr;
use RuntimeException;
@@ -245,7 +244,7 @@ trait Queueable
public function invokeChainCatchCallbacks($e)
{
collect($this->chainCatchCallbacks)->each(function ($callback) use ($e) {
$callback instanceof SerializableClosure ? $callback->__invoke($e) : call_user_func($callback, $e);
$callback($e);
});
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php
namespace Illuminate\Bus;
use Illuminate\Contracts\Cache\Repository as Cache;
class UniqueLock
{
/**
* The cache repository implementation.
*
* @var \Illuminate\Contracts\Cache\Repository
*/
protected $cache;
/**
* Create a new unique lock manager instance.
*
* @param \Illuminate\Contracts\Cache\Repository $cache
* @return void
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
/**
* Attempt to acquire a lock for the given job.
*
* @param mixed $job
* @return bool
*/
public function acquire($job)
{
$uniqueId = method_exists($job, 'uniqueId')
? $job->uniqueId()
: ($job->uniqueId ?? '');
$cache = method_exists($job, 'uniqueVia')
? $job->uniqueVia()
: $this->cache;
return (bool) $cache->lock(
$key = 'laravel_unique_job:'.get_class($job).$uniqueId,
$job->uniqueFor ?? 0
)->get();
}
}
+13
View File
@@ -393,6 +393,19 @@ class Arr
return array_keys($keys) !== $keys;
}
/**
* Determines if an array is a list.
*
* An array is a "list" if all array keys are sequential integers starting from 0 with no gaps in between.
*
* @param array $array
* @return bool
*/
public static function isList($array)
{
return ! self::isAssoc($array);
}
/**
* Get a subset of the items from the given array.
*
+47 -1
View File
@@ -4,11 +4,12 @@ namespace Illuminate\Support;
use ArrayAccess;
use ArrayIterator;
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
use Illuminate\Support\Traits\EnumeratesValues;
use Illuminate\Support\Traits\Macroable;
use stdClass;
class Collection implements ArrayAccess, Enumerable
class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerable
{
use EnumeratesValues, Macroable;
@@ -501,6 +502,29 @@ class Collection implements ArrayAccess, Enumerable
return true;
}
/**
* Determine if any of the keys exist in the collection.
*
* @param mixed $key
* @return bool
*/
public function hasAny($key)
{
if ($this->isEmpty()) {
return false;
}
$keys = is_array($key) ? $key : func_get_args();
foreach ($keys as $value) {
if ($this->has($value)) {
return true;
}
}
return false;
}
/**
* Concatenate values of a given key as a string.
*
@@ -1411,6 +1435,28 @@ class Collection implements ArrayAccess, Enumerable
return $this;
}
/**
* Return only unique items from the collection array.
*
* @param string|callable|null $key
* @param bool $strict
* @return static
*/
public function unique($key = null, $strict = false)
{
$callback = $this->valueRetriever($key);
$exists = [];
return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
if (in_array($id = $callback($item, $key), $exists, $strict)) {
return true;
}
$exists[] = $id;
});
}
/**
* Reset the keys on the underlying array.
*
+45 -1
View File
@@ -5,12 +5,13 @@ namespace Illuminate\Support;
use ArrayIterator;
use Closure;
use DateTimeInterface;
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
use Illuminate\Support\Traits\EnumeratesValues;
use Illuminate\Support\Traits\Macroable;
use IteratorAggregate;
use stdClass;
class LazyCollection implements Enumerable
class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
{
use EnumeratesValues, Macroable;
@@ -512,6 +513,25 @@ class LazyCollection implements Enumerable
return false;
}
/**
* Determine if any of the keys exist in the collection.
*
* @param mixed $key
* @return bool
*/
public function hasAny($key)
{
$keys = array_flip(is_array($key) ? $key : func_get_args());
foreach ($this as $key => $value) {
if (array_key_exists($key, $keys)) {
return true;
}
}
return false;
}
/**
* Concatenate values of a given key as a string.
*
@@ -1352,6 +1372,30 @@ class LazyCollection implements Enumerable
});
}
/**
* Return only unique items from the collection array.
*
* @param string|callable|null $key
* @param bool $strict
* @return static
*/
public function unique($key = null, $strict = false)
{
$callback = $this->valueRetriever($key);
return new static(function () use ($callback, $strict) {
$exists = [];
foreach ($this as $key => $item) {
if (! in_array($id = $callback($item, $key), $exists, $strict)) {
yield $key => $item;
$exists[] = $id;
}
}
});
}
/**
* Reset the keys on the underlying array.
*
+67 -23
View File
@@ -15,6 +15,7 @@ use Illuminate\Support\HigherOrderWhenProxy;
use JsonSerializable;
use Symfony\Component\VarDumper\VarDumper;
use Traversable;
use UnexpectedValueException;
/**
* @property-read HigherOrderCollectionProxy $average
@@ -45,6 +46,13 @@ use Traversable;
*/
trait EnumeratesValues
{
/**
* Indicates that the object's string representation should be escaped when __toString is invoked.
*
* @var bool
*/
protected $escapeWhenCastingToString = false;
/**
* The methods that can be proxied.
*
@@ -744,6 +752,49 @@ trait EnumeratesValues
return $result;
}
/**
* Reduce the collection to multiple aggregate values.
*
* @param callable $callback
* @param mixed ...$initial
* @return array
*
* @deprecated Use "reduceSpread" instead
*
* @throws \UnexpectedValueException
*/
public function reduceMany(callable $callback, ...$initial)
{
return $this->reduceSpread($callback, ...$initial);
}
/**
* Reduce the collection to multiple aggregate values.
*
* @param callable $callback
* @param mixed ...$initial
* @return array
*
* @throws \UnexpectedValueException
*/
public function reduceSpread(callable $callback, ...$initial)
{
$result = $initial;
foreach ($this as $key => $value) {
$result = call_user_func_array($callback, array_merge($result, [$value, $key]));
if (! is_array($result)) {
throw new UnexpectedValueException(sprintf(
"%s::reduceMany expects reducer to return an array, but got a '%s' instead.",
class_basename(static::class), gettype($result)
));
}
}
return $result;
}
/**
* Reduce an associative collection to a single value.
*
@@ -773,28 +824,6 @@ trait EnumeratesValues
});
}
/**
* Return only unique items from the collection array.
*
* @param string|callable|null $key
* @param bool $strict
* @return static
*/
public function unique($key = null, $strict = false)
{
$callback = $this->valueRetriever($key);
$exists = [];
return $this->reject(function ($item, $key) use ($callback, $strict, &$exists) {
if (in_array($id = $callback($item, $key), $exists, $strict)) {
return true;
}
$exists[] = $id;
});
}
/**
* Return only unique items from the collection array using strict comparison.
*
@@ -878,7 +907,22 @@ trait EnumeratesValues
*/
public function __toString()
{
return $this->toJson();
return $this->escapeWhenCastingToString
? e($this->toJson())
: $this->toJson();
}
/**
* Indicate that the model's string representation should be escaped when __toString is invoked.
*
* @param bool $escape
* @return $this
*/
public function escapeWhenCastingToString($escape = true)
{
$this->escapeWhenCastingToString = $escape;
return $this;
}
/**
+6 -2
View File
@@ -187,7 +187,9 @@ class Container implements ArrayAccess, ContainerContract
}
/**
* {@inheritdoc}
* {@inheritdoc}
*
* @return bool
*/
public function has($id)
{
@@ -693,7 +695,9 @@ class Container implements ArrayAccess, ContainerContract
}
/**
* {@inheritdoc}
* {@inheritdoc}
*
* @return mixed
*/
public function get($id)
{
+1 -1
View File
@@ -53,7 +53,7 @@ class Util
$type = $parameter->getType();
if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) {
return;
return null;
}
$name = $type->getName();
@@ -0,0 +1,14 @@
<?php
namespace Illuminate\Contracts\Support;
interface CanBeEscapedWhenCastToString
{
/**
* Indicate that the object's string representation should be escaped when __toString is invoked.
*
* @param bool $escape
* @return $this
*/
public function escapeWhenCastingToString($escape = true);
}
+24
View File
@@ -161,6 +161,13 @@ class Connection implements ConnectionInterface
*/
protected $pretending = false;
/**
* All of the callbacks that should be invoked before a query is executed.
*
* @var array
*/
protected $beforeExecutingCallbacks = [];
/**
* The instance of Doctrine connection.
*
@@ -641,6 +648,10 @@ class Connection implements ConnectionInterface
*/
protected function run($query, $bindings, Closure $callback)
{
foreach ($this->beforeExecutingCallbacks as $beforeExecutingCallback) {
$beforeExecutingCallback($query, $bindings, $this);
}
$this->reconnectIfMissingConnection();
$start = microtime(true);
@@ -807,6 +818,19 @@ class Connection implements ConnectionInterface
$this->setPdo(null)->setReadPdo(null);
}
/**
* Register a hook to be run just before a database query is executed.
*
* @param \Closure $callback
* @return $this
*/
public function beforeExecuting(Closure $callback)
{
$this->beforeExecutingCallbacks[] = $callback;
return $this;
}
/**
* Register a database query listener with the connection.
*
@@ -3,17 +3,9 @@
namespace {{ factoryNamespace }};
use Illuminate\Database\Eloquent\Factories\Factory;
use {{ namespacedModel }};
class {{ factory }}Factory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = {{ model }}::class;
/**
* Define the model's default state.
*
+33 -2
View File
@@ -19,7 +19,8 @@ class PruneCommand extends Command
*/
protected $signature = 'model:prune
{--model=* : Class names of the models to be pruned}
{--chunk=1000 : The number of models to retrieve per chunk of models to be deleted}';
{--chunk=1000 : The number of models to retrieve per chunk of models to be deleted}
{--pretend : Display the number of prunable records found instead of deleting them}';
/**
* The console command description.
@@ -44,6 +45,14 @@ class PruneCommand extends Command
return;
}
if ($this->option('pretend')) {
$models->each(function ($model) {
$this->pretendToPrune($model);
});
return;
}
$events->listen(ModelsPruned::class, function ($event) {
$this->info("{$event->count} [{$event->model}] records have been pruned.");
});
@@ -78,7 +87,7 @@ class PruneCommand extends Command
return collect($models);
}
return collect((new Finder)->in(app_path('Models'))->files())
return collect((new Finder)->in(app_path('Models'))->files()->name('*.php'))
->map(function ($model) {
$namespace = $this->laravel->getNamespace();
@@ -104,4 +113,26 @@ class PruneCommand extends Command
return in_array(Prunable::class, $uses) || in_array(MassPrunable::class, $uses);
}
/**
* Display how many models will be pruned.
*
* @param string $model
* @return void
*/
protected function pretendToPrune($model)
{
$instance = new $model;
$count = $instance->prunable()
->when(in_array(SoftDeletes::class, class_uses_recursive(get_class($instance))), function ($query) {
$query->withTrashed();
})->count();
if ($count === 0) {
$this->info("No prunable [$model] records found.");
} else {
$this->info("{$count} [{$model}] records will be pruned.");
}
}
}
+6 -1
View File
@@ -4,12 +4,15 @@ namespace Illuminate\Database\DBAL;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\PhpDateTimeMappingType;
use Doctrine\DBAL\Types\Type;
class TimestampType extends Type
class TimestampType extends Type implements PhpDateTimeMappingType
{
/**
* {@inheritdoc}
*
* @return string
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
@@ -97,6 +100,8 @@ class TimestampType extends Type
/**
* {@inheritdoc}
*
* @return string
*/
public function getName()
{
+1 -1
View File
@@ -16,7 +16,7 @@ trait DetectsConcurrencyErrors
*/
protected function causedByConcurrencyError(Throwable $e)
{
if ($e instanceof PDOException && $e->getCode() === '40001') {
if ($e instanceof PDOException && ($e->getCode() === 40001 || $e->getCode() === '40001')) {
return true;
}
+2
View File
@@ -54,6 +54,8 @@ trait DetectsLostConnections
'SQLSTATE[08S01]: Communication link failure',
'SQLSTATE[08006] [7] could not connect to server: Connection refused Is the server running on host',
'SQLSTATE[HY000]: General error: 7 SSL SYSCALL error: No route to host',
'The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior.',
'SQLSTATE[08006] [7] could not translate host name',
]);
}
}
@@ -0,0 +1,32 @@
<?php
namespace Illuminate\Database\Eloquent\Casts;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Support\Str;
class AsStringable implements Castable
{
/**
* Get the caster class to use when casting from / to this cast target.
*
* @param array $arguments
* @return object|string
*/
public static function castUsing(array $arguments)
{
return new class implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return isset($value) ? Str::of($value) : null;
}
public function set($model, $key, $value, $attributes)
{
return isset($value) ? (string) $value : null;
}
};
}
}
@@ -8,6 +8,8 @@ use DateTimeInterface;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\AsCollection;
use Illuminate\Database\Eloquent\InvalidCastException;
use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Database\Eloquent\Relations\Relation;
@@ -262,6 +264,10 @@ trait HasAttributes
$attributes[$key] = $this->serializeClassCastableAttribute($key, $attributes[$key]);
}
if ($this->isEnumCastable($key)) {
$attributes[$key] = isset($attributes[$key]) ? $attributes[$key]->value : null;
}
if ($attributes[$key] instanceof Arrayable) {
$attributes[$key] = $attributes[$key]->toArray();
}
@@ -620,6 +626,10 @@ trait HasAttributes
return $this->asTimestamp($value);
}
if ($this->isEnumCastable($key)) {
return $this->getEnumCastableAttributeValue($key, $value);
}
if ($this->isClassCastable($key)) {
return $this->getClassCastableAttributeValue($key, $value);
}
@@ -655,6 +665,24 @@ trait HasAttributes
}
}
/**
* Cast the given attribute to an enum.
*
* @param string $key
* @param mixed $value
* @return mixed
*/
protected function getEnumCastableAttributeValue($key, $value)
{
if (is_null($value)) {
return;
}
$castType = $this->getCasts()[$key];
return $castType::from($value);
}
/**
* Get the type of cast for a model attribute.
*
@@ -765,6 +793,12 @@ trait HasAttributes
$value = $this->fromDateTime($value);
}
if ($this->isEnumCastable($key)) {
$this->setEnumCastableAttribute($key, $value);
return $this;
}
if ($this->isClassCastable($key)) {
$this->setClassCastableAttribute($key, $value);
@@ -883,6 +917,18 @@ trait HasAttributes
}
}
/**
* Set the value of an enum castable attribute.
*
* @param string $key
* @param \BackedEnum $value
* @return void
*/
protected function setEnumCastableAttribute($key, $value)
{
$this->attributes[$key] = isset($value) ? $value->value : null;
}
/**
* Get an array attribute with the given key and value set.
*
@@ -1217,7 +1263,18 @@ trait HasAttributes
*/
protected function isDateCastable($key)
{
return $this->hasCast($key, ['date', 'datetime', 'custom_datetime', 'immutable_date', 'immutable_datetime', 'immutable_custom_datetime']);
return $this->hasCast($key, ['date', 'datetime', 'immutable_date', 'immutable_datetime']);
}
/**
* Determine whether a value is Date / DateTime custom-castable for inbound manipulation.
*
* @param string $key
* @return bool
*/
protected function isDateCastableWithCustomFormat($key)
{
return $this->hasCast($key, ['custom_datetime', 'immutable_custom_datetime']);
}
/**
@@ -1269,6 +1326,29 @@ trait HasAttributes
throw new InvalidCastException($this->getModel(), $key, $castType);
}
/**
* Determine if the given key is cast using an enum.
*
* @param string $key
* @return bool
*/
protected function isEnumCastable($key)
{
if (! array_key_exists($key, $this->getCasts())) {
return false;
}
$castType = $this->getCasts()[$key];
if (in_array($castType, static::$primitiveCastTypes)) {
return false;
}
if (function_exists('enum_exists') && enum_exists($castType)) {
return true;
}
}
/**
* Determine if the key is deviable using a custom class.
*
@@ -1294,8 +1374,9 @@ trait HasAttributes
*/
protected function isClassSerializable($key)
{
return $this->isClassCastable($key) &&
method_exists($this->parseCasterClass($this->getCasts()[$key]), 'serialize');
return ! $this->isEnumCastable($key) &&
$this->isClassCastable($key) &&
method_exists($this->resolveCasterClass($key), 'serialize');
}
/**
@@ -1643,7 +1724,7 @@ trait HasAttributes
return true;
} elseif (is_null($attribute)) {
return false;
} elseif ($this->isDateAttribute($key) || $this->isDateCastable($key)) {
} elseif ($this->isDateAttribute($key) || $this->isDateCastableWithCustomFormat($key)) {
return $this->fromDateTime($attribute) ===
$this->fromDateTime($original);
} elseif ($this->hasCast($key, ['object', 'collection'])) {
@@ -1658,6 +1739,8 @@ trait HasAttributes
} elseif ($this->hasCast($key, static::$primitiveCastTypes)) {
return $this->castAttribute($key, $attribute) ===
$this->castAttribute($key, $original);
} elseif ($this->isClassCastable($key) && in_array($this->getCasts()[$key], [AsArrayObject::class, AsCollection::class])) {
return $this->fromJson($attribute) === $this->fromJson($original);
}
return is_numeric($attribute) && is_numeric($original)
@@ -2,8 +2,11 @@
namespace Illuminate\Database\Eloquent\Concerns;
use BadMethodCallException;
use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\RelationNotFoundException;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Builder as QueryBuilder;
@@ -455,6 +458,56 @@ trait QueriesRelationships
return $this->whereMorphedTo($relation, $model, 'or');
}
/**
* Add a "belongs to" relationship where clause to the query.
*
* @param \Illuminate\Database\Eloquent\Model $related
* @param string $relationship
* @param string $boolean
* @return $this
*
* @throws \Exception
*/
public function whereBelongsTo($related, $relationshipName = null, $boolean = 'and')
{
if ($relationshipName === null) {
$relationshipName = Str::camel(class_basename($related));
}
try {
$relationship = $this->model->{$relationshipName}();
} catch (BadMethodCallException $exception) {
throw RelationNotFoundException::make($this->model, $relationshipName);
}
if (! $relationship instanceof BelongsTo) {
throw RelationNotFoundException::make($this->model, $relationshipName, BelongsTo::class);
}
$this->where(
$relationship->getQualifiedForeignKeyName(),
'=',
$related->getAttributeValue($relationship->getOwnerKeyName()),
$boolean,
);
return $this;
}
/**
* Add an "BelongsTo" relationship with an "or where" clause to the query.
*
* @param \Illuminate\Database\Eloquent\Model $related
* @param string $relationship
* @return $this
*
* @throws \Exception
*/
public function orWhereBelongsTo($related, $relationshipName = null)
{
return $this->whereBelongsTo($related, $relationshipName, 'or');
}
/**
* Add subselect queries to include an aggregate value for a relationship.
*
+3 -2
View File
@@ -10,20 +10,21 @@ use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\Macroable;
use Throwable;
abstract class Factory
{
use ForwardsCalls, Macroable {
use Conditionable, ForwardsCalls, Macroable {
__call as macroCall;
}
/**
* The name of the factory's corresponding model.
*
* @var string
* @var string|null
*/
protected $model;
+25 -2
View File
@@ -8,6 +8,7 @@ use Illuminate\Contracts\Queue\QueueableCollection;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Database\ConnectionResolverInterface as Resolver;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
@@ -22,7 +23,7 @@ use Illuminate\Support\Traits\ForwardsCalls;
use JsonSerializable;
use LogicException;
abstract class Model implements Arrayable, ArrayAccess, HasBroadcastChannel, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToString, HasBroadcastChannel, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
{
use Concerns\HasAttributes,
Concerns\HasEvents,
@@ -110,6 +111,13 @@ abstract class Model implements Arrayable, ArrayAccess, HasBroadcastChannel, Jso
*/
public $wasRecentlyCreated = false;
/**
* Indicates that the object's string representation should be escaped when __toString is invoked.
*
* @var bool
*/
protected $escapeWhenCastingToString = false;
/**
* The connection resolver instance.
*
@@ -2128,7 +2136,22 @@ abstract class Model implements Arrayable, ArrayAccess, HasBroadcastChannel, Jso
*/
public function __toString()
{
return $this->toJson();
return $this->escapeWhenCastingToString
? e($this->toJson())
: $this->toJson();
}
/**
* Indicate that the object's string representation should be escaped when __toString is invoked.
*
* @param bool $escape
* @return $this
*/
public function escapeWhenCastingToString($escape = true)
{
$this->escapeWhenCastingToString = $escape;
return $this;
}
/**
@@ -25,13 +25,18 @@ class RelationNotFoundException extends RuntimeException
*
* @param object $model
* @param string $relation
* @param string|null $type
* @return static
*/
public static function make($model, $relation)
public static function make($model, $relation, $type = null)
{
$class = get_class($model);
$instance = new static("Call to undefined relationship [{$relation}] on model [{$class}].");
$instance = new static(
is_null($type)
? "Call to undefined relationship [{$relation}] on model [{$class}]."
: "Call to undefined relationship [{$relation}] on model [{$class}] of type [{$type}].",
);
$instance->model = $class;
$instance->relation = $relation;
@@ -277,7 +277,7 @@ class BelongsToMany extends Relation
// Once we have an array dictionary of child objects we can easily match the
// children back to their parent using the dictionary and the keys on the
// the parent models. Then we will return the hydrated models back out.
// parent models. Then we should return these hydrated models back out.
foreach ($models as $model) {
$key = $this->getDictionaryKey($model->{$this->parentKey});
@@ -102,7 +102,9 @@ trait CanBeOneOfMany
if (isset($previous)) {
$this->addOneOfManyJoinSubQuery($subQuery, $previous['subQuery'], $previous['column']);
} elseif (isset($closure)) {
}
if (isset($closure)) {
$closure($subQuery);
}
@@ -122,6 +124,12 @@ trait CanBeOneOfMany
$this->addConstraints();
$columns = $this->query->getQuery()->columns;
if (is_null($columns) || $columns === ['*']) {
$this->select([$this->qualifyColumn('*')]);
}
return $this;
}
@@ -137,7 +145,7 @@ trait CanBeOneOfMany
{
return $this->ofMany(collect(Arr::wrap($column))->mapWithKeys(function ($column) {
return [$column => 'MAX'];
})->all(), 'MAX', $relation ?: $this->guessRelationship());
})->all(), 'MAX', $relation);
}
/**
@@ -152,7 +160,7 @@ trait CanBeOneOfMany
{
return $this->ofMany(collect(Arr::wrap($column))->mapWithKeys(function ($column) {
return [$column => 'MIN'];
})->all(), 'MIN', $relation ?: $this->guessRelationship());
})->all(), 'MIN', $relation);
}
/**
@@ -179,14 +187,15 @@ trait CanBeOneOfMany
protected function newOneOfManySubQuery($groupBy, $column = null, $aggregate = null)
{
$subQuery = $this->query->getModel()
->newQuery();
->newQuery()
->withoutGlobalScopes($this->removedScopes());
foreach (Arr::wrap($groupBy) as $group) {
$subQuery->groupBy($this->qualifyRelatedColumn($group));
}
if (! is_null($column)) {
$subQuery->selectRaw($aggregate.'('.$subQuery->getQuery()->grammar->wrap($column).') as '.$subQuery->getQuery()->grammar->wrap($column));
$subQuery->selectRaw($aggregate.'('.$subQuery->getQuery()->grammar->wrap($subQuery->qualifyColumn($column)).') as '.$subQuery->getQuery()->grammar->wrap($column.'_aggregate'));
}
$this->addOneOfManySubQueryConstraints($subQuery, $groupBy, $column, $aggregate);
@@ -208,7 +217,7 @@ trait CanBeOneOfMany
$subQuery->applyBeforeQueryCallbacks();
$parent->joinSub($subQuery, $this->relationName, function ($join) use ($on) {
$join->on($this->qualifySubSelectColumn($on), '=', $this->qualifyRelatedColumn($on));
$join->on($this->qualifySubSelectColumn($on.'_aggregate'), '=', $this->qualifyRelatedColumn($on));
$this->addOneOfManyJoinSubQueryConstraints($join, $on);
});
+1 -1
View File
@@ -407,7 +407,7 @@ abstract class Relation
/**
* Define the morph map for polymorphic relations and require all morphed models to be explicitly mapped.
*
* @param array|null $map
* @param array $map
* @param bool $merge
* @return array
*/
+3
View File
@@ -6,6 +6,9 @@ use Doctrine\DBAL\Driver\AbstractSQLServerDriver;
class SqlServerDriver extends AbstractSQLServerDriver
{
/**
* @return \Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params)
{
return new SqlServerConnection(
+27 -5
View File
@@ -20,6 +20,7 @@ use Illuminate\Support\Str;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
use LogicException;
use RuntimeException;
class Builder
@@ -1960,7 +1961,7 @@ class Builder
/**
* Add an "order by" clause to the query.
*
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @param string $direction
* @return $this
*
@@ -1993,7 +1994,7 @@ class Builder
/**
* Add a descending "order by" clause to the query.
*
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @return $this
*/
public function orderByDesc($column)
@@ -2004,7 +2005,7 @@ class Builder
/**
* Add an "order by" clause for a timestamp to the query.
*
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @return $this
*/
public function latest($column = 'created_at')
@@ -2015,7 +2016,7 @@ class Builder
/**
* Add an "order by" clause for a timestamp to the query.
*
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
* @return $this
*/
public function oldest($column = 'created_at')
@@ -3000,6 +3001,27 @@ class Builder
));
}
/**
* Update records in a PostgreSQL database using the update from syntax.
*
* @param array $values
* @return int
*/
public function updateFrom(array $values)
{
if (! method_exists($this->grammar, 'compileUpdateFrom')) {
throw new LogicException('This database engine does not support the updateFrom method.');
}
$this->applyBeforeQueryCallbacks();
$sql = $this->grammar->compileUpdateFrom($this, $values);
return $this->connection->update($sql, $this->cleanBindings(
$this->grammar->prepareBindingsForUpdateFrom($this->bindings, $values)
));
}
/**
* Insert or update a record matching the attributes, and fill it with values.
*
@@ -3402,7 +3424,7 @@ class Builder
/**
* Die and dump the current SQL and bindings.
*
* @return void
* @return never
*/
public function dd()
{
@@ -260,6 +260,114 @@ class PostgresGrammar extends Grammar
return "{$field} = jsonb_set({$field}::jsonb, {$path}, {$this->parameter($value)})";
}
/**
* Compile an update from statement into SQL.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $values
* @return string
*/
public function compileUpdateFrom(Builder $query, $values)
{
$table = $this->wrapTable($query->from);
// Each one of the columns in the update statements needs to be wrapped in the
// keyword identifiers, also a place-holder needs to be created for each of
// the values in the list of bindings so we can make the sets statements.
$columns = $this->compileUpdateColumns($query, $values);
$from = '';
if (isset($query->joins)) {
// When using Postgres, updates with joins list the joined tables in the from
// clause, which is different than other systems like MySQL. Here, we will
// compile out the tables that are joined and add them to a from clause.
$froms = collect($query->joins)->map(function ($join) {
return $this->wrapTable($join->table);
})->all();
if (count($froms) > 0) {
$from = ' from '.implode(', ', $froms);
}
}
$where = $this->compileUpdateWheres($query);
return trim("update {$table} set {$columns}{$from} {$where}");
}
/**
* Compile the additional where clauses for updates with joins.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileUpdateWheres(Builder $query)
{
$baseWheres = $this->compileWheres($query);
if (! isset($query->joins)) {
return $baseWheres;
}
// Once we compile the join constraints, we will either use them as the where
// clause or append them to the existing base where clauses. If we need to
// strip the leading boolean we will do so when using as the only where.
$joinWheres = $this->compileUpdateJoinWheres($query);
if (trim($baseWheres) == '') {
return 'where '.$this->removeLeadingBoolean($joinWheres);
}
return $baseWheres.' '.$joinWheres;
}
/**
* Compile the "join" clause where clauses for an update.
*
* @param \Illuminate\Database\Query\Builder $query
* @return string
*/
protected function compileUpdateJoinWheres(Builder $query)
{
$joinWheres = [];
// Here we will just loop through all of the join constraints and compile them
// all out then implode them. This should give us "where" like syntax after
// everything has been built and then we will join it to the real wheres.
foreach ($query->joins as $join) {
foreach ($join->wheres as $where) {
$method = "where{$where['type']}";
$joinWheres[] = $where['boolean'].' '.$this->$method($query, $where);
}
}
return implode(' ', $joinWheres);
}
/**
* Prepare the bindings for an update statement.
*
* @param array $bindings
* @param array $values
* @return array
*/
public function prepareBindingsForUpdateFrom(array $bindings, array $values)
{
$values = collect($values)->map(function ($value, $column) {
return is_array($value) || ($this->isJsonSelector($column) && ! $this->isExpression($value))
? json_encode($value)
: $value;
})->all();
$bindingsWithoutWhere = Arr::except($bindings, ['select', 'where']);
return array_values(
array_merge($values, $bindings['where'], Arr::flatten($bindingsWithoutWhere))
);
}
/**
* Compile an update statement with joins or limit into SQL.
*
@@ -24,6 +24,16 @@ class ForeignKeyDefinition extends Fluent
return $this->onUpdate('cascade');
}
/**
* Indicate that updates should be restricted.
*
* @return $this
*/
public function restrictOnUpdate()
{
return $this->onUpdate('restrict');
}
/**
* Indicate that deletes should cascade.
*
@@ -198,6 +198,7 @@ class ChangeColumn
'binary',
'boolean',
'date',
'dateTime',
'decimal',
'double',
'float',
+1 -1
View File
@@ -85,7 +85,7 @@ class MySqlSchemaState extends SchemaState
*/
protected function baseDumpCommand()
{
$command = 'mysqldump '.$this->connectionString().' --skip-add-locks --skip-comments --skip-set-charset --tz-utc';
$command = 'mysqldump '.$this->connectionString().' --no-tablespaces --skip-add-locks --skip-comments --skip-set-charset --tz-utc';
if (! $this->connection->isMaria()) {
$command .= ' --column-statistics=0 --set-gtid-purged=OFF';
+1 -1
View File
@@ -58,7 +58,7 @@ abstract class SchemaState
$this->files = $files ?: new Filesystem;
$this->processFactory = $processFactory ?: function (...$arguments) {
return Process::fromShellCommandline(...$arguments);
return Process::fromShellCommandline(...$arguments)->setTimeout(null);
};
$this->handleOutputUsing(function () {
+1 -1
View File
@@ -35,7 +35,7 @@
}
},
"suggest": {
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).",
"doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.2).",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
"illuminate/console": "Required to use the database commands (^8.0).",
"illuminate/events": "Required to use the observers with Eloquent (^8.0).",
+2 -2
View File
@@ -7,7 +7,7 @@ class InvokeQueuedClosure
/**
* Handle the event.
*
* @param \Illuminate\Queue\SerializableClosure $closure
* @param \Laravel\SerializableClosure\SerializableClosure $closure
* @param array $arguments
* @return void
*/
@@ -19,7 +19,7 @@ class InvokeQueuedClosure
/**
* Handle a job failure.
*
* @param \Illuminate\Queue\SerializableClosure $closure
* @param \Laravel\SerializableClosure\SerializableClosure $closure
* @param array $arguments
* @param array $catchCallbacks
* @param \Throwable $exception
+3 -3
View File
@@ -3,7 +3,7 @@
namespace Illuminate\Events;
use Closure;
use Illuminate\Queue\SerializableClosure;
use Illuminate\Queue\SerializableClosureFactory;
class QueuedClosure
{
@@ -114,10 +114,10 @@ class QueuedClosure
{
return function (...$arguments) {
dispatch(new CallQueuedListener(InvokeQueuedClosure::class, 'handle', [
'closure' => new SerializableClosure($this->closure),
'closure' => SerializableClosureFactory::make($this->closure),
'arguments' => $arguments,
'catch' => collect($this->catchCallbacks)->map(function ($callback) {
return new SerializableClosure($callback);
return SerializableClosureFactory::make($callback);
})->all(),
]))->onConnection($this->connection)->onQueue($this->queue)->delay($this->delay);
};
+3 -1
View File
@@ -11,6 +11,8 @@ namespace Illuminate\Support\Facades;
* @method static bool configurationIsCached()
* @method static bool hasBeenBootstrapped()
* @method static bool isDownForMaintenance()
* @method static bool isLocal()
* @method static bool isProduction()
* @method static bool routesAreCached()
* @method static bool runningInConsole()
* @method static bool runningUnitTests()
@@ -34,7 +36,7 @@ namespace Illuminate\Support\Facades;
* @method static string storagePath(string $path = '')
* @method static string version()
* @method static string|bool environment(string|array ...$environments)
* @method static void abort(int $code, string $message = '', array $headers = [])
* @method static never abort(int $code, string $message = '', array $headers = [])
* @method static void boot()
* @method static void booted(callable $callback)
* @method static void booting(callable $callback)
+1
View File
@@ -24,6 +24,7 @@ use Illuminate\Support\Testing\Fakes\BusFake;
* @method static void assertDispatchedAfterResponseTimes(string $command, int $times = 1)
* @method static void assertNotDispatchedAfterResponse(string|\Closure $command, callable $callback = null)
* @method static void assertBatched(callable $callback)
* @method static void assertChained(array $expectedChain)
*
* @see \Illuminate\Contracts\Bus\Dispatcher
*/
+1
View File
@@ -28,6 +28,7 @@ namespace Illuminate\Support\Facades;
* @method static void enableQueryLog()
* @method static void disableQueryLog()
* @method static void flushQueryLog()
* @method static \Illuminate\Database\Connection beforeExecuting(\Closure $callback)
* @method static void listen(\Closure $callback)
* @method static void rollBack(int $toLevel = null)
* @method static void setDefaultConnection(string $name)
+1 -1
View File
@@ -17,7 +17,7 @@ use Illuminate\Support\Testing\Fakes\EventFake;
* @method static void assertDispatchedTimes(string $event, int $times = 1)
* @method static void assertNotDispatched(string|\Closure $event, callable|int $callback = null)
* @method static void assertNothingDispatched()
* @method static void assertListening(string $expectedEvent, string expectedListener)
* @method static void assertListening(string $expectedEvent, string $expectedListener)
* @method static void flush(string $event)
* @method static void forget(string $event)
* @method static void forgetPushed()
+1
View File
@@ -7,6 +7,7 @@ namespace Illuminate\Support\Facades;
* @method static bool check(string $value, string $hashedValue, array $options = [])
* @method static bool needsRehash(string $hashedValue, array $options = [])
* @method static string make(string $value, array $options = [])
* @method static \Illuminate\Hashing\HashManager extend($driver, \Closure $callback)
*
* @see \Illuminate\Hashing\HashManager
*/
+1 -1
View File
@@ -19,7 +19,7 @@ use Illuminate\Support\Testing\Fakes\QueueFake;
* @method static void assertNotPushed(string|\Closure $job, callable $callback = null)
* @method static void assertNothingPushed()
* @method static void assertPushed(string|\Closure $job, callable|int $callback = null)
* @method static void assertPushedOn(string $queue, string|\Closure $job, callable|int $callback = null)
* @method static void assertPushedOn(string $queue, string|\Closure $job, callable $callback = null)
* @method static void assertPushedWithChain(string $job, array $expectedChain = [], callable $callback = null)
*
* @see \Illuminate\Queue\QueueManager
+12 -4
View File
@@ -97,8 +97,12 @@ abstract class ServiceProvider
*/
public function callBootingCallbacks()
{
foreach ($this->bootingCallbacks as $callback) {
$this->app->call($callback);
$index = 0;
while ($index < count($this->bootingCallbacks)) {
$this->app->call($this->bootingCallbacks[$index]);
$index++;
}
}
@@ -109,8 +113,12 @@ abstract class ServiceProvider
*/
public function callBootedCallbacks()
{
foreach ($this->bootedCallbacks as $callback) {
$this->app->call($callback);
$index = 0;
while ($index < count($this->bootedCallbacks)) {
$this->app->call($this->bootedCallbacks[$index]);
$index++;
}
}
+57
View File
@@ -253,11 +253,15 @@ class Str
{
$patterns = Arr::wrap($pattern);
$value = (string) $value;
if (empty($patterns)) {
return false;
}
foreach ($patterns as $pattern) {
$pattern = (string) $pattern;
// If the given value is an exact match we can of course return true right
// from the beginning. Otherwise, we will translate asterisks and do an
// actual pattern match against the two strings to see if they match.
@@ -394,6 +398,38 @@ class Str
return (string) $converter->convertToHtml($string);
}
/**
* Masks a portion of a string with a repeated character.
*
* @param string $string
* @param string $character
* @param int $index
* @param int|null $length
* @param string $encoding
* @return string
*/
public static function mask($string, $character, $index, $length = null, $encoding = 'UTF-8')
{
if ($character === '') {
return $string;
}
if (is_null($length) && PHP_MAJOR_VERSION < 8) {
$length = mb_strlen($string, $encoding);
}
$segment = mb_substr($string, $index, $length, $encoding);
if ($segment === '') {
return $string;
}
$start = mb_substr($string, 0, mb_strpos($string, $segment, 0, $encoding), $encoding);
$end = mb_substr($string, mb_strpos($string, $segment, 0, $encoding) + mb_strlen($segment, $encoding));
return $start.str_repeat(mb_substr($character, 0, 1, $encoding), mb_strlen($segment, $encoding)).$end;
}
/**
* Get the string matching the given pattern.
*
@@ -675,6 +711,27 @@ class Str
return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
}
/**
* Convert the given string to title case for each word.
*
* @param string $value
* @return string
*/
public static function headline($value)
{
$parts = explode('_', static::replace(' ', '_', $value));
if (count($parts) > 1) {
$parts = array_map([static::class, 'title'], $parts);
}
$studly = static::studly(implode($parts));
$words = preg_split('/(?=[A-Z])/', $studly, -1, PREG_SPLIT_NO_EMPTY);
return implode(' ', $words);
}
/**
* Get the singular form of an English word.
*
+36 -1
View File
@@ -342,6 +342,20 @@ class Stringable implements JsonSerializable
return new static(Str::markdown($this->value, $options));
}
/**
* Masks a portion of a string with a repeated character.
*
* @param string $character
* @param int $index
* @param int|null $length
* @param string $encoding
* @return static
*/
public function mask($character, $index, $length = null, $encoding = 'UTF-8')
{
return new static(Str::mask($this->value, $character, $index, $length, $encoding));
}
/**
* Get the string matching the given pattern.
*
@@ -565,6 +579,17 @@ class Stringable implements JsonSerializable
return new static(Str::start($this->value, $prefix));
}
/**
* Strip HTML and PHP tags from the given string.
*
* @param string $allowedTags
* @return static
*/
public function stripTags($allowedTags = null)
{
return new static(strip_tags($this->value, $allowedTags));
}
/**
* Convert the given string to upper-case.
*
@@ -585,6 +610,16 @@ class Stringable implements JsonSerializable
return new static(Str::title($this->value));
}
/**
* Convert the given string to title case for each word.
*
* @return static
*/
public function headline()
{
return new static(Str::headline($this->value));
}
/**
* Get the singular form of an English word.
*
@@ -778,7 +813,7 @@ class Stringable implements JsonSerializable
/**
* Dump the string and end the script.
*
* @return void
* @return never
*/
public function dd()
{
+10
View File
@@ -135,6 +135,16 @@ class BusFake implements QueueingDispatcher
);
}
/**
* Assert that no jobs were dispatched.
*
* @return void
*/
public function assertNothingDispatched()
{
PHPUnit::assertEmpty($this->commands, 'Jobs were dispatched unexpectedly.');
}
/**
* Assert if a job was explicitly dispatched synchronously based on a truth-test callback.
*
@@ -7,6 +7,7 @@ use Exception;
use Illuminate\Contracts\Notifications\Dispatcher as NotificationDispatcher;
use Illuminate\Contracts\Notifications\Factory as NotificationFactory;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
@@ -31,6 +32,20 @@ class NotificationFake implements NotificationDispatcher, NotificationFactory
*/
public $locale;
/**
* Assert if a notification was sent on-demand based on a truth-test callback.
*
* @param string|\Closure $notification
* @param callable|null $callback
* @return void
*
* @throws \Exception
*/
public function assertSentOnDemand($notification, $callback = null)
{
$this->assertSentTo(new AnonymousNotifiable, $notification, $callback);
}
/**
* Assert if a notification was sent based on a truth-test callback.
*
@@ -69,6 +84,18 @@ class NotificationFake implements NotificationDispatcher, NotificationFactory
);
}
/**
* Assert if a notification was sent on-demand a number of times.
*
* @param string $notification
* @param int $times
* @return void
*/
public function assertSentOnDemandTimes($notification, $times = 1)
{
return $this->assertSentToTimes(new AnonymousNotifiable, $notification, $times);
}
/**
* Assert if a notification was sent a number of times.
*
@@ -232,9 +259,24 @@ class NotificationFake implements NotificationDispatcher, NotificationFactory
$notification->id = Str::uuid()->toString();
}
$notifiableChannels = $channels ?: $notification->via($notifiable);
if (method_exists($notification, 'shouldSend')) {
$notifiableChannels = array_filter(
$notifiableChannels,
function ($channel) use ($notification, $notifiable) {
return $notification->shouldSend($notifiable, $channel) !== false;
}
);
if (empty($notifiableChannels)) {
continue;
}
}
$this->notifications[get_class($notifiable)][$notifiable->getKey()][get_class($notification)][] = [
'notification' => $notification,
'channels' => $channels ?: $notification->via($notifiable),
'channels' => $notifiableChannels,
'notifiable' => $notifiable,
'locale' => $notification->locale ?? $this->locale ?? value(function () use ($notifiable) {
if ($notifiable instanceof HasLocalePreference) {
+3 -3
View File
@@ -21,7 +21,7 @@
"illuminate/collections": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0",
"nesbot/carbon": "^2.31",
"nesbot/carbon": "^2.53.1",
"voku/portable-ascii": "^1.4.8"
},
"conflict": {
@@ -42,8 +42,8 @@
},
"suggest": {
"illuminate/filesystem": "Required to use the composer class (^8.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0).",
"ramsey/uuid": "Required to use Str::uuid() (^4.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^1.3|^2.0.2).",
"ramsey/uuid": "Required to use Str::uuid() (^4.2.2).",
"symfony/process": "Required to use the composer class (^5.1.4).",
"symfony/var-dumper": "Required to use the dd function (^5.1.4).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.2)."