From 75ef1341ebbc102ce5440338414c7a6aa2679645 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 30 Sep 2021 17:39:49 -0600 Subject: [PATCH 01/21] Added new HTTP\Client class for more general use --- system/blueprints/config/system.yaml | 76 ++++++++++-- system/config/system.yaml | 12 +- system/src/Grav/Common/GPM/Response.php | 144 +---------------------- system/src/Grav/Common/HTTP/Client.php | 125 ++++++++++++++++++++ system/src/Grav/Common/HTTP/Response.php | 96 +++++++++++++++ 5 files changed, 295 insertions(+), 158 deletions(-) create mode 100644 system/src/Grav/Common/HTTP/Client.php create mode 100644 system/src/Grav/Common/HTTP/Response.php diff --git a/system/blueprints/config/system.yaml b/system/blueprints/config/system.yaml index dffe099020..43679a11e3 100644 --- a/system/blueprints/config/system.yaml +++ b/system/blueprints/config/system.yaml @@ -1446,6 +1446,10 @@ form: title: PLUGIN_ADMIN.ADVANCED underline: true + gpm_section: + type: section + title: PLUGIN_ADMIN.GPM_SECTION + gpm.releases: type: toggle label: PLUGIN_ADMIN.GPM_RELEASES @@ -1455,14 +1459,23 @@ form: stable: PLUGIN_ADMIN.STABLE testing: PLUGIN_ADMIN.TESTING - gpm.proxy_url: - type: text - size: medium - placeholder: "e.g. 127.0.0.1:3128" - label: PLUGIN_ADMIN.PROXY_URL - help: PLUGIN_ADMIN.PROXY_URL_HELP + gpm.official_gpm_only: + type: toggle + label: PLUGIN_ADMIN.GPM_OFFICIAL_ONLY + highlight: 1 + help: PLUGIN_ADMIN.GPM_OFFICIAL_ONLY_HELP + options: + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + default: true + validate: + type: bool - gpm.method: + http_section: + type: section + title: PLUGIN_ADMIN.HTTP_SECTION + + http.method: type: toggle label: PLUGIN_ADMIN.GPM_METHOD highlight: auto @@ -1472,11 +1485,10 @@ form: fopen: PLUGIN_ADMIN.FOPEN curl: PLUGIN_ADMIN.CURL - gpm.official_gpm_only: + http.enable_proxy: type: toggle - label: PLUGIN_ADMIN.GPM_OFFICIAL_ONLY + label: PLUGIN_ADMIN.SSL_ENABLE_PROXY highlight: 1 - help: PLUGIN_ADMIN.GPM_OFFICIAL_ONLY_HELP options: 1: PLUGIN_ADMIN.YES 0: PLUGIN_ADMIN.NO @@ -1484,17 +1496,55 @@ form: validate: type: bool - gpm.verify_peer: + http.proxy_url: + type: text + size: medium + placeholder: "e.g. 127.0.0.1:3128" + label: PLUGIN_ADMIN.PROXY_URL + help: PLUGIN_ADMIN.PROXY_URL_HELP + + http.proxy_cert_path: + type: text + size: medium + placeholder: "e.g. /Users/bob/certs/" + label: PLUGIN_ADMIN.PROXY_CERT + help: PLUGIN_ADMIN.PROXY_CERT_HELP + + http.verify_peer: type: toggle - label: PLUGIN_ADMIN.GPM_VERIFY_PEER + label: PLUGIN_ADMIN.SSL_VERIFY_PEER highlight: 1 - help: PLUGIN_ADMIN.GPM_VERIFY_PEER_HELP + help: PLUGIN_ADMIN.SSL_VERIFY_PEER_HELP options: 1: PLUGIN_ADMIN.YES 0: PLUGIN_ADMIN.NO validate: type: bool + http.verify_host: + type: toggle + label: PLUGIN_ADMIN.SSL_VERIFY_HOST + highlight: 1 + help: PLUGIN_ADMIN.SSL_VERIFY_HOST_HELP + options: + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + validate: + type: bool + + http.concurrent_connections: + type: number + size: x-small + label: PLUGIN_ADMIN.HTTP_CONNECTIONS + help: PLUGIN_ADMIN.HTTP_CONNECTIONS_HELP + validate: + min: 1 + max: 20 + + misc_section: + type: section + title: PLUGIN_ADMIN.MISC_SECTION + reverse_proxy_setup: type: toggle label: PLUGIN_ADMIN.REVERSE_PROXY diff --git a/system/config/system.yaml b/system/config/system.yaml index fb5f391f4a..140a95246d 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -184,11 +184,17 @@ session: gpm: releases: stable # Set to either 'stable' or 'testing' - proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128) - method: 'auto' # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL - verify_peer: true # Sometimes on some systems (Windows most commonly) GPM is unable to connect because the SSL certificate cannot be verified. Disabling this setting might help. official_gpm_only: true # By default GPM direct-install will only allow URLs via the official GPM proxy to ensure security +http: + method: auto # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL + enable_proxy: false # Enabled proxy server + proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128) + proxy_cert_path: # Local path to proxy certificate folder containing pem files + concurrent_connections: 5 # Concurrent HTTP connections when multiplexing + verify_peer: true # Enable/Disable SSL verification of peer certificates + verify_host: true # Enable/Disable SSL verification of host certificates + accounts: type: regular # EXPERIMENTAL: Account type: regular or flex storage: file # EXPERIMENTAL: Flex storage type: file or folder diff --git a/system/src/Grav/Common/GPM/Response.php b/system/src/Grav/Common/GPM/Response.php index 47cef7c096..98654b6a1b 100644 --- a/system/src/Grav/Common/GPM/Response.php +++ b/system/src/Grav/Common/GPM/Response.php @@ -1,143 +1,3 @@ 'Grav CMS' - ]; - - /** - * Makes a request to the URL by using the preferred method - * - * @param string $uri URL to call - * @param array $overrides An array of parameters for both `curl` and `fopen` - * @param callable|null $callback Either a function or callback in array notation - * @return string The response of the request - * @throws TransportExceptionInterface - */ - public static function get($uri = '', $overrides = [], $callback = null) - { - if (empty($uri)) { - throw new TransportException('missing URI'); - } - - // check if this function is available, if so use it to stop any timeouts - try { - if (Utils::functionExists('set_time_limit')) { - @set_time_limit(0); - } - } catch (Exception $e) { - } - - $config = Grav::instance()['config']; - $referer = defined('GRAV_CLI') ? 'grav_cli' : Grav::instance()['uri']->rootUrl(true); - $options = new HttpOptions(); - - // Set default Headers - $options->setHeaders(array_merge([ 'Referer' => $referer ], self::$headers)); - - // Disable verify Peer if required - $verify_peer = $config->get('system.gpm.verify_peer', true); - if ($verify_peer !== true) { - $options->verifyPeer($verify_peer); - } - - // Set proxy url if provided - $proxy_url = $config->get('system.gpm.proxy_url', false); - if ($proxy_url) { - $options->setProxy($proxy_url); - } - - // Use callback if provided - if ($callback) { - self::$callback = $callback; - $options->setOnProgress([Response::class, 'progress']); - } - - $preferred_method = $config->get('system.gpm.method', 'auto'); - - $settings = array_merge_recursive($options->toArray(), $overrides); - - switch ($preferred_method) { - case 'curl': - $client = new CurlHttpClient($settings); - break; - case 'fopen': - case 'native': - $client = new NativeHttpClient($settings); - break; - default: - $client = HttpClient::create($settings); - } - - $response = $client->request('GET', $uri); - - return $response->getContent(); - } - - - /** - * Is this a remote file or not - * - * @param string $file - * @return bool - */ - public static function isRemote($file) - { - return (bool) filter_var($file, FILTER_VALIDATE_URL); - } - - /** - * Progress normalized for cURL and Fopen - * Accepts a variable length of arguments passed in by stream method - * - * @return void - */ - public static function progress(int $bytes_transferred, int $filesize, array $info) - { - - if ($bytes_transferred > 0) { - $percent = $filesize <= 0 ? 0 : (int)(($bytes_transferred * 100) / $filesize); - - $progress = [ - 'code' => $info['http_code'], - 'filesize' => $filesize, - 'transferred' => $bytes_transferred, - 'percent' => $percent < 100 ? $percent : 100 - ]; - - if (self::$callback !== null) { - call_user_func(self::$callback, $progress); - } - } - } -} +// Create alias for the deprecated class. +class_alias(\Grav\Common\HTTP\Response::class, \Grav\Common\GPM\Response::class); diff --git a/system/src/Grav/Common/HTTP/Client.php b/system/src/Grav/Common/HTTP/Client.php new file mode 100644 index 0000000000..d0d524dfb2 --- /dev/null +++ b/system/src/Grav/Common/HTTP/Client.php @@ -0,0 +1,125 @@ + 'Grav CMS' + ]; + + public static function getClient(array $overrides = [], int $connections = 6, callable $callback = null): HttpClientInterface + { + $config = Grav::instance()['config']; + $options = static::getOptions(); + + // Use callback if provided + if ($callback) { + self::$callback = $callback; + $options->setOnProgress([Response::class, 'progress']); + } + + $settings = array_merge($options->toArray(), $overrides); + $preferred_method = $config->get('system.http.method', $config->get('system.gpm.method', 'auto')); + + switch ($preferred_method) { + case 'curl': + $client = new CurlHttpClient($settings, $connections); + break; + case 'fopen': + case 'native': + $client = new NativeHttpClient($settings, $connections); + break; + default: + $client = HttpClient::create($settings, $connections); + } + + return $client; + } + + /** + * Get HTTP Options + * + * @return HttpOptions + */ + public static function getOptions(): HttpOptions + { + $config = Grav::instance()['config']; + $referer = defined('GRAV_CLI') ? 'grav_cli' : Grav::instance()['uri']->rootUrl(true); + + $options = new HttpOptions(); + + // Set default Headers + $options->setHeaders(array_merge([ 'Referer' => $referer ], self::$headers)); + + // Disable verify Peer if required + $verify_peer = $config->get('system.http.verify_peer', $config->get('system.gpm.verify_peer', null)); + if ($verify_peer !== null) { + $options->verifyPeer($verify_peer); + } + + // Disable verify Host if required + $verify_host = $config->get('system.http.verify_host', null); + if ($verify_host !== null) { + $options->verifyHost($verify_host); + } + + if ($config->get('system.http.enable_proxy', true)) { + // Set proxy url if provided + $proxy_url = $config->get('system.http.proxy_url', $config->get('system.gpm.proxy_url', null)); + if ($proxy_url !== null) { + $options->setProxy($proxy_url); + } + + // Certificate + $proxy_cert = $config->get('system.http.proxy_cert_path', null); + if ($proxy_cert !== null) { + $options->setCaPath($proxy_cert); + } + } + + return $options; + } + + /** + * Progress normalized for cURL and Fopen + * Accepts a variable length of arguments passed in by stream method + * + * @return void + */ + public static function progress(int $bytes_transferred, int $filesize, array $info) + { + + if ($bytes_transferred > 0) { + $percent = $filesize <= 0 ? 0 : (int)(($bytes_transferred * 100) / $filesize); + + $progress = [ + 'code' => $info['http_code'], + 'filesize' => $filesize, + 'transferred' => $bytes_transferred, + 'percent' => $percent < 100 ? $percent : 100 + ]; + + if (self::$callback !== null) { + call_user_func(self::$callback, $progress); + } + } + } +} diff --git a/system/src/Grav/Common/HTTP/Response.php b/system/src/Grav/Common/HTTP/Response.php new file mode 100644 index 0000000000..4a0513667c --- /dev/null +++ b/system/src/Grav/Common/HTTP/Response.php @@ -0,0 +1,96 @@ +getContent(); + } + + + /** + * Makes a request to the URL by using the preferred method + * + * @param string $method method to call such as GET, PUT, etc + * @param string $uri URL to call + * @param array $overrides An array of parameters for both `curl` and `fopen` + * @param callable|null $callback Either a function or callback in array notation + * @return ResponseInterface + * @throws TransportExceptionInterface + */ + public static function request(string $method, string $uri, array $overrides = [], callable $callback = null): ResponseInterface + { + if (empty($method)) { + throw new TransportException('missing method (GET, PUT, etc.)'); + } + + if (empty($uri)) { + throw new TransportException('missing URI'); + } + + // check if this function is available, if so use it to stop any timeouts + try { + if (Utils::functionExists('set_time_limit')) { + @set_time_limit(0); + } + } catch (Exception $e) {} + + $client = Client::getClient($overrides, 6, $callback); + + return $client->request($method, $uri); + } + + + /** + * Is this a remote file or not + * + * @param string $file + * @return bool + */ + public static function isRemote($file): bool + { + return (bool) filter_var($file, FILTER_VALIDATE_URL); + } + + +} From 07bd1e03d0b9321d8f8d382d08825d98e89ff6dc Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Fri, 1 Oct 2021 11:42:41 -0600 Subject: [PATCH 02/21] Better backwards compatibility --- system/blueprints/config/system.yaml | 2 +- system/config/system.yaml | 2 +- system/src/Grav/Common/HTTP/Client.php | 23 ++++++++++++++--------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/system/blueprints/config/system.yaml b/system/blueprints/config/system.yaml index 43679a11e3..1aeaf2bf21 100644 --- a/system/blueprints/config/system.yaml +++ b/system/blueprints/config/system.yaml @@ -1492,7 +1492,7 @@ form: options: 1: PLUGIN_ADMIN.YES 0: PLUGIN_ADMIN.NO - default: true + default: false validate: type: bool diff --git a/system/config/system.yaml b/system/config/system.yaml index 140a95246d..47151d3f75 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -188,7 +188,7 @@ gpm: http: method: auto # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL - enable_proxy: false # Enabled proxy server + enable_proxy: true # Enable proxy server configuration proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128) proxy_cert_path: # Local path to proxy certificate folder containing pem files concurrent_connections: 5 # Concurrent HTTP connections when multiplexing diff --git a/system/src/Grav/Common/HTTP/Client.php b/system/src/Grav/Common/HTTP/Client.php index d0d524dfb2..867748f656 100644 --- a/system/src/Grav/Common/HTTP/Client.php +++ b/system/src/Grav/Common/HTTP/Client.php @@ -37,7 +37,11 @@ public static function getClient(array $overrides = [], int $connections = 6, ca } $settings = array_merge($options->toArray(), $overrides); - $preferred_method = $config->get('system.http.method', $config->get('system.gpm.method', 'auto')); + $preferred_method = $config->get('system.http.method'); + // Try old GPM setting if value is the same as system default + if ($preferred_method === 'auto') { + $preferred_method = $config->get('system.gpm.method', 'auto'); + } switch ($preferred_method) { case 'curl': @@ -70,17 +74,18 @@ public static function getOptions(): HttpOptions $options->setHeaders(array_merge([ 'Referer' => $referer ], self::$headers)); // Disable verify Peer if required - $verify_peer = $config->get('system.http.verify_peer', $config->get('system.gpm.verify_peer', null)); - if ($verify_peer !== null) { - $options->verifyPeer($verify_peer); + $verify_peer = $config->get('system.http.verify_peer'); + // Try old GPM setting if value is default + if ($verify_peer === true) { + $verify_peer = $config->get('system.gpm.verify_peer', null) ?? $verify_peer; } + $options->verifyPeer($verify_peer); - // Disable verify Host if required - $verify_host = $config->get('system.http.verify_host', null); - if ($verify_host !== null) { - $options->verifyHost($verify_host); - } + // Set verify Host + $verify_host = $config->get('system.http.verify_host', true); + $options->verifyHost($verify_host); + // New setting and must be enabled for Proxy to work if ($config->get('system.http.enable_proxy', true)) { // Set proxy url if provided $proxy_url = $config->get('system.http.proxy_url', $config->get('system.gpm.proxy_url', null)); From b13648066979ab9a327b3cc8c4999ecde82b280d Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 6 Oct 2021 10:40:31 +0300 Subject: [PATCH 03/21] Composer update --- composer.lock | 101 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/composer.lock b/composer.lock index 68dc24c9d0..6d8a127fe5 100644 --- a/composer.lock +++ b/composer.lock @@ -56,16 +56,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.2.10", + "version": "1.2.11", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8" + "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", + "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", "shasum": "" }, "require": { @@ -77,7 +77,7 @@ "phpstan/phpstan": "^0.12.55", "psr/log": "^1.0", "symfony/phpunit-bridge": "^4.2 || ^5", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0" }, "type": "library", "extra": { @@ -112,7 +112,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.2.10" + "source": "https://github.com/composer/ca-bundle/tree/1.2.11" }, "funding": [ { @@ -128,7 +128,7 @@ "type": "tidelift" } ], - "time": "2021-06-07T13:58:28+00:00" + "time": "2021-09-25T20:32:43+00:00" }, { "name": "composer/semver", @@ -596,21 +596,21 @@ }, { "name": "filp/whoops", - "version": "2.14.3", + "version": "2.14.4", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "89584ce67dd32307f1063cc43846674f4679feda" + "reference": "f056f1fe935d9ed86e698905a957334029899895" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/89584ce67dd32307f1063cc43846674f4679feda", - "reference": "89584ce67dd32307f1063cc43846674f4679feda", + "url": "https://api.github.com/repos/filp/whoops/zipball/f056f1fe935d9ed86e698905a957334029899895", + "reference": "f056f1fe935d9ed86e698905a957334029899895", "shasum": "" }, "require": { "php": "^5.5.9 || ^7.0 || ^8.0", - "psr/log": "^1.0.1" + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "require-dev": { "mockery/mockery": "^0.9 || ^1.0", @@ -655,7 +655,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.14.3" + "source": "https://github.com/filp/whoops/tree/2.14.4" }, "funding": [ { @@ -663,7 +663,7 @@ "type": "github" } ], - "time": "2021-09-19T12:00:00+00:00" + "time": "2021-10-03T12:00:00+00:00" }, { "name": "getgrav/cache", @@ -778,16 +778,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.8.2", + "version": "1.8.3", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "dc960a912984efb74d0a90222870c72c87f10c91" + "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91", - "reference": "dc960a912984efb74d0a90222870c72c87f10c91", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85", + "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85", "shasum": "" }, "require": { @@ -824,13 +824,34 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, { "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" } ], @@ -847,9 +868,23 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.8.2" + "source": "https://github.com/guzzle/psr7/tree/1.8.3" }, - "time": "2021-04-26T09:17:50+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2021-10-05T13:56:00+00:00" }, { "name": "itsgoingd/clockwork", @@ -2048,16 +2083,16 @@ }, { "name": "rhukster/dom-sanitizer", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/rhukster/dom-sanitizer.git", - "reference": "836d1dd9808adee0e4bb0ce4cdacc0f9a1497b7e" + "reference": "4db3ef1ac3d5505d044c5eb12aa106ba745bf129" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rhukster/dom-sanitizer/zipball/836d1dd9808adee0e4bb0ce4cdacc0f9a1497b7e", - "reference": "836d1dd9808adee0e4bb0ce4cdacc0f9a1497b7e", + "url": "https://api.github.com/repos/rhukster/dom-sanitizer/zipball/4db3ef1ac3d5505d044c5eb12aa106ba745bf129", + "reference": "4db3ef1ac3d5505d044c5eb12aa106ba745bf129", "shasum": "" }, "require": { @@ -2087,9 +2122,9 @@ "description": "A simple but effective DOM/SVG/MathML Sanitizer for PHP 7.4+", "support": { "issues": "https://github.com/rhukster/dom-sanitizer/issues", - "source": "https://github.com/rhukster/dom-sanitizer/tree/1.0.5" + "source": "https://github.com/rhukster/dom-sanitizer/tree/1.0.6" }, - "time": "2021-09-29T20:14:54+00:00" + "time": "2021-09-30T15:41:33+00:00" }, { "name": "rockettheme/toolbox", @@ -4399,16 +4434,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.5.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "30f38bffc6f24293dadd1823936372dfa9e86e2f" + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/30f38bffc6f24293dadd1823936372dfa9e86e2f", - "reference": "30f38bffc6f24293dadd1823936372dfa9e86e2f", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/a12f7e301eb7258bb68acd89d4aefa05c2906cae", + "reference": "a12f7e301eb7258bb68acd89d4aefa05c2906cae", "shasum": "" }, "require": { @@ -4443,9 +4478,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.5.1" }, - "time": "2021-09-17T15:28:14+00:00" + "time": "2021-10-02T14:08:47+00:00" }, { "name": "phpspec/prophecy", @@ -6535,5 +6570,5 @@ "platform-overrides": { "php": "7.3.6" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.0.0" } From 60fd4ec51632a71a3a3225b3a3f946448a1b9de6 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 7 Oct 2021 12:49:14 +0300 Subject: [PATCH 04/21] Added `UserObject::isMyself()` method to check if flex user is currently logged in --- CHANGELOG.md | 1 + system/src/Grav/Common/Flex/Types/Users/UserObject.php | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e67e470fd..5a4164f2d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ 1. [](#new) * Added method `Pages::referrerRoute()` to get the referrer route and language * Added true unique `Utils::uniqueId()` / `{{ unique_id() }}` utilities with length, prefix, and suffix support + * Added `UserObject::isMyself()` method to check if flex user is currently logged in 2. [](#improved) * Replaced GPL `SVG-Sanitizer` with MIT licensed `DOM-Sanitizer` * `Uri::referrer()` now accepts third parameter, if set to `true`, it returns route without base or language code [#3411](https://github.com/getgrav/grav/issues/3411) diff --git a/system/src/Grav/Common/Flex/Types/Users/UserObject.php b/system/src/Grav/Common/Flex/Types/Users/UserObject.php index 310c313fe6..02caee4aa0 100644 --- a/system/src/Grav/Common/Flex/Types/Users/UserObject.php +++ b/system/src/Grav/Common/Flex/Types/Users/UserObject.php @@ -230,6 +230,16 @@ public function def($name, $default = null, $separator = null) return $this; } + /** + * @return bool + */ + public function isMyself(): bool + { + $me = $this->getActiveUser(); + + return $me && $me->authenticated && $this->username === $me->username; + } + /** * Checks user authorization to the action. * From be136d3ce4584a71bbe17043cd3d4f0382b03b7b Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 7 Oct 2021 14:00:17 +0300 Subject: [PATCH 05/21] Added support for custom form field options validation with `validate: options: key|ignore` --- CHANGELOG.md | 1 + system/src/Grav/Common/Data/Validation.php | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a4164f2d0..510ec65918 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Added method `Pages::referrerRoute()` to get the referrer route and language * Added true unique `Utils::uniqueId()` / `{{ unique_id() }}` utilities with length, prefix, and suffix support * Added `UserObject::isMyself()` method to check if flex user is currently logged in + * Added support for custom form field options validation with `validate: options: key|ignore` 2. [](#improved) * Replaced GPL `SVG-Sanitizer` with MIT licensed `DOM-Sanitizer` * `Uri::referrer()` now accepts third parameter, if set to `true`, it returns route without base or language code [#3411](https://github.com/getgrav/grav/issues/3411) diff --git a/system/src/Grav/Common/Data/Validation.php b/system/src/Grav/Common/Data/Validation.php index c5b21ffac4..bfb40578db 100644 --- a/system/src/Grav/Common/Data/Validation.php +++ b/system/src/Grav/Common/Data/Validation.php @@ -781,14 +781,22 @@ public static function typeArray($value, array $params, array $field) } // If creating new values is allowed, no further checks are needed. - if (!empty($field['selectize']['create'])) { + $validateOptions = $field['validate']['options'] ?? null; + if (!empty($field['selectize']['create']) || $validateOptions === 'ignore') { return true; } $options = $field['options'] ?? []; $use = $field['use'] ?? 'values'; - if (empty($field['selectize']) || empty($field['multiple'])) { + if ($validateOptions) { + // Use custom options structure. + foreach ($options as &$option) { + $option = $option[$validateOptions] ?? null; + } + unset($option); + $options = array_values($options); + } elseif (empty($field['selectize']) || empty($field['multiple'])) { $options = array_keys($options); } if ($use === 'keys') { From 11decd588950d1d2238ee4d4429007a111b0b60b Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Thu, 7 Oct 2021 08:16:14 -0600 Subject: [PATCH 06/21] Use client now --- system/src/Grav/Common/HTTP/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/HTTP/Client.php b/system/src/Grav/Common/HTTP/Client.php index 867748f656..cd4f8dbb2a 100644 --- a/system/src/Grav/Common/HTTP/Client.php +++ b/system/src/Grav/Common/HTTP/Client.php @@ -33,7 +33,7 @@ public static function getClient(array $overrides = [], int $connections = 6, ca // Use callback if provided if ($callback) { self::$callback = $callback; - $options->setOnProgress([Response::class, 'progress']); + $options->setOnProgress([Client::class, 'progress']); } $settings = array_merge($options->toArray(), $overrides); From 280cbc2330782a59dc650fd3fca05be875c8446e Mon Sep 17 00:00:00 2001 From: Andreas Becker Date: Tue, 19 Oct 2021 09:59:21 +0700 Subject: [PATCH 07/21] Update LanguageCodes.php (#3469) Adding my - Myanmar Burmese sw - Swahili lo - Lao km - Khmer --- system/src/Grav/Common/Language/LanguageCodes.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/src/Grav/Common/Language/LanguageCodes.php b/system/src/Grav/Common/Language/LanguageCodes.php index f0a35322dc..e637bddaf6 100644 --- a/system/src/Grav/Common/Language/LanguageCodes.php +++ b/system/src/Grav/Common/Language/LanguageCodes.php @@ -86,12 +86,14 @@ class LanguageCodes 'ja-JP' => [ 'name' => 'Japanese', 'nativeName' => '日本語' ], // not iso-639-1 'ka' => [ 'name' => 'Georgian', 'nativeName' => 'ქართული' ], 'kk' => [ 'name' => 'Kazakh', 'nativeName' => 'Қазақ' ], + 'km' => [ 'name' => 'Khmer', 'nativeName' => 'Khmer' ], 'kn' => [ 'name' => 'Kannada', 'nativeName' => 'ಕನ್ನಡ' ], 'ko' => [ 'name' => 'Korean', 'nativeName' => '한국어' ], 'ku' => [ 'name' => 'Kurdish', 'nativeName' => 'Kurdî' ], 'la' => [ 'name' => 'Latin', 'nativeName' => 'Latina' ], 'lb' => [ 'name' => 'Luxembourgish', 'nativeName' => 'Lëtzebuergesch' ], 'lg' => [ 'name' => 'Luganda', 'nativeName' => 'Luganda' ], + 'lo' => [ 'name' => 'Lao', 'nativeName' => 'Lao' ], 'lt' => [ 'name' => 'Lithuanian', 'nativeName' => 'Lietuvių' ], 'lv' => [ 'name' => 'Latvian', 'nativeName' => 'Latviešu' ], 'mai' => [ 'name' => 'Maithili', 'nativeName' => 'मैथिली মৈথিলী' ], @@ -101,6 +103,7 @@ class LanguageCodes 'ml' => [ 'name' => 'Malayalam', 'nativeName' => 'മലയാളം' ], 'mn' => [ 'name' => 'Mongolian', 'nativeName' => 'Монгол' ], 'mr' => [ 'name' => 'Marathi', 'nativeName' => 'मराठी' ], + 'my' => [ 'name' => 'Myanmar (Burmese)', 'nativeName' => 'ဗမာी' ], 'no' => [ 'name' => 'Norwegian', 'nativeName' => 'Norsk' ], 'nb' => [ 'name' => 'Norwegian', 'nativeName' => 'Norsk' ], 'nb-NO' => [ 'name' => 'Norwegian (Bokmål)', 'nativeName' => 'Norsk bokmål' ], @@ -132,6 +135,7 @@ class LanguageCodes 'st' => [ 'name' => 'Southern Sotho', 'nativeName' => 'Sesotho' ], 'sv' => [ 'name' => 'Swedish', 'nativeName' => 'Svenska' ], 'sv-SE' => [ 'name' => 'Swedish', 'nativeName' => 'Svenska' ], + 'sw' => [ 'name' => 'Swahili', 'nativeName' => 'Swahili' ], 'ta' => [ 'name' => 'Tamil', 'nativeName' => 'தமிழ்' ], 'ta-IN' => [ 'name' => 'Tamil (India)', 'nativeName' => 'தமிழ் (இந்தியா)' ], 'ta-LK' => [ 'name' => 'Tamil (Sri Lanka)', 'nativeName' => 'தமிழ் (இலங்கை)' ], From 33a57099038a30aa8001d908abaa08b37943c228 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Oct 2021 10:24:00 +0300 Subject: [PATCH 08/21] Fixed a bug in `PermissionsReader` in PHP 7.3 --- CHANGELOG.md | 6 ++++++ system/src/Grav/Common/Security.php | 8 ++------ system/src/Grav/Framework/Acl/PermissionsReader.php | 2 +- system/src/Grav/Framework/Flex/Storage/FolderStorage.php | 8 ++------ 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 510ec65918..d087c242de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v1.7.24 +## mm/dd/2021 + +3. [](#bugfix) + * Fixed a bug in `PermissionsReader` in PHP 7.3 + # v1.7.23 ## 09/29/2021 diff --git a/system/src/Grav/Common/Security.php b/system/src/Grav/Common/Security.php index 833e648088..55aa54593c 100644 --- a/system/src/Grav/Common/Security.php +++ b/system/src/Grav/Common/Security.php @@ -138,7 +138,7 @@ public static function detectXssFromArray(array $array, string $prefix = '', arr $options = static::getXssDefaults(); } - $list = []; + $list = [[]]; foreach ($array as $key => $value) { if (is_array($value)) { $list[] = static::detectXssFromArray($value, $prefix . $key . '.', $options); @@ -148,11 +148,7 @@ public static function detectXssFromArray(array $array, string $prefix = '', arr } } - if (!empty($list)) { - return array_merge(...$list); - } - - return $list; + return array_merge(...$list); } /** diff --git a/system/src/Grav/Framework/Acl/PermissionsReader.php b/system/src/Grav/Framework/Acl/PermissionsReader.php index 2c38afbea0..4f4a6a3174 100644 --- a/system/src/Grav/Framework/Acl/PermissionsReader.php +++ b/system/src/Grav/Framework/Acl/PermissionsReader.php @@ -131,7 +131,7 @@ protected static function initTypes(array $types) */ protected static function getDependencies(array $dependencies): array { - $list = []; + $list = [[]]; foreach ($dependencies as $name => $deps) { $current = $deps ? static::getDependencies($deps) : []; $current[] = $name; diff --git a/system/src/Grav/Framework/Flex/Storage/FolderStorage.php b/system/src/Grav/Framework/Flex/Storage/FolderStorage.php index 5b4f9f3861..ff2c94d7a6 100644 --- a/system/src/Grav/Framework/Flex/Storage/FolderStorage.php +++ b/system/src/Grav/Framework/Flex/Storage/FolderStorage.php @@ -634,7 +634,7 @@ protected function buildPrefixedIndexFromFilesystem($path) $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS; $iterator = new FilesystemIterator($path, $flags); - $list = []; + $list = [[]]; /** @var SplFileInfo $info */ foreach ($iterator as $filename => $info) { if (!$info->isDir() || strpos($info->getFilename(), '.') === 0) { @@ -644,11 +644,7 @@ protected function buildPrefixedIndexFromFilesystem($path) $list[] = $this->buildIndexFromFilesystem($filename); } - if (!$list) { - return []; - } - - return count($list) > 1 ? array_merge(...$list) : $list[0]; + return array_merge(...$list); } /** From 08d7ad80dfa518f00477abf9364f7939b45e738f Mon Sep 17 00:00:00 2001 From: Nicolas Busseneau Date: Tue, 12 Oct 2021 04:33:08 +0200 Subject: [PATCH 09/21] fix `session_store_active` functionality At the moment and since 1.7.19, the `system.languages.session_store_active` setting has no effect. Session must be initialized before URI for `$language->setActiveFromUri($uri)` (called from `$this->initializeUri($config) -> $uri->init()`) to properly retrieve / store `active_language` in Session. This was previously detected in #3269 as per the code comment, but got reversed in 2e9fe80e33b1f6a80b061239fe2f425aa1f54b06. --- system/src/Grav/Common/Processors/InitializeProcessor.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/src/Grav/Common/Processors/InitializeProcessor.php b/system/src/Grav/Common/Processors/InitializeProcessor.php index 61144648c9..55cba033cc 100644 --- a/system/src/Grav/Common/Processors/InitializeProcessor.php +++ b/system/src/Grav/Common/Processors/InitializeProcessor.php @@ -105,12 +105,12 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface // TODO: remove in 2.0. $this->container['accounts']; + // Initialize session (used by URI, see issue #3269). + $this->initializeSession($config); + // Initialize URI (uses session, see issue #3269). $this->initializeUri($config); - // Initialize session. - $this->initializeSession($config); - // Grav may return redirect response right away. $redirectCode = (int)$config->get('system.pages.redirect_trailing_slash', 1); if ($redirectCode) { From d2536379e52addce1a879e984943e2944b73c549 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Oct 2021 12:31:27 +0300 Subject: [PATCH 10/21] Changelog update (#3464) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d087c242de..3ea43ee023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 3. [](#bugfix) * Fixed a bug in `PermissionsReader` in PHP 7.3 + * Fixed `session_store_active` language option (#3464) # v1.7.23 ## 09/29/2021 From be44bf0b55f1945ac7c455166bf647f5786ef636 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Oct 2021 18:56:21 +0300 Subject: [PATCH 11/21] Fixed deprecated warnings on `ArrayAccess` in PHP 8.1 --- CHANGELOG.md | 1 + system/src/Grav/Common/Getters.php | 4 ++++ system/src/Grav/Common/Page/Collection.php | 1 + system/src/Grav/Common/Page/Media.php | 2 ++ system/src/Grav/Common/Page/Medium/GlobalMedia.php | 2 ++ system/src/Grav/Common/Plugin.php | 4 ++++ system/src/Grav/Common/User/DataUser/User.php | 2 ++ .../src/Grav/Framework/Collection/AbstractIndexCollection.php | 4 ++++ system/src/Grav/Framework/Object/Access/ArrayAccessTrait.php | 4 ++++ .../Grav/Framework/Object/Access/NestedArrayAccessTrait.php | 4 ++++ 10 files changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ea43ee023..0ce4cba371 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ 3. [](#bugfix) * Fixed a bug in `PermissionsReader` in PHP 7.3 * Fixed `session_store_active` language option (#3464) + * Fixed deprecated warnings on `ArrayAccess` in PHP 8.1 # v1.7.23 ## 09/29/2021 diff --git a/system/src/Grav/Common/Getters.php b/system/src/Grav/Common/Getters.php index 8f3a73a2ba..916d5249a2 100644 --- a/system/src/Grav/Common/Getters.php +++ b/system/src/Grav/Common/Getters.php @@ -69,6 +69,7 @@ public function __unset($offset) * @param int|string $offset * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { if ($this->gettersVariable) { @@ -84,6 +85,7 @@ public function offsetExists($offset) * @param int|string $offset * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { if ($this->gettersVariable) { @@ -99,6 +101,7 @@ public function offsetGet($offset) * @param int|string $offset * @param mixed $value */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if ($this->gettersVariable) { @@ -112,6 +115,7 @@ public function offsetSet($offset, $value) /** * @param int|string $offset */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { if ($this->gettersVariable) { diff --git a/system/src/Grav/Common/Page/Collection.php b/system/src/Grav/Common/Page/Collection.php index 32b917cd28..930aeda2bf 100644 --- a/system/src/Grav/Common/Page/Collection.php +++ b/system/src/Grav/Common/Page/Collection.php @@ -187,6 +187,7 @@ public function key() * @param string $offset * @return PageInterface|null */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->pages->get($offset) ?: null; diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index 94fd2c4f8a..e18201420c 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -63,6 +63,7 @@ public function __wakeup() * @param string $offset * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return parent::offsetExists($offset) ?: isset(static::$global[$offset]); @@ -72,6 +73,7 @@ public function offsetExists($offset) * @param string $offset * @return MediaObjectInterface|null */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return parent::offsetGet($offset) ?: static::$global[$offset]; diff --git a/system/src/Grav/Common/Page/Medium/GlobalMedia.php b/system/src/Grav/Common/Page/Medium/GlobalMedia.php index 4097c8f587..50d69c747a 100644 --- a/system/src/Grav/Common/Page/Medium/GlobalMedia.php +++ b/system/src/Grav/Common/Page/Medium/GlobalMedia.php @@ -46,6 +46,7 @@ public function getPath(): ?string * @param string $offset * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return parent::offsetExists($offset) ?: !empty($this->resolveStream($offset)); @@ -55,6 +56,7 @@ public function offsetExists($offset) * @param string $offset * @return MediaObjectInterface|null */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return parent::offsetGet($offset) ?: $this->addMedium($offset); diff --git a/system/src/Grav/Common/Plugin.php b/system/src/Grav/Common/Plugin.php index b32e39e6bb..3b0d3fb14e 100644 --- a/system/src/Grav/Common/Plugin.php +++ b/system/src/Grav/Common/Plugin.php @@ -227,6 +227,7 @@ protected function disable(array $events) * @param string $offset An offset to check for. * @return bool Returns TRUE on success or FALSE on failure. */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { if ($offset === 'title') { @@ -244,6 +245,7 @@ public function offsetExists($offset) * @param string $offset The offset to retrieve. * @return mixed Can return all value types. */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { if ($offset === 'title') { @@ -262,6 +264,7 @@ public function offsetGet($offset) * @param mixed $value The value to set. * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new LogicException(__CLASS__ . ' blueprints cannot be modified.'); @@ -273,6 +276,7 @@ public function offsetSet($offset, $value) * @param string $offset The offset to unset. * @throws LogicException */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new LogicException(__CLASS__ . ' blueprints cannot be modified.'); diff --git a/system/src/Grav/Common/User/DataUser/User.php b/system/src/Grav/Common/User/DataUser/User.php index 47353425de..8fcdbbbd6d 100644 --- a/system/src/Grav/Common/User/DataUser/User.php +++ b/system/src/Grav/Common/User/DataUser/User.php @@ -57,6 +57,7 @@ public function __construct(array $items = [], $blueprints = null) * @param string $offset * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { $value = parent::offsetExists($offset); @@ -73,6 +74,7 @@ public function offsetExists($offset) * @param string $offset * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { $value = parent::offsetGet($offset); diff --git a/system/src/Grav/Framework/Collection/AbstractIndexCollection.php b/system/src/Grav/Framework/Collection/AbstractIndexCollection.php index 6a8861e9ba..38d3ab51ef 100644 --- a/system/src/Grav/Framework/Collection/AbstractIndexCollection.php +++ b/system/src/Grav/Framework/Collection/AbstractIndexCollection.php @@ -144,6 +144,7 @@ public function removeElement($element) * * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->containsKey($offset); @@ -154,6 +155,7 @@ public function offsetExists($offset) * * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->get($offset); @@ -164,6 +166,7 @@ public function offsetGet($offset) * * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if (null === $offset) { @@ -178,6 +181,7 @@ public function offsetSet($offset, $value) * * {@inheritDoc} */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { return $this->remove($offset); diff --git a/system/src/Grav/Framework/Object/Access/ArrayAccessTrait.php b/system/src/Grav/Framework/Object/Access/ArrayAccessTrait.php index de5cc7aeb4..affff03b0d 100644 --- a/system/src/Grav/Framework/Object/Access/ArrayAccessTrait.php +++ b/system/src/Grav/Framework/Object/Access/ArrayAccessTrait.php @@ -21,6 +21,7 @@ trait ArrayAccessTrait * @param mixed $offset An offset to check for. * @return bool Returns TRUE on success or FALSE on failure. */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->hasProperty($offset); @@ -32,6 +33,7 @@ public function offsetExists($offset) * @param mixed $offset The offset to retrieve. * @return mixed Can return all value types. */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->getProperty($offset); @@ -44,6 +46,7 @@ public function offsetGet($offset) * @param mixed $value The value to set. * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->setProperty($offset, $value); @@ -55,6 +58,7 @@ public function offsetSet($offset, $value) * @param mixed $offset The offset to unset. * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->unsetProperty($offset); diff --git a/system/src/Grav/Framework/Object/Access/NestedArrayAccessTrait.php b/system/src/Grav/Framework/Object/Access/NestedArrayAccessTrait.php index e0485655c0..83658753d0 100644 --- a/system/src/Grav/Framework/Object/Access/NestedArrayAccessTrait.php +++ b/system/src/Grav/Framework/Object/Access/NestedArrayAccessTrait.php @@ -21,6 +21,7 @@ trait NestedArrayAccessTrait * @param mixed $offset An offset to check for. * @return bool Returns TRUE on success or FALSE on failure. */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->hasNestedProperty($offset); @@ -32,6 +33,7 @@ public function offsetExists($offset) * @param mixed $offset The offset to retrieve. * @return mixed Can return all value types. */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->getNestedProperty($offset); @@ -44,6 +46,7 @@ public function offsetGet($offset) * @param mixed $value The value to set. * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->setNestedProperty($offset, $value); @@ -55,6 +58,7 @@ public function offsetSet($offset, $value) * @param mixed $offset The offset to unset. * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->unsetNestedProperty($offset); From 8b0a6906c73fc8962873a449ae74f2ecc08afe75 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 20 Oct 2021 20:27:11 +0300 Subject: [PATCH 12/21] Composer update --- composer.lock | 149 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 100 insertions(+), 49 deletions(-) diff --git a/composer.lock b/composer.lock index 6d8a127fe5..df02b8d5ad 100644 --- a/composer.lock +++ b/composer.lock @@ -1153,21 +1153,21 @@ }, { "name": "maximebf/debugbar", - "version": "v1.17.1", + "version": "v1.17.2", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "0a3532556be0145603f8a9de23e76dc28eed7054" + "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/0a3532556be0145603f8a9de23e76dc28eed7054", - "reference": "0a3532556be0145603f8a9de23e76dc28eed7054", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/3541f09f09c003c4a9ff7ddb0eb3361a7f14d418", + "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418", "shasum": "" }, "require": { "php": "^7.1|^8", - "psr/log": "^1.0", + "psr/log": "^1|^2|^3", "symfony/var-dumper": "^2.6|^3|^4|^5" }, "require-dev": { @@ -1212,9 +1212,9 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.1" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.2" }, - "time": "2021-08-01T09:19:02+00:00" + "time": "2021-10-18T09:39:00+00:00" }, { "name": "miljar/php-exif", @@ -3348,25 +3348,24 @@ "packages-dev": [ { "name": "behat/gherkin", - "version": "v4.8.0", + "version": "v4.9.0", "source": { "type": "git", "url": "https://github.com/Behat/Gherkin.git", - "reference": "2391482cd003dfdc36b679b27e9f5326bd656acd" + "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/2391482cd003dfdc36b679b27e9f5326bd656acd", - "reference": "2391482cd003dfdc36b679b27e9f5326bd656acd", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/0bc8d1e30e96183e4f36db9dc79caead300beff4", + "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4", "shasum": "" }, "require": { "php": "~7.2|~8.0" }, "require-dev": { - "cucumber/cucumber": "dev-gherkin-16.0.0", + "cucumber/cucumber": "dev-gherkin-22.0.0", "phpunit/phpunit": "~8|~9", - "symfony/phpunit-bridge": "~3|~4|~5", "symfony/yaml": "~3|~4|~5" }, "suggest": { @@ -3375,7 +3374,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "4.x-dev" } }, "autoload": { @@ -3406,9 +3405,9 @@ ], "support": { "issues": "https://github.com/Behat/Gherkin/issues", - "source": "https://github.com/Behat/Gherkin/tree/v4.8.0" + "source": "https://github.com/Behat/Gherkin/tree/v4.9.0" }, - "time": "2021-02-04T12:44:21+00:00" + "time": "2021-10-12T13:05:09+00:00" }, { "name": "codeception/codeception", @@ -3942,24 +3941,25 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.3.0", + "version": "7.4.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "7008573787b430c1c1f650e3722d9bba59967628" + "reference": "868b3571a039f0ebc11ac8f344f4080babe2cb94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", - "reference": "7008573787b430c1c1f650e3722d9bba59967628", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/868b3571a039f0ebc11ac8f344f4080babe2cb94", + "reference": "868b3571a039f0ebc11ac8f344f4080babe2cb94", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.4", - "guzzlehttp/psr7": "^1.7 || ^2.0", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.8.3 || ^2.1", "php": "^7.2.5 || ^8.0", - "psr/http-client": "^1.0" + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2" }, "provide": { "psr/http-client-implementation": "1.0" @@ -3969,7 +3969,7 @@ "ext-curl": "*", "php-http/client-integration-tests": "^3.0", "phpunit/phpunit": "^8.5.5 || ^9.3.5", - "psr/log": "^1.1" + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { "ext-curl": "Required for CURL handler support", @@ -3979,7 +3979,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.3-dev" + "dev-master": "7.4-dev" } }, "autoload": { @@ -3995,19 +3995,43 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, { "name": "Márk Sági-Kazár", "email": "mark.sagikazar@gmail.com", - "homepage": "https://sagikazarmark.hu" + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", "keywords": [ "client", "curl", @@ -4021,7 +4045,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.3.0" + "source": "https://github.com/guzzle/guzzle/tree/7.4.0" }, "funding": [ { @@ -4033,28 +4057,24 @@ "type": "github" }, { - "url": "https://github.com/alexeyshockov", - "type": "github" - }, - { - "url": "https://github.com/gmponos", - "type": "github" + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" } ], - "time": "2021-03-23T11:33:13+00:00" + "time": "2021-10-18T09:52:00+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" + "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", - "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0", + "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0", "shasum": "" }, "require": { @@ -4066,7 +4086,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.5-dev" } }, "autoload": { @@ -4082,10 +4102,25 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "description": "Guzzle promises library", @@ -4094,9 +4129,23 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.4.1" + "source": "https://github.com/guzzle/promises/tree/1.5.0" }, - "time": "2021-03-07T09:25:29+00:00" + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2021-10-07T13:05:22+00:00" }, { "name": "myclabs/deep-copy", @@ -4378,16 +4427,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { @@ -4398,7 +4447,8 @@ "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -4428,9 +4478,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" }, - "time": "2020-09-03T19:13:55+00:00" + "time": "2021-10-19T17:43:47+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -5990,6 +6040,7 @@ "type": "github" } ], + "abandoned": true, "time": "2020-09-28T06:45:17+00:00" }, { From fd61f82f5ae8f145809031544a262d629d753a3a Mon Sep 17 00:00:00 2001 From: Ricardo Verdugo Date: Thu, 21 Oct 2021 13:31:33 +0100 Subject: [PATCH 13/21] Watermark Media Action (#3308) * added gregwar merge media action and watermark media function * remove the dump left by accident * added scaling to the watermark Co-authored-by: Ricardo Co-authored-by: Andy Miller <1084697+rhukster@users.noreply.github.com> --- system/config/system.yaml | 6 ++ system/images/watermark.png | Bin 0 -> 95789 bytes .../Common/Media/Traits/ImageMediaTrait.php | 8 +++ .../Grav/Common/Page/Medium/ImageMedium.php | 62 ++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 system/images/watermark.png diff --git a/system/config/system.yaml b/system/config/system.yaml index 47151d3f75..3d0983c310 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -162,6 +162,12 @@ images: retina_scale: 1 # scale to adjust auto-sizes for better handling of HiDPI resolutions defaults: loading: auto # Let browser pick [auto|lazy|eager] + watermark: + image: 'system://images/watermark.png' # Path to a watermark image + position_y: 'center' # top|center|bottom + position_x: 'center' # left|center|right + scale: 33 # percentage of watermark scale + watermark_all: false # automatically watermark all images media: enable_media_timestamp: false # Enable media timestamps diff --git a/system/images/watermark.png b/system/images/watermark.png new file mode 100644 index 0000000000000000000000000000000000000000..0f38a75c40d48ba2fd062a82eb50090f4cc61133 GIT binary patch literal 95789 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%0D2)uoNCMzd4 z4#kTL#oXu@n|bCUT5!dX{{bK=muucT!s8qNM%;`z^jbhDM!bJ^86LrH?o%%R6+eKa zT*VKXBBH&y|NN8X#hm3vF-YYZN*%axg_A?&jbNBY9whVQs|4n*a1rf>oYobl?Zc`a zvTE=D;!u?;M17i~Y)R|7JnVD#H5bvY-&l*J^!X;-2eDzot+=>Vn5RHiuoooI@7`Za z?MpvT{5WHV6v@!FyhS(s{;KfOp{nEDY5^OshFiUj1mNX+gA4{Rd&=`2T4PkkPGxS+ zMbU6}1PonH1t#*^?JQ|9hxN96P^JZq=r4-XIil`PVr5mJWTF4gUKVHe>e@+13Y<`4 zNAQq>Q^62XL4EUYw%F$YTZLpN{YkxzF`|pV8m2gA45qW=H07gat$xR0lxLNQ`4;YG z*LxUdO=$~w7zuO|=V2!1hk4TT`7CSf^_nsrRk58yYw&v7>mv8gr~giNj-b5Gm!%uB zS-FgcrNeIYdt!2vL6JoyDxx&nacQ#5XOi5xpr>&W{!cdD04TfgD|E38#c7|<@sU41 z_T*1!*&a{zC9CS~ml*p;PF}AZo}KGv*L<}AT2X)m(DX&BPJeZ`ondl9mRnUK+&&p?#h#8<@)BktPi1`AU zG}>IKg-A*qyZ8lU+mQ$);(-$uWl8c;>Ky}Hw7%O3X<#4|Kc@k>%l5as(mnkt1}AyN zuznp3S-zY@sp=QYRDYaQumX;`g#!IWyQFd>Lj$E;a}>TSm-}W2twH&#ua5Kzv4A)N zlIj4UeHi=;&~Ci0IdOC7p*`hVnP`H!K`M3!F@tDaXI1P|+Ij{#ty!1?mJaNj(>NS8 z%UL&SxPbORE}&hO188UB-{k>-_AU+bgds)$%N~ee2k-%#UgB%Fl~)i$mqSfpnGVKm z%xIF4^rg67G~j@S7+~>9eW3&XxEB=?-j$BdOUy>XdB4;jHkN`q-2p+Y5<5<+C0o4n zXwTM`&v3C|HU&f#^SLEW)xcLsB!S1oY~?H9dfe(c!xG~wQW;?DB< zE>b?Yxfg!(G{CrBiI!isYjJ0X%&gD%0RLIm)_QuZ@e9RyZk2^Qwq=tH7yGHl;_l}v zs(9&WbW9h%=nvbL>8|(pMf}m(o%4AZN$;>v#^IVqY94RGYA;<9w>`;Igu*aXFoi_A+%ElxP*3{jfHq%iyQ$6 z?JpRlTYb&~S+H@VP8M<2lU+g%mP1h+{4Jt5HWWBE5+uK7zaRGxJBBVP)q5KR5ZdWB z-QyfWdoq{M?vW#57O~bfdJovwpk4Pr{35gqW;2G)zVlxnM2#@8){1e!@+6P>lCL?Lu*0Mne227@aEqxv_8xGvUAP_#GB}hy#;P0$}np)|JO6(JzVCdnU4CGv{^1 zRN|etgC9Hq9$$Y!S{Yh^By56}wm(7^Q0S$ok>Y=R_Z zeHd=ud^E?8M%ZG6`7vYjjJyz@Spd9ni&6pHp`TO~H?&{Jo#Gj7$d6 zGA=oYwkK+q1lZer`Z}eyXV+@HFqmocC}9^Tod|L@9mS3fTZcTSh4i-BoeXbWMW3h? z^5hz7*i2{%6V6_cxwnMG#}xoVTuqI9za+zlr;h1#$f6uFGC}94o889->ygCJ!d_*A zO6k@_b=U0)|HC$Js|~oBng`Lml?1M_I+eQ%PNa8#SRZhxi37TgUB~^@y40rBvM)Uw z53(+(rrXWdwB}3~yLtHN8zb@h+}q(_g=CZBQTkfmMRJZmH`H!{`>Xp~~kj ze=;}4TX5|Yx-6Y^iUkFW8VLsOpK%w3C8)90opgEP`Mlb&N7J^0^E5dT%NiM#0ABC( zx0s9#?LjtdYhZKP++>{1gqo|;6|5P2G%$18&vdnIV%kGN;etp3!uxksa8pb)f3wYx T&xaspect_ratio = $config->get('system.images.cls.aspect_ratio', false); $this->retina_scale = $config->get('system.images.cls.retina_scale', 1); + $this->watermark = $config->get('system.images.watermark.watermark_all', false); + return $this; } @@ -415,6 +419,10 @@ protected function saveImage() $this->image->merge(ImageFile::open($overlay)); } + if ($this->watermark) { + $this->watermark(); + } + return $this->image->cacheFile($this->format, $this->quality, false, [$this->get('width'), $this->get('height'), $this->get('modified')]); } } diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index 70d13f8fdb..46c832ee95 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -17,6 +17,7 @@ use Grav\Common\Media\Traits\ImageLoadingTrait; use Grav\Common\Media\Traits\ImageMediaTrait; use Grav\Common\Utils; +use Gregwar\Image\Image; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use function func_get_args; use function in_array; @@ -325,6 +326,67 @@ public function retinaScale($scale = 1) return $this; } + public function watermark($image = null, $position = null, $scale = null) + { + $grav = $this->getGrav(); + + $locator = $grav['locator']; + $config = $grav['config']; + + $args = func_get_args(); + + $file = $args[0] ?? '1'; // using '1' because of markdown. doing ![](image.jpg?watermark) returns $args[0]='1'; + $file = $file === '1' ? $config->get('system.images.watermark.image') : $args[0]; + + $watermark = $locator->findResource($file); + $watermark = ImageFile::open($watermark); + + // Scaling operations + $scale = ($scale ?? $config->get('system.images.watermark.scale', 100)) / 100; + $wwidth = $this->get('width') * $scale; + $wheight = $this->get('height') * $scale; + $watermark->resize($wwidth, $wheight); + + // Position operations + $position = !empty($args[1]) ? explode('-', $args[1]) : ['center', 'center']; // todo change to config + $positionY = $position[0] ?? $config->get('system.images.watermark.position_y', 'center'); + $positionX = $position[1] ?? $config->get('system.images.watermark.position_x', 'center'); + + switch ($positionY) + { + case 'top': + $positionY = 0; + break; + + case 'bottom': + $positionY = $this->get('height')-$wheight; + break; + + case 'center': + $positionY = ($this->get('height')/2) - ($wheight/2); + break; + } + + switch ($positionX) + { + case 'left': + $positionX = 0; + break; + + case 'right': + $positionX = $this->get('width')-$wwidth; + break; + + case 'center': + $positionX = ($this->get('width')/2) - ($wwidth/2); + break; + } + + $this->__call('merge', [$watermark,$positionX, $positionY]); + + return $this; + } + /** * Handle this commonly used variant * From 715477586c2b2301a427916873fdfcc19d6d85b5 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 22 Oct 2021 15:07:42 +0300 Subject: [PATCH 14/21] Added support to disable a form, making it readonly --- CHANGELOG.md | 2 ++ .../Grav/Framework/Flex/FlexDirectoryForm.php | 6 +++++ system/src/Grav/Framework/Flex/FlexForm.php | 6 +++++ .../Grav/Framework/Form/Traits/FormTrait.php | 26 +++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ce4cba371..bed1e1b6d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # v1.7.24 ## mm/dd/2021 +1. [](#new) + * Added support to disable a form, making it readonly 3. [](#bugfix) * Fixed a bug in `PermissionsReader` in PHP 7.3 * Fixed `session_store_active` language option (#3464) diff --git a/system/src/Grav/Framework/Flex/FlexDirectoryForm.php b/system/src/Grav/Framework/Flex/FlexDirectoryForm.php index a2259678bc..66b6f3e148 100644 --- a/system/src/Grav/Framework/Flex/FlexDirectoryForm.php +++ b/system/src/Grav/Framework/Flex/FlexDirectoryForm.php @@ -15,6 +15,7 @@ use Grav\Common\Data\Data; use Grav\Common\Grav; use Grav\Common\Twig\Twig; +use Grav\Common\Utils; use Grav\Framework\Flex\Interfaces\FlexDirectoryFormInterface; use Grav\Framework\Flex\Interfaces\FlexFormInterface; use Grav\Framework\Form\Interfaces\FormFlashInterface; @@ -94,9 +95,14 @@ public function __construct(string $name, FlexDirectory $directory, array $optio $uniqueId = md5($directory->getFlexType() . '-directory-' . $this->name); } $this->setUniqueId($uniqueId); + $this->setFlashLookupFolder($directory->getDirectoryBlueprint()->get('form/flash_folder') ?? 'tmp://forms/[SESSIONID]'); $this->form = $options['form'] ?? null; + if (Utils::isPositive($this->items['disabled'] ?? $this->form['disabled'] ?? false)) { + $this->disable(); + } + $this->initialize(); } diff --git a/system/src/Grav/Framework/Flex/FlexForm.php b/system/src/Grav/Framework/Flex/FlexForm.php index 4fb8daf272..d25cefc408 100644 --- a/system/src/Grav/Framework/Flex/FlexForm.php +++ b/system/src/Grav/Framework/Flex/FlexForm.php @@ -15,6 +15,7 @@ use Grav\Common\Data\Data; use Grav\Common\Grav; use Grav\Common\Twig\Twig; +use Grav\Common\Utils; use Grav\Framework\Flex\Interfaces\FlexFormInterface; use Grav\Framework\Flex\Interfaces\FlexObjectFormInterface; use Grav\Framework\Flex\Interfaces\FlexObjectInterface; @@ -125,10 +126,15 @@ public function __construct(string $name, FlexObjectInterface $object, array $op $uniqueId = md5($uniqueId); } $this->setUniqueId($uniqueId); + $directory = $object->getFlexDirectory(); $this->setFlashLookupFolder($options['flash_folder'] ?? $directory->getBlueprint()->get('form/flash_folder') ?? 'tmp://forms/[SESSIONID]'); $this->form = $options['form'] ?? null; + if (Utils::isPositive($this->items['disabled'] ?? $this->form['disabled'] ?? false)) { + $this->disable(); + } + if (!empty($options['reset'])) { $this->getFlash()->delete(); } diff --git a/system/src/Grav/Framework/Form/Traits/FormTrait.php b/system/src/Grav/Framework/Form/Traits/FormTrait.php index 8dfed19835..4362cf5e47 100644 --- a/system/src/Grav/Framework/Form/Traits/FormTrait.php +++ b/system/src/Grav/Framework/Form/Traits/FormTrait.php @@ -57,6 +57,8 @@ trait FormTrait private $name; /** @var string */ private $id; + /** @var bool */ + private $enabled = true; /** @var string */ private $uniqueid; /** @var string */ @@ -90,6 +92,30 @@ public function setId(string $id): void $this->id = $id; } + /** + * @return void + */ + public function disable(): void + { + $this->enabled = false; + } + + /** + * @return void + */ + public function enable(): void + { + $this->enabled = true; + } + + /** + * @return bool + */ + public function isEnabled(): bool + { + return $this->enabled; + } + /** * @return string */ From 17dfd130b6c7c4d939e27a65fdadc47c13d4ba45 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 22 Oct 2021 15:08:28 +0300 Subject: [PATCH 15/21] Changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bed1e1b6d8..5bf8e14e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## mm/dd/2021 1. [](#new) + * Added support for image watermarks * Added support to disable a form, making it readonly 3. [](#bugfix) * Fixed a bug in `PermissionsReader` in PHP 7.3 From afc69a3229bb6fe120b2c1ea27bc6f196ed7284d Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 25 Oct 2021 20:37:59 +0300 Subject: [PATCH 16/21] Fixed XSS detection with `:` --- CHANGELOG.md | 1 + system/src/Grav/Common/Security.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bf8e14e03..45c4b5a1a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Fixed a bug in `PermissionsReader` in PHP 7.3 * Fixed `session_store_active` language option (#3464) * Fixed deprecated warnings on `ArrayAccess` in PHP 8.1 + * Fixed XSS detection with `:` # v1.7.23 ## 09/29/2021 diff --git a/system/src/Grav/Common/Security.php b/system/src/Grav/Common/Security.php index 55aa54593c..fe259d8ba9 100644 --- a/system/src/Grav/Common/Security.php +++ b/system/src/Grav/Common/Security.php @@ -203,7 +203,7 @@ public static function detectXss($string, array $options = null): ?string $string = preg_replace('!(�+[0-9]+)!u', '$1;', $string); // Decode entities - $string = html_entity_decode($string, ENT_NOQUOTES, 'UTF-8'); + $string = html_entity_decode($string, ENT_NOQUOTES | ENT_HTML5, 'UTF-8'); // Strip whitespace characters $string = preg_replace('!\s!u', '', $string); From af4243aff267996021560a982274f10bb9dcf5e6 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 26 Oct 2021 19:22:56 +0300 Subject: [PATCH 17/21] User `authorize()` now checks user groups before superuser, allowing deny rules to work --- CHANGELOG.md | 2 ++ .../src/Grav/Common/Flex/Types/Users/UserObject.php | 12 +++++++----- system/src/Grav/Common/Page/Pages.php | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45c4b5a1a8..a7ff259e28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ 1. [](#new) * Added support for image watermarks * Added support to disable a form, making it readonly +2. [](#improved) + * User `authorize()` now checks user groups before superuser, allowing deny rules to work 3. [](#bugfix) * Fixed a bug in `PermissionsReader` in PHP 7.3 * Fixed `session_store_active` language option (#3464) diff --git a/system/src/Grav/Common/Flex/Types/Users/UserObject.php b/system/src/Grav/Common/Flex/Types/Users/UserObject.php index 02caee4aa0..424e5ebefb 100644 --- a/system/src/Grav/Common/Flex/Types/Users/UserObject.php +++ b/system/src/Grav/Common/Flex/Types/Users/UserObject.php @@ -274,6 +274,7 @@ public function authorize(string $action, string $scope = null): ?bool } } + // Check custom application access. $authorizeCallable = static::$authorizeCallable; if ($authorizeCallable instanceof Closure) { $authorizeCallable->bindTo($this); @@ -290,13 +291,14 @@ public function authorize(string $action, string $scope = null): ?bool return $authorized; } - // If specific rule isn't hit, check if user is super user. - if ($access->authorize('admin.super') === true) { - return true; + // Check group access. + $authorized = $this->getGroups()->authorize($action, $scope); + if (is_bool($authorized)) { + return $authorized; } - // Check group access. - return $this->getGroups()->authorize($action, $scope); + // If any specific rule isn't hit, check if user is a superuser. + return $access->authorize('admin.super') === true; } /** diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 941c9a7b3b..9e5d47db09 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -649,7 +649,7 @@ protected function evaluate($value, PageInterface $self = null) $cmd = $value; $params = []; } elseif (is_array($value) && count($value) === 1 && !is_int(key($value))) { - // Format: @command.param: { attr1: value1, attr2: value2 } + // Format: @command.param: { attr1: value1, attr2: value2 } $cmd = (string)key($value); $params = (array)current($value); } else { From 53c7f4c1198bfcd394a242db745ad3edf570b16c Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 26 Oct 2021 19:25:41 +0300 Subject: [PATCH 18/21] Changelog update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ff259e28..17cc376188 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ * Added support for image watermarks * Added support to disable a form, making it readonly 2. [](#improved) - * User `authorize()` now checks user groups before superuser, allowing deny rules to work + * Flex `$user->authorize()` now checks user groups before `admin.super`, allowing deny rules to work properly 3. [](#bugfix) * Fixed a bug in `PermissionsReader` in PHP 7.3 * Fixed `session_store_active` language option (#3464) From 7dc6b7125293f90dfec7a60440028b7e4e8fca71 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 26 Oct 2021 11:39:15 -0600 Subject: [PATCH 19/21] whitespace --- system/config/system.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/config/system.yaml b/system/config/system.yaml index 3d0983c310..652910d863 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -96,7 +96,7 @@ cache: purge_at: '0 4 * * *' # How often to purge old file cache (using new scheduler) clear_at: '0 3 * * *' # How often to clear cache (using new scheduler) clear_job_type: 'standard' # Type to clear when processing the scheduled clear job `standard`|`all` - clear_images_by_default: false # By default grav does not include processed images in cache clear, this can be enabled + clear_images_by_default: false # By default grav does not include processed images in cache clear, this can be enabled cli_compatibility: false # Ensures only non-volatile drivers are used (file, redis, memcache, etc.) lifetime: 604800 # Lifetime of cached data in seconds (0 = infinite) gzip: false # GZip compress the page output From 917aa9407ddb2b45ba14d876ffa78e74a2343368 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 26 Oct 2021 13:44:43 -0600 Subject: [PATCH 20/21] updated vendor libs --- composer.lock | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index df02b8d5ad..5fbc07ac55 100644 --- a/composer.lock +++ b/composer.lock @@ -4065,16 +4065,16 @@ }, { "name": "guzzlehttp/promises", - "version": "1.5.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0" + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0", - "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0", + "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", "shasum": "" }, "require": { @@ -4129,7 +4129,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.0" + "source": "https://github.com/guzzle/promises/tree/1.5.1" }, "funding": [ { @@ -4145,7 +4145,7 @@ "type": "tidelift" } ], - "time": "2021-10-07T13:05:22+00:00" + "time": "2021-10-22T20:56:57+00:00" }, { "name": "myclabs/deep-copy", @@ -6040,7 +6040,6 @@ "type": "github" } ], - "abandoned": true, "time": "2020-09-28T06:45:17+00:00" }, { @@ -6621,5 +6620,5 @@ "platform-overrides": { "php": "7.3.6" }, - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.1.0" } From 4db28bf47ede3d4fe38e706a9f027474f48f7b34 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 26 Oct 2021 13:45:30 -0600 Subject: [PATCH 21/21] prepare for release --- CHANGELOG.md | 2 +- system/defines.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17cc376188..5320a0e5aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # v1.7.24 -## mm/dd/2021 +## 10/26/2021 1. [](#new) * Added support for image watermarks diff --git a/system/defines.php b/system/defines.php index e3cbb369fe..633534327e 100644 --- a/system/defines.php +++ b/system/defines.php @@ -9,7 +9,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '1.7.23'); +define('GRAV_VERSION', '1.7.24'); define('GRAV_SCHEMA', '1.7.0_2020-11-20_1'); define('GRAV_TESTING', false);