mirror of
https://github.com/getgrav/grav.git
synced 2026-02-21 05:58:01 +01:00
Merge branch 'release/1.7.32'
This commit is contained in:
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,3 +1,21 @@
|
||||
# v1.7.32
|
||||
## 03/28/2022
|
||||
|
||||
1. [](#new)
|
||||
* Added `|replace_last(search, replace)` filter
|
||||
* Added `parseurl` Twig function to expose PHP's `parse_url` function
|
||||
2. [](#improved)
|
||||
* Added multi-language support for page routes in `Utils::url()`
|
||||
* Set default maximum length for text fields
|
||||
- `password`: 256
|
||||
- `email`: 320
|
||||
- `text`, `url`, `hidden`, `commalist`: 2048
|
||||
- `text` (multiline), `textarea`: 65536
|
||||
3. [](#bugfix)
|
||||
* Fixed issue with `system.cache.gzip: true` resulted in "Fetch Failed" for PHP 8.0.17 and PHP 8.1.4 [PHP issue #8218](https://github.com/php/php-src/issues/8218)
|
||||
* Fix for multi-lang issues with Security Report
|
||||
* Fixed page search not working with selected language [#3316](https://github.com/getgrav/grav/issues/3316)
|
||||
|
||||
# v1.7.31
|
||||
## 03/14/2022
|
||||
|
||||
|
||||
95
composer.lock
generated
95
composer.lock
generated
@@ -730,16 +730,16 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.8.3",
|
||||
"version": "1.8.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85"
|
||||
"reference": "337e3ad8e5716c15f9657bd214d16cc5e69df268"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/337e3ad8e5716c15f9657bd214d16cc5e69df268",
|
||||
"reference": "337e3ad8e5716c15f9657bd214d16cc5e69df268",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -820,7 +820,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.3"
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -836,7 +836,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-05T13:56:00+00:00"
|
||||
"time": "2022-03-20T21:51:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "itsgoingd/clockwork",
|
||||
@@ -1230,16 +1230,16 @@
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "1.26.1",
|
||||
"version": "1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Seldaek/monolog.git",
|
||||
"reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5"
|
||||
"reference": "52ebd235c1f7e0d5e1b16464b695a28335f8e44a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/c6b00f05152ae2c9b04a448f99c7590beb6042f5",
|
||||
"reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5",
|
||||
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/52ebd235c1f7e0d5e1b16464b695a28335f8e44a",
|
||||
"reference": "52ebd235c1f7e0d5e1b16464b695a28335f8e44a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1300,7 +1300,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Seldaek/monolog/issues",
|
||||
"source": "https://github.com/Seldaek/monolog/tree/1.26.1"
|
||||
"source": "https://github.com/Seldaek/monolog/tree/1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1312,7 +1312,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-05-28T08:32:12+00:00"
|
||||
"time": "2022-03-13T20:29:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "multiavatar/multiavatar-php",
|
||||
@@ -3491,16 +3491,16 @@
|
||||
},
|
||||
{
|
||||
"name": "codeception/codeception",
|
||||
"version": "4.1.30",
|
||||
"version": "4.1.31",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/Codeception.git",
|
||||
"reference": "a035d77d070fa57fad438e07a65447aeca248c45"
|
||||
"reference": "15524571ae0686a7facc2eb1f40f600e5bbce9e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/a035d77d070fa57fad438e07a65447aeca248c45",
|
||||
"reference": "a035d77d070fa57fad438e07a65447aeca248c45",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/15524571ae0686a7facc2eb1f40f600e5bbce9e5",
|
||||
"reference": "15524571ae0686a7facc2eb1f40f600e5bbce9e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3577,7 +3577,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Codeception/Codeception/issues",
|
||||
"source": "https://github.com/Codeception/Codeception/tree/4.1.30"
|
||||
"source": "https://github.com/Codeception/Codeception/tree/4.1.31"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3585,7 +3585,7 @@
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-05T18:12:30+00:00"
|
||||
"time": "2022-03-13T17:07:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/lib-asserts",
|
||||
@@ -4025,16 +4025,16 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.4.1",
|
||||
"version": "7.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79"
|
||||
"reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ee0a041b1760e6a53d2a39c8c34115adc2af2c79",
|
||||
"reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ac1ec1cd9b5624694c3a40be801d94137afb12b4",
|
||||
"reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4129,7 +4129,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/guzzle/issues",
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.4.1"
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4145,7 +4145,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-12-06T18:43:05+00:00"
|
||||
"time": "2022-03-20T14:16:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
@@ -4686,16 +4686,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.4.8",
|
||||
"version": "1.4.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "2a6d6704b17c4db6190cc3104056c0aad740cb15"
|
||||
"reference": "898c479c39caa727bedf4311dd294a8f4e250e72"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/2a6d6704b17c4db6190cc3104056c0aad740cb15",
|
||||
"reference": "2a6d6704b17c4db6190cc3104056c0aad740cb15",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/898c479c39caa727bedf4311dd294a8f4e250e72",
|
||||
"reference": "898c479c39caa727bedf4311dd294a8f4e250e72",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4709,11 +4709,6 @@
|
||||
"phpstan.phar"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
@@ -4726,7 +4721,7 @@
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.4.8"
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.4.10"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4746,7 +4741,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-04T13:03:56+00:00"
|
||||
"time": "2022-03-14T10:25:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
@@ -5118,16 +5113,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.5.18",
|
||||
"version": "9.5.19",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "1b5856028273bfd855e60a887278857d872ec67a"
|
||||
"reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b5856028273bfd855e60a887278857d872ec67a",
|
||||
"reference": "1b5856028273bfd855e60a887278857d872ec67a",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/35ea4b7f3acabb26f4bb640f8c30866c401da807",
|
||||
"reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5157,7 +5152,7 @@
|
||||
"sebastian/global-state": "^5.0.1",
|
||||
"sebastian/object-enumerator": "^4.0.3",
|
||||
"sebastian/resource-operations": "^3.0.3",
|
||||
"sebastian/type": "^2.3.4",
|
||||
"sebastian/type": "^3.0",
|
||||
"sebastian/version": "^3.0.2"
|
||||
},
|
||||
"require-dev": {
|
||||
@@ -5205,7 +5200,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.18"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.19"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5217,7 +5212,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-08T06:52:28+00:00"
|
||||
"time": "2022-03-15T09:57:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-client",
|
||||
@@ -6128,28 +6123,28 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/type",
|
||||
"version": "2.3.4",
|
||||
"version": "3.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/type.git",
|
||||
"reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914"
|
||||
"reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914",
|
||||
"reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
|
||||
"reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.3"
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3-dev"
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -6172,7 +6167,7 @@
|
||||
"homepage": "https://github.com/sebastianbergmann/type",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/type/issues",
|
||||
"source": "https://github.com/sebastianbergmann/type/tree/2.3.4"
|
||||
"source": "https://github.com/sebastianbergmann/type/tree/3.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6180,7 +6175,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-06-15T12:49:02+00:00"
|
||||
"time": "2022-03-15T09:54:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/version",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.7.31');
|
||||
define('GRAV_VERSION', '1.7.32');
|
||||
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
|
||||
define('GRAV_TESTING', false);
|
||||
|
||||
|
||||
@@ -246,7 +246,9 @@ class Validation
|
||||
return false;
|
||||
}
|
||||
|
||||
$max = (int)($params['max'] ?? 0);
|
||||
$multiline = isset($params['multiline']) && $params['multiline'];
|
||||
|
||||
$max = (int)($params['max'] ?? ($multiline ? 65536 : 2048));
|
||||
if ($max && $len > $max) {
|
||||
return false;
|
||||
}
|
||||
@@ -256,7 +258,7 @@ class Validation
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!isset($params['multiline']) || !$params['multiline']) && preg_match('/\R/um', $value)) {
|
||||
if (!$multiline && preg_match('/\R/um', $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -317,6 +319,10 @@ class Validation
|
||||
*/
|
||||
public static function typeCommaList($value, array $params, array $field)
|
||||
{
|
||||
if (!isset($params['max'])) {
|
||||
$params['max'] = 2048;
|
||||
}
|
||||
|
||||
return is_array($value) ? true : self::typeText($value, $params, $field);
|
||||
}
|
||||
|
||||
@@ -379,6 +385,10 @@ class Validation
|
||||
*/
|
||||
public static function typePassword($value, array $params, array $field)
|
||||
{
|
||||
if (!isset($params['max'])) {
|
||||
$params['max'] = 256;
|
||||
}
|
||||
|
||||
return self::typeText($value, $params, $field);
|
||||
}
|
||||
|
||||
@@ -621,6 +631,10 @@ class Validation
|
||||
*/
|
||||
public static function typeEmail($value, array $params, array $field)
|
||||
{
|
||||
if (!isset($params['max'])) {
|
||||
$params['max'] = 320;
|
||||
}
|
||||
|
||||
$values = !is_array($value) ? explode(',', preg_replace('/\s+/', '', $value)) : $value;
|
||||
|
||||
foreach ($values as $val) {
|
||||
@@ -642,6 +656,10 @@ class Validation
|
||||
*/
|
||||
public static function typeUrl($value, array $params, array $field)
|
||||
{
|
||||
if (!isset($params['max'])) {
|
||||
$params['max'] = 2048;
|
||||
}
|
||||
|
||||
return self::typeText($value, $params, $field) && filter_var($value, FILTER_VALIDATE_URL);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,4 +43,25 @@ class SystemFacade extends \Whoops\Util\SystemFacade
|
||||
$handler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $httpCode
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function setHttpResponseCode($httpCode)
|
||||
{
|
||||
if (!headers_sent()) {
|
||||
// Ensure that no 'location' header is present as otherwise this
|
||||
// will override the HTTP code being set here, and mask the
|
||||
// expected error page.
|
||||
header_remove('location');
|
||||
|
||||
// Work around PHP bug #8218 (8.0.17 & 8.1.4).
|
||||
header_remove('Content-Encoding');
|
||||
}
|
||||
|
||||
return http_response_code($httpCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,7 +454,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the main key without template and langauge.
|
||||
// Get the main key without template and language.
|
||||
[$main_key,] = explode('|', $entry['storage_key'] . '|', 2);
|
||||
|
||||
// Update storage key and language.
|
||||
@@ -527,10 +527,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
$language = $options['lang'];
|
||||
|
||||
$status = 'error';
|
||||
$msg = null;
|
||||
$response = [];
|
||||
$children = null;
|
||||
$sub_route = null;
|
||||
$extra = null;
|
||||
|
||||
// Handle leaf_route
|
||||
@@ -610,7 +607,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
$children = $page->children();
|
||||
/** @var PageIndex $children */
|
||||
$children = $children->getIndex();
|
||||
$selectedChildren = $children->filterBy($filters, true);
|
||||
$selectedChildren = $children->filterBy($filters + ['language' => $language], true);
|
||||
|
||||
/** @var Header $header */
|
||||
$header = $page->header();
|
||||
|
||||
@@ -242,6 +242,7 @@ class PageObject extends FlexPageObject
|
||||
{
|
||||
/** @var PageCollection $siblings */
|
||||
$siblings = $variables['siblings'];
|
||||
/** @var PageObject $sibling */
|
||||
foreach ($siblings as $sibling) {
|
||||
$sibling->save(false);
|
||||
}
|
||||
@@ -585,38 +586,46 @@ class PageObject extends FlexPageObject
|
||||
*/
|
||||
public function filterBy(array $filters, bool $recursive = false): bool
|
||||
{
|
||||
$language = $filters['language'] ?? null;
|
||||
if (null !== $language) {
|
||||
/** @var PageObject $test */
|
||||
$test = $this->getTranslation($language) ?? $this;
|
||||
} else {
|
||||
$test = $this;
|
||||
}
|
||||
|
||||
foreach ($filters as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'search':
|
||||
$matches = $this->search((string)$value) > 0.0;
|
||||
$matches = $test->search((string)$value) > 0.0;
|
||||
break;
|
||||
case 'page_type':
|
||||
$types = $value ? explode(',', $value) : [];
|
||||
$matches = in_array($this->template(), $types, true);
|
||||
$matches = in_array($test->template(), $types, true);
|
||||
break;
|
||||
case 'extension':
|
||||
$matches = Utils::contains((string)$value, $this->extension());
|
||||
$matches = Utils::contains((string)$value, $test->extension());
|
||||
break;
|
||||
case 'routable':
|
||||
$matches = $this->isRoutable() === (bool)$value;
|
||||
$matches = $test->isRoutable() === (bool)$value;
|
||||
break;
|
||||
case 'published':
|
||||
$matches = $this->isPublished() === (bool)$value;
|
||||
$matches = $test->isPublished() === (bool)$value;
|
||||
break;
|
||||
case 'visible':
|
||||
$matches = $this->isVisible() === (bool)$value;
|
||||
$matches = $test->isVisible() === (bool)$value;
|
||||
break;
|
||||
case 'module':
|
||||
$matches = $this->isModule() === (bool)$value;
|
||||
$matches = $test->isModule() === (bool)$value;
|
||||
break;
|
||||
case 'page':
|
||||
$matches = $this->isPage() === (bool)$value;
|
||||
$matches = $test->isPage() === (bool)$value;
|
||||
break;
|
||||
case 'folder':
|
||||
$matches = $this->isPage() === !$value;
|
||||
$matches = $test->isPage() === !$value;
|
||||
break;
|
||||
case 'translated':
|
||||
$matches = $this->hasTranslation() === (bool)$value;
|
||||
$matches = $test->hasTranslation() === (bool)$value;
|
||||
break;
|
||||
default:
|
||||
$matches = true;
|
||||
|
||||
@@ -341,6 +341,23 @@ class Grav extends Container
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean any output buffers. Useful when exiting from the application.
|
||||
*
|
||||
* Please use $grav->close() and $grav->redirect() instead of calling this one!
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanOutputBuffers(): void
|
||||
{
|
||||
// Make sure nothing extra gets written to the response.
|
||||
while (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
// Work around PHP bug #8218 (8.0.17 & 8.1.4).
|
||||
header_remove('Content-Encoding');
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates Grav request with a response.
|
||||
*
|
||||
@@ -351,10 +368,7 @@ class Grav extends Container
|
||||
*/
|
||||
public function close(ResponseInterface $response): void
|
||||
{
|
||||
// Make sure nothing extra gets written to the response.
|
||||
while (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
$this->cleanOutputBuffers();
|
||||
|
||||
// Close the session.
|
||||
if (isset($this['session'])) {
|
||||
@@ -400,7 +414,7 @@ class Grav extends Container
|
||||
/**
|
||||
* @param ResponseInterface $response
|
||||
* @return never-return
|
||||
* @deprecated 1.7 Do not use
|
||||
* @deprecated 1.7 Use $grav->close() instead.
|
||||
*/
|
||||
public function exit(ResponseInterface $response): void
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@ class Security
|
||||
*/
|
||||
public static function detectXssFromPages(Pages $pages, $route = true, callable $status = null)
|
||||
{
|
||||
$routes = $pages->routes();
|
||||
$routes = $pages->getList(null, 0, true);
|
||||
|
||||
// Remove duplicate for homepage
|
||||
unset($routes['/']);
|
||||
@@ -110,26 +110,23 @@ class Security
|
||||
'steps' => count($routes),
|
||||
]);
|
||||
|
||||
foreach ($routes as $path) {
|
||||
foreach (array_keys($routes) as $route) {
|
||||
$status && $status([
|
||||
'type' => 'progress',
|
||||
]);
|
||||
|
||||
try {
|
||||
$page = $pages->get($path);
|
||||
$page = $pages->find($route);
|
||||
if ($page->exists()) {
|
||||
// call the content to load/cache it
|
||||
$header = (array) $page->header();
|
||||
$content = $page->value('content');
|
||||
|
||||
// call the content to load/cache it
|
||||
$header = (array) $page->header();
|
||||
$content = $page->value('content');
|
||||
$data = ['header' => $header, 'content' => $content];
|
||||
$results = static::detectXssFromArray($data);
|
||||
|
||||
$data = ['header' => $header, 'content' => $content];
|
||||
$results = static::detectXssFromArray($data);
|
||||
|
||||
if (!empty($results)) {
|
||||
if ($route) {
|
||||
$list[$page->route()] = $results;
|
||||
} else {
|
||||
$list[$page->filePathClean()] = $results;
|
||||
if (!empty($results)) {
|
||||
$list[$page->rawRoute()] = $results;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
|
||||
@@ -145,6 +145,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface
|
||||
new TwigFilter('yaml_encode', [$this, 'yamlEncodeFilter']),
|
||||
new TwigFilter('yaml_decode', [$this, 'yamlDecodeFilter']),
|
||||
new TwigFilter('nicecron', [$this, 'niceCronFilter']),
|
||||
new TwigFilter('replace_last', [$this, 'replaceLastFilter']),
|
||||
|
||||
// Translations
|
||||
new TwigFilter('t', [$this, 'translate'], ['needs_environment' => true]),
|
||||
@@ -194,6 +195,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface
|
||||
new TwigFunction('gist', [$this, 'gistFunc']),
|
||||
new TwigFunction('nonce_field', [$this, 'nonceFieldFunc']),
|
||||
new TwigFunction('pathinfo', 'pathinfo'),
|
||||
new TwigFunction('parseurl', 'parse_url'),
|
||||
new TwigFunction('random_string', [$this, 'randomStringFunc']),
|
||||
new TwigFunction('repeat', [$this, 'repeatFunc']),
|
||||
new TwigFunction('regex_replace', [$this, 'regexReplace']),
|
||||
@@ -547,6 +549,21 @@ class GravExtension extends AbstractExtension implements GlobalsInterface
|
||||
return $cron->getText('en');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|mixed $str
|
||||
* @param string $search
|
||||
* @param string $replace
|
||||
* @return string|mixed
|
||||
*/
|
||||
public function replaceLastFilter($str, $search, $replace)
|
||||
{
|
||||
if (is_string($str) && ($pos = mb_strrpos($str, $search)) !== false) {
|
||||
$str = mb_substr($str, 0, $pos) . $replace . mb_substr($str, $pos + mb_strlen($search));
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Cron object for a crontab 'at' format
|
||||
*
|
||||
|
||||
@@ -83,6 +83,7 @@ abstract class Utils
|
||||
|
||||
$resource = false;
|
||||
if (static::contains((string)$input, '://')) {
|
||||
// Url contains a scheme (https:// , user:// etc).
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $grav['locator'];
|
||||
|
||||
@@ -134,6 +135,16 @@ abstract class Utils
|
||||
$resource = $locator->findResource($input, false);
|
||||
}
|
||||
} else {
|
||||
// Just a path.
|
||||
/** @var Pages $pages */
|
||||
$pages = $grav['pages'];
|
||||
|
||||
// Is this a page?
|
||||
$page = $pages->find($input, true);
|
||||
if ($page && $page->routable()) {
|
||||
return $page->url($domain);
|
||||
}
|
||||
|
||||
$root = preg_quote($uri->rootUrl(), '#');
|
||||
$pattern = '#(' . $root . '$|' . $root . '/)#';
|
||||
if (!empty($root) && preg_match($pattern, $input, $matches)) {
|
||||
@@ -657,18 +668,17 @@ abstract class Utils
|
||||
*/
|
||||
public static function download($file, $force_download = true, $sec = 0, $bytes = 1024, array $options = [])
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
|
||||
if (file_exists($file)) {
|
||||
// fire download event
|
||||
Grav::instance()->fireEvent('onBeforeDownload', new Event(['file' => $file, 'options' => &$options]));
|
||||
$grav->fireEvent('onBeforeDownload', new Event(['file' => $file, 'options' => &$options]));
|
||||
|
||||
$file_parts = static::pathinfo($file);
|
||||
$mimetype = $options['mime'] ?? static::getMimeByExtension($file_parts['extension']);
|
||||
$size = filesize($file); // File size
|
||||
|
||||
// clean all buffers
|
||||
while (ob_get_level()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
$grav->cleanOutputBuffers();
|
||||
|
||||
// required for IE, otherwise Content-Disposition may be ignored
|
||||
if (ini_get('zlib.output_compression')) {
|
||||
@@ -703,8 +713,8 @@ abstract class Utils
|
||||
$new_length = $size;
|
||||
header('Content-Length: ' . $size);
|
||||
|
||||
if (Grav::instance()['config']->get('system.cache.enabled')) {
|
||||
$expires = $options['expires'] ?? Grav::instance()['config']->get('system.pages.expires');
|
||||
if ($grav['config']->get('system.cache.enabled')) {
|
||||
$expires = $options['expires'] ?? $grav['config']->get('system.pages.expires');
|
||||
if ($expires > 0) {
|
||||
$expires_date = gmdate('D, d M Y H:i:s T', time() + $expires);
|
||||
header('Cache-Control: max-age=' . $expires);
|
||||
|
||||
@@ -147,6 +147,10 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
|
||||
*/
|
||||
public function search(string $search, $properties = null, array $options = null)
|
||||
{
|
||||
$directory = $this->getFlexDirectory();
|
||||
$properties = $directory->getSearchProperties($properties);
|
||||
$options = $directory->getSearchOptions($options);
|
||||
|
||||
$matching = $this->call('search', [$search, $properties, $options]);
|
||||
$matching = array_filter($matching);
|
||||
|
||||
|
||||
@@ -170,6 +170,44 @@ class FlexDirectory implements FlexDirectoryInterface
|
||||
return null === $name ? $this->config : $this->config->get($name, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|string[]|null
|
||||
* @return array
|
||||
*/
|
||||
public function getSearchProperties($properties = null): array
|
||||
{
|
||||
if (null !== $properties) {
|
||||
return (array)$properties;
|
||||
}
|
||||
|
||||
$properties = $this->getConfig('data.search.fields');
|
||||
if (!$properties) {
|
||||
$fields = $this->getConfig('admin.views.list.fields') ?? $this->getConfig('admin.list.fields', []);
|
||||
foreach ($fields as $property => $value) {
|
||||
if (!empty($value['link'])) {
|
||||
$properties[] = $property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $options
|
||||
* @return array
|
||||
*/
|
||||
public function getSearchOptions(array $options = null): array
|
||||
{
|
||||
if (empty($options['merge'])) {
|
||||
return $options ?? (array)$this->getConfig('data.search.options');
|
||||
}
|
||||
|
||||
unset($options['merge']);
|
||||
|
||||
return $options + (array)$this->getConfig('data.search.options');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @param array $options
|
||||
|
||||
@@ -162,6 +162,10 @@ class FlexIndex extends ObjectIndex implements FlexIndexInterface
|
||||
*/
|
||||
public function search(string $search, $properties = null, array $options = null)
|
||||
{
|
||||
$directory = $this->getFlexDirectory();
|
||||
$properties = $directory->getSearchProperties($properties);
|
||||
$options = $directory->getSearchOptions($options);
|
||||
|
||||
return $this->__call('search', [$search, $properties, $options]);
|
||||
}
|
||||
|
||||
|
||||
@@ -287,17 +287,9 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
|
||||
*/
|
||||
public function search(string $search, $properties = null, array $options = null): float
|
||||
{
|
||||
$properties = (array)($properties ?? $this->getFlexDirectory()->getConfig('data.search.fields'));
|
||||
if (!$properties) {
|
||||
$fields = $this->getFlexDirectory()->getConfig('admin.views.list.fields') ?? $this->getFlexDirectory()->getConfig('admin.list.fields', []);
|
||||
foreach ($fields as $property => $value) {
|
||||
if (!empty($value['link'])) {
|
||||
$properties[] = $property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$options = $options ?? (array)$this->getFlexDirectory()->getConfig('data.search.options');
|
||||
$directory = $this->getFlexDirectory();
|
||||
$properties = $directory->getSearchProperties($properties);
|
||||
$options = $directory->getSearchOptions($options);
|
||||
|
||||
$weight = 0;
|
||||
foreach ($properties as $property) {
|
||||
|
||||
Reference in New Issue
Block a user