This commit is contained in:
Ouidade Soussi Chiadmi 2022-03-15 10:52:21 +01:00
parent 12814f64d4
commit ef94f03cde
476 changed files with 4612 additions and 1563 deletions

View File

@ -1,3 +1,120 @@
# v1.7.31
## 03/14/2022
1. [](#new)
* Added new local Multiavatar (local generation). **This will be default in Grav 1.8**
* Added support to get image size for SVG vector images [#3533](https://github.com/getgrav/grav/pull/3533)
* Added XSS check for uploaded SVG files before they get stored
* Fixed phpstan issues (All level 2, Framework level 5)
2. [](#improved)
* Moved Accounts out of Experimental section of System configuration to new "Accounts" tab
3. [](#bugfix)
* Fixed `'mbstring' extension is not loaded` error, use Polyfill instead [#3504](https://github.com/getgrav/grav/pull/3504)
* Fixed new `Utils::pathinfo()` and `Utils::basename()` being too strict for legacy use [#3542](https://github.com/getgrav/grav/issues/3542)
* Fixed non-standard video html atributes generated by `{{ media.html() }}` [#3540](https://github.com/getgrav/grav/issues/3540)
* Fixed entity sanitization for XSS detection
* Fixed avatar save location when `account://` stream points to custom directory
* Fixed bug in `Utils::url()` when path contains part of root
# v1.7.30
## 02/07/2022
1. [](#new)
* Added twig filter `|field_parent` to get parent field name
2. [](#bugfix)
* Fixed error while deleting retina image in admin
* Fixed "Page Authors" field in Security tab, wrongly loading and saving the value [#3525](https://github.com/getgrav/grav/issues/3525)
* Fixed accounts filter only matches against email address [getgrav/grav-plugin-admin#2224](https://github.com/getgrav/grav-plugin-admin/issues/2224)
# v1.7.29.1
## 01/31/2022
1. [](#bugfix)
* Fixed `Call to undefined method` error when upgrading from Grav 1.6 [#3523](https://github.com/getgrav/grav/issues/3523)
# v1.7.29
## 01/28/2022
1. [](#new)
* Added support for registering assets from `HtmlBlock`
* Added unicode-safe `Utils::basename()` and `Utils::pathinfo()` methods
2. [](#improved)
* Improved `Filesystem::basename()` and `Filesystem::pathinfo()` to be unicode-safe
* Made path handling unicode-safe, use new `Utils::basename()` and `Utils::pathinfo()` everywhere
3. [](#bugfix)
* Fixed error on thumbnail image creation
* Fixed MimeType for `gzip` (`application/x-gzip`)
# v1.7.28
## 01/24/2022
1. [](#new)
* Added links and modules support to `HtmlBlock` class
* Added module support for twig script tag: `{% script module 'theme://js/module.mjs' %}`
* Added twig tag for links: `{% link icon 'theme://images/favicon.png' priority: 20 with { type: 'image/png' } %}`
* Added `HtmlBlock` support for `{% style %}`, `{% script %}` and `{% link %}` tags
* Support for page-level `redirect_default_route` frontmatter header override
3. [](#bugfix)
* Fixed XSS check not detecting escaped `&#58`
# v1.7.27.1
## 01/12/2022
3. [](#bugfix)
* Fixed a typo in CSS Asset pipeline that was erroneously joining files with `;`
# v1.7.27
## 01/12/2022
1. [](#new)
* Support for `YubiKey OTP` 2-Factor authenticator
* Added support for generic `assets.link()` for external references. No pipeline support
* Added support for `assets.addJsModule()` with full pipeline support
* Added `Utils::getExtensionsByMime()` method to get all the registered extensions for the specific mime type
* Added `Media::getRoute()` and `Media::getRawRoute()` methods to get page route if available
* Added `Medium::getAlternatives()` to be able to list all the retina sizes
2. [](#improved)
* Improved `Utils::download()` method to allow overrides on download name, mime and expires header
* Improved `onPageFallBackUrl` event
* Reorganized the Asset system configuration blueprint for clarity
3. [](#bugfix)
* Fixed CLI `--env` and `--lang` options having no effect if they aren't added before all the other options
* Fixed scaled image medium filename when using non-existing retina file
* Fixed an issue with JS `imports` and pipelining Assets
# v1.7.26.1
## 01/04/2022
3. [](#bugfix)
* Fixed `UserObject::getAccess()` after cloning the object
# v1.7.26
## 01/03/2022
1. [](#new)
* Made `Grav::redirect()` to accept `Route` class
* Added `translated()` method to `PageTranslateInterface`
* Added second parameter to `UserObject::isMyself()` method
* Added `UserObject::$isAuthorizedCallable` to allow `$user->isAuthorized()` customization
* Use secure session cookies in HTTPS by default (`system.session.secure_https: true`)
* Added new `Plugin::inheritedConfigOption()` function to access plugin specific functions for page overrides
2. [](#improved)
* Upgraded vendor libs for PHP 8.1 compatibility
* Upgraded to **composer v2.1.14** for PHP 8.1 compatibility
* Added third `$name` parameter to `Blueprint::flattenData()` method, useful for flattening repeating data
* `ControllerResponseTrait`: Redirect response should be json if the extension is .json
* When symlinking Grav install, include also tests
* Updated copyright year to `2022`
3. [](#bugfix)
* Fixed bad key lookup in `FlexRelatedDirectoryTrait::getCollectionByProperty()`
* Fixed RequestHandlers `NotFoundException` having empty request
* Block `.json` files in web server configs
* Disabled pretty debug info for Flex as it slows down Twig rendering
* Fixed Twig being very slow when template overrides do not exist
* Fixed `UserObject::$authorizeCallable` binding to the user object
* Fixed `FlexIndex::call()` to return null instead of failing to call undefined method
* Fixed Flex directory configuration creating environment configuration when it should not
# v1.7.25
## 11/16/2021

View File

@ -2,18 +2,18 @@
[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat)](https://github.com/phpstan/phpstan)
[![Discord](https://img.shields.io/discord/501836936584101899.svg?logo=discord&colorB=728ADA&label=Discord%20Chat)](https://chat.getgrav.org)
[![PHP Tests](https://github.com/getgrav/grav/workflows/PHP%20Tests/badge.svg?branch=develop)](https://github.com/getgrav/grav/actions?query=workflow%3A%22PHP+Tests%22) [![OpenCollective](https://opencollective.com/grav/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/grav/sponsors/badge.svg)](#sponsors)
[![PHP Tests](https://github.com/getgrav/grav/workflows/PHP%20Tests/badge.svg?branch=develop)](https://github.com/getgrav/grav/actions?query=workflow%3A%22PHP+Tests%22) [![OpenCollective](https://opencollective.com/grav/tiers/backers/badge.svg?label=Backers&color=brightgreen)](#backers) [![OpenCollective](https://opencollective.com/grav/tiers/supporters/badge.svg?label=Supporters&color=brightgreen)](#supporters) [![OpenCollective](https://opencollective.com/grav/tiers/sponsors/badge.svg?label=Sponsors&color=brightgreen)](#sponsors)
Grav is a **Fast**, **Simple**, and **Flexible**, file-based Web-platform. There is **Zero** installation required. Just extract the ZIP archive, and you are already up and running. It follows similar principles to other flat-file CMS platforms, but has a different design philosophy than most. Grav comes with a powerful **Package Management System** to allow for simple installation and upgrading of plugins and themes, as well as simple updating of Grav itself.
The underlying architecture of Grav is designed to use well-established and _best-in-class_ technologies to ensure that Grav is simple to use and easy to extend. Some of these key technologies include:
* [Twig Templating](https://twig.sensiolabs.org/): for powerful control of the user interface
* [Twig Templating](https://twig.symfony.com/): for powerful control of the user interface
* [Markdown](https://en.wikipedia.org/wiki/Markdown): for easy content creation
* [YAML](https://yaml.org): for simple configuration
* [Parsedown](https://parsedown.org/): for fast Markdown and Markdown Extra support
* [Doctrine Cache](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/caching.html): layer for performance
* [Pimple Dependency Injection Container](https://pimple.sensiolabs.org/): for extensibility and maintainability
* [Pimple Dependency Injection Container](https://github.com/silexphp/Pimple): for extensibility and maintainability
* [Symfony Event Dispatcher](https://symfony.com/doc/current/components/event_dispatcher/introduction.html): for plugin event handling
* [Symfony Console](https://symfony.com/doc/current/components/console/introduction.html): for CLI interface
* [Gregwar Image Library](https://github.com/Gregwar/Image): for dynamic image manipulation
@ -117,12 +117,19 @@ If you discover a possible security issue related to Grav or one of its plugins,
* More [Awesome Grav Stuff](https://github.com/getgrav/awesome-grav)
# Backers
Support Grav with a monthly donation to help us continue development. [[Become a backer](https://opencollective.com/grav#backer)]
Support Grav with a monthly donation to help us continue development. [[Become a backer](https://opencollective.com/grav/contribute)]
<img src="https://opencollective.com/grav/tiers/backers.svg?avatarHeight=36&width=600" />
# Supporters
Support Grav with a monthly donation to help us continue development. [[Become a supporter](https://opencollective.com/grav/contribute)]
<img src="https://opencollective.com/grav/tiers/supporters.svg?avatarHeight=36&width=600" />
# Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/grav#sponsor)]
Support Grav with a yearly donation to help us continue development. [[Become a sponsor](https://opencollective.com/grav/contribute)]
<img src="https://opencollective.com/grav/tiers/sponsors.svg?avatarHeight=36&width=600" />

View File

@ -1 +1 @@
/* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved. */
/* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved. */

Binary file not shown.

14
bin/gpm
View File

@ -2,7 +2,7 @@
<?php
/**
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -25,18 +25,10 @@ if (!file_exists(__DIR__ . '/../vendor/autoload.php')){
$autoload = require __DIR__ . '/../vendor/autoload.php';
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
}
if (!ini_get('date.timezone')) {
date_default_timezone_set('UTC');
}
// Set timezone to default, falls back to system if php.ini not set
date_default_timezone_set(@date_default_timezone_get());
// Set internal encoding.
if (!\extension_loaded('mbstring')) {
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
}
@ini_set('default_charset', 'UTF-8');
mb_internal_encoding('UTF-8');

View File

@ -2,7 +2,7 @@
<?php
/**
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -25,18 +25,10 @@ if (!file_exists(__DIR__ . '/../vendor/autoload.php')){
$autoload = require __DIR__ . '/../vendor/autoload.php';
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
}
if (!ini_get('date.timezone')) {
date_default_timezone_set('UTC');
}
// Set timezone to default, falls back to system if php.ini not set
date_default_timezone_set(@date_default_timezone_get());
// Set internal encoding.
if (!\extension_loaded('mbstring')) {
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
}
@ini_set('default_charset', 'UTF-8');
mb_internal_encoding('UTF-8');

View File

@ -2,7 +2,7 @@
<?php
/**
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -25,18 +25,10 @@ if (!file_exists(__DIR__ . '/../vendor/autoload.php')){
$autoload = require __DIR__ . '/../vendor/autoload.php';
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
}
if (!ini_get('date.timezone')) {
date_default_timezone_set('UTC');
}
// Set timezone to default, falls back to system if php.ini not set
date_default_timezone_set(@date_default_timezone_get());
// Set internal encoding.
if (!\extension_loaded('mbstring')) {
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
}
@ini_set('default_charset', 'UTF-8');
mb_internal_encoding('UTF-8');

View File

@ -19,7 +19,7 @@
"ext-zip": "*",
"ext-dom": "*",
"ext-libxml": "*",
"symfony/polyfill-mbstring": "~1.20",
"symfony/polyfill-mbstring": "~1.23",
"symfony/polyfill-iconv": "^1.23",
"symfony/polyfill-php74": "^1.23",
"symfony/polyfill-php80": "^1.23",
@ -27,10 +27,10 @@
"psr/simple-cache": "^1.0",
"psr/http-message": "^1.0",
"psr/http-server-middleware": "^1.0",
"psr/container": "~1.0.0",
"psr/container": "~1.1.0",
"nyholm/psr7-server": "^1.0",
"nyholm/psr7": "^1.3",
"twig/twig": "~1.44",
"twig/twig": "~v1.44",
"erusev/parsedown": "^1.7",
"erusev/parsedown-extra": "~0.8",
"symfony/contracts": "~1.1",
@ -48,11 +48,10 @@
"getgrav/image": "^3.0",
"getgrav/cache": "^2.0",
"donatj/phpuseragentparser": "~1.1",
"pimple/pimple": "~3.3.0",
"pimple/pimple": "~3.5.0",
"rockettheme/toolbox": "~1.5",
"maximebf/debugbar": "~1.16",
"league/climate": "^3.6",
"antoligy/dom-string-iterators": "^1.0",
"miljar/php-exif": "^0.6",
"composer/ca-bundle": "^1.2",
"dragonmantank/cron-expression": "^1.2",
@ -60,11 +59,12 @@
"itsgoingd/clockwork": "^5.0",
"symfony/http-client": "^4.4",
"composer/semver": "^1.4",
"rhukster/dom-sanitizer": "^1.0"
"rhukster/dom-sanitizer": "^1.0",
"multiavatar/multiavatar-php": "^1.0"
},
"require-dev": {
"codeception/codeception": "^4.1",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan": "^1.2",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpunit/php-code-coverage": "~9.2",
"getgrav/markdowndocs": "^2.0",
@ -83,7 +83,8 @@
"ext-intl": "Recommended for multi-language sites",
"ext-memcache": "Needed to support Memcache servers",
"ext-memcached": "Needed to support Memcached servers",
"ext-redis": "Needed to support Redis servers"
"ext-redis": "Needed to support Redis servers",
"ext-exif": "Needed to use exif data from images."
},
"config": {
"apcu-autoloader": true,
@ -97,9 +98,16 @@
"Twig\\": "system/src/Twig"
},
"files": [
"system/defines.php"
"system/defines.php",
"system/src/DOMLettersIterator.php",
"system/src/DOMWordsIterator.php"
]
},
"autoload-dev": {
"psr-4": {
"PHPStan\\": "tests/phpstan/classes"
}
},
"archive": {
"exclude": [
"VERSION"
@ -108,8 +116,8 @@
"scripts": {
"api-17": "vendor/bin/phpdoc-md generate system/src > user/pages/14.api/default.17.md",
"post-create-project-cmd": "bin/grav install",
"phpstan": "vendor/bin/phpstan analyse -l 1 -c ./tests/phpstan/phpstan.neon --memory-limit=520M system/src",
"phpstan-framework": "vendor/bin/phpstan analyse -l 3 -c ./tests/phpstan/phpstan.neon --memory-limit=480M system/src/Grav/Framework system/src/Grav/Events system/src/Grav/Installer",
"phpstan": "vendor/bin/phpstan analyse -l 2 -c ./tests/phpstan/phpstan.neon --memory-limit=720M system/src",
"phpstan-framework": "vendor/bin/phpstan analyse -l 5 -c ./tests/phpstan/phpstan.neon --memory-limit=480M system/src/Grav/Framework system/src/Grav/Events system/src/Grav/Installer",
"phpstan-plugins": "vendor/bin/phpstan analyse -l 1 -c ./tests/phpstan/plugins.neon --memory-limit=400M user/plugins",
"test": "vendor/bin/codecept run unit",
"test-windows": "vendor\\bin\\codecept run unit"

809
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
/**
* @package Grav.Core
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -12,10 +12,6 @@ namespace Grav;
\define('GRAV_REQUEST_TIME', microtime(true));
\define('GRAV_PHP_MIN', '7.3.6');
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
die(sprintf('You are running PHP %s, but Grav needs at least <strong>PHP %s</strong> to run.', $ver, $req));
}
if (PHP_SAPI === 'cli-server') {
$symfony_server = stripos(getenv('_'), 'symfony') !== false || stripos($_SERVER['SERVER_SOFTWARE'] ?? '', 'symfony') !== false || stripos($_ENV['SERVER_SOFTWARE'] ?? '', 'symfony') !== false;
@ -24,16 +20,6 @@ if (PHP_SAPI === 'cli-server') {
}
}
// Set timezone to default, falls back to system if php.ini not set
date_default_timezone_set(@date_default_timezone_get());
// Set internal encoding.
if (!\extension_loaded('mbstring')) {
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
}
@ini_set('default_charset', 'UTF-8');
mb_internal_encoding('UTF-8');
// Ensure vendor libraries exist
$autoload = __DIR__ . '/vendor/autoload.php';
if (!is_file($autoload)) {
@ -43,23 +29,23 @@ if (!is_file($autoload)) {
// Register the auto-loader.
$loader = require $autoload;
// Set timezone to default, falls back to system if php.ini not set
date_default_timezone_set(@date_default_timezone_get());
// Set internal encoding.
@ini_set('default_charset', 'UTF-8');
mb_internal_encoding('UTF-8');
use Grav\Common\Grav;
use RocketTheme\Toolbox\Event\Event;
// Get the Grav instance
$grav = Grav::instance(
array(
'loader' => $loader
)
);
$grav = Grav::instance(array('loader' => $loader));
// Process the page
try {
$grav->process();
} catch (\Error $e) {
$grav->fireEvent('onFatalException', new Event(array('exception' => $e)));
throw $e;
} catch (\Exception $e) {
} catch (\Error|\Exception $e) {
$grav->fireEvent('onFatalException', new Event(array('exception' => $e)));
throw $e;
}

View File

@ -888,9 +888,45 @@ form:
title: PLUGIN_ADMIN.ASSETS
fields:
assets_section:
general_config_section:
type: section
title: PLUGIN_ADMIN.ASSETS
title: PLUGIN_ADMIN.GENERAL_CONFIG
underline: true
assets.enable_asset_timestamp:
type: toggle
label: PLUGIN_ADMIN.ENABLED_TIMESTAMPS_ON_ASSETS
help: PLUGIN_ADMIN.ENABLED_TIMESTAMPS_ON_ASSETS_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.enable_asset_sri:
type: toggle
label: PLUGIN_ADMIN.ENABLED_SRI_ON_ASSETS
help: PLUGIN_ADMIN.ENABLED_SRI_ON_ASSETS_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.collections:
type: multilevel
label: PLUGIN_ADMIN.COLLECTIONS
placeholder_key: collection_name
placeholder_value: collection_path
validate:
type: array
css_assets_section:
type: section
title: PLUGIN_ADMIN.CSS_ASSETS
underline: true
assets.css_pipeline:
@ -959,6 +995,11 @@ form:
validate:
type: bool
js_assets_section:
type: section
title: PLUGIN_ADMIN.JS_ASSETS
underline: true
assets.js_pipeline:
type: toggle
label: PLUGIN_ADMIN.JAVASCRIPT_PIPELINE
@ -1003,10 +1044,15 @@ form:
validate:
type: bool
assets.enable_asset_timestamp:
js_module_assets_section:
type: section
title: PLUGIN_ADMIN.JS_MODULE_ASSETS
underline: true
assets.js_module_pipeline:
type: toggle
label: PLUGIN_ADMIN.ENABLED_TIMESTAMPS_ON_ASSETS
help: PLUGIN_ADMIN.ENABLED_TIMESTAMPS_ON_ASSETS_HELP
label: PLUGIN_ADMIN.JAVASCRIPT_MODULE_PIPELINE
help: PLUGIN_ADMIN.JAVASCRIPT_MODULE_PIPELINE_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
@ -1014,24 +1060,29 @@ form:
validate:
type: bool
assets.enable_asset_sri:
assets.js_module_pipeline_include_externals:
type: toggle
label: PLUGIN_ADMIN.ENABLED_SRI_ON_ASSETS
help: PLUGIN_ADMIN.ENABLED_SRI_ON_ASSETS_HELP
highlight: 0
label: PLUGIN_ADMIN.JAVASCRIPT_MODULE_PIPELINE_INCLUDE_EXTERNALS
help: PLUGIN_ADMIN.JAVASCRIPT_MODULE_PIPELINE_INCLUDE_EXTERNALS_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.collections:
type: multilevel
label: PLUGIN_ADMIN.COLLECTIONS
placeholder_key: collection_name
placeholder_value: collection_path
assets.js_module_pipeline_before_excludes:
type: toggle
label: PLUGIN_ADMIN.JAVASCRIPT_MODULE_PIPELINE_BEFORE_EXCLUDES
help: PLUGIN_ADMIN.JAVASCRIPT_MODULE_PIPELINE_BEFORE_EXCLUDES_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: array
type: bool
errors:
type: tab
@ -1394,6 +1445,18 @@ form:
validate:
type: bool
session.secure_https:
type: toggle
label: PLUGIN_ADMIN.SESSION_SECURE_HTTPS
help: PLUGIN_ADMIN.SESSION_SECURE_HTTPS_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
default: true
validate:
type: bool
session.httponly:
type: toggle
label: PLUGIN_ADMIN.SESSION_HTTPONLY
@ -1723,35 +1786,15 @@ form:
validate:
type: bool
experimental:
accounts:
type: tab
title: PLUGIN_ADMIN.EXPERIMENTAL
title: PLUGIN_ADMIN.ACCOUNTS
fields:
experimental_section:
type: section
title: PLUGIN_ADMIN.EXPERIMENTAL
underline: true
# flex_pages:
# type: section
# title: Flex Pages
#
# pages.type:
# type: select
# label: PLUGIN_ADMIN.PAGES_TYPE
# highlight: regular
# help: PLUGIN_ADMIN.PAGES_TYPE_HELP
# options:
# regular: PLUGIN_ADMIN.REGULAR
# flex: PLUGIN_ADMIN.FLEX
pages.type:
type: hidden
flex_accounts:
type: section
title: Flex Accounts
title: User Accounts
accounts.type:
type: select
@ -1770,3 +1813,41 @@ form:
options:
file: PLUGIN_ADMIN.FILE
folder: PLUGIN_ADMIN.FOLDER
accounts.avatar:
type: select
label: PLUGIN_ADMIN.AVATAR
default: gravatar
help: PLUGIN_ADMIN.AVATAR_HELP
options:
multiavatar: Multiavatar [local]
gravatar: Gravatar [external]
# experimental:
# type: tab
# title: PLUGIN_ADMIN.EXPERIMENTAL
#
# fields:
# experimental_section:
# type: section
# title: PLUGIN_ADMIN.EXPERIMENTAL
# underline: true
#
# flex_pages:
# type: section
# title: Flex Pages
#
# pages.type:
# type: select
# label: PLUGIN_ADMIN.PAGES_TYPE
# highlight: regular
# help: PLUGIN_ADMIN.PAGES_TYPE_HELP
# options:
# regular: PLUGIN_ADMIN.REGULAR
# flex: PLUGIN_ADMIN.FLEX
#
# pages.type:
# type: hidden

View File

@ -104,7 +104,7 @@ config:
edit:
title:
template: "{% if object.root %}Root <small>( &lt;root&gt; ){% else %}{{ (form.value('header.title') ?? form.value('folder'))|e }} <small>( {{ (object.getRoute().toString(false) ?: '/')|e }} )</small>{% endif %}"
template: "{% if object.root %}Root <small>( &lt;root&gt; )</small>{% else %}{{ (form.value('header.title') ?? form.value('folder'))|e }} <small>( {{ (object.getRoute().toString(false) ?: '/')|e }} )</small>{% endif %}"
# TODO: not used yet
buttons:

View File

@ -122,6 +122,8 @@ config:
fields:
- key
- email
- username
- fullname
blueprints:
configure:

View File

@ -113,6 +113,7 @@ config:
fields:
- key
- groupname
- readableName
- description
blueprints:

View File

@ -320,6 +320,18 @@ form:
fields:
header.redirect_default_route:
type: toggle
toggleable: true
label: PLUGIN_ADMIN.REDIRECT_DEFAULT_ROUTE
help: PLUGIN_ADMIN.REDIRECT_DEFAULT_ROUTE_HELP
config-highlight@: system.pages.redirect_default_route
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
header.routes.default:
type: text
toggleable: true

View File

@ -1,7 +1,7 @@
title: PLUGIN_ADMIN:EXTERNAL
title: PLUGIN_ADMIN.EXTERNAL
extends@:
type: default
context: blueprints://pages
type: default
context: blueprints://pages
form:
validation: loose
@ -29,16 +29,16 @@ form:
unset@: true
header.external_url:
type: text
label: PLUGIN_ADMIN.EXTERNAL_URL
placeholder: https://getgrav.org
validate:
required: true
type: text
label: PLUGIN_ADMIN.EXTERNAL_URL
placeholder: https://getgrav.org
validate:
required: true
options:
fields:
publishing:
fields:
header.date:

View File

@ -51,17 +51,13 @@ form:
type: bool
header.permissions.authors:
type: list
type: array
toggleable: true
value_only: true
placeholder_value: PLUGIN_ADMIN.USERNAME
label: PLUGIN_ADMIN.PAGE_AUTHORS
help: PLUGIN_ADMIN.PAGE_AUTHORS_HELP
fields:
value:
type: text
placeholder: PLUGIN_ADMIN.USERNAME
style: vertical
header.permissions.groups:
ignore@: true
type: acl_picker

View File

@ -11,10 +11,21 @@ form:
avatar:
type: file
size: large
destination: 'user://accounts/avatars'
destination: 'account://avatars'
multiple: false
random_name: true
multiavatar_only:
type: conditional
condition: config.system.accounts.avatar == 'multiavatar'
fields:
avatar_hash:
type: text
label: ''
placeholder: 'e.g. dceaadcfda491f4e45'
description: PLUGIN_ADMIN.AVATAR_HASH
size: large
content:
type: section
title: PLUGIN_ADMIN.ACCOUNT
@ -107,6 +118,12 @@ form:
label: PLUGIN_ADMIN.2FA_SECRET
sublabel: PLUGIN_ADMIN.2FA_SECRET_HELP
yubikey_id:
type: text
label: PLUGIN_ADMIN.YUBIKEY_ID
description: PLUGIN_ADMIN.YUBIKEY_HELP
size: small
maxlength: 12

View File

@ -199,7 +199,7 @@ types:
gz:
type: file
thumb: media/thumb-gz.png
mime: application/gzip
mime: application/x-gzip
tar:
type: file
thumb: media/thumb-tar.png

View File

@ -127,6 +127,9 @@ assets: # Configuration for Assets Mana
js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file
js_pipeline_include_externals: true # Include external URLs in the pipeline by default
js_pipeline_before_excludes: true # Render the pipeline before any excluded files
js_module_pipeline: false # The JS Module pipeline is the unification of multiple JS Module resources into one file
js_module_pipeline_include_externals: true # Include external URLs in the pipeline by default
js_module_pipeline_before_excludes: true # Render the pipeline before any excluded files
js_minify: true # Minify the JS during pipelining
enable_asset_timestamp: false # Enable asset timestamps
enable_asset_sri: false # Enable asset SRI
@ -182,6 +185,7 @@ session:
name: grav-site # Name prefix of the session cookie. Use alphanumeric, dashes or underscores only. Do not use dots in the session name
uniqueness: path # Should sessions be `path` based or `security.salt` based
secure: false # Set session secure. If true, indicates that communication for this cookie must be over an encrypted transmission. Enable this only on sites that run exclusively on HTTPS
secure_https: true # Set session secure on HTTPS but not on HTTP. Has no effect if you have `session.secure: true`. Set to false if your site jumps between HTTP and HTTPS.
httponly: true # Set session HTTP only. If true, indicates that cookies should be used only over HTTP, and JavaScript modification is not allowed.
samesite: Lax # Set session SameSite. Possible values are Lax, Strict and None. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
split: true # Sessions should be independent between site and plugins (such as admin)
@ -204,6 +208,7 @@ http:
accounts:
type: regular # EXPERIMENTAL: Account type: regular or flex
storage: file # EXPERIMENTAL: Flex storage type: file or folder
avatar: gravatar # Avatar generator [multiavatar|gravatar]
flex:
cache:

View File

@ -3,13 +3,13 @@
/**
* @package Grav\Core
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.7.25');
define('GRAV_VERSION', '1.7.31');
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
define('GRAV_TESTING', false);

View File

@ -2,7 +2,7 @@
/**
* @package Grav\Core
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -44,7 +44,7 @@ GRAV:
WK: sem
MO: mes
YR: año
DEC: dic
DEC: déc
SECOND_PLURAL: segundos
MINUTE_PLURAL: minutos
HOUR_PLURAL: horas
@ -64,7 +64,7 @@ GRAV:
VALIDATION_FAIL: '<b>Falló la validación: </b>'
INVALID_INPUT: 'Dato inválido en: '
MISSING_REQUIRED_FIELD: 'Falta el campo requerido: '
XSS_ISSUES: "Se detectaron problemas XSS potenciales en el campo '%s'"
XSS_ISSUES: "Se detectaron potenciales problemas XSS en el campo '%s'"
MONTHS_OF_THE_YEAR:
- 'Enero'
- 'Febrero'
@ -86,7 +86,7 @@ GRAV:
- 'Viernes'
- 'Sábado'
- 'Domingo'
YES: "Si"
YES: "Sí"
NO: "No"
CRON:
EVERY: cada
@ -96,12 +96,12 @@ GRAV:
EVERY_DAY_OF_MONTH: cada día del mes
EVERY_MONTH: cada mes
TEXT_PERIOD: Cada <b />
TEXT_MINS: ' a <b /> minuto(s) despues de la hora'
TEXT_MINS: ' a <b /> minuto(s) después de la hora'
TEXT_TIME: ' a <b />:<b />'
TEXT_DOW: ' en <b />'
TEXT_MONTH: ' de<b />'
TEXT_DOM: ' en<b />'
ERROR1: La etiqueta %s no está soportada!
ERROR2: El número de elementos es erroneo
ERROR1: '¡La etiqueta %s no está soportada!'
ERROR2: El número de elementos es erróneo
ERROR3: El jquery_element debería establecerse en la configuración del jqCron
ERROR4: Expresión no reconocida

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Core
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -22,9 +22,9 @@ if ($path !== '/index.php' && is_file($root . $path)) {
// Block all direct access for these folders
|| preg_match('`^/(\.git|cache|bin|logs|backup|webserver-configs|tests)/`ui', $path)
// Block access to specific file types for these system folders
|| preg_match('`^/(system|vendor)/(.*)\.(txt|xml|md|html|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', $path)
|| preg_match('`^/(system|vendor)/(.*)\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', $path)
// Block access to specific file types for these user folders
|| preg_match('`^/(user)/(.*)\.(txt|md|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', $path)
|| preg_match('`^/(user)/(.*)\.(txt|md|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', $path)
// Block all direct access to .md files
|| preg_match('`\.md$`ui', $path)
// Block access to specific files in the root folder

View File

@ -0,0 +1,165 @@
<?php
/**
* Iterates individual characters (Unicode codepoints) of DOM text and CDATA nodes
* while keeping track of their position in the document.
*
* Example:
*
* $doc = new DOMDocument();
* $doc->load('example.xml');
* foreach(new DOMLettersIterator($doc) as $letter) echo $letter;
*
* NB: If you only need characters without their position
* in the document, use DOMNode->textContent instead.
*
* @author porneL http://pornel.net
* @license Public Domain
* @url https://github.com/antoligy/dom-string-iterators
*
* @implements Iterator<int,string>
*/
final class DOMLettersIterator implements Iterator
{
/** @var DOMElement */
private $start;
/** @var DOMElement|null */
private $current;
/** @var int */
private $offset = -1;
/** @var int|null */
private $key;
/** @var array<int,string>|null */
private $letters;
/**
* expects DOMElement or DOMDocument (see DOMDocument::load and DOMDocument::loadHTML)
*
* @param DOMNode $el
*/
public function __construct(DOMNode $el)
{
if ($el instanceof DOMDocument) {
$el = $el->documentElement;
}
if (!$el instanceof DOMElement) {
throw new InvalidArgumentException('Invalid arguments, expected DOMElement or DOMDocument');
}
$this->start = $el;
}
/**
* Returns position in text as DOMText node and character offset.
* (it's NOT a byte offset, you must use mb_substr() or similar to use this offset properly).
* node may be NULL if iterator has finished.
*
* @return array
*/
public function currentTextPosition(): array
{
return [$this->current, $this->offset];
}
/**
* Returns DOMElement that is currently being iterated or NULL if iterator has finished.
*
* @return DOMElement|null
*/
public function currentElement(): ?DOMElement
{
return $this->current ? $this->current->parentNode : null;
}
// Implementation of Iterator interface
/**
* @return int|null
*/
public function key(): ?int
{
return $this->key;
}
/**
* @return void
*/
public function next(): void
{
if (null === $this->current) {
return;
}
if ($this->current->nodeType === XML_TEXT_NODE || $this->current->nodeType === XML_CDATA_SECTION_NODE) {
if ($this->offset === -1) {
preg_match_all('/./us', $this->current->textContent, $m);
$this->letters = $m[0];
}
$this->offset++;
$this->key++;
if ($this->letters && $this->offset < count($this->letters)) {
return;
}
$this->offset = -1;
}
while ($this->current->nodeType === XML_ELEMENT_NODE && $this->current->firstChild) {
$this->current = $this->current->firstChild;
if ($this->current->nodeType === XML_TEXT_NODE || $this->current->nodeType === XML_CDATA_SECTION_NODE) {
$this->next();
return;
}
}
while (!$this->current->nextSibling && $this->current->parentNode) {
$this->current = $this->current->parentNode;
if ($this->current === $this->start) {
$this->current = null;
return;
}
}
$this->current = $this->current->nextSibling;
$this->next();
}
/**
* Return the current element
* @link https://php.net/manual/en/iterator.current.php
*
* @return string|null
*/
public function current(): ?string
{
return $this->letters ? $this->letters[$this->offset] : null;
}
/**
* Checks if current position is valid
* @link https://php.net/manual/en/iterator.valid.php
*
* @return bool
*/
public function valid(): bool
{
return (bool)$this->current;
}
/**
* @return void
*/
public function rewind(): void
{
$this->current = $this->start;
$this->offset = -1;
$this->key = 0;
$this->letters = [];
$this->next();
}
}

View File

@ -0,0 +1,158 @@
<?php
/**
* Iterates individual words of DOM text and CDATA nodes
* while keeping track of their position in the document.
*
* Example:
*
* $doc = new DOMDocument();
* $doc->load('example.xml');
* foreach(new DOMWordsIterator($doc) as $word) echo $word;
*
* @author pjgalbraith http://www.pjgalbraith.com
* @author porneL http://pornel.net (based on DOMLettersIterator available at http://pornel.net/source/domlettersiterator.php)
* @license Public Domain
* @url https://github.com/antoligy/dom-string-iterators
*
* @implements Iterator<int,string>
*/
final class DOMWordsIterator implements Iterator
{
/** @var DOMElement */
private $start;
/** @var DOMElement|null */
private $current;
/** @var int */
private $offset = -1;
/** @var int|null */
private $key;
/** @var array<int,array<int,int|string>>|null */
private $words;
/**
* expects DOMElement or DOMDocument (see DOMDocument::load and DOMDocument::loadHTML)
*
* @param DOMNode $el
*/
public function __construct(DOMNode $el)
{
if ($el instanceof DOMDocument) {
$el = $el->documentElement;
}
if (!$el instanceof DOMElement) {
throw new InvalidArgumentException('Invalid arguments, expected DOMElement or DOMDocument');
}
$this->start = $el;
}
/**
* Returns position in text as DOMText node and character offset.
* (it's NOT a byte offset, you must use mb_substr() or similar to use this offset properly).
* node may be NULL if iterator has finished.
*
* @return array
*/
public function currentWordPosition(): array
{
return [$this->current, $this->offset, $this->words];
}
/**
* Returns DOMElement that is currently being iterated or NULL if iterator has finished.
*
* @return DOMElement|null
*/
public function currentElement(): ?DOMElement
{
return $this->current ? $this->current->parentNode : null;
}
// Implementation of Iterator interface
/**
* Return the key of the current element
* @link https://php.net/manual/en/iterator.key.php
* @return int|null
*/
public function key(): ?int
{
return $this->key;
}
/**
* @return void
*/
public function next(): void
{
if (null === $this->current) {
return;
}
if ($this->current->nodeType === XML_TEXT_NODE || $this->current->nodeType === XML_CDATA_SECTION_NODE) {
if ($this->offset === -1) {
$this->words = preg_split("/[\n\r\t ]+/", $this->current->textContent, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_OFFSET_CAPTURE) ?: [];
}
$this->offset++;
if ($this->words && $this->offset < count($this->words)) {
$this->key++;
return;
}
$this->offset = -1;
}
while ($this->current->nodeType === XML_ELEMENT_NODE && $this->current->firstChild) {
$this->current = $this->current->firstChild;
if ($this->current->nodeType === XML_TEXT_NODE || $this->current->nodeType === XML_CDATA_SECTION_NODE) {
$this->next();
return;
}
}
while (!$this->current->nextSibling && $this->current->parentNode) {
$this->current = $this->current->parentNode;
if ($this->current === $this->start) {
$this->current = null;
return;
}
}
$this->current = $this->current->nextSibling;
$this->next();
}
/**
* Return the current element
* @link https://php.net/manual/en/iterator.current.php
* @return string|null
*/
public function current(): ?string
{
return $this->words ? (string)$this->words[$this->offset][0] : null;
}
/**
* Checks if current position is valid
* @link https://php.net/manual/en/iterator.valid.php
* @return bool
*/
public function valid(): bool
{
return (bool)$this->current;
}
public function rewind(): void
{
$this->current = $this->start;
$this->offset = -1;
$this->key = 0;
$this->words = [];
$this->next();
}
}

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -16,8 +16,8 @@ use Grav\Common\Assets\Traits\TestingAssetsTrait;
use Grav\Common\Config\Config;
use Grav\Framework\Object\PropertyObject;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use function array_slice;
use function call_user_func_array;
use function count;
use function func_get_args;
use function is_array;
@ -30,14 +30,21 @@ class Assets extends PropertyObject
use TestingAssetsTrait;
use LegacyAssetsTrait;
const LINK = 'link';
const CSS = 'css';
const JS = 'js';
const JS_MODULE = 'js_module';
const LINK_COLLECTION = 'assets_link';
const CSS_COLLECTION = 'assets_css';
const JS_COLLECTION = 'assets_js';
const JS_MODULE_COLLECTION = 'assets_js_module';
const LINK_TYPE = Assets\Link::class;
const CSS_TYPE = Assets\Css::class;
const JS_TYPE = Assets\Js::class;
const JS_MODULE_TYPE = Assets\JsModule::class;
const INLINE_CSS_TYPE = Assets\InlineCss::class;
const INLINE_JS_TYPE = Assets\InlineJs::class;
const INLINE_JS_MODULE_TYPE = Assets\InlineJsModule::class;
/** @const Regex to match CSS and JavaScript files */
const DEFAULT_REGEX = '/.\.(css|js)$/i';
@ -48,15 +55,24 @@ class Assets extends PropertyObject
/** @const Regex to match JavaScript files */
const JS_REGEX = '/.\.js$/i';
/** @const Regex to match JavaScriptModyle files */
const JS_MODULE_REGEX = '/.\.mjs$/i';
/** @var string */
protected $assets_dir;
/** @var string */
protected $assets_url;
/** @var array */
protected $assets_link = [];
/** @var array */
protected $assets_css = [];
/** @var array */
protected $assets_js = [];
/** @var array */
protected $assets_js_module = [];
// Following variables come from the configuration:
/** @var bool */
@ -66,19 +82,17 @@ class Assets extends PropertyObject
/** @var bool */
protected $css_pipeline_before_excludes;
/** @var bool */
protected $inlinecss_pipeline_include_externals;
/** @var bool */
protected $inlinecss_pipeline_before_excludes;
/** @var bool */
protected $js_pipeline;
/** @var bool */
protected $js_pipeline_include_externals;
/** @var bool */
protected $js_pipeline_before_excludes;
/** @var bool */
protected $inlinejs_pipeline_include_externals;
protected $js_module_pipeline;
/** @var bool */
protected $inlinejs_pipeline_before_excludes;
protected $js_module_pipeline_include_externals;
/** @var bool */
protected $js_module_pipeline_before_excludes;
/** @var array */
protected $pipeline_options = [];
@ -160,6 +174,10 @@ class Assets extends PropertyObject
*/
public function add($asset)
{
if (!$asset) {
return $this;
}
$args = func_get_args();
// More than one asset
@ -184,7 +202,8 @@ class Assets extends PropertyObject
call_user_func_array([$this, 'add'], $args);
} else {
// Get extension
$extension = pathinfo(parse_url($asset, PHP_URL_PATH), PATHINFO_EXTENSION);
$path = parse_url($asset, PHP_URL_PATH);
$extension = $path ? Utils::pathinfo($path, PATHINFO_EXTENSION) : '';
// JavaScript or CSS
if ($extension !== '') {
@ -193,6 +212,8 @@ class Assets extends PropertyObject
call_user_func_array([$this, 'addCss'], $args);
} elseif ($extension === 'js') {
call_user_func_array([$this, 'addJs'], $args);
} elseif ($extension === 'mjs') {
call_user_func_array([$this, 'addJsModule'], $args);
}
}
}
@ -222,7 +243,7 @@ class Assets extends PropertyObject
return $this;
}
if (($type === $this::CSS_TYPE || $type === $this::JS_TYPE) && isset($this->collections[$asset])) {
if ($this->isValidType($type) && isset($this->collections[$asset])) {
$this->addType($collection, $type, $this->collections[$asset], $options);
return $this;
}
@ -230,7 +251,9 @@ class Assets extends PropertyObject
// If pipeline disabled, set to position if provided, else after
if (isset($options['pipeline'])) {
if ($options['pipeline'] === false) {
$exclude_type = ($type === $this::JS_TYPE || $type === $this::INLINE_JS_TYPE) ? $this::JS : $this::CSS;
$exclude_type = $this->getBaseType($type);
$excludes = strtolower($exclude_type . '_pipeline_before_excludes');
if ($this->{$excludes}) {
$default = 'after';
@ -269,6 +292,16 @@ class Assets extends PropertyObject
return $this;
}
/**
* Add a CSS asset or a collection of assets.
*
* @return $this
*/
public function addLink($asset)
{
return $this->addType($this::LINK_COLLECTION, $this::LINK_TYPE, $asset, $this->unifyLegacyArguments(func_get_args(), $this::LINK_TYPE));
}
/**
* Add a CSS asset or a collection of assets.
*
@ -309,6 +342,25 @@ class Assets extends PropertyObject
return $this->addType($this::JS_COLLECTION, $this::INLINE_JS_TYPE, $asset, $this->unifyLegacyArguments(func_get_args(), $this::INLINE_JS_TYPE));
}
/**
* Add a JS asset or a collection of assets.
*
* @return $this
*/
public function addJsModule($asset)
{
return $this->addType($this::JS_MODULE_COLLECTION, $this::JS_MODULE_TYPE, $asset, $this->unifyLegacyArguments(func_get_args(), $this::JS_MODULE_TYPE));
}
/**
* Add an Inline JS asset or a collection of assets.
*
* @return $this
*/
public function addInlineJsModule($asset)
{
return $this->addType($this::JS_MODULE_COLLECTION, $this::INLINE_JS_MODULE_TYPE, $asset, $this->unifyLegacyArguments(func_get_args(), $this::INLINE_JS_MODULE_TYPE));
}
/**
* Add/replace collection.
@ -400,7 +452,7 @@ class Assets extends PropertyObject
$after_assets = $this->filterAssets($group_assets, 'position', 'after', true);
// Pipeline
if ($this->{$pipeline_enabled}) {
if ($this->{$pipeline_enabled} ?? false) {
$options = array_merge($this->pipeline_options, ['timestamp' => $this->timestamp]);
$pipeline = new Pipeline($options);
@ -432,9 +484,29 @@ class Assets extends PropertyObject
* @param array $attributes
* @return string
*/
public function css($group = 'head', $attributes = [])
public function css($group = 'head', $attributes = [], $include_link = true)
{
return $this->render('css', $group, $attributes);
$output = '';
if ($include_link) {
$output = $this->link($group, $attributes);
}
$output .= $this->render(self::CSS, $group, $attributes);
return $output;
}
/**
* Build the CSS link tags.
*
* @param string $group name of the group
* @param array $attributes
* @return string
*/
public function link($group = 'head', $attributes = [])
{
return $this->render(self::LINK, $group, $attributes);
}
/**
@ -444,8 +516,71 @@ class Assets extends PropertyObject
* @param array $attributes
* @return string
*/
public function js($group = 'head', $attributes = [])
public function js($group = 'head', $attributes = [], $include_js_module = true)
{
return $this->render('js', $group, $attributes);
$output = $this->render(self::JS, $group, $attributes);
if ($include_js_module) {
$output .= $this->jsModule($group, $attributes);
}
return $output;
}
/**
* Build the Javascript Modules tags
*
* @param string $group
* @param array $attributes
* @return string
*/
public function jsModule($group = 'head', $attributes = [])
{
return $this->render(self::JS_MODULE, $group, $attributes);
}
/**
* @param string $group
* @param array $attributes
* @return string
*/
public function all($group = 'head', $attributes = [])
{
$output = $this->css($group, $attributes, false);
$output .= $this->link($group, $attributes);
$output .= $this->js($group, $attributes, false);
$output .= $this->jsModule($group, $attributes);
return $output;
}
/**
* @param class-string $type
* @return bool
*/
protected function isValidType($type)
{
return in_array($type, [self::CSS_TYPE, self::JS_TYPE, self::JS_MODULE_TYPE]);
}
/**
* @param class-string $type
* @return string
*/
protected function getBaseType($type)
{
switch ($type) {
case $this::JS_TYPE:
case $this::INLINE_JS_TYPE:
$base_type = $this::JS;
break;
case $this::JS_MODULE_TYPE:
case $this::INLINE_JS_MODULE_TYPE:
$base_type = $this::JS_MODULE;
break;
default:
$base_type = $this::CSS;
}
return $base_type;
}
}

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -26,8 +26,9 @@ abstract class BaseAsset extends PropertyObject
{
use AssetUtilsTrait;
protected const CSS_ASSET = true;
protected const JS_ASSET = false;
protected const CSS_ASSET = 1;
protected const JS_ASSET = 2;
protected const JS_MODULE_ASSET = 3;
/** @var string|false */
protected $asset;
@ -69,7 +70,7 @@ abstract class BaseAsset extends PropertyObject
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], $key = null)
public function __construct(array $elements = [], ?string $key = null)
{
$base_config = [
'group' => 'head',
@ -248,6 +249,7 @@ abstract class BaseAsset extends PropertyObject
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return ['type' => $this->getType(), 'elements' => $this->getElements()];
@ -265,4 +267,17 @@ abstract class BaseAsset extends PropertyObject
{
return '';
}
/**
* Finds relative JS urls() and rewrites the URL with an absolute one
*
* @param string $file the css source file
* @param string $dir local relative path to the css file
* @param bool $local is this a local or remote asset
* @return string
*/
protected function jsRewrite($file, $dir, $local)
{
return '';
}
}

View File

@ -0,0 +1,207 @@
<?php
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Assets;
use Grav\Common\Assets;
use Grav\Common\Config\Config;
use Grav\Common\Grav;
use Grav\Framework\ContentBlock\HtmlBlock;
use function strlen;
/**
* Register block assets into Grav.
*/
class BlockAssets
{
/**
* @param HtmlBlock $block
* @return void
*/
public static function registerAssets(HtmlBlock $block): void
{
$grav = Grav::instance();
/** @var Assets $assets */
$assets = $grav['assets'];
$types = $block->getAssets();
foreach ($types as $type => $groups) {
switch ($type) {
case 'frameworks':
static::registerFrameworks($assets, $groups);
break;
case 'styles':
static::registerStyles($assets, $groups);
break;
case 'scripts':
static::registerScripts($assets, $groups);
break;
case 'links':
static::registerLinks($assets, $groups);
break;
case 'html':
static::registerHtml($assets, $groups);
break;
}
}
}
/**
* @param Assets $assets
* @param array $list
* @return void
*/
protected static function registerFrameworks(Assets $assets, array $list): void
{
if ($list) {
throw new \RuntimeException('Not Implemented');
}
}
/**
* @param Assets $assets
* @param array $groups
* @return void
*/
protected static function registerStyles(Assets $assets, array $groups): void
{
$grav = Grav::instance();
/** @var Config $config */
$config = $grav['config'];
foreach ($groups as $group => $styles) {
foreach ($styles as $style) {
switch ($style[':type']) {
case 'file':
$options = [
'priority' => $style[':priority'],
'group' => $group,
'type' => $style['type'],
'media' => $style['media']
] + $style['element'];
$assets->addCss(static::getRelativeUrl($style['href'], $config->get('system.assets.css_pipeline')), $options);
break;
case 'inline':
$options = [
'priority' => $style[':priority'],
'group' => $group,
'type' => $style['type'],
] + $style['element'];
$assets->addInlineCss($style['content'], $options);
break;
}
}
}
}
/**
* @param Assets $assets
* @param array $groups
* @return void
*/
protected static function registerScripts(Assets $assets, array $groups): void
{
$grav = Grav::instance();
/** @var Config $config */
$config = $grav['config'];
foreach ($groups as $group => $scripts) {
$group = $group === 'footer' ? 'bottom' : $group;
foreach ($scripts as $script) {
switch ($script[':type']) {
case 'file':
$options = [
'group' => $group,
'priority' => $script[':priority'],
'src' => $script['src'],
'type' => $script['type'],
'loading' => $script['loading'],
'defer' => $script['defer'],
'async' => $script['async'],
'handle' => $script['handle']
] + $script['element'];
$assets->addJs(static::getRelativeUrl($script['src'], $config->get('system.assets.js_pipeline')), $options);
break;
case 'inline':
$options = [
'priority' => $script[':priority'],
'group' => $group,
'type' => $script['type'],
'loading' => $script['loading']
] + $script['element'];
$assets->addInlineJs($script['content'], $options);
break;
}
}
}
}
/**
* @param Assets $assets
* @param array $groups
* @return void
*/
protected static function registerLinks(Assets $assets, array $groups): void
{
foreach ($groups as $group => $links) {
foreach ($links as $link) {
$href = $link['href'];
$options = [
'group' => $group,
'priority' => $link[':priority'],
'rel' => $link['rel'],
] + $link['element'];
$assets->addLink($href, $options);
}
}
}
/**
* @param Assets $assets
* @param array $groups
* @return void
*/
protected static function registerHtml(Assets $assets, array $groups): void
{
if ($groups) {
throw new \RuntimeException('Not Implemented');
}
}
/**
* @param string $url
* @param bool $pipeline
* @return string
*/
protected static function getRelativeUrl($url, $pipeline)
{
$grav = Grav::instance();
$base = rtrim($grav['base_url'], '/') ?: '/';
if (strpos($url, $base) === 0) {
if ($pipeline) {
// Remove file timestamp if CSS pipeline has been enabled.
$url = preg_replace('|[?#].*|', '', $url);
}
return substr($url, strlen($base) - 1);
}
return $url;
}
}

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -22,7 +22,7 @@ class Css extends BaseAsset
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], $key = null)
public function __construct(array $elements = [], ?string $key = null)
{
$base_options = [
'asset_type' => 'css',

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -22,7 +22,7 @@ class InlineCss extends BaseAsset
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], $key = null)
public function __construct(array $elements = [], ?string $key = null)
{
$base_options = [
'asset_type' => 'css',

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -22,7 +22,7 @@ class InlineJs extends BaseAsset
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], $key = null)
public function __construct(array $elements = [], ?string $key = null)
{
$base_options = [
'asset_type' => 'js',

View File

@ -0,0 +1,46 @@
<?php
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Assets;
use Grav\Common\Utils;
/**
* Class InlineJs
* @package Grav\Common\Assets
*/
class InlineJsModule extends BaseAsset
{
/**
* InlineJs constructor.
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], ?string $key = null)
{
$base_options = [
'asset_type' => 'js_module',
'attributes' => ['type' => 'module'],
'position' => 'after'
];
$merged_attributes = Utils::arrayMergeRecursiveUnique($base_options, $elements);
parent::__construct($merged_attributes, $key);
}
/**
* @return string
*/
public function render()
{
return '<script' . $this->renderAttributes(). ">\n" . trim($this->asset) . "\n</script>\n";
}
}

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -22,7 +22,7 @@ class Js extends BaseAsset
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], $key = null)
public function __construct(array $elements = [], ?string $key = null)
{
$base_options = [
'asset_type' => 'js',

View File

@ -0,0 +1,49 @@
<?php
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Assets;
use Grav\Common\Utils;
/**
* Class Js
* @package Grav\Common\Assets
*/
class JsModule extends BaseAsset
{
/**
* Js constructor.
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], ?string $key = null)
{
$base_options = [
'asset_type' => 'js_module',
'attributes' => ['type' => 'module']
];
$merged_attributes = Utils::arrayMergeRecursiveUnique($base_options, $elements);
parent::__construct($merged_attributes, $key);
}
/**
* @return string
*/
public function render()
{
if (isset($this->attributes['loading']) && $this->attributes['loading'] === 'inline') {
$buffer = $this->gatherLinks([$this], self::JS_MODULE_ASSET);
return '<script' . $this->renderAttributes() . ">\n" . trim($buffer) . "\n</script>\n";
}
return '<script src="' . trim($this->asset) . $this->renderQueryString() . '"' . $this->renderAttributes() . $this->integrityHash($this->asset) . "></script>\n";
}
}

View File

@ -0,0 +1,43 @@
<?php
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Assets;
use Grav\Common\Utils;
/**
* Class Link
* @package Grav\Common\Assets
*/
class Link extends BaseAsset
{
/**
* Css constructor.
* @param array $elements
* @param string|null $key
*/
public function __construct(array $elements = [], ?string $key = null)
{
$base_options = [
'asset_type' => 'link',
];
$merged_attributes = Utils::arrayMergeRecursiveUnique($base_options, $elements);
parent::__construct($merged_attributes, $key);
}
/**
* @return string
*/
public function render()
{
return '<link href="' . trim($this->asset) . $this->renderQueryString() . '"' . $this->renderAttributes() . $this->integrityHash($this->asset) . ">\n";
}
}

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -29,12 +29,16 @@ class Pipeline extends PropertyObject
{
use AssetUtilsTrait;
protected const CSS_ASSET = true;
protected const JS_ASSET = false;
protected const CSS_ASSET = 1;
protected const JS_ASSET = 2;
protected const JS_MODULE_ASSET = 3;
/** @const Regex to match CSS urls */
protected const CSS_URL_REGEX = '{url\(([\'\"]?)(.*?)\1\)}';
/** @const Regex to match JS imports */
protected const JS_IMPORT_REGEX = '{import.+from\s?[\'|\"](.+?)[\'|\"]}';
/** @const Regex to match CSS sourcemap comments */
protected const CSS_SOURCEMAP_REGEX = '{\/\*# (.*?) \*\/}';
@ -122,7 +126,7 @@ class Pipeline extends PropertyObject
// Compute uid based on assets and timestamp
$json_assets = json_encode($assets);
$uid = md5($json_assets . $this->css_minify . $this->css_rewrite . $group);
$uid = md5($json_assets . (int)$this->css_minify . (int)$this->css_rewrite . $group);
$file = $uid . '.css';
$relative_path = "{$this->base_url}{$this->assets_url}/{$file}";
@ -169,7 +173,7 @@ class Pipeline extends PropertyObject
* @param array $attributes
* @return bool|string URL or generated content if available, else false
*/
public function renderJs($assets, $group, $attributes = [])
public function renderJs($assets, $group, $attributes = [], $type = self::JS_ASSET)
{
// temporary list of assets to pipeline
$inline_group = false;
@ -198,7 +202,7 @@ class Pipeline extends PropertyObject
}
// Concatenate files
$buffer = $this->gatherLinks($assets, self::JS_ASSET);
$buffer = $this->gatherLinks($assets, $type);
// Minify if required
if ($this->shouldMinify('js')) {
@ -223,6 +227,19 @@ class Pipeline extends PropertyObject
return $output;
}
/**
* Minify and concatenate JS files.
*
* @param array $assets
* @param string $group
* @param array $attributes
* @return bool|string URL or generated content if available, else false
*/
public function renderJs_Module($assets, $group, $attributes = [])
{
$attributes['type'] = 'module';
return $this->renderJs($assets, $group, $attributes, self::JS_MODULE_ASSET);
}
/**
* Finds relative CSS urls() and rewrites the URL with an absolute one
@ -262,6 +279,42 @@ class Pipeline extends PropertyObject
return $file;
}
/**
* Finds relative JS urls() and rewrites the URL with an absolute one
*
* @param string $file the css source file
* @param string $dir local relative path to the css file
* @param bool $local is this a local or remote asset
* @return string
*/
protected function jsRewrite($file, $dir, $local)
{
// Find any js import elements, grab the URLs and calculate an absolute path
// Then replace the old url with the new one
$file = (string)preg_replace_callback(self::JS_IMPORT_REGEX, function ($matches) use ($dir, $local) {
$old_url = $matches[1];
// Ensure link is not rooted to web server, a data URL, or to a remote host
if (preg_match(self::FIRST_FORWARDSLASH_REGEX, $old_url) || $this->isRemoteLink($old_url)) {
return $matches[0];
}
// clean leading /
$old_url = Utils::normalizePath($dir . '/' . $old_url);
$old_url = str_replace('/./', '/', $old_url);
if (preg_match(self::FIRST_FORWARDSLASH_REGEX, $old_url)) {
$old_url = ltrim($old_url, '/');
}
$new_url = ($local ? $this->base_url : '') . $old_url;
return str_replace($matches[1], $new_url, $matches[0]);
}, $file);
return $file;
}
/**
* @param string $type
* @return bool

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets\Traits
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -62,13 +62,13 @@ trait AssetUtilsTrait
* Download and concatenate the content of several links.
*
* @param array $assets
* @param bool $css
* @param int $type
* @return string
*/
protected function gatherLinks(array $assets, $css = true)
protected function gatherLinks(array $assets, int $type = self::CSS_ASSET): string
{
$buffer = '';
foreach ($assets as $id => $asset) {
foreach ($assets as $asset) {
$local = true;
$link = $asset->getAsset();
@ -100,21 +100,25 @@ trait AssetUtilsTrait
}
// Double check last character being
if (!$css) {
if ($type === self::JS_ASSET || $type === self::JS_MODULE_ASSET) {
$file = rtrim($file, ' ;') . ';';
}
// If this is CSS + the file is local + rewrite enabled
if ($css && $this->css_rewrite) {
if ($type === self::CSS_ASSET && $this->css_rewrite) {
$file = $this->cssRewrite($file, $relative_dir, $local);
}
if ($type === self::JS_MODULE_ASSET) {
$file = $this->jsRewrite($file, $relative_dir, $local);
}
$file = rtrim($file) . PHP_EOL;
$buffer .= $file;
}
// Pull out @imports and move to top
if ($css) {
if ($type === self::CSS_ASSET) {
$buffer = $this->moveImports($buffer);
}

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets\Traits
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Assets\Traits
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -285,6 +285,15 @@ trait TestingAssetsTrait
return $this;
}
// Add JavaScript Module files
if ($pattern === self::JS_MODULE_REGEX) {
foreach ($files as $file) {
$this->addJsModule($file);
}
return $this;
}
// Unknown pattern.
foreach ($files as $asset) {
$this->add($asset);

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Backup
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -104,8 +104,8 @@ class Backups
*/
public function getBackupDownloadUrl($backup, $base_url)
{
$param_sep = $param_sep = Grav::instance()['config']->get('system.param_sep', ':');
$download = urlencode(base64_encode(basename($backup)));
$param_sep = Grav::instance()['config']->get('system.param_sep', ':');
$download = urlencode(base64_encode(Utils::basename($backup)));
$url = rtrim(Grav::instance()['uri']->rootUrl(true), '/') . '/' . trim(
$base_url,
'/'
@ -145,7 +145,7 @@ class Backups
{
$backups = static::getAvailableBackups();
return array_sum(array_column($backups, 'size'));
return $backups ? array_sum(array_column($backups, 'size')) : 0;
}
/**

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -177,7 +177,7 @@ class Cache extends Getters
public function purgeOldCache()
{
$cache_dir = dirname($this->cache_dir);
$current = basename($this->cache_dir);
$current = Utils::basename($this->cache_dir);
$count = 0;
foreach (new DirectoryIterator($cache_dir) as $file) {

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Config
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -401,7 +401,7 @@ class Setup extends Data
}
// Create security.yaml salt if it doesn't exist into existing configuration environment if possible.
$securityFile = basename(static::$securityFile);
$securityFile = Utils::basename(static::$securityFile);
$securityFolder = substr(static::$securityFile, 0, -\strlen($securityFile));
$securityFolder = $locator->findResource($securityFolder, true) ?: $locator->findResource($securityFolder, true, true);
$filename = "{$securityFolder}/{$securityFile}";

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Data
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -99,7 +99,7 @@ class Blueprint extends BlueprintForm
*/
public function getDefaultValue(string $name)
{
$path = explode('.', $name) ?: [];
$path = explode('.', $name);
$current = $this->getDefaults();
foreach ($path as $field) {
@ -293,15 +293,16 @@ class Blueprint extends BlueprintForm
/**
* Flatten data by using blueprints.
*
* @param array $data
* @param bool $includeAll
* @param array $data Data to be flattened.
* @param bool $includeAll True if undefined properties should also be included.
* @param string $name Property which will be flattened, useful for flattening repeating data.
* @return array
*/
public function flattenData(array $data, bool $includeAll = false)
public function flattenData(array $data, bool $includeAll = false, string $name = '')
{
$this->initInternals();
return $this->blueprintSchema->flattenData($data, $includeAll);
return $this->blueprintSchema->flattenData($data, $includeAll, $name);
}

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Data
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -115,23 +115,29 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
/**
* Flatten data by using blueprints.
*
* @param array $data Data to be flattened.
* @param bool $includeAll
* @param array $data Data to be flattened.
* @param bool $includeAll True if undefined properties should also be included.
* @param string $name Property which will be flattened, useful for flattening repeating data.
* @return array
*/
public function flattenData(array $data, bool $includeAll = false)
public function flattenData(array $data, bool $includeAll = false, string $name = '')
{
$prefix = $name !== '' ? $name . '.' : '';
$list = [];
if ($includeAll) {
foreach ($this->items as $key => $rules) {
$items = $name !== '' ? $this->getProperty($name)['fields'] ?? [] : $this->items;
foreach ($items as $key => $rules) {
$type = $rules['type'] ?? '';
if (!str_starts_with($type, '_') && !str_contains($key, '*')) {
$list[$key] = null;
$list[$prefix . $key] = null;
}
}
}
return array_replace($list, $this->flattenArray($data, $this->nested, ''));
$nested = $this->getNestedRules($name);
return array_replace($list, $this->flattenArray($data, $nested, $prefix));
}
/**

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Data
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Data
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -335,6 +335,7 @@ class Data implements DataInterface, ArrayAccess, \Countable, JsonSerializable,
/**
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return $this->items;

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Data
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Data
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -816,7 +816,7 @@ class Validation
{
$value = static::filterArray($value, $params, $field);
return Utils::arrayUnflattenDotNotation($value);
return is_array($value) ? Utils::arrayUnflattenDotNotation($value) : null;
}
/**

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Data
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -856,6 +856,10 @@ class Debugger
$scope = 'grav';
} elseif (strpos($errfile, '/twig/') !== false) {
$scope = 'twig';
// TODO: remove when upgrading to Twig 2+
if (str_contains($errstr, '#[\ReturnTypeWillChange]') || str_contains($errstr, 'Passing null to parameter')) {
return true;
}
} elseif (stripos($errfile, '/yaml/') !== false) {
$scope = 'yaml';
} elseif (strpos($errfile, '/vendor/') !== false) {

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Errors
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Errors
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Errors
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Errors
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,13 +3,14 @@
/**
* @package Grav\Common\File
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\File;
use Exception;
use Grav\Common\Utils;
use RocketTheme\Toolbox\File\PhpFile;
use RuntimeException;
use Throwable;
@ -88,7 +89,7 @@ trait CompiledFile
$this->content = $cache['data'];
}
} catch (Exception $e) {
throw new RuntimeException(sprintf('Failed to read %s: %s', basename($this->filename), $e->getMessage()), 500, $e);
throw new RuntimeException(sprintf('Failed to read %s: %s', Utils::basename($this->filename), $e->getMessage()), 500, $e);
}
return parent::content($var);

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\File
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\File
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\File
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Filesystem
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Filesystem
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -513,7 +513,7 @@ abstract class Folder
}
$directories = glob($directory . '/*', GLOB_ONLYDIR);
return count($directories);
return $directories ? count($directories) : false;
}
/**
@ -530,7 +530,8 @@ abstract class Folder
}
// Go through all items in filesystem and recursively remove everything.
$files = array_diff(scandir($folder, SCANDIR_SORT_NONE), array('.', '..'));
$files = scandir($folder, SCANDIR_SORT_NONE);
$files = $files ? array_diff($files, ['.', '..']) : [];
foreach ($files as $file) {
$path = "{$folder}/{$file}";
is_dir($path) ? self::doDelete($path) : @unlink($path);

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Filesystem
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Filesystem
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Common\Filesystem
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -34,7 +34,9 @@ use function is_string;
* Class GravPageCollection
* @package Grav\Plugin\FlexObjects\Types\GravPages
*
* @extends FlexPageCollection<PageObject>
* @template T as PageObject
* @extends FlexPageCollection<T>
* @implements PageCollectionInterface<string,T>
*
* Incompatibilities with Grav\Common\Page\Collection:
* $page = $collection->key() will not work at all
@ -46,10 +48,6 @@ use function is_string;
* $collection->prev() does not rewind the internal pointer
* AND most methods are immutable; they do not update the current collection, but return updated one
*
* @method static shuffle()
* @method static select(array $keys)
* @method static unselect(array $keys)
* @method static createFrom(array $elements, string $keyField = null)
* @method PageIndex getIndex()
*/
class PageCollection extends FlexPageCollection implements PageCollectionInterface
@ -108,13 +106,11 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
}
/**
* @return PageObject
* @return PageInterface
*/
public function getRoot()
{
$index = $this->getIndex();
return $index->getRoot();
return $this->getIndex()->getRoot();
}
/**
@ -154,7 +150,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Add a single page to a collection
*
* @param PageInterface $page
* @return static
* @return $this
*/
public function addPage(PageInterface $page)
{
@ -174,6 +170,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param PageCollectionInterface $collection
* @return static
* @phpstan-return static<T>
*/
public function merge(PageCollectionInterface $collection)
{
@ -185,6 +182,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param PageCollectionInterface $collection
* @return static
* @phpstan-return static<T>
*/
public function intersect(PageCollectionInterface $collection)
{
@ -203,7 +201,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Return previous item.
*
* @return PageInterface|false
* @phpstan-return PageObject|false
* @phpstan-return T|false
*/
public function prev()
{
@ -218,7 +216,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Return nth item.
* @param int $key
* @return PageInterface|bool
* @phpstan-return PageObject|false
* @phpstan-return T|false
*/
public function nth($key)
{
@ -230,6 +228,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param int $num Specifies how many entries should be picked.
* @return static
* @phpstan-return static<T>
*/
public function random($num = 1)
{
@ -241,6 +240,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param array $items Items to be appended. Existing keys will be overridden with the new values.
* @return static
* @phpstan-return static<T>
*/
public function append($items)
{
@ -252,6 +252,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param int $size
* @return static[]
* @phpstan-return static<T>[]
*/
public function batch($size): array
{
@ -273,6 +274,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @param array|null $manual
* @param int|null $sort_flags
* @return static
* @phpstan-return static<T>
*/
public function order($by, $dir = 'asc', $manual = null, $sort_flags = null)
{
@ -333,7 +335,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
$list[$key] = $child->slug();
break;
case 'basename':
$list[$key] = basename($key);
$list[$key] = Utils::basename($key);
break;
case 'folder':
$list[$key] = $child->folder();
@ -441,6 +443,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @param string|null $endDate
* @param string|null $field
* @return static
* @phpstan-return static<T>
* @throws Exception
*/
public function dateRange($startDate = null, $endDate = null, $field = null)
@ -468,6 +471,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only visible pages
*
* @return static The collection with only visible pages
* @phpstan-return static<T>
*/
public function visible()
{
@ -485,6 +489,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only non-visible pages
*
* @return static The collection with only non-visible pages
* @phpstan-return static<T>
*/
public function nonVisible()
{
@ -502,6 +507,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only pages
*
* @return static The collection with only pages
* @phpstan-return static<T>
*/
public function pages()
{
@ -523,6 +529,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only modules
*
* @return static The collection with only modules
* @phpstan-return static<T>
*/
public function modules()
{
@ -544,6 +551,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Alias of modules()
*
* @return static
* @phpstan-return static<T>
*/
public function modular()
{
@ -554,6 +562,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Alias of pages()
*
* @return static
* @phpstan-return static<T>
*/
public function nonModular()
{
@ -564,6 +573,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only published pages
*
* @return static The collection with only published pages
* @phpstan-return static<T>
*/
public function published()
{
@ -581,6 +591,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only non-published pages
*
* @return static The collection with only non-published pages
* @phpstan-return static<T>
*/
public function nonPublished()
{
@ -598,6 +609,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only routable pages
*
* @return static The collection with only routable pages
* @phpstan-return static<T>
*/
public function routable()
{
@ -615,6 +627,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* Creates new collection with only non-routable pages
*
* @return static The collection with only non-routable pages
* @phpstan-return static<T>
*/
public function nonRoutable()
{
@ -633,6 +646,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param string $type
* @return static The collection
* @phpstan-return static<T>
*/
public function ofType($type)
{
@ -651,6 +665,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param string[] $types
* @return static The collection
* @phpstan-return static<T>
*/
public function ofOneOfTheseTypes($types)
{
@ -669,6 +684,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
*
* @param array $accessLevels
* @return static The collection
* @phpstan-return static<T>
*/
public function ofOneOfTheseAccessLevels($accessLevels)
{
@ -710,6 +726,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
/**
* @param bool $bool
* @return static
* @phpstan-return static<T>
*/
public function withOrdered(bool $bool = true)
{
@ -721,6 +738,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
/**
* @param bool $bool
* @return static
* @phpstan-return static<T>
*/
public function withModules(bool $bool = true)
{
@ -732,6 +750,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
/**
* @param bool $bool
* @return static
* @phpstan-return static<T>
*/
public function withPages(bool $bool = true)
{
@ -745,6 +764,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @param string|null $languageCode
* @param bool|null $fallback
* @return static
* @phpstan-return static<T>
*/
public function withTranslation(bool $bool = true, string $languageCode = null, bool $fallback = null)
{
@ -778,6 +798,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @param array $filters
* @param bool $recursive
* @return static
* @phpstan-return static<T>
*/
public function filterBy(array $filters, bool $recursive = false)
{

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -39,7 +39,10 @@ use function is_string;
* Class GravPageObject
* @package Grav\Plugin\FlexObjects\Types\GravPages
*
* @extends FlexPageIndex<PageObject,PageCollection>
* @template T of PageObject
* @template C of PageCollection
* @extends FlexPageIndex<T,C>
* @implements PageCollectionInterface<string,T>
*
* @method PageIndex withModules(bool $bool = true)
* @method PageIndex withPages(bool $bool = true)
@ -101,6 +104,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
/**
* @param string $key
* @return PageObject|null
* @phpstan-return T|null
*/
public function get($key)
{
@ -117,11 +121,13 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
$element = $element->getTranslation(ltrim($params, '.'));
}
\assert(null === $element || $element instanceof PageObject);
return $element;
}
/**
* @return PageObject
* @return PageInterface
*/
public function getRoot()
{
@ -172,7 +178,8 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
/**
* @param string|null $languageCode
* @param bool|null $fallback
* @return PageIndex
* @return static
* @phpstan-return static<T,C>
*/
public function withTranslated(string $languageCode = null, bool $fallback = null)
{
@ -276,6 +283,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param array $filters
* @param bool $recursive
* @return static
* @phpstan-return static<T,C>
*/
public function filterBy(array $filters, bool $recursive = false)
{
@ -332,6 +340,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
/**
* @param array $filters
* @return static
* @phpstan-return static<T,C>
*/
protected function filterByParent(array $filters)
{
@ -402,6 +411,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param array $entries
* @param string|null $keyField
* @return static
* @phpstan-return static<T,C>
*/
protected function createFrom(array $entries, string $keyField = null)
{
@ -596,8 +606,10 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
}
}
/** @var PageCollection|PageIndex $children */
$children = $page->children();
/** @var PageIndex $children */
$children = $page->children()->getIndex();
$children = $children->getIndex();
$selectedChildren = $children->filterBy($filters, true);
/** @var Header $header */
@ -627,7 +639,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
$payload = [
'name' => $child->menu(),
'value' => $child->rawRoute(),
'item-key' => basename($child->rawRoute() ?? ''),
'item-key' => Utils::basename($child->rawRoute() ?? ''),
'filename' => $child->folder(),
'extension' => $child->extension(),
'type' => 'dir',
@ -676,13 +688,15 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
$extras = array_filter($extras, static function ($v) {
return $v !== null;
});
/** @var PageIndex $tmp */
$tmp = $child->children()->getIndex();
$child_count = $tmp->count();
$count = $filters ? $tmp->filterBy($filters, true)->count() : null;
$route = $child->getRoute();
$route = $route ? ($route->toString(false) ?: '/') : '';
$payload = [
'item-key' => htmlspecialchars(basename($child->rawRoute() ?? $child->getKey())),
'item-key' => htmlspecialchars(Utils::basename($child->rawRoute() ?? $child->getKey())),
'icon' => $icon,
'title' => htmlspecialchars($child->menu()),
'route' => [
@ -787,6 +801,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param PageInterface $page
* @return PageCollection
* @phpstan-return C
*/
public function addPage(PageInterface $page)
{
@ -798,6 +813,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Create a copy of this collection
*
* @return static
* @phpstan-return static<T,C>
*/
public function copy()
{
@ -810,6 +826,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param PageCollectionInterface $collection
* @return PageCollection
* @phpstan-return C
*/
public function merge(PageCollectionInterface $collection)
{
@ -822,6 +839,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param PageCollectionInterface $collection
* @return PageCollection
* @phpstan-return C
*/
public function intersect(PageCollectionInterface $collection)
{
@ -833,6 +851,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param int $size
* @return PageCollection[]
* @phpstan-return C[]
*/
public function batch($size)
{
@ -844,6 +863,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param string $key
* @return PageObject|null
* @phpstan-return T|null
* @throws InvalidArgumentException
*/
public function remove($key)
@ -859,6 +879,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param array $manual
* @param string $sort_flags
* @return static
* @phpstan-return static<T,C>
*/
public function order($by, $dir = 'asc', $manual = null, $sort_flags = null)
{
@ -902,6 +923,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param string $path
* @return PageObject|null The previous item.
* @phpstan-return T|null
*/
public function prevSibling($path)
{
@ -916,6 +938,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param string $path
* @return PageObject|null The next item.
* @phpstan-return T|null
*/
public function nextSibling($path)
{
@ -931,6 +954,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param string $path
* @param int $direction either -1 or +1
* @return PageObject|false The sibling item.
* @phpstan-return T|false
*/
public function adjacentSibling($path, $direction = 1)
{
@ -964,6 +988,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param string|null $endDate
* @param string|null $field
* @return static
* @phpstan-return static<T,C>
* @throws Exception
*/
public function dateRange($startDate = null, $endDate = null, $field = null)
@ -988,6 +1013,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only visible pages
*
* @return static The collection with only visible pages
* @phpstan-return static<T,C>
*/
public function visible()
{
@ -1000,6 +1026,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only non-visible pages
*
* @return static The collection with only non-visible pages
* @phpstan-return static<T,C>
*/
public function nonVisible()
{
@ -1012,6 +1039,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only non-modular pages
*
* @return static The collection with only non-modular pages
* @phpstan-return static<T,C>
*/
public function pages()
{
@ -1024,6 +1052,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only modular pages
*
* @return static The collection with only modular pages
* @phpstan-return static<T,C>
*/
public function modules()
{
@ -1036,6 +1065,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only modular pages
*
* @return static The collection with only modular pages
* @phpstan-return static<T,C>
*/
public function modular()
{
@ -1046,6 +1076,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only non-modular pages
*
* @return static The collection with only non-modular pages
* @phpstan-return static<T,C>
*/
public function nonModular()
{
@ -1056,6 +1087,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only published pages
*
* @return static The collection with only published pages
* @phpstan-return static<T,C>
*/
public function published()
{
@ -1068,6 +1100,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only non-published pages
*
* @return static The collection with only non-published pages
* @phpstan-return static<T,C>
*/
public function nonPublished()
{
@ -1080,6 +1113,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only routable pages
*
* @return static The collection with only routable pages
* @phpstan-return static<T,C>
*/
public function routable()
{
@ -1092,6 +1126,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Creates new collection with only non-routable pages
*
* @return static The collection with only non-routable pages
* @phpstan-return static<T,C>
*/
public function nonRoutable()
{
@ -1105,6 +1140,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param string $type
* @return static The collection
* @phpstan-return static<T,C>
*/
public function ofType($type)
{
@ -1118,6 +1154,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param string[] $types
* @return static The collection
* @phpstan-return static<T,C>
*/
public function ofOneOfTheseTypes($types)
{
@ -1131,6 +1168,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
*
* @param array $accessLevels
* @return static The collection
* @phpstan-return static<T,C>
*/
public function ofOneOfTheseAccessLevels($accessLevels)
{

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -25,9 +25,9 @@ use Grav\Common\Page\Pages;
use Grav\Common\User\Interfaces\UserInterface;
use Grav\Common\Utils;
use Grav\Framework\Filesystem\Filesystem;
use Grav\Framework\Flex\FlexObject;
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
use Grav\Framework\Flex\Pages\FlexPageObject;
use Grav\Framework\Object\ObjectCollection;
use Grav\Framework\Route\Route;
use Grav\Framework\Route\RouteFactory;
use Grav\Plugin\Admin\Admin;
@ -93,11 +93,6 @@ class PageObject extends FlexPageObject
}
}
public function translated(): bool
{
return $this->translatedLanguages(true) ? true : false;
}
/**
* @param string|array $query
* @return Route|null
@ -282,7 +277,7 @@ class PageObject extends FlexPageObject
/**
* @param array|bool $reorder
* @return FlexObject|FlexObjectInterface
* @return static
*/
public function save($reorder = true)
{
@ -317,7 +312,7 @@ class PageObject extends FlexPageObject
}
/**
* @return PageObject
* @return static
*/
public function delete()
{
@ -391,6 +386,7 @@ class PageObject extends FlexPageObject
/**
* @param array $ordering
* @return PageCollection|null
* @phpstan-return ObjectCollection<string,PageObject>|null
*/
protected function reorderSiblings(array $ordering)
{
@ -466,7 +462,9 @@ class PageObject extends FlexPageObject
if ($isMoved && $this->order() !== false) {
$parentKey = $this->getProperty('parent_key');
if ($parentKey === '') {
$newParent = $this->getFlexDirectory()->getIndex()->getRoot();
/** @var PageIndex $index */
$index = $this->getFlexDirectory()->getIndex();
$newParent = $index->getRoot();
} else {
$newParent = $this->getFlexDirectory()->getObject($parentKey, 'storage_key');
if (!$newParent instanceof PageInterface) {
@ -627,7 +625,14 @@ class PageObject extends FlexPageObject
// If current filter does not match, we still may have match as a parent.
if ($matches === false) {
return $recursive && $this->children()->getIndex()->filterBy($filters, true)->count() > 0;
if (!$recursive) {
return false;
}
/** @var PageIndex $index */
$index = $this->children()->getIndex();
return $index->filterBy($filters, true)->count() > 0;
}
}

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -16,13 +16,13 @@ use Grav\Common\Debugger;
use Grav\Common\Flex\Types\Pages\PageIndex;
use Grav\Common\Grav;
use Grav\Common\Language\Language;
use Grav\Common\Utils;
use Grav\Framework\Filesystem\Filesystem;
use Grav\Framework\Flex\Storage\FolderStorage;
use RocketTheme\Toolbox\File\MarkdownFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RuntimeException;
use SplFileInfo;
use function assert;
use function in_array;
use function is_string;
@ -277,7 +277,7 @@ class PageStorage extends FolderStorage
} else {
$params = $template = $language = '';
}
$objectKey = basename($key);
$objectKey = Utils::basename($key);
if (preg_match('|^(\d+)\.(.+)$|', $objectKey, $matches)) {
[, $order, $folder] = $matches;
} else {
@ -584,7 +584,7 @@ class PageStorage extends FolderStorage
$mark = $matches[2] ?? '';
$ext = $matches[1] ?? '';
$ext .= $this->dataExt;
$markdown[$mark][basename($k, $ext)] = $timestamp;
$markdown[$mark][Utils::basename($k, $ext)] = $timestamp;
}
$modified = max($modified, $timestamp);
@ -675,7 +675,7 @@ class PageStorage extends FolderStorage
/** @phpstan-var array{'storage_key': string, 'storage_timestamp': int, 'children': array<string, mixed>} $parent */
$parent = &$list[$parentKey];
$basename = basename($storage_key);
$basename = Utils::basename($storage_key);
if (isset($parent['children'][$basename])) {
$timestamp = $meta['storage_timestamp'];

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -27,7 +27,7 @@ class UserGroupCollection extends FlexCollection
public static function getCachedMethods(): array
{
return [
'authorize' => 'session',
'authorize' => false,
] + parent::getCachedMethods();
}

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -37,7 +37,7 @@ class UserGroupObject extends FlexObject implements UserGroupInterface
public static function getCachedMethods(): array
{
return [
'authorize' => 'session',
'authorize' => false,
] + parent::getCachedMethods();
}

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -84,6 +84,7 @@ trait UserObjectLegacyTrait
* @return int
* @deprecated 1.6 Method makes no sense for user account.
*/
#[\ReturnTypeWillChange]
public function count()
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6', E_USER_DEPRECATED);

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
/**
* @package Grav\Common\Flex
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
@ -164,7 +164,7 @@ class UserIndex extends FlexIndex implements UserCollectionInterface
*/
protected static function filterUsername(string $key, FlexStorageInterface $storage): string
{
return $storage->normalizeKey($key);
return method_exists($storage, 'normalizeKey') ? $storage->normalizeKey($key) : $key;
}
/**

Some files were not shown because too many files have changed in this diff Show More