= $this->Html->link(
$p['sorid'],
diff --git a/app/templates/email/text/potential_match.php b/app/templates/email/text/potential_match.php
index 83641abce..64eee3ccf 100644
--- a/app/templates/email/text/potential_match.php
+++ b/app/templates/email/text/potential_match.php
@@ -30,7 +30,7 @@
-?>
+
A new potential match is available for your review. You may access the
pending request at this URL:
diff --git a/app/vendor/bin/sql-formatter b/app/vendor/bin/sql-formatter
new file mode 100755
index 000000000..de69b8ade
--- /dev/null
+++ b/app/vendor/bin/sql-formatter
@@ -0,0 +1,120 @@
+#!/usr/bin/env php
+realpath = realpath($opened_path) ?: $opened_path;
+ $opened_path = $this->realpath;
+ $this->handle = fopen($this->realpath, $mode);
+ $this->position = 0;
+
+ return (bool) $this->handle;
+ }
+
+ public function stream_read($count)
+ {
+ $data = fread($this->handle, $count);
+
+ if ($this->position === 0) {
+ $data = preg_replace('{^#!.*\r?\n}', '', $data);
+ }
+
+ $this->position += strlen($data);
+
+ return $data;
+ }
+
+ public function stream_cast($castAs)
+ {
+ return $this->handle;
+ }
+
+ public function stream_close()
+ {
+ fclose($this->handle);
+ }
+
+ public function stream_lock($operation)
+ {
+ return $operation ? flock($this->handle, $operation) : true;
+ }
+
+ public function stream_seek($offset, $whence)
+ {
+ if (0 === fseek($this->handle, $offset, $whence)) {
+ $this->position = ftell($this->handle);
+ return true;
+ }
+
+ return false;
+ }
+
+ public function stream_tell()
+ {
+ return $this->position;
+ }
+
+ public function stream_eof()
+ {
+ return feof($this->handle);
+ }
+
+ public function stream_stat()
+ {
+ return array();
+ }
+
+ public function stream_set_option($option, $arg1, $arg2)
+ {
+ return true;
+ }
+
+ public function url_stat($path, $flags)
+ {
+ $path = substr($path, 17);
+ if (file_exists($path)) {
+ return stat($path);
+ }
+
+ return false;
+ }
+ }
+ }
+
+ if (
+ (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
+ || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
+ ) {
+ include("phpvfscomposer://" . __DIR__ . '/..'.'/doctrine/sql-formatter/bin/sql-formatter');
+ exit(0);
+ }
+}
+
+include __DIR__ . '/..'.'/doctrine/sql-formatter/bin/sql-formatter';
diff --git a/app/vendor/bin/validate-json b/app/vendor/bin/validate-json
index 5910c8159..d077db58b 100755
--- a/app/vendor/bin/validate-json
+++ b/app/vendor/bin/validate-json
@@ -108,7 +108,10 @@ if (PHP_VERSION_ID < 80000) {
}
}
- if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
+ if (
+ (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
+ || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
+ ) {
include("phpvfscomposer://" . __DIR__ . '/..'.'/justinrainbow/json-schema/bin/validate-json');
exit(0);
}
diff --git a/app/vendor/cakephp/cakephp/VERSION.txt b/app/vendor/cakephp/cakephp/VERSION.txt
index 7a0262349..7bfb2d629 100644
--- a/app/vendor/cakephp/cakephp/VERSION.txt
+++ b/app/vendor/cakephp/cakephp/VERSION.txt
@@ -16,4 +16,4 @@
// @license https://opensource.org/licenses/mit-license.php MIT License
// +--------------------------------------------------------------------------------------------+ //
////////////////////////////////////////////////////////////////////////////////////////////////////
-4.4.17
+4.6.1
diff --git a/app/vendor/cakephp/cakephp/composer.json b/app/vendor/cakephp/cakephp/composer.json
index 278f11070..0060696c6 100644
--- a/app/vendor/cakephp/cakephp/composer.json
+++ b/app/vendor/cakephp/cakephp/composer.json
@@ -22,11 +22,11 @@
}
],
"require": {
- "php": ">=7.4.0",
+ "php": ">=7.4.0,<9",
"ext-intl": "*",
"ext-json": "*",
"ext-mbstring": "*",
- "cakephp/chronos": "^2.2",
+ "cakephp/chronos": "^2.4.0-RC2",
"composer/ca-bundle": "^1.2",
"laminas/laminas-diactoros": "^2.2.2",
"laminas/laminas-httphandlerrunner": "^1.1 || ^2.0",
@@ -58,7 +58,7 @@
"require-dev": {
"cakephp/cakephp-codesniffer": "^4.5",
"mikey179/vfsstream": "^1.6.10",
- "paragonie/csp-builder": "^2.3",
+ "paragonie/csp-builder": "^2.3 || ^3.0",
"phpunit/phpunit": "^8.5 || ^9.3"
},
"suggest": {
@@ -88,6 +88,7 @@
},
"files": [
"src/Core/functions.php",
+ "src/Error/functions.php",
"src/Collection/functions.php",
"src/I18n/functions.php",
"src/Routing/functions.php",
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Cache.php b/app/vendor/cakephp/cakephp/src/Cache/Cache.php
index 0c8d8d37f..b91032291 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/Cache.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/Cache.php
@@ -17,8 +17,11 @@
namespace Cake\Cache;
use Cake\Cache\Engine\NullEngine;
+use Cake\Cache\Exception\CacheWriteException;
+use Cake\Cache\Exception\InvalidArgumentException;
use Cake\Core\StaticConfigTrait;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
/**
* Cache provides a consistent interface to Caching in your application. It allows you
@@ -136,7 +139,7 @@ public static function setRegistry(CacheRegistry $registry): void
* Finds and builds the instance of the required engine class.
*
* @param string $name Name of the config array that needs an engine instance built
- * @throws \Cake\Cache\InvalidArgumentException When a cache engine cannot be created.
+ * @throws \Cake\Cache\Exception\InvalidArgumentException When a cache engine cannot be created.
* @throws \RuntimeException If loading of the engine failed.
* @return void
*/
@@ -265,15 +268,12 @@ public static function write(string $key, $value, string $config = 'default'): b
$backend = static::pool($config);
$success = $backend->set($key, $value);
if ($success === false && $value !== '') {
- trigger_error(
- sprintf(
- "%s cache was unable to write '%s' to %s cache",
- $config,
- $key,
- get_class($backend)
- ),
- E_USER_WARNING
- );
+ throw new CacheWriteException(sprintf(
+ "%s cache was unable to write '%s' to %s cache",
+ $config,
+ $key,
+ get_class($backend)
+ ));
}
return $success;
@@ -299,7 +299,7 @@ public static function write(string $key, $value, string $config = 'default'): b
* @param iterable $data An array or Traversable of data to be stored in the cache
* @param string $config Optional string configuration name to write to. Defaults to 'default'
* @return bool True on success, false on failure
- * @throws \Cake\Cache\InvalidArgumentException
+ * @throws \Cake\Cache\Exception\InvalidArgumentException
*/
public static function writeMany(iterable $data, string $config = 'default'): bool
{
@@ -354,7 +354,7 @@ public static function read(string $key, string $config = 'default')
* @param string $config optional name of the configuration to use. Defaults to 'default'
* @return iterable An array containing, for each of the given $keys,
* the cached data or false if cached data could not be retrieved.
- * @throws \Cake\Cache\InvalidArgumentException
+ * @throws \Cake\Cache\Exception\InvalidArgumentException
*/
public static function readMany(iterable $keys, string $config = 'default'): iterable
{
@@ -369,7 +369,7 @@ public static function readMany(iterable $keys, string $config = 'default'): ite
* @param string $config Optional string configuration name. Defaults to 'default'
* @return int|false New value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it.
- * @throws \Cake\Cache\InvalidArgumentException When offset < 0
+ * @throws \Cake\Cache\Exception\InvalidArgumentException When offset < 0
*/
public static function increment(string $key, int $offset = 1, string $config = 'default')
{
@@ -388,7 +388,7 @@ public static function increment(string $key, int $offset = 1, string $config =
* @param string $config Optional string configuration name. Defaults to 'default'
* @return int|false New value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it
- * @throws \Cake\Cache\InvalidArgumentException when offset < 0
+ * @throws \Cake\Cache\Exception\InvalidArgumentException when offset < 0
*/
public static function decrement(string $key, int $offset = 1, string $config = 'default')
{
@@ -445,7 +445,7 @@ public static function delete(string $key, string $config = 'default'): bool
* @param iterable $keys Array or Traversable of cache keys to be deleted
* @param string $config name of the configuration to use. Defaults to 'default'
* @return bool True on success, false on failure.
- * @throws \Cake\Cache\InvalidArgumentException
+ * @throws \Cake\Cache\Exception\InvalidArgumentException
*/
public static function deleteMany(iterable $keys, string $config = 'default'): bool
{
@@ -505,7 +505,7 @@ public static function clearGroup(string $group, string $config = 'default'): bo
*
* @param string|null $group Group name or null to retrieve all group mappings
* @return array Map of group and all configuration that has the same group
- * @throws \Cake\Cache\InvalidArgumentException
+ * @throws \Cake\Cache\Exception\InvalidArgumentException
*/
public static function groupConfigs(?string $group = null): array
{
diff --git a/app/vendor/cakephp/cakephp/src/Cache/CacheEngine.php b/app/vendor/cakephp/cakephp/src/Cache/CacheEngine.php
index da5bcc719..b37fc672f 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/CacheEngine.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/CacheEngine.php
@@ -16,10 +16,12 @@
*/
namespace Cake\Cache;
+use Cake\Cache\Exception\InvalidArgumentException;
use Cake\Core\InstanceConfigTrait;
use DateInterval;
use DateTime;
use Psr\SimpleCache\CacheInterface;
+use function Cake\Core\triggerWarning;
/**
* Storage engine for CakePHP caching
@@ -96,7 +98,7 @@ public function init(array $config = []): bool
*
* @param string $key Key to check.
* @return void
- * @throws \Cake\Cache\InvalidArgumentException When the key is not valid.
+ * @throws \Cake\Cache\Exception\InvalidArgumentException When the key is not valid.
*/
protected function ensureValidKey($key): void
{
@@ -111,7 +113,7 @@ protected function ensureValidKey($key): void
* @param iterable $iterable The iterable to check.
* @param string $check Whether to check keys or values.
* @return void
- * @throws \Cake\Cache\InvalidArgumentException
+ * @throws \Cake\Cache\Exception\InvalidArgumentException
*/
protected function ensureValidType($iterable, string $check = self::CHECK_VALUE): void
{
@@ -137,7 +139,7 @@ protected function ensureValidType($iterable, string $check = self::CHECK_VALUE)
* @param iterable $keys A list of keys that can obtained in a single operation.
* @param mixed $default Default value to return for keys that do not exist.
* @return iterable A list of key value pairs. Cache keys that do not exist or are stale will have $default as value.
- * @throws \Cake\Cache\InvalidArgumentException If $keys is neither an array nor a Traversable,
+ * @throws \Cake\Cache\Exception\InvalidArgumentException If $keys is neither an array nor a Traversable,
* or if any of the $keys are not a legal value.
*/
public function getMultiple($keys, $default = null): iterable
@@ -160,7 +162,7 @@ public function getMultiple($keys, $default = null): iterable
* the driver supports TTL then the library may set a default value
* for it or let the driver take care of that.
* @return bool True on success and false on failure.
- * @throws \Cake\Cache\InvalidArgumentException If $values is neither an array nor a Traversable,
+ * @throws \Cake\Cache\Exception\InvalidArgumentException If $values is neither an array nor a Traversable,
* or if any of the $values are not a legal value.
*/
public function setMultiple($values, $ttl = null): bool
@@ -196,7 +198,7 @@ public function setMultiple($values, $ttl = null): bool
*
* @param iterable $keys A list of string-based keys to be deleted.
* @return bool True if the items were successfully removed. False if there was an error.
- * @throws \Cake\Cache\InvalidArgumentException If $keys is neither an array nor a Traversable,
+ * @throws \Cake\Cache\Exception\InvalidArgumentException If $keys is neither an array nor a Traversable,
* or if any of the $keys are not a legal value.
*/
public function deleteMultiple($keys): bool
@@ -223,7 +225,7 @@ public function deleteMultiple($keys): bool
*
* @param string $key The cache item key.
* @return bool
- * @throws \Cake\Cache\InvalidArgumentException If the $key string is not a legal value.
+ * @throws \Cake\Cache\Exception\InvalidArgumentException If the $key string is not a legal value.
*/
public function has($key): bool
{
@@ -236,7 +238,7 @@ public function has($key): bool
* @param string $key The unique key of this item in the cache.
* @param mixed $default Default value to return if the key does not exist.
* @return mixed The value of the item from the cache, or $default in case of cache miss.
- * @throws \Cake\Cache\InvalidArgumentException If the $key string is not a legal value.
+ * @throws \Cake\Cache\Exception\InvalidArgumentException If the $key string is not a legal value.
*/
abstract public function get($key, $default = null);
@@ -249,7 +251,7 @@ abstract public function get($key, $default = null);
* the driver supports TTL then the library may set a default value
* for it or let the driver take care of that.
* @return bool True on success and false on failure.
- * @throws \Cake\Cache\InvalidArgumentException
+ * @throws \Cake\Cache\Exception\InvalidArgumentException
* MUST be thrown if the $key string is not a legal value.
*/
abstract public function set($key, $value, $ttl = null): bool;
@@ -337,7 +339,7 @@ public function groups(): array
*
* @param string $key the key passed over
* @return string Prefixed key with potentially unsafe characters replaced.
- * @throws \Cake\Cache\InvalidArgumentException If key's value is invalid.
+ * @throws \Cake\Cache\Exception\InvalidArgumentException If key's value is invalid.
*/
protected function _key($key): string
{
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Engine/FileEngine.php b/app/vendor/cakephp/cakephp/src/Cache/Engine/FileEngine.php
index 35252b98e..9e786787a 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/Engine/FileEngine.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/Engine/FileEngine.php
@@ -50,6 +50,7 @@ class FileEngine extends CacheEngine
* handy for deleting a complete group from cache.
* - `lock` Used by FileCache. Should files be locked before writing to them?
* - `mask` The mask used for created files
+ * - `dirMask` The mask used for created folders
* - `path` Path to where cachefiles should be saved. Defaults to system's temp dir.
* - `prefix` Prepended to all entries. Good for when you need to share a keyspace
* with either another cache config or another application.
@@ -63,6 +64,7 @@ class FileEngine extends CacheEngine
'groups' => [],
'lock' => true,
'mask' => 0664,
+ 'dirMask' => 0770,
'path' => null,
'prefix' => 'cake_',
'serialize' => true,
@@ -371,7 +373,7 @@ protected function _setKey(string $key, bool $createKey = false): bool
$dir = $this->_config['path'] . $groups;
if (!is_dir($dir)) {
- mkdir($dir, 0775, true);
+ mkdir($dir, $this->_config['dirMask'], true);
}
$path = new SplFileInfo($dir . $key);
@@ -418,7 +420,7 @@ protected function _active(): bool
$success = true;
if (!is_dir($path)) {
// phpcs:disable
- $success = @mkdir($path, 0775, true);
+ $success = @mkdir($path, $this->_config['dirMask'], true);
// phpcs:enable
}
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php b/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php
index b714f5056..687987603 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/Engine/MemcachedEngine.php
@@ -17,7 +17,7 @@
namespace Cake\Cache\Engine;
use Cake\Cache\CacheEngine;
-use InvalidArgumentException;
+use Cake\Cache\Exception\InvalidArgumentException;
use Memcached;
use RuntimeException;
@@ -98,7 +98,7 @@ class MemcachedEngine extends CacheEngine
*
* @param array $config array of setting for the engine
* @return bool True if the engine has been successfully initialized, false if not
- * @throws \InvalidArgumentException When you try use authentication without
+ * @throws \Cake\Cache\Exception\InvalidArgumentException When you try use authentication without
* Memcached compiled with SASL support
*/
public function init(array $config = []): bool
@@ -199,7 +199,7 @@ public function init(array $config = []): bool
* Settings the memcached instance
*
* @return void
- * @throws \InvalidArgumentException When the Memcached extension is not built
+ * @throws \Cake\Cache\Exception\InvalidArgumentException When the Memcached extension is not built
* with the desired serializer engine.
*/
protected function _setOptions(): void
@@ -365,7 +365,7 @@ public function getMultiple($keys, $default = null): array
$values = $this->_Memcached->getMulti($cacheKeys);
$return = [];
foreach ($cacheKeys as $original => $prefixed) {
- $return[$original] = $values[$prefixed] ?? $default;
+ $return[$original] = array_key_exists($prefixed, $values) ? $values[$prefixed] : $default;
}
return $return;
@@ -437,7 +437,7 @@ public function clear(): bool
}
foreach ($keys as $key) {
- if (strpos($key, $this->_config['prefix']) === 0) {
+ if ($this->_config['prefix'] === '' || strpos($key, $this->_config['prefix']) === 0) {
$this->_Memcached->delete($key);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php b/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php
index 4612a276b..89defe467 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/Engine/NullEngine.php
@@ -62,7 +62,13 @@ public function get($key, $default = null)
*/
public function getMultiple($keys, $default = null): iterable
{
- return [];
+ $result = [];
+
+ foreach ($keys as $key) {
+ $result[$key] = $default;
+ }
+
+ return $result;
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Engine/RedisEngine.php b/app/vendor/cakephp/cakephp/src/Cache/Engine/RedisEngine.php
index dc90ef72f..cdd479fb2 100644
--- a/app/vendor/cakephp/cakephp/src/Cache/Engine/RedisEngine.php
+++ b/app/vendor/cakephp/cakephp/src/Cache/Engine/RedisEngine.php
@@ -45,6 +45,7 @@ class RedisEngine extends CacheEngine
* - `password` Redis server password.
* - `persistent` Connect to the Redis server with a persistent connection
* - `port` port number to the Redis server.
+ * - `tls` connect to the Redis server using TLS.
* - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
* with either another cache config or another application.
* - `scanCount` Number of keys to ask for each scan (default: 10)
@@ -61,6 +62,7 @@ class RedisEngine extends CacheEngine
'password' => false,
'persistent' => true,
'port' => 6379,
+ 'tls' => false,
'prefix' => 'cake_',
'host' => null,
'server' => '127.0.0.1',
@@ -99,24 +101,29 @@ public function init(array $config = []): bool
*/
protected function _connect(): bool
{
+ $tls = $this->_config['tls'] === true ? 'tls://' : '';
+
+ $map = [
+ 'ssl_ca' => 'cafile',
+ 'ssl_key' => 'local_pk',
+ 'ssl_cert' => 'local_cert',
+ ];
+
+ $ssl = [];
+ foreach ($map as $key => $context) {
+ if (!empty($this->_config[$key])) {
+ $ssl[$context] = $this->_config[$key];
+ }
+ }
+
try {
- $this->_Redis = new Redis();
+ $this->_Redis = $this->_createRedisInstance();
if (!empty($this->_config['unix_socket'])) {
$return = $this->_Redis->connect($this->_config['unix_socket']);
} elseif (empty($this->_config['persistent'])) {
- $return = $this->_Redis->connect(
- $this->_config['server'],
- (int)$this->_config['port'],
- (int)$this->_config['timeout']
- );
+ $return = $this->_connectTransient($tls . $this->_config['server'], $ssl);
} else {
- $persistentId = $this->_config['port'] . $this->_config['timeout'] . $this->_config['database'];
- $return = $this->_Redis->pconnect(
- $this->_config['server'],
- (int)$this->_config['port'],
- (int)$this->_config['timeout'],
- $persistentId
- );
+ $return = $this->_connectPersistent($tls . $this->_config['server'], $ssl);
}
} catch (RedisException $e) {
if (class_exists(Log::class)) {
@@ -135,6 +142,67 @@ protected function _connect(): bool
return $return;
}
+ /**
+ * Connects to a Redis server using a new connection.
+ *
+ * @param string $server Server to connect to.
+ * @param array $ssl SSL context options.
+ * @throws \RedisException
+ * @return bool True if Redis server was connected
+ */
+ protected function _connectTransient($server, array $ssl): bool
+ {
+ if (empty($ssl)) {
+ return $this->_Redis->connect(
+ $server,
+ (int)$this->_config['port'],
+ (int)$this->_config['timeout']
+ );
+ }
+
+ return $this->_Redis->connect(
+ $server,
+ (int)$this->_config['port'],
+ (int)$this->_config['timeout'],
+ null,
+ 0,
+ 0.0,
+ ['ssl' => $ssl]
+ );
+ }
+
+ /**
+ * Connects to a Redis server using a persistent connection.
+ *
+ * @param string $server Server to connect to.
+ * @param array $ssl SSL context options.
+ * @throws \RedisException
+ * @return bool True if Redis server was connected
+ */
+ protected function _connectPersistent($server, array $ssl): bool
+ {
+ $persistentId = $this->_config['port'] . $this->_config['timeout'] . $this->_config['database'];
+
+ if (empty($ssl)) {
+ return $this->_Redis->pconnect(
+ $server,
+ (int)$this->_config['port'],
+ (int)$this->_config['timeout'],
+ $persistentId
+ );
+ }
+
+ return $this->_Redis->pconnect(
+ $server,
+ (int)$this->_config['port'],
+ (int)$this->_config['timeout'],
+ $persistentId,
+ 0,
+ 0.0,
+ ['ssl' => $ssl]
+ );
+ }
+
/**
* Write data for key into cache.
*
@@ -394,6 +462,16 @@ protected function unserialize(string $value)
return unserialize($value);
}
+ /**
+ * Create new Redis instance.
+ *
+ * @return \Redis
+ */
+ protected function _createRedisInstance(): Redis
+ {
+ return new Redis();
+ }
+
/**
* Disconnects from the redis server
*/
diff --git a/app/vendor/cakephp/cakephp/src/Cache/Exception/CacheWriteException.php b/app/vendor/cakephp/cakephp/src/Cache/Exception/CacheWriteException.php
new file mode 100644
index 000000000..241ef6539
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Cache/Exception/CacheWriteException.php
@@ -0,0 +1,27 @@
+>
*/
class Collection extends IteratorIterator implements CollectionInterface, Serializable
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/CollectionInterface.php b/app/vendor/cakephp/cakephp/src/Collection/CollectionInterface.php
index 7e50cfced..1fcd3a1ab 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/CollectionInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/CollectionInterface.php
@@ -24,6 +24,8 @@
* Describes the methods a Collection should implement. A collection is an immutable
* list of elements exposing a number of traversing and extracting method for
* generating other collections.
+ *
+ * @template-extends \Iterator
*/
interface CollectionInterface extends Iterator, JsonSerializable
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/CollectionTrait.php b/app/vendor/cakephp/cakephp/src/Collection/CollectionTrait.php
index 010b06a63..7cee96969 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/CollectionTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/CollectionTrait.php
@@ -591,14 +591,37 @@ public function combine($keyPath, $valuePath, $groupPath = null): CollectionInte
$rowVal = $options['valuePath'];
if (!$options['groupPath']) {
- $mapReduce->emit($rowVal($value, $key), $rowKey($value, $key));
+ $mapKey = $rowKey($value, $key);
+ if ($mapKey === null) {
+ throw new InvalidArgumentException(
+ 'Cannot index by path that does not exist or contains a null value. ' .
+ 'Use a callback to return a default value for that path.'
+ );
+ }
+
+ $mapReduce->emit($rowVal($value, $key), $mapKey);
return null;
}
$key = $options['groupPath']($value, $key);
+ if ($key === null) {
+ throw new InvalidArgumentException(
+ 'Cannot group by path that does not exist or contains a null value. ' .
+ 'Use a callback to return a default value for that path.'
+ );
+ }
+
+ $mapKey = $rowKey($value, $key);
+ if ($mapKey === null) {
+ throw new InvalidArgumentException(
+ 'Cannot index by path that does not exist or contains a null value. ' .
+ 'Use a callback to return a default value for that path.'
+ );
+ }
+
$mapReduce->emitIntermediate(
- [$rowKey($value, $key) => $rowVal($value, $key)],
+ [$mapKey => $rowVal($value, $key)],
$key
);
};
diff --git a/app/vendor/cakephp/cakephp/src/Collection/Iterator/MapReduce.php b/app/vendor/cakephp/cakephp/src/Collection/Iterator/MapReduce.php
index 6e3048c7d..0ea3368fe 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/Iterator/MapReduce.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/Iterator/MapReduce.php
@@ -25,6 +25,8 @@
* like an iterator for the original passed data after each result has been
* processed, thus offering a transparent wrapper for results coming from any
* source.
+ *
+ * @template-implements \IteratorAggregate
*/
class MapReduce implements IteratorAggregate
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/Iterator/NestIterator.php b/app/vendor/cakephp/cakephp/src/Collection/Iterator/NestIterator.php
index c60c39b2f..831bc46fa 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/Iterator/NestIterator.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/Iterator/NestIterator.php
@@ -23,6 +23,8 @@
/**
* A type of collection that is aware of nested items and exposes methods to
* check or retrieve them
+ *
+ * @template-implements \RecursiveIterator
*/
class NestIterator extends Collection implements RecursiveIterator
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/Iterator/NoChildrenIterator.php b/app/vendor/cakephp/cakephp/src/Collection/Iterator/NoChildrenIterator.php
index ed940c1c4..53f5ceb79 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/Iterator/NoChildrenIterator.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/Iterator/NoChildrenIterator.php
@@ -23,6 +23,8 @@
* An iterator that can be used as an argument for other iterators that require
* a RecursiveIterator but do not want children. This iterator will
* always behave as having no nested items.
+ *
+ * @template-implements \RecursiveIterator
*/
class NoChildrenIterator extends Collection implements RecursiveIterator
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreeIterator.php b/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreeIterator.php
index 49a28fe01..e8072db31 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreeIterator.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreeIterator.php
@@ -24,6 +24,8 @@
/**
* A Recursive iterator used to flatten nested structures and also exposes
* all Collection methods
+ *
+ * @template-extends \RecursiveIteratorIterator<\RecursiveIterator>
*/
class TreeIterator extends RecursiveIteratorIterator implements CollectionInterface
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreePrinter.php b/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreePrinter.php
index d509d471a..0942b0f18 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreePrinter.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/Iterator/TreePrinter.php
@@ -24,6 +24,8 @@
/**
* Iterator for flattening elements in a tree structure while adding some
* visual markers for their relative position in the tree
+ *
+ * @template-extends \RecursiveIteratorIterator<\RecursiveIterator>
*/
class TreePrinter extends RecursiveIteratorIterator implements CollectionInterface
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/Iterator/UnfoldIterator.php b/app/vendor/cakephp/cakephp/src/Collection/Iterator/UnfoldIterator.php
index 017373ebc..db284c1aa 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/Iterator/UnfoldIterator.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/Iterator/UnfoldIterator.php
@@ -26,6 +26,8 @@
*
* @internal
* @see \Cake\Collection\Collection::unfold()
+ * @template-implements \RecursiveIterator
+ * @template-extends \IteratorIterator>
*/
class UnfoldIterator extends IteratorIterator implements RecursiveIterator
{
diff --git a/app/vendor/cakephp/cakephp/src/Collection/functions.php b/app/vendor/cakephp/cakephp/src/Collection/functions.php
index 0440f10ff..b3bbfb9eb 100644
--- a/app/vendor/cakephp/cakephp/src/Collection/functions.php
+++ b/app/vendor/cakephp/cakephp/src/Collection/functions.php
@@ -1,4 +1,5 @@
setDescription('Clear all data in a single cache group.');
+ $parser->addArgument('group', [
+ 'help' => 'The cache group to clear. For example, `cake cache clear_group mygroup` will clear ' .
+ 'all cache items belonging to group "mygroup".',
+ 'required' => true,
+ ]);
+ $parser->addArgument('config', [
+ 'help' => 'Name of the configuration to use. Defaults to no value which clears all cache configurations.',
+ ]);
+
+ return $parser;
+ }
+
+ /**
+ * Clears the cache group
+ *
+ * @param \Cake\Console\Arguments $args The command arguments.
+ * @param \Cake\Console\ConsoleIo $io The console io
+ * @return int|null The exit code or null for success
+ */
+ public function execute(Arguments $args, ConsoleIo $io): ?int
+ {
+ $group = (string)$args->getArgument('group');
+ try {
+ $groupConfigs = Cache::groupConfigs($group);
+ } catch (InvalidArgumentException $e) {
+ $io->error(sprintf('Cache group "%s" not found', $group));
+
+ return static::CODE_ERROR;
+ }
+
+ $config = $args->getArgument('config');
+ if ($config !== null && Cache::getConfig($config) === null) {
+ $io->error(sprintf('Cache config "%s" not found', $config));
+
+ return static::CODE_ERROR;
+ }
+
+ foreach ($groupConfigs[$group] as $groupConfig) {
+ if ($config !== null && $config !== $groupConfig) {
+ continue;
+ }
+
+ if (!Cache::clearGroup($group, $groupConfig)) {
+ $io->error(sprintf(
+ 'Error encountered clearing group "%s". Was unable to clear entries for "%s".',
+ $group,
+ $groupConfig
+ ));
+ $this->abort();
+ } else {
+ $io->success(sprintf('Cache "%s" was cleared.', $groupConfig));
+ }
+ }
+
+ return static::CODE_SUCCESS;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Command/I18nExtractCommand.php b/app/vendor/cakephp/cakephp/src/Command/I18nExtractCommand.php
index 724783bcf..1b6a04252 100644
--- a/app/vendor/cakephp/cakephp/src/Command/I18nExtractCommand.php
+++ b/app/vendor/cakephp/cakephp/src/Command/I18nExtractCommand.php
@@ -133,7 +133,7 @@ protected function _getPaths(ConsoleIo $io): void
/** @psalm-suppress UndefinedConstant */
$defaultPaths = array_merge(
[APP],
- App::path('templates'),
+ array_values(App::path('templates')),
['D'] // This is required to break the loop below
);
$defaultPathIndex = 0;
@@ -217,7 +217,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
. 'locales' . DIRECTORY_SEPARATOR;
} else {
$message = "What is the path you would like to output?\n[Q]uit";
- $localePaths = App::path('locales');
+ $localePaths = array_values(App::path('locales'));
if (!$localePaths) {
$localePaths[] = ROOT . 'resources' . DIRECTORY_SEPARATOR . 'locales';
}
diff --git a/app/vendor/cakephp/cakephp/src/Command/I18nInitCommand.php b/app/vendor/cakephp/cakephp/src/Command/I18nInitCommand.php
index ff2806888..39bbf5b83 100644
--- a/app/vendor/cakephp/cakephp/src/Command/I18nInitCommand.php
+++ b/app/vendor/cakephp/cakephp/src/Command/I18nInitCommand.php
@@ -56,7 +56,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
return static::CODE_ERROR;
}
- $paths = App::path('locales');
+ $paths = array_values(App::path('locales'));
if ($args->hasOption('plugin')) {
$plugin = Inflector::camelize((string)$args->getOption('plugin'));
$paths = [Plugin::path($plugin) . 'resources' . DIRECTORY_SEPARATOR . 'locales' . DIRECTORY_SEPARATOR];
@@ -66,7 +66,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
$sourceFolder = rtrim($response, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$targetFolder = $sourceFolder . $language . DIRECTORY_SEPARATOR;
if (!is_dir($targetFolder)) {
- mkdir($targetFolder, 0775, true);
+ mkdir($targetFolder, 0770, true);
}
$count = 0;
diff --git a/app/vendor/cakephp/cakephp/src/Command/ServerCommand.php b/app/vendor/cakephp/cakephp/src/Command/ServerCommand.php
index 69f1203a0..8019638f9 100644
--- a/app/vendor/cakephp/cakephp/src/Command/ServerCommand.php
+++ b/app/vendor/cakephp/cakephp/src/Command/ServerCommand.php
@@ -21,6 +21,7 @@
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
use Cake\Core\Configure;
+use function Cake\Core\env;
/**
* built-in Server command
diff --git a/app/vendor/cakephp/cakephp/src/Console/BaseCommand.php b/app/vendor/cakephp/cakephp/src/Console/BaseCommand.php
index c927ccf80..b9b13e47a 100644
--- a/app/vendor/cakephp/cakephp/src/Console/BaseCommand.php
+++ b/app/vendor/cakephp/cakephp/src/Console/BaseCommand.php
@@ -21,6 +21,7 @@
use Cake\Utility\Inflector;
use InvalidArgumentException;
use RuntimeException;
+use function Cake\Core\getTypeName;
/**
* Base class for console commands.
@@ -238,7 +239,7 @@ protected function setOutputLevel(Arguments $args, ConsoleIo $io): void
abstract public function execute(Arguments $args, ConsoleIo $io);
/**
- * Halt the the current process with a StopException.
+ * Halt the current process with a StopException.
*
* @param int $code The exit code to use.
* @throws \Cake\Console\Exception\StopException
diff --git a/app/vendor/cakephp/cakephp/src/Console/Command.php b/app/vendor/cakephp/cakephp/src/Console/Command.php
index 9494b024a..5062c8ddc 100644
--- a/app/vendor/cakephp/cakephp/src/Console/Command.php
+++ b/app/vendor/cakephp/cakephp/src/Console/Command.php
@@ -1,7 +1,9 @@
>
*/
class CommandCollection implements IteratorAggregate, Countable
{
@@ -127,7 +129,7 @@ public function has(string $name): bool
* Get the target for a command.
*
* @param string $name The named shell.
- * @return \Cake\Console\CommandInterface|\Cake\Console\Shell|string Either the command class or an instance.
+ * @return \Cake\Console\CommandInterface|\Cake\Console\Shell|class-string<\Cake\Console\CommandInterface> Either the command class or an instance.
* @throws \InvalidArgumentException when unknown commands are fetched.
* @psalm-return \Cake\Console\CommandInterface|\Cake\Console\Shell|class-string
*/
@@ -144,7 +146,7 @@ public function get(string $name)
* Implementation of IteratorAggregate.
*
* @return \Traversable
- * @psalm-return \Traversable
+ * @psalm-return \Traversable)>
*/
public function getIterator(): Traversable
{
diff --git a/app/vendor/cakephp/cakephp/src/Console/ConsoleErrorHandler.php b/app/vendor/cakephp/cakephp/src/Console/ConsoleErrorHandler.php
index cac0d22f5..27fcf22f8 100644
--- a/app/vendor/cakephp/cakephp/src/Console/ConsoleErrorHandler.php
+++ b/app/vendor/cakephp/cakephp/src/Console/ConsoleErrorHandler.php
@@ -1,7 +1,10 @@
$choices Valid choices for this option.
+ * @param string|null $default The default value for this argument.
*/
- public function __construct($name, $help = '', $required = false, $choices = [])
+ public function __construct($name, $help = '', $required = false, $choices = [], $default = null)
{
if (is_array($name) && isset($name['name'])) {
foreach ($name as $key => $value) {
@@ -75,6 +83,7 @@ public function __construct($name, $help = '', $required = false, $choices = [])
$this->_help = $help;
$this->_required = $required;
$this->_choices = $choices;
+ $this->_default = $default;
}
}
@@ -119,6 +128,9 @@ public function help(int $width = 0): string
if ($this->_choices) {
$optional .= sprintf(' (choices: %s)', implode('|', $this->_choices));
}
+ if ($this->_default !== null) {
+ $optional .= sprintf(' default: "%s"', $this->_default);
+ }
return sprintf('%s%s%s', $name, $this->_help, $optional);
}
@@ -142,6 +154,16 @@ public function usage(): string
return $name;
}
+ /**
+ * Get the default value for this argument
+ *
+ * @return string|null
+ */
+ public function defaultValue()
+ {
+ return $this->_default;
+ }
+
/**
* Check if this argument is a required argument
*
@@ -194,6 +216,9 @@ public function xml(SimpleXMLElement $parent): SimpleXMLElement
foreach ($this->_choices as $valid) {
$choices->addChild('choice', $valid);
}
+ if ($this->_default !== null) {
+ $option->addAttribute('default', $this->_default);
+ }
return $parent;
}
diff --git a/app/vendor/cakephp/cakephp/src/Console/ConsoleIo.php b/app/vendor/cakephp/cakephp/src/Console/ConsoleIo.php
index 583873800..4e5e9c7ea 100644
--- a/app/vendor/cakephp/cakephp/src/Console/ConsoleIo.php
+++ b/app/vendor/cakephp/cakephp/src/Console/ConsoleIo.php
@@ -207,7 +207,7 @@ public function out($message = '', int $newlines = 1, int $level = self::NORMAL)
}
/**
- * Convenience method for out() that wraps message between tag
+ * Convenience method for out() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
@@ -225,7 +225,7 @@ public function info($message, int $newlines = 1, int $level = self::NORMAL): ?i
}
/**
- * Convenience method for out() that wraps message between tag
+ * Convenience method for out() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
@@ -243,7 +243,7 @@ public function comment($message, int $newlines = 1, int $level = self::NORMAL):
}
/**
- * Convenience method for err() that wraps message between tag
+ * Convenience method for err() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
@@ -259,7 +259,7 @@ public function warning($message, int $newlines = 1): int
}
/**
- * Convenience method for err() that wraps message between tag
+ * Convenience method for err() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
@@ -275,7 +275,7 @@ public function error($message, int $newlines = 1): int
}
/**
- * Convenience method for out() that wraps message between tag
+ * Convenience method for out() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
diff --git a/app/vendor/cakephp/cakephp/src/Console/ConsoleOptionParser.php b/app/vendor/cakephp/cakephp/src/Console/ConsoleOptionParser.php
index b20775a1d..eee1c8b4f 100644
--- a/app/vendor/cakephp/cakephp/src/Console/ConsoleOptionParser.php
+++ b/app/vendor/cakephp/cakephp/src/Console/ConsoleOptionParser.php
@@ -691,10 +691,23 @@ public function parse(array $argv, ?ConsoleIo $io = null): array
/** @psalm-suppress PossiblyNullReference */
return $this->_subcommands[$command]->parser()->parse($argv, $io);
}
+
$params = $args = [];
$this->_tokens = $argv;
+
+ $afterDoubleDash = false;
while (($token = array_shift($this->_tokens)) !== null) {
$token = (string)$token;
+ if ($token === '--') {
+ $afterDoubleDash = true;
+ continue;
+ }
+ if ($afterDoubleDash) {
+ // only positional arguments after --
+ $args = $this->_parseArg($token, $args);
+ continue;
+ }
+
if (isset($this->_subcommands[$token])) {
continue;
}
@@ -712,10 +725,15 @@ public function parse(array $argv, ?ConsoleIo $io = null): array
}
foreach ($this->_args as $i => $arg) {
- if ($arg->isRequired() && !isset($args[$i])) {
- throw new ConsoleException(
- sprintf('Missing required argument. The `%s` argument is required.', $arg->name())
- );
+ if (!isset($args[$i])) {
+ if ($arg->isRequired()) {
+ throw new ConsoleException(
+ sprintf('Missing required argument. The `%s` argument is required.', $arg->name())
+ );
+ }
+ if ($arg->defaultValue() !== null) {
+ $args[$i] = $arg->defaultValue();
+ }
}
}
foreach ($this->_options as $option) {
diff --git a/app/vendor/cakephp/cakephp/src/Console/ConsoleOutput.php b/app/vendor/cakephp/cakephp/src/Console/ConsoleOutput.php
index c11101875..4c7ea902a 100644
--- a/app/vendor/cakephp/cakephp/src/Console/ConsoleOutput.php
+++ b/app/vendor/cakephp/cakephp/src/Console/ConsoleOutput.php
@@ -16,7 +16,9 @@
*/
namespace Cake\Console;
+use Cake\Console\Exception\ConsoleException;
use InvalidArgumentException;
+use function Cake\Core\env;
/**
* Object wrapper for outputting information from a shell application.
@@ -160,11 +162,20 @@ class ConsoleOutput
* Checks for a pretty console environment. Ansicon and ConEmu allows
* pretty consoles on Windows, and is supported.
*
- * @param string $stream The identifier of the stream to write output to.
+ * @param string|resource $stream The identifier of the stream to write output to.
+ * @throws \Cake\Console\Exception\ConsoleException If the given stream is not a valid resource.
*/
- public function __construct(string $stream = 'php://stdout')
+ public function __construct($stream = 'php://stdout')
{
- $this->_output = fopen($stream, 'wb');
+ if (is_string($stream)) {
+ $stream = fopen($stream, 'wb');
+ }
+
+ if (!is_resource($stream)) {
+ throw new ConsoleException('Invalid stream in constructor. It is not a valid resource.');
+ }
+
+ $this->_output = $stream;
if (
(
diff --git a/app/vendor/cakephp/cakephp/src/Console/Shell.php b/app/vendor/cakephp/cakephp/src/Console/Shell.php
index 636216766..46bdda200 100644
--- a/app/vendor/cakephp/cakephp/src/Console/Shell.php
+++ b/app/vendor/cakephp/cakephp/src/Console/Shell.php
@@ -31,6 +31,7 @@
use ReflectionException;
use ReflectionMethod;
use RuntimeException;
+use function Cake\Core\namespaceSplit;
/**
* Base class for command-line utilities for automating programmer chores.
@@ -719,7 +720,7 @@ public function err($message, int $newlines = 1): int
}
/**
- * Convenience method for out() that wraps message between tag
+ * Convenience method for out() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
@@ -733,7 +734,7 @@ public function info($message, int $newlines = 1, int $level = Shell::NORMAL): ?
}
/**
- * Convenience method for err() that wraps message between tag
+ * Convenience method for err() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
@@ -746,7 +747,7 @@ public function warn($message, int $newlines = 1): int
}
/**
- * Convenience method for out() that wraps message between tag
+ * Convenience method for out() that wraps message between tag
*
* @param array|string $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
diff --git a/app/vendor/cakephp/cakephp/src/Console/ShellDispatcher.php b/app/vendor/cakephp/cakephp/src/Console/ShellDispatcher.php
index 2075784b0..a8615a168 100644
--- a/app/vendor/cakephp/cakephp/src/Console/ShellDispatcher.php
+++ b/app/vendor/cakephp/cakephp/src/Console/ShellDispatcher.php
@@ -24,6 +24,7 @@
use Cake\Log\Log;
use Cake\Shell\Task\CommandTask;
use Cake\Utility\Inflector;
+use function Cake\Core\pluginSplit;
/**
* Shell dispatcher handles dispatching CLI commands.
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/ConsoleIntegrationTestTrait.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/ConsoleIntegrationTestTrait.php
index f5f756fc7..b10d2cd98 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/ConsoleIntegrationTestTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/ConsoleIntegrationTestTrait.php
@@ -343,3 +343,10 @@ protected function commandStringToArgs(string $command): array
return $argv;
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\ConsoleIntegrationTestTrait',
+ 'Cake\TestSuite\ConsoleIntegrationTestTrait'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsBase.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsBase.php
index 8ea9d2619..f9f87322d 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsBase.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsBase.php
@@ -46,3 +46,10 @@ public function __construct(array $contents, string $output)
$this->output = $output;
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\Constraint\ContentsBase',
+ 'Cake\TestSuite\Constraint\Console\ContentsBase'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContain.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContain.php
index 5dc3942e4..82747a782 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContain.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContain.php
@@ -43,3 +43,10 @@ public function toString(): string
return sprintf('is in %s,' . PHP_EOL . 'actual result:' . PHP_EOL, $this->output) . $this->contents;
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\Constraint\ContentsContain',
+ 'Cake\TestSuite\Constraint\Console\ContentsContain'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContainRow.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContainRow.php
index a1b9edd08..583abbfb5 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContainRow.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsContainRow.php
@@ -59,3 +59,10 @@ public function failureDescription($other): string
return '`' . $this->exporter()->shortenedExport($other) . '` ' . $this->toString();
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\Constraint\ContentsContainRow',
+ 'Cake\TestSuite\Constraint\Console\ContentsContainRow'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsEmpty.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsEmpty.php
index 015d68bbc..6cae114e3 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsEmpty.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsEmpty.php
@@ -54,3 +54,10 @@ protected function failureDescription($other): string
return $this->toString();
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\Constraint\ContentsEmpty',
+ 'Cake\TestSuite\Constraint\Console\ContentsEmpty'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsNotContain.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsNotContain.php
index 47855c520..c8a666c13 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsNotContain.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsNotContain.php
@@ -43,3 +43,10 @@ public function toString(): string
return sprintf('is not in %s', $this->output);
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\Constraint\ContentsNotContain',
+ 'Cake\TestSuite\Constraint\Console\ContentsNotContain'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsRegExp.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsRegExp.php
index e3a3fb6c7..a715b95d6 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsRegExp.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ContentsRegExp.php
@@ -52,3 +52,10 @@ public function failureDescription($other): string
return '`' . $other . '` ' . $this->toString();
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\Constraint\ContentsRegExp',
+ 'Cake\TestSuite\Constraint\Console\ContentsRegExp'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ExitCode.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ExitCode.php
index 4e7f01edb..da3f46a5d 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ExitCode.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/Constraint/ExitCode.php
@@ -60,3 +60,10 @@ public function toString(): string
return sprintf('matches exit code %s', $this->exitCode ?? 'null');
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\Constraint\ExitCode',
+ 'Cake\TestSuite\Constraint\Console\ExitCode'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyCommandRunner.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyCommandRunner.php
index 8cbb5542a..d1ec2c74d 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyCommandRunner.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyCommandRunner.php
@@ -37,3 +37,10 @@ public function run(array $argv, ?ConsoleIo $io = null): int
return $dispatcher->dispatch();
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\LegacyCommandRunner',
+ 'Cake\TestSuite\LegacyCommandRunner'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyShellDispatcher.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyShellDispatcher.php
index 59caba325..cc9fde4da 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyShellDispatcher.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/LegacyShellDispatcher.php
@@ -18,6 +18,7 @@
use Cake\Console\ConsoleIo;
use Cake\Console\Shell;
use Cake\Console\ShellDispatcher;
+use function Cake\Core\pluginSplit;
/**
* Allows injecting mock IO into shells
@@ -62,3 +63,10 @@ protected function _createShell(string $className, string $shortName): Shell
return $instance;
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\LegacyShellDispatcher',
+ 'Cake\TestSuite\LegacyShellDispatcher'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/MissingConsoleInputException.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/MissingConsoleInputException.php
index a76d36f63..9b58c4659 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/MissingConsoleInputException.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/MissingConsoleInputException.php
@@ -35,5 +35,8 @@ public function setQuestion($question)
}
// phpcs:disable
-class_alias(MissingConsoleInputException::class, 'Cake\TestSuite\Stub\MissingConsoleInputException');
+class_alias(
+ 'Cake\Console\TestSuite\MissingConsoleInputException',
+ 'Cake\TestSuite\Stub\MissingConsoleInputException'
+);
// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleInput.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleInput.php
index 96a83198f..cd968194a 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleInput.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleInput.php
@@ -86,3 +86,10 @@ public function dataAvailable($timeout = 0): bool
return true;
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\StubConsoleInput',
+ 'Cake\TestSuite\Stub\ConsoleInput'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleOutput.php b/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleOutput.php
index 280ea3e7d..46b234237 100644
--- a/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleOutput.php
+++ b/app/vendor/cakephp/cakephp/src/Console/TestSuite/StubConsoleOutput.php
@@ -82,3 +82,10 @@ public function output(): string
return implode("\n", $this->_out);
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Console\TestSuite\StubConsoleOutput',
+ 'Cake\TestSuite\Stub\ConsoleOutput'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Controller/Component.php b/app/vendor/cakephp/cakephp/src/Controller/Component.php
index 1ebafbd59..9cdc87ad1 100644
--- a/app/vendor/cakephp/cakephp/src/Controller/Component.php
+++ b/app/vendor/cakephp/cakephp/src/Controller/Component.php
@@ -19,6 +19,7 @@
use Cake\Core\InstanceConfigTrait;
use Cake\Event\EventListenerInterface;
use Cake\Log\LogTrait;
+use function Cake\Core\deprecationWarning;
/**
* Base class for an individual Component. Components provide reusable bits of
diff --git a/app/vendor/cakephp/cakephp/src/Controller/Component/AuthComponent.php b/app/vendor/cakephp/cakephp/src/Controller/Component/AuthComponent.php
index d9b0a59e5..851117c75 100644
--- a/app/vendor/cakephp/cakephp/src/Controller/Component/AuthComponent.php
+++ b/app/vendor/cakephp/cakephp/src/Controller/Component/AuthComponent.php
@@ -31,6 +31,7 @@
use Cake\Http\ServerRequest;
use Cake\Routing\Router;
use Cake\Utility\Hash;
+use function Cake\I18n\__d;
/**
* Authentication control component class.
diff --git a/app/vendor/cakephp/cakephp/src/Controller/Component/FormProtectionComponent.php b/app/vendor/cakephp/cakephp/src/Controller/Component/FormProtectionComponent.php
index 947403dca..54a2fd99a 100644
--- a/app/vendor/cakephp/cakephp/src/Controller/Component/FormProtectionComponent.php
+++ b/app/vendor/cakephp/cakephp/src/Controller/Component/FormProtectionComponent.php
@@ -67,6 +67,20 @@ class FormProtectionComponent extends Component
'validationFailureCallback' => null,
];
+ /**
+ * Get Session id for FormProtector
+ * Must be the same as in FormHelper
+ *
+ * @return string
+ */
+ protected function _getSessionId(): string
+ {
+ $session = $this->getController()->getRequest()->getSession();
+ $session->start();
+
+ return $session->id();
+ }
+
/**
* Component startup.
*
@@ -86,12 +100,11 @@ public function startup(EventInterface $event): ?Response
&& $hasData
&& $this->_config['validate']
) {
- $session = $request->getSession();
- $session->start();
+ $sessionId = $this->_getSessionId();
$url = Router::url($request->getRequestTarget());
$formProtector = new FormProtector($this->_config);
- $isValid = $formProtector->validate($data, $url, $session->id());
+ $isValid = $formProtector->validate($data, $url, $sessionId);
if (!$isValid) {
return $this->validationFailure($formProtector);
diff --git a/app/vendor/cakephp/cakephp/src/Controller/Component/PaginatorComponent.php b/app/vendor/cakephp/cakephp/src/Controller/Component/PaginatorComponent.php
index 85e27729a..07dc6352e 100644
--- a/app/vendor/cakephp/cakephp/src/Controller/Component/PaginatorComponent.php
+++ b/app/vendor/cakephp/cakephp/src/Controller/Component/PaginatorComponent.php
@@ -24,6 +24,7 @@
use Cake\Http\Exception\NotFoundException;
use InvalidArgumentException;
use UnexpectedValueException;
+use function Cake\Core\deprecationWarning;
/**
* This component is used to handle automatic model data pagination. The primary way to use this
diff --git a/app/vendor/cakephp/cakephp/src/Controller/Component/SecurityComponent.php b/app/vendor/cakephp/cakephp/src/Controller/Component/SecurityComponent.php
index 1b84ba258..6938d0cb4 100644
--- a/app/vendor/cakephp/cakephp/src/Controller/Component/SecurityComponent.php
+++ b/app/vendor/cakephp/cakephp/src/Controller/Component/SecurityComponent.php
@@ -209,7 +209,7 @@ protected function _secureRequired(Controller $controller): void
($requireSecure[0] === '*' ||
in_array($this->_action, $requireSecure, true)
) &&
- !$controller->getRequest()->is('ssl')
+ !$controller->getRequest()->is('https')
) {
throw new SecurityException(
'Request is not SSL and the action is required to be secure'
diff --git a/app/vendor/cakephp/cakephp/src/Controller/Controller.php b/app/vendor/cakephp/cakephp/src/Controller/Controller.php
index 623214fd6..5d2831ff5 100644
--- a/app/vendor/cakephp/cakephp/src/Controller/Controller.php
+++ b/app/vendor/cakephp/cakephp/src/Controller/Controller.php
@@ -44,6 +44,11 @@
use ReflectionMethod;
use RuntimeException;
use UnexpectedValueException;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\getTypeName;
+use function Cake\Core\namespaceSplit;
+use function Cake\Core\pluginSplit;
+use function Cake\Core\triggerWarning;
/**
* Application controller class for organization of business logic.
@@ -91,6 +96,7 @@
* @property \Cake\Controller\Component\RequestHandlerComponent $RequestHandler
* @property \Cake\Controller\Component\SecurityComponent $Security
* @property \Cake\Controller\Component\AuthComponent $Auth
+ * @property \Cake\Controller\Component\CheckHttpCacheComponent $CheckHttpCache
* @link https://book.cakephp.org/4/en/controllers.html
*/
#[\AllowDynamicProperties]
@@ -170,6 +176,13 @@ class Controller implements EventListenerInterface, EventDispatcherInterface
*/
protected $middlewares = [];
+ /**
+ * View classes for content negotiation.
+ *
+ * @var array
+ */
+ protected $viewClasses = [];
+
/**
* Constructor.
*
@@ -320,7 +333,7 @@ public function __get(string $name)
}
if ($class === $name) {
- return $this->loadModel();
+ return $this->fetchModel();
}
}
@@ -684,10 +697,14 @@ public function redirect($url, int $status = 302): ?Response
{
$this->autoRender = false;
- if ($status) {
- $this->response = $this->response->withStatus($status);
+ if ($status < 300 || $status > 399) {
+ throw new InvalidArgumentException(
+ sprintf('Invalid status code `%s`. It should be within the range ' .
+ '`300` - `399` for redirect responses.', $status)
+ );
}
+ $this->response = $this->response->withStatus($status);
$event = $this->dispatchEvent('Controller.beforeRedirect', [$url, $this->response]);
if ($event->getResult() instanceof Response) {
return $this->response = $event->getResult();
@@ -787,7 +804,25 @@ public function render(?string $template = null, ?string $layout = null): Respon
*/
public function viewClasses(): array
{
- return [];
+ return $this->viewClasses;
+ }
+
+ /**
+ * Add View classes this controller can perform content negotiation with.
+ *
+ * Each view class must implement the `getContentType()` hook method
+ * to participate in negotiation.
+ *
+ * @param array $viewClasses View classes list.
+ * @return $this
+ * @see Cake\Http\ContentTypeNegotiation
+ * @since 4.5.0
+ */
+ public function addViewClasses(array $viewClasses)
+ {
+ $this->viewClasses = array_merge($this->viewClasses, $viewClasses);
+
+ return $this;
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Controller/ControllerFactory.php b/app/vendor/cakephp/cakephp/src/Controller/ControllerFactory.php
index 34b8c18a7..88e776c4b 100644
--- a/app/vendor/cakephp/cakephp/src/Controller/ControllerFactory.php
+++ b/app/vendor/cakephp/cakephp/src/Controller/ControllerFactory.php
@@ -32,6 +32,7 @@
use ReflectionClass;
use ReflectionFunction;
use ReflectionNamedType;
+use function Cake\Core\deprecationWarning;
/**
* Factory method for building controllers for request.
@@ -105,7 +106,7 @@ public function invoke($controller): ResponseInterface
$middlewares = $controller->getMiddleware();
if ($middlewares) {
- $middlewareQueue = new MiddlewareQueue($middlewares);
+ $middlewareQueue = new MiddlewareQueue($middlewares, $this->container);
$runner = new Runner();
return $runner->run($middlewareQueue, $controller->getRequest(), $this);
@@ -159,17 +160,6 @@ protected function getActionArgs(Closure $action, array $passedParams): array
$function = new ReflectionFunction($action);
foreach ($function->getParameters() as $parameter) {
$type = $parameter->getType();
- if ($type && !$type instanceof ReflectionNamedType) {
- // Only single types are supported
- throw new InvalidParameterException([
- 'template' => 'unsupported_type',
- 'parameter' => $parameter->getName(),
- 'controller' => $this->controller->getName(),
- 'action' => $this->controller->getRequest()->getParam('action'),
- 'prefix' => $this->controller->getRequest()->getParam('prefix'),
- 'plugin' => $this->controller->getRequest()->getParam('plugin'),
- ]);
- }
// Check for dependency injection for classes
if ($type instanceof ReflectionNamedType && !$type->isBuiltin()) {
@@ -354,3 +344,10 @@ protected function missingController(ServerRequest $request)
]);
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Controller\ControllerFactory',
+ 'Cake\Http\ControllerFactory'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Core/Configure/FileConfigTrait.php b/app/vendor/cakephp/cakephp/src/Core/Configure/FileConfigTrait.php
index 34931c895..79bcdea49 100644
--- a/app/vendor/cakephp/cakephp/src/Core/Configure/FileConfigTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Core/Configure/FileConfigTrait.php
@@ -18,6 +18,7 @@
use Cake\Core\Exception\CakeException;
use Cake\Core\Plugin;
+use function Cake\Core\pluginSplit;
/**
* Trait providing utility methods for file based config engines.
diff --git a/app/vendor/cakephp/cakephp/src/Core/Exception/CakeException.php b/app/vendor/cakephp/cakephp/src/Core/Exception/CakeException.php
index 82ef43738..43f885a81 100644
--- a/app/vendor/cakephp/cakephp/src/Core/Exception/CakeException.php
+++ b/app/vendor/cakephp/cakephp/src/Core/Exception/CakeException.php
@@ -16,6 +16,7 @@
use RuntimeException;
use Throwable;
+use function Cake\Core\deprecationWarning;
/**
* Base class that all CakePHP Exceptions extend.
@@ -115,5 +116,8 @@ public function responseHeader($header = null, $value = null): ?array
}
// phpcs:disable
-class_exists('Cake\Core\Exception\Exception');
+class_alias(
+ 'Cake\Core\Exception\CakeException',
+ 'Cake\Core\Exception\Exception'
+);
// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Core/Exception/Exception.php b/app/vendor/cakephp/cakephp/src/Core/Exception/Exception.php
index fb5d49fb2..bd93c509e 100644
--- a/app/vendor/cakephp/cakephp/src/Core/Exception/Exception.php
+++ b/app/vendor/cakephp/cakephp/src/Core/Exception/Exception.php
@@ -1,6 +1,8 @@
*/
abstract class ObjectRegistry implements Countable, IteratorAggregate
{
@@ -336,7 +337,6 @@ public function reset()
* @param object $object instance to store in the registry
* @return $this
* @psalm-param TObject $object
- * @psalm-suppress MoreSpecificReturnType
*/
public function set(string $name, object $object)
{
@@ -351,7 +351,6 @@ public function set(string $name, object $object)
}
$this->_loaded[$objName] = $object;
- /** @psalm-suppress LessSpecificReturnStatement */
return $this;
}
@@ -362,7 +361,6 @@ public function set(string $name, object $object)
*
* @param string $name The name of the object to remove from the registry.
* @return $this
- * @psalm-suppress MoreSpecificReturnType
*/
public function unload(string $name)
{
@@ -377,7 +375,6 @@ public function unload(string $name)
}
unset($this->_loaded[$name]);
- /** @psalm-suppress LessSpecificReturnStatement */
return $this;
}
diff --git a/app/vendor/cakephp/cakephp/src/Core/PluginCollection.php b/app/vendor/cakephp/cakephp/src/Core/PluginCollection.php
index 1862d6e43..a9fc4a191 100644
--- a/app/vendor/cakephp/cakephp/src/Core/PluginCollection.php
+++ b/app/vendor/cakephp/cakephp/src/Core/PluginCollection.php
@@ -15,6 +15,7 @@
*/
namespace Cake\Core;
+use Cake\Core\Exception\CakeException;
use Cake\Core\Exception\MissingPluginException;
use Countable;
use Generator;
@@ -34,6 +35,8 @@
*
* While its implementation supported nested iteration it does not
* support using `continue` or `break` inside loops.
+ *
+ * @template-implements \Iterator
*/
class PluginCollection implements Iterator, Countable
{
@@ -232,6 +235,10 @@ public function get(string $name): PluginInterface
*/
public function create(string $name, array $config = []): PluginInterface
{
+ if ($name === '') {
+ throw new CakeException('Cannot create a plugin with empty name');
+ }
+
if (strpos($name, '\\') !== false) {
/** @var \Cake\Core\PluginInterface */
return new $name($config);
diff --git a/app/vendor/cakephp/cakephp/src/Core/TestSuite/ContainerStubTrait.php b/app/vendor/cakephp/cakephp/src/Core/TestSuite/ContainerStubTrait.php
index 909ade79f..9c6ae1e05 100644
--- a/app/vendor/cakephp/cakephp/src/Core/TestSuite/ContainerStubTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Core/TestSuite/ContainerStubTrait.php
@@ -172,3 +172,10 @@ public function cleanupContainer(): void
$this->containerServices = [];
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Core\TestSuite\ContainerStubTrait',
+ 'Cake\TestSuite\ContainerStubTrait'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Core/functions.php b/app/vendor/cakephp/cakephp/src/Core/functions.php
index f938d8817..af2d2b6c3 100644
--- a/app/vendor/cakephp/cakephp/src/Core/functions.php
+++ b/app/vendor/cakephp/cakephp/src/Core/functions.php
@@ -11,20 +11,13 @@
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
- * @since 3.0.0
+ * @since 4.5.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
+// phpcs:disable PSR1.Files.SideEffects
+namespace Cake\Core;
-use Cake\Core\Configure;
-
-if (!defined('DS')) {
- /**
- * Defines DS as short form of DIRECTORY_SEPARATOR.
- */
- define('DS', DIRECTORY_SEPARATOR);
-}
-
-if (!function_exists('h')) {
+if (!function_exists('Cake\Core\h')) {
/**
* Convenience method for htmlspecialchars.
*
@@ -66,10 +59,9 @@ function h($text, bool $double = true, ?string $charset = null)
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, $charset ?: $defaultCharset, $double);
}
-
}
-if (!function_exists('pluginSplit')) {
+if (!function_exists('Cake\Core\pluginSplit')) {
/**
* Splits a dot syntax plugin name into its plugin and class name.
* If $name does not have a dot, then index 0 will be null.
@@ -94,16 +86,15 @@ function pluginSplit(string $name, bool $dotAppend = false, ?string $plugin = nu
$parts[0] .= '.';
}
- /** @psalm-var array{string, string}*/
+ /** @psalm-var array{string, string} */
return $parts;
}
return [$plugin, $name];
}
-
}
-if (!function_exists('namespaceSplit')) {
+if (!function_exists('Cake\Core\namespaceSplit')) {
/**
* Split the namespace from the classname.
*
@@ -121,10 +112,9 @@ function namespaceSplit(string $class): array
return [substr($class, 0, $pos), substr($class, $pos + 1)];
}
-
}
-if (!function_exists('pr')) {
+if (!function_exists('Cake\Core\pr')) {
/**
* print_r() convenience function.
*
@@ -149,10 +139,9 @@ function pr($var)
return $var;
}
-
}
-if (!function_exists('pj')) {
+if (!function_exists('Cake\Core\pj')) {
/**
* JSON pretty print convenience function.
*
@@ -177,10 +166,9 @@ function pj($var)
return $var;
}
-
}
-if (!function_exists('env')) {
+if (!function_exists('Cake\Core\env')) {
/**
* Gets an environment variable from available sources, and provides emulation
* for unsupported or inconsistent environment variables (i.e. DOCUMENT_ROOT on
@@ -242,10 +230,9 @@ function env(string $key, $default = null)
return $default;
}
-
}
-if (!function_exists('triggerWarning')) {
+if (!function_exists('Cake\Core\triggerWarning')) {
/**
* Triggers an E_USER_WARNING.
*
@@ -269,7 +256,7 @@ function triggerWarning(string $message): void
}
}
-if (!function_exists('deprecationWarning')) {
+if (!function_exists('Cake\Core\deprecationWarning')) {
/**
* Helper method for outputting deprecation warnings
*
@@ -294,7 +281,11 @@ function deprecationWarning(string $message, int $stackFrame = 1): void
if (defined('ROOT')) {
$root = ROOT;
}
- $relative = str_replace(DIRECTORY_SEPARATOR, '/', substr($frame['file'], strlen($root) + 1));
+ $relative = str_replace(
+ DIRECTORY_SEPARATOR,
+ '/',
+ substr($frame['file'], strlen($root) + 1)
+ );
$patterns = (array)Configure::read('Error.ignoredDeprecationPaths');
foreach ($patterns as $pattern) {
$pattern = str_replace(DIRECTORY_SEPARATOR, '/', $pattern);
@@ -304,8 +295,7 @@ function deprecationWarning(string $message, int $stackFrame = 1): void
}
$message = sprintf(
- "%s\n%s, line: %s\n" .
- 'You can disable all deprecation warnings by setting `Error.errorLevel` to ' .
+ "%s\n%s, line: %s\n" . 'You can disable all deprecation warnings by setting `Error.errorLevel` to ' .
'`E_ALL & ~E_USER_DEPRECATED`. Adding `%s` to `Error.ignoredDeprecationPaths` ' .
'in your `config/app.php` config will mute deprecations from that file only.',
$message,
@@ -329,7 +319,7 @@ function deprecationWarning(string $message, int $stackFrame = 1): void
}
}
-if (!function_exists('getTypeName')) {
+if (!function_exists('Cake\Core\getTypeName')) {
/**
* Returns the objects class or var type of it's not an object
*
@@ -341,3 +331,10 @@ function getTypeName($var): string
return is_object($var) ? get_class($var) : gettype($var);
}
}
+
+/**
+ * Include global functions.
+ */
+if (!getenv('CAKE_DISABLE_GLOBAL_FUNCS')) {
+ include 'functions_global.php';
+}
diff --git a/app/vendor/cakephp/cakephp/src/Core/functions_global.php b/app/vendor/cakephp/cakephp/src/Core/functions_global.php
new file mode 100644
index 000000000..bb2a71478
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Core/functions_global.php
@@ -0,0 +1,190 @@
+ plugin name, 1 => class name.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#pluginSplit
+ * @psalm-return array{string|null, string}
+ */
+ function pluginSplit(string $name, bool $dotAppend = false, ?string $plugin = null): array
+ {
+ return cakePluginSplit($name, $dotAppend, $plugin);
+ }
+}
+
+if (!function_exists('namespaceSplit')) {
+ /**
+ * Split the namespace from the classname.
+ *
+ * Commonly used like `list($namespace, $className) = namespaceSplit($class);`.
+ *
+ * @param string $class The full class name, ie `Cake\Core\App`.
+ * @return array Array with 2 indexes. 0 => namespace, 1 => classname.
+ */
+ function namespaceSplit(string $class): array
+ {
+ return cakeNamespaceSplit($class);
+ }
+}
+
+if (!function_exists('pr')) {
+ /**
+ * print_r() convenience function.
+ *
+ * In terminals this will act similar to using print_r() directly, when not run on CLI
+ * print_r() will also wrap `
` tags around the output of given variable. Similar to debug().
+ *
+ * This function returns the same variable that was passed.
+ *
+ * @param mixed $var Variable to print out.
+ * @return mixed the same $var that was passed to this function
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#pr
+ * @see debug()
+ */
+ function pr($var)
+ {
+ return cakePr($var);
+ }
+}
+
+if (!function_exists('pj')) {
+ /**
+ * JSON pretty print convenience function.
+ *
+ * In terminals this will act similar to using json_encode() with JSON_PRETTY_PRINT directly, when not run on CLI
+ * will also wrap `
` tags around the output of given variable. Similar to pr().
+ *
+ * This function returns the same variable that was passed.
+ *
+ * @param mixed $var Variable to print out.
+ * @return mixed the same $var that was passed to this function
+ * @see pr()
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#pj
+ */
+ function pj($var)
+ {
+ return cakePj($var);
+ }
+}
+
+if (!function_exists('env')) {
+ /**
+ * Gets an environment variable from available sources, and provides emulation
+ * for unsupported or inconsistent environment variables (i.e. DOCUMENT_ROOT on
+ * IIS, or SCRIPT_NAME in CGI mode). Also exposes some additional custom
+ * environment information.
+ *
+ * @param string $key Environment variable name.
+ * @param string|bool|null $default Specify a default value in case the environment variable is not defined.
+ * @return string|bool|null Environment variable setting.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#env
+ */
+ function env(string $key, $default = null)
+ {
+ return cakeEnv($key, $default);
+ }
+}
+
+if (!function_exists('triggerWarning')) {
+ /**
+ * Triggers an E_USER_WARNING.
+ *
+ * @param string $message The warning message.
+ * @return void
+ */
+ function triggerWarning(string $message): void
+ {
+ cakeTriggerWarning($message);
+ }
+}
+
+if (!function_exists('deprecationWarning')) {
+ /**
+ * Helper method for outputting deprecation warnings
+ *
+ * @param string $message The message to output as a deprecation warning.
+ * @param int $stackFrame The stack frame to include in the error. Defaults to 1
+ * as that should point to application/plugin code.
+ * @return void
+ */
+ function deprecationWarning(string $message, int $stackFrame = 1): void
+ {
+ cakeDeprecationWarning($message, $stackFrame + 1);
+ }
+}
+
+if (!function_exists('getTypeName')) {
+ /**
+ * Returns the objects class or var type of it's not an object
+ *
+ * @param mixed $var Variable to check
+ * @return string Returns the class name or variable type
+ */
+ function getTypeName($var): string
+ {
+ return cakeGetTypeName($var);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Connection.php b/app/vendor/cakephp/cakephp/src/Database/Connection.php
index 92a54ae8d..83777d723 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Connection.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Connection.php
@@ -26,6 +26,10 @@
use Cake\Database\Log\LoggedQuery;
use Cake\Database\Log\LoggingStatement;
use Cake\Database\Log\QueryLogger;
+use Cake\Database\Query\DeleteQuery;
+use Cake\Database\Query\InsertQuery;
+use Cake\Database\Query\SelectQuery;
+use Cake\Database\Query\UpdateQuery;
use Cake\Database\Retry\ReconnectStrategy;
use Cake\Database\Schema\CachedCollection;
use Cake\Database\Schema\Collection as SchemaCollection;
@@ -37,6 +41,7 @@
use Psr\SimpleCache\CacheInterface;
use RuntimeException;
use Throwable;
+use function Cake\Core\deprecationWarning;
/**
* Represents a connection with a database server.
@@ -53,12 +58,14 @@ class Connection implements ConnectionInterface
protected $_config;
/**
- * Driver object, responsible for creating the real connection
- * and provide specific SQL dialect.
- *
* @var \Cake\Database\DriverInterface
*/
- protected $_driver;
+ protected DriverInterface $readDriver;
+
+ /**
+ * @var \Cake\Database\DriverInterface
+ */
+ protected DriverInterface $writeDriver;
/**
* Contains how many nested transactions have been started.
@@ -135,19 +142,61 @@ class Connection implements ConnectionInterface
public function __construct(array $config)
{
$this->_config = $config;
+ [self::ROLE_READ => $this->readDriver, self::ROLE_WRITE => $this->writeDriver] = $this->createDrivers($config);
+
+ if (!empty($config['log'])) {
+ $this->enableQueryLogging((bool)$config['log']);
+ }
+ }
- $driverConfig = array_diff_key($config, array_flip([
+ /**
+ * Creates read and write drivers.
+ *
+ * @param array $config Connection config
+ * @return array
+ * @psalm-return array{read: \Cake\Database\DriverInterface, write: \Cake\Database\DriverInterface}
+ */
+ protected function createDrivers(array $config): array
+ {
+ $driver = $config['driver'] ?? '';
+ if (!is_string($driver)) {
+ /** @var \Cake\Database\DriverInterface $driver */
+ if (!$driver->enabled()) {
+ throw new MissingExtensionException(['driver' => get_class($driver), 'name' => $this->configName()]);
+ }
+
+ // Legacy support for setting instance instead of driver class
+ return [self::ROLE_READ => $driver, self::ROLE_WRITE => $driver];
+ }
+
+ /** @var class-string<\Cake\Database\DriverInterface>|null $driverClass */
+ $driverClass = App::className($driver, 'Database/Driver');
+ if ($driverClass === null) {
+ throw new MissingDriverException(['driver' => $driver, 'connection' => $this->configName()]);
+ }
+
+ $sharedConfig = array_diff_key($config, array_flip([
'name',
'driver',
'log',
'cacheMetaData',
'cacheKeyPrefix',
]));
- $this->_driver = $this->createDriver($config['driver'] ?? '', $driverConfig);
- if (!empty($config['log'])) {
- $this->enableQueryLogging((bool)$config['log']);
+ $writeConfig = $config['write'] ?? [] + $sharedConfig;
+ $readConfig = $config['read'] ?? [] + $sharedConfig;
+ if ($readConfig == $writeConfig) {
+ $readDriver = $writeDriver = new $driverClass(['_role' => self::ROLE_WRITE] + $writeConfig);
+ } else {
+ $readDriver = new $driverClass(['_role' => self::ROLE_READ] + $readConfig);
+ $writeDriver = new $driverClass(['_role' => self::ROLE_WRITE] + $writeConfig);
}
+
+ if (!$writeDriver->enabled()) {
+ throw new MissingExtensionException(['driver' => get_class($writeDriver), 'name' => $this->configName()]);
+ }
+
+ return [self::ROLE_READ => $readDriver, self::ROLE_WRITE => $writeDriver];
}
/**
@@ -178,6 +227,16 @@ public function configName(): string
return $this->_config['name'] ?? '';
}
+ /**
+ * Returns the connection role: read or write.
+ *
+ * @return string
+ */
+ public function role(): string
+ {
+ return preg_match('/:read$/', $this->configName()) === 1 ? static::ROLE_READ : static::ROLE_WRITE;
+ }
+
/**
* Sets the driver instance. If a string is passed it will be treated
* as a class name and will be instantiated.
@@ -193,7 +252,8 @@ public function setDriver($driver, $config = [])
{
deprecationWarning('Setting the driver is deprecated. Use the connection config instead.');
- $this->_driver = $this->createDriver($driver, $config);
+ $driver = $this->createDriver($driver, $config);
+ $this->readDriver = $this->writeDriver = $driver;
return $this;
}
@@ -216,7 +276,7 @@ protected function createDriver($name, array $config): DriverInterface
if ($className === null) {
throw new MissingDriverException(['driver' => $driver, 'connection' => $this->configName()]);
}
- $driver = new $className($config);
+ $driver = new $className(['_role' => self::ROLE_WRITE] + $config);
}
if (!$driver->enabled()) {
@@ -240,11 +300,14 @@ public function getDisconnectRetry(): CommandRetry
/**
* Gets the driver instance.
*
+ * @param string $role Connection role ('read' or 'write')
* @return \Cake\Database\DriverInterface
*/
- public function getDriver(): DriverInterface
+ public function getDriver(string $role = self::ROLE_WRITE): DriverInterface
{
- return $this->_driver;
+ assert($role === self::ROLE_READ || $role === self::ROLE_WRITE);
+
+ return $role === self::ROLE_READ ? $this->readDriver : $this->writeDriver;
}
/**
@@ -252,43 +315,62 @@ public function getDriver(): DriverInterface
*
* @throws \Cake\Database\Exception\MissingConnectionException If database connection could not be established.
* @return bool true, if the connection was already established or the attempt was successful.
+ * @deprecated 4.5.0 Use getDriver()->connect() instead.
*/
public function connect(): bool
{
- try {
- return $this->_driver->connect();
- } catch (MissingConnectionException $e) {
- throw $e;
- } catch (Throwable $e) {
- throw new MissingConnectionException(
- [
- 'driver' => App::shortName(get_class($this->_driver), 'Database/Driver'),
- 'reason' => $e->getMessage(),
- ],
- null,
- $e
- );
+ deprecationWarning(
+ 'If you cannot use automatic connection management, use $connection->getDriver()->connect() instead.'
+ );
+
+ $connected = true;
+ foreach ([self::ROLE_READ, self::ROLE_WRITE] as $role) {
+ try {
+ $connected = $connected && $this->getDriver($role)->connect();
+ } catch (MissingConnectionException $e) {
+ throw $e;
+ } catch (Throwable $e) {
+ throw new MissingConnectionException(
+ [
+ 'driver' => App::shortName(get_class($this->getDriver($role)), 'Database/Driver'),
+ 'reason' => $e->getMessage(),
+ ],
+ null,
+ $e
+ );
+ }
}
+
+ return $connected;
}
/**
* Disconnects from database server.
*
* @return void
+ * @deprecated 4.5.0 Use getDriver()->disconnect() instead.
*/
public function disconnect(): void
{
- $this->_driver->disconnect();
+ deprecationWarning(
+ 'If you cannot use automatic connection management, use $connection->getDriver()->disconnect() instead.'
+ );
+
+ $this->getDriver(self::ROLE_READ)->disconnect();
+ $this->getDriver(self::ROLE_WRITE)->disconnect();
}
/**
* Returns whether connection to database server was already established.
*
* @return bool
+ * @deprecated 4.5.0 Use getDriver()->isConnected() instead.
*/
public function isConnected(): bool
{
- return $this->_driver->isConnected();
+ deprecationWarning('Use $connection->getDriver()->isConnected() instead.');
+
+ return $this->getDriver(self::ROLE_READ)->isConnected() && $this->getDriver(self::ROLE_WRITE)->isConnected();
}
/**
@@ -296,11 +378,14 @@ public function isConnected(): bool
*
* @param \Cake\Database\Query|string $query The SQL to convert into a prepared statement.
* @return \Cake\Database\StatementInterface
+ * @deprecated 4.5.0 Use getDriver()->prepare() instead.
*/
public function prepare($query): StatementInterface
{
- return $this->getDisconnectRetry()->run(function () use ($query) {
- $statement = $this->_driver->prepare($query);
+ $role = $query instanceof Query ? $query->getConnectionRole() : self::ROLE_WRITE;
+
+ return $this->getDisconnectRetry()->run(function () use ($query, $role) {
+ $statement = $this->getDriver($role)->prepare($query);
if ($this->_logQueries) {
$statement = $this->_newLogger($statement);
@@ -339,10 +424,13 @@ public function execute(string $sql, array $params = [], array $types = []): Sta
* @param \Cake\Database\Query $query The query to be compiled
* @param \Cake\Database\ValueBinder $binder Value binder
* @return string
+ * @deprecated 4.5.0 Use getDriver()->compileQuery() instead.
*/
public function compileQuery(Query $query, ValueBinder $binder): string
{
- return $this->getDriver()->compileQuery($query, $binder)[1];
+ deprecationWarning('Use getDriver()->compileQuery() instead.');
+
+ return $this->getDriver($query->getConnectionRole())->compileQuery($query, $binder)[1];
}
/**
@@ -363,14 +451,42 @@ public function run(Query $query): StatementInterface
});
}
+ /**
+ * Create a new SelectQuery instance for this connection.
+ *
+ * @param \Cake\Database\ExpressionInterface|callable|array|string $fields fields to be added to the list.
+ * @param array|string $table The table or list of tables to query.
+ * @param array $types Associative array containing the types to be used for casting.
+ * @return \Cake\Database\Query\SelectQuery
+ */
+ public function selectQuery(
+ $fields = [],
+ $table = [],
+ array $types = []
+ ): SelectQuery {
+ $query = new SelectQuery($this);
+ if ($table) {
+ $query->from($table);
+ }
+ if ($fields) {
+ $query->select($fields, false);
+ }
+ $query->setDefaultTypes($types);
+
+ return $query;
+ }
+
/**
* Executes a SQL statement and returns the Statement object as result.
*
* @param string $sql The SQL query to execute.
* @return \Cake\Database\StatementInterface
+ * @deprecated 4.5.0 Use either `selectQuery`, `insertQuery`, `deleteQuery`, `updateQuery` instead.
*/
public function query(string $sql): StatementInterface
{
+ deprecationWarning('Use either `selectQuery`, `insertQuery`, `deleteQuery`, `updateQuery` instead.');
+
return $this->getDisconnectRetry()->run(function () use ($sql) {
$statement = $this->prepare($sql);
$statement->execute();
@@ -383,9 +499,17 @@ public function query(string $sql): StatementInterface
* Create a new Query instance for this connection.
*
* @return \Cake\Database\Query
+ * @deprecated 4.5.0 Use `insertQuery()`, `deleteQuery()`, `selectQuery()` or `updateQuery()` instead.
*/
public function newQuery(): Query
{
+ deprecationWarning(
+ 'As of 4.5.0, using newQuery() is deprecated. Instead, use `insertQuery()`, ' .
+ '`deleteQuery()`, `selectQuery()` or `updateQuery()`. The query objects ' .
+ 'returned by these methods will emit deprecations that will become fatal errors in 5.0.' .
+ 'See https://book.cakephp.org/4/en/appendices/4-5-migration-guide.html for more information.'
+ );
+
return new Query($this);
}
@@ -435,13 +559,31 @@ public function getSchemaCollection(): SchemaCollectionInterface
public function insert(string $table, array $values, array $types = []): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($table, $values, $types) {
+ return $this->insertQuery($table, $values, $types)->execute();
+ });
+ }
+
+ /**
+ * Create a new InsertQuery instance for this connection.
+ *
+ * @param string|null $table The table to insert rows into.
+ * @param array $values Associative array of column => value to be inserted.
+ * @param array $types Associative array containing the types to be used for casting.
+ * @return \Cake\Database\Query\InsertQuery
+ */
+ public function insertQuery(?string $table = null, array $values = [], array $types = []): InsertQuery
+ {
+ $query = new InsertQuery($this);
+ if ($table) {
+ $query->into($table);
+ }
+ if ($values) {
$columns = array_keys($values);
+ $query->insert($columns, $types)
+ ->values($values);
+ }
- return $this->newQuery()->insert($columns, $types)
- ->into($table)
- ->values($values)
- ->execute();
- });
+ return $query;
}
/**
@@ -456,13 +598,39 @@ public function insert(string $table, array $values, array $types = []): Stateme
public function update(string $table, array $values, array $conditions = [], array $types = []): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($table, $values, $conditions, $types) {
- return $this->newQuery()->update($table)
- ->set($values, $types)
- ->where($conditions, $types)
- ->execute();
+ return $this->updateQuery($table, $values, $conditions, $types)->execute();
});
}
+ /**
+ * Create a new UpdateQuery instance for this connection.
+ *
+ * @param \Cake\Database\ExpressionInterface|string|null $table The table to update rows of.
+ * @param array $values Values to be updated.
+ * @param array $conditions Conditions to be set for the update statement.
+ * @param array $types Associative array containing the types to be used for casting.
+ * @return \Cake\Database\Query\UpdateQuery
+ */
+ public function updateQuery(
+ $table = null,
+ array $values = [],
+ array $conditions = [],
+ array $types = []
+ ): UpdateQuery {
+ $query = new UpdateQuery($this);
+ if ($table) {
+ $query->update($table);
+ }
+ if ($values) {
+ $query->set($values, $types);
+ }
+ if ($conditions) {
+ $query->where($conditions, $types);
+ }
+
+ return $query;
+ }
+
/**
* Executes a DELETE statement on the specified table.
*
@@ -474,12 +642,31 @@ public function update(string $table, array $values, array $conditions = [], arr
public function delete(string $table, array $conditions = [], array $types = []): StatementInterface
{
return $this->getDisconnectRetry()->run(function () use ($table, $conditions, $types) {
- return $this->newQuery()->delete($table)
- ->where($conditions, $types)
- ->execute();
+ return $this->deleteQuery($table, $conditions, $types)->execute();
});
}
+ /**
+ * Create a new DeleteQuery instance for this connection.
+ *
+ * @param string|null $table The table to delete rows from.
+ * @param array $conditions Conditions to be set for the delete statement.
+ * @param array $types Associative array containing the types to be used for casting.
+ * @return \Cake\Database\Query\DeleteQuery
+ */
+ public function deleteQuery(?string $table = null, array $conditions = [], array $types = []): DeleteQuery
+ {
+ $query = new DeleteQuery($this);
+ if ($table) {
+ $query->from($table);
+ }
+ if ($conditions) {
+ $query->where($conditions, $types);
+ }
+
+ return $query;
+ }
+
/**
* Starts a new transaction.
*
@@ -493,7 +680,7 @@ public function begin(): void
}
$this->getDisconnectRetry()->run(function (): void {
- $this->_driver->beginTransaction();
+ $this->getDriver()->beginTransaction();
});
$this->_transactionLevel = 0;
@@ -534,7 +721,7 @@ public function commit(): bool
$this->log('COMMIT');
}
- return $this->_driver->commitTransaction();
+ return $this->getDriver()->commitTransaction();
}
if ($this->isSavePointsEnabled()) {
$this->releaseSavePoint((string)$this->_transactionLevel);
@@ -569,7 +756,7 @@ public function rollback(?bool $toBeginning = null): bool
if ($this->_logQueries) {
$this->log('ROLLBACK');
}
- $this->_driver->rollbackTransaction();
+ $this->getDriver()->rollbackTransaction();
return true;
}
@@ -598,7 +785,7 @@ public function enableSavePoints(bool $enable = true)
if ($enable === false) {
$this->_useSavePoints = false;
} else {
- $this->_useSavePoints = $this->_driver->supports(DriverInterface::FEATURE_SAVEPOINT);
+ $this->_useSavePoints = $this->getDriver()->supports(DriverInterface::FEATURE_SAVEPOINT);
}
return $this;
@@ -634,7 +821,7 @@ public function isSavePointsEnabled(): bool
*/
public function createSavePoint($name): void
{
- $this->execute($this->_driver->savePointSQL($name))->closeCursor();
+ $this->execute($this->getDriver()->savePointSQL($name))->closeCursor();
}
/**
@@ -645,7 +832,7 @@ public function createSavePoint($name): void
*/
public function releaseSavePoint($name): void
{
- $sql = $this->_driver->releaseSavePointSQL($name);
+ $sql = $this->getDriver()->releaseSavePointSQL($name);
if ($sql) {
$this->execute($sql)->closeCursor();
}
@@ -659,7 +846,7 @@ public function releaseSavePoint($name): void
*/
public function rollbackSavepoint($name): void
{
- $this->execute($this->_driver->rollbackSavePointSQL($name))->closeCursor();
+ $this->execute($this->getDriver()->rollbackSavePointSQL($name))->closeCursor();
}
/**
@@ -670,7 +857,7 @@ public function rollbackSavepoint($name): void
public function disableForeignKeys(): void
{
$this->getDisconnectRetry()->run(function (): void {
- $this->execute($this->_driver->disableForeignKeySQL())->closeCursor();
+ $this->execute($this->getDriver()->disableForeignKeySQL())->closeCursor();
});
}
@@ -682,7 +869,7 @@ public function disableForeignKeys(): void
public function enableForeignKeys(): void
{
$this->getDisconnectRetry()->run(function (): void {
- $this->execute($this->_driver->enableForeignKeySQL())->closeCursor();
+ $this->execute($this->getDriver()->enableForeignKeySQL())->closeCursor();
});
}
@@ -695,7 +882,7 @@ public function enableForeignKeys(): void
*/
public function supportsDynamicConstraints(): bool
{
- return $this->_driver->supportsDynamicConstraints();
+ return $this->getDriver()->supportsDynamicConstraints();
}
/**
@@ -774,12 +961,14 @@ public function inTransaction(): bool
* @param mixed $value The value to quote.
* @param \Cake\Database\TypeInterface|string|int $type Type to be used for determining kind of quoting to perform
* @return string Quoted value
+ * @deprecated 4.5.0 Use getDriver()->quote() instead.
*/
public function quote($value, $type = 'string'): string
{
+ deprecationWarning('Use getDriver()->quote() instead.');
[$value, $type] = $this->cast($value, $type);
- return $this->_driver->quote($value, $type);
+ return $this->getDriver()->quote($value, $type);
}
/**
@@ -788,10 +977,13 @@ public function quote($value, $type = 'string'): string
* This is not required to use `quoteIdentifier()`.
*
* @return bool
+ * @deprecated 4.5.0 Use getDriver()->supportsQuoting() instead.
*/
public function supportsQuoting(): bool
{
- return $this->_driver->supports(DriverInterface::FEATURE_QUOTE);
+ deprecationWarning('Use getDriver()->supportsQuoting() instead.');
+
+ return $this->getDriver()->supports(DriverInterface::FEATURE_QUOTE);
}
/**
@@ -802,10 +994,13 @@ public function supportsQuoting(): bool
*
* @param string $identifier The identifier to quote.
* @return string
+ * @deprecated 4.5.0 Use getDriver()->quoteIdentifier() instead.
*/
public function quoteIdentifier(string $identifier): string
{
- return $this->_driver->quoteIdentifier($identifier);
+ deprecationWarning('Use getDriver()->quoteIdentifier() instead.');
+
+ return $this->getDriver()->quoteIdentifier($identifier);
}
/**
@@ -865,6 +1060,7 @@ public function getCacher(): CacheInterface
*
* @param bool $enable Enable/disable query logging
* @return $this
+ * @deprecated 4.5.0 Connection logging is moving to the driver in 5.x
*/
public function enableQueryLogging(bool $enable = true)
{
@@ -877,6 +1073,7 @@ public function enableQueryLogging(bool $enable = true)
* Disable query logging
*
* @return $this
+ * @deprecated 4.5.0 Connection logging is moving to the driver in 5.x
*/
public function disableQueryLogging()
{
@@ -889,6 +1086,7 @@ public function disableQueryLogging()
* Check if query logging is enabled.
*
* @return bool
+ * @deprecated 4.5.0 Connection logging is moving to the driver in 5.x
*/
public function isQueryLoggingEnabled(): bool
{
@@ -952,7 +1150,7 @@ public function log(string $sql): void
*/
protected function _newLogger(StatementInterface $statement): LoggingStatement
{
- $log = new LoggingStatement($statement, $this->_driver);
+ $log = new LoggingStatement($statement, $this->getDriver());
$log->setLogger($this->getLogger());
return $log;
@@ -976,9 +1174,19 @@ public function __debugInfo(): array
$replace = array_intersect_key($secrets, $this->_config);
$config = $replace + $this->_config;
+ if (isset($config['read'])) {
+ /** @psalm-suppress PossiblyInvalidArgument */
+ $config['read'] = array_intersect_key($secrets, $config['read']) + $config['read'];
+ }
+ if (isset($config['write'])) {
+ /** @psalm-suppress PossiblyInvalidArgument */
+ $config['write'] = array_intersect_key($secrets, $config['write']) + $config['write'];
+ }
+
return [
'config' => $config,
- 'driver' => $this->_driver,
+ 'readDriver' => $this->readDriver,
+ 'writeDriver' => $this->writeDriver,
'transactionLevel' => $this->_transactionLevel,
'transactionStarted' => $this->_transactionStarted,
'useSavePoints' => $this->_useSavePoints,
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver.php b/app/vendor/cakephp/cakephp/src/Database/Driver.php
index 249868c47..5d43f1acc 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver.php
@@ -27,6 +27,7 @@
use InvalidArgumentException;
use PDO;
use PDOException;
+use function Cake\Core\deprecationWarning;
/**
* Represents a database driver containing all specificities for
@@ -108,6 +109,16 @@ public function __construct(array $config = [])
}
}
+ /**
+ * Get the configuration data used to create the driver.
+ *
+ * @return array
+ */
+ public function config(): array
+ {
+ return $this->_config;
+ }
+
/**
* Establishes a connection to the database server
*
@@ -513,6 +524,16 @@ public function getConnectRetries(): int
return $this->connectRetries;
}
+ /**
+ * Returns the connection role this driver performs.
+ *
+ * @return string
+ */
+ public function getRole(): string
+ {
+ return $this->_config['_role'] ?? Connection::ROLE_WRITE;
+ }
+
/**
* Destructor
*/
@@ -532,6 +553,7 @@ public function __debugInfo(): array
{
return [
'connected' => $this->_connection !== null,
+ 'role' => $this->getRole(),
];
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php b/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php
index 68f46ff74..b7d30b69f 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php
@@ -23,6 +23,7 @@
use Cake\Database\Statement\MysqlStatement;
use Cake\Database\StatementInterface;
use PDO;
+use function Cake\Core\deprecationWarning;
/**
* MySQL Driver
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/SqlDialectTrait.php b/app/vendor/cakephp/cakephp/src/Database/Driver/SqlDialectTrait.php
index 7bcabda6b..94a5e88b9 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/SqlDialectTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/SqlDialectTrait.php
@@ -306,3 +306,10 @@ public function rollbackSavePointSQL($name): string
return 'ROLLBACK TO SAVEPOINT LEVEL' . $name;
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Database\Driver\SqlDialectTrait',
+ 'Cake\Database\SqlDialectTrait'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php b/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php
index 6ca955856..65c3e7a1d 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/Sqlite.php
@@ -30,6 +30,7 @@
use InvalidArgumentException;
use PDO;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
/**
* Class Sqlite
diff --git a/app/vendor/cakephp/cakephp/src/Database/Driver/TupleComparisonTranslatorTrait.php b/app/vendor/cakephp/cakephp/src/Database/Driver/TupleComparisonTranslatorTrait.php
index e94b268b5..e21a79d08 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Driver/TupleComparisonTranslatorTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Driver/TupleComparisonTranslatorTrait.php
@@ -90,8 +90,7 @@ protected function _transformTupleComparison(TupleComparison $expression, Query
}
$surrogate = $query->getConnection()
- ->newQuery()
- ->select($true);
+ ->selectQuery($true);
if (!is_array(current($value))) {
$value = [$value];
diff --git a/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php b/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php
index e2ccc4d31..914d6b755 100644
--- a/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Database/DriverInterface.php
@@ -27,6 +27,8 @@
* @method int getConnectRetries() Returns the number of connection retry attempts made.
* @method bool supports(string $feature) Checks whether a feature is supported by the driver.
* @method bool inTransaction() Returns whether a transaction is active.
+ * @method array config() Get the configuration data used to create the driver.
+ * @method string getRole() Returns the connection role this driver prforms.
*/
interface DriverInterface
{
diff --git a/app/vendor/cakephp/cakephp/src/Database/Exception.php b/app/vendor/cakephp/cakephp/src/Database/Exception.php
index d47914df0..b8f495836 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Exception.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Exception.php
@@ -1,16 +1,10 @@
_conditions[] = $conditions;
-
- return $this;
- }
-
- if ($conditions instanceof ExpressionInterface) {
+ if (is_string($conditions) || $conditions instanceof ExpressionInterface) {
$this->_conditions[] = $conditions;
return $this;
diff --git a/app/vendor/cakephp/cakephp/src/Database/Expression/WhenThenExpression.php b/app/vendor/cakephp/cakephp/src/Database/Expression/WhenThenExpression.php
index bf51eaf19..bbc415414 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Expression/WhenThenExpression.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Expression/WhenThenExpression.php
@@ -24,6 +24,7 @@
use Closure;
use InvalidArgumentException;
use LogicException;
+use function Cake\Core\getTypeName;
/**
* Represents a SQL when/then clause with a fluid API
diff --git a/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php b/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php
index 1251fcad4..9e50ad63c 100644
--- a/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php
+++ b/app/vendor/cakephp/cakephp/src/Database/FunctionsBuilder.php
@@ -19,6 +19,7 @@
use Cake\Database\Expression\AggregateExpression;
use Cake\Database\Expression\FunctionExpression;
use InvalidArgumentException;
+use function Cake\Core\deprecationWarning;
/**
* Contains methods related to generating FunctionExpression objects
diff --git a/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php b/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php
index 6560a367f..f029bc935 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Log/LoggedQuery.php
@@ -130,6 +130,7 @@ public function getContext(): array
return [
'numRows' => $this->numRows,
'took' => $this->took,
+ 'role' => $this->driver ? $this->driver->getRole() : '',
];
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php b/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php
index ada3d381d..e83f6f60e 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Log/LoggingStatement.php
@@ -21,6 +21,7 @@
use Cake\Database\Statement\StatementDecorator;
use Exception;
use Psr\Log\LoggerInterface;
+use function Cake\Core\deprecationWarning;
/**
* Statement decorator used to
diff --git a/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php b/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php
index a7f27b489..e2faadce2 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Log/QueryLogger.php
@@ -50,7 +50,7 @@ public function log($level, $message, array $context = [])
if ($context['query'] instanceof LoggedQuery) {
$context = $context['query']->getContext() + $context;
- $message = 'connection={connection} duration={took} rows={numRows} ' . $message;
+ $message = 'connection={connection} role={role} duration={took} rows={numRows} ' . $message;
}
Log::write('debug', (string)$message, $context);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Query.php b/app/vendor/cakephp/cakephp/src/Database/Query.php
index 503c3a443..594b8a70f 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Query.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Query.php
@@ -30,6 +30,7 @@
use IteratorAggregate;
use RuntimeException;
use Throwable;
+use function Cake\Core\deprecationWarning;
/**
* This class represents a Relational database SQL Query. A query can be of
@@ -63,6 +64,13 @@ class Query implements ExpressionInterface, IteratorAggregate
*/
protected $_connection;
+ /**
+ * Connection role ('read' or 'write')
+ *
+ * @var string
+ */
+ protected $connectionRole = Connection::ROLE_WRITE;
+
/**
* Type of this query (select, insert, update, delete).
*
@@ -178,6 +186,7 @@ class Query implements ExpressionInterface, IteratorAggregate
* are enabled.
*
* @var bool
+ * @deprecated 4.5.0 Results will always be buffered in 5.0.
*/
protected $_useBufferedResults = true;
@@ -230,6 +239,16 @@ public function getConnection(): Connection
return $this->_connection;
}
+ /**
+ * Returns the connection role ('read' or 'write')
+ *
+ * @return string
+ */
+ public function getConnectionRole(): string
+ {
+ return $this->connectionRole;
+ }
+
/**
* Compiles the SQL representation of this query and executes it using the
* configured connection object. Returns the resulting statement object.
@@ -311,8 +330,9 @@ public function sql(?ValueBinder $binder = null): string
$binder = $this->getValueBinder();
$binder->resetCount();
}
+ $connection = $this->getConnection();
- return $this->getConnection()->compileQuery($this, $binder);
+ return $connection->getDriver($this->getConnectionRole())->compileQuery($this, $binder)[1];
}
/**
@@ -428,7 +448,7 @@ public function with($cte, bool $overwrite = false)
}
if ($cte instanceof Closure) {
- $query = $this->getConnection()->newQuery();
+ $query = $this->getConnection()->selectQuery();
$cte = $cte(new CommonTableExpression(), $query);
if (!($cte instanceof CommonTableExpression)) {
throw new RuntimeException(
@@ -864,7 +884,6 @@ public function innerJoin($table, $conditions = [], $types = [])
* to use for joining.
* @param string $type the join type to use
* @return array
- * @psalm-suppress InvalidReturnType
*/
protected function _makeJoin($table, $conditions, $type): array
{
@@ -877,7 +896,6 @@ protected function _makeJoin($table, $conditions, $type): array
/**
* @psalm-suppress InvalidArrayOffset
- * @psalm-suppress InvalidReturnStatement
*/
return [
$alias => [
@@ -2197,9 +2215,15 @@ public function setValueBinder(?ValueBinder $binder)
*
* @param bool $enable Whether to enable buffering
* @return $this
+ * @deprecated 4.5.0 Results will always be buffered in 5.0.
*/
public function enableBufferedResults(bool $enable = true)
{
+ if (!$enable) {
+ deprecationWarning(
+ '4.5.0 enableBufferedResults() is deprecated. Results will always be buffered in 5.0.'
+ );
+ }
$this->_dirty();
$this->_useBufferedResults = $enable;
@@ -2213,6 +2237,7 @@ public function enableBufferedResults(bool $enable = true)
* remembered for future iterations.
*
* @return $this
+ * @deprecated 4.5.0 Results will always be buffered in 5.0.
*/
public function disableBufferedResults()
{
@@ -2233,6 +2258,7 @@ public function disableBufferedResults()
* remembered for future iterations.
*
* @return bool
+ * @deprecated 4.5.0 Results will always be buffered in 5.0.
*/
public function isBufferedResultsEnabled(): bool
{
@@ -2327,7 +2353,7 @@ public function isResultsCastingEnabled(): bool
protected function _decorateStatement(StatementInterface $statement)
{
$typeMap = $this->getSelectTypeMap();
- $driver = $this->getConnection()->getDriver();
+ $driver = $this->getConnection()->getDriver($this->connectionRole);
if ($this->typeCastEnabled && $typeMap->toArray()) {
$statement = new CallbackStatement($statement, $driver, new FieldTypeConverter($typeMap, $driver));
@@ -2418,7 +2444,6 @@ public function __clone()
}
}
} elseif ($piece instanceof ExpressionInterface) {
- /** @psalm-suppress PossiblyUndefinedMethod */
$this->_parts[$name][$i] = clone $piece;
}
}
@@ -2473,4 +2498,19 @@ function ($errno, $errstr) {
'executed' => $this->_iterator ? true : false,
];
}
+
+ /**
+ * Helper for Query deprecation methods.
+ *
+ * @param string $method The method that is invalid.
+ * @param string $message An additional message.
+ * @return void
+ * @internal
+ */
+ protected function _deprecatedMethod($method, $message = '')
+ {
+ $class = static::class;
+ $text = "As of 4.5.0 calling {$method}() on {$class} is deprecated. " . $message;
+ deprecationWarning($text);
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Query/DeleteQuery.php b/app/vendor/cakephp/cakephp/src/Database/Query/DeleteQuery.php
new file mode 100644
index 000000000..5c11ae9d7
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/Query/DeleteQuery.php
@@ -0,0 +1,222 @@
+_deprecatedMethod('select()', 'Create your query with selectQuery() instead.');
+
+ return parent::select($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function distinct($on = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('distint()');
+
+ return parent::distinct($on, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function modifier($modifiers, $overwrite = false)
+ {
+ $this->_deprecatedMethod('modifier()');
+
+ return parent::modifier($modifiers, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function order($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('order()');
+
+ return parent::order($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function orderAsc($field, $overwrite = false)
+ {
+ $this->_deprecatedMethod('orderAsc()');
+
+ return parent::orderAsc($field, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function orderDesc($field, $overwrite = false)
+ {
+ $this->_deprecatedMethod('orderDesc()');
+
+ return parent::orderDesc($field, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function group($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('group()');
+
+ return parent::group($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function having($conditions = null, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('having()');
+
+ return parent::having($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andHaving($conditions, $types = [])
+ {
+ $this->_deprecatedMethod('andHaving()');
+
+ return parent::andHaving($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function page(int $num, ?int $limit = null)
+ {
+ $this->_deprecatedMethod('page()');
+
+ return parent::page($num, $limit);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function limit($limit)
+ {
+ $this->_deprecatedMethod('limit()');
+
+ return parent::limit($limit);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offset($offset)
+ {
+ $this->_deprecatedMethod('offset()');
+
+ return parent::offset($offset);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function union($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::union($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function unionAll($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('unionAll()');
+
+ return parent::unionAll($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function insert(array $columns, array $types = [])
+ {
+ $this->_deprecatedMethod('insert()', 'Create your query with insertQuery() instead.');
+
+ return parent::insert($columns, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function into(string $table)
+ {
+ $this->_deprecatedMethod('into()');
+
+ return parent::into($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function values($data)
+ {
+ $this->_deprecatedMethod('values()');
+
+ return parent::values($data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update($table)
+ {
+ $this->_deprecatedMethod('update()', 'Create your query with updateQuery() instead.');
+
+ return parent::update($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function set($key, $value = null, $types = [])
+ {
+ $this->_deprecatedMethod('set()');
+
+ return parent::set($key, $value, $types);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Query/InsertQuery.php b/app/vendor/cakephp/cakephp/src/Database/Query/InsertQuery.php
new file mode 100644
index 000000000..7d326239b
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/Query/InsertQuery.php
@@ -0,0 +1,322 @@
+_deprecatedMethod('delete()', 'Create your query with deleteQuery() instead.');
+
+ return parent::delete($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function select($fields = [], bool $overwrite = false)
+ {
+ $this->_deprecatedMethod('select()', 'Create your query with selectQuery() instead.');
+
+ return parent::select($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function distinct($on = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('distinct()');
+
+ return parent::distinct($on, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function modifier($modifiers, $overwrite = false)
+ {
+ $this->_deprecatedMethod('modifier()');
+
+ return parent::modifier($modifiers, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function join($tables, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('join()');
+
+ return parent::join($tables, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeJoin(string $name)
+ {
+ $this->_deprecatedMethod('removeJoin()');
+
+ return parent::removeJoin($name);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function leftJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('leftJoin()');
+
+ return parent::leftJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function rightJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('rightJoin()');
+
+ return parent::rightJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function innerJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('innerJoin()');
+
+ return parent::innerJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function group($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('group()');
+
+ return parent::group($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function having($conditions = null, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('having()');
+
+ return parent::having($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andHaving($conditions, $types = [])
+ {
+ $this->_deprecatedMethod('andHaving()');
+
+ return parent::andHaving($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function page(int $num, ?int $limit = null)
+ {
+ $this->_deprecatedMethod('page()');
+
+ return parent::page($num, $limit);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offset($offset)
+ {
+ $this->_deprecatedMethod('offset()');
+
+ return parent::offset($offset);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function union($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::union($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function unionAll($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::unionAll($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function from($tables = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('from()', 'Use into() instead.');
+
+ return parent::from($tables, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update($table)
+ {
+ $this->_deprecatedMethod('update()', 'Create your query with updateQuery() instead.');
+
+ return parent::update($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function set($key, $value = null, $types = [])
+ {
+ $this->_deprecatedMethod('set()');
+
+ return parent::set($key, $value, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function where($conditions = null, array $types = [], bool $overwrite = false)
+ {
+ $this->_deprecatedMethod('where()');
+
+ return parent::where($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNotNull($fields)
+ {
+ $this->_deprecatedMethod('whereNotNull()');
+
+ return parent::whereNotNull($fields);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNull($fields)
+ {
+ $this->_deprecatedMethod('whereNull()');
+
+ return parent::whereNull($fields);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereInList(string $field, array $values, array $options = [])
+ {
+ $this->_deprecatedMethod('whereInList()');
+
+ return parent::whereInList($field, $values, $options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNotInList(string $field, array $values, array $options = [])
+ {
+ $this->_deprecatedMethod('whereNotInList()');
+
+ return parent::whereNotInList($field, $values, $options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNotInListOrNull(string $field, array $values, array $options = [])
+ {
+ $this->_deprecatedMethod('whereNotInListOrNull()');
+
+ return parent::whereNotInListOrNull($field, $values, $options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andWhere($conditions, array $types = [])
+ {
+ $this->_deprecatedMethod('andWhere()');
+
+ return parent::andWhere($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function order($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('order()');
+
+ return parent::order($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function orderAsc($field, $overwrite = false)
+ {
+ $this->_deprecatedMethod('orderAsc()');
+
+ return parent::orderAsc($field, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function orderDesc($field, $overwrite = false)
+ {
+ $this->_deprecatedMethod('orderDesc()');
+
+ return parent::orderDesc($field, $overwrite);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Query/SelectQuery.php b/app/vendor/cakephp/cakephp/src/Database/Query/SelectQuery.php
new file mode 100644
index 000000000..7d2986aba
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/Query/SelectQuery.php
@@ -0,0 +1,127 @@
+_deprecatedMethod('delete()', 'Create your query with deleteQuery() instead.');
+
+ return parent::delete($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function insert(array $columns, array $types = [])
+ {
+ $this->_deprecatedMethod('insert()', 'Create your query with insertQuery() instead.');
+
+ return parent::insert($columns, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function into(string $table)
+ {
+ $this->_deprecatedMethod('into()', 'Use from() instead.');
+
+ return parent::into($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function values($data)
+ {
+ $this->_deprecatedMethod('values()');
+
+ return parent::values($data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update($table)
+ {
+ $this->_deprecatedMethod('update()', 'Create your query with updateQuery() instead.');
+
+ return parent::update($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function set($key, $value = null, $types = [])
+ {
+ $this->_deprecatedMethod('set()');
+
+ return parent::set($key, $value, $types);
+ }
+
+ /**
+ * Sets the connection role.
+ *
+ * @param string $role Connection role ('read' or 'write')
+ * @return $this
+ */
+ public function setConnectionRole(string $role)
+ {
+ assert($role === Connection::ROLE_READ || $role === Connection::ROLE_WRITE);
+ $this->connectionRole = $role;
+
+ return $this;
+ }
+
+ /**
+ * Sets the connection role to read.
+ *
+ * @return $this
+ */
+ public function useReadRole()
+ {
+ return $this->setConnectionRole(Connection::ROLE_READ);
+ }
+
+ /**
+ * Sets the connection role to write.
+ *
+ * @return $this
+ */
+ public function useWriteRole()
+ {
+ return $this->setConnectionRole(Connection::ROLE_WRITE);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Query/UpdateQuery.php b/app/vendor/cakephp/cakephp/src/Database/Query/UpdateQuery.php
new file mode 100644
index 000000000..0f84cce6c
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Database/Query/UpdateQuery.php
@@ -0,0 +1,182 @@
+_deprecatedMethod('delete()', 'Create your query with deleteQuery() instead.');
+
+ return parent::delete($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function select($fields = [], bool $overwrite = false)
+ {
+ $this->_deprecatedMethod('select()', 'Create your query with selectQuery() instead.');
+
+ return parent::select($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function distinct($on = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('distinct()');
+
+ return parent::distinct($on, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function modifier($modifiers, $overwrite = false)
+ {
+ $this->_deprecatedMethod('modifier()');
+
+ return parent::modifier($modifiers, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function group($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('group()');
+
+ return parent::group($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function having($conditions = null, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('having()');
+
+ return parent::having($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andHaving($conditions, $types = [])
+ {
+ $this->_deprecatedMethod('andHaving()');
+
+ return parent::andHaving($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function page(int $num, ?int $limit = null)
+ {
+ $this->_deprecatedMethod('page()');
+
+ return parent::page($num, $limit);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offset($offset)
+ {
+ $this->_deprecatedMethod('offset()');
+
+ return parent::offset($offset);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function union($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::union($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function unionAll($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::unionAll($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function insert(array $columns, array $types = [])
+ {
+ $this->_deprecatedMethod('insert()', 'Create your query with insertQuery() instead.');
+
+ return parent::insert($columns, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function into(string $table)
+ {
+ $this->_deprecatedMethod('into()', 'Use update() instead.');
+
+ return parent::into($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function values($data)
+ {
+ $this->_deprecatedMethod('values()');
+
+ return parent::values($data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function from($tables = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('from()', 'Use update() instead.');
+
+ return parent::from($tables, $overwrite);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php b/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php
index 236d5eb72..9ed44223e 100644
--- a/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php
+++ b/app/vendor/cakephp/cakephp/src/Database/QueryCompiler.php
@@ -201,7 +201,7 @@ protected function _buildSelectPart(array $parts, Query $query, ValueBinder $bin
$distinct = $query->clause('distinct');
$modifiers = $this->_buildModifierPart($query->clause('modifier'), $query, $binder);
- $driver = $query->getConnection()->getDriver();
+ $driver = $query->getConnection()->getDriver($query->getConnectionRole());
$quoteIdentifiers = $driver->isAutoQuotingEnabled() || $this->_quotedSelectAliases;
$normalized = [];
$parts = $this->_stringifyExpressions($parts, $binder);
diff --git a/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php b/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
index 7d76cc01e..25fb69f80 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Retry/ReconnectStrategy.php
@@ -104,12 +104,12 @@ protected function reconnect(): bool
try {
// Make sure we free any resources associated with the old connection
- $this->connection->disconnect();
+ $this->connection->getDriver()->disconnect();
} catch (Exception $e) {
}
try {
- $this->connection->connect();
+ $this->connection->getDriver()->connect();
if ($this->connection->isQueryLoggingEnabled()) {
$this->connection->log('[RECONNECT]');
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php b/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php
index 46513170d..8d32d3448 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/BaseSchema.php
@@ -1,5 +1,10 @@
_dialect->listTablesWithoutViewsSql($this->_connection->config());
+ [$sql, $params] = $this->_dialect->listTablesWithoutViewsSql($this->_connection->getDriver()->config());
$result = [];
$statement = $this->_connection->execute($sql, $params);
while ($row = $statement->fetch()) {
@@ -78,7 +78,7 @@ public function listTablesWithoutViews(): array
*/
public function listTables(): array
{
- [$sql, $params] = $this->_dialect->listTablesSql($this->_connection->config());
+ [$sql, $params] = $this->_dialect->listTablesSql($this->_connection->getDriver()->config());
$result = [];
$statement = $this->_connection->execute($sql, $params);
while ($row = $statement->fetch()) {
@@ -109,7 +109,7 @@ public function listTables(): array
*/
public function describe(string $name, array $options = []): TableSchemaInterface
{
- $config = $this->_connection->config();
+ $config = $this->_connection->getDriver()->config();
if (strpos($name, '.')) {
[$config['schema'], $name] = explode('.', $name);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/MysqlSchema.php b/app/vendor/cakephp/cakephp/src/Database/Schema/MysqlSchema.php
index 237d6362b..30b20db6e 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/MysqlSchema.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/MysqlSchema.php
@@ -1,5 +1,10 @@
TableSchema::TYPE_BOOLEAN, 'length' => null];
}
- if ($col === 'char' && $length === 36) {
+ if (($col === 'char' && $length === 36) || $col === 'uuid') {
return ['type' => TableSchema::TYPE_UUID, 'length' => null];
}
if ($col === 'char') {
@@ -642,6 +642,8 @@ public function hasSequences(): bool
}
// phpcs:disable
-// Add backwards compatible alias.
-class_alias('Cake\Database\Schema\SqliteSchemaDialect', 'Cake\Database\Schema\SqliteSchema');
+class_alias(
+ 'Cake\Database\Schema\SqliteSchemaDialect',
+ 'Cake\Database\Schema\SqliteSchema'
+);
// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php b/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php
index dbe584efd..62e3f6981 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Schema/SqlserverSchema.php
@@ -1,5 +1,10 @@
_schema->describe($table, ['forceRefresh' => true]);
}
@@ -86,7 +85,6 @@ public function clear(?string $name = null): array
$cacher = $this->_schema->getCacher();
foreach ($tables as $table) {
- /** @psalm-suppress PossiblyNullArgument */
$key = $this->_schema->cacheKey($table);
$cacher->delete($key);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php b/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php
index 38ef7bc08..763f8fd70 100644
--- a/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/SqlDialectTrait.php
@@ -1,5 +1,10 @@
*/
class BufferedStatement implements Iterator, StatementInterface
{
@@ -85,6 +87,16 @@ public function __construct(StatementInterface $statement, DriverInterface $driv
$this->_driver = $driver;
}
+ /**
+ * Returns the connection driver.
+ *
+ * @return \Cake\Database\DriverInterface
+ */
+ protected function getDriver(): DriverInterface
+ {
+ return $this->_driver;
+ }
+
/**
* Magic getter to return $queryString as read-only.
*
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php
index 5e7309ad1..6cbc82720 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/PDOStatement.php
@@ -20,6 +20,7 @@
use Cake\Database\DriverInterface;
use PDO;
use PDOStatement as Statement;
+use function Cake\Core\getTypeName;
/**
* Decorator for \PDOStatement class mainly used for converting human readable
@@ -55,7 +56,6 @@ public function __construct(Statement $statement, DriverInterface $driver)
public function __get(string $property)
{
if ($property === 'queryString' && isset($this->_statement->queryString)) {
- /** @psalm-suppress NoInterfaceProperties */
return $this->_statement->queryString;
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php b/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php
index efd3b6a2c..39f3be8c3 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/SqlserverStatement.php
@@ -45,7 +45,6 @@ public function bindValue($column, $value, $type = 'string'): void
[$value, $type] = $this->cast($value, $type);
}
if ($type === PDO::PARAM_LOB) {
- /** @psalm-suppress UndefinedConstant */
$this->_statement->bindParam($column, $value, $type, 0, PDO::SQLSRV_ENCODING_BINARY);
} else {
$this->_statement->bindValue($column, $value, $type);
diff --git a/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php b/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php
index 4a1d33e95..2c2f46bfa 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Statement/StatementDecorator.php
@@ -32,6 +32,7 @@
* PDOStatement.
*
* @property-read string $queryString
+ * @template-implements \IteratorAggregate
*/
class StatementDecorator implements StatementInterface, Countable, IteratorAggregate
{
@@ -72,6 +73,16 @@ public function __construct(StatementInterface $statement, DriverInterface $driv
$this->_driver = $driver;
}
+ /**
+ * Returns the connection driver.
+ *
+ * @return \Cake\Database\DriverInterface
+ */
+ protected function getDriver(): DriverInterface
+ {
+ return $this->_driver;
+ }
+
/**
* Magic getter to return $queryString as read-only.
*
@@ -326,7 +337,6 @@ public function bind(array $params, array $types): void
/** @psalm-suppress InvalidOperand */
$index += $offset;
}
- /** @psalm-suppress InvalidScalarArgument */
$this->bindValue($index, $value, $type);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type.php b/app/vendor/cakephp/cakephp/src/Database/Type.php
index 466b8d597..164419c87 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type.php
@@ -1,5 +1,9 @@
setTimezone($this->defaultTimezone);
}
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php b/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php
index 19d5453fe..0cd63cd6c 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/DateType.php
@@ -22,6 +22,8 @@
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
+use Exception;
+use function Cake\Core\deprecationWarning;
/**
* Class DateType
@@ -102,14 +104,61 @@ public function useMutable()
*/
public function marshal($value): ?DateTimeInterface
{
- $date = parent::marshal($value);
- /** @psalm-var \DateTime|\DateTimeImmutable|null $date */
- if ($date && !$date instanceof I18nDateTimeInterface) {
- // Clear time manually when I18n types aren't available and raw DateTime used
- $date = $date->setTime(0, 0, 0);
+ if ($value instanceof DateTimeInterface) {
+ return new FrozenDate($value);
}
- return $date;
+ /** @var class-string<\Cake\Chronos\ChronosDate> $class */
+ $class = $this->_className;
+ try {
+ if ($value === '' || $value === null || is_bool($value)) {
+ return null;
+ }
+
+ if (is_int($value) || (is_string($value) && ctype_digit($value))) {
+ /** @var \Cake\I18n\FrozenDate|\DateTimeImmutable $dateTime */
+ $dateTime = new $class('@' . $value);
+
+ return $dateTime;
+ }
+
+ if (is_string($value)) {
+ if ($this->_useLocaleMarshal) {
+ $dateTime = $this->_parseLocaleValue($value);
+ } else {
+ $dateTime = $this->_parseValue($value);
+ }
+
+ return $dateTime;
+ }
+ } catch (Exception $e) {
+ return null;
+ }
+
+ if (is_array($value) && implode('', $value) === '') {
+ return null;
+ }
+ $format = '';
+ if (
+ isset($value['year'], $value['month'], $value['day']) &&
+ (
+ is_numeric($value['year']) &&
+ is_numeric($value['month']) &&
+ is_numeric($value['day'])
+ )
+ ) {
+ $format .= sprintf('%d-%02d-%02d', $value['year'], $value['month'], $value['day']);
+ }
+
+ if (empty($format)) {
+ // Invalid array format.
+ return null;
+ }
+
+ /** @var \Cake\I18n\FrozenDate|\DateTimeImmutable $dateTime */
+ $dateTime = new $class($format);
+
+ return $dateTime;
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php b/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php
index cb332fd37..f06f6d795 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/DecimalType.php
@@ -21,6 +21,7 @@
use InvalidArgumentException;
use PDO;
use RuntimeException;
+use function Cake\Core\getTypeName;
/**
* Decimal type converter.
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php b/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php
index 4a84c59e3..973d7ca55 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/IntegerType.php
@@ -19,6 +19,7 @@
use Cake\Database\DriverInterface;
use InvalidArgumentException;
use PDO;
+use function Cake\Core\getTypeName;
/**
* Integer type converter.
diff --git a/app/vendor/cakephp/cakephp/src/Database/Type/StringType.php b/app/vendor/cakephp/cakephp/src/Database/Type/StringType.php
index 4dd38bc86..4c98e3369 100644
--- a/app/vendor/cakephp/cakephp/src/Database/Type/StringType.php
+++ b/app/vendor/cakephp/cakephp/src/Database/Type/StringType.php
@@ -19,6 +19,7 @@
use Cake\Database\DriverInterface;
use InvalidArgumentException;
use PDO;
+use function Cake\Core\getTypeName;
/**
* String type converter.
diff --git a/app/vendor/cakephp/cakephp/src/Database/TypeConverterTrait.php b/app/vendor/cakephp/cakephp/src/Database/TypeConverterTrait.php
index f92c85027..2f04b814e 100644
--- a/app/vendor/cakephp/cakephp/src/Database/TypeConverterTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Database/TypeConverterTrait.php
@@ -36,8 +36,8 @@ public function cast($value, $type = 'string'): array
$type = TypeFactory::build($type);
}
if ($type instanceof TypeInterface) {
- $value = $type->toDatabase($value, $this->_driver);
- $type = $type->toStatement($value, $this->_driver);
+ $value = $type->toDatabase($value, $this->getDriver());
+ $type = $type->toStatement($value, $this->getDriver());
}
return [$value, $type];
diff --git a/app/vendor/cakephp/cakephp/src/Database/TypeFactory.php b/app/vendor/cakephp/cakephp/src/Database/TypeFactory.php
index 2f5006697..617bad6d9 100644
--- a/app/vendor/cakephp/cakephp/src/Database/TypeFactory.php
+++ b/app/vendor/cakephp/cakephp/src/Database/TypeFactory.php
@@ -162,3 +162,10 @@ public static function clear(): void
static::$_builtTypes = [];
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Database\TypeFactory',
+ 'Cake\Database\Type'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php b/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php
index 1a63a57d9..0e5dd3d08 100644
--- a/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php
+++ b/app/vendor/cakephp/cakephp/src/Database/ValueBinder.php
@@ -148,4 +148,16 @@ public function attachTo(StatementInterface $statement): void
$statement->bindValue($b['placeholder'], $b['value'], $b['type']);
}
}
+
+ /**
+ * Get verbose debugging data.
+ *
+ * @return array
+ */
+ public function __debugInfo(): array
+ {
+ return [
+ 'bindings' => $this->bindings(),
+ ];
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php
index 01a7d5330..7efef433d 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionInterface.php
@@ -30,8 +30,6 @@
* already created tables. {@see \Cake\Database\Connnection::supportsDynamicConstraints()}
* @method \Cake\Database\Schema\Collection getSchemaCollection() Gets a Schema\Collection object for this connection.
* {@see \Cake\Database\Connnection::getSchemaCollection()}
- * @method \Cake\Database\Query newQuery() Create a new Query instance for this connection.
- * {@see \Cake\Database\Connnection::newQuery()}
* @method \Cake\Database\StatementInterface prepare($sql) Prepares a SQL statement to be executed.
* {@see \Cake\Database\Connnection::prepare()}
* @method \Cake\Database\StatementInterface execute($query, $params = [], array $types = []) Executes a query using
@@ -42,6 +40,16 @@
*/
interface ConnectionInterface extends LoggerAwareInterface
{
+ /**
+ * @var string
+ */
+ public const ROLE_WRITE = 'write';
+
+ /**
+ * @var string
+ */
+ public const ROLE_READ = 'read';
+
/**
* Gets the current logger object.
*
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php
index 54adf540f..8f244ea16 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ConnectionManager.php
@@ -43,7 +43,7 @@ class ConnectionManager
/**
* A map of connection aliases.
*
- * @var array
+ * @var array
*/
protected static $_aliasMap = [];
@@ -63,7 +63,7 @@ class ConnectionManager
/**
* The ConnectionRegistry used by the manager.
*
- * @var \Cake\Datasource\ConnectionRegistry
+ * @var \Cake\Datasource\ConnectionRegistry|null
*/
protected static $_registry;
@@ -173,6 +173,16 @@ public static function dropAlias(string $alias): void
unset(static::$_aliasMap[$alias]);
}
+ /**
+ * Returns the current connection aliases and what they alias.
+ *
+ * @return array
+ */
+ public static function aliases(): array
+ {
+ return static::$_aliasMap;
+ }
+
/**
* Get a connection.
*
@@ -182,8 +192,8 @@ public static function dropAlias(string $alias): void
* as second parameter.
*
* @param string $name The connection name.
- * @param bool $useAliases Set to false to not use aliased connections.
- * @return \Cake\Datasource\ConnectionInterface A connection object.
+ * @param bool $useAliases Whether connection aliases are used
+ * @return \Cake\Datasource\ConnectionInterface
* @throws \Cake\Datasource\Exception\MissingDatasourceConfigException When config
* data is missing.
*/
@@ -192,15 +202,15 @@ public static function get(string $name, bool $useAliases = true)
if ($useAliases && isset(static::$_aliasMap[$name])) {
$name = static::$_aliasMap[$name];
}
- if (empty(static::$_config[$name])) {
+
+ if (!isset(static::$_config[$name])) {
throw new MissingDatasourceConfigException(['name' => $name]);
}
- /** @psalm-suppress RedundantPropertyInitializationCheck */
+
if (!isset(static::$_registry)) {
static::$_registry = new ConnectionRegistry();
}
- return static::$_registry->{$name}
- ?? static::$_registry->load($name, static::$_config[$name]);
+ return static::$_registry->{$name} ?? static::$_registry->load($name, static::$_config[$name]);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php
index c0991064b..58876709b 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/EntityInterface.php
@@ -25,6 +25,7 @@
*
* @property mixed $id Alias for commonly used primary key.
* @method bool[] getAccessible() Accessible configuration for this entity.
+ * @template-extends \ArrayAccess
*/
interface EntityInterface extends ArrayAccess, JsonSerializable
{
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php b/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php
index b8ef4a9dd..3cd54bb1a 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/EntityTrait.php
@@ -22,6 +22,7 @@
use Cake\Utility\Inflector;
use InvalidArgumentException;
use Traversable;
+use function Cake\Core\deprecationWarning;
/**
* An entity represents a single result row from a repository. It exposes the
@@ -118,6 +119,23 @@ trait EntityTrait
*/
protected $_registryAlias = '';
+ /**
+ * Storing the current visitation status while recursing through entities getting errors.
+ *
+ * @var bool
+ */
+ protected $_hasBeenVisited = false;
+
+ /**
+ * Set to true in your entity's class definition or
+ * via application logic. When true. has() and related
+ * methods will use `array_key_exists` instead of `isset`
+ * to decide if fields are 'defined' in an entity.
+ *
+ * @var bool
+ */
+ protected $_hasAllowsNull = false;
+
/**
* Magic getter to access fields that have been set in this entity
*
@@ -361,7 +379,11 @@ public function getOriginalValues(): array
public function has($field): bool
{
foreach ((array)$field as $prop) {
- if ($this->get($prop) === null) {
+ if ($this->_hasAllowsNull) {
+ if (!array_key_exists($prop, $this->_fields) && !static::_accessor($prop, 'get')) {
+ return false;
+ }
+ } elseif ($this->get($prop) === null) {
return false;
}
}
@@ -845,6 +867,11 @@ public function isNew(): bool
*/
public function hasErrors(bool $includeNested = true): bool
{
+ if ($this->_hasBeenVisited) {
+ // While recursing through entities, each entity should only be visited once. See https://github.com/cakephp/cakephp/issues/17318
+ return false;
+ }
+
if (Hash::filter($this->_errors)) {
return true;
}
@@ -853,10 +880,15 @@ public function hasErrors(bool $includeNested = true): bool
return false;
}
- foreach ($this->_fields as $field) {
- if ($this->_readHasErrors($field)) {
- return true;
+ $this->_hasBeenVisited = true;
+ try {
+ foreach ($this->_fields as $field) {
+ if ($this->_readHasErrors($field)) {
+ return true;
+ }
}
+ } finally {
+ $this->_hasBeenVisited = false;
}
return false;
@@ -869,17 +901,29 @@ public function hasErrors(bool $includeNested = true): bool
*/
public function getErrors(): array
{
+ if ($this->_hasBeenVisited) {
+ // While recursing through entities, each entity should only be visited once. See https://github.com/cakephp/cakephp/issues/17318
+ return [];
+ }
+
$diff = array_diff_key($this->_fields, $this->_errors);
- return $this->_errors + (new Collection($diff))
- ->filter(function ($value) {
- return is_array($value) || $value instanceof EntityInterface;
- })
- ->map(function ($value) {
- return $this->_readError($value);
- })
- ->filter()
- ->toArray();
+ $this->_hasBeenVisited = true;
+ try {
+ $errors = $this->_errors + (new Collection($diff))
+ ->filter(function ($value) {
+ return is_array($value) || $value instanceof EntityInterface;
+ })
+ ->map(function ($value) {
+ return $this->_readError($value);
+ })
+ ->filter()
+ ->toArray();
+ } finally {
+ $this->_hasBeenVisited = false;
+ }
+
+ return $errors;
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/Exception/PageOutOfBoundsException.php b/app/vendor/cakephp/cakephp/src/Datasource/Exception/PageOutOfBoundsException.php
index be75b2d76..a841303dd 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/Exception/PageOutOfBoundsException.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/Exception/PageOutOfBoundsException.php
@@ -1,7 +1,10 @@
{$alias})) {
return $this->{$alias};
@@ -135,6 +142,60 @@ public function loadModel(?string $modelClass = null, ?string $modelType = null)
return $this->{$alias};
}
+ /**
+ * Fetch or construct a model instance from a locator.
+ *
+ * Uses a modelFactory based on `$modelType` to fetch and construct a `RepositoryInterface`
+ * and return it. The default `modelType` can be defined with `setModelType()`.
+ *
+ * Unlike `loadModel()` this method will *not* set an object property.
+ *
+ * If a repository provider does not return an object a MissingModelException will
+ * be thrown.
+ *
+ * @param string|null $modelClass Name of model class to load. Defaults to $this->modelClass.
+ * The name can be an alias like `'Post'` or FQCN like `App\Model\Table\PostsTable::class`.
+ * @param string|null $modelType The type of repository to load. Defaults to the getModelType() value.
+ * @return \Cake\Datasource\RepositoryInterface The model instance created.
+ * @throws \Cake\Datasource\Exception\MissingModelException If the model class cannot be found.
+ * @throws \UnexpectedValueException If $modelClass argument is not provided
+ * and ModelAwareTrait::$modelClass property value is empty.
+ */
+ public function fetchModel(?string $modelClass = null, ?string $modelType = null): RepositoryInterface
+ {
+ $modelClass = $modelClass ?? $this->modelClass;
+ if (empty($modelClass)) {
+ throw new UnexpectedValueException('Default modelClass is empty');
+ }
+ $modelType = $modelType ?? $this->getModelType();
+
+ $options = [];
+ if (strpos($modelClass, '\\') === false) {
+ [, $alias] = pluginSplit($modelClass, true);
+ } else {
+ $options['className'] = $modelClass;
+ /** @psalm-suppress PossiblyFalseOperand */
+ $alias = substr(
+ $modelClass,
+ strrpos($modelClass, '\\') + 1,
+ -strlen($modelType)
+ );
+ $modelClass = $alias;
+ }
+
+ $factory = $this->_modelFactories[$modelType] ?? FactoryLocator::get($modelType);
+ if ($factory instanceof LocatorInterface) {
+ $instance = $factory->get($modelClass, $options);
+ } else {
+ $instance = $factory($modelClass, $options);
+ }
+ if ($instance) {
+ return $instance;
+ }
+
+ throw new MissingModelException([$modelClass, $modelType]);
+ }
+
/**
* Override a existing callable to generate repositories of a given type.
*
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php b/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php
index a87c8ea62..926b2318f 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/Paginator.php
@@ -1,7 +1,10 @@
20,
'maxLimit' => 100,
'allowedParameters' => ['limit', 'sort', 'page', 'direction'],
+ 'sortableFields' => null,
+ 'finder' => 'all',
];
/**
@@ -214,10 +217,17 @@ public function paginate(object $object, array $params = [], array $settings = [
*/
protected function getQuery(RepositoryInterface $object, ?QueryInterface $query, array $data): QueryInterface
{
+ $options = $data['options'];
+ unset(
+ $options['scope'],
+ $options['sort'],
+ $options['direction'],
+ );
+
if ($query === null) {
- $query = $object->find($data['finder'], $data['options']);
+ $query = $object->find($data['finder'], $options);
} else {
- $query->applyOptions($data['options']);
+ $query->applyOptions($options);
}
return $query;
@@ -247,6 +257,20 @@ protected function extractData(RepositoryInterface $object, array $params, array
{
$alias = $object->getAlias();
$defaults = $this->getDefaults($alias, $settings);
+
+ $validSettings = array_merge(
+ array_keys($this->_defaultConfig),
+ ['whitelist', 'sortWhitelist', 'order', 'scope']
+ );
+ $extraSettings = array_diff_key($defaults, array_flip($validSettings));
+ if ($extraSettings) {
+ deprecationWarning(
+ 'Passing query options as paginator settings is deprecated.'
+ . ' Use a custom finder through `finder` config instead.'
+ . ' Extra keys found are: ' . implode(',', array_keys($extraSettings))
+ );
+ }
+
$options = $this->mergeOptions($params, $defaults);
$options = $this->validateSort($object, $options);
$options = $this->checkLimit($options);
@@ -396,7 +420,14 @@ protected function addSortingParams(array $params, array $data): array
protected function _extractFinder(array $options): array
{
$type = !empty($options['finder']) ? $options['finder'] : 'all';
- unset($options['finder'], $options['maxLimit']);
+ unset(
+ $options['finder'],
+ $options['maxLimit'],
+ $options['allowedParameters'],
+ $options['whitelist'],
+ $options['sortableFields'],
+ $options['sortWhitelist'],
+ );
if (is_array($type)) {
$options = (array)current($type) + $options;
@@ -611,6 +642,13 @@ protected function _removeAliases(array $fields, string $model): array
{
$result = [];
foreach ($fields as $field => $sort) {
+ if (is_int($field)) {
+ throw new CakeException(sprintf(
+ 'The `order` config must be an associative array. Found invalid value with numeric key: `%s`',
+ $sort
+ ));
+ }
+
if (strpos($field, '.') === false) {
$result[$field] = $sort;
continue;
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php
index 3c34bdf8d..47fede090 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/QueryInterface.php
@@ -24,6 +24,7 @@
* provided list using the AND operator. {@see \Cake\Database\Query::andWhere()}
* @method \Cake\Datasource\EntityInterface|array firstOrFail() Get the first result from the executing query or raise an exception.
* {@see \Cake\Database\Query::firstOrFail()}
+ * @method $this setRepository(\Cake\Datasource\RepositoryInterface $repository) Set the default repository object that will be used by this query.
*/
interface QueryInterface
{
@@ -278,6 +279,7 @@ public function toArray(): array;
*
* @param \Cake\Datasource\RepositoryInterface $repository The default repository object to use
* @return $this
+ * @deprecated
*/
public function repository(RepositoryInterface $repository);
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php b/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php
index 6d70a77b5..15525612e 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/QueryTrait.php
@@ -17,10 +17,12 @@
namespace Cake\Datasource;
use BadMethodCallException;
+use Cake\Collection\CollectionInterface;
use Cake\Collection\Iterator\MapReduce;
use Cake\Datasource\Exception\RecordNotFoundException;
use InvalidArgumentException;
use Traversable;
+use function Cake\Core\deprecationWarning;
/**
* Contains the characteristics for an object that is attached to a repository and
@@ -89,8 +91,23 @@ trait QueryTrait
*
* @param \Cake\Datasource\RepositoryInterface|\Cake\ORM\Table $repository The default table object to use
* @return $this
+ * @deprecated 4.5.0 Use `setRepository()` instead.
*/
public function repository(RepositoryInterface $repository)
+ {
+ deprecationWarning('`repository() method is deprecated. Use `setRepository()` instead.');
+
+ return $this->setRepository($repository);
+ }
+
+ /**
+ * Set the default Table object that will be used by this query
+ * and form the `FROM` clause.
+ *
+ * @param \Cake\Datasource\RepositoryInterface|\Cake\ORM\Table $repository The default table object to use
+ * @return $this
+ */
+ public function setRepository(RepositoryInterface $repository)
{
$this->_repository = $repository;
@@ -564,6 +581,833 @@ public function __call(string $method, array $arguments)
);
}
+ /**
+ * @param callable $callback The callback to apply
+ * @see \Cake\Collection\CollectionInterface::each()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function each(callable $callback): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling each() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->each(...)` instead.'
+ );
+
+ return $this->all()->each($callback);
+ }
+
+ /**
+ * @param ?callable $callback The callback to apply
+ * @see \Cake\Collection\CollectionInterface::filter()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function filter(?callable $callback = null): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling filter() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->filter(...)` instead.'
+ );
+
+ return $this->all()->filter($callback);
+ }
+
+ /**
+ * @param callable $callback The callback to apply
+ * @see \Cake\Collection\CollectionInterface::reject()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function reject(callable $callback): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling reject() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->reject(...)` instead.'
+ );
+
+ return $this->all()->reject($callback);
+ }
+
+ /**
+ * @param callable $callback The callback to apply
+ * @see \Cake\Collection\CollectionInterface::every()
+ * @return bool
+ * @deprecated
+ */
+ public function every(callable $callback): bool
+ {
+ deprecationWarning(
+ '4.3.0 - Calling every() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->every(...)` instead.'
+ );
+
+ return $this->all()->every($callback);
+ }
+
+ /**
+ * @param callable $callback The callback to apply
+ * @see \Cake\Collection\CollectionInterface::some()
+ * @return bool
+ * @deprecated
+ */
+ public function some(callable $callback): bool
+ {
+ deprecationWarning(
+ '4.3.0 - Calling some() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->some(...)` instead.'
+ );
+
+ return $this->all()->some($callback);
+ }
+
+ /**
+ * @param mixed $value The value to check.
+ * @see \Cake\Collection\CollectionInterface::contains()
+ * @return bool
+ * @deprecated
+ */
+ public function contains($value): bool
+ {
+ deprecationWarning(
+ '4.3.0 - Calling contains() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->contains(...)` instead.'
+ );
+
+ return $this->all()->contains($value);
+ }
+
+ /**
+ * @param callable $callback The callback to apply
+ * @see \Cake\Collection\CollectionInterface::map()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function map(callable $callback): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling map() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->map(...)` instead.'
+ );
+
+ return $this->all()->map($callback);
+ }
+
+ /**
+ * @param callable $callback The callback to apply
+ * @param mixed $initial The initial value
+ * @see \Cake\Collection\CollectionInterface::reduce()
+ * @return mixed
+ * @deprecated
+ */
+ public function reduce(callable $callback, $initial = null)
+ {
+ deprecationWarning(
+ '4.3.0 - Calling reduce() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->reduce(...)` instead.'
+ );
+
+ return $this->all()->reduce($callback, $initial);
+ }
+
+ /**
+ * @param callable|string $path The path to extract
+ * @see \Cake\Collection\CollectionInterface::extract()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function extract($path): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling extract() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->extract(...)` instead.'
+ );
+
+ return $this->all()->extract($path);
+ }
+
+ /**
+ * @param callable|string $path The path to max
+ * @param int $sort The SORT_ constant to order by.
+ * @see \Cake\Collection\CollectionInterface::max()
+ * @return mixed
+ * @deprecated
+ */
+ public function max($path, int $sort = \SORT_NUMERIC)
+ {
+ deprecationWarning(
+ '4.3.0 - Calling max() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->max(...)` instead.'
+ );
+
+ return $this->all()->max($path, $sort);
+ }
+
+ /**
+ * @param callable|string $path The path to max
+ * @param int $sort The SORT_ constant to order by.
+ * @see \Cake\Collection\CollectionInterface::min()
+ * @return mixed
+ * @deprecated
+ */
+ public function min($path, int $sort = \SORT_NUMERIC)
+ {
+ deprecationWarning(
+ '4.3.0 - Calling min() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->min(...)` instead.'
+ );
+
+ return $this->all()->min($path, $sort);
+ }
+
+ /**
+ * @param callable|string|null $path the path to average
+ * @see \Cake\Collection\CollectionInterface::avg()
+ * @return float|int|null
+ * @deprecated
+ */
+ public function avg($path = null)
+ {
+ deprecationwarning(
+ '4.3.0 - calling avg() on a query is deprecated. ' .
+ 'instead call `$query->all()->avg(...)` instead.'
+ );
+
+ return $this->all()->avg($path);
+ }
+
+ /**
+ * @param callable|string|null $path the path to average
+ * @see \Cake\Collection\CollectionInterface::median()
+ * @return float|int|null
+ * @deprecated
+ */
+ public function median($path = null)
+ {
+ deprecationwarning(
+ '4.3.0 - calling median() on a query is deprecated. ' .
+ 'instead call `$query->all()->median(...)` instead.'
+ );
+
+ return $this->all()->median($path);
+ }
+
+ /**
+ * @param callable|string $path the path to average
+ * @param int $order The \SORT_ constant for the direction you want results in.
+ * @param int $sort The \SORT_ method to use.
+ * @see \Cake\Collection\CollectionInterface::sortBy()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function sortBy($path, int $order = SORT_DESC, int $sort = \SORT_NUMERIC): CollectionInterface
+ {
+ deprecationwarning(
+ '4.3.0 - calling sortBy() on a query is deprecated. ' .
+ 'instead call `$query->all()->sortBy(...)` instead.'
+ );
+
+ return $this->all()->sortBy($path, $order, $sort);
+ }
+
+ /**
+ * @param callable|string $path The path to group by
+ * @see \Cake\Collection\CollectionInterface::groupBy()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function groupBy($path): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling groupBy() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->groupBy(...)` instead.'
+ );
+
+ return $this->all()->groupBy($path);
+ }
+
+ /**
+ * @param string|callable $path The path to extract
+ * @see \Cake\Collection\CollectionInterface::indexBy()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function indexBy($path): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling indexBy() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->indexBy(...)` instead.'
+ );
+
+ return $this->all()->indexBy($path);
+ }
+
+ /**
+ * @param string|callable $path The path to count by
+ * @see \Cake\Collection\CollectionInterface::countBy()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function countBy($path): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling countBy() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->countBy(...)` instead.'
+ );
+
+ return $this->all()->countBy($path);
+ }
+
+ /**
+ * @param string|callable $path The path to sum
+ * @see \Cake\Collection\CollectionInterface::sumOf()
+ * @return int|float
+ * @deprecated
+ */
+ public function sumOf($path = null)
+ {
+ deprecationWarning(
+ '4.3.0 - Calling sumOf() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->sumOf(...)` instead.'
+ );
+
+ return $this->all()->sumOf($path);
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::shuffle()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function shuffle(): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling shuffle() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->shuffle(...)` instead.'
+ );
+
+ return $this->all()->shuffle();
+ }
+
+ /**
+ * @param int $length The number of samples to select
+ * @see \Cake\Collection\CollectionInterface::sample()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function sample(int $length = 10): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling sample() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->sample(...)` instead.'
+ );
+
+ return $this->all()->sample($length);
+ }
+
+ /**
+ * @param int $length The number of elements to take
+ * @param int $offset The offset of the first element to take.
+ * @see \Cake\Collection\CollectionInterface::take()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function take(int $length = 1, int $offset = 0): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling take() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->take(...)` instead.'
+ );
+
+ return $this->all()->take($length, $offset);
+ }
+
+ /**
+ * @param int $length The number of items to take.
+ * @see \Cake\Collection\CollectionInterface::takeLast()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function takeLast(int $length): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling takeLast() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->takeLast(...)` instead.'
+ );
+
+ return $this->all()->takeLast($length);
+ }
+
+ /**
+ * @param int $length The number of items to skip
+ * @see \Cake\Collection\CollectionInterface::skip()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function skip(int $length): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling skip() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->skip(...)` instead.'
+ );
+
+ return $this->all()->skip($length);
+ }
+
+ /**
+ * @param array $conditions The conditions to use.
+ * @see \Cake\Collection\CollectionInterface::match()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function match(array $conditions): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling match() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->match(...)` instead.'
+ );
+
+ return $this->all()->match($conditions);
+ }
+
+ /**
+ * @param array $conditions The conditions to apply
+ * @see \Cake\Collection\CollectionInterface::firstMatch()
+ * @return mixed
+ * @deprecated
+ */
+ public function firstMatch(array $conditions)
+ {
+ deprecationWarning(
+ '4.3.0 - Calling firstMatch() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->firstMatch(...)` instead.'
+ );
+
+ return $this->all()->firstMatch($conditions);
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::last()
+ * @deprecated
+ * @return mixed
+ */
+ public function last()
+ {
+ deprecationWarning(
+ '4.3.0 - Calling last() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->last(...)` instead.'
+ );
+
+ return $this->all()->last();
+ }
+
+ /**
+ * @param mixed $items The items to append
+ * @see \Cake\Collection\CollectionInterface::append()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function append($items): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling append() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->append(...)` instead.'
+ );
+
+ return $this->all()->append($items);
+ }
+
+ /**
+ * @param mixed $item The item to apply
+ * @param mixed $key The key to append with
+ * @see \Cake\Collection\CollectionInterface::appendItem()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function appendItem($item, $key = null): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling appendItem() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->appendItem(...)` instead.'
+ );
+
+ return $this->all()->appendItem($item, $key);
+ }
+
+ /**
+ * @param mixed $items The items to prepend.
+ * @see \Cake\Collection\CollectionInterface::prepend()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function prepend($items): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling prepend() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->prepend(...)` instead.'
+ );
+
+ return $this->all()->prepend($items);
+ }
+
+ /**
+ * @param mixed $item The item to prepend
+ * @param mixed $key The key to use.
+ * @see \Cake\Collection\CollectionInterface::prependItem()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function prependItem($item, $key = null): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling prependItem() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->prependItem(...)` instead.'
+ );
+
+ return $this->all()->prependItem($item, $key);
+ }
+
+ /**
+ * @param callable|string $keyPath The path for keys
+ * @param callable|string $valuePath The path for values
+ * @param callable|string|null $groupPath The path for grouping
+ * @see \Cake\Collection\CollectionInterface::combine()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function combine($keyPath, $valuePath, $groupPath = null): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling combine() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->combine(...)` instead.'
+ );
+
+ return $this->all()->combine($keyPath, $valuePath, $groupPath);
+ }
+
+ /**
+ * @param callable|string $idPath The path to ids
+ * @param callable|string $parentPath The path to parents
+ * @param string $nestingKey Key used for nesting children.
+ * @see \Cake\Collection\CollectionInterface::nest()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function nest($idPath, $parentPath, string $nestingKey = 'children'): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling nest() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->nest(...)` instead.'
+ );
+
+ return $this->all()->nest($idPath, $parentPath, $nestingKey);
+ }
+
+ /**
+ * @param string $path The path to insert on
+ * @param mixed $values The values to insert.
+ * @see \Cake\Collection\CollectionInterface::insert()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function insert(string $path, $values): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling insert() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->insert(...)` instead.'
+ );
+
+ return $this->all()->insert($path, $values);
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::toList()
+ * @return array
+ * @deprecated
+ */
+ public function toList(): array
+ {
+ deprecationWarning(
+ '4.3.0 - Calling toList() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->toList(...)` instead.'
+ );
+
+ return $this->all()->toList();
+ }
+
+ /**
+ * @param bool $keepKeys Whether or not keys should be kept
+ * @see \Cake\Collection\CollectionInterface::compile()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function compile(bool $keepKeys = true): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling compile() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->compile(...)` instead.'
+ );
+
+ return $this->all()->compile($keepKeys);
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::lazy()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function lazy(): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling lazy() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->lazy(...)` instead.'
+ );
+
+ return $this->all()->lazy();
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::buffered()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function buffered(): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling buffered() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->buffered(...)` instead.'
+ );
+
+ return $this->all()->buffered();
+ }
+
+ /**
+ * @param string|int $order The order in which to return the elements
+ * @param callable|string $nestingKey The key name under which children are nested
+ * @see \Cake\Collection\CollectionInterface::listNested()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function listNested($order = 'desc', $nestingKey = 'children'): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling listNested() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->listNested(...)` instead.'
+ );
+
+ return $this->all()->listNested($order, $nestingKey);
+ }
+
+ /**
+ * @param callable|array $condition the method that will receive each of the elements and
+ * returns true when the iteration should be stopped.
+ * @see \Cake\Collection\CollectionInterface::stopWhen()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function stopWhen($condition): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling stopWhen() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->stopWhen(...)` instead.'
+ );
+
+ return $this->all()->stopWhen($condition);
+ }
+
+ /**
+ * @param callable|null $callback A callable function that will receive each of
+ * items in the collection.
+ * @see \Cake\Collection\CollectionInterface::unfold()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function unfold(?callable $callback = null): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling unfold() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->unfold(...)` instead.'
+ );
+
+ return $this->all()->unfold($callback);
+ }
+
+ /**
+ * @param callable $callback A callable function that will receive each of
+ * items in the collection.
+ * @see \Cake\Collection\CollectionInterface::through()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function through(callable $callback): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling through() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->through(...)` instead.'
+ );
+
+ return $this->all()->through($callback);
+ }
+
+ /**
+ * @param iterable ...$items The collections to zip.
+ * @see \Cake\Collection\CollectionInterface::zip()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function zip(iterable $items): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling zip() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->zip(...)` instead.'
+ );
+
+ return $this->all()->zip($items);
+ }
+
+ /**
+ * @param iterable ...$items The collections to zip.
+ * @param callable $callback The function to use for zipping the elements together.
+ * @see \Cake\Collection\CollectionInterface::zipWith()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function zipWith(iterable $items, $callback): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling zipWith() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->zipWith(...)` instead.'
+ );
+
+ return $this->all()->zipWith($items, $callback);
+ }
+
+ /**
+ * @param int $chunkSize The maximum size for each chunk
+ * @see \Cake\Collection\CollectionInterface::chunk()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function chunk(int $chunkSize): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling chunk() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->chunk(...)` instead.'
+ );
+
+ return $this->all()->chunk($chunkSize);
+ }
+
+ /**
+ * @param int $chunkSize The maximum size for each chunk
+ * @param bool $keepKeys If the keys of the array should be kept
+ * @see \Cake\Collection\CollectionInterface::chunkWithKeys()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function chunkWithKeys(int $chunkSize, bool $keepKeys = true): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling chunkWithKeys() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->chunkWithKeys(...)` instead.'
+ );
+
+ return $this->all()->chunkWithKeys($chunkSize, $keepKeys);
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::isEmpty()
+ * @return bool
+ * @deprecated
+ */
+ public function isEmpty(): bool
+ {
+ deprecationWarning(
+ '4.3.0 - Calling isEmpty() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->isEmpty(...)` instead.'
+ );
+
+ return $this->all()->isEmpty();
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::unwrap()
+ * @return \Traversable
+ * @deprecated
+ */
+ public function unwrap(): Traversable
+ {
+ deprecationWarning(
+ '4.3.0 - Calling unwrap() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->unwrap(...)` instead.'
+ );
+
+ return $this->all()->unwrap();
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::transpose()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function transpose(): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling transpose() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->transpose(...)` instead.'
+ );
+
+ return $this->all()->transpose();
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::count()
+ * @return int
+ * @deprecated
+ */
+ public function count(): int
+ {
+ deprecationWarning(
+ '4.3.0 - Calling count() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->count(...)` instead.'
+ );
+
+ return $this->all()->count();
+ }
+
+ /**
+ * @see \Cake\Collection\CollectionInterface::countKeys()
+ * @return int
+ * @deprecated
+ */
+ public function countKeys(): int
+ {
+ deprecationWarning(
+ '4.3.0 - Calling countKeys() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->countKeys(...)` instead.'
+ );
+
+ return $this->all()->countKeys();
+ }
+
+ /**
+ * @param callable|null $operation A callable that allows you to customize the product result.
+ * @param callable|null $filter A filtering callback that must return true for a result to be part
+ * of the final results.
+ * @see \Cake\Collection\CollectionInterface::cartesianProduct()
+ * @return \Cake\Collection\CollectionInterface
+ * @deprecated
+ */
+ public function cartesianProduct(?callable $operation = null, ?callable $filter = null): CollectionInterface
+ {
+ deprecationWarning(
+ '4.3.0 - Calling cartesianProduct() on a Query is deprecated. ' .
+ 'Instead call `$query->all()->cartesianProduct(...)` instead.'
+ );
+
+ return $this->all()->cartesianProduct($operation, $filter);
+ }
+
/**
* Populates or adds parts to current query clauses using an array.
* This is handy for passing all query clauses at once.
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php
index e59e63e54..85d98b618 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetDecorator.php
@@ -17,11 +17,15 @@
namespace Cake\Datasource;
use Cake\Collection\Collection;
+use Cake\Core\Configure;
use Countable;
/**
* Generic ResultSet decorator. This will make any traversable object appear to
* be a database result
+ *
+ * @template T of \Cake\Datasource\EntityInterface|array
+ * @implements \Cake\Datasource\ResultSetInterface
*/
class ResultSetDecorator extends Collection implements ResultSetInterface
{
@@ -43,4 +47,15 @@ public function count(): int
return count($this->toArray());
}
+
+ /**
+ * @inheritDoc
+ */
+ public function __debugInfo(): array
+ {
+ $parentInfo = parent::__debugInfo();
+ $limit = Configure::read('App.ResultSetDebugLimit', 10);
+
+ return array_merge($parentInfo, ['items' => $this->take($limit)->toArray()]);
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php
index a62ee77f3..c193fac81 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/ResultSetInterface.php
@@ -22,6 +22,8 @@
/**
* Describes how a collection of datasource results should look like
+ *
+ * @template T
*/
interface ResultSetInterface extends CollectionInterface, Countable, Serializable
{
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php b/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php
index 1bf5c9c37..c523eba5a 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/RulesChecker.php
@@ -112,7 +112,7 @@ class RulesChecker
public function __construct(array $options = [])
{
$this->_options = $options;
- $this->_useI18n = function_exists('__d');
+ $this->_useI18n = function_exists('\Cake\I18n\__d');
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Datasource/SimplePaginator.php b/app/vendor/cakephp/cakephp/src/Datasource/SimplePaginator.php
index 95499fb6d..134b0bd64 100644
--- a/app/vendor/cakephp/cakephp/src/Datasource/SimplePaginator.php
+++ b/app/vendor/cakephp/cakephp/src/Datasource/SimplePaginator.php
@@ -1,7 +1,10 @@
getTrace();
+ }
+ $parentFrames = $parent->getTrace();
+ $frames = $exception->getTrace();
+
+ $parentCount = count($parentFrames) - 1;
+ $frameCount = count($frames) - 1;
+
+ // Reverse loop through both traces removing frames that
+ // are the same.
+ for ($i = $frameCount, $p = $parentCount; $i >= 0 && $p >= 0; $p--) {
+ $parentTail = $parentFrames[$p];
+ $tail = $frames[$i];
+
+ // Frames without file/line are never equal to another frame.
+ $isEqual = (
+ (
+ isset($tail['file']) &&
+ isset($tail['line']) &&
+ isset($parentTail['file']) &&
+ isset($parentTail['line'])
+ ) &&
+ ($tail['file'] === $parentTail['file']) &&
+ ($tail['line'] === $parentTail['line'])
+ );
+ if ($isEqual) {
+ unset($frames[$i]);
+ $i--;
+ }
+ }
+
+ return $frames;
+ }
+
/**
* Outputs a stack trace based on the supplied options.
*
@@ -390,7 +438,11 @@ public static function log($var, $level = 'debug', int $maxDepth = 3): void
*/
public static function trace(array $options = [])
{
- return Debugger::formatTrace(debug_backtrace(), $options);
+ // Remove the frame for Debugger::trace()
+ $backtrace = debug_backtrace();
+ array_shift($backtrace);
+
+ return Debugger::formatTrace($backtrace, $options);
}
/**
@@ -426,60 +478,50 @@ public static function formatTrace($backtrace, array $options = [])
];
$options = Hash::merge($defaults, $options);
- $count = count($backtrace);
+ $count = count($backtrace) + 1;
$back = [];
- $_trace = [
- 'line' => '??',
- 'file' => '[internal]',
- 'class' => null,
- 'function' => '[main]',
- ];
-
for ($i = $options['start']; $i < $count && $i < $options['depth']; $i++) {
- $trace = $backtrace[$i] + ['file' => '[internal]', 'line' => '??'];
- $signature = $reference = '[main]';
-
- if (isset($backtrace[$i + 1])) {
- $next = $backtrace[$i + 1] + $_trace;
- $signature = $reference = $next['function'];
-
- if (!empty($next['class'])) {
- $signature = $next['class'] . '::' . $next['function'];
- $reference = $signature . '(';
- if ($options['args'] && isset($next['args'])) {
- $args = [];
- foreach ($next['args'] as $arg) {
- $args[] = Debugger::exportVar($arg);
- }
- $reference .= implode(', ', $args);
+ $frame = ['file' => '[main]', 'line' => ''];
+ if (isset($backtrace[$i])) {
+ $frame = $backtrace[$i] + ['file' => '[internal]', 'line' => '??'];
+ }
+
+ $signature = $reference = $frame['file'];
+ if (!empty($frame['class'])) {
+ $signature = $frame['class'] . $frame['type'] . $frame['function'];
+ $reference = $signature . '(';
+ if ($options['args'] && isset($frame['args'])) {
+ $args = [];
+ foreach ($frame['args'] as $arg) {
+ $args[] = Debugger::exportVar($arg);
}
- $reference .= ')';
+ $reference .= implode(', ', $args);
}
+ $reference .= ')';
}
if (in_array($signature, $options['exclude'], true)) {
continue;
}
if ($options['format'] === 'points') {
- $back[] = ['file' => $trace['file'], 'line' => $trace['line'], 'reference' => $reference];
+ $back[] = ['file' => $frame['file'], 'line' => $frame['line'], 'reference' => $reference];
} elseif ($options['format'] === 'array') {
if (!$options['args']) {
- unset($trace['args']);
+ unset($frame['args']);
}
- $back[] = $trace;
+ $back[] = $frame;
} else {
- if (isset($self->_templates[$options['format']]['traceLine'])) {
- $tpl = $self->_templates[$options['format']]['traceLine'];
+ $tpl = $self->_templates[$options['format']]['traceLine'] ?? $self->_templates['base']['traceLine'];
+ if ($frame['file'] == '[main]') {
+ $back[] = '[main]';
} else {
- $tpl = $self->_templates['base']['traceLine'];
+ $frame['path'] = static::trimPath($frame['file']);
+ $frame['reference'] = $reference;
+ unset($frame['object'], $frame['args']);
+ $back[] = Text::insert($tpl, $frame, ['before' => '{:', 'after' => '}']);
}
- $trace['path'] = static::trimPath($trace['file']);
- $trace['reference'] = $reference;
- unset($trace['object'], $trace['args']);
- $back[] = Text::insert($tpl, $trace, ['before' => '{:', 'after' => '}']);
}
}
-
if ($options['format'] === 'array' || $options['format'] === 'points') {
return $back;
}
@@ -575,9 +617,6 @@ public static function excerpt(string $file, int $line, int $context = 2): array
*/
protected static function _highlight(string $str): string
{
- if (function_exists('hphp_log') || function_exists('hphp_gettid')) {
- return htmlentities($str);
- }
$added = false;
if (strpos($str, '', '<?php '],
+ ['<?php ', '<?php ', '<?php '],
'',
$highlight
);
@@ -1119,7 +1158,7 @@ public static function printVar($var, array $location = [], ?bool $showHtml = nu
*
* - HTML escape the message.
* - Convert `bool` into `bool`
- * - Convert newlines into ` `
+ * - Convert newlines into ` `
*
* @param string $message The string message to format.
* @return string Formatted message.
diff --git a/app/vendor/cakephp/cakephp/src/Error/ErrorTrap.php b/app/vendor/cakephp/cakephp/src/Error/ErrorTrap.php
index 76fdf1a81..ab2f54d04 100644
--- a/app/vendor/cakephp/cakephp/src/Error/ErrorTrap.php
+++ b/app/vendor/cakephp/cakephp/src/Error/ErrorTrap.php
@@ -10,6 +10,7 @@
use Cake\Event\EventDispatcherTrait;
use Cake\Routing\Router;
use Exception;
+use function Cake\Core\deprecationWarning;
/**
* Entry point to CakePHP's error handling.
@@ -122,6 +123,17 @@ public function handleError(
$trace = Debugger::trace(['start' => 1, 'format' => 'points']);
$error = new PhpError($code, $description, $file, $line, $trace);
+ $ignoredPaths = (array)Configure::read('Error.ignoredDeprecationPaths');
+ if ($code === E_USER_DEPRECATED && $ignoredPaths) {
+ $relativePath = str_replace(DIRECTORY_SEPARATOR, '/', substr((string)$file, strlen(ROOT) + 1));
+ foreach ($ignoredPaths as $pattern) {
+ $pattern = str_replace(DIRECTORY_SEPARATOR, '/', $pattern);
+ if (fnmatch($pattern, $relativePath)) {
+ return true;
+ }
+ }
+ }
+
$debug = Configure::read('debug');
$renderer = $this->renderer();
@@ -132,7 +144,7 @@ public function handleError(
if ($event->isStopped()) {
return true;
}
- $renderer->write($renderer->render($error, $debug));
+ $renderer->write($event->getResult() ?: $renderer->render($error, $debug));
} catch (Exception $e) {
// Fatal errors always log.
$this->logger()->logMessage('error', 'Could not render error. Got: ' . $e->getMessage());
diff --git a/app/vendor/cakephp/cakephp/src/Error/ExceptionTrap.php b/app/vendor/cakephp/cakephp/src/Error/ExceptionTrap.php
index f86155762..249cca920 100644
--- a/app/vendor/cakephp/cakephp/src/Error/ExceptionTrap.php
+++ b/app/vendor/cakephp/cakephp/src/Error/ExceptionTrap.php
@@ -10,6 +10,8 @@
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Throwable;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\env;
/**
* Entry point to CakePHP's exception handling.
@@ -237,8 +239,15 @@ public function handleException(Throwable $exception): void
$this->logException($exception, $request);
try {
- $renderer = $this->renderer($exception);
- $renderer->write($renderer->render());
+ $event = $this->dispatchEvent('Exception.beforeRender', ['exception' => $exception, 'request' => $request]);
+ if ($event->isStopped()) {
+ return;
+ }
+ $exception = $event->getData('exception');
+ assert($exception instanceof Throwable);
+
+ $renderer = $this->renderer($exception, $request);
+ $renderer->write($event->getResult() ?: $renderer->render());
} catch (Throwable $exception) {
$this->logInternalError($exception);
}
@@ -365,7 +374,6 @@ public function logException(Throwable $exception, ?ServerRequestInterface $requ
$this->logger()->log($exception, $request);
}
}
- $this->dispatchEvent('Exception.beforeRender', ['exception' => $exception]);
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php b/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php
index d1e7efae7..b39ecc3f9 100644
--- a/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php
@@ -19,11 +19,15 @@
use Cake\Core\App;
use Cake\Core\Configure;
use Cake\Core\InstanceConfigTrait;
+use Cake\Core\PluginApplicationInterface;
use Cake\Error\ErrorHandler;
use Cake\Error\ExceptionTrap;
use Cake\Error\Renderer\WebExceptionRenderer;
+use Cake\Event\EventDispatcherTrait;
use Cake\Http\Exception\RedirectException;
use Cake\Http\Response;
+use Cake\Routing\Router;
+use Cake\Routing\RoutingApplicationInterface;
use InvalidArgumentException;
use Laminas\Diactoros\Response\RedirectResponse;
use Psr\Http\Message\ResponseInterface;
@@ -31,6 +35,9 @@
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Throwable;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\getTypeName;
+use function Cake\Core\triggerWarning;
/**
* Error handling middleware.
@@ -41,6 +48,7 @@
class ErrorHandlerMiddleware implements MiddlewareInterface
{
use InstanceConfigTrait;
+ use EventDispatcherTrait;
/**
* Default configuration values.
@@ -72,22 +80,32 @@ class ErrorHandlerMiddleware implements MiddlewareInterface
*/
protected $exceptionTrap = null;
+ /**
+ * @var \Cake\Routing\RoutingApplicationInterface|null
+ */
+ protected $app = null;
+
/**
* Constructor
*
* @param \Cake\Error\ErrorHandler|\Cake\Error\ExceptionTrap|array $errorHandler The error handler instance
* or config array.
+ * @param \Cake\Routing\RoutingApplicationInterface|null $app Application instance.
* @throws \InvalidArgumentException
*/
- public function __construct($errorHandler = [])
+ public function __construct($errorHandler = [], $app = null)
{
if (func_num_args() > 1) {
- deprecationWarning(
- 'The signature of ErrorHandlerMiddleware::__construct() has changed. '
- . 'Pass the config array as 1st argument instead.'
- );
+ if (is_array($app)) {
+ deprecationWarning(
+ 'The signature of ErrorHandlerMiddleware::__construct() has changed. '
+ . 'Pass the config array as 1st argument instead.'
+ );
- $errorHandler = func_get_arg(1);
+ $errorHandler = func_get_arg(1);
+ } else {
+ $this->app = $app;
+ }
}
if (PHP_VERSION_ID >= 70400 && Configure::read('debug')) {
@@ -145,11 +163,24 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
*/
public function handleException(Throwable $exception, ServerRequestInterface $request): ResponseInterface
{
+ $this->loadRoutes();
+
+ $response = null;
if ($this->errorHandler === null) {
$handler = $this->getExceptionTrap();
$handler->logException($exception, $request);
+ $event = $this->dispatchEvent(
+ 'Exception.beforeRender',
+ ['exception' => $exception, 'request' => $request],
+ $handler
+ );
+
+ $exception = $event->getData('exception');
+ assert($exception instanceof Throwable);
$renderer = $handler->renderer($exception, $request);
+
+ $response = $event->getResult();
} else {
$handler = $this->getErrorHandler();
$handler->logException($exception, $request);
@@ -158,13 +189,13 @@ public function handleException(Throwable $exception, ServerRequestInterface $re
}
try {
- /** @var \Psr\Http\Message\ResponseInterface|string $response */
- $response = $renderer->render();
- if (is_string($response)) {
- return new Response(['body' => $response, 'status' => 500]);
+ if ($response === null) {
+ $response = $renderer->render();
}
- return $response;
+ return $response instanceof ResponseInterface
+ ? $response
+ : new Response(['body' => $response, 'status' => 500]);
} catch (Throwable $internalException) {
$handler->logException($internalException, $request);
@@ -231,4 +262,34 @@ protected function getExceptionTrap(): ExceptionTrap
return $this->exceptionTrap;
}
+
+ /**
+ * Ensure that the application's routes are loaded.
+ *
+ * @return void
+ */
+ protected function loadRoutes(): void
+ {
+ if (
+ !($this->app instanceof RoutingApplicationInterface)
+ || Router::routes()
+ ) {
+ return;
+ }
+
+ try {
+ $builder = Router::createRouteBuilder('/');
+
+ $this->app->routes($builder);
+ if ($this->app instanceof PluginApplicationInterface) {
+ $this->app->pluginRoutes($builder);
+ }
+ } catch (Throwable $e) {
+ triggerWarning(sprintf(
+ "Exception loading routes when rendering an error page: \n %s - %s",
+ get_class($e),
+ $e->getMessage()
+ ));
+ }
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/Error/PhpError.php b/app/vendor/cakephp/cakephp/src/Error/PhpError.php
index a0a5396fe..0b9944edb 100644
--- a/app/vendor/cakephp/cakephp/src/Error/PhpError.php
+++ b/app/vendor/cakephp/cakephp/src/Error/PhpError.php
@@ -183,7 +183,11 @@ public function getTraceAsString(): string
{
$out = [];
foreach ($this->trace as $frame) {
- $out[] = "{$frame['reference']} {$frame['file']}, line {$frame['line']}";
+ if (!empty($frame['line'])) {
+ $out[] = "{$frame['reference']} {$frame['file']}, line {$frame['line']}";
+ } else {
+ $out[] = $frame['reference'];
+ }
}
return implode("\n", $out);
diff --git a/app/vendor/cakephp/cakephp/src/Error/Renderer/ConsoleExceptionRenderer.php b/app/vendor/cakephp/cakephp/src/Error/Renderer/ConsoleExceptionRenderer.php
index 988dcfa44..cba448219 100644
--- a/app/vendor/cakephp/cakephp/src/Error/Renderer/ConsoleExceptionRenderer.php
+++ b/app/vendor/cakephp/cakephp/src/Error/Renderer/ConsoleExceptionRenderer.php
@@ -19,6 +19,7 @@
use Cake\Console\ConsoleOutput;
use Cake\Core\Configure;
use Cake\Core\Exception\CakeException;
+use Cake\Error\Debugger;
use Psr\Http\Message\ServerRequestInterface;
use Throwable;
@@ -76,7 +77,8 @@ public function render()
}
$out = [];
foreach ($exceptions as $i => $error) {
- $out = array_merge($out, $this->renderException($error, $i));
+ $parent = $exceptions[$i - 1] ?? null;
+ $out = array_merge($out, $this->renderException($error, $parent));
}
return join("\n", $out);
@@ -86,15 +88,15 @@ public function render()
* Render an individual exception
*
* @param \Throwable $exception The exception to render.
- * @param int $index Exception index in the chain
+ * @param ?\Throwable $parent The Exception index in the chain
* @return array
*/
- protected function renderException(Throwable $exception, int $index): array
+ protected function renderException(Throwable $exception, ?Throwable $parent): array
{
$out = [
sprintf(
'%s[%s] %s in %s on line %s',
- $index > 0 ? 'Caused by ' : '',
+ $parent ? 'Caused by ' : '',
get_class($exception),
$exception->getMessage(),
$exception->getFile(),
@@ -114,10 +116,11 @@ protected function renderException(Throwable $exception, int $index): array
}
if ($this->trace) {
+ $stacktrace = Debugger::getUniqueFrames($exception, $parent);
$out[] = '';
$out[] = 'Stack Trace:';
$out[] = '';
- $out[] = $exception->getTraceAsString();
+ $out[] = Debugger::formatTrace($stacktrace, ['format' => 'txt']);
$out[] = '';
}
diff --git a/app/vendor/cakephp/cakephp/src/Error/Renderer/HtmlErrorRenderer.php b/app/vendor/cakephp/cakephp/src/Error/Renderer/HtmlErrorRenderer.php
index 569445e0b..7e49178f5 100644
--- a/app/vendor/cakephp/cakephp/src/Error/Renderer/HtmlErrorRenderer.php
+++ b/app/vendor/cakephp/cakephp/src/Error/Renderer/HtmlErrorRenderer.php
@@ -19,6 +19,7 @@
use Cake\Error\Debugger;
use Cake\Error\ErrorRendererInterface;
use Cake\Error\PhpError;
+use function Cake\Core\h;
/**
* Interactive HTML error rendering with a stack trace.
diff --git a/app/vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php b/app/vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php
index 5c7143c1b..b249f7409 100644
--- a/app/vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php
+++ b/app/vendor/cakephp/cakephp/src/Error/Renderer/WebExceptionRenderer.php
@@ -44,6 +44,9 @@
use PDOException;
use Psr\Http\Message\ResponseInterface;
use Throwable;
+use function Cake\Core\h;
+use function Cake\Core\namespaceSplit;
+use function Cake\I18n\__d;
/**
* Web Exception Renderer.
@@ -167,9 +170,17 @@ protected function _getController(): Controller
$params['controller'] = 'Error';
$factory = new ControllerFactory(new Container());
+ // Check including plugin + prefix
$class = $factory->getControllerClass($request->withAttribute('params', $params));
+ if (!$class && !empty($params['prefix']) && !empty($params['plugin'])) {
+ unset($params['prefix']);
+ // Fallback to only plugin
+ $class = $factory->getControllerClass($request->withAttribute('params', $params));
+ }
+
if (!$class) {
+ // Fallback to app/core provided controller.
/** @var string $class */
$class = App::className('Error', 'Controller', 'Controller');
}
diff --git a/app/vendor/cakephp/cakephp/src/Error/functions.php b/app/vendor/cakephp/cakephp/src/Error/functions.php
new file mode 100644
index 000000000..6a33370a1
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Error/functions.php
@@ -0,0 +1,117 @@
+ 0, 'depth' => 1, 'format' => 'array']);
+ if (isset($trace[0]['line']) && isset($trace[0]['file'])) {
+ $location = [
+ 'line' => $trace[0]['line'],
+ 'file' => $trace[0]['file'],
+ ];
+ }
+ }
+
+ Debugger::printVar($var, $location, $showHtml);
+
+ return $var;
+}
+
+/**
+ * Outputs a stack trace based on the supplied options.
+ *
+ * ### Options
+ *
+ * - `depth` - The number of stack frames to return. Defaults to 999
+ * - `args` - Should arguments for functions be shown? If true, the arguments for each method call
+ * will be displayed.
+ * - `start` - The stack frame to start generating a trace from. Defaults to 1
+ *
+ * @param array $options Format for outputting stack trace
+ * @return void
+ */
+function stackTrace(array $options = []): void
+{
+ if (!Configure::read('debug')) {
+ return;
+ }
+
+ $options += ['start' => 0];
+ $options['start']++;
+
+ /** @var string $trace */
+ $trace = Debugger::trace($options);
+ echo $trace;
+}
+
+/**
+ * Prints out debug information about given variable and dies.
+ *
+ * Only runs if debug mode is enabled.
+ * It will otherwise just continue code execution and ignore this function.
+ *
+ * @param mixed $var Variable to show debug information for.
+ * @param bool|null $showHtml If set to true, the method prints the debug data in a browser-friendly way.
+ * @return void
+ * @link https://book.cakephp.org/4/en/development/debugging.html#basic-debugging
+ */
+function dd($var, $showHtml = null): void
+{
+ if (!Configure::read('debug')) {
+ return;
+ }
+
+ $trace = Debugger::trace(['start' => 0, 'depth' => 2, 'format' => 'array']);
+ /** @psalm-suppress PossiblyInvalidArrayOffset */
+ $location = [
+ 'line' => $trace[0]['line'],
+ 'file' => $trace[0]['file'],
+ ];
+
+ Debugger::printVar($var, $location, $showHtml);
+ die(1);
+}
+
+/**
+ * Include global functions.
+ */
+if (!getenv('CAKE_DISABLE_GLOBAL_FUNCS')) {
+ include 'functions_global.php';
+}
diff --git a/app/vendor/cakephp/cakephp/src/Error/functions_global.php b/app/vendor/cakephp/cakephp/src/Error/functions_global.php
new file mode 100644
index 000000000..1f5ae23d8
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Error/functions_global.php
@@ -0,0 +1,141 @@
+ 0, 'depth' => 1, 'format' => 'array']);
+ if (isset($trace[0]['line']) && isset($trace[0]['file'])) {
+ $location = [
+ 'line' => $trace[0]['line'],
+ 'file' => $trace[0]['file'],
+ ];
+ }
+ }
+
+ Debugger::printVar($var, $location, $showHtml);
+
+ return $var;
+ }
+}
+
+if (!function_exists('stackTrace')) {
+ /**
+ * Outputs a stack trace based on the supplied options.
+ *
+ * ### Options
+ *
+ * - `depth` - The number of stack frames to return. Defaults to 999
+ * - `args` - Should arguments for functions be shown? If true, the arguments for each method call
+ * will be displayed.
+ * - `start` - The stack frame to start generating a trace from. Defaults to 1
+ *
+ * @param array $options Format for outputting stack trace
+ * @return void
+ */
+ function stackTrace(array $options = []): void
+ {
+ if (!Configure::read('debug')) {
+ return;
+ }
+
+ $options += ['start' => 0];
+ $options['start']++;
+
+ /** @var string $trace */
+ $trace = Debugger::trace($options);
+ echo $trace;
+ }
+}
+
+if (!function_exists('dd')) {
+ /**
+ * Prints out debug information about given variable and dies.
+ *
+ * Only runs if debug mode is enabled.
+ * It will otherwise just continue code execution and ignore this function.
+ *
+ * @param mixed $var Variable to show debug information for.
+ * @param bool|null $showHtml If set to true, the method prints the debug data in a browser-friendly way.
+ * @return void
+ * @link https://book.cakephp.org/4/en/development/debugging.html#basic-debugging
+ */
+ function dd($var, $showHtml = null): void
+ {
+ if (!Configure::read('debug')) {
+ return;
+ }
+
+ $trace = Debugger::trace(['start' => 0, 'depth' => 2, 'format' => 'array']);
+ /** @psalm-suppress PossiblyInvalidArrayOffset */
+ $location = [
+ 'line' => $trace[0]['line'],
+ 'file' => $trace[0]['file'],
+ ];
+
+ Debugger::printVar($var, $location, $showHtml);
+ die(1);
+ }
+}
+
+if (!function_exists('breakpoint')) {
+ /**
+ * Command to return the eval-able code to startup PsySH in interactive debugger
+ * Works the same way as eval(\Psy\sh());
+ * psy/psysh must be loaded in your project
+ *
+ * ```
+ * eval(breakpoint());
+ * ```
+ *
+ * @return string|null
+ * @link https://psysh.org/
+ */
+ function breakpoint(): ?string
+ {
+ if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && class_exists(PsyShell::class)) {
+ return 'extract(\Psy\Shell::debug(get_defined_vars(), isset($this) ? $this : null));';
+ }
+ trigger_error(
+ 'psy/psysh must be installed and you must be in a CLI environment to use the breakpoint function',
+ E_USER_WARNING
+ );
+
+ return null;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Event/EventList.php b/app/vendor/cakephp/cakephp/src/Event/EventList.php
index e8cc40c93..00be78cd2 100644
--- a/app/vendor/cakephp/cakephp/src/Event/EventList.php
+++ b/app/vendor/cakephp/cakephp/src/Event/EventList.php
@@ -21,6 +21,8 @@
/**
* The Event List
+ *
+ * @template-implements \ArrayAccess
*/
class EventList implements ArrayAccess, Countable
{
@@ -69,7 +71,7 @@ public function offsetExists($offset): bool
*
* @link https://secure.php.net/manual/en/arrayaccess.offsetget.php
* @param mixed $offset The offset to retrieve.
- * @return mixed Can return all value types.
+ * @return \Cake\Event\EventInterface|null
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
diff --git a/app/vendor/cakephp/cakephp/src/Form/Form.php b/app/vendor/cakephp/cakephp/src/Form/Form.php
index 9e8122359..29f8b198b 100644
--- a/app/vendor/cakephp/cakephp/src/Form/Form.php
+++ b/app/vendor/cakephp/cakephp/src/Form/Form.php
@@ -23,6 +23,7 @@
use Cake\Utility\Hash;
use Cake\Validation\ValidatorAwareInterface;
use Cake\Validation\ValidatorAwareTrait;
+use function Cake\Core\deprecationWarning;
/**
* Form abstraction used to create forms not tied to ORM backed models,
@@ -234,6 +235,17 @@ public function getErrors(): array
return $this->_errors;
}
+ /**
+ * Returns validation errors for the given field
+ *
+ * @param string $field Field name to get the errors from.
+ * @return array The validation errors for the given field.
+ */
+ public function getError(string $field): array
+ {
+ return $this->_errors[$field] ?? [];
+ }
+
/**
* Set the errors in the form.
*
diff --git a/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php b/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php
index a8c381db3..3f2dbaf84 100644
--- a/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php
+++ b/app/vendor/cakephp/cakephp/src/Http/BaseApplication.php
@@ -18,6 +18,7 @@
namespace Cake\Http;
use Cake\Console\CommandCollection;
+use Cake\Controller\ComponentRegistry;
use Cake\Controller\ControllerFactory;
use Cake\Core\ConsoleApplicationInterface;
use Cake\Core\Container;
@@ -306,6 +307,7 @@ public function handle(
): ResponseInterface {
$container = $this->getContainer();
$container->add(ServerRequest::class, $request);
+ $container->add(ContainerInterface::class, $container);
if ($this->controllerFactory === null) {
$this->controllerFactory = new ControllerFactory($container);
@@ -317,6 +319,9 @@ public function handle(
$controller = $this->controllerFactory->create($request);
+ // This is needed for auto-wiring. Should be removed in 5.x
+ $container->add(ComponentRegistry::class, $controller->components());
+
return $this->controllerFactory->invoke($controller);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php b/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php
index 4ceed68e4..8289c19df 100644
--- a/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php
+++ b/app/vendor/cakephp/cakephp/src/Http/CallbackStream.php
@@ -40,7 +40,6 @@ public function getContents(): string
{
$callback = $this->detach();
$result = '';
- /** @psalm-suppress TypeDoesNotContainType */
if ($callback !== null) {
$result = $callback();
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Mock.php b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Mock.php
index 15ee3bf21..4ec86236d 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Mock.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Mock.php
@@ -21,6 +21,7 @@
use Closure;
use InvalidArgumentException;
use Psr\Http\Message\RequestInterface;
+use function Cake\Core\getTypeName;
/**
* Implements sending requests to an array of stubbed responses
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php
index d77fb0a6d..fcddd89d0 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Adapter/Stream.php
@@ -314,7 +314,6 @@ protected function _open(string $url, RequestInterface $request): void
return true;
});
try {
- /** @psalm-suppress PossiblyNullArgument */
$this->_stream = fopen($url, 'rb', false, $this->_context);
} finally {
restore_error_handler();
diff --git a/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php b/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php
index 577b1b78f..41e8903c3 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Client/Auth/Digest.php
@@ -17,6 +17,8 @@
use Cake\Http\Client;
use Cake\Http\Client\Request;
+use Cake\Http\HeaderUtility;
+use Cake\Utility\Hash;
/**
* Digest authentication adapter for Cake\Http\Client
@@ -26,6 +28,33 @@
*/
class Digest
{
+ /**
+ * Algorithms
+ */
+ public const ALGO_MD5 = 'MD5';
+ public const ALGO_SHA_256 = 'SHA-256';
+ public const ALGO_SHA_512_256 = 'SHA-512-256';
+ public const ALGO_MD5_SESS = 'MD5-sess';
+ public const ALGO_SHA_256_SESS = 'SHA-256-sess';
+ public const ALGO_SHA_512_256_SESS = 'SHA-512-256-sess';
+
+ /**
+ * QOP
+ */
+ public const QOP_AUTH = 'auth';
+ public const QOP_AUTH_INT = 'auth-int';
+
+ /**
+ * Algorithms <-> Hash type
+ */
+ public const HASH_ALGORITHMS = [
+ self::ALGO_MD5 => 'md5',
+ self::ALGO_SHA_256 => 'sha256',
+ self::ALGO_SHA_512_256 => 'sha512/256',
+ self::ALGO_MD5_SESS => 'md5',
+ self::ALGO_SHA_256_SESS => 'sha256',
+ self::ALGO_SHA_512_256_SESS => 'sha512/256',
+ ];
/**
* Instance of Cake\Http\Client
*
@@ -33,6 +62,27 @@ class Digest
*/
protected $_client;
+ /**
+ * Algorithm
+ *
+ * @var string
+ */
+ protected $algorithm;
+
+ /**
+ * Hash type
+ *
+ * @var string
+ */
+ protected $hashType;
+
+ /**
+ * Is Sess algorithm
+ *
+ * @var bool
+ */
+ protected $isSessAlgorithm;
+
/**
* Constructor
*
@@ -44,6 +94,24 @@ public function __construct(Client $client, ?array $options = null)
$this->_client = $client;
}
+ /**
+ * Set algorithm based on credentials
+ *
+ * @param array $credentials authentication params
+ * @return void
+ */
+ protected function setAlgorithm(array $credentials): void
+ {
+ $algorithm = $credentials['algorithm'] ?? self::ALGO_MD5;
+ if (!isset(self::HASH_ALGORITHMS[$algorithm])) {
+ throw new \InvalidArgumentException('Invalid Algorithm. Valid ones are: ' .
+ implode(',', array_keys(self::HASH_ALGORITHMS)));
+ }
+ $this->algorithm = $algorithm;
+ $this->isSessAlgorithm = strpos($this->algorithm, '-sess') !== false;
+ $this->hashType = Hash::get(self::HASH_ALGORITHMS, $this->algorithm);
+ }
+
/**
* Add Authorization header to the request.
*
@@ -63,6 +131,8 @@ public function authentication(Request $request, array $credentials): Request
if (!isset($credentials['realm'])) {
return $request;
}
+
+ $this->setAlgorithm($credentials);
$value = $this->_generateHeader($request, $credentials);
return $request->withHeader('Authorization', $value);
@@ -87,25 +157,28 @@ protected function _getServerInfo(Request $request, array $credentials): array
['auth' => ['type' => null]]
);
- if (!$response->getHeader('WWW-Authenticate')) {
+ $header = $response->getHeader('WWW-Authenticate');
+ if (!$header) {
return [];
}
- preg_match_all(
- '@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@',
- $response->getHeaderLine('WWW-Authenticate'),
- $matches,
- PREG_SET_ORDER
- );
- foreach ($matches as $match) {
- $credentials[$match[1]] = $match[2];
- }
- if (!empty($credentials['qop']) && empty($credentials['nc'])) {
+ $matches = HeaderUtility::parseWwwAuthenticate($header[0]);
+ $credentials = array_merge($credentials, $matches);
+
+ if (($this->isSessAlgorithm || !empty($credentials['qop'])) && empty($credentials['nc'])) {
$credentials['nc'] = 1;
}
return $credentials;
}
+ /**
+ * @return string
+ */
+ protected function generateCnonce(): string
+ {
+ return uniqid();
+ }
+
/**
* Generate the header Authorization
*
@@ -115,18 +188,39 @@ protected function _getServerInfo(Request $request, array $credentials): array
*/
protected function _generateHeader(Request $request, array $credentials): string
{
- $path = $request->getUri()->getPath();
- $a1 = md5($credentials['username'] . ':' . $credentials['realm'] . ':' . $credentials['password']);
- $a2 = md5($request->getMethod() . ':' . $path);
- $nc = '';
+ $path = $request->getRequestTarget();
+
+ if ($this->isSessAlgorithm) {
+ $credentials['cnonce'] = $this->generateCnonce();
+ $a1 = hash($this->hashType, $credentials['username'] . ':' .
+ $credentials['realm'] . ':' . $credentials['password']) . ':' .
+ $credentials['nonce'] . ':' . $credentials['cnonce'];
+ } else {
+ $a1 = $credentials['username'] . ':' . $credentials['realm'] . ':' . $credentials['password'];
+ }
+ $ha1 = hash($this->hashType, $a1);
+ $a2 = $request->getMethod() . ':' . $path;
+ $nc = sprintf('%08x', $credentials['nc'] ?? 1);
if (empty($credentials['qop'])) {
- $response = md5($a1 . ':' . $credentials['nonce'] . ':' . $a2);
+ $ha2 = hash($this->hashType, $a2);
+ $response = hash($this->hashType, $ha1 . ':' . $credentials['nonce'] . ':' . $ha2);
} else {
- $credentials['cnonce'] = uniqid();
- $nc = sprintf('%08x', $credentials['nc']++);
- $response = md5(
- $a1 . ':' . $credentials['nonce'] . ':' . $nc . ':' . $credentials['cnonce'] . ':auth:' . $a2
+ if (!in_array($credentials['qop'], [self::QOP_AUTH, self::QOP_AUTH_INT])) {
+ throw new \InvalidArgumentException('Invalid QOP parameter. Valid types are: ' .
+ implode(',', [self::QOP_AUTH, self::QOP_AUTH_INT]));
+ }
+ if ($credentials['qop'] === self::QOP_AUTH_INT) {
+ $a2 = $request->getMethod() . ':' . $path . ':' . hash($this->hashType, (string)$request->getBody());
+ }
+ if (empty($credentials['cnonce'])) {
+ $credentials['cnonce'] = $this->generateCnonce();
+ }
+ $ha2 = hash($this->hashType, $a2);
+ $response = hash(
+ $this->hashType,
+ $ha1 . ':' . $credentials['nonce'] . ':' . $nc . ':' .
+ $credentials['cnonce'] . ':' . $credentials['qop'] . ':' . $ha2
);
}
@@ -135,13 +229,19 @@ protected function _generateHeader(Request $request, array $credentials): string
$authHeader .= 'realm="' . $credentials['realm'] . '", ';
$authHeader .= 'nonce="' . $credentials['nonce'] . '", ';
$authHeader .= 'uri="' . $path . '", ';
- $authHeader .= 'response="' . $response . '"';
+ $authHeader .= 'algorithm="' . $this->algorithm . '"';
+
+ if (!empty($credentials['qop'])) {
+ $authHeader .= ', qop=' . $credentials['qop'];
+ }
+ if ($this->isSessAlgorithm || !empty($credentials['qop'])) {
+ $authHeader .= ', nc=' . $nc . ', cnonce="' . $credentials['cnonce'] . '"';
+ }
+ $authHeader .= ', response="' . $response . '"';
+
if (!empty($credentials['opaque'])) {
$authHeader .= ', opaque="' . $credentials['opaque'] . '"';
}
- if (!empty($credentials['qop'])) {
- $authHeader .= ', qop="auth", nc=' . $nc . ', cnonce="' . $credentials['cnonce'] . '"';
- }
return $authHeader;
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/ContentTypeNegotiation.php b/app/vendor/cakephp/cakephp/src/Http/ContentTypeNegotiation.php
index e02e78b0d..9db0c5530 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ContentTypeNegotiation.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ContentTypeNegotiation.php
@@ -51,37 +51,7 @@ public function parseAcceptLanguage(RequestInterface $request): array
*/
protected function parseQualifiers(string $header): array
{
- $accept = [];
- if (!$header) {
- return $accept;
- }
- $headers = explode(',', $header);
- foreach (array_filter($headers) as $value) {
- $prefValue = '1.0';
- $value = trim($value);
-
- $semiPos = strpos($value, ';');
- if ($semiPos !== false) {
- $params = explode(';', $value);
- $value = trim($params[0]);
- foreach ($params as $param) {
- $qPos = strpos($param, 'q=');
- if ($qPos !== false) {
- $prefValue = substr($param, $qPos + 2);
- }
- }
- }
-
- if (!isset($accept[$prefValue])) {
- $accept[$prefValue] = [];
- }
- if ($prefValue) {
- $accept[$prefValue][] = $value;
- }
- }
- krsort($accept);
-
- return $accept;
+ return HeaderUtility::parseAccept($header);
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php b/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php
index 4e01026b8..d5af2a37e 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ControllerFactory.php
@@ -1,10 +1,10 @@
urldecode($name),
'value' => urldecode($value),
diff --git a/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php b/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php
index a028433f3..966b57e9e 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Cookie/CookieCollection.php
@@ -27,12 +27,16 @@
use Psr\Http\Message\ServerRequestInterface;
use Traversable;
use TypeError;
+use function Cake\Core\getTypeName;
+use function Cake\Core\triggerWarning;
/**
* Cookie Collection
*
* Provides an immutable collection of cookies objects. Adding or removing
* to a collection returns a *new* collection that you must retain.
+ *
+ * @template-implements \IteratorAggregate
*/
class CookieCollection implements IteratorAggregate, Countable
{
diff --git a/app/vendor/cakephp/cakephp/src/Http/Exception/RedirectException.php b/app/vendor/cakephp/cakephp/src/Http/Exception/RedirectException.php
index 5d6b1065f..ee74d3d59 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Exception/RedirectException.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Exception/RedirectException.php
@@ -16,6 +16,8 @@
*/
namespace Cake\Http\Exception;
+use function Cake\Core\deprecationWarning;
+
/**
* An exception subclass used by routing and application code to
* trigger a redirect.
diff --git a/app/vendor/cakephp/cakephp/src/Http/FlashMessage.php b/app/vendor/cakephp/cakephp/src/Http/FlashMessage.php
index 2df3b396e..529f602e0 100644
--- a/app/vendor/cakephp/cakephp/src/Http/FlashMessage.php
+++ b/app/vendor/cakephp/cakephp/src/Http/FlashMessage.php
@@ -18,6 +18,7 @@
use Cake\Core\InstanceConfigTrait;
use Throwable;
+use function Cake\Core\pluginSplit;
/**
* The FlashMessage class provides a way for you to write a flash variable
diff --git a/app/vendor/cakephp/cakephp/src/Http/HeaderUtility.php b/app/vendor/cakephp/cakephp/src/Http/HeaderUtility.php
new file mode 100644
index 000000000..3242179c1
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Http/HeaderUtility.php
@@ -0,0 +1,125 @@
+
+ */
+ protected static function parseLinkItem(string $value): array
+ {
+ preg_match('/<(.*)>[; ]?[; ]?(.*)?/i', $value, $matches);
+
+ $url = $matches[1];
+ $parsedParams = ['link' => $url];
+
+ $params = $matches[2];
+ if ($params) {
+ $explodedParams = explode(';', $params);
+ foreach ($explodedParams as $param) {
+ $explodedParam = explode('=', $param);
+ $trimedKey = trim($explodedParam[0]);
+ $trimedValue = trim($explodedParam[1], '"');
+ if ($trimedKey === 'title*') {
+ // See https://www.rfc-editor.org/rfc/rfc8187#section-3.2.3
+ preg_match('/(.*)\'(.*)\'(.*)/i', $trimedValue, $matches);
+ $trimedValue = [
+ 'language' => $matches[2],
+ 'encoding' => $matches[1],
+ 'value' => urldecode($matches[3]),
+ ];
+ }
+ $parsedParams[$trimedKey] = $trimedValue;
+ }
+ }
+
+ return $parsedParams;
+ }
+
+ /**
+ * Parse the Accept header value into weight => value mapping.
+ *
+ * @param string $header The header value to parse
+ * @return array>
+ */
+ public static function parseAccept(string $header): array
+ {
+ $accept = [];
+ if (!$header) {
+ return $accept;
+ }
+
+ $headers = explode(',', $header);
+ foreach (array_filter($headers) as $value) {
+ $prefValue = '1.0';
+ $value = trim($value);
+
+ $semiPos = strpos($value, ';');
+ if ($semiPos !== false) {
+ $params = explode(';', $value);
+ $value = trim($params[0]);
+ foreach ($params as $param) {
+ $qPos = strpos($param, 'q=');
+ if ($qPos !== false) {
+ $prefValue = substr($param, $qPos + 2);
+ }
+ }
+ }
+
+ if (!isset($accept[$prefValue])) {
+ $accept[$prefValue] = [];
+ }
+ if ($prefValue) {
+ $accept[$prefValue][] = $value;
+ }
+ }
+ krsort($accept);
+
+ return $accept;
+ }
+
+ /**
+ * @param string $value The WWW-Authenticate header
+ * @return array
+ */
+ public static function parseWwwAuthenticate(string $value): array
+ {
+ preg_match_all(
+ '@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@',
+ $value,
+ $matches,
+ PREG_SET_ORDER
+ );
+
+ $return = [];
+ foreach ($matches as $match) {
+ $return[$match[1]] = $match[3] ?? $match[2];
+ }
+
+ return $return;
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php
index a350b24f4..a10d7b53e 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php
@@ -29,6 +29,8 @@
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
+use function Cake\I18n\__d;
/**
* Provides CSRF protection & validation.
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/DoublePassDecoratorMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/DoublePassDecoratorMiddleware.php
index 7bf83d67b..96eec01cb 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/DoublePassDecoratorMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/DoublePassDecoratorMiddleware.php
@@ -21,6 +21,7 @@
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
+use function Cake\Core\deprecationWarning;
/**
* Decorate double-pass middleware as PSR-15 middleware.
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/HttpsEnforcerMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/HttpsEnforcerMiddleware.php
index 709cc6f10..81458e858 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/HttpsEnforcerMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/HttpsEnforcerMiddleware.php
@@ -18,6 +18,7 @@
use Cake\Core\Configure;
use Cake\Http\Exception\BadRequestException;
+use Cake\Http\ServerRequest;
use Laminas\Diactoros\Response\RedirectResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
@@ -39,6 +40,7 @@ class HttpsEnforcerMiddleware implements MiddlewareInterface
* - `statusCode` - Status code to use in case of redirect, defaults to 301 - Permanent redirect.
* - `headers` - Array of response headers in case of redirect.
* - `disableOnDebug` - Whether HTTPS check should be disabled when debug is on. Default `true`.
+ * - `trustedProxies` - Array of trusted proxies that will be passed to the request. Defaults to `null`.
* - 'hsts' - Strict-Transport-Security header for HTTPS response configuration. Defaults to `null`.
* If enabled, an array of config options:
*
@@ -53,6 +55,7 @@ class HttpsEnforcerMiddleware implements MiddlewareInterface
'statusCode' => 301,
'headers' => [],
'disableOnDebug' => true,
+ 'trustedProxies' => null,
'hsts' => null,
];
@@ -80,6 +83,10 @@ public function __construct(array $config = [])
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
+ if ($request instanceof ServerRequest && is_array($this->config['trustedProxies'])) {
+ $request->setTrustedProxies($this->config['trustedProxies']);
+ }
+
if (
$request->getUri()->getScheme() === 'https'
|| ($this->config['disableOnDebug']
diff --git a/app/vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php b/app/vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php
index abba6cd1a..82b2279e7 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Middleware/SessionCsrfProtectionMiddleware.php
@@ -18,6 +18,7 @@
use ArrayAccess;
use Cake\Http\Exception\InvalidCsrfTokenException;
+use Cake\Http\ServerRequest;
use Cake\Http\Session;
use Cake\Utility\Hash;
use Cake\Utility\Security;
@@ -26,6 +27,7 @@
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;
+use function Cake\I18n\__d;
/**
* Provides CSRF protection via session based tokens.
@@ -267,4 +269,24 @@ protected function validateToken(ServerRequestInterface $request, Session $sessi
'CSRF token from either the request body or request headers did not match or is missing.'
));
}
+
+ /**
+ * Replace the token in the provided request.
+ *
+ * Replace the token in the session and request attribute. Replacing
+ * tokens is a good idea during privilege escalation or privilege reduction.
+ *
+ * @param \Cake\Http\ServerRequest $request The request to update
+ * @param string $key The session key/attribute to set.
+ * @return \Cake\Http\ServerRequest An updated request.
+ */
+ public static function replaceToken(ServerRequest $request, string $key = 'csrfToken'): ServerRequest
+ {
+ $middleware = new SessionCsrfProtectionMiddleware(['key' => $key]);
+
+ $token = $middleware->createToken();
+ $request->getSession()->write($key, $token);
+
+ return $request->withAttribute($key, $middleware->saltToken($token));
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php b/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php
index 1069117c0..6079d8cda 100644
--- a/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php
+++ b/app/vendor/cakephp/cakephp/src/Http/MiddlewareQueue.php
@@ -17,6 +17,7 @@
namespace Cake\Http;
use Cake\Core\App;
+use Cake\Core\ContainerInterface;
use Cake\Http\Middleware\ClosureDecoratorMiddleware;
use Cake\Http\Middleware\DoublePassDecoratorMiddleware;
use Closure;
@@ -50,13 +51,20 @@ class MiddlewareQueue implements Countable, SeekableIterator
*/
protected $queue = [];
+ /**
+ * @var \Cake\Core\ContainerInterface|null
+ */
+ protected $container;
+
/**
* Constructor
*
* @param array $middleware The list of middleware to append.
+ * @param \Cake\Core\ContainerInterface $container Container instance.
*/
- public function __construct(array $middleware = [])
+ public function __construct(array $middleware = [], ?ContainerInterface $container = null)
{
+ $this->container = $container;
$this->queue = $middleware;
}
@@ -70,14 +78,20 @@ public function __construct(array $middleware = [])
protected function resolve($middleware): MiddlewareInterface
{
if (is_string($middleware)) {
- $className = App::className($middleware, 'Middleware', 'Middleware');
- if ($className === null) {
- throw new RuntimeException(sprintf(
- 'Middleware "%s" was not found.',
- $middleware
- ));
+ if ($this->container && $this->container->has($middleware)) {
+ $middleware = $this->container->get($middleware);
+ } else {
+ $className = App::className($middleware, 'Middleware', 'Middleware');
+ if ($className === null) {
+ throw new RuntimeException(
+ sprintf(
+ 'Middleware "%s" was not found.',
+ $middleware
+ )
+ );
+ }
+ $middleware = new $className();
}
- $middleware = new $className();
}
if ($middleware instanceof MiddlewareInterface) {
diff --git a/app/vendor/cakephp/cakephp/src/Http/Response.php b/app/vendor/cakephp/cakephp/src/Http/Response.php
index 3feb4b4b1..d8833deaa 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Response.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Response.php
@@ -29,6 +29,9 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use SplFileInfo;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\env;
+use function Cake\I18n\__d;
/**
* Responses contain the response text, status and headers of a HTTP response.
@@ -1387,9 +1390,9 @@ public function withCookieCollection(CookieCollection $cookieCollection)
public function cors(ServerRequest $request): CorsBuilder
{
$origin = $request->getHeaderLine('Origin');
- $ssl = $request->is('ssl');
+ $https = $request->is('https');
- return new CorsBuilder($this, $origin, $ssl);
+ return new CorsBuilder($this, $origin, $https);
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php b/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php
index 2dac3d4ca..0cbb23c6f 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ResponseEmitter.php
@@ -232,7 +232,6 @@ protected function setCookie($cookie): bool
}
if (PHP_VERSION_ID >= 70300) {
- /** @psalm-suppress InvalidArgument */
return setcookie($cookie->getName(), $cookie->getScalarValue(), $cookie->getOptions());
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/Server.php b/app/vendor/cakephp/cakephp/src/Http/Server.php
index fe90d51f0..ea9cf5973 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Server.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Server.php
@@ -16,6 +16,7 @@
*/
namespace Cake\Http;
+use Cake\Core\ContainerApplicationInterface;
use Cake\Core\HttpApplicationInterface;
use Cake\Core\PluginApplicationInterface;
use Cake\Event\EventDispatcherInterface;
@@ -80,7 +81,15 @@ public function run(
$request = $request ?: ServerRequestFactory::fromGlobals();
- $middleware = $this->app->middleware($middlewareQueue ?? new MiddlewareQueue());
+ if ($middlewareQueue === null) {
+ if ($this->app instanceof ContainerApplicationInterface) {
+ $middlewareQueue = new MiddlewareQueue([], $this->app->getContainer());
+ } else {
+ $middlewareQueue = new MiddlewareQueue();
+ }
+ }
+
+ $middleware = $this->app->middleware($middlewareQueue);
if ($this->app instanceof PluginApplicationInterface) {
$middleware = $this->app->pluginMiddleware($middleware);
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php b/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php
index eaf661177..cd63b5375 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ServerRequest.php
@@ -30,6 +30,8 @@
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UploadedFileInterface;
use Psr\Http\Message\UriInterface;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\env;
/**
* A class that helps wrap Request information and particulars about a single request.
@@ -127,6 +129,7 @@ class ServerRequest implements ServerRequestInterface
'head' => ['env' => 'REQUEST_METHOD', 'value' => 'HEAD'],
'options' => ['env' => 'REQUEST_METHOD', 'value' => 'OPTIONS'],
'ssl' => ['env' => 'HTTPS', 'options' => [1, 'on']],
+ 'https' => ['env' => 'HTTPS', 'options' => [1, 'on']],
'ajax' => ['env' => 'HTTP_X_REQUESTED_WITH', 'value' => 'XMLHttpRequest'],
'json' => ['accept' => ['application/json'], 'param' => '_ext', 'value' => 'json'],
'xml' => [
@@ -485,6 +488,7 @@ public function __call(string $name, array $params)
* this method will return true if the request matches any type.
* @param mixed ...$args List of arguments
* @return bool Whether the request is the type you are checking.
+ * @throws \InvalidArgumentException If no detector has been set for the provided type.
*/
public function is($type, ...$args): bool
{
@@ -500,7 +504,7 @@ public function is($type, ...$args): bool
$type = strtolower($type);
if (!isset(static::$_detectors[$type])) {
- return false;
+ throw new InvalidArgumentException("No detector set for type `{$type}`");
}
if ($args) {
return $this->_is($type, $args);
@@ -528,6 +532,9 @@ public function clearDetectorCache(): void
*/
protected function _is(string $type, array $args): bool
{
+ if ($type === 'ssl') {
+ deprecationWarning('The `ssl` detector is deprecated. Use `https` instead.');
+ }
$detect = static::$_detectors[$type];
if (is_callable($detect)) {
array_unshift($args, $this);
@@ -1792,7 +1799,6 @@ public function withUri(UriInterface $uri, $preserveHost = false)
* request-target forms allowed in request messages)
* @param string $requestTarget The request target.
* @return static
- * @psalm-suppress MoreSpecificImplementedParamType
*/
public function withRequestTarget($requestTarget)
{
diff --git a/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php b/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php
index fe6e4f9f4..836c3c5b0 100644
--- a/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php
+++ b/app/vendor/cakephp/cakephp/src/Http/ServerRequestFactory.php
@@ -71,7 +71,6 @@ public static function fromGlobals(
$uri->getUri();
}
- /** @psalm-suppress NoInterfaceProperties */
$sessionConfig = (array)Configure::read('Session') + [
'defaults' => 'php',
'cookiePath' => $webroot,
@@ -248,14 +247,7 @@ protected static function marshalUriFromSapi(array $server, array $headers): Uri
$uri = marshalUriFromSapi($server, $headers);
[$base, $webroot] = static::getBase($uri, $server);
- // Look in PATH_INFO first, as this is the exact value we need prepared
- // by PHP.
- $pathInfo = Hash::get($server, 'PATH_INFO');
- if ($pathInfo) {
- $uri = $uri->withPath($pathInfo);
- } else {
- $uri = static::updatePath($base, $uri);
- }
+ $uri = static::updatePath($base, $uri);
if (!$uri->getHost()) {
$uri = $uri->withHost('localhost');
@@ -283,12 +275,18 @@ protected static function updatePath(string $base, UriInterface $uri): UriInterf
if (empty($path) || $path === '/' || $path === '//' || $path === '/index.php') {
$path = '/';
}
- $endsWithIndex = '/' . (Configure::read('App.webroot') ?: 'webroot') . '/index.php';
- $endsWithLength = strlen($endsWithIndex);
- if (
- strlen($path) >= $endsWithLength &&
- substr($path, -$endsWithLength) === $endsWithIndex
- ) {
+ // Check for $webroot/index.php at the start and end of the path.
+ $search = '';
+ if ($path[0] === '/') {
+ $search .= '/';
+ }
+ $search .= (Configure::read('App.webroot') ?: 'webroot') . '/index.php';
+ if (strpos($path, $search) === 0) {
+ $path = substr($path, strlen($search));
+ } elseif (substr($path, -strlen($search)) === $search) {
+ $path = '/';
+ }
+ if (!$path) {
$path = '/';
}
@@ -322,9 +320,9 @@ protected static function getBase(UriInterface $uri, array $server): array
// Clean up additional / which cause following code to fail..
$base = preg_replace('#/+#', '/', $base);
- $indexPos = strpos($base, '/' . $webroot . '/index.php');
+ $indexPos = strpos($base, '/index.php');
if ($indexPos !== false) {
- $base = substr($base, 0, $indexPos) . '/' . $webroot;
+ $base = substr($base, 0, $indexPos);
}
if ($webroot === basename($base)) {
$base = dirname($base);
diff --git a/app/vendor/cakephp/cakephp/src/Http/Session.php b/app/vendor/cakephp/cakephp/src/Http/Session.php
index d9a88e35e..c3cf9ae07 100644
--- a/app/vendor/cakephp/cakephp/src/Http/Session.php
+++ b/app/vendor/cakephp/cakephp/src/Http/Session.php
@@ -23,6 +23,7 @@
use InvalidArgumentException;
use RuntimeException;
use SessionHandlerInterface;
+use function Cake\Core\env;
/**
* This class is a wrapper for the native PHP session functions. It provides
@@ -526,7 +527,6 @@ public function write($name, $value = null): void
$data = Hash::insert($data, $key, $val);
}
- /** @psalm-suppress PossiblyNullArgument */
$this->_overwrite($_SESSION, $data);
}
diff --git a/app/vendor/cakephp/cakephp/src/Http/TestSuite/HttpClientTrait.php b/app/vendor/cakephp/cakephp/src/Http/TestSuite/HttpClientTrait.php
index 0c5f75b15..d4281d2d0 100644
--- a/app/vendor/cakephp/cakephp/src/Http/TestSuite/HttpClientTrait.php
+++ b/app/vendor/cakephp/cakephp/src/Http/TestSuite/HttpClientTrait.php
@@ -115,3 +115,10 @@ public function mockClientDelete(string $url, Response $response, array $options
Client::addMockResponse('DELETE', $url, $response, $options);
}
}
+
+// phpcs:disable
+class_alias(
+ 'Cake\Http\TestSuite\HttpClientTrait',
+ 'Cake\TestSuite\HttpClientTrait'
+);
+// phpcs:enable
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Date.php b/app/vendor/cakephp/cakephp/src/I18n/Date.php
index 3dcc47eb2..9678bfdeb 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Date.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Date.php
@@ -18,6 +18,7 @@
use Cake\Chronos\MutableDate;
use IntlDateFormatter;
+use function Cake\Core\deprecationWarning;
/**
* Extends the Date class provided by Chronos.
diff --git a/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php b/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php
index 942ce1a30..dca02329c 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/DateFormatTrait.php
@@ -262,7 +262,7 @@ protected function _formatObject($date, $format, ?string $locale): string
static::$_formatters[$key] = $formatter;
}
- return static::$_formatters[$key]->format($date->format('U'));
+ return static::$_formatters[$key]->format($date);
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/I18n/FrozenDate.php b/app/vendor/cakephp/cakephp/src/I18n/FrozenDate.php
index 4596bb0ea..84d11f1cd 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/FrozenDate.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/FrozenDate.php
@@ -16,7 +16,7 @@
*/
namespace Cake\I18n;
-use Cake\Chronos\Date as ChronosDate;
+use Cake\Chronos\ChronosDate;
use IntlDateFormatter;
/**
diff --git a/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php b/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php
index e3993d9f5..d47e86923 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/MessagesFileLoader.php
@@ -21,6 +21,7 @@
use Cake\Utility\Inflector;
use Locale;
use RuntimeException;
+use function Cake\Core\pluginSplit;
/**
* A generic translations package factory that will load translations files
@@ -37,6 +38,13 @@ class MessagesFileLoader
*/
protected $_name;
+ /**
+ * The package (domain) plugin
+ *
+ * @var string|null
+ */
+ protected $_plugin;
+
/**
* The locale to load for the given package.
*
@@ -93,6 +101,13 @@ class MessagesFileLoader
public function __construct(string $name, string $locale, string $extension = 'po')
{
$this->_name = $name;
+ // If space is not added after slash, the character after it remains lowercased
+ $pluginName = Inflector::camelize(str_replace('/', '/ ', $this->_name));
+ if (strpos($this->_name, '.')) {
+ [$this->_plugin, $this->_name] = pluginSplit($pluginName);
+ } elseif (Plugin::isLoaded($pluginName)) {
+ $this->_plugin = $pluginName;
+ }
$this->_locale = $locale;
$this->_extension = $extension;
}
@@ -166,15 +181,17 @@ public function translationsFolders(): array
foreach ($localePaths as $path) {
foreach ($folders as $folder) {
$searchPaths[] = $path . $folder . DIRECTORY_SEPARATOR;
+ // gettext compatible paths, see https://www.php.net/manual/en/function.gettext.php
+ $searchPaths[] = $path . $folder . DIRECTORY_SEPARATOR . 'LC_MESSAGES' . DIRECTORY_SEPARATOR;
}
}
- // If space is not added after slash, the character after it remains lowercased
- $pluginName = Inflector::camelize(str_replace('/', '/ ', $this->_name));
- if (Plugin::isLoaded($pluginName)) {
- $basePath = App::path('locales', $pluginName)[0];
+ if ($this->_plugin && Plugin::isLoaded($this->_plugin)) {
+ $basePath = App::path('locales', $this->_plugin)[0];
foreach ($folders as $folder) {
$searchPaths[] = $basePath . $folder . DIRECTORY_SEPARATOR;
+ // gettext compatible paths, see https://www.php.net/manual/en/function.gettext.php
+ $searchPaths[] = $basePath . $folder . DIRECTORY_SEPARATOR . 'LC_MESSAGES' . DIRECTORY_SEPARATOR;
}
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Number.php b/app/vendor/cakephp/cakephp/src/I18n/Number.php
index accd550b0..6c12f715a 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Number.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Number.php
@@ -17,6 +17,7 @@
namespace Cake\I18n;
use NumberFormatter;
+use function Cake\Core\deprecationWarning;
/**
* Number helper library.
@@ -85,7 +86,7 @@ class Number
*
* - `locale`: The locale name to use for formatting the number, e.g. fr_FR
*
- * @param string|float $value A floating point number.
+ * @param string|float|int $value A floating point number.
* @param int $precision The precision of the returned number.
* @param array $options Additional options
* @return string Formatted float.
@@ -101,7 +102,7 @@ public static function precision($value, int $precision = 3, array $options = []
/**
* Returns a formatted-for-humans file size.
*
- * @param string|int $size Size in bytes
+ * @param string|float|int $size Size in bytes
* @return string Human readable size
* @link https://book.cakephp.org/4/en/core-libraries/number.html#interacting-with-human-readable-values
*/
@@ -131,7 +132,7 @@ public static function toReadableSize($size): string
* - `multiply`: Multiply the input value by 100 for decimal percentages.
* - `locale`: The locale name to use for formatting the number, e.g. fr_FR
*
- * @param string|float $value A floating point number
+ * @param string|float|int $value A floating point number
* @param int $precision The precision of the returned number
* @param array $options Options
* @return string Percentage string
@@ -230,6 +231,8 @@ public static function formatDelta($value, array $options = []): string
* - `zero` - The text to use for zero values, can be a string or a number. e.g. 0, 'Free!'
* - `places` - Number of decimal places to use. e.g. 2
* - `precision` - Maximum Number of decimal places to use, e.g. 2
+ * - `roundingMode` - Rounding mode to use. e.g. NumberFormatter::ROUND_HALF_UP.
+ * When not set locale default will be used
* - `pattern` - An ICU number pattern to use for formatting the number. e.g #,##0.00
* - `useIntlCode` - Whether to replace the currency symbol with the international
* currency code.
@@ -364,6 +367,8 @@ public static function setDefaultCurrencyFormat($currencyFormat = null): void
* numbers representing money or a NumberFormatter constant.
* - `places` - Number of decimal places to use. e.g. 2
* - `precision` - Maximum Number of decimal places to use, e.g. 2
+ * - `roundingMode` - Rounding mode to use. e.g. NumberFormatter::ROUND_HALF_UP.
+ * When not set locale default will be used
* - `pattern` - An ICU number pattern to use for formatting the number. e.g #,##0.00
* - `useIntlCode` - Whether to replace the currency symbol with the international
* currency code.
@@ -405,6 +410,7 @@ public static function formatter(array $options = []): NumberFormatter
$options = array_intersect_key($options, [
'places' => null,
'precision' => null,
+ 'roundingMode' => null,
'pattern' => null,
'useIntlCode' => null,
]);
@@ -451,6 +457,10 @@ protected static function _setAttributes(NumberFormatter $formatter, array $opti
$formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $options['precision']);
}
+ if (isset($options['roundingMode'])) {
+ $formatter->setAttribute(NumberFormatter::ROUNDING_MODE, $options['roundingMode']);
+ }
+
if (!empty($options['pattern'])) {
$formatter->setPattern($options['pattern']);
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Parser/PoFileParser.php b/app/vendor/cakephp/cakephp/src/I18n/Parser/PoFileParser.php
index a3b195923..e4aa46270 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Parser/PoFileParser.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Parser/PoFileParser.php
@@ -94,7 +94,6 @@ public function parse(string $resource): array
} elseif (substr($line, 0, 7) === 'msgid "') {
// We start a new msg so save previous
$this->_addMessage($messages, $item);
- /** @psalm-suppress InvalidArrayOffset */
$item['ids']['singular'] = substr($line, 7, -1);
$stage = ['ids', 'singular'];
} elseif (substr($line, 0, 8) === 'msgstr "') {
@@ -124,7 +123,6 @@ public function parse(string $resource): array
break;
}
} elseif (substr($line, 0, 14) === 'msgid_plural "') {
- /** @psalm-suppress InvalidArrayOffset */
$item['ids']['plural'] = substr($line, 14, -1);
$stage = ['ids', 'plural'];
} elseif (substr($line, 0, 7) === 'msgstr[') {
diff --git a/app/vendor/cakephp/cakephp/src/I18n/Time.php b/app/vendor/cakephp/cakephp/src/I18n/Time.php
index 9528e9de3..9209418cc 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/Time.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/Time.php
@@ -20,6 +20,7 @@
use DateTimeInterface;
use DateTimeZone;
use IntlDateFormatter;
+use function Cake\Core\deprecationWarning;
/**
* Extends the built-in DateTime class to provide handy methods and locale-aware
diff --git a/app/vendor/cakephp/cakephp/src/I18n/functions.php b/app/vendor/cakephp/cakephp/src/I18n/functions.php
index 45f17250f..3295049ad 100644
--- a/app/vendor/cakephp/cakephp/src/I18n/functions.php
+++ b/app/vendor/cakephp/cakephp/src/I18n/functions.php
@@ -14,240 +14,221 @@
* @since 3.0.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
+namespace Cake\I18n;
-use Cake\I18n\I18n;
-
+// phpcs:disable PSR1.Files.SideEffects
// Backwards compatibility alias for custom translation messages loaders which return a Package instance.
-// phpcs:disable
if (!class_exists('Aura\Intl\Package')) {
class_alias('Cake\I18n\Package', 'Aura\Intl\Package');
}
-// phpcs:enable
-
-if (!function_exists('__')) {
- /**
- * Returns a translated string if one is found; Otherwise, the submitted message.
- *
- * @param string $singular Text to translate.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string The translated text.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__
- */
- function __(string $singular, ...$args): string
- {
- if (!$singular) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator()->translate($singular, $args);
+
+/**
+ * Returns a translated string if one is found; Otherwise, the submitted message.
+ *
+ * @param string $singular Text to translate.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string The translated text.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__
+ */
+function __(string $singular, ...$args): string
+{
+ if (!$singular) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator()->translate($singular, $args);
}
-if (!function_exists('__n')) {
- /**
- * Returns correct plural form of message identified by $singular and $plural for count $count.
- * Some languages have more than one form for plural messages dependent on the count.
- *
- * @param string $singular Singular text to translate.
- * @param string $plural Plural text.
- * @param int $count Count.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string Plural form of translated string.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__n
- */
- function __n(string $singular, string $plural, int $count, ...$args): string
- {
- if (!$singular) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator()->translate(
- $plural,
- ['_count' => $count, '_singular' => $singular] + $args
- );
+/**
+ * Returns correct plural form of message identified by $singular and $plural for count $count.
+ * Some languages have more than one form for plural messages dependent on the count.
+ *
+ * @param string $singular Singular text to translate.
+ * @param string $plural Plural text.
+ * @param int $count Count.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string Plural form of translated string.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__n
+ */
+function __n(string $singular, string $plural, int $count, ...$args): string
+{
+ if (!$singular) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator()->translate(
+ $plural,
+ ['_count' => $count, '_singular' => $singular] + $args
+ );
}
-if (!function_exists('__d')) {
- /**
- * Allows you to override the current domain for a single message lookup.
- *
- * @param string $domain Domain.
- * @param string $msg String to translate.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string Translated string.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__d
- */
- function __d(string $domain, string $msg, ...$args): string
- {
- if (!$msg) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator($domain)->translate($msg, $args);
+/**
+ * Allows you to override the current domain for a single message lookup.
+ *
+ * @param string $domain Domain.
+ * @param string $msg String to translate.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string Translated string.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__d
+ */
+function __d(string $domain, string $msg, ...$args): string
+{
+ if (!$msg) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator($domain)->translate($msg, $args);
}
-if (!function_exists('__dn')) {
- /**
- * Allows you to override the current domain for a single plural message lookup.
- * Returns correct plural form of message identified by $singular and $plural for count $count
- * from domain $domain.
- *
- * @param string $domain Domain.
- * @param string $singular Singular string to translate.
- * @param string $plural Plural.
- * @param int $count Count.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string Plural form of translated string.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__dn
- */
- function __dn(string $domain, string $singular, string $plural, int $count, ...$args): string
- {
- if (!$singular) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator($domain)->translate(
- $plural,
- ['_count' => $count, '_singular' => $singular] + $args
- );
+/**
+ * Allows you to override the current domain for a single plural message lookup.
+ * Returns correct plural form of message identified by $singular and $plural for count $count
+ * from domain $domain.
+ *
+ * @param string $domain Domain.
+ * @param string $singular Singular string to translate.
+ * @param string $plural Plural.
+ * @param int $count Count.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string Plural form of translated string.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__dn
+ */
+function __dn(string $domain, string $singular, string $plural, int $count, ...$args): string
+{
+ if (!$singular) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator($domain)->translate(
+ $plural,
+ ['_count' => $count, '_singular' => $singular] + $args
+ );
}
-if (!function_exists('__x')) {
- /**
- * Returns a translated string if one is found; Otherwise, the submitted message.
- * The context is a unique identifier for the translations string that makes it unique
- * within the same domain.
- *
- * @param string $context Context of the text.
- * @param string $singular Text to translate.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string Translated string.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__x
- */
- function __x(string $context, string $singular, ...$args): string
- {
- if (!$singular) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator()->translate($singular, ['_context' => $context] + $args);
+/**
+ * Returns a translated string if one is found; Otherwise, the submitted message.
+ * The context is a unique identifier for the translations string that makes it unique
+ * within the same domain.
+ *
+ * @param string $context Context of the text.
+ * @param string $singular Text to translate.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string Translated string.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__x
+ */
+function __x(string $context, string $singular, ...$args): string
+{
+ if (!$singular) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator()->translate($singular, ['_context' => $context] + $args);
}
-if (!function_exists('__xn')) {
- /**
- * Returns correct plural form of message identified by $singular and $plural for count $count.
- * Some languages have more than one form for plural messages dependent on the count.
- * The context is a unique identifier for the translations string that makes it unique
- * within the same domain.
- *
- * @param string $context Context of the text.
- * @param string $singular Singular text to translate.
- * @param string $plural Plural text.
- * @param int $count Count.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string Plural form of translated string.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__xn
- */
- function __xn(string $context, string $singular, string $plural, int $count, ...$args): string
- {
- if (!$singular) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator()->translate(
- $plural,
- ['_count' => $count, '_singular' => $singular, '_context' => $context] + $args
- );
+/**
+ * Returns correct plural form of message identified by $singular and $plural for count $count.
+ * Some languages have more than one form for plural messages dependent on the count.
+ * The context is a unique identifier for the translations string that makes it unique
+ * within the same domain.
+ *
+ * @param string $context Context of the text.
+ * @param string $singular Singular text to translate.
+ * @param string $plural Plural text.
+ * @param int $count Count.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string Plural form of translated string.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__xn
+ */
+function __xn(string $context, string $singular, string $plural, int $count, ...$args): string
+{
+ if (!$singular) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator()->translate(
+ $plural,
+ ['_count' => $count, '_singular' => $singular, '_context' => $context] + $args
+ );
}
-if (!function_exists('__dx')) {
- /**
- * Allows you to override the current domain for a single message lookup.
- * The context is a unique identifier for the translations string that makes it unique
- * within the same domain.
- *
- * @param string $domain Domain.
- * @param string $context Context of the text.
- * @param string $msg String to translate.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string Translated string.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__dx
- */
- function __dx(string $domain, string $context, string $msg, ...$args): string
- {
- if (!$msg) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator($domain)->translate(
- $msg,
- ['_context' => $context] + $args
- );
+/**
+ * Allows you to override the current domain for a single message lookup.
+ * The context is a unique identifier for the translations string that makes it unique
+ * within the same domain.
+ *
+ * @param string $domain Domain.
+ * @param string $context Context of the text.
+ * @param string $msg String to translate.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string Translated string.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__dx
+ */
+function __dx(string $domain, string $context, string $msg, ...$args): string
+{
+ if (!$msg) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator($domain)->translate(
+ $msg,
+ ['_context' => $context] + $args
+ );
}
-if (!function_exists('__dxn')) {
- /**
- * Returns correct plural form of message identified by $singular and $plural for count $count.
- * Allows you to override the current domain for a single message lookup.
- * The context is a unique identifier for the translations string that makes it unique
- * within the same domain.
- *
- * @param string $domain Domain.
- * @param string $context Context of the text.
- * @param string $singular Singular text to translate.
- * @param string $plural Plural text.
- * @param int $count Count.
- * @param mixed ...$args Array with arguments or multiple arguments in function.
- * @return string Plural form of translated string.
- * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__dxn
- */
- function __dxn(string $domain, string $context, string $singular, string $plural, int $count, ...$args): string
- {
- if (!$singular) {
- return '';
- }
- if (isset($args[0]) && is_array($args[0])) {
- $args = $args[0];
- }
-
- return I18n::getTranslator($domain)->translate(
- $plural,
- ['_count' => $count, '_singular' => $singular, '_context' => $context] + $args
- );
+/**
+ * Returns correct plural form of message identified by $singular and $plural for count $count.
+ * Allows you to override the current domain for a single message lookup.
+ * The context is a unique identifier for the translations string that makes it unique
+ * within the same domain.
+ *
+ * @param string $domain Domain.
+ * @param string $context Context of the text.
+ * @param string $singular Singular text to translate.
+ * @param string $plural Plural text.
+ * @param int $count Count.
+ * @param mixed ...$args Array with arguments or multiple arguments in function.
+ * @return string Plural form of translated string.
+ * @link https://book.cakephp.org/4/en/core-libraries/global-constants-and-functions.html#__dxn
+ */
+function __dxn(string $domain, string $context, string $singular, string $plural, int $count, ...$args): string
+{
+ if (!$singular) {
+ return '';
+ }
+ if (isset($args[0]) && is_array($args[0])) {
+ $args = $args[0];
}
+ return I18n::getTranslator($domain)->translate(
+ $plural,
+ ['_count' => $count, '_singular' => $singular, '_context' => $context] + $args
+ );
+}
+
+/**
+ * Include global functions.
+ */
+if (!getenv('CAKE_DISABLE_GLOBAL_FUNCS')) {
+ include 'functions_global.php';
}
diff --git a/app/vendor/cakephp/cakephp/src/I18n/functions_global.php b/app/vendor/cakephp/cakephp/src/I18n/functions_global.php
new file mode 100644
index 000000000..94e48d381
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/I18n/functions_global.php
@@ -0,0 +1,174 @@
+
@@ -54,6 +55,7 @@ class FileLog extends BaseLog
'rotate' => 10,
'size' => 10485760, // 10MB
'mask' => null,
+ 'dirMask' => 0770,
'formatter' => [
'className' => DefaultFormatter::class,
],
@@ -90,8 +92,8 @@ public function __construct(array $config = [])
parent::__construct($config);
$this->_path = $this->getConfig('path', sys_get_temp_dir() . DIRECTORY_SEPARATOR);
- if (Configure::read('debug') && !is_dir($this->_path)) {
- mkdir($this->_path, 0775, true);
+ if (!is_dir($this->_path)) {
+ mkdir($this->_path, $this->_config['dirMask'], true);
}
if (!empty($this->_config['file'])) {
diff --git a/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php b/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php
index 1e48d0d52..5f8c6d342 100644
--- a/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php
+++ b/app/vendor/cakephp/cakephp/src/Log/Engine/SyslogLog.php
@@ -18,6 +18,7 @@
use Cake\Log\Formatter\DefaultFormatter;
use Cake\Log\Formatter\LegacySyslogFormatter;
+use function Cake\Core\deprecationWarning;
/**
* Syslog stream for Logging. Writes logs to the system logger
diff --git a/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php b/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php
index 113f67002..535ade03f 100644
--- a/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/Log/LogEngineRegistry.php
@@ -20,6 +20,7 @@
use Cake\Core\ObjectRegistry;
use Psr\Log\LoggerInterface;
use RuntimeException;
+use function Cake\Core\getTypeName;
/**
* Registry of loaded log engines
@@ -79,7 +80,6 @@ protected function _create($class, string $alias, array $config): LoggerInterfac
}
if (!isset($instance)) {
- /** @psalm-suppress UndefinedClass */
$instance = new $class($config);
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Mailer.php b/app/vendor/cakephp/cakephp/src/Mailer/Mailer.php
index ce1b87fab..1cd89c23f 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Mailer.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Mailer.php
@@ -24,6 +24,7 @@
use Cake\ORM\Locator\LocatorAwareTrait;
use Cake\View\ViewBuilder;
use InvalidArgumentException;
+use function Cake\Core\deprecationWarning;
/**
* Mailer base class.
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Message.php b/app/vendor/cakephp/cakephp/src/Mailer/Message.php
index 9b51be0e1..78ae98a62 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Message.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Message.php
@@ -28,6 +28,7 @@
use Psr\Http\Message\UploadedFileInterface;
use Serializable;
use SimpleXMLElement;
+use function Cake\Core\env;
/**
* Email message class.
@@ -301,6 +302,18 @@ class Message implements JsonSerializable, Serializable
*/
protected $emailPattern = self::EMAIL_PATTERN;
+ /**
+ * Properties that could be serialized
+ *
+ * @var array
+ */
+ protected $serializableProperties = [
+ 'to', 'from', 'sender', 'replyTo', 'cc', 'bcc', 'subject',
+ 'returnPath', 'readReceipt', 'emailFormat', 'emailPattern', 'domain',
+ 'attachments', 'messageId', 'headers', 'appCharset', 'charset', 'headerCharset',
+ 'textMessage', 'htmlMessage',
+ ];
+
/**
* Constructor
*
@@ -999,8 +1012,8 @@ protected function formatAddress(array $address): array
$return[] = $email;
} else {
$encoded = $this->encodeForHeader($alias);
- if ($encoded === $alias && preg_match('/[^a-z0-9 ]/i', $encoded)) {
- $encoded = '"' . str_replace('"', '\"', $encoded) . '"';
+ if (preg_match('/[^a-z0-9+\-\\=? ]/i', $encoded)) {
+ $encoded = '"' . addcslashes($encoded, '"\\') . '"';
}
$return[] = sprintf('%s <%s>', $encoded, $email);
}
@@ -1151,7 +1164,7 @@ public function getDomain(): string
* ```
*
* The `contentId` key allows you to specify an inline attachment. In your email text, you
- * can use `` to display the image inline.
+ * can use `` to display the image inline.
*
* The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve
* attachment compatibility with outlook email clients.
@@ -1849,15 +1862,8 @@ public function getContentTypeCharset(): string
*/
public function jsonSerialize(): array
{
- $properties = [
- 'to', 'from', 'sender', 'replyTo', 'cc', 'bcc', 'subject',
- 'returnPath', 'readReceipt', 'emailFormat', 'emailPattern', 'domain',
- 'attachments', 'messageId', 'headers', 'appCharset', 'charset', 'headerCharset',
- 'textMessage', 'htmlMessage',
- ];
-
$array = [];
- foreach ($properties as $property) {
+ foreach ($this->serializableProperties as $property) {
$array[$property] = $this->{$property};
}
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Renderer.php b/app/vendor/cakephp/cakephp/src/Mailer/Renderer.php
index 2c394309f..32cef1f86 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Renderer.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Renderer.php
@@ -18,6 +18,7 @@
use Cake\View\View;
use Cake\View\ViewVarsTrait;
+use function Cake\Core\pluginSplit;
/**
* Class for rendering email message.
diff --git a/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php b/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php
index 0e6409eed..428316b47 100644
--- a/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php
+++ b/app/vendor/cakephp/cakephp/src/Mailer/Transport/SmtpTransport.php
@@ -23,6 +23,7 @@
use Cake\Network\Socket;
use Exception;
use RuntimeException;
+use function Cake\Core\env;
/**
* Send mail using SMTP protocol
diff --git a/app/vendor/cakephp/cakephp/src/Network/Socket.php b/app/vendor/cakephp/cakephp/src/Network/Socket.php
index e94d8eab9..bfcdbc14f 100644
--- a/app/vendor/cakephp/cakephp/src/Network/Socket.php
+++ b/app/vendor/cakephp/cakephp/src/Network/Socket.php
@@ -23,6 +23,7 @@
use Composer\CaBundle\CaBundle;
use Exception;
use InvalidArgumentException;
+use function Cake\Core\deprecationWarning;
/**
* CakePHP network socket connection class.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association.php b/app/vendor/cakephp/cakephp/src/ORM/Association.php
index 9621dd2c4..8601283b7 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association.php
@@ -29,6 +29,8 @@
use Closure;
use InvalidArgumentException;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\pluginSplit;
/**
* An Association is a relationship established between two tables and is used
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php
index 1950b2568..3072073a5 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsTo.php
@@ -24,12 +24,16 @@
use Cake\Utility\Inflector;
use Closure;
use RuntimeException;
+use function Cake\Core\pluginSplit;
/**
* Represents an 1 - N relationship where the source side of the relation is
* related to only one record in the target table.
*
* An example of a BelongsTo association would be Article belongs to Author.
+ *
+ * @template T of \Cake\ORM\Table
+ * @mixin T
*/
class BelongsTo extends Association
{
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php
index f43402258..71b26e4a0 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php
@@ -37,6 +37,9 @@
*
* An example of a BelongsToMany association would be Article belongs to many Tags.
* In this example 'Article' is the source table and 'Tags' is the target table.
+ *
+ * @template T of \Cake\ORM\Table
+ * @mixin T
*/
class BelongsToMany extends Association
{
@@ -1206,7 +1209,7 @@ function () use ($sourceEntity, $targetEntities, $primaryValue, $options) {
// Create a subquery join to ensure we get
// the correct entity passed to callbacks.
- $existing = $junction->query()
+ $existing = $junction->selectQuery()
->from([$junctionQueryAlias => $matches])
->innerJoin(
[$junction->getAlias() => $junction->getTable()],
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php b/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php
index 9dbeac72b..5d95621da 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/HasMany.php
@@ -33,6 +33,9 @@
* will have one or multiple records per each one in the source side.
*
* An example of a HasMany association would be Author has many Articles.
+ *
+ * @template T of \Cake\ORM\Table
+ * @mixin T
*/
class HasMany extends Association
{
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php b/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php
index b48ea7213..ff239477d 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Association/HasOne.php
@@ -22,12 +22,16 @@
use Cake\ORM\Table;
use Cake\Utility\Inflector;
use Closure;
+use function Cake\Core\pluginSplit;
/**
* Represents an 1 - 1 relationship where the source side of the relation is
* related to only one record in the target table and vice versa.
*
* An example of a HasOne association would be User has one Profile.
+ *
+ * @template T of \Cake\ORM\Table
+ * @mixin T
*/
class HasOne extends Association
{
diff --git a/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php b/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php
index 9e9e9c0d1..9f213145a 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/AssociationCollection.php
@@ -23,12 +23,16 @@
use InvalidArgumentException;
use IteratorAggregate;
use Traversable;
+use function Cake\Core\namespaceSplit;
+use function Cake\Core\pluginSplit;
/**
* A container/collection for association classes.
*
* Contains methods for managing associations, and
* ordering operations around saving and deleting.
+ *
+ * @template-implements \IteratorAggregate
*/
class AssociationCollection implements IteratorAggregate
{
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior.php
index 31ab1f295..485770880 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior.php
@@ -21,6 +21,7 @@
use Cake\Event\EventListenerInterface;
use ReflectionClass;
use ReflectionMethod;
+use function Cake\Core\deprecationWarning;
/**
* Base class for behaviors.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/ShadowTableStrategy.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/ShadowTableStrategy.php
index 3284c3dc1..2408090b1 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/ShadowTableStrategy.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/Translate/ShadowTableStrategy.php
@@ -27,6 +27,7 @@
use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Utility\Hash;
+use function Cake\Core\pluginSplit;
/**
* This class provides a way to translate dynamic data by keeping translations
@@ -266,7 +267,6 @@ function ($c, &$field) use ($fields, $alias, $mainTableAlias, $mainTableFields,
return $c;
}
- /** @psalm-suppress ParadoxicalCondition */
if (in_array($field, $fields, true)) {
$joinRequired = true;
$field = "$alias.$field";
@@ -323,7 +323,6 @@ function ($expression) use ($fields, $alias, $mainTableAlias, $mainTableFields,
return;
}
- /** @psalm-suppress ParadoxicalCondition */
if (in_array($field, $mainTableFields, true)) {
$expression->setField("$mainTableAlias.$field");
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
index dc0df6671..576ea8909 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TranslateBehavior.php
@@ -25,6 +25,7 @@
use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Utility\Inflector;
+use function Cake\Core\namespaceSplit;
/**
* This behavior provides a way to translate dynamic data by keeping translations
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php
index b009d0d52..493bea37d 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Behavior/TreeBehavior.php
@@ -18,6 +18,7 @@
use Cake\Collection\CollectionInterface;
use Cake\Database\Expression\IdentifierExpression;
+use Cake\Database\Expression\QueryExpression;
use Cake\Datasource\EntityInterface;
use Cake\Datasource\Exception\RecordNotFoundException;
use Cake\Event\EventInterface;
@@ -227,20 +228,24 @@ public function beforeDelete(EventInterface $event, EntityInterface $entity)
$diff = $right - $left + 1;
if ($diff > 2) {
- $query = $this->_scope($this->_table->query())
- ->where(function ($exp) use ($config, $left, $right) {
- /** @var \Cake\Database\Expression\QueryExpression $exp */
- return $exp
- ->gte($config['leftField'], $left + 1)
- ->lte($config['leftField'], $right - 1);
- });
if ($this->getConfig('cascadeCallbacks')) {
+ $query = $this->_scope($this->_table->selectQuery())
+ ->where(function (QueryExpression $exp) use ($config, $left, $right) {
+ return $exp
+ ->gte($config['leftField'], $left + 1)
+ ->lte($config['leftField'], $right - 1);
+ });
$entities = $query->toArray();
foreach ($entities as $entityToDelete) {
$this->_table->delete($entityToDelete, ['atomic' => false]);
}
} else {
- $query->delete();
+ $query = $this->_scope($this->_table->deleteQuery())
+ ->where(function (QueryExpression $exp) use ($config, $left, $right) {
+ return $exp
+ ->gte($config['leftField'], $left + 1)
+ ->lte($config['leftField'], $right - 1);
+ });
$statement = $query->execute();
$statement->closeCursor();
}
@@ -848,7 +853,7 @@ protected function _recoverTree(int $lftRght = 1, $parentId = null, $level = 0):
$primaryKey = $this->_getPrimaryKey();
$order = $config['recoverOrder'] ?: $primaryKey;
- $nodes = $this->_scope($this->_table->query())
+ $nodes = $this->_scope($this->_table->selectQuery())
->select($primaryKey)
->where([$parent . ' IS' => $parentId])
->order($order)
@@ -911,7 +916,7 @@ protected function _sync(int $shift, string $dir, string $conditions, bool $mark
$config = $this->_config;
foreach ([$config['leftField'], $config['rightField']] as $field) {
- $query = $this->_scope($this->_table->query());
+ $query = $this->_scope($this->_table->updateQuery());
$exp = $query->newExpr();
$movement = clone $exp;
@@ -925,10 +930,7 @@ protected function _sync(int $shift, string $dir, string $conditions, bool $mark
$where = clone $exp;
$where->add($field)->add($conditions)->setConjunction('');
- $query->update()
- ->set($exp->eq($field, $movement))
- ->where($where);
-
+ $query->set($exp->eq($field, $movement))->where($where);
$query->execute()->closeCursor();
}
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php b/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
index e4b76e1c3..fc06b3118 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/BehaviorRegistry.php
@@ -203,6 +203,49 @@ protected function _getMethods(Behavior $instance, string $class, string $alias)
return compact('methods', 'finders');
}
+ /**
+ * Set an object directly into the registry by name.
+ *
+ * @param string $name The name of the object to set in the registry.
+ * @param \Cake\ORM\Behavior $object instance to store in the registry
+ * @return $this
+ */
+ public function set(string $name, object $object)
+ {
+ parent::set($name, $object);
+
+ $methods = $this->_getMethods($object, get_class($object), $name);
+ $this->_methodMap += $methods['methods'];
+ $this->_finderMap += $methods['finders'];
+
+ return $this;
+ }
+
+ /**
+ * Remove an object from the registry.
+ *
+ * If this registry has an event manager, the object will be detached from any events as well.
+ *
+ * @param string $name The name of the object to remove from the registry.
+ * @return $this
+ */
+ public function unload(string $name)
+ {
+ $instance = $this->get($name);
+ $result = parent::unload($name);
+
+ $methods = array_change_key_case($instance->implementedMethods());
+ foreach (array_keys($methods) as $method) {
+ unset($this->_methodMap[$method]);
+ }
+ $finders = array_change_key_case($instance->implementedFinders());
+ foreach (array_keys($finders) as $finder) {
+ unset($this->_finderMap[$finder]);
+ }
+
+ return $result;
+ }
+
/**
* Check if any loaded behavior implements a method.
*
diff --git a/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php b/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
index 1778c32de..d4fa10a25 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/EagerLoader.php
@@ -630,7 +630,7 @@ public function loadExternal(Query $query, StatementInterface $statement): State
return $statement;
}
- $driver = $query->getConnection()->getDriver();
+ $driver = $query->getConnection()->getDriver($query->getConnectionRole());
[$collected, $statement] = $this->_collectKeys($external, $query, $statement);
// No records found, skip trying to attach associations.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Locator/TableLocator.php b/app/vendor/cakephp/cakephp/src/ORM/Locator/TableLocator.php
index 67a875201..3fefe3f40 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Locator/TableLocator.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Locator/TableLocator.php
@@ -25,6 +25,7 @@
use Cake\ORM\Table;
use Cake\Utility\Inflector;
use RuntimeException;
+use function Cake\Core\pluginSplit;
/**
* Provides a default registry/factory for Table objects.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php b/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php
index 7511aafa4..2caa7e573 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Marshaller.php
@@ -26,6 +26,8 @@
use Cake\Utility\Hash;
use InvalidArgumentException;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\getTypeName;
/**
* Contains logic to convert array data into entities.
@@ -659,7 +661,6 @@ public function merge(EntityInterface $entity, array $data, array $options = [])
* @param array $options List of options.
* @return array<\Cake\Datasource\EntityInterface>
* @see \Cake\ORM\Entity::$_accessible
- * @psalm-suppress NullArrayOffset
*/
public function mergeMany(iterable $entities, array $data, array $options = []): array
{
@@ -755,7 +756,6 @@ protected function _mergeAssociation($original, Association $assoc, $value, arra
$types = [Association::ONE_TO_ONE, Association::MANY_TO_ONE];
$type = $assoc->type();
if (in_array($type, $types, true)) {
- /** @psalm-suppress PossiblyInvalidArgument, ArgumentTypeCoercion */
return $marshaller->merge($original, $value, $options);
}
if ($type === Association::MANY_TO_MANY) {
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Query.php b/app/vendor/cakephp/cakephp/src/ORM/Query.php
index 7ba368007..3f40d5b6f 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Query.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Query.php
@@ -31,6 +31,7 @@
use JsonSerializable;
use RuntimeException;
use Traversable;
+use function Cake\Core\deprecationWarning;
/**
* Extends the base Query class to provide new methods related to association
@@ -51,28 +52,28 @@
* @method \Cake\Collection\CollectionInterface map(callable $c) Modifies each of the results using the callable
* @method mixed reduce(callable $c, $zero = null) Folds all the results into a single value using the callable.
* @method \Cake\Collection\CollectionInterface extract($field) Extracts a single column from each row
- * @method mixed max($field) Returns the maximum value for a single column in all the results.
- * @method mixed min($field) Returns the minimum value for a single column in all the results.
+ * @method mixed max($field, $sort = \SORT_NUMERIC) Returns the maximum value for a single column in all the results.
+ * @method mixed min($field, $sort = \SORT_NUMERIC) Returns the minimum value for a single column in all the results.
* @method \Cake\Collection\CollectionInterface groupBy(callable|string $field) In-memory group all results by the value of a column.
* @method \Cake\Collection\CollectionInterface indexBy(callable|string $callback) Returns the results indexed by the value of a column.
* @method \Cake\Collection\CollectionInterface countBy(callable|string $field) Returns the number of unique values for a column
- * @method float sumOf(callable|string $field) Returns the sum of all values for a single column
+ * @method int|float sumOf($field = null) Returns the sum of all values for a single column
* @method \Cake\Collection\CollectionInterface shuffle() In-memory randomize the order the results are returned
* @method \Cake\Collection\CollectionInterface sample(int $size = 10) In-memory shuffle the results and return a subset of them.
* @method \Cake\Collection\CollectionInterface take(int $size = 1, int $from = 0) In-memory limit and offset for the query results.
* @method \Cake\Collection\CollectionInterface skip(int $howMany) Skips some rows from the start of the query result.
* @method mixed last() Return the last row of the query result
- * @method \Cake\Collection\CollectionInterface append(array|\Traversable $items) Appends more rows to the result of the query.
+ * @method \Cake\Collection\CollectionInterface append(mixed $items) Appends more rows to the result of the query.
* @method \Cake\Collection\CollectionInterface combine($k, $v, $g = null) Returns the values of the column $v index by column $k,
* and grouped by $g.
* @method \Cake\Collection\CollectionInterface nest($k, $p, $n = 'children') Creates a tree structure by nesting the values of column $p into that
* with the same value for $k using $n as the nesting key.
* @method array toArray() Returns a key-value array with the results of this query.
* @method array toList() Returns a numerically indexed array with the results of this query.
- * @method \Cake\Collection\CollectionInterface stopWhen(callable $c) Returns each row until the callable returns true.
- * @method \Cake\Collection\CollectionInterface zip(array|\Traversable $c) Returns the first result of both the query and $c in an array,
+ * @method \Cake\Collection\CollectionInterface stopWhen(callable|array $c) Returns each row until the callable returns true.
+ * @method \Cake\Collection\CollectionInterface zip(iterable $c) Returns the first result of both the query and $c in an array,
* then the second results and so on.
- * @method \Cake\Collection\CollectionInterface zipWith($collections, callable $callable) Returns each of the results out of calling $c
+ * @method \Cake\Collection\CollectionInterface zipWith(iterable $collections, callable $callable) Returns each of the results out of calling $c
* with the first rows of the query and each of the items, then the second rows and so on.
* @method \Cake\Collection\CollectionInterface chunk(int $size) Groups the results in arrays of $size rows each.
* @method bool isEmpty() Returns true if this query found no results.
@@ -178,7 +179,7 @@ class Query extends DatabaseQuery implements JsonSerializable, QueryInterface
public function __construct(Connection $connection, Table $table)
{
parent::__construct($connection);
- $this->repository($table);
+ $this->setRepository($table);
if ($this->_repository !== null) {
$this->addDefaultTypes($this->_repository);
@@ -242,6 +243,24 @@ public function select($fields = [], bool $overwrite = false)
return parent::select($fields, $overwrite);
}
+ /**
+ * Behaves the exact same as `select()` except adds the field to the list of fields selected and
+ * does not disable auto-selecting fields for Associations.
+ *
+ * Use this instead of calling `select()` then `enableAutoFields()` to re-enable auto-fields.
+ *
+ * @param \Cake\Database\ExpressionInterface|\Cake\ORM\Table|\Cake\ORM\Association|callable|array|string $fields Fields
+ * to be added to the list.
+ * @return $this
+ */
+ public function selectAlso($fields)
+ {
+ $this->select($fields);
+ $this->_autoFields = true;
+
+ return $this;
+ }
+
/**
* All the fields associated with the passed table except the excluded
* fields will be added to the select clause of the query. Passed excluded fields should not be aliased.
@@ -977,8 +996,8 @@ protected function _performCount(): int
->disableAutoFields()
->execute();
} else {
- $statement = $this->getConnection()->newQuery()
- ->select($count)
+ $statement = $this->getConnection()
+ ->selectQuery($count)
->from(['count_source' => $query])
->execute();
}
@@ -1440,4 +1459,19 @@ protected function _decorateResults(Traversable $result): ResultSetInterface
return $result;
}
+
+ /**
+ * Helper for ORM\Query exceptions
+ *
+ * @param string $method The method that is invalid.
+ * @param string $message An additional message.
+ * @return void
+ * @internal
+ */
+ protected function _deprecatedMethod($method, $message = '')
+ {
+ $class = static::class;
+ $text = "As of 4.5.0 calling {$method}() on {$class} is deprecated. " . $message;
+ deprecationWarning($text);
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Query/DeleteQuery.php b/app/vendor/cakephp/cakephp/src/ORM/Query/DeleteQuery.php
new file mode 100644
index 000000000..40470210e
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Query/DeleteQuery.php
@@ -0,0 +1,337 @@
+_type === 'delete' && empty($this->_parts['from'])) {
+ $repository = $this->getRepository();
+ $this->from([$repository->getAlias() => $repository->getTable()]);
+ }
+
+ return parent::sql($binder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function delete(?string $table = null)
+ {
+ $this->_deprecatedMethod('delete()', 'Remove this method call.');
+
+ return parent::delete($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function cache($key, $config = 'default')
+ {
+ $this->_deprecatedMethod('cache()', 'Use execute() instead.');
+
+ return parent::cache($key, $config);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function all(): ResultSetInterface
+ {
+ $this->_deprecatedMethod('all()', 'Use execute() instead.');
+
+ return parent::all();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function select($fields = [], bool $overwrite = false)
+ {
+ $this->_deprecatedMethod('select()', 'Create your query with selectQuery() instead.');
+
+ return parent::select($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function distinct($on = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('distinct()');
+
+ return parent::distinct($on, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function modifier($modifiers, $overwrite = false)
+ {
+ $this->_deprecatedMethod('modifier()');
+
+ return parent::modifier($modifiers, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function join($tables, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('join()');
+
+ return parent::join($tables, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeJoin(string $name)
+ {
+ $this->_deprecatedMethod('removeJoin()');
+
+ return parent::removeJoin($name);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function leftJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('leftJoin()');
+
+ return parent::leftJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function rightJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('rightJoin()');
+
+ return parent::rightJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function leftJoinWith(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('leftJoinWith()');
+
+ return parent::leftJoinWith($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function innerJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('innerJoin()');
+
+ return parent::innerJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function innerJoinWith(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('innerJoinWith()');
+
+ return parent::innerJoinWith($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function group($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('group()');
+
+ return parent::group($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function having($conditions = null, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('having()');
+
+ return parent::having($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andHaving($conditions, $types = [])
+ {
+ $this->_deprecatedMethod('andHaving()');
+
+ return parent::andHaving($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function page(int $num, ?int $limit = null)
+ {
+ $this->_deprecatedMethod('page()');
+
+ return parent::page($num, $limit);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function union($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::union($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function unionAll($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::unionAll($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function insert(array $columns, array $types = [])
+ {
+ $this->_deprecatedMethod('insert()', 'Create your query with insertQuery() instead.');
+
+ return parent::insert($columns, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function into(string $table)
+ {
+ $this->_deprecatedMethod('into()', 'Use from() instead.');
+
+ return parent::into($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function values($data)
+ {
+ $this->_deprecatedMethod('values()');
+
+ return parent::values($data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update($table = null)
+ {
+ $this->_deprecatedMethod('update()', 'Create your query with updateQuery() instead.');
+
+ return parent::update($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function set($key, $value = null, $types = [])
+ {
+ $this->_deprecatedMethod('set()');
+
+ return parent::set($key, $value, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function matching(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('matching()');
+
+ return parent::matching($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function notMatching(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('notMatching()');
+
+ return parent::notMatching($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function contain($associations, $override = false)
+ {
+ $this->_deprecatedMethod('contain()');
+
+ return parent::contain($associations, $override);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContain(): array
+ {
+ $this->_deprecatedMethod('getContain()');
+
+ return parent::getContain();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function find(string $finder, array $options = [])
+ {
+ $this->_deprecatedMethod('find()');
+
+ return parent::find($finder, $options);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Query/InsertQuery.php b/app/vendor/cakephp/cakephp/src/ORM/Query/InsertQuery.php
new file mode 100644
index 000000000..6c3462f97
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Query/InsertQuery.php
@@ -0,0 +1,413 @@
+_deprecatedMethod('delete()', 'Create your query with deleteQuery() instead.');
+
+ return parent::delete($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function cache($key, $config = 'default')
+ {
+ $this->_deprecatedMethod('cache()', 'Use execute() instead.');
+
+ return parent::cache($key, $config);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function all(): ResultSetInterface
+ {
+ $this->_deprecatedMethod('all()', 'Use execute() instead.');
+
+ return parent::all();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function select($fields = [], bool $overwrite = false)
+ {
+ $this->_deprecatedMethod('select()', 'Create your query with selectQuery() instead.');
+
+ return parent::select($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function distinct($on = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('distinct()');
+
+ return parent::distinct($on, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function modifier($modifiers, $overwrite = false)
+ {
+ $this->_deprecatedMethod('modifier()');
+
+ return parent::modifier($modifiers, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function join($tables, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('join()');
+
+ return parent::join($tables, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeJoin(string $name)
+ {
+ $this->_deprecatedMethod('removeJoin()');
+
+ return parent::removeJoin($name);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function leftJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('leftJoin()');
+
+ return parent::leftJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function rightJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('rightJoin()');
+
+ return parent::rightJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function leftJoinWith(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('leftJoinWith()');
+
+ return parent::leftJoinWith($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function innerJoin($table, $conditions = [], $types = [])
+ {
+ $this->_deprecatedMethod('innerJoin()');
+
+ return parent::innerJoin($table, $conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function innerJoinWith(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('innerJoinWith()');
+
+ return parent::innerJoinWith($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function group($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('group()');
+
+ return parent::group($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function having($conditions = null, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('having()');
+
+ return parent::having($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andHaving($conditions, $types = [])
+ {
+ $this->_deprecatedMethod('andHaving()');
+
+ return parent::andHaving($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function page(int $num, ?int $limit = null)
+ {
+ $this->_deprecatedMethod('page()');
+
+ return parent::page($num, $limit);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offset($offset)
+ {
+ $this->_deprecatedMethod('offset()');
+
+ return parent::offset($offset);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function union($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::union($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function unionAll($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::unionAll($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function from($tables = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('from()', 'Use into() instead.');
+
+ return parent::from($tables, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update($table = null)
+ {
+ $this->_deprecatedMethod('update()', 'Create your query with updateQuery() instead.');
+
+ return parent::update($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function set($key, $value = null, $types = [])
+ {
+ $this->_deprecatedMethod('set()');
+
+ return parent::set($key, $value, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function matching(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('matching()');
+
+ return parent::matching($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function notMatching(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('notMatching()');
+
+ return parent::notMatching($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function contain($associations, $override = false)
+ {
+ $this->_deprecatedMethod('contain()');
+
+ return parent::contain($associations, $override);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContain(): array
+ {
+ $this->_deprecatedMethod('getContain()');
+
+ return parent::getContain();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function find(string $finder, array $options = [])
+ {
+ $this->_deprecatedMethod('find()');
+
+ return parent::find($finder, $options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function where($conditions = null, array $types = [], bool $overwrite = false)
+ {
+ $this->_deprecatedMethod('where()');
+
+ return parent::where($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNotNull($fields)
+ {
+ $this->_deprecatedMethod('whereNotNull()');
+
+ return parent::whereNotNull($fields);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNull($fields)
+ {
+ $this->_deprecatedMethod('whereNull()');
+
+ return parent::whereNull($fields);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereInList(string $field, array $values, array $options = [])
+ {
+ $this->_deprecatedMethod('whereInList()');
+
+ return parent::whereInList($field, $values, $options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNotInList(string $field, array $values, array $options = [])
+ {
+ $this->_deprecatedMethod('whereNotInList()');
+
+ return parent::whereNotInList($field, $values, $options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function whereNotInListOrNull(string $field, array $values, array $options = [])
+ {
+ $this->_deprecatedMethod('whereNotInListOrNull()');
+
+ return parent::whereNotInListOrNull($field, $values, $options);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andWhere($conditions, array $types = [])
+ {
+ $this->_deprecatedMethod('andWhere()');
+
+ return parent::andWhere($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function order($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('order()');
+
+ return parent::order($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function orderAsc($field, $overwrite = false)
+ {
+ $this->_deprecatedMethod('orderAsc()');
+
+ return parent::orderAsc($field, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function orderDesc($field, $overwrite = false)
+ {
+ $this->_deprecatedMethod('orderDesc()');
+
+ return parent::orderDesc($field, $overwrite);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Query/SelectQuery.php b/app/vendor/cakephp/cakephp/src/ORM/Query/SelectQuery.php
new file mode 100644
index 000000000..368b6d7b7
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Query/SelectQuery.php
@@ -0,0 +1,127 @@
+_deprecatedMethod('delete()', 'Create your query with deleteQuery() instead.');
+
+ return parent::delete($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function insert(array $columns, array $types = [])
+ {
+ $this->_deprecatedMethod('insert()', 'Create your query with insertQuery() instead.');
+
+ return parent::insert($columns, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function into(string $table)
+ {
+ $this->_deprecatedMethod('into()', 'Use from() instead.');
+
+ return parent::into($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function values($data)
+ {
+ $this->_deprecatedMethod('values()');
+
+ return parent::values($data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update($table = null)
+ {
+ $this->_deprecatedMethod('update()', 'Create your query with updateQuery() instead.');
+
+ return parent::update($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function set($key, $value = null, $types = [])
+ {
+ $this->_deprecatedMethod('set()');
+
+ return parent::set($key, $value, $types);
+ }
+
+ /**
+ * Sets the connection role.
+ *
+ * @param string $role Connection role ('read' or 'write')
+ * @return $this
+ */
+ public function setConnectionRole(string $role)
+ {
+ assert($role === Connection::ROLE_READ || $role === Connection::ROLE_WRITE);
+ $this->connectionRole = $role;
+
+ return $this;
+ }
+
+ /**
+ * Sets the connection role to read.
+ *
+ * @return $this
+ */
+ public function useReadRole()
+ {
+ return $this->setConnectionRole(Connection::ROLE_READ);
+ }
+
+ /**
+ * Sets the connection role to write.
+ *
+ * @return $this
+ */
+ public function useWriteRole()
+ {
+ return $this->setConnectionRole(Connection::ROLE_WRITE);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Query/UpdateQuery.php b/app/vendor/cakephp/cakephp/src/ORM/Query/UpdateQuery.php
new file mode 100644
index 000000000..ff25a89da
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/ORM/Query/UpdateQuery.php
@@ -0,0 +1,267 @@
+_type === 'update' && empty($this->_parts['update'])) {
+ $repository = $this->getRepository();
+ $this->update($repository->getTable());
+ }
+
+ return parent::sql($binder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function delete(?string $table = null)
+ {
+ $this->_deprecatedMethod('delete()', 'Create your query with deleteQuery() instead.');
+
+ return parent::delete($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function cache($key, $config = 'default')
+ {
+ $this->_deprecatedMethod('cache()', 'Use execute() instead.');
+
+ return parent::cache($key, $config);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function all(): ResultSetInterface
+ {
+ $this->_deprecatedMethod('all()', 'Use execute() instead.');
+
+ return parent::all();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function select($fields = [], bool $overwrite = false)
+ {
+ $this->_deprecatedMethod('select()', 'Create your query with selectQuery() instead.');
+
+ return parent::select($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function distinct($on = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('distinct()');
+
+ return parent::distinct($on, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function modifier($modifiers, $overwrite = false)
+ {
+ $this->_deprecatedMethod('modifier()');
+
+ return parent::modifier($modifiers, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function group($fields, $overwrite = false)
+ {
+ $this->_deprecatedMethod('group()');
+
+ return parent::group($fields, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function having($conditions = null, $types = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('having()');
+
+ return parent::having($conditions, $types, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function andHaving($conditions, $types = [])
+ {
+ $this->_deprecatedMethod('andHaving()');
+
+ return parent::andHaving($conditions, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function page(int $num, ?int $limit = null)
+ {
+ $this->_deprecatedMethod('page()');
+
+ return parent::page($num, $limit);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function offset($offset)
+ {
+ $this->_deprecatedMethod('offset()');
+
+ return parent::offset($offset);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function union($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::union($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function unionAll($query, $overwrite = false)
+ {
+ $this->_deprecatedMethod('union()');
+
+ return parent::unionAll($query, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function insert(array $columns, array $types = [])
+ {
+ $this->_deprecatedMethod('insert()', 'Create your query with insertQuery() instead.');
+
+ return parent::insert($columns, $types);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function into(string $table)
+ {
+ $this->_deprecatedMethod('into()', 'Use update() instead.');
+
+ return parent::into($table);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function values($data)
+ {
+ $this->_deprecatedMethod('values()');
+
+ return parent::values($data);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function from($tables = [], $overwrite = false)
+ {
+ $this->_deprecatedMethod('from()', 'Use update() instead.');
+
+ return parent::from($tables, $overwrite);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function matching(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('matching()');
+
+ return parent::matching($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function notMatching(string $assoc, ?callable $builder = null)
+ {
+ $this->_deprecatedMethod('notMatching()');
+
+ return parent::notMatching($assoc, $builder);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function contain($associations, $override = false)
+ {
+ $this->_deprecatedMethod('contain()');
+
+ return parent::contain($associations, $override);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContain(): array
+ {
+ $this->_deprecatedMethod('getContain()');
+
+ return parent::getContain();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function find(string $finder, array $options = [])
+ {
+ $this->_deprecatedMethod('find()');
+
+ return parent::find($finder, $options);
+ }
+}
diff --git a/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php b/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php
index 1fe3cf69d..012c40025 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/ResultSet.php
@@ -29,6 +29,9 @@
* This object is responsible for correctly nesting result keys reported from
* the query, casting each field to the correct type and executing the extra
* queries required for eager loading external associations.
+ *
+ * @template T of \Cake\Datasource\EntityInterface|array
+ * @implements \Cake\Datasource\ResultSetInterface
*/
class ResultSet implements ResultSetInterface
{
@@ -51,7 +54,8 @@ class ResultSet implements ResultSetInterface
/**
* Last record fetched from the statement
*
- * @var object|array
+ * @var \Cake\Datasource\EntityInterface|array
+ * @psalm-var T
*/
protected $_current;
@@ -161,7 +165,7 @@ public function __construct(Query $query, StatementInterface $statement)
{
$repository = $query->getRepository();
$this->_statement = $statement;
- $this->_driver = $query->getConnection()->getDriver();
+ $this->_driver = $query->getConnection()->getDriver($query->getConnectionRole());
$this->_defaultTable = $repository;
$this->_calculateAssociationMap($query);
$this->_hydrate = $query->isHydrationEnabled();
@@ -182,7 +186,8 @@ public function __construct(Query $query, StatementInterface $statement)
*
* Part of Iterator interface.
*
- * @return object|array
+ * @return \Cake\Datasource\EntityInterface|array
+ * @psalm-return T
*/
#[\ReturnTypeWillChange]
public function current()
@@ -276,7 +281,8 @@ public function valid(): bool
*
* This method will also close the underlying statement cursor.
*
- * @return object|array|null
+ * @return \Cake\Datasource\EntityInterface|array|null
+ * @psalm-return T|null
*/
public function first()
{
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Rule/LinkConstraint.php b/app/vendor/cakephp/cakephp/src/ORM/Rule/LinkConstraint.php
index 37fbdf7d0..fe2b1cc76 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Rule/LinkConstraint.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Rule/LinkConstraint.php
@@ -19,6 +19,7 @@
use Cake\Datasource\EntityInterface;
use Cake\ORM\Association;
use Cake\ORM\Table;
+use function Cake\Core\getTypeName;
/**
* Checks whether links to a given association exist / do not exist.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php b/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php
index 8136b6d82..dd6a8ee4e 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/RulesChecker.php
@@ -23,6 +23,8 @@
use Cake\ORM\Rule\LinkConstraint;
use Cake\ORM\Rule\ValidCount;
use Cake\Utility\Inflector;
+use function Cake\Core\getTypeName;
+use function Cake\I18n\__d;
/**
* ORM flavoured rules checker.
diff --git a/app/vendor/cakephp/cakephp/src/ORM/Table.php b/app/vendor/cakephp/cakephp/src/ORM/Table.php
index 1a37af224..b101dcddf 100644
--- a/app/vendor/cakephp/cakephp/src/ORM/Table.php
+++ b/app/vendor/cakephp/cakephp/src/ORM/Table.php
@@ -40,13 +40,21 @@
use Cake\ORM\Exception\MissingEntityException;
use Cake\ORM\Exception\PersistenceFailedException;
use Cake\ORM\Exception\RolledbackTransactionException;
+use Cake\ORM\Query\DeleteQuery;
+use Cake\ORM\Query\InsertQuery;
+use Cake\ORM\Query\SelectQuery;
+use Cake\ORM\Query\UpdateQuery;
use Cake\ORM\Rule\IsUnique;
use Cake\Utility\Inflector;
use Cake\Validation\ValidatorAwareInterface;
use Cake\Validation\ValidatorAwareTrait;
use Exception;
use InvalidArgumentException;
+use ReflectionMethod;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\getTypeName;
+use function Cake\Core\namespaceSplit;
/**
* Represents a single database table.
@@ -515,11 +523,17 @@ public function getConnection(): Connection
public function getSchema(): TableSchemaInterface
{
if ($this->_schema === null) {
- $this->_schema = $this->_initializeSchema(
- $this->getConnection()
- ->getSchemaCollection()
- ->describe($this->getTable())
- );
+ $this->_schema = $this->getConnection()
+ ->getSchemaCollection()
+ ->describe($this->getTable());
+
+ $method = new ReflectionMethod($this, '_initializeSchema');
+ if ($method->getDeclaringClass()->getName() != Table::class) {
+ deprecationWarning(
+ 'Table::_initializeSchema() is deprecated. Override `getSchema()` with a parent call instead.'
+ );
+ $this->_schema = $this->_initializeSchema($this->_schema);
+ }
if (Configure::read('debug')) {
$this->checkAliasLengths();
}
@@ -682,22 +696,34 @@ public function setDisplayField($field)
/**
* Returns the display field.
*
- * @return array|string|null
+ * @return array|string
*/
public function getDisplayField()
{
- if ($this->_displayField === null) {
- $schema = $this->getSchema();
- $this->_displayField = $this->getPrimaryKey();
- foreach (['title', 'name', 'label'] as $field) {
- if ($schema->hasColumn($field)) {
- $this->_displayField = $field;
- break;
- }
+ if ($this->_displayField !== null) {
+ return $this->_displayField;
+ }
+
+ $schema = $this->getSchema();
+ foreach (['title', 'name', 'label'] as $field) {
+ if ($schema->hasColumn($field)) {
+ return $this->_displayField = $field;
}
}
- return $this->_displayField;
+ foreach ($schema->columns() as $column) {
+ $columnSchema = $schema->getColumn($column);
+ if (
+ $columnSchema &&
+ $columnSchema['null'] !== true &&
+ $columnSchema['type'] === 'string' &&
+ !preg_match('/pass|token|secret/i', $column)
+ ) {
+ return $this->_displayField = $column;
+ }
+ }
+
+ return $this->_displayField = $this->getPrimaryKey();
}
/**
@@ -1252,7 +1278,7 @@ public function belongsToMany(string $associated, array $options = []): BelongsT
*/
public function find(string $type = 'all', array $options = []): Query
{
- return $this->callFinder($type, $this->query()->select(), $options);
+ return $this->callFinder($type, $this->selectQuery()->select(), $options);
}
/**
@@ -1697,9 +1723,56 @@ protected function _getFindOrCreateQuery($search): Query
*/
public function query(): Query
{
+ deprecationWarning(
+ 'As of 4.5.0 using query() is deprecated. Instead use `insertQuery()`, ' .
+ '`deleteQuery()`, `selectQuery()` or `updateQuery()`. The query objects ' .
+ 'returned by these methods will emit deprecations that will become fatal errors in 5.0.' .
+ 'See https://book.cakephp.org/4/en/appendices/4-5-migration-guide.html for more information.'
+ );
+
return new Query($this->getConnection(), $this);
}
+ /**
+ * Creates a new DeleteQuery instance for a table.
+ *
+ * @return \Cake\ORM\Query\DeleteQuery
+ */
+ public function deleteQuery(): DeleteQuery
+ {
+ return new DeleteQuery($this->getConnection(), $this);
+ }
+
+ /**
+ * Creates a new InsertQuery instance for a table.
+ *
+ * @return \Cake\ORM\Query\InsertQuery
+ */
+ public function insertQuery(): InsertQuery
+ {
+ return new InsertQuery($this->getConnection(), $this);
+ }
+
+ /**
+ * Creates a new SelectQuery instance for a table.
+ *
+ * @return \Cake\ORM\Query\SelectQuery
+ */
+ public function selectQuery(): SelectQuery
+ {
+ return new SelectQuery($this->getConnection(), $this);
+ }
+
+ /**
+ * Creates a new UpdateQuery instance for a table.
+ *
+ * @return \Cake\ORM\Query\UpdateQuery
+ */
+ public function updateQuery(): UpdateQuery
+ {
+ return new UpdateQuery($this->getConnection(), $this);
+ }
+
/**
* Creates a new Query::subquery() instance for a table.
*
@@ -1716,8 +1789,7 @@ public function subquery(): Query
*/
public function updateAll($fields, $conditions): int
{
- $statement = $this->query()
- ->update()
+ $statement = $this->updateQuery()
->set($fields)
->where($conditions)
->execute();
@@ -1731,8 +1803,7 @@ public function updateAll($fields, $conditions): int
*/
public function deleteAll($conditions): int
{
- $statement = $this->query()
- ->delete()
+ $statement = $this->deleteQuery()
->where($conditions)
->execute();
$statement->closeCursor();
@@ -2072,7 +2143,8 @@ protected function _insert(EntityInterface $entity, array $data)
return false;
}
- $statement = $this->query()->insert(array_keys($data))
+ $statement = $this->insertQuery()
+ ->insert(array_keys($data))
->values($data)
->execute();
@@ -2153,8 +2225,7 @@ protected function _update(EntityInterface $entity, array $data)
throw new InvalidArgumentException($message);
}
- $statement = $this->query()
- ->update()
+ $statement = $this->updateQuery()
->set($data)
->where($primaryKey)
->execute();
@@ -2494,8 +2565,7 @@ protected function _processDelete(EntityInterface $entity, ArrayObject $options)
return $success;
}
- $statement = $this->query()
- ->delete()
+ $statement = $this->deleteQuery()
->where($entity->extract($primaryKey))
->execute();
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Asset.php b/app/vendor/cakephp/cakephp/src/Routing/Asset.php
index 88dee894c..ae8bd3bbe 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Asset.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Asset.php
@@ -19,6 +19,7 @@
use Cake\Core\Configure;
use Cake\Core\Plugin;
use Cake\Utility\Inflector;
+use function Cake\Core\pluginSplit;
/**
* Class for generating asset URLs.
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php b/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php
index 7ea24dde5..448490aaa 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Exception/MissingControllerException.php
@@ -1,8 +1,10 @@
getMessage(),
- $e->getCode()
+ $e->getCode(),
+ $e->getHeaders()
);
} catch (DeprecatedRedirectException $e) {
return new RedirectResponse(
@@ -186,7 +189,10 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
return $handler->handle($request);
}
- $middleware = new MiddlewareQueue($matching);
+ $container = $this->app instanceof ContainerApplicationInterface
+ ? $this->app->getContainer()
+ : null;
+ $middleware = new MiddlewareQueue($matching, $container);
$runner = new Runner();
return $runner->run($middleware, $request, $handler);
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php
index 2444e4029..7122b8aea 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/DashedRoute.php
@@ -31,9 +31,9 @@ class DashedRoute extends Route
* Default values need to be inflected so that they match the inflections that
* match() will create.
*
- * @var bool
+ * @var array|null
*/
- protected $_inflectedDefaults = false;
+ protected $_inflectedDefaults;
/**
* Camelizes the previously dashed plugin route taking into account plugin vendors
@@ -97,12 +97,18 @@ public function parse(string $url, string $method = ''): ?array
public function match(array $url, array $context = []): ?string
{
$url = $this->_dasherize($url);
- if (!$this->_inflectedDefaults) {
- $this->_inflectedDefaults = true;
- $this->defaults = $this->_dasherize($this->defaults);
+ if ($this->_inflectedDefaults === null) {
+ $this->compile();
+ $this->_inflectedDefaults = $this->_dasherize($this->defaults);
}
+ $restore = $this->defaults;
+ try {
+ $this->defaults = $this->_inflectedDefaults;
- return parent::match($url, $context);
+ return parent::match($url, $context);
+ } finally {
+ $this->defaults = $restore;
+ }
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php
index 6adaedc65..4a721724b 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/EntityRoute.php
@@ -18,6 +18,7 @@
use ArrayAccess;
use RuntimeException;
+use function Cake\Core\getTypeName;
/**
* Matches entities to routes
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php b/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php
index fdc552b60..2c819d078 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/InflectedRoute.php
@@ -30,9 +30,9 @@ class InflectedRoute extends Route
* Default values need to be inflected so that they match the inflections that match()
* will create.
*
- * @var bool
+ * @var array|null
*/
- protected $_inflectedDefaults = false;
+ protected $_inflectedDefaults;
/**
* Parses a string URL into an array. If it matches, it will convert the prefix, controller and
@@ -76,12 +76,18 @@ public function parse(string $url, string $method = ''): ?array
public function match(array $url, array $context = []): ?string
{
$url = $this->_underscore($url);
- if (!$this->_inflectedDefaults) {
- $this->_inflectedDefaults = true;
- $this->defaults = $this->_underscore($this->defaults);
+ if ($this->_inflectedDefaults === null) {
+ $this->compile();
+ $this->_inflectedDefaults = $this->_underscore($this->defaults);
}
+ $restore = $this->defaults;
+ try {
+ $this->defaults = $this->_inflectedDefaults;
- return parent::match($url, $context);
+ return parent::match($url, $context);
+ } finally {
+ $this->defaults = $restore;
+ }
}
/**
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php b/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php
index 2315a07f2..15e6c07cb 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Route/Route.php
@@ -19,6 +19,7 @@
use Cake\Http\Exception\BadRequestException;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
+use function Cake\Core\deprecationWarning;
/**
* A single Route used by the Router to connect requests to
diff --git a/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php b/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php
index 25dcfd5eb..4f04e9773 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/RouteBuilder.php
@@ -25,6 +25,7 @@
use Cake\Utility\Inflector;
use InvalidArgumentException;
use RuntimeException;
+use function Cake\Core\getTypeName;
/**
* Provides features for building routes inside scopes.
diff --git a/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php b/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php
index 8f96a5a99..c91e5ba9e 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/RouteCollection.php
@@ -21,6 +21,7 @@
use Cake\Routing\Route\Route;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
/**
* Contains a collection of routes.
@@ -46,6 +47,13 @@ class RouteCollection
*/
protected $_named = [];
+ /**
+ * Routes indexed by static path.
+ *
+ * @var array>
+ */
+ protected $staticPaths = [];
+
/**
* Routes indexed by path prefix.
*
@@ -104,12 +112,17 @@ public function add(Route $route, array $options = []): void
// Index path prefixes (for parsing)
$path = $route->staticPath();
- $this->_paths[$path][] = $route;
$extensions = $route->getExtensions();
if (count($extensions) > 0) {
$this->setExtensions($extensions);
}
+
+ if ($path === $route->template) {
+ $this->staticPaths[$path][] = $route;
+ }
+
+ $this->_paths[$path][] = $route;
}
/**
@@ -119,17 +132,37 @@ public function add(Route $route, array $options = []): void
* @param string $method The HTTP method to use.
* @return array An array of request parameters parsed from the URL.
* @throws \Cake\Routing\Exception\MissingRouteException When a URL has no matching route.
+ * @deprecated 4.5.0 Use parseRequest() instead.
*/
public function parse(string $url, string $method = ''): array
{
- $decoded = urldecode($url);
-
+ deprecationWarning('4.5.0 - Use parseRequest() instead.');
$queryParameters = [];
if (strpos($url, '?') !== false) {
[$url, $qs] = explode('?', $url, 2);
parse_str($qs, $queryParameters);
}
+ $decoded = urldecode($url);
+ if ($decoded !== '/') {
+ $decoded = rtrim($decoded, '/');
+ }
+
+ if (isset($this->staticPaths[$decoded])) {
+ foreach ($this->staticPaths[$decoded] as $route) {
+ $r = $route->parse($url, $method);
+ if ($r === null) {
+ continue;
+ }
+
+ if ($queryParameters) {
+ $r['?'] = $queryParameters;
+ }
+
+ return $r;
+ }
+ }
+
// Sort path segments matching longest paths first.
krsort($this->_paths);
@@ -171,7 +204,33 @@ public function parse(string $url, string $method = ''): array
public function parseRequest(ServerRequestInterface $request): array
{
$uri = $request->getUri();
- $urlPath = urldecode($uri->getPath());
+ $urlPath = $uri->getPath();
+ if (strpos($urlPath, '%') !== false) {
+ // decode urlencoded segments, but don't decode %2f aka /
+ $parts = explode('/', $urlPath);
+ $parts = array_map(
+ fn (string $part) => str_replace('/', '%2f', urldecode($part)),
+ $parts
+ );
+ $urlPath = implode('/', $parts);
+ }
+ if ($urlPath !== '/') {
+ $urlPath = rtrim($urlPath, '/');
+ }
+ if (isset($this->staticPaths[$urlPath])) {
+ foreach ($this->staticPaths[$urlPath] as $route) {
+ $r = $route->parseRequest($request);
+ if ($r === null) {
+ continue;
+ }
+ if ($uri->getQuery()) {
+ parse_str($uri->getQuery(), $queryParameters);
+ $r['?'] = array_merge($r['?'] ?? [], $queryParameters);
+ }
+
+ return $r;
+ }
+ }
// Sort path segments matching longest paths first.
krsort($this->_paths);
@@ -329,6 +388,8 @@ public function match(array $url, array $context): string
/**
* Get all the connected routes as a flat list.
*
+ * Routes will not be returned in the order they were added.
+ *
* @return array<\Cake\Routing\Route\Route>
*/
public function routes(): array
diff --git a/app/vendor/cakephp/cakephp/src/Routing/Router.php b/app/vendor/cakephp/cakephp/src/Routing/Router.php
index 9b4235cc3..d11b2788c 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/Router.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/Router.php
@@ -25,6 +25,7 @@
use ReflectionMethod;
use RuntimeException;
use Throwable;
+use function Cake\Core\deprecationWarning;
/**
* Parses the request URL into controller, action, and parameters. Uses the connected routes
@@ -283,6 +284,7 @@ public static function reload(): void
}
}
static::$_collection = new RouteCollection();
+ static::$_routePaths = [];
}
/**
@@ -401,7 +403,7 @@ protected static function _applyUrlFilters(array $url): array
* - `_port` - Set the port if you need to create links on non-standard ports.
* - `_full` - If true output of `Router::fullBaseUrl()` will be prepended to generated URLs.
* - `#` - Allows you to set URL hash fragments.
- * - `_ssl` - Set to true to convert the generated URL to https, or false to force http.
+ * - `_https` - Set to true to convert the generated URL to https, or false to force http.
* - `_name` - Name of route. If you have setup named routes you can use this key
* to specify it.
*
@@ -449,7 +451,13 @@ public static function url($url = null, bool $full = false): string
}
if (isset($url['_ssl'])) {
- $url['_scheme'] = $url['_ssl'] === true ? 'https' : 'http';
+ deprecationWarning('`_ssl` option is deprecated. Use `_https` instead.');
+ $url['_https'] = $url['_ssl'];
+ unset($url['_ssl']);
+ }
+
+ if (isset($url['_https'])) {
+ $url['_scheme'] = $url['_https'] === true ? 'https' : 'http';
}
if (isset($url['_full']) && $url['_full'] === true) {
@@ -458,7 +466,7 @@ public static function url($url = null, bool $full = false): string
if (isset($url['#'])) {
$frag = '#' . $url['#'];
}
- unset($url['_ssl'], $url['_full'], $url['#']);
+ unset($url['_https'], $url['_full'], $url['#']);
$url = static::_applyUrlFilters($url);
@@ -930,7 +938,9 @@ public static function plugin(string $name, $options = [], $callback = null): vo
}
/**
- * Get the route scopes and their connected routes.
+ * Get the all of the routes currently connected.
+ *
+ * Routes will not always be returned in the order they were defined.
*
* @return array<\Cake\Routing\Route\Route>
*/
@@ -995,7 +1005,7 @@ protected static function unwrapShortString(array $url)
* - Vendor/Cms.Management/Admin/Articles::view
*
* @param string $url Route path in [Plugin.][Prefix/]Controller::action format
- * @return array
+ * @return array
*/
public static function parseRoutePath(string $url): array
{
@@ -1009,24 +1019,52 @@ public static function parseRoutePath(string $url): array
(?[a-z0-9]+)
::
(?[a-z0-9_]+)
+ (?(?:/(?:[a-z][a-z0-9-_]*=)?
+ (?:([a-z0-9-_=]+)|(["\'][^\'"]+[\'"]))
+ )+/?)?
$#ix';
if (!preg_match($regex, $url, $matches)) {
throw new InvalidArgumentException("Could not parse a string route path `{$url}`.");
}
- $defaults = [];
-
+ $defaults = [
+ 'controller' => $matches['controller'],
+ 'action' => $matches['action'],
+ ];
if ($matches['plugin'] !== '') {
$defaults['plugin'] = $matches['plugin'];
}
if ($matches['prefix'] !== '') {
$defaults['prefix'] = $matches['prefix'];
}
- $defaults['controller'] = $matches['controller'];
- $defaults['action'] = $matches['action'];
- static::$_routePaths[$url] = $defaults;
+ if (isset($matches['params']) && $matches['params'] !== '') {
+ $paramsArray = explode('/', trim($matches['params'], '/'));
+ foreach ($paramsArray as $param) {
+ if (strpos($param, '=') !== false) {
+ if (!preg_match('/(?.+?)=(?.*)/', $param, $paramMatches)) {
+ throw new InvalidArgumentException(
+ "Could not parse a key=value from `{$param}` in route path `{$url}`."
+ );
+ }
+ $paramKey = $paramMatches['key'];
+ if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $paramKey)) {
+ throw new InvalidArgumentException(
+ "Param key `{$paramKey}` is not valid in route path `{$url}`."
+ );
+ }
+ $defaults[$paramKey] = trim($paramMatches['value'], '\'"');
+ } else {
+ $defaults[] = $param;
+ }
+ }
+ }
+ // Only cache 200 routes per request. Beyond that we could
+ // be soaking up too much memory.
+ if (count(static::$_routePaths) < 200) {
+ static::$_routePaths[$url] = $defaults;
+ }
return $defaults;
}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/functions.php b/app/vendor/cakephp/cakephp/src/Routing/functions.php
index d43f6b788..310ce6990 100644
--- a/app/vendor/cakephp/cakephp/src/Routing/functions.php
+++ b/app/vendor/cakephp/cakephp/src/Routing/functions.php
@@ -11,30 +11,54 @@
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
- * @since 4.1.0
+ * @since 4.5.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
+// phpcs:disable PSR1.Files.SideEffects
+namespace Cake\Routing;
-use Cake\Routing\Router;
+/**
+ * Convenience wrapper for Router::url().
+ *
+ * @param \Psr\Http\Message\UriInterface|array|string|null $url An array specifying any of the following:
+ * 'controller', 'action', 'plugin' additionally, you can provide routed
+ * elements or query string parameters. If string it can be name any valid url
+ * string or it can be an UriInterface instance.
+ * @param bool $full If true, the full base URL will be prepended to the result.
+ * Default is false.
+ * @return string Full translated URL with base path.
+ * @throws \Cake\Core\Exception\CakeException When the route name is not found
+ * @see \Cake\Routing\Router::url()
+ * @since 4.5.0
+ */
+function url($url = null, bool $full = false): string
+{
+ return Router::url($url, $full);
+}
-if (!function_exists('urlArray')) {
- /**
- * Returns an array URL from a route path string.
- *
- * @param string $path Route path.
- * @param array $params An array specifying any additional parameters.
- * Can be also any special parameters supported by `Router::url()`.
- * @return array URL
- * @see \Cake\Routing\Router::pathUrl()
- */
- function urlArray(string $path, array $params = []): array
- {
- $url = Router::parseRoutePath($path);
- $url += [
- 'plugin' => false,
- 'prefix' => false,
- ];
+/**
+ * Returns an array URL from a route path string.
+ *
+ * @param string $path Route path.
+ * @param array $params An array specifying any additional parameters.
+ * Can be also any special parameters supported by `Router::url()`.
+ * @return array URL
+ * @see \Cake\Routing\Router::pathUrl()
+ */
+function urlArray(string $path, array $params = []): array
+{
+ $url = Router::parseRoutePath($path);
+ $url += [
+ 'plugin' => false,
+ 'prefix' => false,
+ ];
+
+ return $url + $params;
+}
- return $url + $params;
- }
+/**
+ * Include global functions.
+ */
+if (!getenv('CAKE_DISABLE_GLOBAL_FUNCS')) {
+ include 'functions_global.php';
}
diff --git a/app/vendor/cakephp/cakephp/src/Routing/functions_global.php b/app/vendor/cakephp/cakephp/src/Routing/functions_global.php
new file mode 100644
index 000000000..e13958b0c
--- /dev/null
+++ b/app/vendor/cakephp/cakephp/src/Routing/functions_global.php
@@ -0,0 +1,56 @@
+groupBy(function (EventInterface $event): string {
return $event->getName();
})
@@ -111,6 +112,6 @@ public function matches($other): bool
*/
public function toString(): string
{
- return 'was fired with ' . $this->_dataKey . ' matching ' . (string)$this->_dataValue;
+ return "was fired with `{$this->_dataKey}` matching `" . json_encode($this->_dataValue) . '`';
}
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php
index 0522f86cd..2edbec970 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieEquals.php
@@ -55,7 +55,7 @@ public function __construct(?Response $response, string $cookieName)
*/
public function matches($other): bool
{
- $cookie = $this->response->getCookie($this->cookieName);
+ $cookie = $this->readCookie($this->cookieName);
return $cookie !== null && $cookie['value'] === $other;
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieSet.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieSet.php
index 370c40c6d..bd31234f4 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieSet.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/CookieSet.php
@@ -35,7 +35,7 @@ class CookieSet extends ResponseBase
*/
public function matches($other): bool
{
- $cookie = $this->response->getCookie($other);
+ $cookie = $this->readCookie($other);
return $cookie !== null && $cookie['value'] !== '';
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php
index c17f9956d..5b43b0124 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Constraint/Response/ResponseBase.php
@@ -15,6 +15,7 @@
*/
namespace Cake\TestSuite\Constraint\Response;
+use Cake\Http\Cookie\CookieCollection;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\Constraint\Constraint;
use Psr\Http\Message\ResponseInterface;
@@ -54,4 +55,24 @@ protected function _getBodyAsString(): string
{
return (string)$this->response->getBody();
}
+
+ /**
+ * Read a cookie from either the response cookie collection,
+ * or headers
+ *
+ * @param string $name The name of the cookie you want to read.
+ * @return array|null Null if the cookie does not exist, array with `value` as the only key.
+ */
+ protected function readCookie(string $name): ?array
+ {
+ if (method_exists($this->response, 'getCookie')) {
+ return $this->response->getCookie($name);
+ }
+ $cookies = CookieCollection::createFromHeader($this->response->getHeader('Set-Cookie'));
+ if (!$cookies->has($name)) {
+ return null;
+ }
+
+ return $cookies->get($name)->toArray();
+ }
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/ContainerStubTrait.php b/app/vendor/cakephp/cakephp/src/TestSuite/ContainerStubTrait.php
index 7e564fc3d..8cd3f99bf 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/ContainerStubTrait.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/ContainerStubTrait.php
@@ -1,6 +1,10 @@
*/
$className = $fixture;
- /** @psalm-suppress PossiblyFalseArgument */
$name = preg_replace('/Fixture\z/', '', substr(strrchr($fixture, '\\'), 1));
}
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/SchemaLoader.php b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/SchemaLoader.php
index 3a97b1bd6..5e200f207 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/SchemaLoader.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/SchemaLoader.php
@@ -92,12 +92,58 @@ public function loadSqlFiles(
}
/**
- * Load and apply CakePHP-specific schema file.
+ * Load and apply CakePHP schema file.
+ *
+ * This method will process the array returned by `$file` and treat
+ * the contents as a list of table schema.
+ *
+ * An example table is:
+ *
+ * ```
+ * return [
+ * 'articles' => [
+ * 'columns' => [
+ * 'id' => [
+ * 'type' => 'integer',
+ * ],
+ * 'author_id' => [
+ * 'type' => 'integer',
+ * 'null' => true,
+ * ],
+ * 'title' => [
+ * 'type' => 'string',
+ * 'null' => true,
+ * ],
+ * 'body' => 'text',
+ * 'published' => [
+ * 'type' => 'string',
+ * 'length' => 1,
+ * 'default' => 'N',
+ * ],
+ * ],
+ * 'constraints' => [
+ * 'primary' => [
+ * 'type' => 'primary',
+ * 'columns' => [
+ * 'id',
+ * ],
+ * ],
+ * ],
+ * ],
+ * ];
+ * ```
+ *
+ * This schema format can be useful for plugins that want to include
+ * tables to test against but don't need to include production
+ * ready schema via migrations. Applications should favour using migrations
+ * or SQL dump files over this format for ease of maintenance.
+ *
+ * A more complete example can be found in `tests/schema.php`.
*
* @param string $file Schema file
* @param string $connectionName Connection name
+ * @throws \InvalidArgumentException For missing table name(s).
* @return void
- * @internal
*/
public function loadInternalFile(string $file, string $connectionName = 'test'): void
{
@@ -112,8 +158,15 @@ public function loadInternalFile(string $file, string $connectionName = 'test'):
$connection = ConnectionManager::get($connectionName);
$connection->disableConstraints(function ($connection) use ($tables) {
- foreach ($tables as $table) {
- $schema = new TableSchema($table['table'], $table['columns']);
+ foreach ($tables as $tableName => $table) {
+ $name = $table['table'] ?? $tableName;
+ if (!is_string($name)) {
+ throw new InvalidArgumentException(
+ sprintf('`%s` is not a valid table name. Either use a string key for the table definition'
+ . '(`\'articles\' => [...]`) or define the `table` key in the table definition.', $name)
+ );
+ }
+ $schema = new TableSchema($name, $table['columns']);
if (isset($table['indexes'])) {
foreach ($table['indexes'] as $key => $index) {
$schema->addIndex($key, $index);
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php
index a4f0fde86..7eefb8ac4 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php
@@ -26,6 +26,7 @@
use Cake\ORM\Locator\LocatorAwareTrait;
use Cake\Utility\Inflector;
use Exception;
+use function Cake\Core\namespaceSplit;
/**
* Cake TestFixture is responsible for building and destroying tables to be used
@@ -335,7 +336,8 @@ public function insert(ConnectionInterface $connection)
{
if (!empty($this->records)) {
[$fields, $values, $types] = $this->_getRecords();
- $query = $connection->newQuery()
+ /** @var \Cake\Database\Connection $connection */
+ $query = $connection->insertQuery()
->insert($fields, $types)
->into($this->sourceName());
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/HttpClientTrait.php b/app/vendor/cakephp/cakephp/src/TestSuite/HttpClientTrait.php
index c20b154db..0bafe7e65 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/HttpClientTrait.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/HttpClientTrait.php
@@ -1,6 +1,10 @@
$query,
'REQUEST_URI' => $url,
];
- if (!empty($hostInfo['ssl'])) {
+ if (!empty($hostInfo['https'])) {
$env['HTTPS'] = 'on';
}
if (isset($hostInfo['host'])) {
@@ -728,7 +728,7 @@ protected function _url(string $url): array
$hostData['host'] = $uri->getHost();
}
if ($uri->getScheme()) {
- $hostData['ssl'] = $uri->getScheme() === 'https';
+ $hostData['https'] = $uri->getScheme() === 'https';
}
return [$path, $query, $hostData];
@@ -1248,6 +1248,22 @@ public function assertCookie($expected, string $name, string $message = ''): voi
$this->assertThat($expected, new CookieEquals($this->_response, $name), $verboseMessage);
}
+ /**
+ * Asserts that a cookie is set.
+ *
+ * Useful when you're working with cookies that have obfuscated values
+ * but the cookie being set is important.
+ *
+ * @param string $name The cookie name.
+ * @param string $message The failure message that will be appended to the generated message.
+ * @return void
+ */
+ public function assertCookieIsSet(string $name, string $message = ''): void
+ {
+ $verboseMessage = $this->extractVerboseMessage($message);
+ $this->assertThat($name, new CookieSet($this->_response), $verboseMessage);
+ }
+
/**
* Asserts a cookie has not been set in the response
*
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php b/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php
index e598b17f4..d386817d2 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/LegacyCommandRunner.php
@@ -1,6 +1,10 @@
_capturedError = null;
+ set_error_handler(
+ function (int $code, string $description, string $file, int $line) {
+ $trace = Debugger::trace(['start' => 1, 'format' => 'points']);
+ $this->_capturedError = new PhpError($code, $description, $file, $line, $trace);
+
+ return true;
+ },
+ $errorLevel
+ );
+
+ try {
+ $callable();
+ } finally {
+ restore_error_handler();
+ error_reporting($default);
+ }
+ if ($this->_capturedError === null) {
+ $this->fail('No error was captured');
+ }
+ /** @var \Cake\Error\PhpError $this->_capturedError */
+ return $this->_capturedError;
+ }
+
/**
* Helper method for check deprecation methods
*
@@ -208,9 +256,6 @@ public function deprecated(callable $callable): void
/** @var bool $deprecation */
$deprecation = false;
- /**
- * @psalm-suppress InvalidArgument
- */
$previousHandler = set_error_handler(
function ($code, $message, $file, $line, $context = null) use (&$previousHandler, &$deprecation): bool {
if ($code == E_USER_DEPRECATED) {
@@ -763,7 +808,6 @@ public function assertHtml(array $expected, string $string, bool $fullDebug = fa
continue;
}
foreach ($tags as $tag => $attributes) {
- /** @psalm-suppress PossiblyFalseArgument */
$regex[] = [
sprintf('Open %s tag', $tag),
sprintf('[\s]*<%s', preg_quote($tag, '/')),
@@ -810,7 +854,6 @@ public function assertHtml(array $expected, string $string, bool $fullDebug = fa
'attrs' => $attrs,
];
}
- /** @psalm-suppress PossiblyFalseArgument */
$regex[] = [
sprintf('End %s tag', $tag),
'[\s]*\/?[\s]*>[\n\r]*',
@@ -833,7 +876,6 @@ public function assertHtml(array $expected, string $string, bool $fullDebug = fa
}
// If 'attrs' is not present then the array is just a regular int-offset one
- /** @psalm-suppress PossiblyUndefinedArrayOffset */
[$description, $expressions, $itemNum] = $assertion;
$expression = '';
foreach ((array)$expressions as $expression) {
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/TestListenerTrait.php b/app/vendor/cakephp/cakephp/src/TestSuite/TestListenerTrait.php
index 440530d7d..f51e74590 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/TestListenerTrait.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/TestListenerTrait.php
@@ -22,6 +22,9 @@
use PHPUnit\Framework\Warning;
use Throwable;
+// phpcs:disable
+deprecationWarning('4.5.0 - TestListenerTrait is deprecated, as PHPUnit is removing support for listeners.');
+
/**
* Implements empty default methods for PHPUnit\Framework\TestListener.
*/
diff --git a/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php b/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php
index e5a18c215..eb96dffe9 100644
--- a/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php
+++ b/app/vendor/cakephp/cakephp/src/TestSuite/TestSuite.php
@@ -21,6 +21,7 @@
use Cake\Filesystem\Filesystem;
use PHPUnit\Framework\TestSuite as BaseTestSuite;
use SplFileInfo;
+use function Cake\Core\deprecationWarning;
/**
* A class to contain test cases and run them with shared fixtures
@@ -35,6 +36,7 @@ class TestSuite extends BaseTestSuite
*/
public function addTestDirectory(string $directory = '.'): void
{
+ deprecationWarning('4.5.0 - TestSuite is deprecated as PHPunit is removing support for testsuites.');
$fs = new Filesystem();
$files = $fs->find($directory, '/\.php$/');
foreach ($files as $file => $fileInfo) {
@@ -50,6 +52,7 @@ public function addTestDirectory(string $directory = '.'): void
*/
public function addTestDirectoryRecursive(string $directory = '.'): void
{
+ deprecationWarning('4.5.0 - TestSuite is deprecated as PHPunit is removing support for testsuites.');
$fs = new Filesystem();
$files = $fs->findRecursive($directory, function (SplFileInfo $current) {
$file = $current->getFilename();
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Hash.php b/app/vendor/cakephp/cakephp/src/Utility/Hash.php
index 782f2c5ca..32781929f 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/Hash.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/Hash.php
@@ -336,7 +336,10 @@ public static function insert(array $data, string $path, $values = null): array
foreach ($data as $k => $v) {
if (static::_matchToken($k, $token)) {
- if (!$conditions || static::_matches($v, $conditions)) {
+ if (
+ !$conditions ||
+ ((is_array($v) || $v instanceof ArrayAccess) && static::_matches($v, $conditions))
+ ) {
$data[$k] = $nextPath
? static::insert($v, $nextPath, $values)
: array_merge($v, (array)$values);
@@ -1154,10 +1157,11 @@ public static function mergeDiff(array $data, array $compare): array
*
* @param array $data List to normalize
* @param bool $assoc If true, $data will be converted to an associative array.
+ * @param mixed $default The default value to use when a top level numeric key is converted to associative form.
* @return array
* @link https://book.cakephp.org/4/en/core-libraries/hash.html#Cake\Utility\Hash::normalize
*/
- public static function normalize(array $data, bool $assoc = true): array
+ public static function normalize(array $data, bool $assoc = true, $default = null): array
{
$keys = array_keys($data);
$count = count($keys);
@@ -1175,7 +1179,7 @@ public static function normalize(array $data, bool $assoc = true): array
$newList = [];
for ($i = 0; $i < $count; $i++) {
if (is_int($keys[$i])) {
- $newList[$data[$keys[$i]]] = null;
+ $newList[$data[$keys[$i]]] = $default;
} else {
$newList[$keys[$i]] = $data[$keys[$i]];
}
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Inflector.php b/app/vendor/cakephp/cakephp/src/Utility/Inflector.php
index 9cb8c1f44..8abcd079d 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/Inflector.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/Inflector.php
@@ -464,7 +464,7 @@ public static function delimit(string $string, string $delimiter = '_'): string
}
/**
- * Returns corresponding table name for given model $className. ("people" for the model class "Person").
+ * Returns corresponding table name for given model $className. ("people" for the class name "Person").
*
* @param string $className Name of class to get database table name for
* @return string Name of the database table for given class
@@ -483,7 +483,7 @@ public static function tableize(string $className): string
}
/**
- * Returns Cake model class name ("Person" for the database table "people".) for given database table.
+ * Returns a singular, CamelCase inflection for given database table. ("Person" for the table name "people")
*
* @param string $tableName Name of database table to get class name for
* @return string Class name
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Text.php b/app/vendor/cakephp/cakephp/src/Utility/Text.php
index 95cf22c9e..7116b0dec 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/Text.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/Text.php
@@ -19,6 +19,8 @@
use Cake\Core\Exception\CakeException;
use InvalidArgumentException;
use Transliterator;
+use function Cake\Core\deprecationWarning;
+use function Cake\I18n\__d;
/**
* Text handling methods.
diff --git a/app/vendor/cakephp/cakephp/src/Utility/Xml.php b/app/vendor/cakephp/cakephp/src/Utility/Xml.php
index 069177af4..53ddfbda7 100644
--- a/app/vendor/cakephp/cakephp/src/Utility/Xml.php
+++ b/app/vendor/cakephp/cakephp/src/Utility/Xml.php
@@ -475,7 +475,6 @@ protected static function _toArray(SimpleXMLElement $xml, array &$parentData, st
}
foreach ($xml->children($namespace, true) as $child) {
- /** @psalm-suppress PossiblyNullArgument */
static::_toArray($child, $data, $namespace, $namespaces);
}
}
diff --git a/app/vendor/cakephp/cakephp/src/Validation/Validation.php b/app/vendor/cakephp/cakephp/src/Validation/Validation.php
index 6ca684f3a..043347bfa 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/Validation.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/Validation.php
@@ -25,6 +25,7 @@
use NumberFormatter;
use Psr\Http\Message\UploadedFileInterface;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
/**
* Validation Class. Used for validation of model data
diff --git a/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php b/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php
index a16ab6b6a..69808d138 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/ValidationSet.php
@@ -25,6 +25,9 @@
/**
* ValidationSet object. Holds all validation rules for a field and exposes
* methods to dynamically add or remove validation rules
+ *
+ * @template-implements \ArrayAccess
+ * @template-implements \IteratorAggregate
*/
class ValidationSet implements ArrayAccess, IteratorAggregate, Countable
{
diff --git a/app/vendor/cakephp/cakephp/src/Validation/Validator.php b/app/vendor/cakephp/cakephp/src/Validation/Validator.php
index e968a4c96..51764b486 100644
--- a/app/vendor/cakephp/cakephp/src/Validation/Validator.php
+++ b/app/vendor/cakephp/cakephp/src/Validation/Validator.php
@@ -23,6 +23,9 @@
use IteratorAggregate;
use Psr\Http\Message\UploadedFileInterface;
use Traversable;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\getTypeName;
+use function Cake\I18n\__d;
/**
* Validator object encapsulates all methods related to data validations for a model
@@ -31,6 +34,8 @@
* Implements ArrayAccess to easily modify rules in the set
*
* @link https://book.cakephp.org/4/en/core-libraries/validation.html
+ * @template-implements \ArrayAccess
+ * @template-implements \IteratorAggregate
*/
class Validator implements ArrayAccess, IteratorAggregate, Countable
{
@@ -193,7 +198,7 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
*/
public function __construct()
{
- $this->_useI18n = function_exists('__d');
+ $this->_useI18n = function_exists('\Cake\I18n\__d');
$this->_providers = self::$_defaultProviders;
}
@@ -2349,8 +2354,30 @@ public function integer(string $field, ?string $message = null, $when = null)
* @see \Cake\Validation\Validation::isArray()
* @return $this
*/
+ public function array(string $field, ?string $message = null, $when = null)
+ {
+ $extra = array_filter(['on' => $when, 'message' => $message]);
+
+ return $this->add($field, 'array', $extra + [
+ 'rule' => 'isArray',
+ ]);
+ }
+
+ /**
+ * Add a validation rule to ensure that a field contains an array.
+ *
+ * @param string $field The field you want to apply the rule to.
+ * @param string|null $message The error message when the rule fails.
+ * @param callable|string|null $when Either 'create' or 'update' or a callable that returns
+ * true when the validation rule should be applied.
+ * @see \Cake\Validation\Validation::isArray()
+ * @return $this
+ * @deprecated 4.5.0 Use Validator::array() instead.
+ */
public function isArray(string $field, ?string $message = null, $when = null)
{
+ deprecationWarning('`Validator::isArray()` is deprecated, use `Validator::array()` instead');
+
$extra = array_filter(['on' => $when, 'message' => $message]);
return $this->add($field, 'isArray', $extra + [
diff --git a/app/vendor/cakephp/cakephp/src/View/Cell.php b/app/vendor/cakephp/cakephp/src/View/Cell.php
index 49cf528b5..9908a74f2 100644
--- a/app/vendor/cakephp/cakephp/src/View/Cell.php
+++ b/app/vendor/cakephp/cakephp/src/View/Cell.php
@@ -245,7 +245,6 @@ protected function _cacheConfig(string $action, ?string $template = null): array
return $default;
}
- /** @psalm-suppress PossiblyFalseOperand */
return $this->_cache + $default;
}
diff --git a/app/vendor/cakephp/cakephp/src/View/CellTrait.php b/app/vendor/cakephp/cakephp/src/View/CellTrait.php
index 5252c98c9..78d75aacc 100644
--- a/app/vendor/cakephp/cakephp/src/View/CellTrait.php
+++ b/app/vendor/cakephp/cakephp/src/View/CellTrait.php
@@ -19,6 +19,7 @@
use Cake\Core\App;
use Cake\Utility\Inflector;
use Cake\View\Exception\MissingCellException;
+use function Cake\Core\pluginSplit;
/**
* Provides cell() method for usage in Controller and View classes.
diff --git a/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellTemplateException.php b/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellTemplateException.php
index 9a9a54373..b276c0f80 100644
--- a/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellTemplateException.php
+++ b/app/vendor/cakephp/cakephp/src/View/Exception/MissingCellTemplateException.php
@@ -56,7 +56,7 @@ public function __construct(
* Get the passed in attributes
*
* @return array
- * @psalm-return array{name: string, file: string, paths: array}
+ * @psalm-return array{name: string, file: string, paths: array}
*/
public function getAttributes(): array
{
diff --git a/app/vendor/cakephp/cakephp/src/View/Exception/MissingTemplateException.php b/app/vendor/cakephp/cakephp/src/View/Exception/MissingTemplateException.php
index 2cd422e04..cf50c7a22 100644
--- a/app/vendor/cakephp/cakephp/src/View/Exception/MissingTemplateException.php
+++ b/app/vendor/cakephp/cakephp/src/View/Exception/MissingTemplateException.php
@@ -87,7 +87,7 @@ public function formatMessage(): string
* Get the passed in attributes
*
* @return array
- * @psalm-return array{file: string, paths: array}
+ * @psalm-return array{file: string, paths: array}
*/
public function getAttributes(): array
{
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/ArrayContext.php b/app/vendor/cakephp/cakephp/src/View/Form/ArrayContext.php
index 8271c92b9..1e197569e 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/ArrayContext.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/ArrayContext.php
@@ -17,6 +17,8 @@
namespace Cake\View\Form;
use Cake\Utility\Hash;
+use function Cake\Core\deprecationWarning;
+use function Cake\I18n\__d;
/**
* Provides a basic array based context provider for FormHelper.
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php b/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php
index d24fa3de9..482fa85d2 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/ContextFactory.php
@@ -21,6 +21,7 @@
use Cake\Form\Form;
use Cake\Http\ServerRequest;
use RuntimeException;
+use function Cake\Core\getTypeName;
/**
* Factory for getting form context instance based on provided data.
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/EntityContext.php b/app/vendor/cakephp/cakephp/src/View/Form/EntityContext.php
index 87e2ce4e1..728ade06e 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/EntityContext.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/EntityContext.php
@@ -27,6 +27,8 @@
use Cake\Validation\Validator;
use RuntimeException;
use Traversable;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\namespaceSplit;
/**
* Provides a form context around a single entity and its relations.
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php b/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php
index 007e2dcb1..731cc045e 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/FormContext.php
@@ -19,6 +19,7 @@
use Cake\Core\Exception\CakeException;
use Cake\Form\Form;
use Cake\Utility\Hash;
+use function Cake\Core\deprecationWarning;
/**
* Provides a context provider for {@link \Cake\Form\Form} instances.
diff --git a/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php b/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php
index 5adf5639e..8defaa128 100644
--- a/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php
+++ b/app/vendor/cakephp/cakephp/src/View/Form/NullContext.php
@@ -16,6 +16,8 @@
*/
namespace Cake\View\Form;
+use function Cake\Core\deprecationWarning;
+
/**
* Provides a context provider that does nothing.
*
diff --git a/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php b/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php
index 2b298118d..77bc7451c 100644
--- a/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php
+++ b/app/vendor/cakephp/cakephp/src/View/Helper/FormHelper.php
@@ -30,6 +30,10 @@
use Cake\View\Widget\WidgetLocator;
use InvalidArgumentException;
use RuntimeException;
+use function Cake\Core\deprecationWarning;
+use function Cake\Core\h;
+use function Cake\I18n\__;
+use function Cake\I18n\__d;
/**
* Form helper library.
@@ -113,9 +117,9 @@ class FormHelper extends Helper
// Wrapper content used to hide other content.
'hiddenBlock' => '