diff --git a/.github/workflows/databases-nightly.yml b/.github/workflows/databases-nightly.yml index 059c35ce1321..9003fab41ec5 100644 --- a/.github/workflows/databases-nightly.yml +++ b/.github/workflows/databases-nightly.yml @@ -36,7 +36,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -82,7 +82,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/databases.yml b/.github/workflows/databases.yml index bd20bfad48bd..f2f57a6249a3 100644 --- a/.github/workflows/databases.yml +++ b/.github/workflows/databases.yml @@ -40,7 +40,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -87,7 +87,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -133,7 +133,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -180,7 +180,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -229,7 +229,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -276,7 +276,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -324,7 +324,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -363,7 +363,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/facades.yml b/.github/workflows/facades.yml index 3a3bf57c2f06..7b8671755aae 100644 --- a/.github/workflows/facades.yml +++ b/.github/workflows/facades.yml @@ -26,13 +26,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/queues.yml b/.github/workflows/queues.yml index 3df36c7d6c82..a66202accef5 100644 --- a/.github/workflows/queues.yml +++ b/.github/workflows/queues.yml @@ -23,13 +23,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -58,13 +58,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -106,13 +106,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -144,13 +144,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -182,9 +182,9 @@ jobs: fail-fast: true matrix: include: - - php: 8.2 - pheanstalk: 5 - php: 8.3 + pheanstalk: 5 + - php: 8.4 pheanstalk: 7 name: Beanstalkd Driver (pda/pheanstalk:^${{ matrix.pheanstalk }}) @@ -209,7 +209,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index da698e647f91..e112061b8844 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -25,12 +25,12 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fd2a5f2a7a67..9d98d6c13723 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,14 +39,9 @@ jobs: strategy: fail-fast: true matrix: - php: [8.2, 8.3, 8.4] - phpunit: ['10.5.35', '11.5.3', '12.0.0', '12.2.0'] + php: [8.3, 8.4] + phpunit: ['11.5.3', '12.0.0', '12.2.0'] stability: [prefer-lowest, prefer-stable] - exclude: - - php: 8.2 - phpunit: '12.0.0' - - php: 8.2 - phpunit: '12.2.0' include: - php: 8.3 phpunit: '12.1.0' @@ -71,7 +66,7 @@ jobs: REDIS_LIBS: liblz4-dev, liblzf-dev, libzstd-dev - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -104,14 +99,9 @@ jobs: strategy: fail-fast: true matrix: - php: [8.2, 8.3, 8.4] - phpunit: ['10.5.35', '11.5.3', '12.0.0', '12.1.0'] + php: [8.3, 8.4] + phpunit: ['11.5.3', '12.0.0', '12.1.0'] stability: [prefer-lowest, prefer-stable] - exclude: - - php: 8.2 - phpunit: '12.0.0' - - php: 8.2 - phpunit: '12.1.0' name: PHP ${{ matrix.php }} - PHPUnit ${{ matrix.phpunit }} - ${{ matrix.stability }} - Windows @@ -133,7 +123,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/bin/split.sh b/bin/split.sh index ae4cdf01f8f3..9536ec7a4f31 100755 --- a/bin/split.sh +++ b/bin/split.sh @@ -3,7 +3,7 @@ set -e set -x -CURRENT_BRANCH="12.x" +CURRENT_BRANCH="master" function split() { diff --git a/composer.json b/composer.json index 681e1a6884e4..2d0caacf5d8f 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-ctype": "*", "ext-filter": "*", "ext-hash": "*", @@ -44,20 +44,19 @@ "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^7.2.0", - "symfony/error-handler": "^7.2.0", - "symfony/finder": "^7.2.0", - "symfony/http-foundation": "^7.2.0", - "symfony/http-kernel": "^7.2.0", - "symfony/mailer": "^7.2.0", - "symfony/mime": "^7.2.0", - "symfony/polyfill-php83": "^1.31", + "symfony/console": "^7.4.0|^8.0.0", + "symfony/error-handler": "^7.4.0|^8.0.0", + "symfony/finder": "^7.4.0|^8.0.0", + "symfony/http-foundation": "^7.4.0|^8.0.0", + "symfony/http-kernel": "^7.4.0|^8.0.0", + "symfony/mailer": "^7.4.0|^8.0.0", + "symfony/mime": "^7.4.0|^8.0.0", + "symfony/process": "^7.4.0|^8.0.0", "symfony/polyfill-php84": "^1.31", "symfony/polyfill-php85": "^1.31", - "symfony/process": "^7.2.0", - "symfony/routing": "^7.2.0", - "symfony/uid": "^7.2.0", - "symfony/var-dumper": "^7.2.0", + "symfony/routing": "^7.4.0|^8.0.0", + "symfony/uid": "^7.4.0|^8.0.0", + "symfony/var-dumper": "^7.4.0|^8.0.0", "tijsverkoyen/css-to-inline-styles": "^2.2.5", "vlucas/phpdotenv": "^5.6.1", "voku/portable-ascii": "^2.0.2" @@ -113,17 +112,17 @@ "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^10.6.0", + "orchestra/testbench-core": "^11.0.0", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", + "phpunit/phpunit": "^11.5.3|^12.0.1", "predis/predis": "^2.3|^3.0", "resend/resend-php": "^0.10.0", - "symfony/cache": "^7.2.0", - "symfony/http-client": "^7.2.0", - "symfony/psr-http-message-bridge": "^7.2.0", - "symfony/translation": "^7.2.0" + "symfony/cache": "^7.4.0|^8.0.0", + "symfony/http-client": "^7.4.0|^8.0.0", + "symfony/psr-http-message-bridge": "^7.4.0|^8.0.0", + "symfony/translation": "^7.4.0" }, "conflict": { "tightenco/collect": "<5.5.33" @@ -163,7 +162,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { @@ -195,12 +194,12 @@ "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", - "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", - "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", - "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." + "symfony/cache": "Required to PSR-6 cache bridge (^7.4|^8.0).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.4|^8.0).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.4|^8.0).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.4|^8.0).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.4|^8.0).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.4|^8.0)." }, "config": { "sort-packages": true, diff --git a/config/cache.php b/config/cache.php index f529e1e3ec74..c2d927d79978 100644 --- a/config/cache.php +++ b/config/cache.php @@ -103,6 +103,6 @@ | */ - 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel'), '_').'_cache_'), + 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'), ]; diff --git a/config/database.php b/config/database.php index 8a3b731fb52e..2c28fef7d038 100644 --- a/config/database.php +++ b/config/database.php @@ -148,7 +148,7 @@ 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'redis'), - 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel'), '_').'_database_'), + 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'), 'persistent' => env('REDIS_PERSISTENT', false), ], diff --git a/config/session.php b/config/session.php index 13d86a4ac63d..f348f5f8c2db 100644 --- a/config/session.php +++ b/config/session.php @@ -129,7 +129,7 @@ 'cookie' => env( 'SESSION_COOKIE', - Str::slug((string) env('APP_NAME', 'laravel'), '_').'_session' + Str::snake((string) env('APP_NAME', 'laravel')).'_session' ), /* diff --git a/src/Illuminate/Auth/composer.json b/src/Illuminate/Auth/composer.json index 7073f8b060cc..45cbc2f973bc 100644 --- a/src/Illuminate/Auth/composer.json +++ b/src/Illuminate/Auth/composer.json @@ -14,14 +14,14 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-hash": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/http": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/queue": "^12.0", - "illuminate/support": "^12.0" + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/http": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/queue": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -30,13 +30,13 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/console": "Required to use the auth:clear-resets command (^12.0).", - "illuminate/queue": "Required to fire login / logout events (^12.0).", - "illuminate/session": "Required to use the session based guard (^12.0)." + "illuminate/console": "Required to use the auth:clear-resets command (^13.0).", + "illuminate/queue": "Required to fire login / logout events (^13.0).", + "illuminate/session": "Required to use the session based guard (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Broadcasting/BroadcastEvent.php b/src/Illuminate/Broadcasting/BroadcastEvent.php index c4da0faab220..7c03641ace53 100644 --- a/src/Illuminate/Broadcasting/BroadcastEvent.php +++ b/src/Illuminate/Broadcasting/BroadcastEvent.php @@ -50,6 +50,13 @@ class BroadcastEvent implements ShouldQueue */ public $maxExceptions; + /** + * Indicates if the job should be deleted when models are missing. + * + * @var bool + */ + public $deleteWhenMissingModels; + /** * Create a new job handler instance. * @@ -63,6 +70,7 @@ public function __construct($event) $this->backoff = property_exists($event, 'backoff') ? $event->backoff : null; $this->afterCommit = property_exists($event, 'afterCommit') ? $event->afterCommit : null; $this->maxExceptions = property_exists($event, 'maxExceptions') ? $event->maxExceptions : null; + $this->deleteWhenMissingModels = property_exists($event, 'deleteWhenMissingModels') ? $event->deleteWhenMissingModels : null; } /** diff --git a/src/Illuminate/Broadcasting/composer.json b/src/Illuminate/Broadcasting/composer.json index 103b02ac2733..03d45b78ea54 100644 --- a/src/Illuminate/Broadcasting/composer.json +++ b/src/Illuminate/Broadcasting/composer.json @@ -14,14 +14,14 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "psr/log": "^1.0|^2.0|^3.0", - "illuminate/bus": "^12.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/queue": "^12.0", - "illuminate/support": "^12.0" + "illuminate/bus": "^13.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/queue": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Bus/composer.json b/src/Illuminate/Bus/composer.json index dc3385da5120..57aea7551f3e 100644 --- a/src/Illuminate/Bus/composer.json +++ b/src/Illuminate/Bus/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/pipeline": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/pipeline": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -27,11 +27,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/queue": "Required to use closures when chaining jobs (^12.0)." + "illuminate/queue": "Required to use closures when chaining jobs (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Cache/ApcStore.php b/src/Illuminate/Cache/ApcStore.php index 89c31a3f7f0c..0c4f62710bf3 100755 --- a/src/Illuminate/Cache/ApcStore.php +++ b/src/Illuminate/Cache/ApcStore.php @@ -92,6 +92,24 @@ public function forever($key, $value) return $this->put($key, $value, 0); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + $value = $this->apc->get($key = $this->getPrefix().$key); + + if (is_null($value)) { + return false; + } + + return $this->apc->put($key, $value, $seconds); + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/ArrayStore.php b/src/Illuminate/Cache/ArrayStore.php index 112501831822..f318d1c34dec 100644 --- a/src/Illuminate/Cache/ArrayStore.php +++ b/src/Illuminate/Cache/ArrayStore.php @@ -3,6 +3,7 @@ namespace Illuminate\Cache; use Illuminate\Contracts\Cache\LockProvider; +use Illuminate\Support\Arr; use Illuminate\Support\Carbon; use Illuminate\Support\InteractsWithTime; @@ -130,6 +131,28 @@ public function forever($key, $value) return $this->put($key, $value, 0); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + $item = Arr::get($this->storage, $key = $this->getPrefix().$key, null); + + if (is_null($item)) { + return false; + } + + $item['expiresAt'] = $this->calculateExpiration($seconds); + + $this->storage = array_merge($this->storage, [$key => $item]); + + return true; + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/Console/ClearCommand.php b/src/Illuminate/Cache/Console/ClearCommand.php index e84cefae8d6c..965a39cf0248 100755 --- a/src/Illuminate/Cache/Console/ClearCommand.php +++ b/src/Illuminate/Cache/Console/ClearCommand.php @@ -57,7 +57,7 @@ public function __construct(CacheManager $cache, Filesystem $files) /** * Execute the console command. * - * @return void + * @return int|null */ public function handle() { @@ -70,7 +70,9 @@ public function handle() $this->flushFacades(); if (! $successful) { - return $this->components->error('Failed to clear cache. Make sure you have the appropriate permissions.'); + $this->components->error('Failed to clear cache. Make sure you have the appropriate permissions.'); + + return 1; } $this->laravel['events']->dispatch( diff --git a/src/Illuminate/Cache/DatabaseStore.php b/src/Illuminate/Cache/DatabaseStore.php index 0c25ddc01f74..711df7c8338a 100755 --- a/src/Illuminate/Cache/DatabaseStore.php +++ b/src/Illuminate/Cache/DatabaseStore.php @@ -352,6 +352,21 @@ public function restoreLock($name, $owner) return $this->lock($name, 0, $owner); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + return (bool) $this->table() + ->where('key', '=', $this->getPrefix().$key) + ->where('expiration', '>', $now = $this->getTime()) + ->update(['expiration' => $now + $seconds]); + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/DynamoDbStore.php b/src/Illuminate/Cache/DynamoDbStore.php index 1bc7aa879865..89f6774a7f11 100644 --- a/src/Illuminate/Cache/DynamoDbStore.php +++ b/src/Illuminate/Cache/DynamoDbStore.php @@ -428,6 +428,43 @@ public function restoreLock($name, $owner) return $this->lock($name, 0, $owner); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + * + * @throws DynamoDbException + */ + public function touch($key, $seconds) + { + try { + $this->dynamo->updateItem([ + 'TableName' => $this->table, + 'Key' => [$this->keyAttribute => ['S' => $this->getPrefix().$key]], + 'UpdateExpression' => 'SET #expiry = :expiry', + 'ConditionExpression' => 'attribute_exists(#key) AND #expiry > :now', + 'ExpressionAttributeNames' => [ + '#key' => $this->keyAttribute, + '#expiry' => $this->expirationAttribute, + ], + 'ExpressionAttributeValues' => [ + ':expiry' => ['N' => (string) $this->toTimestamp($seconds)], + ':now' => ['N' => (string) $this->currentTime()], + ], + ]); + } catch (DynamoDbException $e) { + if (str_contains($e->getMessage(), 'ConditionalCheckFailed')) { + return false; + } + + throw $e; + } + + return true; + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/FileStore.php b/src/Illuminate/Cache/FileStore.php index d445f5fc7c23..4aa09a9904b5 100755 --- a/src/Illuminate/Cache/FileStore.php +++ b/src/Illuminate/Cache/FileStore.php @@ -238,6 +238,24 @@ public function restoreLock($name, $owner) return $this->lock($name, 0, $owner); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + $payload = $this->getPayload($this->getPrefix().$key); + + if (is_null($payload['data'])) { + return false; + } + + return $this->put($key, $payload['data'], $seconds); + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/MemcachedStore.php b/src/Illuminate/Cache/MemcachedStore.php index b05560e1a986..404dceed5ed3 100755 --- a/src/Illuminate/Cache/MemcachedStore.php +++ b/src/Illuminate/Cache/MemcachedStore.php @@ -202,6 +202,18 @@ public function restoreLock($name, $owner) return $this->lock($name, 0, $owner); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + return $this->memcached->touch($this->getPrefix().$key, $this->calculateExpiration($seconds)); + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/MemoizedStore.php b/src/Illuminate/Cache/MemoizedStore.php index 6c24e33346ce..e81d7bc534f8 100644 --- a/src/Illuminate/Cache/MemoizedStore.php +++ b/src/Illuminate/Cache/MemoizedStore.php @@ -196,6 +196,20 @@ public function restoreLock($name, $owner) return $this->repository->resoreLock(...func_get_args()); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + unset($this->cache[$this->prefix($key)]); + + return $this->repository->touch($key, $seconds); + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/NullStore.php b/src/Illuminate/Cache/NullStore.php index 6c35ee386c26..e00470159bb6 100755 --- a/src/Illuminate/Cache/NullStore.php +++ b/src/Illuminate/Cache/NullStore.php @@ -93,6 +93,18 @@ public function restoreLock($name, $owner) return $this->lock($name, 0, $owner); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + return false; + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/RedisStore.php b/src/Illuminate/Cache/RedisStore.php index 399f4ac78ea0..1d923a984a97 100755 --- a/src/Illuminate/Cache/RedisStore.php +++ b/src/Illuminate/Cache/RedisStore.php @@ -248,6 +248,18 @@ public function restoreLock($name, $owner) return $this->lock($name, 0, $owner); } + /** + * Adjust the expiration time of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds) + { + return (bool) $this->connection()->expire($this->getPrefix().$key, (int) max(1, $seconds)); + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/Repository.php b/src/Illuminate/Cache/Repository.php index 5b55da8e3008..98d101760f89 100755 --- a/src/Illuminate/Cache/Repository.php +++ b/src/Illuminate/Cache/Repository.php @@ -526,6 +526,26 @@ public function flexible($key, $ttl, $callback, $lock = null, $alwaysDefer = fal return $value; } + /** + * Set the expiration of a cached item; null TTL will retain the item forever. + * + * @param string $key + * @param \DateTimeInterface|\DateInterval|int|null $ttl + * @return bool + */ + public function touch($key, $ttl = null) + { + $value = $this->get($key); + + if (is_null($value)) { + return false; + } + + return is_null($ttl) + ? $this->forever($key, $value) + : $this->store->touch($this->itemKey($key), $this->getSeconds($ttl)); + } + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Cache/composer.json b/src/Illuminate/Cache/composer.json index b1a44ef6d451..07628f3c6ed9 100755 --- a/src/Illuminate/Cache/composer.json +++ b/src/Illuminate/Cache/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0" }, "provide": { "psr/simple-cache-implementation": "1.0|2.0|3.0" @@ -30,17 +30,17 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-apcu": "Required to use the APC cache driver.", "ext-filter": "Required to use the DynamoDb cache driver.", "ext-memcached": "Required to use the memcache cache driver.", - "illuminate/database": "Required to use the database cache driver (^12.0).", - "illuminate/filesystem": "Required to use the file cache driver (^12.0).", - "illuminate/redis": "Required to use the redis cache driver (^12.0).", - "symfony/cache": "Required to use PSR-6 cache bridge (^7.2)." + "illuminate/database": "Required to use the database cache driver (^13.0).", + "illuminate/filesystem": "Required to use the file cache driver (^13.0).", + "illuminate/redis": "Required to use the redis cache driver (^13.0).", + "symfony/cache": "Required to use PSR-6 cache bridge (^7.4|^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Collections/composer.json b/src/Illuminate/Collections/composer.json index bf7565d3a4ec..86980e8dc9b5 100644 --- a/src/Illuminate/Collections/composer.json +++ b/src/Illuminate/Collections/composer.json @@ -14,10 +14,10 @@ } ], "require": { - "php": "^8.2", - "illuminate/conditionable": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", + "php": "^8.3", + "illuminate/conditionable": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", "symfony/polyfill-php84": "^1.31" }, "autoload": { @@ -31,12 +31,12 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "illuminate/http": "Required to convert collections to API resources (^12.0).", - "symfony/var-dumper": "Required to use the dump method (^7.2)." + "symfony/var-dumper": "Required to use the dump method (^7.4|^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Concurrency/composer.json b/src/Illuminate/Concurrency/composer.json index eb4e9467f66e..0a5d5c39bbe4 100644 --- a/src/Illuminate/Concurrency/composer.json +++ b/src/Illuminate/Concurrency/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/console": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/process": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/console": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/process": "^13.0", + "illuminate/support": "^13.0", "laravel/serializable-closure": "^1.3|^2.0" }, "autoload": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Conditionable/composer.json b/src/Illuminate/Conditionable/composer.json index 9e0ddfbbdcf1..be75be9adf18 100644 --- a/src/Illuminate/Conditionable/composer.json +++ b/src/Illuminate/Conditionable/composer.json @@ -23,7 +23,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Config/composer.json b/src/Illuminate/Config/composer.json index 48db6c1db52a..484c4c58ea47 100755 --- a/src/Illuminate/Config/composer.json +++ b/src/Illuminate/Config/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Console/Application.php b/src/Illuminate/Console/Application.php index 6263d85341bd..4babe246fc32 100755 --- a/src/Illuminate/Console/Application.php +++ b/src/Illuminate/Console/Application.php @@ -209,28 +209,14 @@ public function output() : ''; } - /** - * Add an array of commands to the console. - * - * @param array $commands - * @return void - */ - #[\Override] - public function addCommands(array $commands): void - { - foreach ($commands as $command) { - $this->add($command); - } - } - /** * Add a command to the console. * - * @param \Symfony\Component\Console\Command\Command $command + * @param \Symfony\Component\Console\Command\Command|callable $command * @return \Symfony\Component\Console\Command\Command|null */ #[\Override] - public function add(SymfonyCommand $command): ?SymfonyCommand + public function addCommand(SymfonyCommand|callable $command): ?SymfonyCommand { if ($command instanceof Command) { $command->setLaravel($this->laravel); @@ -242,12 +228,12 @@ public function add(SymfonyCommand $command): ?SymfonyCommand /** * Add the command to the parent instance. * - * @param \Symfony\Component\Console\Command\Command $command + * @param \Symfony\Component\Console\Command\Command|callable $command * @return \Symfony\Component\Console\Command\Command */ - protected function addToParent(SymfonyCommand $command) + protected function addToParent(SymfonyCommand|callable $command) { - return parent::add($command); + return parent::addCommand($command); } /** @@ -273,10 +259,10 @@ public function resolve($command) } if ($command instanceof Command) { - return $this->add($command); + return $this->addCommand($command); } - return $this->add($this->laravel->make($command)); + return $this->addCommand($this->laravel->make($command)); } /** diff --git a/src/Illuminate/Console/composer.json b/src/Illuminate/Console/composer.json index 82fe11336e8a..4b8974ad8bdd 100755 --- a/src/Illuminate/Console/composer.json +++ b/src/Illuminate/Console/composer.json @@ -14,18 +14,17 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-mbstring": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "illuminate/view": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", + "illuminate/view": "^13.0", "laravel/prompts": "^0.3.0", "nunomaduro/termwind": "^2.0", - "symfony/console": "^7.2.0", - "symfony/polyfill-php83": "^1.31", - "symfony/process": "^7.2.0" + "symfony/console": "^7.4.0|^8.0.0", + "symfony/process": "^7.4.0|^8.0.0" }, "autoload": { "psr-4": { @@ -34,17 +33,17 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-pcntl": "Required to use signal trapping.", "dragonmantank/cron-expression": "Required to use scheduler (^3.3.2).", "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^7.8).", - "illuminate/bus": "Required to use the scheduled job dispatcher (^12.0).", - "illuminate/container": "Required to use the scheduler (^12.0).", - "illuminate/filesystem": "Required to use the generator command (^12.0).", - "illuminate/queue": "Required to use closures for scheduled jobs (^12.0)." + "illuminate/bus": "Required to use the scheduled job dispatcher (^13.0).", + "illuminate/container": "Required to use the scheduler (^13.0).", + "illuminate/filesystem": "Required to use the generator command (^13.0).", + "illuminate/queue": "Required to use closures for scheduled jobs (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Container/composer.json b/src/Illuminate/Container/composer.json index 16d737f2a216..85b4860bf832 100755 --- a/src/Illuminate/Container/composer.json +++ b/src/Illuminate/Container/composer.json @@ -14,8 +14,8 @@ } ], "require": { - "php": "^8.2", - "illuminate/contracts": "^12.0", + "php": "^8.3", + "illuminate/contracts": "^13.0", "psr/container": "^1.1.1|^2.0.1" }, "provide": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Contracts/Cache/Repository.php b/src/Illuminate/Contracts/Cache/Repository.php index 4bc4638e46fe..ebb6fc5bf3b6 100644 --- a/src/Illuminate/Contracts/Cache/Repository.php +++ b/src/Illuminate/Contracts/Cache/Repository.php @@ -99,6 +99,15 @@ public function sear($key, Closure $callback); */ public function rememberForever($key, Closure $callback); + /** + * Set the expiration of a cached item; null TTL will retain the item forever. + * + * @param string $key + * @param \DateTimeInterface|\DateInterval|int|null $ttl + * @return bool + */ + public function touch($key, $ttl = null); + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Contracts/Cache/Store.php b/src/Illuminate/Contracts/Cache/Store.php index 4ededd4efbc8..a9a8756aaf7c 100644 --- a/src/Illuminate/Contracts/Cache/Store.php +++ b/src/Illuminate/Contracts/Cache/Store.php @@ -68,6 +68,15 @@ public function decrement($key, $value = 1); */ public function forever($key, $value); + /** + * Set the expiration of a cached item. + * + * @param string $key + * @param int $seconds + * @return bool + */ + public function touch($key, $seconds); + /** * Remove an item from the cache. * diff --git a/src/Illuminate/Contracts/Routing/ResponseFactory.php b/src/Illuminate/Contracts/Routing/ResponseFactory.php index 95dcf96bcf73..c724fbb8a3dd 100644 --- a/src/Illuminate/Contracts/Routing/ResponseFactory.php +++ b/src/Illuminate/Contracts/Routing/ResponseFactory.php @@ -2,6 +2,9 @@ namespace Illuminate\Contracts\Routing; +use Closure; +use Illuminate\Http\StreamedEvent; + interface ResponseFactory { /** @@ -57,6 +60,16 @@ public function json($data = [], $status = 200, array $headers = [], $options = */ public function jsonp($callback, $data = [], $status = 200, array $headers = [], $options = 0); + /** + * Create a new event stream response. + * + * @param \Closure $callback + * @param array $headers + * @param \Illuminate\Http\StreamedEvent|string|null $endStreamWith + * @return \Symfony\Component\HttpFoundation\StreamedResponse + */ + public function eventStream(Closure $callback, array $headers = [], StreamedEvent|string|null $endStreamWith = ''); + /** * Create a new streamed response instance. * diff --git a/src/Illuminate/Contracts/composer.json b/src/Illuminate/Contracts/composer.json index 01e8f8495602..dea7426f157e 100644 --- a/src/Illuminate/Contracts/composer.json +++ b/src/Illuminate/Contracts/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "psr/container": "^1.1.1|^2.0.1", "psr/simple-cache": "^1.0|^2.0|^3.0" }, @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Cookie/composer.json b/src/Illuminate/Cookie/composer.json index 7184c3d2e351..ca7be9b040c5 100755 --- a/src/Illuminate/Cookie/composer.json +++ b/src/Illuminate/Cookie/composer.json @@ -14,14 +14,14 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-hash": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "symfony/http-foundation": "^7.2.0", - "symfony/http-kernel": "^7.2.0" + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", + "symfony/http-foundation": "^7.4.0|^8.0.0", + "symfony/http-kernel": "^7.4.0|^8.0.0" }, "autoload": { "psr-4": { @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 9910fe911b66..eba28448b146 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -390,11 +390,12 @@ public function selectFromWriteConnection($query, $bindings = []) * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return array */ - public function select($query, $bindings = [], $useReadPdo = true) + public function select($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []) { - return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { + return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo, $fetchUsing) { if ($this->pretending()) { return []; } @@ -410,7 +411,7 @@ public function select($query, $bindings = [], $useReadPdo = true) $statement->execute(); - return $statement->fetchAll(); + return $statement->fetchAll(...$fetchUsing); }); } @@ -420,11 +421,12 @@ public function select($query, $bindings = [], $useReadPdo = true) * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return array */ - public function selectResultSets($query, $bindings = [], $useReadPdo = true) + public function selectResultSets($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []) { - return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { + return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo, $fetchUsing) { if ($this->pretending()) { return []; } @@ -440,7 +442,7 @@ public function selectResultSets($query, $bindings = [], $useReadPdo = true) $sets = []; do { - $sets[] = $statement->fetchAll(); + $sets[] = $statement->fetchAll(...$fetchUsing); } while ($statement->nextRowset()); return $sets; @@ -453,9 +455,10 @@ public function selectResultSets($query, $bindings = [], $useReadPdo = true) * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return \Generator */ - public function cursor($query, $bindings = [], $useReadPdo = true) + public function cursor($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []) { $statement = $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { if ($this->pretending()) { @@ -480,7 +483,7 @@ public function cursor($query, $bindings = [], $useReadPdo = true) return $statement; }); - while ($record = $statement->fetch()) { + while ($record = $statement->fetch(...$fetchUsing)) { yield $record; } } diff --git a/src/Illuminate/Database/ConnectionInterface.php b/src/Illuminate/Database/ConnectionInterface.php index b28c63f9c25b..69e1fafa389c 100755 --- a/src/Illuminate/Database/ConnectionInterface.php +++ b/src/Illuminate/Database/ConnectionInterface.php @@ -51,9 +51,10 @@ public function scalar($query, $bindings = [], $useReadPdo = true); * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return array */ - public function select($query, $bindings = [], $useReadPdo = true); + public function select($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []); /** * Run a select statement against the database and returns a generator. @@ -61,9 +62,10 @@ public function select($query, $bindings = [], $useReadPdo = true); * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return \Generator */ - public function cursor($query, $bindings = [], $useReadPdo = true); + public function cursor($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []); /** * Run an insert statement against the database. diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index b53f26a2c699..1427c016f1c8 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -341,6 +341,9 @@ public function where($column, $operator = null, $value = null, $boolean = 'and' $this->eagerLoad = array_merge($this->eagerLoad, $query->getEagerLoads()); + $this->withoutGlobalScopes( + $query->removedScopes() + ); $this->query->addNestedWhereQuery($query->getQuery(), $boolean); } else { $this->query->where(...func_get_args()); diff --git a/src/Illuminate/Database/Eloquent/Model.php b/src/Illuminate/Database/Eloquent/Model.php index 94973c365318..5a534a603fb1 100644 --- a/src/Illuminate/Database/Eloquent/Model.php +++ b/src/Illuminate/Database/Eloquent/Model.php @@ -4,6 +4,7 @@ use ArrayAccess; use Closure; +use Exception; use Illuminate\Contracts\Broadcasting\HasBroadcastChannel; use Illuminate\Contracts\Queue\QueueableCollection; use Illuminate\Contracts\Queue\QueueableEntity; @@ -147,6 +148,13 @@ abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToSt */ protected static $dispatcher; + /** + * The models that are currently being booted. + * + * @var array + */ + protected static $booting = []; + /** * The array of booted models. * @@ -311,12 +319,20 @@ public function __construct(array $attributes = []) protected function bootIfNotBooted() { if (! isset(static::$booted[static::class])) { - static::$booted[static::class] = true; + if (isset(static::$booting[static::class])) { + throw new LogicException('The ['.__METHOD__.'] method may not be called on model ['.static::class.'] while it is being booted.'); + } + + static::$booting[static::class] = true; $this->fireModelEvent('booting', false); static::booting(); static::boot(); + + static::$booted[static::class] = true; + unset(static::$booting[static::class]); + static::booted(); static::$bootedCallbacks[static::class] ??= []; diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 7c585a169533..fc50f1c06ccd 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -262,6 +262,13 @@ class Builder implements BuilderContract */ public $useWritePdo = false; + /** + * The custom arguments for the PDOStatement::fetchAll / fetch functions. + * + * @var array + */ + public array $fetchUsing = []; + /** * Create a new query builder instance. */ @@ -769,6 +776,49 @@ public function crossJoinSub($query, $as) return $this; } + /** + * Add a straight join to the query. + * + * @param \Illuminate\Contracts\Database\Query\Expression|string $table + * @param \Closure|string $first + * @param string|null $operator + * @param \Illuminate\Contracts\Database\Query\Expression|string|null $second + * @return $this + */ + public function straightJoin($table, $first, $operator = null, $second = null) + { + return $this->join($table, $first, $operator, $second, 'straight_join'); + } + + /** + * Add a "straight join where" clause to the query. + * + * @param \Illuminate\Contracts\Database\Query\Expression|string $table + * @param \Closure|\Illuminate\Contracts\Database\Query\Expression|string $first + * @param string $operator + * @param \Illuminate\Contracts\Database\Query\Expression|string $second + * @return $this + */ + public function straightJoinWhere($table, $first, $operator, $second) + { + return $this->joinWhere($table, $first, $operator, $second, 'straight_join'); + } + + /** + * Add a subquery straight join to the query. + * + * @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|string $query + * @param string $as + * @param \Closure|\Illuminate\Contracts\Database\Query\Expression|string $first + * @param string|null $operator + * @param \Illuminate\Contracts\Database\Query\Expression|string|null $second + * @return $this + */ + public function straightJoinSub($query, $as, $first, $operator = null, $second = null) + { + return $this->joinSub($query, $as, $first, $operator, $second, 'straight_join'); + } + /** * Get a new join clause. * @@ -3169,9 +3219,13 @@ public function soleValue($column) */ public function get($columns = ['*']) { - $items = new Collection($this->onceWithColumns(Arr::wrap($columns), function () { - return $this->processor->processSelect($this, $this->runSelect()); - })); + $original = $this->columns; + + $this->columns ??= Arr::wrap($columns); + + $items = new Collection($this->processor->processSelect($this, $this->runSelect())); + + $this->columns = $original; return $this->applyAfterQueryCallbacks( isset($this->groupLimit) ? $this->withoutGroupLimitKeys($items) : $items @@ -3186,7 +3240,7 @@ public function get($columns = ['*']) protected function runSelect() { return $this->connection->select( - $this->toSql(), $this->getBindings(), ! $this->useWritePdo + $this->toSql(), $this->getBindings(), ! $this->useWritePdo, $this->fetchUsing ); } @@ -3406,7 +3460,7 @@ public function cursor() return (new LazyCollection(function () { yield from $this->connection->cursor( - $this->toSql(), $this->getBindings(), ! $this->useWritePdo + $this->toSql(), $this->getBindings(), ! $this->useWritePdo, $this->fetchUsing ); }))->map(function ($item) { return $this->applyAfterQueryCallbacks(new Collection([$item]))->first(); @@ -3436,17 +3490,18 @@ protected function enforceOrderBy() */ public function pluck($column, $key = null) { + $original = $this->columns; + // First, we will need to select the results of the query accounting for the // given columns / key. Once we have the results, we will be able to take // the results and get the exact data that was requested for the query. - $queryResult = $this->onceWithColumns( - is_null($key) || $key === $column ? [$column] : [$column, $key], - function () { - return $this->processor->processSelect( - $this, $this->runSelect() - ); - } - ); + $this->columns ??= is_null($key) || $key === $column + ? [$column] + : [$column, $key]; + + $queryResult = $this->processor->processSelect($this, $this->runSelect()); + + $this->columns = $original; if (empty($queryResult)) { return new Collection; @@ -3741,32 +3796,6 @@ protected function setAggregate($function, $columns) return $this; } - /** - * Execute the given callback while selecting the given columns. - * - * After running the callback, the columns are reset to the original value. - * - * @template TResult - * - * @param array $columns - * @param callable(): TResult $callback - * @return TResult - */ - protected function onceWithColumns($columns, $callback) - { - $original = $this->columns; - - if (is_null($original)) { - $this->columns = $columns; - } - - $result = $callback(); - - $this->columns = $original; - - return $result; - } - /** * Insert new records into the database. * @@ -4391,6 +4420,19 @@ public function useWritePdo() return $this; } + /** + * Specify arguments for the PDOStatement::fetchAll / fetch functions. + * + * @param mixed ...$fetchUsing + * @return $this + */ + public function fetchUsing(...$fetchUsing) + { + $this->fetchUsing = $fetchUsing; + + return $this; + } + /** * Determine if the value is a query builder instance or a Closure. * diff --git a/src/Illuminate/Database/Query/Grammars/Grammar.php b/src/Illuminate/Database/Query/Grammars/Grammar.php index 27effd7c4a34..09fa694967d6 100755 --- a/src/Illuminate/Database/Query/Grammars/Grammar.php +++ b/src/Illuminate/Database/Query/Grammars/Grammar.php @@ -199,7 +199,9 @@ protected function compileJoins(Builder $query, $joins) return $this->compileJoinLateral($join, $tableAndNestedJoins); } - return trim("{$join->type} join {$tableAndNestedJoins} {$this->compileWheres($join)}"); + $joinWord = ($join->type === 'straight_join' && $this->supportsStraightJoins()) ? '' : ' join'; + + return trim("{$join->type}{$joinWord} {$tableAndNestedJoins} {$this->compileWheres($join)}"); })->implode(' '); } @@ -217,6 +219,16 @@ public function compileJoinLateral(JoinLateralClause $join, string $expression): throw new RuntimeException('This database engine does not support lateral joins.'); } + /** + * Determine if the grammar supports straight joins. + * + * @return bool + */ + protected function supportsStraightJoins() + { + throw new RuntimeException('This database engine does not support straight joins.'); + } + /** * Compile the "where" portions of the query. * diff --git a/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php b/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php index 4372bae32791..6c4c2c09e212 100755 --- a/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php @@ -387,6 +387,14 @@ public function compileJoinLateral(JoinLateralClause $join, string $expression): return trim("{$join->type} join lateral {$expression} on true"); } + /** + * {@inheritdoc} + */ + protected function supportsStraightJoins() + { + return true; + } + /** * Prepare a JSON column being updated using the JSON_SET function. * diff --git a/src/Illuminate/Database/Schema/Blueprint.php b/src/Illuminate/Database/Schema/Blueprint.php index 5be4561bf046..7e22cc1fb24a 100755 --- a/src/Illuminate/Database/Schema/Blueprint.php +++ b/src/Illuminate/Database/Schema/Blueprint.php @@ -1326,7 +1326,7 @@ public function softDeletesTz($column = 'deleted_at', $precision = null) */ public function softDeletesDatetime($column = 'deleted_at', $precision = null) { - return $this->datetime($column, $precision)->nullable(); + return $this->dateTime($column, $precision)->nullable(); } /** diff --git a/src/Illuminate/Database/composer.json b/src/Illuminate/Database/composer.json index dcf37d499b52..a5ce5414590d 100644 --- a/src/Illuminate/Database/composer.json +++ b/src/Illuminate/Database/composer.json @@ -15,14 +15,14 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-pdo": "*", "brick/math": "^0.11|^0.12|^0.13", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", "laravel/serializable-closure": "^1.3|^2.0" }, "autoload": { @@ -32,18 +32,18 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-filter": "Required to use the Postgres database driver.", "fakerphp/faker": "Required to use the eloquent factory builder (^1.24).", - "illuminate/console": "Required to use the database commands (^12.0).", - "illuminate/events": "Required to use the observers with Eloquent (^12.0).", - "illuminate/filesystem": "Required to use the migrations (^12.0).", - "illuminate/http": "Required to convert Eloquent models to API resources (^12.0).", - "illuminate/pagination": "Required to paginate the result set (^12.0).", - "symfony/finder": "Required to use Eloquent model factories (^7.2)." + "illuminate/console": "Required to use the database commands (^13.0).", + "illuminate/events": "Required to use the observers with Eloquent (^13.0).", + "illuminate/filesystem": "Required to use the migrations (^13.0).", + "illuminate/http": "Required to convert Eloquent models to API resources (^13.0).", + "illuminate/pagination": "Required to paginate the result set (^13.0).", + "symfony/finder": "Required to use Eloquent model factories (^7.4|^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Encryption/composer.json b/src/Illuminate/Encryption/composer.json index 1c430e9c3e34..1539e86ff687 100644 --- a/src/Illuminate/Encryption/composer.json +++ b/src/Illuminate/Encryption/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-hash": "*", "ext-mbstring": "*", "ext-openssl": "*", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0" + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Events/CallQueuedListener.php b/src/Illuminate/Events/CallQueuedListener.php index e78a4c4e2c5f..13f33e338304 100644 --- a/src/Illuminate/Events/CallQueuedListener.php +++ b/src/Illuminate/Events/CallQueuedListener.php @@ -82,6 +82,13 @@ class CallQueuedListener implements ShouldQueue */ public $shouldBeEncrypted = false; + /** + * Indicates if the job should be deleted when models are missing. + * + * @var bool + */ + public $deleteWhenMissingModels; + /** * Create a new job instance. * diff --git a/src/Illuminate/Events/Dispatcher.php b/src/Illuminate/Events/Dispatcher.php index 08140d9223f3..1b962790e1e0 100755 --- a/src/Illuminate/Events/Dispatcher.php +++ b/src/Illuminate/Events/Dispatcher.php @@ -706,6 +706,7 @@ protected function propagateListenerOptions($listener, $job) $job->timeout = $listener->timeout ?? null; $job->failOnTimeout = $listener->failOnTimeout ?? false; $job->tries = $listener->tries ?? null; + $job->deleteWhenMissingModels = $listener->deleteWhenMissingModels ?? false; $job->through(array_merge( method_exists($listener, 'middleware') ? $listener->middleware(...$data) : [], diff --git a/src/Illuminate/Events/composer.json b/src/Illuminate/Events/composer.json index 801895fd899f..4f3f2b4c62e5 100755 --- a/src/Illuminate/Events/composer.json +++ b/src/Illuminate/Events/composer.json @@ -14,13 +14,13 @@ } ], "require": { - "php": "^8.2", - "illuminate/bus": "^12.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/bus": "^13.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -32,7 +32,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Filesystem/composer.json b/src/Illuminate/Filesystem/composer.json index f5fa95db75a5..13deb8c174fb 100644 --- a/src/Illuminate/Filesystem/composer.json +++ b/src/Illuminate/Filesystem/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "symfony/finder": "^7.2.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", + "symfony/finder": "^7.4.0|^8.0.0" }, "autoload": { "psr-4": { @@ -31,21 +31,21 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-hash": "Required to use the Filesystem class.", - "illuminate/http": "Required for handling uploaded files (^12.0).", + "illuminate/http": "Required for handling uploaded files (^13.0).", "league/flysystem": "Required to use the Flysystem local driver (^3.25.1).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", - "symfony/mime": "Required to enable support for guessing extensions (^7.2)." + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.4|^8.0).", + "symfony/mime": "Required to enable support for guessing extensions (^7.4|^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 436fe9c12674..5fd2090f74e2 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -45,7 +45,7 @@ class Application extends Container implements ApplicationContract, CachesConfig * * @var string */ - const VERSION = '12.25.0'; + const VERSION = '13.x-dev'; /** * The base path for the Laravel installation. diff --git a/src/Illuminate/Hashing/composer.json b/src/Illuminate/Hashing/composer.json index 623485f95dfc..18eec76368bd 100755 --- a/src/Illuminate/Hashing/composer.json +++ b/src/Illuminate/Hashing/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^8.2", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Http/Client/Response.php b/src/Illuminate/Http/Client/Response.php index 27f0899cb517..c3516c03abc4 100644 --- a/src/Illuminate/Http/Client/Response.php +++ b/src/Illuminate/Http/Client/Response.php @@ -323,14 +323,13 @@ public function toException() /** * Throw an exception if a server or client error occurred. * + * @param null|(\Closure(\Illuminate\Http\Client\Response, \Illuminate\Http\Client\RequestException): mixed) $callback * @return $this * * @throws \Illuminate\Http\Client\RequestException */ - public function throw() + public function throw($callback = null) { - $callback = func_get_args()[0] ?? null; - if ($this->failed()) { throw tap($this->toException(), function ($exception) use ($callback) { if ($callback && is_callable($callback)) { @@ -346,13 +345,14 @@ public function throw() * Throw an exception if a server or client error occurred and the given condition evaluates to true. * * @param \Closure|bool $condition + * @param null|(\Closure(\Illuminate\Http\Client\Response, \Illuminate\Http\Client\RequestException): mixed) $callback * @return $this * * @throws \Illuminate\Http\Client\RequestException */ - public function throwIf($condition) + public function throwIf($condition, $callback = null) { - return value($condition, $this) ? $this->throw(func_get_args()[1] ?? null) : $this; + return value($condition, $this) ? $this->throw($callback) : $this; } /** diff --git a/src/Illuminate/Http/composer.json b/src/Illuminate/Http/composer.json index 9681e6060ec4..b0b6d13b5322 100755 --- a/src/Illuminate/Http/composer.json +++ b/src/Illuminate/Http/composer.json @@ -14,20 +14,19 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-filter": "*", "fruitcake/php-cors": "^1.3", "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", - "illuminate/collections": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/session": "^12.0", - "illuminate/support": "^12.0", - "symfony/http-foundation": "^7.2.0", - "symfony/http-kernel": "^7.2.0", - "symfony/polyfill-php83": "^1.31", + "illuminate/collections": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/session": "^13.0", + "illuminate/support": "^13.0", + "symfony/http-foundation": "^7.4.0|^8.0.0", + "symfony/http-kernel": "^7.4.0|^8.0.0", "symfony/polyfill-php85": "^1.31", - "symfony/mime": "^7.2.0" + "symfony/mime": "^7.4.0|^8.0.0" }, "autoload": { "psr-4": { @@ -39,7 +38,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Log/composer.json b/src/Illuminate/Log/composer.json index 201883d80002..7dfa1dcd0d1d 100755 --- a/src/Illuminate/Log/composer.json +++ b/src/Illuminate/Log/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^8.2", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0", "monolog/monolog": "^3.0", "psr/log": "^1.0|^2.0|^3.0" }, @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Macroable/composer.json b/src/Illuminate/Macroable/composer.json index 38dc6f161a42..6c2d4901c89a 100644 --- a/src/Illuminate/Macroable/composer.json +++ b/src/Illuminate/Macroable/composer.json @@ -23,7 +23,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Mail/composer.json b/src/Illuminate/Mail/composer.json index 8df873951555..98497b8352b8 100755 --- a/src/Illuminate/Mail/composer.json +++ b/src/Illuminate/Mail/composer.json @@ -14,15 +14,15 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", "league/commonmark": "^2.7", "psr/log": "^1.0|^2.0|^3.0", - "symfony/mailer": "^7.2.0", + "symfony/mailer": "^7.4.0|^8.0.0", "tijsverkoyen/css-to-inline-styles": "^2.2.5" }, "autoload": { @@ -32,16 +32,16 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "aws/aws-sdk-php": "Required to use the SES mail driver (^3.322.9).", "illuminate/http": "Required to create an attachment from an UploadedFile instance (^12.0).", "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", - "symfony/http-client": "Required to use the Symfony API mail transports (^7.2).", - "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", - "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2)." + "symfony/http-client": "Required to use the Symfony API mail transports (^7.4|^8.0).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.4|^8.0).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.4|^8.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Notifications/composer.json b/src/Illuminate/Notifications/composer.json index 4041897464c5..eee1f69ccfa8 100644 --- a/src/Illuminate/Notifications/composer.json +++ b/src/Illuminate/Notifications/composer.json @@ -14,16 +14,16 @@ } ], "require": { - "php": "^8.2", - "illuminate/broadcasting": "^12.0", - "illuminate/bus": "^12.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/filesystem": "^12.0", - "illuminate/mail": "^12.0", - "illuminate/queue": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/broadcasting": "^13.0", + "illuminate/bus": "^13.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/filesystem": "^13.0", + "illuminate/mail": "^13.0", + "illuminate/queue": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -32,11 +32,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/database": "Required to use the database transport (^12.0)." + "illuminate/database": "Required to use the database transport (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Pagination/composer.json b/src/Illuminate/Pagination/composer.json index b848b4a3b08d..dcb94402aaf9 100755 --- a/src/Illuminate/Pagination/composer.json +++ b/src/Illuminate/Pagination/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-filter": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0" + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Pagination/resources/views/bootstrap-5.blade.php b/src/Illuminate/Pagination/resources/views/bootstrap-5.blade.php index a1795a4d84e3..9dcf5312c242 100644 --- a/src/Illuminate/Pagination/resources/views/bootstrap-5.blade.php +++ b/src/Illuminate/Pagination/resources/views/bootstrap-5.blade.php @@ -27,16 +27,14 @@
-
-

- {!! __('Showing') !!} - {{ $paginator->firstItem() }} - {!! __('to') !!} - {{ $paginator->lastItem() }} - {!! __('of') !!} - {{ $paginator->total() }} - {!! __('results') !!} -

+
+ {!! __('Showing') !!} + {{ $paginator->firstItem() }} + {!! __('to') !!} + {{ $paginator->lastItem() }} + {!! __('of') !!} + {{ $paginator->total() }} + {!! __('results') !!}
diff --git a/src/Illuminate/Pagination/resources/views/tailwind.blade.php b/src/Illuminate/Pagination/resources/views/tailwind.blade.php index aee2ad28e1d1..49916e89e10c 100644 --- a/src/Illuminate/Pagination/resources/views/tailwind.blade.php +++ b/src/Illuminate/Pagination/resources/views/tailwind.blade.php @@ -23,20 +23,18 @@