mirror of
https://github.com/getgrav/grav.git
synced 2025-12-05 15:29:57 +01:00
Compare commits
232 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8c4e730f6 | ||
|
|
d329df2bb0 | ||
|
|
f90232e511 | ||
|
|
57bd3c9cb5 | ||
|
|
419692b9e4 | ||
|
|
b422d9585c | ||
|
|
67b9623d6c | ||
|
|
bda6b26896 | ||
|
|
9b2af98b0b | ||
|
|
b07bf96ad9 | ||
|
|
fb2c4f48f7 | ||
|
|
308383b093 | ||
|
|
f8f5502c40 | ||
|
|
55b45fcf2f | ||
|
|
bd471cb61b | ||
|
|
2ac38d39ea | ||
|
|
7bb8d10b22 | ||
|
|
f9fcdd6c51 | ||
|
|
3febaaa802 | ||
|
|
178cc9c5ea | ||
|
|
8d51911873 | ||
|
|
99ceb40c5f | ||
|
|
8767bfb9b0 | ||
|
|
756b088ada | ||
|
|
c962201bae | ||
|
|
2335271472 | ||
|
|
47d7927bac | ||
|
|
d15542e553 | ||
|
|
e6447f7203 | ||
|
|
fbcaf991aa | ||
|
|
cc8ec10098 | ||
|
|
92824f44e6 | ||
|
|
c4eefc13a7 | ||
|
|
d541808604 | ||
|
|
231c8a0f4c | ||
|
|
ea39587329 | ||
|
|
8f3ac75afd | ||
|
|
b40b543790 | ||
|
|
3b7921b698 | ||
|
|
6af1ee48a5 | ||
|
|
4519971a76 | ||
|
|
26295d5cf2 | ||
|
|
bfc9e26f26 | ||
|
|
d939b1e563 | ||
|
|
8343cfb278 | ||
|
|
290a28109e | ||
|
|
5bec5db5e1 | ||
|
|
a6fb0a14f0 | ||
|
|
7cb62ddc75 | ||
|
|
0f85b831b5 | ||
|
|
530e6a4399 | ||
|
|
c7700c2e16 | ||
|
|
89acc59ac3 | ||
|
|
9a25c88471 | ||
|
|
4ccbdafe8a | ||
|
|
74096e836f | ||
|
|
1c51bf8a66 | ||
|
|
a4beb9b8bd | ||
|
|
484a41e42a | ||
|
|
def62ec2a2 | ||
|
|
fae431bc39 | ||
|
|
25bc1edf31 | ||
|
|
945b90fa46 | ||
|
|
420a4e3566 | ||
|
|
f2a7833933 | ||
|
|
491252476d | ||
|
|
6ed453890d | ||
|
|
432f0eb9e5 | ||
|
|
236c068d70 | ||
|
|
3f3503e0f3 | ||
|
|
bc70c9b93c | ||
|
|
90f5ff7c74 | ||
|
|
3bfbb1a4ef | ||
|
|
1f3f1828c2 | ||
|
|
6c7064db93 | ||
|
|
9df7b35c65 | ||
|
|
5552ea2d70 | ||
|
|
6079562c90 | ||
|
|
a56453cf0a | ||
|
|
c2f394de17 | ||
|
|
878de339e5 | ||
|
|
86cfba3bc9 | ||
|
|
ad1e20abb7 | ||
|
|
2165743810 | ||
|
|
f3789bb17e | ||
|
|
8f2f5e3373 | ||
|
|
70c0dc6419 | ||
|
|
5b84213fce | ||
|
|
3ad68d6d5a | ||
|
|
627a1510dc | ||
|
|
042d4a4603 | ||
|
|
b2cfc4ef5f | ||
|
|
1c148ab6fb | ||
|
|
cf6159ffe3 | ||
|
|
f04f13723d | ||
|
|
5fd4f5f3eb | ||
|
|
512c2e5d9d | ||
|
|
da3e32f945 | ||
|
|
ae74f29b69 | ||
|
|
ecb2d31df0 | ||
|
|
2355d799f2 | ||
|
|
589f75b60d | ||
|
|
6aebbc2be4 | ||
|
|
fb4bce36cb | ||
|
|
3321f49253 | ||
|
|
5c6fd0453b | ||
|
|
179dec4c3b | ||
|
|
d59a4c63db | ||
|
|
4c3daf6e6f | ||
|
|
c220b6e0c2 | ||
|
|
e4f79dbfce | ||
|
|
d220812f5e | ||
|
|
d4a23c1fbe | ||
|
|
a57c18f63f | ||
|
|
8256af5cfa | ||
|
|
eae3668aee | ||
|
|
8d04330dc5 | ||
|
|
b7ab1df4e3 | ||
|
|
664c95e95a | ||
|
|
a8d292a0d9 | ||
|
|
6e9f6e8f7a | ||
|
|
d0604a055f | ||
|
|
193475a0b6 | ||
|
|
47b444a742 | ||
|
|
3c3b44d6de | ||
|
|
88c2b40ec7 | ||
|
|
88ffa163c4 | ||
|
|
956ed013cf | ||
|
|
061ebf06c6 | ||
|
|
e6911ce24a | ||
|
|
d9c9f6a5eb | ||
|
|
2a04628459 | ||
|
|
33b473c290 | ||
|
|
58b48c2f26 | ||
|
|
ad003a0fc4 | ||
|
|
8f9c417c04 | ||
|
|
8bbf7a849b | ||
|
|
a723bcdb46 | ||
|
|
3d0d836d92 | ||
|
|
67ea6c8066 | ||
|
|
cd1dc5b43d | ||
|
|
1d1c10f0a6 | ||
|
|
125f2a8662 | ||
|
|
4046fed60f | ||
|
|
78ca2f68cc | ||
|
|
18fcf80b4f | ||
|
|
4db28bf47e | ||
|
|
917aa9407d | ||
|
|
6fc2bc4f91 | ||
|
|
7dc6b71252 | ||
|
|
53c7f4c119 | ||
|
|
af4243aff2 | ||
|
|
afc69a3229 | ||
|
|
17dfd130b6 | ||
|
|
05101650ce | ||
|
|
715477586c | ||
|
|
fd61f82f5a | ||
|
|
8b0a6906c7 | ||
|
|
be44bf0b55 | ||
|
|
d2536379e5 | ||
|
|
08d7ad80df | ||
|
|
33a5709903 | ||
|
|
280cbc2330 | ||
|
|
746e75b9e4 | ||
|
|
11decd5889 | ||
|
|
be136d3ce4 | ||
|
|
60fd4ec516 | ||
|
|
b136480669 | ||
|
|
07bd1e03d0 | ||
|
|
75ef1341eb | ||
|
|
ed6b60429c | ||
|
|
2edb12bc18 | ||
|
|
5843e226c3 | ||
|
|
4fc73fdc35 | ||
|
|
78fbc787a4 | ||
|
|
8af71742a0 | ||
|
|
22e550820d | ||
|
|
372f81a09e | ||
|
|
22f5ba4bb1 | ||
|
|
028e247df8 | ||
|
|
4038c0649c | ||
|
|
8aee574069 | ||
|
|
c220aa746a | ||
|
|
da00dd9eec | ||
|
|
30b55ae150 | ||
|
|
6b70826961 | ||
|
|
ae8dfde69d | ||
|
|
63661a40e3 | ||
|
|
b76ee25d49 | ||
|
|
3f7c7692ab | ||
|
|
e34d896278 | ||
|
|
3e90baef02 | ||
|
|
7ed87f87e0 | ||
|
|
35af0aa4b0 | ||
|
|
370b0674bd | ||
|
|
e0c3e28809 | ||
|
|
53302ac082 | ||
|
|
9ff605e08b | ||
|
|
5593327dbc | ||
|
|
31b0510bbd | ||
|
|
beba9c029d | ||
|
|
243053659c | ||
|
|
f2d30e3680 | ||
|
|
76d881bac1 | ||
|
|
c5fd282653 | ||
|
|
d276af6fa9 | ||
|
|
ba19ce4919 | ||
|
|
d86a7a1653 | ||
|
|
f3c82f85c8 | ||
|
|
b17eaba8bf | ||
|
|
0600d6a4d8 | ||
|
|
c51fb1779b | ||
|
|
34b7a28fbe | ||
|
|
a446152631 | ||
|
|
61c2abee35 | ||
|
|
c1d520f1cf | ||
|
|
3bd9e44155 | ||
|
|
7311517d65 | ||
|
|
4568a197e7 | ||
|
|
350134b256 | ||
|
|
1350cf5675 | ||
|
|
21db2e7d4a | ||
|
|
cda08242f1 | ||
|
|
fc8936986f | ||
|
|
ec37fd065f | ||
|
|
47875a4525 | ||
|
|
61adb1e6cf | ||
|
|
907e46631c | ||
|
|
aedf8cda47 | ||
|
|
7a1f5539ed | ||
|
|
49087e9a53 | ||
|
|
c6704d8129 |
1
.github/workflows/build.yaml
vendored
1
.github/workflows/build.yaml
vendored
@@ -20,6 +20,7 @@ jobs:
|
||||
with:
|
||||
php-version: 7.3
|
||||
extensions: opcache, gd
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
env:
|
||||
COMPOSER_TOKEN: ${{ secrets.GLOBAL_TOKEN }}
|
||||
|
||||
3
.github/workflows/tests.yaml
vendored
3
.github/workflows/tests.yaml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: [ 8.0, 7.4, 7.3]
|
||||
php: [ 8.1, 8.0, 7.4, 7.3]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
@@ -25,6 +25,7 @@ jobs:
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: opcache, gd
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
env:
|
||||
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -59,9 +59,9 @@ RewriteRule .* index.php [L]
|
||||
# Block all direct access for these folders
|
||||
RewriteRule ^(\.git|cache|bin|logs|backup|webserver-configs|tests)/(.*) error [F]
|
||||
# Block access to specific file types for these system folders
|
||||
RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||
RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||
# Block access to specific file types for these user folders
|
||||
RewriteRule ^(user)/(.*)\.(txt|md|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||
RewriteRule ^(user)/(.*)\.(txt|md|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||
# Block all direct access to .md files:
|
||||
RewriteRule \.md$ error [F]
|
||||
# Block all direct access to files and folders beginning with a dot
|
||||
|
||||
135
CHANGELOG.md
135
CHANGELOG.md
@@ -1,3 +1,138 @@
|
||||
# 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
|
||||
|
||||
1. [](#new)
|
||||
* Updated phpstan to v1.0
|
||||
* Added `FlexObject::getDiff()` to see difference to the saved object
|
||||
2. [](#improved)
|
||||
* Use Symfony `dump` instead of PHP's `vardump` in side the `{{ vardump(x) }}` Twig vardump function
|
||||
* Added `route` and `request` to `onPagesInitialized` event
|
||||
* Improved page cloning, added method `Page::initialize()`
|
||||
* Improved `FlexObject::getChanges()`: return changed lists and arrays as whole instead of just changed keys/values
|
||||
* Improved form validation JSON responses to contain list of failed fields with their error messages
|
||||
* Improved redirects: send redirect response in JSON if the request was in JSON
|
||||
3. [](#bugfix)
|
||||
* Fixed path traversal vulnerability when using `bin/grav server`
|
||||
* Fixed unescaped error messages in JSON error responses
|
||||
* Fixed `|t(variable)` twig filter in admin
|
||||
* Fixed `FlexObject::getChanges()` always returning empty array
|
||||
* Fixed form validation exceptions to use `400 Bad Request` instead of `500 Internal Server Error`
|
||||
|
||||
# v1.7.24
|
||||
## 10/26/2021
|
||||
|
||||
1. [](#new)
|
||||
* Added support for image watermarks
|
||||
* Added support to disable a form, making it readonly
|
||||
2. [](#improved)
|
||||
* Flex `$user->authorize()` now checks user groups before `admin.super`, allowing deny rules to work properly
|
||||
3. [](#bugfix)
|
||||
* Fixed a bug in `PermissionsReader` in PHP 7.3
|
||||
* Fixed `session_store_active` language option (#3464)
|
||||
* Fixed deprecated warnings on `ArrayAccess` in PHP 8.1
|
||||
* Fixed XSS detection with `:`
|
||||
|
||||
# v1.7.23
|
||||
## 09/29/2021
|
||||
|
||||
1. [](#new)
|
||||
* Added method `Pages::referrerRoute()` to get the referrer route and language
|
||||
* Added true unique `Utils::uniqueId()` / `{{ unique_id() }}` utilities with length, prefix, and suffix support
|
||||
* Added `UserObject::isMyself()` method to check if flex user is currently logged in
|
||||
* Added support for custom form field options validation with `validate: options: key|ignore`
|
||||
2. [](#improved)
|
||||
* Replaced GPL `SVG-Sanitizer` with MIT licensed `DOM-Sanitizer`
|
||||
* `Uri::referrer()` now accepts third parameter, if set to `true`, it returns route without base or language code [#3411](https://github.com/getgrav/grav/issues/3411)
|
||||
* Updated vendor libs with latest
|
||||
* Updated with latest language strings via Crowdin.com
|
||||
3. [](#bugfix)
|
||||
* Fixed `Folder::move()` throwing an error when target folder is changed by only appending characters to the end [#3445](https://github.com/getgrav/grav/issues/3445)
|
||||
* Fixed some phpstan issues (all code back to level 1, Framework level 3)
|
||||
* Fixed form reset causing image uploads to fail when using Flex
|
||||
|
||||
# v1.7.22
|
||||
## 09/16/2021
|
||||
|
||||
1. [](#new)
|
||||
* Register plugin autoloaders into plugin objects
|
||||
2. [](#improved)
|
||||
* Improve Twig 2 compatibility
|
||||
* Update to customized version of Twig DeferredExtension (Twig 1/2 compatible)
|
||||
3. [](#bugfix)
|
||||
* Fixed conflicting `$_original` variable in `Flex Pages`
|
||||
|
||||
# v1.7.21
|
||||
## 09/14/2021
|
||||
|
||||
1. [](#new)
|
||||
* Added `|yaml` filter to convert input to YAML
|
||||
* Added `route` and `request` to `onPageNotFound` event
|
||||
* Added file upload/remove support for `Flex Forms`
|
||||
* Added support for `flex-required@: not exists` and `flex-required@: '!exists'` in blueprints
|
||||
* Added `$object->getOriginalData()` to get flex objects data before it was modified with `update()`
|
||||
* Throwing exceptions from Twig templates fires `onDisplayErrorPage.[code]` event allowing better error pages
|
||||
2. [](#improved)
|
||||
* Use a simplified text-based `cron` field for scheduler
|
||||
* Add timestamp to logging output of scheduler jobs to see when they ran
|
||||
3. [](#bugfix)
|
||||
* Fixed escaping in PageIndex::getLevelListing()
|
||||
* Fixed validation of `number` type [#3433](https://github.com/getgrav/grav/issues/3433)
|
||||
* Fixed excessive `security.yaml` file creation [#3432](https://github.com/getgrav/grav/issues/3432)
|
||||
* Fixed incorrect port :0 with nginx unix socket setup [#3439](https://github.com/getgrav/grav/issues/3439)
|
||||
* Fixed `Session::setFlashCookieObject()` to use the same options as the main session cookie
|
||||
|
||||
# v1.7.20
|
||||
## 09/01/2021
|
||||
|
||||
|
||||
15
README.md
15
README.md
@@ -2,13 +2,13 @@
|
||||
|
||||
[](https://github.com/phpstan/phpstan)
|
||||
[](https://chat.getgrav.org)
|
||||
[](https://github.com/getgrav/grav/actions?query=workflow%3A%22PHP+Tests%22) [](#backers) [](#sponsors)
|
||||
[](https://github.com/getgrav/grav/actions?query=workflow%3A%22PHP+Tests%22) [](#backers) [](#supporters) [](#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
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
/* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved. */
|
||||
/* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved. */
|
||||
|
||||
@@ -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.
6
bin/gpm
6
bin/gpm
@@ -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,10 +25,6 @@ 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');
|
||||
}
|
||||
|
||||
6
bin/grav
6
bin/grav
@@ -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,10 +25,6 @@ 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');
|
||||
}
|
||||
|
||||
@@ -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,10 +25,6 @@ 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');
|
||||
}
|
||||
|
||||
2
cache/.gitkeep
vendored
2
cache/.gitkeep
vendored
@@ -1 +1 @@
|
||||
/* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved. */
|
||||
/* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved. */
|
||||
|
||||
@@ -19,17 +19,18 @@
|
||||
"ext-zip": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-libxml": "*",
|
||||
"symfony/polyfill-mbstring": "~1.20",
|
||||
"symfony/polyfill-iconv": "^1.20",
|
||||
"symfony/polyfill-php74": "^1.20",
|
||||
"symfony/polyfill-php80": "^1.20",
|
||||
"symfony/polyfill-mbstring": "~1.23",
|
||||
"symfony/polyfill-iconv": "^1.23",
|
||||
"symfony/polyfill-php74": "^1.23",
|
||||
"symfony/polyfill-php80": "^1.23",
|
||||
"symfony/polyfill-php81": "^1.23",
|
||||
"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",
|
||||
@@ -47,25 +48,23 @@
|
||||
"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",
|
||||
"phive/twig-extensions-deferred": "^1.0",
|
||||
"willdurand/negotiation": "^3.0",
|
||||
"itsgoingd/clockwork": "^5.0",
|
||||
"enshrined/svg-sanitize": "~0.13",
|
||||
"symfony/http-client": "^4.4",
|
||||
"composer/semver": "^1.4"
|
||||
"composer/semver": "^1.4",
|
||||
"rhukster/dom-sanitizer": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "^4.1",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-deprecation-rules": "^0.12",
|
||||
"phpstan/phpstan": "^1.2",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpunit/php-code-coverage": "~9.2",
|
||||
"getgrav/markdowndocs": "^2.0",
|
||||
"codeception/module-asserts": "^1.3",
|
||||
@@ -93,12 +92,20 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Grav\\": "system/src/Grav"
|
||||
"Grav\\": "system/src/Grav",
|
||||
"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"
|
||||
@@ -107,8 +114,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=480M system/src",
|
||||
"phpstan-framework": "vendor/bin/phpstan analyse -l 1 -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 1 -c ./tests/phpstan/phpstan.neon --memory-limit=720M system/src",
|
||||
"phpstan-framework": "vendor/bin/phpstan analyse -l 4 -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"
|
||||
|
||||
960
composer.lock
generated
960
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
/* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved. */
|
||||
/* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
/* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved. */
|
||||
/* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved. */
|
||||
|
||||
@@ -47,7 +47,8 @@ form:
|
||||
label: PLUGIN_ADMIN.EXTRA_ARGUMENTS
|
||||
placeholder: '-lah'
|
||||
.at:
|
||||
type: cron
|
||||
type: text
|
||||
wrapper_classes: cron-selector
|
||||
label: PLUGIN_ADMIN.SCHEDULER_RUNAT
|
||||
help: PLUGIN_ADMIN.SCHEDULER_RUNAT_HELP
|
||||
placeholder: '* * * * *'
|
||||
|
||||
@@ -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
|
||||
@@ -1446,6 +1509,10 @@ form:
|
||||
title: PLUGIN_ADMIN.ADVANCED
|
||||
underline: true
|
||||
|
||||
gpm_section:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.GPM_SECTION
|
||||
|
||||
gpm.releases:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.GPM_RELEASES
|
||||
@@ -1455,23 +1522,6 @@ form:
|
||||
stable: PLUGIN_ADMIN.STABLE
|
||||
testing: PLUGIN_ADMIN.TESTING
|
||||
|
||||
gpm.proxy_url:
|
||||
type: text
|
||||
size: medium
|
||||
placeholder: "e.g. 127.0.0.1:3128"
|
||||
label: PLUGIN_ADMIN.PROXY_URL
|
||||
help: PLUGIN_ADMIN.PROXY_URL_HELP
|
||||
|
||||
gpm.method:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.GPM_METHOD
|
||||
highlight: auto
|
||||
help: PLUGIN_ADMIN.GPM_METHOD_HELP
|
||||
options:
|
||||
auto: PLUGIN_ADMIN.AUTO
|
||||
fopen: PLUGIN_ADMIN.FOPEN
|
||||
curl: PLUGIN_ADMIN.CURL
|
||||
|
||||
gpm.official_gpm_only:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.GPM_OFFICIAL_ONLY
|
||||
@@ -1484,17 +1534,80 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
gpm.verify_peer:
|
||||
http_section:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.HTTP_SECTION
|
||||
|
||||
http.method:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.GPM_VERIFY_PEER
|
||||
label: PLUGIN_ADMIN.GPM_METHOD
|
||||
highlight: auto
|
||||
help: PLUGIN_ADMIN.GPM_METHOD_HELP
|
||||
options:
|
||||
auto: PLUGIN_ADMIN.AUTO
|
||||
fopen: PLUGIN_ADMIN.FOPEN
|
||||
curl: PLUGIN_ADMIN.CURL
|
||||
|
||||
http.enable_proxy:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.SSL_ENABLE_PROXY
|
||||
highlight: 1
|
||||
help: PLUGIN_ADMIN.GPM_VERIFY_PEER_HELP
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
default: false
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
http.proxy_url:
|
||||
type: text
|
||||
size: medium
|
||||
placeholder: "e.g. 127.0.0.1:3128"
|
||||
label: PLUGIN_ADMIN.PROXY_URL
|
||||
help: PLUGIN_ADMIN.PROXY_URL_HELP
|
||||
|
||||
http.proxy_cert_path:
|
||||
type: text
|
||||
size: medium
|
||||
placeholder: "e.g. /Users/bob/certs/"
|
||||
label: PLUGIN_ADMIN.PROXY_CERT
|
||||
help: PLUGIN_ADMIN.PROXY_CERT_HELP
|
||||
|
||||
http.verify_peer:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.SSL_VERIFY_PEER
|
||||
highlight: 1
|
||||
help: PLUGIN_ADMIN.SSL_VERIFY_PEER_HELP
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
http.verify_host:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.SSL_VERIFY_HOST
|
||||
highlight: 1
|
||||
help: PLUGIN_ADMIN.SSL_VERIFY_HOST_HELP
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
http.concurrent_connections:
|
||||
type: number
|
||||
size: x-small
|
||||
label: PLUGIN_ADMIN.HTTP_CONNECTIONS
|
||||
help: PLUGIN_ADMIN.HTTP_CONNECTIONS_HELP
|
||||
validate:
|
||||
min: 1
|
||||
max: 20
|
||||
|
||||
misc_section:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.MISC_SECTION
|
||||
|
||||
reverse_proxy_setup:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.REVERSE_PROXY
|
||||
|
||||
@@ -104,7 +104,7 @@ config:
|
||||
|
||||
edit:
|
||||
title:
|
||||
template: "{% if object.root %}Root <small>( <root> ){% else %}{{ (form.value('header.title') ?? form.value('folder'))|e }} <small>( {{ (object.getRoute().toString(false) ?: '/')|e }} )</small>{% endif %}"
|
||||
template: "{% if object.root %}Root <small>( <root> )</small>{% else %}{{ (form.value('header.title') ?? form.value('folder'))|e }} <small>( {{ (object.getRoute().toString(false) ?: '/')|e }} )</small>{% endif %}"
|
||||
|
||||
# TODO: not used yet
|
||||
buttons:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -107,6 +107,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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ cache:
|
||||
purge_at: '0 4 * * *' # How often to purge old file cache (using new scheduler)
|
||||
clear_at: '0 3 * * *' # How often to clear cache (using new scheduler)
|
||||
clear_job_type: 'standard' # Type to clear when processing the scheduled clear job `standard`|`all`
|
||||
clear_images_by_default: false # By default grav does not include processed images in cache clear, this can be enabled
|
||||
clear_images_by_default: false # By default grav does not include processed images in cache clear, this can be enabled
|
||||
cli_compatibility: false # Ensures only non-volatile drivers are used (file, redis, memcache, etc.)
|
||||
lifetime: 604800 # Lifetime of cached data in seconds (0 = infinite)
|
||||
gzip: false # GZip compress the page output
|
||||
@@ -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
|
||||
@@ -162,6 +165,12 @@ images:
|
||||
retina_scale: 1 # scale to adjust auto-sizes for better handling of HiDPI resolutions
|
||||
defaults:
|
||||
loading: auto # Let browser pick [auto|lazy|eager]
|
||||
watermark:
|
||||
image: 'system://images/watermark.png' # Path to a watermark image
|
||||
position_y: 'center' # top|center|bottom
|
||||
position_x: 'center' # left|center|right
|
||||
scale: 33 # percentage of watermark scale
|
||||
watermark_all: false # automatically watermark all images
|
||||
|
||||
media:
|
||||
enable_media_timestamp: false # Enable media timestamps
|
||||
@@ -176,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)
|
||||
@@ -184,11 +194,17 @@ session:
|
||||
|
||||
gpm:
|
||||
releases: stable # Set to either 'stable' or 'testing'
|
||||
proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128)
|
||||
method: 'auto' # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL
|
||||
verify_peer: true # Sometimes on some systems (Windows most commonly) GPM is unable to connect because the SSL certificate cannot be verified. Disabling this setting might help.
|
||||
official_gpm_only: true # By default GPM direct-install will only allow URLs via the official GPM proxy to ensure security
|
||||
|
||||
http:
|
||||
method: auto # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL
|
||||
enable_proxy: true # Enable proxy server configuration
|
||||
proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128)
|
||||
proxy_cert_path: # Local path to proxy certificate folder containing pem files
|
||||
concurrent_connections: 5 # Concurrent HTTP connections when multiplexing
|
||||
verify_peer: true # Enable/Disable SSL verification of peer certificates
|
||||
verify_host: true # Enable/Disable SSL verification of host certificates
|
||||
|
||||
accounts:
|
||||
type: regular # EXPERIMENTAL: Account type: regular or flex
|
||||
storage: file # EXPERIMENTAL: Flex storage type: file or folder
|
||||
|
||||
@@ -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.20');
|
||||
define('GRAV_VERSION', '1.7.27');
|
||||
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
|
||||
define('GRAV_TESTING', false);
|
||||
|
||||
|
||||
BIN
system/images/watermark.png
Normal file
BIN
system/images/watermark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ GRAV:
|
||||
VALIDATION_FAIL: '<b>فشل التحقق من صحة:</b>'
|
||||
INVALID_INPUT: 'إدخال غير صحيح في'
|
||||
MISSING_REQUIRED_FIELD: 'حقل مطلوب مفقود:'
|
||||
XSS_ISSUES: "مشاكل XSS محتملة تم اكتشافها في حقل '%s' '"
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'كانون الثاني'
|
||||
- 'شباط'
|
||||
@@ -72,6 +73,8 @@ GRAV:
|
||||
- 'الجمعة'
|
||||
- 'السبت'
|
||||
- 'الأحد'
|
||||
YES: "نعم"
|
||||
NO: "لا"
|
||||
CRON:
|
||||
EVERY: كل
|
||||
EVERY_HOUR: كل ساعة
|
||||
@@ -80,3 +83,11 @@ GRAV:
|
||||
EVERY_DAY_OF_MONTH: كل يوم في الشهر
|
||||
EVERY_MONTH: ' كل شهر'
|
||||
TEXT_PERIOD: كل <b />
|
||||
TEXT_MINS: ' في <b /> دقيقة(دقائق) بعد الساعة'
|
||||
TEXT_TIME: ' في <b />:<b />'
|
||||
TEXT_DOW: ' في <b />'
|
||||
TEXT_MONTH: ' من <b />'
|
||||
TEXT_DOM: ' في <b />'
|
||||
ERROR1: الوسم %s غير مدعوم!
|
||||
ERROR2: عدد عناصر غير صالح.
|
||||
ERROR4: تعبير غير معروف
|
||||
|
||||
@@ -15,6 +15,7 @@ GRAV:
|
||||
BAD_DATE: Data invàlida
|
||||
AGO: abans
|
||||
FROM_NOW: des d'ara
|
||||
JUST_NOW: Ara mateix
|
||||
SECOND: segon
|
||||
MINUTE: minut
|
||||
HOUR: hora
|
||||
@@ -48,6 +49,7 @@ GRAV:
|
||||
VALIDATION_FAIL: '<b>Ha fallat la validació:</b>'
|
||||
INVALID_INPUT: 'Entrada no vàlida a'
|
||||
MISSING_REQUIRED_FIELD: 'Falta camp obligatori:'
|
||||
XSS_ISSUES: "Detectats potencials problemes XSS al camp '%s'"
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'Gener'
|
||||
- 'Febrer'
|
||||
@@ -69,3 +71,17 @@ GRAV:
|
||||
- 'Divendres'
|
||||
- 'Dissabte'
|
||||
- 'Diumenge'
|
||||
YES: "Sí"
|
||||
NO: "No"
|
||||
CRON:
|
||||
EVERY: cada
|
||||
EVERY_HOUR: cada hora
|
||||
EVERY_MINUTE: cada minut
|
||||
EVERY_DAY_OF_WEEK: cada dia de la setmana
|
||||
EVERY_DAY_OF_MONTH: cada dia del mes
|
||||
EVERY_MONTH: cada mes
|
||||
TEXT_PERIOD: Cada <b />
|
||||
ERROR1: L'etiqueta %s no està suportada!
|
||||
ERROR2: Nombre d'elements incorrecte
|
||||
ERROR3: El jquery_element s'ha d'establir a la configuració de jqCron
|
||||
ERROR4: Expressió no reconeguda
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,6 +24,7 @@ GRAV:
|
||||
'/(quiz)zes$/i': '\1'
|
||||
'/(alias|status)es$/i': '\1'
|
||||
'/([octop|vir])i$/i': '\1us'
|
||||
'/(n)ews$/i': '\1ouvelles'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- 'équipement'
|
||||
- 'information'
|
||||
@@ -58,10 +59,10 @@ GRAV:
|
||||
MONTH: mois
|
||||
YEAR: année
|
||||
DECADE: décennie
|
||||
SEC: s
|
||||
MIN: m
|
||||
HR: h
|
||||
WK: sem
|
||||
SEC: sec.
|
||||
MIN: min.
|
||||
HR: hr.
|
||||
WK: sem.
|
||||
MO: m
|
||||
YR: an
|
||||
DEC: déc
|
||||
@@ -84,6 +85,7 @@ GRAV:
|
||||
VALIDATION_FAIL: '<b>La validation a échoué :</b>'
|
||||
INVALID_INPUT: 'Saisie non valide'
|
||||
MISSING_REQUIRED_FIELD: 'Champ obligatoire manquant :'
|
||||
XSS_ISSUES: "Erreurs XSS probablement détectées dans le champ '%s'"
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'janvier'
|
||||
- 'février'
|
||||
@@ -105,6 +107,8 @@ GRAV:
|
||||
- 'vendredi'
|
||||
- 'samedi'
|
||||
- 'dimanche'
|
||||
YES: "Oui"
|
||||
NO: "Non"
|
||||
CRON:
|
||||
EVERY: chaque
|
||||
EVERY_HOUR: toutes les heures
|
||||
@@ -118,7 +122,7 @@ GRAV:
|
||||
TEXT_DOW: ' sur <b/>'
|
||||
TEXT_MONTH: ' de <b />'
|
||||
TEXT_DOM: ' sur <b/>'
|
||||
ERROR1: La balise %s n'est pas supportée!
|
||||
ERROR1: La balise %s n'est pas prise en charge !
|
||||
ERROR2: Nombre invalide d'éléments
|
||||
ERROR3: L'élément jquery_element doit être défini dans les paramètres jqCron
|
||||
ERROR4: Expression non reconnue
|
||||
|
||||
@@ -104,6 +104,7 @@ GRAV:
|
||||
VALIDATION_FAIL: '<b>Fallou a validación:</b>'
|
||||
INVALID_INPUT: 'Entrada incorrecta en'
|
||||
MISSING_REQUIRED_FIELD: 'Falta un campo requirido:'
|
||||
XSS_ISSUES: "Detectáronse posibles problemas XSS no campo '% s'"
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'xaneiro'
|
||||
- 'febreiro'
|
||||
@@ -125,6 +126,8 @@ GRAV:
|
||||
- 'venres'
|
||||
- 'sábado'
|
||||
- 'domingo'
|
||||
YES: "Si"
|
||||
NO: "Non"
|
||||
CRON:
|
||||
EVERY: cada
|
||||
EVERY_HOUR: Cada hora
|
||||
|
||||
@@ -3,26 +3,72 @@ GRAV:
|
||||
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Error: Frontmatter tidak valid\n\nLokasi: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_PLURALS:
|
||||
'/(quiz)$/i': '\1zes'
|
||||
'/^(ox)$/i': '\1en'
|
||||
'/([m|l])ouse$/i': '\1ice'
|
||||
'/(matr|vert|ind)ix|ex$/i': '\1ices'
|
||||
'/(x|ch|ss|sh)$/i': '\1es'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([^aeiouy]|qu)y$/i': '\1ies'
|
||||
'/(hive)$/i': '\1s'
|
||||
'/(?:([^f])fe|([lr])f)$/i': '\1\2ves'
|
||||
'/sis$/i': 'ses'
|
||||
'/([ti])um$/i': '\1a'
|
||||
'/(buffal|tomat)o$/i': '\1oes'
|
||||
'/(bu)s$/i': '\1ses'
|
||||
'/(alias|status)/i': '\1es'
|
||||
'/(octop|vir)us$/i': '\1i'
|
||||
'/(ax|test)is$/i': '\1es'
|
||||
'/s$/i': 's'
|
||||
'/$/': 's'
|
||||
INFLECTOR_SINGULAR:
|
||||
'/(quiz)zes$/i': '\1'
|
||||
'/(matr)ices$/i': '\1ix'
|
||||
'/(vert|ind)ices$/i': '\1ex'
|
||||
'/^(ox)en/i': '\1'
|
||||
'/(alias|status)es$/i': '\1'
|
||||
'/([octop|vir])i$/i': '\1us'
|
||||
'/(cris|ax|test)es$/i': '\1is'
|
||||
'/(shoe)s$/i': '\1'
|
||||
'/(o)es$/i': '\1'
|
||||
'/(bus)es$/i': '\1'
|
||||
'/([m|l])ice$/i': '\1ouse'
|
||||
'/(x|ch|ss|sh)es$/i': '\1'
|
||||
'/(m)ovies$/i': '\1ovie'
|
||||
'/(s)eries$/i': '\1eries'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([lr])ves$/i': '\1f'
|
||||
'/(tive)s$/i': '\1'
|
||||
'/(hive)s$/i': '\1'
|
||||
'/([^f])ves$/i': '\1fe'
|
||||
'/(^analy)ses$/i': '\1sis'
|
||||
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2sis'
|
||||
'/([ti])a$/i': '\1um'
|
||||
'/(n)ews$/i': '\1ews'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- 'peralatan'
|
||||
- 'informasi'
|
||||
- 'nasi'
|
||||
- 'uang'
|
||||
- 'spesies'
|
||||
- 'rangkaian'
|
||||
- 'ikan'
|
||||
- 'domba'
|
||||
- 'Peralatan'
|
||||
- 'Informasi '
|
||||
- 'Nasi'
|
||||
- 'Uang'
|
||||
- 'Jenis'
|
||||
- 'Seri'
|
||||
- 'Ikan'
|
||||
- 'Domba'
|
||||
INFLECTOR_IRREGULAR:
|
||||
'person': 'orang-orang'
|
||||
'man': 'laki-laki'
|
||||
'child': 'anak-anak'
|
||||
'sex': 'jenis kelamin'
|
||||
'person': 'Orang-orang'
|
||||
'man': 'Pria'
|
||||
'child': 'Balita'
|
||||
'sex': 'Jenis Kelamin'
|
||||
'move': 'pindahkan'
|
||||
INFLECTOR_ORDINALS:
|
||||
'default': 'ke'
|
||||
'first': 'pertama'
|
||||
'second': 'nd'
|
||||
'third': 'rd'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Tanggal tidak tersedia
|
||||
NO_DATE_PROVIDED: Tidak ada tanggal yang disediakan
|
||||
BAD_DATE: Format tanggal salah
|
||||
AGO: yang lalu
|
||||
FROM_NOW: dari saat ini
|
||||
FROM_NOW: dari sekarang
|
||||
JUST_NOW: baru saja
|
||||
SECOND: detik
|
||||
MINUTE: menit
|
||||
@@ -32,12 +78,12 @@ GRAV:
|
||||
MONTH: bulan
|
||||
YEAR: tahun
|
||||
DECADE: dekade
|
||||
SEC: dtk
|
||||
MIN: mnt
|
||||
HR: j
|
||||
WK: mng
|
||||
MO: bln
|
||||
YR: thn
|
||||
SEC: detik
|
||||
MIN: menit
|
||||
HR: ' jam'
|
||||
WK: minggu
|
||||
MO: bulan
|
||||
YR: tahun
|
||||
DEC: desimal
|
||||
SECOND_PLURAL: detik
|
||||
MINUTE_PLURAL: menit
|
||||
@@ -47,17 +93,18 @@ GRAV:
|
||||
MONTH_PLURAL: bulan
|
||||
YEAR_PLURAL: tahun
|
||||
DECADE_PLURAL: dekade
|
||||
SEC_PLURAL: dtk
|
||||
MIN_PLURAL: mnt
|
||||
HR_PLURAL: j
|
||||
WK_PLURAL: mgg
|
||||
MO_PLURAL: bln
|
||||
YR_PLURAL: thn
|
||||
SEC_PLURAL: detik
|
||||
MIN_PLURAL: menit
|
||||
HR_PLURAL: jam
|
||||
WK_PLURAL: minggu
|
||||
MO_PLURAL: bulan
|
||||
YR_PLURAL: tahun
|
||||
DEC_PLURAL: dekade
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Validasi gagal:</b>'
|
||||
INVALID_INPUT: 'Input tidak valid di'
|
||||
MISSING_REQUIRED_FIELD: 'Data yang diperlukan belum terisi:'
|
||||
XSS_ISSUES: "Isu berpotensial XSS terdeteksi dalam baris %s"
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'Januari'
|
||||
- 'Februari'
|
||||
@@ -76,22 +123,25 @@ GRAV:
|
||||
- 'Selasa'
|
||||
- 'Rabu'
|
||||
- 'Kamis'
|
||||
- 'Jumat'
|
||||
- 'Jum''at'
|
||||
- 'Sabtu'
|
||||
- 'Minggu'
|
||||
YES: "Ya"
|
||||
NO: "Tidak"
|
||||
CRON:
|
||||
EVERY: Setiap
|
||||
EVERY_HOUR: Setiap jam
|
||||
EVERY_MINUTE: Setiap menit
|
||||
EVERY_DAY_OF_WEEK: Setiap hari selama seminggu
|
||||
EVERY_DAY_OF_MONTH: pada tanggal setiap bulannya
|
||||
EVERY_DAY_OF_MONTH: Setiap hari dalam sebulan
|
||||
EVERY_MONTH: setiap bulan
|
||||
TEXT_PERIOD: Setiap <b />
|
||||
TEXT_MINS: 'dalam <b /> menit setelah jam yang lalu'
|
||||
TEXT_TIME: ' pada <b />:<b />'
|
||||
TEXT_DOW: ' pada <b />'
|
||||
TEXT_MONTH: ' pada <b />'
|
||||
TEXT_DOM: ' pada <b />'
|
||||
ERROR1: Tag %s tidak didukung!
|
||||
ERROR2: Jumlah elemen tidak valid
|
||||
ERROR3: jquery_element harus ditetapkan ke pengaturan jqCron
|
||||
ERROR4: Ekspresi tidak dikenali
|
||||
ERROR2: Jumlah elemen yang buruk
|
||||
ERROR3: jquery_element harus diatur ke dalam pengaturan jqCron
|
||||
ERROR4: Ekspresi tidak dikenal
|
||||
|
||||
147
system/languages/mn.yaml
Normal file
147
system/languages/mn.yaml
Normal file
@@ -0,0 +1,147 @@
|
||||
---
|
||||
GRAV:
|
||||
FRONTMATTER_ERROR_PAGE: "---\nГарчиг: %1$s\n---\n\n# Алдаа: Буруу Формат\n\nЗам: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_PLURALS:
|
||||
'/(quiz)$/i': '\1зүүд'
|
||||
'/^(ox)$/i': '\1ууд'
|
||||
'/([m|l])ouse$/i': '\1ууд'
|
||||
'/(matr|vert|ind)ix|ex$/i': '\1иксүүд'
|
||||
'/(x|ch|ss|sh)$/i': '\1үүд'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1үүд'
|
||||
'/([^aeiouy]|qu)y$/i': '\1үүд'
|
||||
'/(hive)$/i': '\1үүд'
|
||||
'/(?:([^f])fe|([lr])f)$/i': '\1\2үүд'
|
||||
'/sis$/i': 'үүд'
|
||||
'/([ti])um$/i': '\1үүд'
|
||||
'/(buffal|tomat)o$/i': '\1үүд'
|
||||
'/(bu)s$/i': '\1үүд'
|
||||
'/(alias|status)/i': '\1үүд'
|
||||
'/(octop|vir)us$/i': '\1үүд'
|
||||
'/(ax|test)is$/i': '\1үүд'
|
||||
'/s$/i': 'үүд'
|
||||
'/$/': 'үүд'
|
||||
INFLECTOR_SINGULAR:
|
||||
'/(quiz)zes$/i': '\1'
|
||||
'/(matr)ices$/i': '\1икс'
|
||||
'/(vert|ind)ices$/i': '\1икс'
|
||||
'/^(ox)en/i': '\1'
|
||||
'/(alias|status)es$/i': '\1'
|
||||
'/([octop|vir])i$/i': '\1'
|
||||
'/(cris|ax|test)es$/i': '\1'
|
||||
'/(shoe)s$/i': '\1'
|
||||
'/(o)es$/i': '\1'
|
||||
'/(bus)es$/i': '\1'
|
||||
'/([m|l])ice$/i': '\1'
|
||||
'/(x|ch|ss|sh)es$/i': '\1'
|
||||
'/(m)ovies$/i': '\1'
|
||||
'/(s)eries$/i': '\1'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1үүд'
|
||||
'/([lr])ves$/i': '\1'
|
||||
'/(tive)s$/i': '\1'
|
||||
'/(hive)s$/i': '\1'
|
||||
'/([^f])ves$/i': '\1'
|
||||
'/(^analy)ses$/i': '\1'
|
||||
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2үүд'
|
||||
'/([ti])a$/i': '\1'
|
||||
'/(n)ews$/i': '\1'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- 'тоног төхөөрөмж'
|
||||
- 'Мэдээлэл'
|
||||
- 'будаа'
|
||||
- 'мөнгө'
|
||||
- 'төрөл зүйл'
|
||||
- 'цуврал'
|
||||
- 'загас'
|
||||
- 'хонь'
|
||||
INFLECTOR_IRREGULAR:
|
||||
'person': 'хүмүүс'
|
||||
'man': 'эрчүүд'
|
||||
'child': 'хүүхэд'
|
||||
'sex': 'хүйс'
|
||||
'move': 'хөдөлгөөн'
|
||||
INFLECTOR_ORDINALS:
|
||||
'default': 'th'
|
||||
'first': 'st'
|
||||
'second': 'nd'
|
||||
'third': 'rd'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Огноо алга
|
||||
BAD_DATE: Буруу огноо
|
||||
AGO: өмнө
|
||||
FROM_NOW: одооноос
|
||||
JUST_NOW: дөнгөж сая
|
||||
SECOND: секунд
|
||||
MINUTE: минут
|
||||
HOUR: цаг
|
||||
DAY: өдөр
|
||||
WEEK: долоо хоног
|
||||
MONTH: сар
|
||||
YEAR: он
|
||||
DECADE: арван жил
|
||||
SEC: сек
|
||||
MIN: мин
|
||||
HR: цаг
|
||||
WK: д.х.
|
||||
MO: сар
|
||||
YR: он
|
||||
DEC: арван жил
|
||||
SECOND_PLURAL: секунд
|
||||
MINUTE_PLURAL: минут
|
||||
HOUR_PLURAL: цаг
|
||||
DAY_PLURAL: өдрүүд
|
||||
WEEK_PLURAL: долоо хоногууд
|
||||
MONTH_PLURAL: сарууд
|
||||
YEAR_PLURAL: онууд
|
||||
DECADE_PLURAL: арван жилүүд
|
||||
SEC_PLURAL: сек.-үүд
|
||||
MIN_PLURAL: мин.-ууд
|
||||
HR_PLURAL: цагууд
|
||||
WK_PLURAL: д.х.-ууд
|
||||
MO_PLURAL: сарууд
|
||||
YR_PLURAL: жилүүд
|
||||
DEC_PLURAL: арван жилүүд
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Баталгаажуулалт амжилтгүй боллоо:</b>'
|
||||
INVALID_INPUT: 'Буруу өгөгдөл дараахид'
|
||||
MISSING_REQUIRED_FIELD: 'Шаардлагатай талбар дутуу байна:'
|
||||
XSS_ISSUES: "'%s' талбарт XSS -ийн болзошгүй асуудлууд илэрсэн"
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- '1-р сар'
|
||||
- '2-р сар'
|
||||
- '3-р сар'
|
||||
- '4-р сар'
|
||||
- '5 сар'
|
||||
- '6 сар'
|
||||
- '7 сар'
|
||||
- '8 сар'
|
||||
- '9 сар'
|
||||
- '10 сар'
|
||||
- '11 сар'
|
||||
- '12 сар'
|
||||
DAYS_OF_THE_WEEK:
|
||||
- 'Даваа гараг'
|
||||
- 'Мягмар гараг'
|
||||
- 'Лхагва гараг'
|
||||
- 'Пүрэв гараг'
|
||||
- 'Баасан гараг'
|
||||
- 'Бямба гараг'
|
||||
- 'Ням гараг'
|
||||
YES: "Тийм"
|
||||
NO: "Үгүй"
|
||||
CRON:
|
||||
EVERY: бүрийн
|
||||
EVERY_HOUR: цаг бүрийн
|
||||
EVERY_MINUTE: минут бүрийн
|
||||
EVERY_DAY_OF_WEEK: долоо хоногийн өдөр болгонд
|
||||
EVERY_DAY_OF_MONTH: сарын өдөр болгонд
|
||||
EVERY_MONTH: сар болгон
|
||||
TEXT_PERIOD: Бүрийн <b />
|
||||
TEXT_MINS: ' <b /> энэ сүүлийн цагийн минутад'
|
||||
TEXT_TIME: ' <b />:<b /> -д'
|
||||
TEXT_DOW: ' <b /> -д'
|
||||
TEXT_MONTH: ' <b /> -ын'
|
||||
TEXT_DOM: ' <b /> -т'
|
||||
ERROR1: '%s -н утга нь дэмжигддэггүй!'
|
||||
ERROR2: Элементүүдийн тоо хэмжээ буруу
|
||||
ERROR3: jquery_element нь jqCron тохиргоонд хийгдсэн байх ёстой
|
||||
ERROR4: Танигдаагүй илэрхийлэл
|
||||
@@ -104,6 +104,7 @@ GRAV:
|
||||
VALIDATION_FAIL: '<b>Falha na validação:</b>'
|
||||
INVALID_INPUT: 'Dados inseridos são inválidos em'
|
||||
MISSING_REQUIRED_FIELD: 'Campo obrigatório em falta:'
|
||||
XSS_ISSUES: "Potenciais problemas de XSS detectados no campo '%s'"
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'Janeiro'
|
||||
- 'Fevereiro'
|
||||
@@ -125,6 +126,8 @@ GRAV:
|
||||
- 'Sexta-feira'
|
||||
- 'Sábado'
|
||||
- 'Domingo'
|
||||
YES: "Sim"
|
||||
NO: "Não"
|
||||
CRON:
|
||||
EVERY: cada
|
||||
EVERY_HOUR: cada hora
|
||||
|
||||
9
system/languages/si.yaml
Normal file
9
system/languages/si.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
GRAV:
|
||||
INFLECTOR_SINGULAR:
|
||||
'/(quiz)zes$/i': '\1'
|
||||
'/^(ox)en/i': '\1'
|
||||
'/(alias|status)es$/i': '\1'
|
||||
'/(o)es$/i': '\1'
|
||||
'/(bus)es$/i': '\1'
|
||||
'/(x|ch|ss|sh)es$/i': '\1'
|
||||
@@ -82,6 +82,8 @@ GRAV:
|
||||
- 'Cuma'
|
||||
- 'Cumartesi'
|
||||
- 'Pazar'
|
||||
YES: "Evet"
|
||||
NO: "Hayır"
|
||||
CRON:
|
||||
EVERY: her
|
||||
EVERY_HOUR: saatte bir
|
||||
|
||||
@@ -38,7 +38,9 @@ GRAV:
|
||||
YR_PLURAL: 年
|
||||
DEC_PLURAL: 十年
|
||||
FORM:
|
||||
MISSING_REQUIRED_FIELD: 遺漏必填欄位:
|
||||
VALIDATION_FAIL: '<b>確驗證失敗:</b>'
|
||||
INVALID_INPUT: '無效輸入:'
|
||||
MISSING_REQUIRED_FIELD: '遺漏必填欄位:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- '一月'
|
||||
- '二月'
|
||||
@@ -60,3 +62,16 @@ GRAV:
|
||||
- '星期五'
|
||||
- '星期六'
|
||||
- '星期日'
|
||||
CRON:
|
||||
EVERY: 每
|
||||
EVERY_HOUR: 每小時
|
||||
EVERY_MINUTE: 每分鐘
|
||||
EVERY_DAY_OF_WEEK: 每一天
|
||||
EVERY_DAY_OF_MONTH: 每一天
|
||||
EVERY_MONTH: 每個月
|
||||
TEXT_PERIOD: 每 <b />
|
||||
TEXT_MINS: ' 的 <b /> 分'
|
||||
TEXT_TIME: ' <b />:<b />'
|
||||
TEXT_DOW: ' 的 <b />'
|
||||
TEXT_MONTH: ' 的 <b />'
|
||||
TEXT_DOM: ' 的 <b />'
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -13,8 +13,25 @@ if (PHP_SAPI !== 'cli-server') {
|
||||
|
||||
$_SERVER['PHP_CLI_ROUTER'] = true;
|
||||
|
||||
if (is_file($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $_SERVER['SCRIPT_NAME'])) {
|
||||
return false;
|
||||
$root = $_SERVER['DOCUMENT_ROOT'];
|
||||
$path = $_SERVER['SCRIPT_NAME'];
|
||||
if ($path !== '/index.php' && is_file($root . $path)) {
|
||||
if (!(
|
||||
// Block all direct access to files and folders beginning with a dot
|
||||
strpos($path, '/.') !== false
|
||||
// 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|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|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
|
||||
|| preg_match('`^/(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$`ui', $path)
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$grav_index = 'index.php';
|
||||
|
||||
165
system/src/DOMLettersIterator.php
Normal file
165
system/src/DOMLettersIterator.php
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
158
system/src/DOMWordsIterator.php
Normal file
158
system/src/DOMWordsIterator.php
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
@@ -193,6 +207,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 +238,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 +246,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 +287,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 +337,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 +447,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 +479,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 +511,58 @@ 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 $group
|
||||
* @param $attributes
|
||||
* @return string
|
||||
*/
|
||||
public function jsModule($group = 'head', $attributes = [])
|
||||
{
|
||||
return $this->render(self::JS_MODULE, $group, $attributes);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected function isValidType($type)
|
||||
{
|
||||
return in_array($type, [self::CSS_TYPE, self::JS_TYPE, self::JS_MODULE_TYPE]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
@@ -92,6 +93,10 @@ abstract class BaseAsset extends PropertyObject
|
||||
*/
|
||||
public function init($asset, $options)
|
||||
{
|
||||
if (!$asset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = Grav::instance()['config'];
|
||||
$uri = Grav::instance()['uri'];
|
||||
|
||||
@@ -244,6 +249,7 @@ abstract class BaseAsset extends PropertyObject
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return ['type' => $this->getType(), 'elements' => $this->getElements()];
|
||||
@@ -259,6 +265,6 @@ abstract class BaseAsset extends PropertyObject
|
||||
*/
|
||||
protected function cssRewrite($file, $dir, $local)
|
||||
{
|
||||
return;
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
46
system/src/Grav/Common/Assets/InlineJsModule.php
Normal file
46
system/src/Grav/Common/Assets/InlineJsModule.php
Normal 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";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
49
system/src/Grav/Common/Assets/JsModule.php
Normal file
49
system/src/Grav/Common/Assets/JsModule.php
Normal 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";
|
||||
}
|
||||
}
|
||||
43
system/src/Grav/Common/Assets/Link.php
Normal file
43
system/src/Grav/Common/Assets/Link.php
Normal 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";
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -254,7 +271,7 @@ class Pipeline extends PropertyObject
|
||||
$old_url = ltrim($old_url, '/');
|
||||
}
|
||||
|
||||
$new_url = ($local ? $this->base_url: '') . $old_url;
|
||||
$new_url = ($local ? $this->base_url : '') . $old_url;
|
||||
|
||||
return str_replace($matches[2], $new_url, $matches[0]);
|
||||
}, $file);
|
||||
@@ -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
|
||||
|
||||
@@ -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,15 +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();
|
||||
@@ -102,21 +100,25 @@ trait AssetUtilsTrait
|
||||
}
|
||||
|
||||
// Double check last character being
|
||||
if (!$css) {
|
||||
if ($type === self::CSS_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);
|
||||
}
|
||||
|
||||
@@ -135,7 +137,7 @@ trait AssetUtilsTrait
|
||||
|
||||
$imports = [];
|
||||
|
||||
$file = (string)preg_replace_callback($regex, function ($matches) use (&$imports) {
|
||||
$file = (string)preg_replace_callback($regex, static function ($matches) use (&$imports) {
|
||||
$imports[] = $matches[0];
|
||||
|
||||
return '';
|
||||
@@ -200,7 +202,7 @@ trait AssetUtilsTrait
|
||||
}
|
||||
|
||||
if ($this->timestamp) {
|
||||
if (Utils::contains($asset, '?') || $querystring) {
|
||||
if ($querystring || Utils::contains($asset, '?')) {
|
||||
$querystring .= '&' . $this->timestamp;
|
||||
} else {
|
||||
$querystring .= '?' . $this->timestamp;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -144,9 +144,8 @@ class Backups
|
||||
public static function getTotalBackupsSize()
|
||||
{
|
||||
$backups = static::getAvailableBackups();
|
||||
$size = array_sum(array_column($backups, 'size'));
|
||||
|
||||
return $size ?? 0;
|
||||
return $backups ? array_sum(array_column($backups, 'size')) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +221,7 @@ class Backups
|
||||
$backup_root = rtrim(GRAV_ROOT . $backup_root, '/');
|
||||
}
|
||||
|
||||
if (!file_exists($backup_root)) {
|
||||
if (!$backup_root || !file_exists($backup_root)) {
|
||||
throw new RuntimeException("Backup location: {$backup_root} does not exist...");
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -141,7 +141,7 @@ class Cache extends Getters
|
||||
$uniqueness = substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION), 2, 8);
|
||||
|
||||
// Cache key allows us to invalidate all cache on configuration changes.
|
||||
$this->key = ($prefix ? $prefix : 'g') . '-' . $uniqueness;
|
||||
$this->key = ($prefix ?: 'g') . '-' . $uniqueness;
|
||||
$this->cache_dir = $grav['locator']->findResource('cache://doctrine/' . $uniqueness, true, true);
|
||||
$this->driver_setting = $this->config->get('system.cache.driver');
|
||||
$this->driver = $this->getCacheDriver();
|
||||
@@ -618,11 +618,7 @@ class Cache extends Getters
|
||||
*/
|
||||
public function isVolatileDriver($setting)
|
||||
{
|
||||
if (in_array($setting, ['apc', 'apcu', 'xcache', 'wincache'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return in_array($setting, ['apc', 'apcu', 'xcache', 'wincache'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -400,8 +400,12 @@ class Setup extends Data
|
||||
$this->initializeLocator($locator);
|
||||
}
|
||||
|
||||
// Create security.yaml if it doesn't exist.
|
||||
$filename = $locator->findResource(static::$securityFile, true, true);
|
||||
// Create security.yaml salt if it doesn't exist into existing configuration environment if possible.
|
||||
$securityFile = basename(static::$securityFile);
|
||||
$securityFolder = substr(static::$securityFile, 0, -\strlen($securityFile));
|
||||
$securityFolder = $locator->findResource($securityFolder, true) ?: $locator->findResource($securityFolder, true, true);
|
||||
$filename = "{$securityFolder}/{$securityFile}";
|
||||
|
||||
$security_file = CompiledYamlFile::instance($filename);
|
||||
$security_content = (array)$security_file->content();
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -37,7 +37,7 @@ class Blueprint extends BlueprintForm
|
||||
/** @var string|null */
|
||||
protected $scope;
|
||||
|
||||
/** @var BlueprintSchema */
|
||||
/** @var BlueprintSchema|null */
|
||||
protected $blueprintSchema;
|
||||
|
||||
/** @var object|null */
|
||||
@@ -54,7 +54,7 @@ class Blueprint extends BlueprintForm
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
if ($this->blueprintSchema) {
|
||||
if (null !== $this->blueprintSchema) {
|
||||
$this->blueprintSchema = clone $this->blueprintSchema;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,15 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
return $this->types[$name] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return array|null
|
||||
*/
|
||||
public function getNestedRules(string $name)
|
||||
{
|
||||
return $this->getNested($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate data against blueprints.
|
||||
*
|
||||
@@ -74,7 +83,7 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
}
|
||||
|
||||
if (!empty($messages)) {
|
||||
throw (new ValidationException())->setMessages($messages);
|
||||
throw (new ValidationException('', 400))->setMessages($messages);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,7 +205,7 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
/** @var Config $config */
|
||||
$config = Grav::instance()['config'];
|
||||
if (!$config->get('system.strict_mode.blueprint_strict_compat', true)) {
|
||||
throw new RuntimeException(sprintf('%s is not defined in blueprints', $key));
|
||||
throw new RuntimeException(sprintf('%s is not defined in blueprints', $key), 400);
|
||||
}
|
||||
|
||||
user_error(sprintf('Having extra key %s in your data is deprecated with blueprint having \'validation: strict\'', $key), E_USER_DEPRECATED);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -264,7 +264,7 @@ class Data implements DataInterface, ArrayAccess, \Countable, JsonSerializable,
|
||||
*/
|
||||
public function blueprints()
|
||||
{
|
||||
if (!$this->blueprints) {
|
||||
if (null === $this->blueprints) {
|
||||
$this->blueprints = new Blueprint();
|
||||
} elseif (is_callable($this->blueprints)) {
|
||||
// Lazy load blueprints.
|
||||
@@ -335,6 +335,7 @@ class Data implements DataInterface, ArrayAccess, \Countable, JsonSerializable,
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->items;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -538,8 +538,10 @@ class Validation
|
||||
|
||||
if (isset($params['step'])) {
|
||||
$step = (float)$params['step'];
|
||||
// Count of how many steps we are above/below the minimum value.
|
||||
$pos = ($value - $min) / $step;
|
||||
|
||||
return fmod($value - $min, $step) === 0.0;
|
||||
return is_int(static::filterNumber($pos, $params, $field));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -606,7 +608,7 @@ class Validation
|
||||
*/
|
||||
public static function typeColor($value, array $params, array $field)
|
||||
{
|
||||
return preg_match('/^\#[0-9a-fA-F]{3}[0-9a-fA-F]{3}?$/u', $value);
|
||||
return (bool)preg_match('/^\#[0-9a-fA-F]{3}[0-9a-fA-F]{3}?$/u', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,14 +781,22 @@ class Validation
|
||||
}
|
||||
|
||||
// If creating new values is allowed, no further checks are needed.
|
||||
if (!empty($field['selectize']['create'])) {
|
||||
$validateOptions = $field['validate']['options'] ?? null;
|
||||
if (!empty($field['selectize']['create']) || $validateOptions === 'ignore') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$options = $field['options'] ?? [];
|
||||
$use = $field['use'] ?? 'values';
|
||||
|
||||
if (empty($field['selectize']) || empty($field['multiple'])) {
|
||||
if ($validateOptions) {
|
||||
// Use custom options structure.
|
||||
foreach ($options as &$option) {
|
||||
$option = $option[$validateOptions] ?? null;
|
||||
}
|
||||
unset($option);
|
||||
$options = array_values($options);
|
||||
} elseif (empty($field['selectize']) || empty($field['multiple'])) {
|
||||
$options = array_keys($options);
|
||||
}
|
||||
if ($use === 'keys') {
|
||||
@@ -806,7 +816,7 @@ class Validation
|
||||
{
|
||||
$value = static::filterArray($value, $params, $field);
|
||||
|
||||
return Utils::arrayUnflattenDotNotation($value);
|
||||
return is_array($value) ? Utils::arrayUnflattenDotNotation($value) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1187,7 +1197,7 @@ class Validation
|
||||
*/
|
||||
public static function filterItem_List($value, $params)
|
||||
{
|
||||
return array_values(array_filter($value, function ($v) {
|
||||
return array_values(array_filter($value, static function ($v) {
|
||||
return !empty($v);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -3,23 +3,25 @@
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Data;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use JsonSerializable;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class ValidationException
|
||||
* @package Grav\Common\Data
|
||||
*/
|
||||
class ValidationException extends RuntimeException
|
||||
class ValidationException extends RuntimeException implements JsonSerializable
|
||||
{
|
||||
/** @var array */
|
||||
protected $messages = [];
|
||||
protected $escape = true;
|
||||
|
||||
/**
|
||||
* @param array $messages
|
||||
@@ -32,21 +34,34 @@ class ValidationException extends RuntimeException
|
||||
$language = Grav::instance()['language'];
|
||||
$this->message = $language->translate('GRAV.FORM.VALIDATION_FAIL', null, true) . ' ' . $this->message;
|
||||
|
||||
foreach ($messages as $variable => &$list) {
|
||||
foreach ($messages as $list) {
|
||||
$list = array_unique($list);
|
||||
foreach ($list as $message) {
|
||||
$this->message .= "<br/>$message";
|
||||
$this->message .= '<br/>' . htmlspecialchars($message, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSimpleMessage(bool $escape = true): void
|
||||
{
|
||||
$first = reset($this->messages);
|
||||
$message = reset($first);
|
||||
|
||||
$this->message = $escape ? htmlspecialchars($message, ENT_QUOTES | ENT_HTML5, 'UTF-8') : $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMessages()
|
||||
public function getMessages(): array
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return ['validation' => $this->messages];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -332,7 +332,7 @@ class Debugger
|
||||
return new Response(404, $headers, json_encode($response));
|
||||
}
|
||||
|
||||
$data = is_array($data) ? array_map(function ($item) {
|
||||
$data = is_array($data) ? array_map(static function ($item) {
|
||||
return $item->toArray();
|
||||
}, $data) : $data->toArray();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -197,7 +197,7 @@ abstract class Folder
|
||||
* Shift first directory out of the path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public static function shift(&$path)
|
||||
{
|
||||
@@ -371,7 +371,7 @@ abstract class Folder
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($target, $source) === 0) {
|
||||
if (strpos($target, $source . '/') === 0) {
|
||||
throw new RuntimeException('Cannot move folder to itself');
|
||||
}
|
||||
|
||||
@@ -417,7 +417,8 @@ abstract class Folder
|
||||
|
||||
if (!$success) {
|
||||
$error = error_get_last();
|
||||
throw new RuntimeException($error['message']);
|
||||
|
||||
throw new RuntimeException($error['message'] ?? 'Unknown error');
|
||||
}
|
||||
|
||||
// Make sure that the change will be detected when caching.
|
||||
@@ -512,7 +513,7 @@ abstract class Folder
|
||||
}
|
||||
$directories = glob($directory . '/*', GLOB_ONLYDIR);
|
||||
|
||||
return count($directories);
|
||||
return $directories ? count($directories) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -529,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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -57,7 +57,9 @@ class ZipArchiver extends Archiver
|
||||
throw new InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');
|
||||
}
|
||||
|
||||
if (!file_exists($source)) {
|
||||
// Get real path for our folder
|
||||
$rootPath = realpath($source);
|
||||
if (!$rootPath) {
|
||||
throw new InvalidArgumentException('ZipArchiver: ' . $source . ' cannot be found...');
|
||||
}
|
||||
|
||||
@@ -66,9 +68,6 @@ class ZipArchiver extends Archiver
|
||||
throw new InvalidArgumentException('ZipArchiver:' . $this->archive_file . ' cannot be created...');
|
||||
}
|
||||
|
||||
// Get real path for our folder
|
||||
$rootPath = realpath($source);
|
||||
|
||||
$files = $this->getArchiveFiles($rootPath);
|
||||
|
||||
$status && $status([
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -43,7 +43,7 @@ abstract class FlexObject extends \Grav\Framework\Flex\FlexObject implements Med
|
||||
|
||||
// Handle media fields.
|
||||
$settings = $this->getFieldSettings($name);
|
||||
if ($settings['media_field'] ?? false === true) {
|
||||
if (($settings['media_field'] ?? false) === true) {
|
||||
return $this->parseFileProperty($value, $settings);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,6 @@ use Grav\Common\Page\Header;
|
||||
use Grav\Common\Page\Interfaces\PageCollectionInterface;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
|
||||
use Grav\Framework\Flex\Pages\FlexPageCollection;
|
||||
use Collator;
|
||||
use InvalidArgumentException;
|
||||
@@ -35,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
|
||||
@@ -47,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
|
||||
@@ -109,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();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,11 +150,11 @@ 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)
|
||||
{
|
||||
if (!$page instanceof FlexObjectInterface) {
|
||||
if (!$page instanceof PageObject) {
|
||||
throw new InvalidArgumentException('$page is not a flex page.');
|
||||
}
|
||||
|
||||
@@ -175,6 +170,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
*
|
||||
* @param PageCollectionInterface $collection
|
||||
* @return static
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function merge(PageCollectionInterface $collection)
|
||||
{
|
||||
@@ -186,6 +182,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
*
|
||||
* @param PageCollectionInterface $collection
|
||||
* @return static
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function intersect(PageCollectionInterface $collection)
|
||||
{
|
||||
@@ -204,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()
|
||||
{
|
||||
@@ -219,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)
|
||||
{
|
||||
@@ -231,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)
|
||||
{
|
||||
@@ -242,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)
|
||||
{
|
||||
@@ -253,6 +252,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
*
|
||||
* @param int $size
|
||||
* @return static[]
|
||||
* @phpstan-return static<T>[]
|
||||
*/
|
||||
public function batch($size): array
|
||||
{
|
||||
@@ -274,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)
|
||||
{
|
||||
@@ -400,8 +401,8 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
$i = count($manual);
|
||||
$new_list = [];
|
||||
foreach ($list as $key => $dummy) {
|
||||
$child = $this[$key];
|
||||
$order = array_search($child->slug, $manual, true);
|
||||
$child = $this[$key] ?? null;
|
||||
$order = $child ? array_search($child->slug, $manual, true) : false;
|
||||
if ($order === false) {
|
||||
$order = $i++;
|
||||
}
|
||||
@@ -442,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)
|
||||
@@ -469,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()
|
||||
{
|
||||
@@ -486,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()
|
||||
{
|
||||
@@ -503,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()
|
||||
{
|
||||
@@ -524,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()
|
||||
{
|
||||
@@ -545,6 +551,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
* Alias of modules()
|
||||
*
|
||||
* @return static
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function modular()
|
||||
{
|
||||
@@ -555,6 +562,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
* Alias of pages()
|
||||
*
|
||||
* @return static
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function nonModular()
|
||||
{
|
||||
@@ -565,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()
|
||||
{
|
||||
@@ -582,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()
|
||||
{
|
||||
@@ -599,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()
|
||||
{
|
||||
@@ -616,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()
|
||||
{
|
||||
@@ -634,6 +646,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
*
|
||||
* @param string $type
|
||||
* @return static The collection
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function ofType($type)
|
||||
{
|
||||
@@ -652,6 +665,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
*
|
||||
* @param string[] $types
|
||||
* @return static The collection
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function ofOneOfTheseTypes($types)
|
||||
{
|
||||
@@ -670,6 +684,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
*
|
||||
* @param array $accessLevels
|
||||
* @return static The collection
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function ofOneOfTheseAccessLevels($accessLevels)
|
||||
{
|
||||
@@ -711,6 +726,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
/**
|
||||
* @param bool $bool
|
||||
* @return static
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function withOrdered(bool $bool = true)
|
||||
{
|
||||
@@ -722,6 +738,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
/**
|
||||
* @param bool $bool
|
||||
* @return static
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function withModules(bool $bool = true)
|
||||
{
|
||||
@@ -733,6 +750,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
|
||||
/**
|
||||
* @param bool $bool
|
||||
* @return static
|
||||
* @phpstan-return static<T>
|
||||
*/
|
||||
public function withPages(bool $bool = true)
|
||||
{
|
||||
@@ -746,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)
|
||||
{
|
||||
@@ -779,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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -109,15 +113,21 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
}
|
||||
|
||||
$element = parent::get($key);
|
||||
if (null === $element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($params)) {
|
||||
$element = $element->getTranslation(ltrim($params, '.'));
|
||||
}
|
||||
|
||||
\assert(null === $element || $element instanceof PageObject);
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PageObject
|
||||
* @return PageInterface
|
||||
*/
|
||||
public function getRoot()
|
||||
{
|
||||
@@ -168,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)
|
||||
{
|
||||
@@ -272,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)
|
||||
{
|
||||
@@ -328,10 +340,14 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
/**
|
||||
* @param array $filters
|
||||
* @return static
|
||||
* @phpstan-return static<T,C>
|
||||
*/
|
||||
protected function filterByParent(array $filters)
|
||||
{
|
||||
return parent::filterBy($filters);
|
||||
/** @var static $index */
|
||||
$index = parent::filterBy($filters);
|
||||
|
||||
return $index;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,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)
|
||||
{
|
||||
@@ -547,6 +564,9 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
$filters = array_filter($filters, static function($val) { return $val !== null && $val !== ''; });
|
||||
|
||||
if ($page) {
|
||||
$status = 'success';
|
||||
$msg = 'PLUGIN_ADMIN.PAGE_ROUTE_FOUND';
|
||||
|
||||
if ($page->root() && (!$filter_type || in_array('root', $filter_type, true))) {
|
||||
if ($field) {
|
||||
$response[] = [
|
||||
@@ -586,9 +606,6 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
}
|
||||
}
|
||||
|
||||
$status = 'success';
|
||||
$msg = 'PLUGIN_ADMIN.PAGE_ROUTE_FOUND';
|
||||
|
||||
/** @var PageIndex $children */
|
||||
$children = $page->children()->getIndex();
|
||||
$selectedChildren = $children->filterBy($filters, true);
|
||||
@@ -673,13 +690,14 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
$child_count = $tmp->count();
|
||||
$count = $filters ? $tmp->filterBy($filters, true)->count() : null;
|
||||
$route = $child->getRoute();
|
||||
$route = $route ? ($route->toString(false) ?: '/') : '';
|
||||
$payload = [
|
||||
'item-key' => basename($child->rawRoute() ?? $child->getKey()),
|
||||
'item-key' => htmlspecialchars(basename($child->rawRoute() ?? $child->getKey())),
|
||||
'icon' => $icon,
|
||||
'title' => htmlspecialchars($child->menu()),
|
||||
'route' => [
|
||||
'display' => ($route ? ($route->toString(false) ?: '/') : null) ?? '',
|
||||
'raw' => $child->rawRoute(),
|
||||
'display' => htmlspecialchars($route) ?: null,
|
||||
'raw' => htmlspecialchars($child->rawRoute()),
|
||||
],
|
||||
'modified' => $this->jsDate($child->modified()),
|
||||
'child_count' => $child_count ?: null,
|
||||
@@ -713,7 +731,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
$response = Utils::arrayFlatten($sorted);
|
||||
}
|
||||
|
||||
return [$status, $msg ?? 'PLUGIN_ADMIN.NO_ROUTE_PROVIDED', $response, $path];
|
||||
return [$status, $msg, $response, $path];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,6 +797,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param PageInterface $page
|
||||
* @return PageCollection
|
||||
* @phpstan-return C
|
||||
*/
|
||||
public function addPage(PageInterface $page)
|
||||
{
|
||||
@@ -790,6 +809,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
* Create a copy of this collection
|
||||
*
|
||||
* @return static
|
||||
* @phpstan-return static<T,C>
|
||||
*/
|
||||
public function copy()
|
||||
{
|
||||
@@ -802,6 +822,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param PageCollectionInterface $collection
|
||||
* @return PageCollection
|
||||
* @phpstan-return C
|
||||
*/
|
||||
public function merge(PageCollectionInterface $collection)
|
||||
{
|
||||
@@ -814,6 +835,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param PageCollectionInterface $collection
|
||||
* @return PageCollection
|
||||
* @phpstan-return C
|
||||
*/
|
||||
public function intersect(PageCollectionInterface $collection)
|
||||
{
|
||||
@@ -825,6 +847,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param int $size
|
||||
* @return PageCollection[]
|
||||
* @phpstan-return C[]
|
||||
*/
|
||||
public function batch($size)
|
||||
{
|
||||
@@ -834,12 +857,12 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
/**
|
||||
* Remove item from the list.
|
||||
*
|
||||
* @param PageInterface|string|null $key
|
||||
*
|
||||
* @return $this
|
||||
* @param string $key
|
||||
* @return PageObject|null
|
||||
* @phpstan-return T|null
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function remove($key = null)
|
||||
public function remove($key)
|
||||
{
|
||||
return $this->getCollection()->remove($key);
|
||||
}
|
||||
@@ -852,6 +875,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)
|
||||
{
|
||||
@@ -895,6 +919,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param string $path
|
||||
* @return PageObject|null The previous item.
|
||||
* @phpstan-return T|null
|
||||
*/
|
||||
public function prevSibling($path)
|
||||
{
|
||||
@@ -909,6 +934,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param string $path
|
||||
* @return PageObject|null The next item.
|
||||
* @phpstan-return T|null
|
||||
*/
|
||||
public function nextSibling($path)
|
||||
{
|
||||
@@ -924,6 +950,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)
|
||||
{
|
||||
@@ -957,6 +984,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)
|
||||
@@ -981,6 +1009,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()
|
||||
{
|
||||
@@ -993,6 +1022,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()
|
||||
{
|
||||
@@ -1005,6 +1035,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()
|
||||
{
|
||||
@@ -1017,6 +1048,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()
|
||||
{
|
||||
@@ -1029,6 +1061,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()
|
||||
{
|
||||
@@ -1039,6 +1072,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()
|
||||
{
|
||||
@@ -1049,6 +1083,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()
|
||||
{
|
||||
@@ -1061,6 +1096,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()
|
||||
{
|
||||
@@ -1073,6 +1109,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()
|
||||
{
|
||||
@@ -1085,6 +1122,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()
|
||||
{
|
||||
@@ -1098,6 +1136,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param string $type
|
||||
* @return static The collection
|
||||
* @phpstan-return static<T,C>
|
||||
*/
|
||||
public function ofType($type)
|
||||
{
|
||||
@@ -1111,6 +1150,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param string[] $types
|
||||
* @return static The collection
|
||||
* @phpstan-return static<T,C>
|
||||
*/
|
||||
public function ofOneOfTheseTypes($types)
|
||||
{
|
||||
@@ -1124,6 +1164,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
|
||||
*
|
||||
* @param array $accessLevels
|
||||
* @return static The collection
|
||||
* @phpstan-return static<T,C>
|
||||
*/
|
||||
public function ofOneOfTheseAccessLevels($accessLevels)
|
||||
{
|
||||
|
||||
@@ -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,23 +93,18 @@ class PageObject extends FlexPageObject
|
||||
}
|
||||
}
|
||||
|
||||
public function translated(): bool
|
||||
{
|
||||
return $this->translatedLanguages(true) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $query
|
||||
* @return Route|null
|
||||
*/
|
||||
public function getRoute($query = []): ?Route
|
||||
{
|
||||
$route = $this->route();
|
||||
if (null === $route) {
|
||||
$path = $this->route();
|
||||
if (null === $path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$route = RouteFactory::createFromString($route);
|
||||
$route = RouteFactory::createFromString($path);
|
||||
if ($lang = $route->getLanguage()) {
|
||||
$grav = Grav::instance();
|
||||
if (!$grav['config']->get('system.languages.include_default_lang')) {
|
||||
@@ -282,7 +277,7 @@ class PageObject extends FlexPageObject
|
||||
|
||||
/**
|
||||
* @param array|bool $reorder
|
||||
* @return FlexObject|FlexObjectInterface
|
||||
* @return static
|
||||
*/
|
||||
public function save($reorder = true)
|
||||
{
|
||||
@@ -311,13 +306,13 @@ class PageObject extends FlexPageObject
|
||||
}
|
||||
|
||||
// Reset original after save events have all been called.
|
||||
$this->_original = null;
|
||||
$this->_originalObject = null;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
@@ -441,7 +437,8 @@ class PageObject extends FlexPageObject
|
||||
|
||||
// Add missing siblings into the end of the list, keeping the previous ordering between them.
|
||||
foreach ($siblings as $sibling) {
|
||||
$basename = preg_replace('|^\d+\.|', '', $sibling->getProperty('folder'));
|
||||
$folder = (string)$sibling->getProperty('folder');
|
||||
$basename = preg_replace('|^\d+\.|', '', $folder);
|
||||
if (!in_array($basename, $ordering, true)) {
|
||||
$ordering[] = $basename;
|
||||
}
|
||||
@@ -451,7 +448,8 @@ class PageObject extends FlexPageObject
|
||||
$ordering = array_flip(array_values($ordering));
|
||||
$count = count($ordering);
|
||||
foreach ($siblings as $sibling) {
|
||||
$basename = preg_replace('|^\d+\.|', '', $sibling->getProperty('folder'));
|
||||
$folder = (string)$sibling->getProperty('folder');
|
||||
$basename = preg_replace('|^\d+\.|', '', $folder);
|
||||
$newOrder = $ordering[$basename] ?? null;
|
||||
$newOrder = null !== $newOrder ? $newOrder + 1 : (int)$sibling->order() + $count;
|
||||
$sibling->order($newOrder);
|
||||
@@ -464,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) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user