Compare commits

...

142 Commits

Author SHA1 Message Date
Andy Miller
6751d28839 prepare for beta release
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 12:09:49 -06:00
Andy Miller
8118d6b980 source fix in restore bin + missing dot files after upgrade
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 12:01:48 -06:00
Andy Miller
ba2536136b prepare for release
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 10:42:33 -06:00
Andy Miller
ee49305053 timelimit on recovery status
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 09:08:32 -06:00
Andy Miller
b4d664fcb0 built in composer update
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 08:23:22 -06:00
Andy Miller
7fcb1d1cb7 renamed to bin/restore
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 08:09:02 -06:00
Andy Miller
dbeaa8ad46 remove accidental recovery flag + add functionality in grav-restore
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 08:07:56 -06:00
Andy Miller
a3da588829 should fix tests this time
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 07:54:44 -06:00
Andy Miller
a3387c106b more test fixes
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 07:50:24 -06:00
Andy Miller
d9d241d806 fix for RecoveryManagerTest
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-16 07:47:50 -06:00
Andy Miller
bb5cdad333 require grav 1.7.50
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-15 20:55:50 -06:00
Andy Miller
44f90cbce0 Merge branch 'develop' into 1.8
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-15 20:22:14 -06:00
Andy Miller
cc97e2ff45 prepare for beta release
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-14 14:30:24 -06:00
Andy Miller
d92c430b8a updated changelog
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-14 14:30:01 -06:00
Andy Miller
184cdea75d Merge branch 'develop' into 1.8
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-13 14:39:29 -06:00
Andy Miller
7b9567ec28 update vendor libs
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-13 14:35:58 -06:00
Andy Miller
9e84d5d004 more fixes for Symfony7 PHP 8+
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-07 13:30:40 -06:00
Andy Miller
fd0d3dc463 PHP 8.4 fixes
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-07 13:18:04 -06:00
Andy Miller
eb985e875d vendor updates and some fixes
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-03 18:16:40 -06:00
Andy Miller
ba3493adce vendor update
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-10-03 16:13:05 -06:00
Andy Miller
d785042a0d set YamlUpdater get/set to public
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 15:20:53 -06:00
Andy Miller
49096b61f3 fixed sessions to use 1.7 style..
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 15:12:38 -06:00
Andy Miller
70e986074c prepare beta release
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 14:06:13 -06:00
Andy Miller
4af22edd36 add missing YamlLinter::exists() method
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 14:05:32 -06:00
Andy Miller
5bc7d6943f added cache check interval
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 11:24:50 -06:00
Andy Miller
8eb4085bcd opcache improvements for first hit
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 11:02:12 -06:00
Andy Miller
b47758e3c7 tweaked changelog
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 10:26:04 -06:00
Andy Miller
972ec26035 prepare for beta release
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-22 10:20:44 -06:00
Andy Miller
9116079e97 twig3 compatiblity layer
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-21 11:40:23 -06:00
Andy Miller
51ddb3984c rector casting clarity
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-20 22:49:21 -06:00
Andy Miller
22de638e52 composer updates + php fixes
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-20 22:33:56 -06:00
Andy Miller
365ab93e7e PHP 8.2+ fixes
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-20 22:12:55 -06:00
Andy Miller
c172964025 fix for cache blowing up
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-20 19:16:12 -06:00
Andy Miller
cb0bbcdb8b Deferred support in Twig 3
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-20 18:38:27 -06:00
Andy Miller
35f5d2f329 Merge branch 'develop' into 1.8
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-09-20 17:57:14 -06:00
Andy Miller
639be5ac0d pages optimizations
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-06-25 16:17:24 -06:00
Andy Miller
d3e32799ab use forked copy of parsedown 1.7.x for PHP 8.4 compatibility
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-04-02 05:34:07 -06:00
Andy Miller
3bebfc6dac fixed for tests
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-04-01 17:03:42 -06:00
Andy Miller
9d80a4d992 upgraded to latest phpdebugbar + fixed browser caching
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-04-01 16:55:29 -06:00
Andy Miller
fc7f72f89d Merge branch 'develop' into 1.8
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-03-31 19:32:54 -06:00
Andy Miller
53391466b0 prepare for beta release
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-01-27 14:08:11 -07:00
Andy Miller
2fadc14c01 Swtiched to forked getgrav/Twig 2.x with PHP 8.4 support
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-01-27 14:03:31 -07:00
Andy Miller
de2af9e470 Fix empty string causing parse error: fixes #3894
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-01-24 15:22:35 -07:00
Andy Miller
edfb1a0868 Merge branch 'develop' into 1.8 2025-01-21 14:41:54 +00:00
Andy Miller
9893a605a6 composer update
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-01-20 11:41:51 +00:00
Andy Miller
83d291c24b 8.2 stuff
Signed-off-by: Andy Miller <rhuk@mac.com>
2025-01-14 15:55:10 +00:00
Andy Miller
ca1b05ba57 Merge branch 'develop' into 1.8
Signed-off-by: Andy Miller <rhuk@mac.com>

# Conflicts:
#	system/src/Grav/Framework/Collection/AbstractLazyCollection.php
2025-01-06 14:17:08 +00:00
Andy Miller
350e4c04cd test action on 1.8
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-12-10 14:35:05 -07:00
Andy Miller
d8123a3662 switch to cache@v4 + limit PHP versions
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-12-10 14:33:29 -07:00
Andy Miller
1e430f635e some more composer updates
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-12-09 17:32:00 -07:00
Andy Miller
17548131d3 rector fixes for PHP 8.2+
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-12-09 17:23:56 -07:00
Andy Miller
4a27bd780c vendor updates
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-12-09 17:14:29 -07:00
Andy Miller
5666d0f211 changelog updated
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-12-03 15:33:10 -07:00
Andy Miller
d17ab9e06c fixed issue with Abstract Lazy Collection
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-12-03 15:33:03 -07:00
Andy Miller
a15fe29f43 update version #
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-11-21 12:46:31 -07:00
Andy Miller
3126fa8388 updated changelog
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-11-21 12:43:32 -07:00
Andy Miller
b0c339c9eb moved to stable version of clockwork (v5.3.1)
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-11-21 12:41:56 -07:00
Andy Miller
f812ee8555 more compoer updates
Signed-off-by: Andy Miller <rhuk@mac.com>
2024-11-18 16:13:08 -07:00
Andy Miller
8c6388bb74 package update 2024-10-30 19:26:04 -06:00
Andy Miller
d7aaef986e updated version 2024-10-28 11:43:14 +00:00
Andy Miller
ab9363c478 Merge branch 'develop' into 1.8 2024-10-28 11:32:43 +00:00
Andy Miller
7f2da96c0b update vendor libs 2024-10-28 11:31:20 +00:00
Andy Miller
b16db4b9c0 typo 2024-10-27 12:21:00 +00:00
Andy Miller
42c0682dd8 Merge branch '1.8' of github.com:getgrav/grav into 1.8 2024-10-26 15:25:11 +01:00
Andy Miller
1969ec1876 monolog2 support 2024-10-26 15:25:00 +01:00
Jeremy Gonyea
c30661736c Fix for #3164. Adds aliases as possible commands during lookup (#3863) 2024-10-26 15:18:43 +01:00
Andy Miller
3d2dfa2faf Updated changelog 2024-10-25 20:18:33 +01:00
Andy Miller
f06bbfc563 Missing RocketTheme\Toolbox\Event\EventSubscriberInterface 2024-10-25 20:17:41 +01:00
Andy Miller
37e5526a4f updated changelog 2024-10-25 18:21:23 +01:00
Andy Miller
85c4b8279e fixes for PHP 8.4 - Implicitly nullable parameter declarations deprecated 2024-10-25 18:20:41 +01:00
Andy Miller
46736ce256 upgrade to doctrine/collectons 2.2 2024-10-25 17:53:51 +01:00
Andy Miller
800b2e1ecb updated changelog 2024-10-25 17:39:34 +01:00
Andy Miller
4f065b95a7 updated composer to latest version 2024-10-25 17:33:47 +01:00
Andy Miller
b59a3adc80 avif support via getgrav/image updates 2024-10-25 15:29:16 +01:00
Andy Miller
4ec9a3a489 Merge branch 'develop' into 1.8 2024-10-25 10:49:38 +01:00
Andy Miller
173d08243a use dev-master of Clockwork to support Monolog2/3 2024-10-24 11:58:04 +01:00
Andy Miller
62c60b8ba1 Fixed a couple of monolog deprecations 2024-10-23 17:17:51 +01:00
Andy Miller
59031a8711 use BUILD_SCRIPT_URL_18 in build 2024-10-23 17:07:10 +01:00
Andy Miller
5cd859865f use build-grav-18.sh build script 2024-10-23 16:44:49 +01:00
Andy Miller
16eafbbb04 udpate build.yaml 2024-10-23 14:37:45 +01:00
Andy Miller
3947bb03aa set version properly 2024-10-23 13:14:26 +01:00
Andy Miller
ee55d097f2 set testing true 2024-10-23 13:08:34 +01:00
Andy Miller
ae567469b7 prepare for beta release 2024-10-23 13:08:06 +01:00
Andy Miller
f6decaab15 Merge branch 'develop' into 1.8 2024-10-23 13:04:01 +01:00
Andy Miller
10d36a10bc updated composer.lock 2024-10-23 12:16:29 +01:00
Andy Miller
574a430a10 more composer updates 2024-10-23 12:14:45 +01:00
Andy Miller
302f02ca5d revert schema 2024-10-22 18:01:41 +01:00
Andy Miller
c334479e4c Merge branch 'develop' into feature/v1.8 2024-10-22 15:47:58 +01:00
Andy Miller
b96483c49a Fix tests for latest Codeception version 2024-10-22 13:24:35 +01:00
Andy Miller
cccce836f6 Merge branch 'develop' into feature/v1.8 2024-10-22 12:09:26 +01:00
Andy Miller
bdcb77d429 Merge branch 'develop' into feature/v1.8 2024-10-21 14:20:23 +01:00
Andy Miller
e15cc86716 toAscii() should be static 2024-10-21 14:19:45 +01:00
Andy Miller
dcfbd73d43 twig compatibility stuff 2024-10-14 20:53:07 +01:00
Andy Miller
1967910789 upgrade to latest symfony 6.4 + PHP 8.2 2024-10-14 19:27:43 +01:00
Andy Miller
4f1f9a7755 Merge branch 'develop' into feature/v1.8
# Conflicts:
#	CHANGELOG.md
#	composer.lock
2024-10-14 19:25:17 +01:00
Andy Miller
e4f483998d composer lock file 2023-05-12 13:50:50 -06:00
Andy Miller
7a393101ee Merge branch 'develop' into feature/v1.8
# Conflicts:
#	CHANGELOG.md
#	composer.json
#	composer.lock
#	system/blueprints/config/system.yaml
#	system/src/Grav/Common/Twig/WriteCacheFileTrait.php
2023-05-12 13:44:07 -06:00
Matias Griese
10b15bedf2 Composer update 2022-08-18 13:27:58 +03:00
Matias Griese
8c14a9907e Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.lock
2022-08-18 13:27:06 +03:00
Matias Griese
f490d9a7e1 Fix phpstan error 2022-06-29 13:16:56 +03:00
Matias Griese
81ca0c2e25 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	CHANGELOG.md
	composer.json
	composer.lock
2022-06-29 13:14:06 +03:00
Matias Griese
fbfac9f8f4 Composer update 2022-06-29 13:12:11 +03:00
Matias Griese
d6e72708bf Composer update 2022-06-15 14:41:05 +03:00
Matias Griese
2aff274c31 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.lock
	system/src/Grav/Common/GPM/Remote/AbstractPackageCollection.php
2022-06-15 14:39:38 +03:00
Matias Griese
74c1dfa433 Composer update 2022-05-20 16:48:41 +03:00
Matias Griese
f51a9d9d87 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	CHANGELOG.md
	composer.lock
2022-05-20 16:45:54 +03:00
Matias Griese
e5498f58e6 Composer update 2022-04-19 11:05:19 +03:00
Matias Griese
8f58a4494c Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.lock
2022-04-19 11:04:33 +03:00
Matias Griese
5bfd43256d Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8 2022-03-31 11:31:04 +03:00
Matias Griese
69bc3f7f25 Composer update 2022-03-31 11:27:39 +03:00
Matias Griese
782ceada80 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	CHANGELOG.md
	composer.lock
2022-03-31 11:26:37 +03:00
Matias Griese
36392acbea Composer update 2022-03-23 13:00:19 +02:00
Matias Griese
4b564df38f Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	CHANGELOG.md
2022-03-23 12:58:48 +02:00
Matias Griese
9d179e5b2a Composer update 2022-03-09 12:33:20 +02:00
Matias Griese
6032bd07dc Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.json
	composer.lock
2022-03-09 12:32:31 +02:00
Matias Griese
9a87a509b0 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8 2022-02-22 11:35:29 +02:00
Matias Griese
46f2a81b21 Phpstan fixes 2022-02-19 15:20:06 +02:00
Matias Griese
f5e21645f6 Support phpstan level 6 in Framework classes 2022-02-19 14:17:02 +02:00
Matias Griese
12c8cf9c40 Phpstan fixes 2022-02-19 13:47:29 +02:00
Matias Griese
93bb929b38 Phpstan updates 2022-02-19 13:17:34 +02:00
Matias Griese
85eaf308d5 Fixed FlexDirectory::getCache() after converting to Symfony Cache 2022-02-19 13:17:19 +02:00
Matias Griese
d9ede28b99 Composer update 2022-02-19 12:18:40 +02:00
Matias Griese
2e65b0eea4 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.lock
2022-02-19 12:18:00 +02:00
Matias Griese
7660a80ef7 Use older monolog due to clockwork incompatibility 2022-02-16 09:51:09 +02:00
Matias Griese
6d0a436834 Changelog update (pt 2) 2022-02-12 16:58:07 +02:00
Matias Griese
176fd8f1d8 Changelog update 2022-02-12 16:52:25 +02:00
Matias Griese
2f85fe9c99 Move unmaintained/unused vendor dependencies to the end of the list 2022-02-12 16:49:09 +02:00
Matias Griese
d93d297dc4 Updated to **Monolog 2.3** 2022-02-12 16:36:58 +02:00
Matias Griese
fcd9093f84 Use **Symfony Cache** instead of unmaintaided **Doctrine Cache** (with backward compatibility layer) 2022-02-12 15:33:38 +02:00
Matias Griese
58b54a70bd Removed system.umask_fix setting for security reasons 2022-02-12 13:49:30 +02:00
Matias Griese
9daa0a9041 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.lock
2022-02-12 13:08:23 +02:00
Matias Griese
965e03daf2 Update dependencies so that everything works again 2022-02-07 14:14:11 +02:00
Matias Griese
b6c3db082a Update composer dependencies 2022-02-07 14:03:05 +02:00
Matias Griese
26b68953c4 Composer update 2022-02-07 13:48:47 +02:00
Matias Griese
fba015c5d9 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.json
	composer.lock
2022-02-07 13:47:41 +02:00
Matias Griese
7223c177c4 Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.json
	composer.lock
2021-12-08 10:08:34 +02:00
Matias Griese
a68bdd2b75 Fixed Toolbox Event 2021-11-25 14:17:13 +02:00
Matias Griese
38e4624506 Composer update 2021-11-25 11:51:40 +02:00
Matias Griese
ad9287ee0f Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8
 Conflicts:
	composer.json
	composer.lock
2021-11-25 11:46:21 +02:00
Matias Griese
777ac119de Update all libraries (WIP) 2021-10-20 20:33:05 +03:00
Matias Griese
076c64841e Merge branch 'develop' of github.com:getgrav/grav into feature/v1.8 2021-10-20 20:28:50 +03:00
Matias Griese
62cb40fef5 Composer update 2021-10-20 20:28:24 +03:00
326 changed files with 7805 additions and 5668 deletions

View File

@@ -11,7 +11,7 @@ jobs:
permissions:
contents: write # for release creation (svenstaro/upload-release-action)
if: "!github.event.release.prerelease"
#if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
@@ -23,7 +23,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.3
php-version: 8.2
extensions: opcache, gd
tools: composer:v2
coverage: none
@@ -38,10 +38,10 @@ jobs:
- name: Retrieval of Builder Scripts
run: |
# Real Grav URL
curl --silent -H "Authorization: token ${{ secrets.GLOBAL_TOKEN }}" -H "Accept: application/vnd.github.v3.raw" ${{ secrets.BUILD_SCRIPT_URL }} --output build-grav.sh
curl --silent -H "Authorization: token ${{ secrets.GLOBAL_TOKEN }}" -H "Accept: application/vnd.github.v3.raw" ${{ secrets.BUILD_SCRIPT_URL_18 }} --output build-grav.sh
# Development Local URL
# curl ${{ secrets.BUILD_SCRIPT_URL }} --output build-grav.sh
# curl ${{ secrets.BUILD_SCRIPT_URL_18 }} --output build-grav.sh
- name: Grav Builder
run: |

View File

@@ -2,9 +2,9 @@ name: PHP Tests
on:
push:
branches: [ develop ]
branches: [ develop, 1.8 ]
pull_request:
branches: [ develop ]
branches: [ develop, 1.8 ]
permissions:
contents: read # to fetch code (actions/checkout)
@@ -13,7 +13,7 @@ jobs:
unit-tests:
strategy:
matrix:
php: ['8.3', '8.2', '8.1', '8.0', '7.4', '7.3']
php: [8.4, 8.3, 8.2]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}

View File

@@ -10,7 +10,7 @@ on:
admin:
description: 'Create also a package with Admin'
required: true
default: true
default: 'true'
permissions:
contents: read # to fetch code (actions/checkout)

View File

@@ -1,3 +1,99 @@
# v1.8.0-beta.10
## 10/16/2025
1. [](#bugfix)
* Fixed an issue with **safe upgrade** losing dot files
# v1.8.0-beta.9
## 10/16/2025
1. [](#new)
* Added new **core safe upgrade** installer with staging, validation, and rollback support
# v1.8.0-beta.8
## 10/14/2025
1. [](#improved)
* Upgraded to latest Symfony 7 (might cause issues with some plugins)
* `wordCount` twig filter (merged from 1.7 branch)
* More PHP 8.4 compatibility fixes
* Update all vendor libraries to latest
1. [](#bugfix)
* Fixed some CLI level bugs
* Fixed a Twig Sandbox bybpass issue
# v1.8.0-beta.7
## 09/22/2025
1. [](#bugfix)
* Changed `private` to `public` for YamlUpdater::get() and YamUpdater::set() methods
* Fixed a session cookie issue that manifested when logging-in to client side
# v1.8.0-beta.6
## 09/22/2025
1. [](#bugfix)
* Fixed a missing YamlUpdater::exists() method
# v1.8.0-beta.5
## 09/22/2025
1. [](#new)
* Deferred Extension support in Forked version of Twig 3
* Added separate `strict_mode.twig2_compat` and `strict_mode.twig3_compat` toggles to manage auto-escape behaviour and automatic Twig 3 compatible template rewrites
1. [](#bugfix)
* Fix for cache blowing up when upgrading from 1.7 to 1.8 via CLI
# v1.8.0-beta.4
## 01/27/2025
1. [](#bugfix)
* Fixed a PHP compatibility issue with `AbstractLazyCollection`
1. [](#improved)
* Global PHP 8.2 code optimizations
* More PHP 8.4 compatibility fixes
* Twig 2.x forked to getgrav/twig 2.x for PHP 8.4 compatibility
* Switch to cache@v4 + limit PHP version for Github actions
* Trigger testing Github action for Grav 1.8
* Merge latest Grav 1.7 fixes into Grav 1.8
# v1.8.0-beta.3
## 11/21/2024
1. [](#improved)
* Updated composer libraries to latest versions for compatibility fixes
# v1.8.0-beta.2
## 10/28/2024
1. [](#new)
* Use `dev-master` branch of Clockwork to support Monolog2 / Monolog3
* `AVIF` image support via updates to `getgrav/Image` library
* Upgraded to **Doctrine Collection 2.2**
1. [](#improved)
* Updated composer libraries
* Updated composer.php binary to `v2.8.1`
* Fixes for PHP 8.4 - Implicitly nullable parameter declarations deprecated
* Added back Missing `RocketTheme\Toolbox\Event\EventSubscriberInterface` for Gantry5
1. [](#bugfix)
* Various fixes to use `$log->debug()`, `$log->info()`, `$log->warning()` and `$log->error()` For Monolog2 support
# v1.8.0-beta.1
## 10/23/2024
1. [](#new)
* Set minimum requirements to **PHP 8.2**
* Updated to **Twig 2.14**
* Updated to **Symfony 6.4**
* Updated to **Monolog 2.3**
* Updated to **RocketTheme/Toolbox 2.0**
* Updated to **Composer/Semver 3.2**
* Use **Symfony Cache** instead of unmaintained **Doctrine Cache**
* Removed unsupported **APC**, **WinCache**, **XCache** and **Memcache**, use apcu or memcached instead
* Removed `system.umask_fix` setting for security reasons
* Support phpstan level 6 in Framework classes
# v1.7.50
## UNRELEASED
@@ -72,18 +168,18 @@
## 10/23/2024
1. [](#new)
* New `Utils::toAscii()` method
* Added support for Clockwork Debugger to allow web UI (requires new `clockwork-web` plugin)
* New `Utils::toAscii()` method
* Added support for Clockwork Debugger to allow web UI (requires new `clockwork-web` plugin)
1. [](#improved)
* Include modular sub-pages in last-modification date computation [#3562](https://github.com/getgrav/grav/pull/3562)
* Updated vendor libs to latest versions
* Updated JQuery to `3.7.1` [#3787](https://github.com/getgrav/grav/pull/3827)
* Updated vendor libraries to latest versions
* Support for Fediverse Creator meta tag [#3844](https://github.com/getgrav/grav/pull/3844)
* Include modular sub-pages in last-modification date computation [#3562](https://github.com/getgrav/grav/pull/3562)
* Updated vendor libs to latest versions
* Updated JQuery to `3.7.1` [#3787](https://github.com/getgrav/grav/pull/3827)
* Updated vendor libraries to latest versions
* Support for Fediverse Creator meta tag [#3844](https://github.com/getgrav/grav/pull/3844)
1. [](#bugfix)
* Fixes deprecated for return type in Filesystem with PHP 8.3.6 [#3831](https://github.com/getgrav/grav/issues/3831)
* Fix for `exif_imagtetype()` throwing an exception when file doesn't exist
* Fix JSON output comments check with content type [#3859](https://github.com/getgrav/grav/pull/3859)
* Fixes deprecated for return type in Filesystem with PHP 8.3.6 [#3831](https://github.com/getgrav/grav/issues/3831)
* Fix for `exif_imagtetype()` throwing an exception when file doesn't exist
* Fix JSON output comments check with content type [#3859](https://github.com/getgrav/grav/pull/3859)
# v1.7.46
## 05/15/2024

View File

@@ -20,7 +20,7 @@ The underlying architecture of Grav is designed to use well-established and _bes
# Requirements
- PHP 7.3.6 or higher. Check the [required modules list](https://learn.getgrav.org/basics/requirements#php-requirements)
- PHP 8.2 or higher. Check the [required modules list](https://learn.getgrav.org/basics/requirements#php-requirements)
- Check the [Apache](https://learn.getgrav.org/basics/requirements#apache-requirements) or [IIS](https://learn.getgrav.org/basics/requirements#iis-requirements) requirements
# Documentation
@@ -89,9 +89,10 @@ bin/gpm update
## Upgrading from older version
* [Upgrading to Grav 1.8](https://learn.getgrav.org/16/advanced/grav-development/grav-18-upgrade-guide)
* [Upgrading to Grav 1.7](https://learn.getgrav.org/16/advanced/grav-development/grav-17-upgrade-guide)
* [Upgrading to Grav 1.6](https://learn.getgrav.org/16/advanced/grav-development/grav-16-upgrade-guide)
* [Upgrading from Grav <1.6](https://learn.getgrav.org/16/advanced/grav-development/grav-15-upgrade-guide)
* [Upgrading from Grav before 1.6](https://learn.getgrav.org/16/advanced/grav-development/grav-15-upgrade-guide)
# Contributing
We appreciate any contribution to Grav, whether it is related to bugs, grammar, or simply a suggestion or improvement! Please refer to the [Contributing guide](CONTRIBUTING.md) for more guidance on this topic.

Binary file not shown.

View File

@@ -25,6 +25,7 @@ if (!file_exists($root . '/index.php')) {
exit(1);
}
use Grav\Common\Recovery\RecoveryManager;
use Grav\Common\Upgrade\SafeUpgradeService;
use Symfony\Component\Yaml\Yaml;
@@ -32,19 +33,24 @@ const RESTORE_USAGE = <<<USAGE
Grav Restore Utility
Usage:
bin/grav-restore list [--staging-root=/absolute/path]
bin/restore list [--staging-root=/absolute/path]
Lists all available snapshots (most recent first).
bin/grav-restore apply <snapshot-id> [--staging-root=/absolute/path]
bin/restore apply <snapshot-id> [--staging-root=/absolute/path]
Restores the specified snapshot created by safe-upgrade.
bin/restore recovery [status|clear]
Shows the recovery flag context or clears it.
Options:
--staging-root Overrides the staging directory (defaults to configured value).
Examples:
bin/grav-restore list
bin/grav-restore apply stage-68eff31cc4104
bin/grav-restore apply stage-68eff31cc4104 --staging-root=/var/grav-backups
bin/restore list
bin/restore apply stage-68eff31cc4104
bin/restore apply stage-68eff31cc4104 --staging-root=/var/grav-backups
bin/restore recovery status
bin/restore recovery clear
USAGE;
/**
@@ -133,7 +139,7 @@ function createUpgradeService(array $options): SafeUpgradeService
}
/**
* @return list<array{id:string,target_version:?string,created_at:int}>
* @return list<array{id:string,source_version:?string,target_version:?string,created_at:int}>
*/
function loadSnapshots(): array
{
@@ -154,6 +160,7 @@ function loadSnapshots(): array
$snapshots[] = [
'id' => $decoded['id'],
'source_version' => $decoded['source_version'] ?? null,
'target_version' => $decoded['target_version'] ?? null,
'created_at' => $decoded['created_at'] ?? 0,
];
@@ -178,8 +185,8 @@ switch ($command) {
echo "Available snapshots:\n";
foreach ($snapshots as $snapshot) {
$time = $snapshot['created_at'] ? date('c', (int)$snapshot['created_at']) : 'unknown';
$version = $snapshot['target_version'] ?? 'unknown';
echo sprintf(" - %s (Grav %s, %s)\n", $snapshot['id'], $version, $time);
$restoreVersion = $snapshot['source_version'] ?? $snapshot['target_version'] ?? 'unknown';
echo sprintf(" - %s (restore to Grav %s, %s)\n", $snapshot['id'], $restoreVersion, $time);
}
exit(0);
@@ -203,10 +210,66 @@ switch ($command) {
exit(1);
}
$version = $manifest['target_version'] ?? 'unknown';
$version = $manifest['source_version'] ?? $manifest['target_version'] ?? 'unknown';
echo "Restored snapshot {$snapshotId} (Grav {$version}).\n";
exit(0);
case 'recovery':
$action = strtolower($arguments[0] ?? 'status');
$manager = new RecoveryManager(GRAV_ROOT);
switch ($action) {
case 'clear':
if ($manager->isActive()) {
$manager->clear();
echo "Recovery flag cleared.\n";
} else {
echo "Recovery mode is not active.\n";
}
exit(0);
case 'status':
if (!$manager->isActive()) {
echo "Recovery mode is not active.\n";
exit(0);
}
$context = $manager->getContext();
if (!$context) {
echo "Recovery flag present but context could not be parsed.\n";
exit(1);
}
$created = isset($context['created_at']) ? date('c', (int)$context['created_at']) : 'unknown';
$token = $context['token'] ?? '(missing)';
$message = $context['message'] ?? '(no message)';
$plugin = $context['plugin'] ?? '(none detected)';
$file = $context['file'] ?? '(unknown file)';
$line = $context['line'] ?? '(unknown line)';
echo "Recovery flag context:\n";
echo " Token: {$token}\n";
echo " Message: {$message}\n";
echo " Plugin: {$plugin}\n";
echo " File: {$file}\n";
echo " Line: {$line}\n";
echo " Created: {$created}\n";
$window = $manager->getUpgradeWindow();
if ($window) {
$expires = isset($window['expires_at']) ? date('c', (int)$window['expires_at']) : 'unknown';
$reason = $window['reason'] ?? '(unknown)';
echo " Window: active ({$reason}, expires {$expires})\n";
} else {
echo " Window: inactive\n";
}
exit(0);
default:
echo "Unknown recovery action: {$action}\n\n" . RESTORE_USAGE . "\n";
exit(1);
}
case 'help':
default:
echo RESTORE_USAGE . "\n";

View File

@@ -2,7 +2,7 @@ actor: Tester
bootstrap: _bootstrap.php
paths:
tests: tests
log: tests/_output
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs

View File

@@ -12,7 +12,7 @@
"homepage": "https://getgrav.org",
"license": "MIT",
"require": {
"php": "^7.3.6 || ^8.0",
"php": "^8.2",
"ext-json": "*",
"ext-openssl": "*",
"ext-curl": "*",
@@ -20,61 +20,79 @@
"ext-dom": "*",
"ext-libxml": "*",
"ext-gd": "*",
"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",
"symfony/polyfill-mbstring": "^1.24",
"symfony/polyfill-iconv": "^1.24",
"symfony/polyfill-php80": "^1.24",
"symfony/polyfill-php81": "^1.24",
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0",
"psr/http-message": "^1.1 || ^2.0",
"psr/http-server-middleware": "^1.0",
"psr/container": "~1.1.0",
"nyholm/psr7-server": "^1.0",
"nyholm/psr7": "^1.3",
"twig/twig": "~v1.44",
"psr/container": "^1.1 || ^2.0",
"psr/log": "^1.1 || ^2.0 || ^3.0",
"symfony/cache": "^6.4 || ^7.0",
"symfony/yaml": "^6.4 || ^7.0",
"symfony/console": "^6.4 || ^7.0",
"symfony/event-dispatcher": "^6.4 || ^7.0",
"symfony/var-exporter": "^6.4 || ^7.0",
"symfony/var-dumper": "^6.4 || ^7.0",
"symfony/process": "^6.4 || ^7.0",
"symfony/http-client": "^6.4 || ^7.0",
"twig/twig": "3.x-dev",
"monolog/monolog": "^3.0",
"doctrine/cache": "^2.2",
"doctrine/collections": "^2.2",
"pimple/pimple": "~3.5.0",
"nyholm/psr7-server": "^1.1",
"nyholm/psr7": "^1.8",
"erusev/parsedown": "^1.7",
"erusev/parsedown-extra": "~0.8",
"symfony/contracts": "~1.1",
"symfony/yaml": "~4.4",
"symfony/console": "~4.4",
"symfony/event-dispatcher": "~4.4",
"symfony/var-dumper": "~4.4",
"symfony/process": "~4.4",
"doctrine/cache": "^1.10",
"doctrine/collections": "^1.6",
"guzzlehttp/psr7": "^1.7",
"filp/whoops": "~2.9",
"rockettheme/toolbox": "v2.x-dev",
"composer/ca-bundle": "^1.5",
"composer/semver": "^3.4",
"dragonmantank/cron-expression": "^3.3",
"willdurand/negotiation": "^3.1",
"rhukster/dom-sanitizer": "^1.0",
"matthiasmullie/minify": "^1.3",
"monolog/monolog": "~1.25",
"donatj/phpuseragentparser": "~1.9",
"guzzlehttp/psr7": "^2.7",
"filp/whoops": "~2.16",
"itsgoingd/clockwork": "^5.3",
"php-debugbar/php-debugbar": "~2.1",
"getgrav/image": "^4.0",
"getgrav/cache": "^2.0",
"donatj/phpuseragentparser": "~1.1",
"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": "^3.3",
"willdurand/negotiation": "^3.0",
"itsgoingd/clockwork": "^5.0",
"symfony/http-client": "^4.4",
"composer/semver": "^1.4",
"rhukster/dom-sanitizer": "^1.0",
"league/climate": "^3.10",
"multiavatar/multiavatar-php": "^1.0"
},
"require-dev": {
"codeception/codeception": "^4.1",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpunit/php-code-coverage": "~9.2",
"codeception/codeception": "^5.1",
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpunit/php-code-coverage": "^11.0",
"getgrav/markdowndocs": "^2.0",
"codeception/module-asserts": "^1.3",
"codeception/module-phpbrowser": "^1.0"
"codeception/module-asserts": "*",
"codeception/module-phpbrowser": "*",
"rector/rector": "^2.1"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/rockettheme/toolbox"
},
{
"type": "vcs",
"url": "https://github.com/getgrav/twig"
},
{
"type": "vcs",
"url": "https://github.com/getgrav/parsedown"
}
],
"replace": {
"symfony/polyfill-php72": "*",
"symfony/polyfill-php73": "*"
"symfony/polyfill-php73": "*",
"symfony/polyfill-php74": "*"
},
"suggest": {
"ext-mbstring": "Recommended for better performance",
@@ -87,11 +105,16 @@
"ext-exif": "Needed to use exif data from images."
},
"config": {
"apcu-autoloader": true
"apcu-autoloader": true,
"platform": {
"php": "8.2"
}
},
"autoload": {
"psr-4": {
"Grav\\": "system/src/Grav",
"Doctrine\\": "system/src/Doctrine",
"RocketTheme\\": "system/src/RocketTheme",
"Twig\\": "system/src/Twig"
},
"files": [
@@ -111,10 +134,12 @@
]
},
"scripts": {
"api-17": "vendor/bin/phpdoc-md generate system/src > user/pages/14.api/default.17.md",
"api-18": "vendor/bin/phpdoc-md generate system/src > user/pages/14.api/default.18.md",
"post-create-project-cmd": "bin/grav install",
"rector": "vendor/bin/rector",
"rector:php-compat": "@php vendor/bin/rector process --config=system/rector.php --ansi --no-progress-bar",
"phpstan": "vendor/bin/phpstan analyse -l 2 -c ./tests/phpstan/phpstan.neon --memory-limit=720M system/src",
"phpstan-framework": "vendor/bin/phpstan analyse -l 5 -c ./tests/phpstan/phpstan.neon --memory-limit=480M system/src/Grav/Framework system/src/Grav/Events system/src/Grav/Installer",
"phpstan-framework": "vendor/bin/phpstan analyse -l 6 -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"

3525
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
namespace Grav;
\define('GRAV_REQUEST_TIME', microtime(true));
\define('GRAV_PHP_MIN', '7.3.6');
\define('GRAV_PHP_MIN', '8.2.0');
if (PHP_SAPI === 'cli-server') {
$symfony_server = stripos(getenv('_'), 'symfony') !== false || stripos($_SERVER['SERVER_SOFTWARE'] ?? '', 'symfony') !== false || stripos($_ENV['SERVER_SOFTWARE'] ?? '', 'symfony') !== false;
@@ -46,12 +46,12 @@ use Grav\Common\Grav;
use RocketTheme\Toolbox\Event\Event;
// Get the Grav instance
$grav = Grav::instance(array('loader' => $loader));
$grav = Grav::instance(['loader' => $loader]);
// Process the page
try {
$grav->process();
} catch (\Error|\Exception $e) {
$grav->fireEvent('onFatalException', new Event(array('exception' => $e)));
$grav->fireEvent('onFatalException', new Event(['exception' => $e]));
throw $e;
}

505
needs_fixing.txt Normal file
View File

@@ -0,0 +1,505 @@
------ ----------------------------------------------------
Line src/Grav/Common/GPM/Response.php
------ ----------------------------------------------------
3 Class Grav\Common\GPM\Response not found.
🪪 class.notFound
💡 Learn more at
https://phpstan.org/user-guide/discovering-symbols
------ ----------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Common/Grav.php
------ -----------------------------------------------------------
148 No error to ignore is reported on line 148.
681 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Common/Page/Collection.php
------ -----------------------------------------------------------
112 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
209 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Common/Processors/InitializeProcessor.php
------ -----------------------------------------------------------
58 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ -------------------------------------------------------
Line src/Grav/Common/Scheduler/Job.php
------ -------------------------------------------------------
574 Call to static method sendEmail() on an unknown class
Grav\Plugin\Email\Utils.
🪪 class.notFound
💡 Learn more at
https://phpstan.org/user-guide/discovering-symbols
------ -------------------------------------------------------
------ ----------------------------------------------------------
Line src/Grav/Common/Scheduler/SchedulerController.php
------ ----------------------------------------------------------
41 Class Grav\Common\Scheduler\ModernScheduler not found.
🪪 class.notFound
💡 Learn more at
https://phpstan.org/user-guide/discovering-symbols
45 Instantiated class Grav\Common\Scheduler\ModernScheduler
not found.
🪪 class.notFound
💡 Learn more at
https://phpstan.org/user-guide/discovering-symbols
------ ----------------------------------------------------------
------ --------------------------------------------------------
Line src/Grav/Common/Service/SchedulerServiceProvider.php
------ --------------------------------------------------------
55 Instantiated class Grav\Common\Scheduler\JobWorker not
found.
🪪 class.notFound
💡 Learn more at
https://phpstan.org/user-guide/discovering-symbols
------ --------------------------------------------------------
------ ---------------------------------------------
Line src/Grav/Common/Session.php
------ ---------------------------------------------
132 No error to ignore is reported on line 132.
137 No error to ignore is reported on line 137.
------ ---------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Common/Uri.php
------ -----------------------------------------------------------
1131 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ --------------------------------------------------------
Line src/Grav/Console/Application/Application.php
------ --------------------------------------------------------
125 Return type mixed of method
Grav\Console\Application\Application::configureIO() is
not covariant with return type void of method
Symfony\Component\Console\Application::configureIO().
------ --------------------------------------------------------
------ ---------------------------------------------------------
Line src/Grav/Console/ConsoleCommand.php
------ ---------------------------------------------------------
29 Return type mixed of method
Grav\Console\ConsoleCommand::execute() is not covariant
with return type int of method
Symfony\Component\Console\Command\Command::execute().
------ ---------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Console/ConsoleTrait.php (in context of class
Grav\Console\ConsoleCommand)
------ -----------------------------------------------------------
89 Method Grav\Console\ConsoleCommand::addOption() overrides
method
Symfony\Component\Console\Command\Command::addOption()
but misses parameter #6 $suggestedValues.
------ -----------------------------------------------------------
------ --------------------------------------------------------
Line src/Grav/Console/ConsoleTrait.php (in context of class
Grav\Console\GpmCommand)
------ --------------------------------------------------------
89 Method Grav\Console\GpmCommand::addOption() overrides
method
Symfony\Component\Console\Command\Command::addOption()
but misses parameter #6 $suggestedValues.
------ --------------------------------------------------------
------ --------------------------------------------------------
Line src/Grav/Console/ConsoleTrait.php (in context of class
Grav\Console\GravCommand)
------ --------------------------------------------------------
89 Method Grav\Console\GravCommand::addOption() overrides
method
Symfony\Component\Console\Command\Command::addOption()
but misses parameter #6 $suggestedValues.
------ --------------------------------------------------------
------ ----------------------------------------------------------
Line src/Grav/Console/GpmCommand.php
------ ----------------------------------------------------------
31 Return type mixed of method
Grav\Console\GpmCommand::execute() is not covariant with
return type int of method
Symfony\Component\Console\Command\Command::execute().
39 No error to ignore is reported on line 39.
------ ----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Console/GravCommand.php
------ -----------------------------------------------------------
29 Return type mixed of method
Grav\Console\GravCommand::execute() is not covariant with
return type int of method
Symfony\Component\Console\Command\Command::execute().
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Acl/RecursiveActionIterator.php
------ -----------------------------------------------------------
62 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ ----------------------------------------------------------
Line src/Grav/Framework/Cache/CacheTrait.php (in context of
class Grav\Framework\Cache\AbstractCache)
------ ----------------------------------------------------------
87 Return type mixed of method
Grav\Framework\Cache\AbstractCache::get() is not
covariant with return type mixed of method
Psr\SimpleCache\CacheInterface::get().
102 Return type mixed of method
Grav\Framework\Cache\AbstractCache::set() is not
covariant with return type bool of method
Psr\SimpleCache\CacheInterface::set().
117 Return type mixed of method
Grav\Framework\Cache\AbstractCache::delete() is not
covariant with return type bool of method
Psr\SimpleCache\CacheInterface::delete().
127 Return type mixed of method
Grav\Framework\Cache\AbstractCache::clear() is not
covariant with return type bool of method
Psr\SimpleCache\CacheInterface::clear().
138 Return type mixed of method
Grav\Framework\Cache\AbstractCache::getMultiple() is not
covariant with return type iterable of method
Psr\SimpleCache\CacheInterface::getMultiple().
181 Return type mixed of method
Grav\Framework\Cache\AbstractCache::setMultiple() is not
covariant with return type bool of method
Psr\SimpleCache\CacheInterface::setMultiple().
214 Return type mixed of method
Grav\Framework\Cache\AbstractCache::deleteMultiple() is
not covariant with return type bool of method
Psr\SimpleCache\CacheInterface::deleteMultiple().
242 Return type mixed of method
Grav\Framework\Cache\AbstractCache::has() is not
covariant with return type bool of method
Psr\SimpleCache\CacheInterface::has().
------ ----------------------------------------------------------
------ ----------------------------------------------------------
Line src/Grav/Framework/Collection/AbstractFileCollection.php
------ ----------------------------------------------------------
95 No error to ignore is reported on line 95.
------ ----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Collection/AbstractIndexCollection.php
------ -----------------------------------------------------------
154 No error to ignore is reported on line 154.
168 No error to ignore is reported on line 168.
185 No error to ignore is reported on line 185.
201 No error to ignore is reported on line 201.
507 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Collection/AbstractLazyCollection.php
------ -----------------------------------------------------------
29 Property
Grav\Framework\Collection\AbstractLazyCollection::$collec
tion overriding property
Doctrine\Common\Collections\AbstractLazyCollection<TKey o
f (int|string),T>::$collection (Doctrine\Common\Collectio
ns\Collection|null) should also have native type
Doctrine\Common\Collections\Collection|null.
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Contracts/Relationships/RelationshipIn
terface.php
------ -----------------------------------------------------------
80 Return type iterable of method
Grav\Framework\Contracts\Relationships\RelationshipInterf
ace::getIterator() is not covariant with tentative return
type Traversable of method IteratorAggregate<string,T of
Grav\Framework\Contracts\Object\IdentifierInterface>::get
Iterator().
💡 Make it covariant, or use the #[\ReturnTypeWillChange]
attribute to temporarily suppress the error.
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Filesystem/Filesystem.php
------ -----------------------------------------------------------
51 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
252 No error to ignore is reported on line 252.
------ -----------------------------------------------------------
------ ---------------------------------------------
Line src/Grav/Framework/Flex/FlexCollection.php
------ ---------------------------------------------
102 No error to ignore is reported on line 102.
------ ---------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Flex/FlexIdentifier.php
------ -----------------------------------------------------------
27 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ ----------------------------------------------------------
Line src/Grav/Framework/Flex/FlexIndex.php
------ ----------------------------------------------------------
109 No error to ignore is reported on line 109.
934 Method Grav\Framework\Flex\FlexIndex::reduce() should
return TInitial|TReturn but return statement is missing.
🪪 return.missing
------ ----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Form/FormFlashFile.php
------ -----------------------------------------------------------
62 Return type mixed of method
Grav\Framework\Form\FormFlashFile::getStream() is not
covariant with return type
Psr\Http\Message\StreamInterface of method
Psr\Http\Message\UploadedFileInterface::getStream().
83 Return type mixed of method
Grav\Framework\Form\FormFlashFile::moveTo() is not
covariant with return type void of method
Psr\Http\Message\UploadedFileInterface::moveTo().
123 Return type mixed of method
Grav\Framework\Form\FormFlashFile::getSize() is not
covariant with return type int|null of method
Psr\Http\Message\UploadedFileInterface::getSize().
131 Return type mixed of method
Grav\Framework\Form\FormFlashFile::getError() is not
covariant with return type int of method
Psr\Http\Message\UploadedFileInterface::getError().
139 Return type mixed of method
Grav\Framework\Form\FormFlashFile::getClientFilename() is
not covariant with return type string|null of method
Psr\Http\Message\UploadedFileInterface::getClientFilename
().
147 Return type mixed of method
Grav\Framework\Form\FormFlashFile::getClientMediaType()
is not covariant with return type string|null of method
Psr\Http\Message\UploadedFileInterface::getClientMediaTyp
e().
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Logger/Processors/UserProcessor.php
------ -----------------------------------------------------------
24 Parameter #1 $record (array) of method
Grav\Framework\Logger\Processors\UserProcessor::__invoke(
) is not contravariant with parameter #1 $record
(Monolog\LogRecord) of method
Monolog\Processor\ProcessorInterface::__invoke().
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Media/MediaIdentifier.php
------ -----------------------------------------------------------
30 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Media/UploadedMediaObject.php
------ -----------------------------------------------------------
36 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Mime/MimeTypes.php
------ -----------------------------------------------------------
42 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ ------------------------------------------------
Line src/Grav/Framework/Object/ObjectCollection.php
------ ------------------------------------------------
96 No error to ignore is reported on line 96.
------ ------------------------------------------------
------ ---------------------------------------------
Line src/Grav/Framework/Object/ObjectIndex.php
------ ---------------------------------------------
193 No error to ignore is reported on line 193.
------ ---------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Psr7/Stream.php
------ -----------------------------------------------------------
31 Unsafe usage of new static().
🪪 new.static
💡 See:
https://phpstan.org/blog/solving-phpstan-error-unsafe-usa
ge-of-new-static
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Psr7/Traits/ServerRequestDecoratorTrai
t.php (in context of class
Grav\Framework\Psr7\ServerRequest)
------ -----------------------------------------------------------
51 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::getAttributes() is not
covariant with return type array of method
Psr\Http\Message\ServerRequestInterface::getAttributes().
60 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::getCookieParams() is
not covariant with return type array of method
Psr\Http\Message\ServerRequestInterface::getCookieParams(
).
76 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::getQueryParams() is
not covariant with return type array of method
Psr\Http\Message\ServerRequestInterface::getQueryParams()
.
84 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::getServerParams() is
not covariant with return type array of method
Psr\Http\Message\ServerRequestInterface::getServerParams(
).
92 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::getUploadedFiles() is
not covariant with return type array of method
Psr\Http\Message\ServerRequestInterface::getUploadedFiles
().
100 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::withAttribute() is not
covariant with return type
Psr\Http\Message\ServerRequestInterface of method
Psr\Http\Message\ServerRequestInterface::withAttribute().
125 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::withoutAttribute() is
not covariant with return type
Psr\Http\Message\ServerRequestInterface of method
Psr\Http\Message\ServerRequestInterface::withoutAttribute
().
136 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::withCookieParams() is
not covariant with return type
Psr\Http\Message\ServerRequestInterface of method
Psr\Http\Message\ServerRequestInterface::withCookieParams
().
147 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::withParsedBody() is
not covariant with return type
Psr\Http\Message\ServerRequestInterface of method
Psr\Http\Message\ServerRequestInterface::withParsedBody()
.
158 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::withQueryParams() is
not covariant with return type
Psr\Http\Message\ServerRequestInterface of method
Psr\Http\Message\ServerRequestInterface::withQueryParams(
).
169 Return type mixed of method
Grav\Framework\Psr7\ServerRequest::withUploadedFiles() is
not covariant with return type
Psr\Http\Message\ServerRequestInterface of method
Psr\Http\Message\ServerRequestInterface::withUploadedFile
s().
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Grav/Framework/Relationships/Relationships.php
------ -----------------------------------------------------------
107 Return type mixed of method
Grav\Framework\Relationships\Relationships::offsetSet()
is not covariant with tentative return type void of
method
ArrayAccess<string,Grav\Framework\Contracts\Relationships
\RelationshipInterface<T of Grav\Framework\Contracts\Obje
ct\IdentifierInterface, P of
Grav\Framework\Contracts\Object\IdentifierInterface>>::of
fsetSet().
💡 Make it covariant, or use the #[\ReturnTypeWillChange]
attribute to temporarily suppress the error.
116 Return type mixed of method
Grav\Framework\Relationships\Relationships::offsetUnset()
is not covariant with tentative return type void of
method
ArrayAccess<string,Grav\Framework\Contracts\Relationships
\RelationshipInterface<T of Grav\Framework\Contracts\Obje
ct\IdentifierInterface, P of
Grav\Framework\Contracts\Object\IdentifierInterface>>::of
fsetUnset().
💡 Make it covariant, or use the #[\ReturnTypeWillChange]
attribute to temporarily suppress the error.
------ -----------------------------------------------------------
------ -----------------------------------------------------------
Line src/Twig/DeferredExtension/DeferredNodeVisitorCompat.php
------ -----------------------------------------------------------
30 Parameter #1 $node (Twig_NodeInterface) of method
Twig\DeferredExtension\DeferredNodeVisitorCompat::enterNo
de() is not contravariant with parameter #1 $node
(Twig\Node\Node) of method
Twig\NodeVisitor\NodeVisitorInterface::enterNode().
30 Parameter $node of method
Twig\DeferredExtension\DeferredNodeVisitorCompat::enterNo
de() has invalid type Twig_NodeInterface.
🪪 class.notFound
46 Parameter #1 $node (Twig_NodeInterface) of method
Twig\DeferredExtension\DeferredNodeVisitorCompat::leaveNo
de() is not contravariant with parameter #1 $node
(Twig\Node\Node) of method
Twig\NodeVisitor\NodeVisitorInterface::leaveNode().
46 Parameter $node of method
Twig\DeferredExtension\DeferredNodeVisitorCompat::leaveNo
de() has invalid type Twig_NodeInterface.
🪪 class.notFound
------ -----------------------------------------------------------
[ERROR] Found 74 errors

View File

@@ -1,67 +1,5 @@
div.phpdebugbar {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
div.phpdebugbar a.phpdebugbar-restore-btn::after {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAA/1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeHh4AAAD///8EBAT7+/sLCwv29vYVFRUvLy/t7e3m5ubCwsKxsbE/Pz+mpqZMTEwcHBzy8vLp6emfn5+AgIA2Njbi4uLf39+rq6tzc3NWVlYhISHa2trW1tbS0tLMzMy7u7uZmZmUlJSMjIxvb29kZGRHR0c7Ozt5eXkqKiq1tbWQkJBqampbW1tSUlLHx8eHh4ckJCRDQ0M3wD42AAAAI3RSTlMA/PibTbQ0x76TVAlw4LhZLOuEYCAN9Hjx0a2ppGZEGYw97djhXHwAAATZSURBVFjDlVcHW+MwDO1eFCjj2McNOzvdpXTTXVbL/P+/5SQ7QSSX5Di1X1onfi/Sk+Q4sTDbKqWK+YuznZ2zi3wxVdqK/Zf92M1nT9gnO8rmd398GX6Z3xaoOFoiAQcx3E5efgmeSuN8F6Xg1x3G06l/wjNpMR1B0uif4EhnIuFb+0diIoFXk3IVfokisR+h52GO4JKgyjmfaMhAFNlSaPR7DpwI+lzn/E4QKIqmKIJirxCMP4izBPPZPXhgXwMBYgULw0nfg/BF5scDbslb7QeJ08yqqTEmGYoB95d4H8ETL8+n9wBqrLu6ao3bBsMwAnxISf/9BHcqxNB8Y7cWl3Zz7TAUfPrvAT6AoNEFFXvsjutL01yOuMrtBxnFXsmT/1wQHmdWAFNnI3uI48Yj0FUcHbKf62GfUfr8eeQt7Uk3mQZpZNoVRPEui5vtEz5zFEpgWnyqVBZMc6oaGNriH2hGVZ0OxEvInPeMaZWJBA7vmPbCr5jjws5HBnAUxvDMH40aCIf4G5BjRQSs8E8HFFYf8bGxgDvD55bzGhwWkoBcuIyHR/AMdaCagxXDhtL6tSqoWpd4BMnlIR+Or+rYTK/a3EAGcc6e4AWHISnWv20iCCojsHoVlQdjrMexFF2C7UMg2A2WEGWbQhXN6l3eXC6XGp4b9qxbuEB2EBGBwtocrK90cVG5mbRXm6vmx/0phq1sIAGKDgLOBiN1MrO5a9aDl+D0W6x0Ar9BCTRuIIANa90Y7LrLVRXzwVtDInCqMRWcf2bUOEAsa4wJqFowQALL9EiAtVRk8QC4OW+1pOM9jIaVASwYagyNXDj+W0NcfuZNzjtXOiL0Zzg30Llj+ptfxQs4+vBPNiL5PawFCBkgXpUaVtqGl+A8dgZHL34BcBUQrwPptToW+o37Ku+UH9eYByJIx3YkAeFnMFuGO7S5gEp7YhXxa5OOAM39RXDPXb0qmpROsswZe+twXdU55oUIZAiEv3bD1UFwIYKkmGqytPCDCwKFQCKK0yL7qtSAPX54UAbtsLuBHkb9zyLmPQSNjsSgmQwKUOIfEY8F8t4B34DvndJY9BA8tNBJq1Nev9axmaStFcQLhgYoCTo0salkIaW8OUDdWjMTR2sHPhrAFZqx6cqcKE4pl2BJJ4K6hfwvqNgAnXfKX/HU6X3Zrhnu0k7tLNZtTBRv1hkwTDBY1NzFU6doDYjJbWdQkQhWwuU7/LvhTh3SDoco4ECL4i5dwURbc8NdDZz2IwKicE8d0KIqWetLE3+lL4hvUuGSeRfVWNLfj/gpOw4smBJBkKQHCzlHGwvAj4woB1gq5NGGLSXtORBPnUQPV5/MPVkDMxbpwG7w4x0xL6Ltxka0A/4NBvV09UVk4DoSn/jl2+JQS9q9KYawisAD4CfhsZ4TH3htylsdEHARIQBusqCKyUpymycgbbkkXEXjT3z7/oKQFTFVuZD2FMJHZIDsO5x2d4aAr2jR+GLwZhtAb028/0yJ9J8dE87jQyKObcjtTXT8dH+fDuKF4/eiPwzH44wTf/yUi6wrpRIOZ9lM1EtXAifFI+CJn9+iX/t2xMQwOMth/UZbASi8btAwR9FHWSpJr75g9Oqbin3VDg+SpwlP6k6TB4ex/7JvmcJx8jydy6XPk8eFTKhyfwCgX71MSvaBHgAAAABJRU5ErkJggg==) !important;
width: 32px;
}
.phpdebugbar pre {
padding: 1rem;
}
.phpdebugbar div.phpdebugbar-header > div > * {
padding: 5px 15px;
}
.phpdebugbar div.phpdebugbar-header > div.phpdebugbar-header-right > * {
padding: 5px 8px;
}
.phpdebugbar a.phpdebugbar-restore-btn {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAA/1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeHh4AAAD///8EBAT7+/sLCwv29vYVFRUvLy/t7e3m5ubCwsKxsbE/Pz+mpqZMTEwcHBzy8vLp6emfn5+AgIA2Njbi4uLf39+rq6tzc3NWVlYhISHa2trW1tbS0tLMzMy7u7uZmZmUlJSMjIxvb29kZGRHR0c7Ozt5eXkqKiq1tbWQkJBqampbW1tSUlLHx8eHh4ckJCRDQ0M3wD42AAAAI3RSTlMA/PibTbQ0x76TVAlw4LhZLOuEYCAN9Hjx0a2ppGZEGYw97djhXHwAAATZSURBVFjDlVcHW+MwDO1eFCjj2McNOzvdpXTTXVbL/P+/5SQ7QSSX5Di1X1onfi/Sk+Q4sTDbKqWK+YuznZ2zi3wxVdqK/Zf92M1nT9gnO8rmd398GX6Z3xaoOFoiAQcx3E5efgmeSuN8F6Xg1x3G06l/wjNpMR1B0uif4EhnIuFb+0diIoFXk3IVfokisR+h52GO4JKgyjmfaMhAFNlSaPR7DpwI+lzn/E4QKIqmKIJirxCMP4izBPPZPXhgXwMBYgULw0nfg/BF5scDbslb7QeJ08yqqTEmGYoB95d4H8ETL8+n9wBqrLu6ao3bBsMwAnxISf/9BHcqxNB8Y7cWl3Zz7TAUfPrvAT6AoNEFFXvsjutL01yOuMrtBxnFXsmT/1wQHmdWAFNnI3uI48Yj0FUcHbKf62GfUfr8eeQt7Uk3mQZpZNoVRPEui5vtEz5zFEpgWnyqVBZMc6oaGNriH2hGVZ0OxEvInPeMaZWJBA7vmPbCr5jjws5HBnAUxvDMH40aCIf4G5BjRQSs8E8HFFYf8bGxgDvD55bzGhwWkoBcuIyHR/AMdaCagxXDhtL6tSqoWpd4BMnlIR+Or+rYTK/a3EAGcc6e4AWHISnWv20iCCojsHoVlQdjrMexFF2C7UMg2A2WEGWbQhXN6l3eXC6XGp4b9qxbuEB2EBGBwtocrK90cVG5mbRXm6vmx/0phq1sIAGKDgLOBiN1MrO5a9aDl+D0W6x0Ar9BCTRuIIANa90Y7LrLVRXzwVtDInCqMRWcf2bUOEAsa4wJqFowQALL9EiAtVRk8QC4OW+1pOM9jIaVASwYagyNXDj+W0NcfuZNzjtXOiL0Zzg30Llj+ptfxQs4+vBPNiL5PawFCBkgXpUaVtqGl+A8dgZHL34BcBUQrwPptToW+o37Ku+UH9eYByJIx3YkAeFnMFuGO7S5gEp7YhXxa5OOAM39RXDPXb0qmpROsswZe+twXdU55oUIZAiEv3bD1UFwIYKkmGqytPCDCwKFQCKK0yL7qtSAPX54UAbtsLuBHkb9zyLmPQSNjsSgmQwKUOIfEY8F8t4B34DvndJY9BA8tNBJq1Nev9axmaStFcQLhgYoCTo0salkIaW8OUDdWjMTR2sHPhrAFZqx6cqcKE4pl2BJJ4K6hfwvqNgAnXfKX/HU6X3Zrhnu0k7tLNZtTBRv1hkwTDBY1NzFU6doDYjJbWdQkQhWwuU7/LvhTh3SDoco4ECL4i5dwURbc8NdDZz2IwKicE8d0KIqWetLE3+lL4hvUuGSeRfVWNLfj/gpOw4smBJBkKQHCzlHGwvAj4woB1gq5NGGLSXtORBPnUQPV5/MPVkDMxbpwG7w4x0xL6Ltxka0A/4NBvV09UVk4DoSn/jl2+JQS9q9KYawisAD4CfhsZ4TH3htylsdEHARIQBusqCKyUpymycgbbkkXEXjT3z7/oKQFTFVuZD2FMJHZIDsO5x2d4aAr2jR+GLwZhtAb028/0yJ9J8dE87jQyKObcjtTXT8dH+fDuKF4/eiPwzH44wTf/yUi6wrpRIOZ9lM1EtXAifFI+CJn9+iX/t2xMQwOMth/UZbASi8btAwR9FHWSpJr75g9Oqbin3VDg+SpwlP6k6TB4ex/7JvmcJx8jydy6XPk8eFTKhyfwCgX71MSvaBHgAAAABJRU5ErkJggg==);
width: 13px;
}
.phpdebugbar a.phpdebugbar-tab.phpdebugbar-active {
background: #3DB9EC;
color: #fff;
margin-top: -1px;
padding-top: 6px;
}
.phpdebugbar .phpdebugbar-widgets-toolbar {
border-top: 1px solid #ddd;
padding-left: 5px;
padding-right: 2px;
padding-top: 2px;
background-color: #fafafa !important;
width: auto !important;
left: 0;
right: 0;
}
.phpdebugbar .phpdebugbar-widgets-toolbar input {
background: transparent !important;
}
.phpdebugbar .phpdebugbar-widgets-toolbar .phpdebugbar-widgets-filter {
}
.phpdebugbar input[type=text] {
padding: 0;
display: inline;
}
.phpdebugbar dl.phpdebugbar-widgets-varlist, ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
font-size: 12px;
}
ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff;
top: 0;
}
.phpdebugbar pre, .phpdebugbar code {
margin: 0;
font-size: 14px;
}

View File

@@ -610,6 +610,15 @@ form:
hash: All files timestamps
none: No timestamp checking
cache.check.interval:
type: number
size: x-small
label: Cache Check Interval
help: Seconds to reuse the previously computed filesystem hash before checking again. Zero keeps existing per-request checks.
validate:
type: int
min: 0
cache.driver:
type: select
size: small
@@ -619,11 +628,9 @@ form:
options:
auto: Auto detect
file: File
apc: APC
apcu: APCu
memcache: Memcache
memcached: Memcached
wincache: WinCache
redis: Redis
cache.prefix:
@@ -720,20 +727,6 @@ form:
validate:
type: bool
cache.memcache.server:
type: text
size: medium
label: PLUGIN_ADMIN.MEMCACHE_SERVER
help: PLUGIN_ADMIN.MEMCACHE_SERVER_HELP
placeholder: "localhost"
cache.memcache.port:
type: text
size: small
label: PLUGIN_ADMIN.MEMCACHE_PORT
help: PLUGIN_ADMIN.MEMCACHE_PORT_HELP
placeholder: "11211"
cache.memcached.server:
type: text
size: medium
@@ -791,8 +784,8 @@ form:
flex.cache.index.enabled:
type: toggle
label: PLUGIN_ADMIN.FLEX_INDEX_CACHE_ENABLED
highlight: 1
default: 1
highlight: 0
default: 0
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
@@ -809,8 +802,8 @@ form:
flex.cache.object.enabled:
type: toggle
label: PLUGIN_ADMIN.FLEX_OBJECT_CACHE_ENABLED
highlight: 1
default: 1
highlight: 0
default: 0
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
@@ -897,17 +890,6 @@ form:
validate:
type: bool
twig.umask_fix:
type: toggle
label: PLUGIN_ADMIN.TWIG_UMASK_FIX
help: PLUGIN_ADMIN.TWIG_UMASK_FIX_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets:
type: tab
title: PLUGIN_ADMIN.ASSETS
@@ -1807,8 +1789,8 @@ form:
http_x_forwarded.host:
type: toggle
label: HTTP_X_FORWARDED_HOST Enabled
highlight: 0
default: 0
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
@@ -1841,8 +1823,8 @@ form:
strict_mode.blueprint_compat:
type: toggle
label: PLUGIN_ADMIN.STRICT_BLUEPRINT_COMPAT
highlight: 0
default: 0
highlight: 1
default: 1
help: PLUGIN_ADMIN.STRICT_BLUEPRINT_COMPAT_HELP
options:
1: PLUGIN_ADMIN.YES
@@ -1862,7 +1844,7 @@ form:
validate:
type: bool
strict_mode.twig_compat:
strict_mode.twig2_compat:
type: toggle
label: PLUGIN_ADMIN.STRICT_TWIG_COMPAT
highlight: 0
@@ -1874,6 +1856,18 @@ form:
validate:
type: bool
strict_mode.twig3_compat:
type: toggle
label: Twig 3 Compatibility
highlight: 0
default: 0
help: Enable automatic rewrites for legacy Twig 1/2 syntax that breaks on Twig 3 (e.g. `for ... if ...` guards)
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
accounts:
type: tab

File diff suppressed because it is too large Load Diff

View File

@@ -93,13 +93,14 @@ cache:
enabled: true # Set to true to enable caching
check:
method: file # Method to check for updates in pages: file|folder|hash|none
driver: auto # One of: auto|file|apcu|memcache|wincache
interval: 0 # Seconds to reuse previous filesystem hash before rechecking (0 = every request)
driver: auto # One of: auto|file|apcu|memcached|redis
prefix: 'g' # Cache prefix string (prevents cache conflicts)
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
cli_compatibility: false # Ensures only non-volatile drivers are used (file, redis, memcache, etc.)
cli_compatibility: false # Ensures only non-volatile drivers are used (file, redis, memcached, etc.)
lifetime: 604800 # Lifetime of cached data in seconds (0 = infinite)
purge_max_age_days: 30 # Maximum age of cache items in days before they are purged
gzip: false # GZip compress the page output
@@ -118,7 +119,6 @@ twig:
undefined_filters: true # Allow undefined filters
safe_functions: [] # List of PHP functions which are allowed to be used as Twig functions
safe_filters: [] # List of PHP functions which are allowed to be used as Twig filters
umask_fix: false # By default Twig creates cached files as 755, fix switches this to 775
assets: # Configuration for Assets Manager (JS, CSS)
css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file
@@ -235,5 +235,6 @@ flex:
strict_mode:
yaml_compat: false # Set to true to enable YAML backwards compatibility
twig_compat: false # Set to true to enable deprecated Twig settings (autoescape: false)
twig2_compat: false # Set to true to enable deprecated Twig settings (autoescape: false)
twig3_compat: true # Set to true to enable automatic fixes for Twig 3 syntax changes
blueprint_compat: false # Set to true to enable backward compatible strict support for blueprints

View File

@@ -9,13 +9,13 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.7.50');
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
define('GRAV_TESTING', false);
define('GRAV_VERSION', '1.8.0-beta.10');
define('GRAV_SCHEMA', '1.8.0_2025-09-21_0');
define('GRAV_TESTING', true);
// PHP minimum requirement
if (!defined('GRAV_PHP_MIN')) {
define('GRAV_PHP_MIN', '7.3.6');
define('GRAV_PHP_MIN', '8.2.0');
}
// Directory separator

16
system/rector.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withSkip([
__DIR__ . '/vendor',
])
->withPaths([
__DIR__
])
->withPhpSets(php82: true)
->withPhpVersion(Rector\ValueObject\PhpVersion::PHP_84)
->withRules([
Rector\Php84\Rector\Param\ExplicitNullableParamTypeRector::class,
]);

View File

@@ -18,17 +18,17 @@ $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
str_contains((string) $path, '/.')
// Block all direct access for these folders
|| preg_match('`^/(\.git|cache|bin|logs|backup|webserver-configs|tests)/`ui', $path)
|| preg_match('`^/(\.git|cache|bin|logs|backup|webserver-configs|tests)/`ui', (string) $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)
|| preg_match('`^/(system|vendor)/(.*)\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', (string) $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)
|| preg_match('`^/(user)/(.*)\.(txt|md|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', (string) $path)
// Block all direct access to .md files
|| preg_match('`\.md$`ui', $path)
|| preg_match('`\.md$`ui', (string) $path)
// Block access to specific files in the root folder
|| preg_match('`^/(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$`ui', $path)
|| preg_match('`^/(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$`ui', (string) $path)
)) {
return false;
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Doctrine\Common\Cache;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
/**
* Filesystem cache driver (backwards compatibility).
*/
class FilesystemCache extends CacheProvider
{
public const EXTENSION = '.doctrinecache.data';
/** @var FilesystemAdapter */
private $pool;
/**
* {@inheritdoc}
*/
public function __construct($directory, $extension = self::EXTENSION, $umask = 0002)
{
user_error(self::class . ' is deprecated since Grav 1.8, use Symfony cache instead', E_USER_DEPRECATED);
$this->pool = new FilesystemAdapter('', 0, $directory);
}
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
$item = $this->pool->getItem(rawurlencode($id));
return $item->isHit() ? $item->get() : false;
}
/**
* {@inheritdoc}
*
* @return bool
*/
protected function doContains($id)
{
return $this->pool->hasItem(rawurlencode($id));
}
/**
* {@inheritdoc}
*
* @return bool
*/
protected function doSave($id, $data, $lifeTime = 0)
{
$item = $this->pool->getItem(rawurlencode($id));
if (0 < $lifeTime) {
$item->expiresAfter($lifeTime);
}
return $this->pool->save($item->set($data));
}
/**
* {@inheritdoc}
*
* @return bool
*/
protected function doDelete($id)
{
return $this->pool->deleteItem(rawurlencode($id));
}
/**
* {@inheritdoc}
*
* @return bool
*/
protected function doFlush()
{
return $this->pool->clear();
}
/**
* {@inheritdoc}
*
* @return array|null
*/
protected function doGetStats()
{
return null;
}
}

View File

@@ -194,12 +194,12 @@ class Assets extends PropertyObject
}
$params = array_merge([$location], $params);
call_user_func_array([$this, 'add'], $params);
call_user_func_array($this->add(...), $params);
}
} elseif (isset($this->collections[$asset])) {
array_shift($args);
$args = array_merge([$this->collections[$asset]], $args);
call_user_func_array([$this, 'add'], $args);
call_user_func_array($this->add(...), $args);
} else {
// Get extension
$path = parse_url($asset, PHP_URL_PATH);
@@ -209,11 +209,11 @@ class Assets extends PropertyObject
if ($extension !== '') {
$extension = strtolower($extension);
if ($extension === 'css') {
call_user_func_array([$this, 'addCss'], $args);
call_user_func_array($this->addCss(...), $args);
} elseif ($extension === 'js') {
call_user_func_array([$this, 'addJs'], $args);
call_user_func_array($this->addJs(...), $args);
} elseif ($extension === 'mjs') {
call_user_func_array([$this, 'addJsModule'], $args);
call_user_func_array($this->addJsModule(...), $args);
}
}
}
@@ -261,7 +261,7 @@ class Assets extends PropertyObject
$default = 'before';
}
$options['position'] = $options['position'] ?? $default;
$options['position'] ??= $default;
}
unset($options['pipeline']);
@@ -432,9 +432,7 @@ class Assets extends PropertyObject
*/
protected function sortAssets($assets)
{
uasort($assets, static function ($a, $b) {
return $b['priority'] <=> $a['priority'] ?: $a['order'] <=> $b['order'];
});
uasort($assets, static fn($a, $b) => $b['priority'] <=> $a['priority'] ?: $a['order'] <=> $b['order']);
return $assets;
}
@@ -577,18 +575,11 @@ class Assets extends PropertyObject
*/
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;
}
$base_type = match ($type) {
$this::JS_TYPE, $this::INLINE_JS_TYPE => $this::JS,
$this::JS_MODULE_TYPE, $this::INLINE_JS_MODULE_TYPE => $this::JS_MODULE,
default => $this::CSS,
};
return $base_type;
}

View File

@@ -114,7 +114,7 @@ abstract class BaseAsset extends PropertyObject
// Do some special stuff for CSS/JS (not inline)
if (!Utils::startsWith($this->getType(), 'inline')) {
$this->base_url = rtrim($uri->rootUrl($config->get('system.absolute_urls')), '/') . '/';
$this->base_url = rtrim((string) $uri->rootUrl($config->get('system.absolute_urls')), '/') . '/';
$this->remote = static::isRemoteLink($asset);
// Move this to render?

View File

@@ -192,15 +192,15 @@ class BlockAssets
{
$grav = Grav::instance();
$base = rtrim($grav['base_url'], '/') ?: '/';
$base = rtrim((string) $grav['base_url'], '/') ?: '/';
if (strpos($url, $base) === 0) {
if (str_starts_with($url, $base)) {
if ($pipeline) {
// Remove file timestamp if CSS pipeline has been enabled.
$url = preg_replace('|[?#].*|', '', $url);
}
return substr($url, strlen($base) - 1);
return substr((string) $url, strlen($base) - 1);
}
return $url;
}

View File

@@ -283,7 +283,7 @@ class Pipeline extends PropertyObject
} else {
return str_replace($matches[2], $new_url, $matches[0]);
}
}, $file);
}, (string) $file);
return $file;
}

View File

@@ -55,7 +55,7 @@ trait AssetUtilsTrait
return false;
}
return (0 === strpos($link, 'http://') || 0 === strpos($link, 'https://') || 0 === strpos($link, '//'));
return (str_starts_with($link, 'http://') || str_starts_with($link, 'https://') || str_starts_with($link, '//'));
}
/**
@@ -76,18 +76,18 @@ trait AssetUtilsTrait
if (static::isRemoteLink($link)) {
$local = false;
if (0 === strpos($link, '//')) {
if (str_starts_with((string) $link, '//')) {
$link = 'http:' . $link;
}
$relative_dir = dirname($relative_path);
$relative_dir = dirname((string) $relative_path);
} else {
// Fix to remove relative dir if grav is in one
if (($this->base_url !== '/') && Utils::startsWith($relative_path, $this->base_url)) {
$base_url = '#' . preg_quote($this->base_url, '#') . '#';
$relative_path = ltrim(preg_replace($base_url, '/', $link, 1), '/');
$relative_path = ltrim((string) preg_replace($base_url, '/', (string) $link, 1), '/');
}
$relative_dir = dirname($relative_path);
$relative_dir = dirname((string) $relative_path);
$link = GRAV_ROOT . '/' . $relative_path;
}
@@ -101,7 +101,7 @@ trait AssetUtilsTrait
// Double check last character being
if ($type === self::JS_ASSET || $type === self::JS_MODULE_ASSET) {
$file = rtrim($file, ' ;') . ';';
$file = rtrim((string) $file, ' ;') . ';';
}
// If this is CSS + the file is local + rewrite enabled
@@ -113,7 +113,7 @@ trait AssetUtilsTrait
$file = $this->jsRewrite($file, $relative_dir, $local);
}
$file = rtrim($file) . PHP_EOL;
$file = rtrim((string) $file) . PHP_EOL;
$buffer .= $file;
}
@@ -170,9 +170,9 @@ trait AssetUtilsTrait
}
if (in_array($key, $no_key, true)) {
$element = htmlentities($value, ENT_QUOTES, 'UTF-8', false);
$element = htmlentities((string) $value, ENT_QUOTES, 'UTF-8', false);
} else {
$element = $key . '="' . htmlentities($value, ENT_QUOTES, 'UTF-8', false) . '"';
$element = $key . '="' . htmlentities((string) $value, ENT_QUOTES, 'UTF-8', false) . '"';
}
$html .= ' ' . $element;
@@ -191,7 +191,7 @@ trait AssetUtilsTrait
{
$querystring = '';
$asset = $asset ?? $this->asset;
$asset ??= $this->asset;
$attributes = $this->attributes;
if (!empty($this->query)) {

View File

@@ -113,7 +113,7 @@ trait LegacyAssetsTrait
*/
public function addAsyncJs($asset, $priority = 10, $pipeline = true, $group = 'head')
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use dynamic method with [\'loading\' => \'async\']', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use dynamic method with [\'loading\' => \'async\']', E_USER_DEPRECATED);
return $this->addJs($asset, $priority, $pipeline, 'async', $group);
}
@@ -130,7 +130,7 @@ trait LegacyAssetsTrait
*/
public function addDeferJs($asset, $priority = 10, $pipeline = true, $group = 'head')
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use dynamic method with [\'loading\' => \'defer\']', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use dynamic method with [\'loading\' => \'defer\']', E_USER_DEPRECATED);
return $this->addJs($asset, $priority, $pipeline, 'defer', $group);
}

View File

@@ -338,7 +338,7 @@ trait TestingAssetsTrait
$directory,
FilesystemIterator::SKIP_DOTS
)), $pattern);
$offset = strlen($ltrim);
$offset = strlen((string) $ltrim);
$files = [];
foreach ($iterator as $file) {

View File

@@ -54,7 +54,7 @@ class Backups
/** @var EventDispatcher $dispatcher */
$dispatcher = $grav['events'];
$dispatcher->addListener('onSchedulerInitialized', [$this, 'onSchedulerInitialized']);
$dispatcher->addListener('onSchedulerInitialized', $this->onSchedulerInitialized(...));
$grav->fireEvent('onBackupsInitialized', new Event(['backups' => $this]));
}
@@ -106,7 +106,7 @@ class Backups
{
$param_sep = Grav::instance()['config']->get('system.param_sep', ':');
$download = urlencode(base64_encode(Utils::basename($backup)));
$url = rtrim(Grav::instance()['uri']->rootUrl(true), '/') . '/' . trim(
$url = rtrim((string) Grav::instance()['uri']->rootUrl(true), '/') . '/' . trim(
$base_url,
'/'
) . '/task' . $param_sep . 'backup/download' . $param_sep . $download . '/admin-nonce' . $param_sep . Utils::getNonce('admin-form');
@@ -158,7 +158,7 @@ class Backups
static::$backups = [];
$grav = Grav::instance();
$backups_itr = new GlobIterator(static::$backup_dir . '/*.zip', FilesystemIterator::KEY_AS_FILENAME);
$backups_itr = new GlobIterator(static::$backup_dir . '/*.zip', FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::SKIP_DOTS);
$inflector = $grav['inflector'];
$long_date_format = DATE_RFC2822;
@@ -194,7 +194,7 @@ class Backups
* @param callable|null $status
* @return string|null
*/
public static function backup($id = 0, callable $status = null)
public static function backup($id = 0, ?callable $status = null)
{
$grav = Grav::instance();
@@ -210,7 +210,7 @@ class Backups
$name = $grav['inflector']->underscorize($backup->name);
$date = date(static::BACKUP_DATE_FORMAT, time());
$filename = trim($name, '_') . '--' . $date . '.zip';
$filename = trim((string) $name, '_') . '--' . $date . '.zip';
$destination = static::$backup_dir . DS . $filename;
$max_execution_time = ini_set('max_execution_time', '600');
$backup_root = $backup->root;

View File

@@ -27,7 +27,7 @@ class Browser
{
try {
$this->useragent = parse_user_agent();
} catch (InvalidArgumentException $e) {
} catch (InvalidArgumentException) {
$this->useragent = parse_user_agent("Mozilla/5.0 (compatible; Unknown;)");
}
}

View File

@@ -10,7 +10,8 @@
namespace Grav\Common;
use DirectoryIterator;
use \Doctrine\Common\Cache as DoctrineCache;
use Doctrine\Common\Cache\CacheProvider;
use Doctrine\Common\Cache\Psr6\DoctrineProvider;
use Exception;
use Grav\Common\Config\Config;
use Grav\Common\Filesystem\Folder;
@@ -18,6 +19,12 @@ use Grav\Common\Scheduler\Scheduler;
use LogicException;
use Psr\SimpleCache\CacheInterface;
use RocketTheme\Toolbox\Event\Event;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\MemcachedAdapter;
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\Psr16Cache;
use Symfony\Component\EventDispatcher\EventDispatcher;
use function dirname;
use function extension_loaded;
@@ -27,12 +34,11 @@ use function is_array;
/**
* The GravCache object is used throughout Grav to store and retrieve cached data.
* It uses DoctrineCache library and supports a variety of caching mechanisms. Those include:
* It uses Symfony library (adding backward compatibility to Doctrine Cache) and supports a variety of caching mechanisms. Those include:
*
* APCu
* RedisCache
* MemCache
* MemCacheD
* MemCached
* FileSystem
*/
class Cache extends Getters
@@ -49,7 +55,10 @@ class Cache extends Getters
/** @var Config $config */
protected $config;
/** @var DoctrineCache\CacheProvider */
/** @var AdapterInterface */
protected $adapter;
/** @var CacheProvider */
protected $driver;
/** @var CacheInterface */
@@ -70,6 +79,7 @@ class Cache extends Getters
protected static $standard_remove = [
'cache://twig/',
'cache://doctrine/',
'cache://grav/',
'cache://compiled/',
'cache://clockwork/',
'cache://validated-',
@@ -80,6 +90,7 @@ class Cache extends Getters
protected static $standard_remove_no_images = [
'cache://twig/',
'cache://doctrine/',
'cache://grav/',
'cache://compiled/',
'cache://clockwork/',
'cache://validated-',
@@ -142,14 +153,14 @@ class Cache extends Getters
// Cache key allows us to invalidate all cache on configuration changes.
$this->key = ($prefix ?: 'g') . '-' . $uniqueness;
$this->cache_dir = $grav['locator']->findResource('cache://doctrine/' . $uniqueness, true, true);
$this->cache_dir = $grav['locator']->findResource('cache://grav/' . $uniqueness, true, true);
$this->driver_setting = $this->config->get('system.cache.driver');
$this->driver = $this->getCacheDriver();
$this->driver->setNamespace($this->key);
$this->adapter = $this->getCacheAdapter();
$this->driver = $this->getCacheDriver($this->adapter);
/** @var EventDispatcher $dispatcher */
$dispatcher = Grav::instance()['events'];
$dispatcher->addListener('onSchedulerInitialized', [$this, 'onSchedulerInitialized']);
$dispatcher->addListener('onSchedulerInitialized', $this->onSchedulerInitialized(...));
}
/**
@@ -158,12 +169,7 @@ class Cache extends Getters
public function getSimpleCache()
{
if (null === $this->simpleCache) {
$cache = new \Grav\Framework\Cache\Adapter\DoctrineCache($this->driver, '', $this->getLifetime());
// Disable cache key validation.
$cache->setValidation(false);
$this->simpleCache = $cache;
$this->simpleCache = new Psr16Cache($this->adapter);
}
return $this->simpleCache;
@@ -280,53 +286,42 @@ class Cache extends Getters
* If there is no config option for $driver in the config, or it's set to 'auto', it will
* pick the best option based on which cache extensions are installed.
*
* @return DoctrineCache\CacheProvider The cache driver to use
* @param string|null $namespace
* @param int|null $defaultLifetime
* @return AdapterInterface The cache driver to use
* @throws \RedisException
* @throws \Symfony\Component\Cache\Exception\CacheException
*/
public function getCacheDriver()
public function getCacheAdapter(?string $namespace = null, ?int $defaultLifetime = null): AdapterInterface
{
$setting = $this->driver_setting;
$setting = $this->driver_setting ?? 'auto';
$driver_name = 'file';
if (in_array($setting, ['apc', 'xcache', 'wincache', 'memcache'], true)) {
throw new LogicException(sprintf('Cache driver for %s has been removed, use auto, file, apcu or memcached instead!', $setting));
}
// CLI compatibility requires a non-volatile cache driver
if ($this->config->get('system.cache.cli_compatibility') && (
$setting === 'auto' || $this->isVolatileDriver($setting))) {
if ($this->config->get('system.cache.cli_compatibility') && ($setting === 'auto' || $this->isVolatileDriver($setting))) {
$setting = $driver_name;
}
if (!$setting || $setting === 'auto') {
if ($setting === 'auto' || $this->isVolatileDriver($setting)) {
if (extension_loaded('apcu')) {
$driver_name = 'apcu';
} elseif (extension_loaded('wincache')) {
$driver_name = 'wincache';
}
} else {
$driver_name = $setting;
}
$this->driver_name = $driver_name;
$namespace ??= $this->key;
$defaultLifetime ??= 0;
switch ($driver_name) {
case 'apc':
case 'apcu':
$driver = new DoctrineCache\ApcuCache();
break;
case 'wincache':
$driver = new DoctrineCache\WinCacheCache();
break;
case 'memcache':
if (extension_loaded('memcache')) {
$memcache = new \Memcache();
$memcache->connect(
$this->config->get('system.cache.memcache.server', 'localhost'),
$this->config->get('system.cache.memcache.port', 11211)
);
$driver = new DoctrineCache\MemcacheCache();
$driver->setMemcache($memcache);
} else {
throw new LogicException('Memcache PHP extension has not been installed');
}
$adapter = new ApcuAdapter($namespace, $defaultLifetime);
break;
case 'memcached':
@@ -336,8 +331,7 @@ class Cache extends Getters
$this->config->get('system.cache.memcached.server', 'localhost'),
$this->config->get('system.cache.memcached.port', 11211)
);
$driver = new DoctrineCache\MemcachedCache();
$driver->setMemcached($memcached);
$adapter = new MemcachedAdapter($memcached, $namespace, $defaultLifetime);
} else {
throw new LogicException('Memcached PHP extension has not been installed');
}
@@ -369,19 +363,39 @@ class Cache extends Getters
throw new \RedisException('Could not select alternate Redis database ID');
}
$driver = new DoctrineCache\RedisCache();
$driver->setRedis($redis);
$adapter = new RedisAdapter($redis, $namespace, $defaultLifetime);
} else {
throw new LogicException('Redis PHP extension has not been installed');
}
break;
default:
$driver = new DoctrineCache\FilesystemCache($this->cache_dir);
$adapter = new FilesystemAdapter($namespace, $defaultLifetime, $this->cache_dir);
break;
}
return $driver;
return $adapter;
}
/**
* Automatically picks the cache mechanism to use. If you pick one manually it will use that
* If there is no config option for $driver in the config, or it's set to 'auto', it will
* pick the best option based on which cache extensions are installed.
*
* @return CacheProvider The cache driver to use
*/
public function getCacheDriver(?AdapterInterface $adapter = null)
{
if (null === $adapter) {
$adapter = $this->getCacheAdapter();
}
$cache = DoctrineProvider::wrap($adapter);
if (!$cache instanceof CacheProvider) {
throw new \RuntimeException('Internal error');
}
return $cache;
}
/**
@@ -523,8 +537,17 @@ class Cache extends Getters
// Delete entries in the doctrine cache if required
if (in_array($remove, ['all', 'standard'])) {
$cache = Grav::instance()['cache'];
$cache->driver->deleteAll();
try {
$grav = Grav::instance();
if ($grav->offsetExists('cache')) {
$cache = $grav['cache'];
if (isset($cache->driver)) {
$cache->driver->deleteAll();
}
}
} catch (\Throwable $e) {
$output[] = 'cache: ' . $e->getMessage();
}
}
// Clearing cache event to add paths to clear
@@ -669,7 +692,7 @@ class Cache extends Getters
*/
public function isVolatileDriver($setting)
{
return in_array($setting, ['apc', 'apcu', 'xcache', 'wincache'], true);
return $setting === 'apcu';
}
/**

View File

@@ -13,7 +13,10 @@ use BadMethodCallException;
use Exception;
use RocketTheme\Toolbox\File\PhpFile;
use RuntimeException;
use function filter_var;
use function function_exists;
use function get_class;
use function ini_get;
use function is_array;
/**
@@ -202,7 +205,7 @@ abstract class CompiledBase
$cache = include $filename;
if (!is_array($cache)
|| !isset($cache['checksum'], $cache['data'], $cache['@class'])
|| $cache['@class'] !== get_class($this)
|| $cache['@class'] !== static::class
) {
return false;
}
@@ -235,7 +238,7 @@ abstract class CompiledBase
// Attempt to lock the file for writing.
try {
$file->lock(false);
} catch (Exception $e) {
} catch (Exception) {
// Another process has locked the file; we will check this in a bit.
}
@@ -245,7 +248,7 @@ abstract class CompiledBase
}
$cache = [
'@class' => get_class($this),
'@class' => static::class,
'timestamp' => time(),
'checksum' => $this->checksum(),
'files' => $this->files,
@@ -254,6 +257,9 @@ abstract class CompiledBase
$file->save($cache);
$file->unlock();
$this->preloadOpcodeCache($file);
$file->free();
$this->modified();
@@ -266,4 +272,40 @@ abstract class CompiledBase
{
return $this->object->toArray();
}
/**
* Ensure compiled cache file is primed into OPcache when available.
*/
protected function preloadOpcodeCache(PhpFile $file): void
{
if (!function_exists('opcache_invalidate') || !$this->isOpcacheEnabled()) {
return;
}
$filename = $file->filename();
if (!$filename) {
return;
}
// Silence errors for restricted functions while keeping best effort behavior.
@opcache_invalidate($filename, true);
if (function_exists('opcache_compile_file')) {
@opcache_compile_file($filename);
}
}
/**
* Detect if OPcache is active for current SAPI.
*/
protected function isOpcacheEnabled(): bool
{
$enabled = filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN);
if (PHP_SAPI === 'cli') {
$enabled = $enabled || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN);
}
return $enabled;
}
}

View File

@@ -149,7 +149,7 @@ class Config extends Data
*/
public function getLanguages()
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.5, use Grav::instance()[\'languages\'] instead', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.5, use Grav::instance()[\'languages\'] instead', E_USER_DEPRECATED);
return Grav::instance()['languages'];
}

View File

@@ -178,9 +178,7 @@ class ConfigFileFinder
'filters' => [
'pre-key' => $this->base,
'key' => $pattern,
'value' => function (RecursiveDirectoryIterator $file) use ($path) {
return ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()];
}
'value' => fn(RecursiveDirectoryIterator $file) => ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()]
],
'key' => 'SubPathname'
];
@@ -254,9 +252,7 @@ class ConfigFileFinder
'filters' => [
'pre-key' => $this->base,
'key' => $pattern,
'value' => function (RecursiveDirectoryIterator $file) use ($path) {
return ["{$path}/{$file->getSubPathname()}" => $file->getMTime()];
}
'value' => fn(RecursiveDirectoryIterator $file) => ["{$path}/{$file->getSubPathname()}" => $file->getMTime()]
],
'key' => 'SubPathname'
];

View File

@@ -202,7 +202,7 @@ class Setup extends Data
$setupFile = defined('GRAV_SETUP_PATH') ? GRAV_SETUP_PATH : (getenv('GRAV_SETUP_PATH') ?: null);
if (null !== $setupFile) {
// Make sure that the custom setup file exists. Terminates the script if not.
if (!str_starts_with($setupFile, '/')) {
if (!str_starts_with((string) $setupFile, '/')) {
$setupFile = GRAV_WEBROOT . '/' . $setupFile;
}
if (!is_file($setupFile)) {

View File

@@ -142,7 +142,7 @@ class Blueprint extends BlueprintForm
{
foreach ($this->dynamic as $key => $data) {
// Locate field.
$path = explode('/', $key);
$path = explode('/', (string) $key);
$current = &$this->items;
foreach ($path as $field) {
@@ -168,7 +168,7 @@ class Blueprint extends BlueprintForm
// Set dynamic property.
foreach ($data as $property => $call) {
$action = $call['action'];
$method = 'dynamic' . ucfirst($action);
$method = 'dynamic' . ucfirst((string) $action);
$call['object'] = $this->object;
if (isset($this->handlers[$action])) {
@@ -434,7 +434,7 @@ class Blueprint extends BlueprintForm
$params = [];
}
[$o, $f] = explode('::', $function, 2);
[$o, $f] = explode('::', (string) $function, 2);
$data = null;
if (!$f) {
@@ -574,10 +574,9 @@ class Blueprint extends BlueprintForm
/**
* @param array $field
* @param string $property
* @param mixed $value
* @return void
*/
public static function addPropertyRecursive(array &$field, $property, $value)
public static function addPropertyRecursive(array &$field, $property, mixed $value)
{
if (is_array($value) && isset($field[$property]) && is_array($field[$property])) {
$field[$property] = array_merge_recursive($field[$property], $value);

View File

@@ -130,7 +130,7 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
foreach ($items as $key => $rules) {
$type = $rules['type'] ?? '';
$ignore = (bool) array_filter((array)($rules['validate']['ignore'] ?? [])) ?? false;
if (!str_starts_with($type, '_') && !str_contains($key, '*') && $ignore !== true) {
if (!str_starts_with((string) $type, '_') && !str_contains((string) $key, '*') && $ignore !== true) {
$list[$prefix . $key] = null;
}
}
@@ -215,7 +215,7 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
// If strings:
if (is_string($currentVal) && is_string($otherVal)) {
$isValid = (strlen($currentVal) && strlen($otherVal) && (str_contains($currentVal,
$otherVal) || strpos($otherVal, $currentVal) !== false));
$otherVal) || str_contains($otherVal, $currentVal)));
}
// If arrays:
if (is_array($currentVal) && is_array($otherVal)) {

View File

@@ -22,8 +22,6 @@ use function is_object;
*/
class Blueprints
{
/** @var array|string */
protected $search;
/** @var array */
protected $types;
/** @var array */
@@ -32,9 +30,8 @@ class Blueprints
/**
* @param string|array $search Search path.
*/
public function __construct($search = 'blueprints://')
public function __construct(protected $search = 'blueprints://')
{
$this->search = $search;
}
/**

View File

@@ -103,7 +103,7 @@ class Data implements DataInterface, ArrayAccess, \Countable, JsonSerializable,
* @return $this
* @throws RuntimeException
*/
public function join($name, $value, $separator = '.')
public function join($name, mixed $value, $separator = '.')
{
$old = $this->get($name, null, $separator);
if ($old !== null) {
@@ -145,7 +145,7 @@ class Data implements DataInterface, ArrayAccess, \Countable, JsonSerializable,
* @param string $separator Separator, defaults to '.'
* @return $this
*/
public function joinDefaults($name, $value, $separator = '.')
public function joinDefaults($name, mixed $value, $separator = '.')
{
if (is_object($value)) {
$value = (array) $value;
@@ -323,7 +323,7 @@ class Data implements DataInterface, ArrayAccess, \Countable, JsonSerializable,
* @param FileInterface|null $storage Optionally enter a new storage.
* @return FileInterface|null
*/
public function file(FileInterface $storage = null)
public function file(?FileInterface $storage = null)
{
if ($storage) {
$this->storage = $storage;

View File

@@ -28,7 +28,7 @@ interface DataInterface
* @param string $separator Separator, defaults to '.'
* @return mixed Value.
*/
public function value($name, $default = null, $separator = '.');
public function value($name, mixed $default = null, $separator = '.');
/**
* Merge external data.
@@ -80,5 +80,5 @@ interface DataInterface
* @param FileInterface|null $storage Optionally enter a new storage.
* @return FileInterface
*/
public function file(FileInterface $storage = null);
public function file(?FileInterface $storage = null);
}

View File

@@ -37,11 +37,10 @@ class Validation
/**
* Validate value against a blueprint field definition.
*
* @param mixed $value
* @param array $field
* @return array
*/
public static function validate($value, array $field)
public static function validate(mixed $value, array $field)
{
if (!isset($field['type'])) {
$field['type'] = 'text';
@@ -78,7 +77,7 @@ class Validation
$messages = [];
$success = method_exists(__CLASS__, $method) ? self::$method($value, $validate, $field) : true;
$success = method_exists(self::class, $method) ? self::$method($value, $validate, $field) : true;
if (!$success) {
$messages[$field['name']][] = $message;
}
@@ -87,7 +86,7 @@ class Validation
foreach ($validate as $rule => $params) {
$method = 'validate' . ucfirst(str_replace('-', '_', $rule));
if (method_exists(__CLASS__, $method)) {
if (method_exists(self::class, $method)) {
$success = self::$method($value, $params);
if (!$success) {
@@ -100,11 +99,10 @@ class Validation
}
/**
* @param mixed $value
* @param array $field
* @return array
*/
public static function checkSafety($value, array $field)
public static function checkSafety(mixed $value, array $field)
{
$messages = [];
@@ -117,7 +115,7 @@ class Validation
$options = [];
}
$name = ucfirst($field['label'] ?? $field['name'] ?? 'UNKNOWN');
$name = ucfirst((string) ($field['label'] ?? $field['name'] ?? 'UNKNOWN'));
/** @var UserInterface $user */
$user = Grav::instance()['user'] ?? null;
@@ -164,7 +162,7 @@ class Validation
* @param UserInterface|null $user
* @return bool
*/
public static function authorize($action, UserInterface $user = null)
public static function authorize($action, ?UserInterface $user = null)
{
if (!$user) {
return false;
@@ -188,11 +186,10 @@ class Validation
/**
* Filter value against a blueprint field definition.
*
* @param mixed $value
* @param array $field
* @return mixed Filtered value.
*/
public static function filter($value, array $field)
public static function filter(mixed $value, array $field)
{
$validate = (array)($field['filter'] ?? $field['validate'] ?? null);
@@ -213,7 +210,7 @@ class Validation
$method = 'filterYaml';
}
if (!method_exists(__CLASS__, $method)) {
if (!method_exists(self::class, $method)) {
$method = isset($field['array']) && $field['array'] === true ? 'filterArray' : 'filterText';
}
@@ -228,7 +225,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeText($value, array $params, array $field)
public static function typeText(mixed $value, array $params, array $field)
{
if (!is_string($value) && !is_numeric($value)) {
return false;
@@ -241,7 +238,7 @@ class Validation
}
$value = preg_replace("/\r\n|\r/um", "\n", $value);
$len = mb_strlen($value);
$len = mb_strlen((string) $value);
$min = (int)($params['min'] ?? 0);
if ($min && $len < $min) {
@@ -260,7 +257,7 @@ class Validation
return false;
}
if (!$multiline && preg_match('/\R/um', $value)) {
if (!$multiline && preg_match('/\R/um', (string) $value)) {
return false;
}
@@ -268,12 +265,11 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return string
*/
protected static function filterText($value, array $params, array $field)
protected static function filterText(mixed $value, array $params, array $field)
{
if (!is_string($value) && !is_numeric($value)) {
return '';
@@ -289,12 +285,11 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return string|null
*/
protected static function filterCheckbox($value, array $params, array $field)
protected static function filterCheckbox(mixed $value, array $params, array $field)
{
$value = (string)$value;
$field_value = (string)($field['value'] ?? '1');
@@ -303,23 +298,21 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return array|array[]|false|string[]
*/
protected static function filterCommaList($value, array $params, array $field)
protected static function filterCommaList(mixed $value, array $params, array $field)
{
return is_array($value) ? $value : preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
return is_array($value) ? $value : preg_split('/\s*,\s*/', (string) $value, -1, PREG_SPLIT_NO_EMPTY);
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return bool
*/
public static function typeCommaList($value, array $params, array $field)
public static function typeCommaList(mixed $value, array $params, array $field)
{
if (!isset($params['max'])) {
$params['max'] = 2048;
@@ -329,34 +322,31 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return array|array[]|false|string[]
*/
protected static function filterLines($value, array $params, array $field)
protected static function filterLines(mixed $value, array $params, array $field)
{
return is_array($value) ? $value : preg_split('/\s*[\r\n]+\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
return is_array($value) ? $value : preg_split('/\s*[\r\n]+\s*/', (string) $value, -1, PREG_SPLIT_NO_EMPTY);
}
/**
* @param mixed $value
* @param array $params
* @return string
*/
protected static function filterLower($value, array $params)
protected static function filterLower(mixed $value, array $params)
{
return mb_strtolower($value);
return mb_strtolower((string) $value);
}
/**
* @param mixed $value
* @param array $params
* @return string
*/
protected static function filterUpper($value, array $params)
protected static function filterUpper(mixed $value, array $params)
{
return mb_strtoupper($value);
return mb_strtoupper((string) $value);
}
@@ -368,7 +358,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeTextarea($value, array $params, array $field)
public static function typeTextarea(mixed $value, array $params, array $field)
{
if (!isset($params['multiline'])) {
$params['multiline'] = true;
@@ -385,7 +375,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typePassword($value, array $params, array $field)
public static function typePassword(mixed $value, array $params, array $field)
{
if (!isset($params['max'])) {
$params['max'] = 256;
@@ -402,7 +392,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeHidden($value, array $params, array $field)
public static function typeHidden(mixed $value, array $params, array $field)
{
return self::typeText($value, $params, $field);
}
@@ -415,7 +405,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeCheckboxes($value, array $params, array $field)
public static function typeCheckboxes(mixed $value, array $params, array $field)
{
// Set multiple: true so checkboxes can easily use min/max counts to control number of options required
$field['multiple'] = true;
@@ -424,12 +414,11 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return array|null
*/
protected static function filterCheckboxes($value, array $params, array $field)
protected static function filterCheckboxes(mixed $value, array $params, array $field)
{
return self::filterArray($value, $params, $field);
}
@@ -442,7 +431,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeCheckbox($value, array $params, array $field)
public static function typeCheckbox(mixed $value, array $params, array $field)
{
$value = (string)$value;
$field_value = (string)($field['value'] ?? '1');
@@ -458,7 +447,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeRadio($value, array $params, array $field)
public static function typeRadio(mixed $value, array $params, array $field)
{
return self::typeArray((array) $value, $params, $field);
}
@@ -471,7 +460,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeToggle($value, array $params, array $field)
public static function typeToggle(mixed $value, array $params, array $field)
{
if (is_bool($value)) {
$value = (int)$value;
@@ -488,18 +477,17 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeFile($value, array $params, array $field)
public static function typeFile(mixed $value, array $params, array $field)
{
return self::typeArray((array)$value, $params, $field);
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return array
*/
protected static function filterFile($value, array $params, array $field)
protected static function filterFile(mixed $value, array $params, array $field)
{
return (array)$value;
}
@@ -512,7 +500,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeSelect($value, array $params, array $field)
public static function typeSelect(mixed $value, array $params, array $field)
{
return self::typeArray((array) $value, $params, $field);
}
@@ -525,7 +513,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeNumber($value, array $params, array $field)
public static function typeNumber(mixed $value, array $params, array $field)
{
if (!is_numeric($value)) {
return false;
@@ -560,23 +548,21 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return float|int
*/
protected static function filterNumber($value, array $params, array $field)
protected static function filterNumber(mixed $value, array $params, array $field)
{
return (string)(int)$value !== (string)(float)$value ? (float)$value : (int)$value;
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return string
*/
protected static function filterDateTime($value, array $params, array $field)
protected static function filterDateTime(mixed $value, array $params, array $field)
{
$format = Grav::instance()['config']->get('system.pages.dateformat.default');
if ($format) {
@@ -594,18 +580,17 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeRange($value, array $params, array $field)
public static function typeRange(mixed $value, array $params, array $field)
{
return self::typeNumber($value, $params, $field);
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return float|int
*/
protected static function filterRange($value, array $params, array $field)
protected static function filterRange(mixed $value, array $params, array $field)
{
return self::filterNumber($value, $params, $field);
}
@@ -618,9 +603,9 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeColor($value, array $params, array $field)
public static function typeColor(mixed $value, array $params, array $field)
{
return (bool)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', (string) $value);
}
/**
@@ -631,7 +616,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeEmail($value, array $params, array $field)
public static function typeEmail(mixed $value, array $params, array $field)
{
if (empty($value)) {
return false;
@@ -641,10 +626,10 @@ class Validation
$params['max'] = 320;
}
$values = !is_array($value) ? explode(',', preg_replace('/\s+/', '', $value)) : $value;
$values = !is_array($value) ? explode(',', (string) preg_replace('/\s+/', '', (string) $value)) : $value;
foreach ($values as $val) {
if (!(self::typeText($val, $params, $field) && strpos($val, '@', 1))) {
if (!(self::typeText($val, $params, $field) && strpos((string) $val, '@', 1))) {
return false;
}
}
@@ -660,7 +645,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeUrl($value, array $params, array $field)
public static function typeUrl(mixed $value, array $params, array $field)
{
if (!isset($params['max'])) {
$params['max'] = 2048;
@@ -677,7 +662,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeDatetime($value, array $params, array $field)
public static function typeDatetime(mixed $value, array $params, array $field)
{
if ($value instanceof DateTime) {
return true;
@@ -702,7 +687,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeDatetimeLocal($value, array $params, array $field)
public static function typeDatetimeLocal(mixed $value, array $params, array $field)
{
return self::typeDatetime($value, $params, $field);
}
@@ -715,7 +700,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeDate($value, array $params, array $field)
public static function typeDate(mixed $value, array $params, array $field)
{
if (!isset($params['format'])) {
$params['format'] = 'Y-m-d';
@@ -732,7 +717,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeTime($value, array $params, array $field)
public static function typeTime(mixed $value, array $params, array $field)
{
if (!isset($params['format'])) {
$params['format'] = 'H:i';
@@ -749,7 +734,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeMonth($value, array $params, array $field)
public static function typeMonth(mixed $value, array $params, array $field)
{
if (!isset($params['format'])) {
$params['format'] = 'Y-m';
@@ -766,9 +751,9 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeWeek($value, array $params, array $field)
public static function typeWeek(mixed $value, array $params, array $field)
{
if (!isset($params['format']) && !preg_match('/^\d{4}-W\d{2}$/u', $value)) {
if (!isset($params['format']) && !preg_match('/^\d{4}-W\d{2}$/u', (string) $value)) {
return false;
}
@@ -783,7 +768,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeArray($value, array $params, array $field)
public static function typeArray(mixed $value, array $params, array $field)
{
if (!is_array($value)) {
return false;
@@ -831,12 +816,11 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return array|null
*/
protected static function filterFlatten_array($value, $params, $field)
protected static function filterFlatten_array(mixed $value, $params, $field)
{
$value = static::filterArray($value, $params, $field);
@@ -844,12 +828,11 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return array|null
*/
protected static function filterArray($value, $params, $field)
protected static function filterArray(mixed $value, $params, $field)
{
$values = (array) $value;
$options = isset($field['options']) ? array_keys($field['options']) : [];
@@ -873,7 +856,7 @@ class Validation
$val = implode(',', $val);
$values[$key] = array_map('trim', explode(',', $val));
} else {
$values[$key] = trim($val);
$values[$key] = trim((string) $val);
}
}
}
@@ -897,16 +880,11 @@ class Validation
{
foreach ($values as $key => &$val) {
if ($params['key_type']) {
switch ($params['key_type']) {
case 'int':
$result = is_int($key);
break;
case 'string':
$result = is_string($key);
break;
default:
$result = false;
}
$result = match ($params['key_type']) {
'int' => is_int($key),
'string' => is_string($key),
default => false,
};
if (!$result) {
unset($values[$key]);
}
@@ -939,7 +917,7 @@ class Validation
$val = (string)$val;
break;
case 'trim':
$val = trim($val);
$val = trim((string) $val);
break;
}
}
@@ -954,12 +932,11 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return bool
*/
public static function typeList($value, array $params, array $field)
public static function typeList(mixed $value, array $params, array $field)
{
if (!is_array($value)) {
return false;
@@ -968,7 +945,7 @@ class Validation
if (isset($field['fields'])) {
foreach ($value as $key => $item) {
foreach ($field['fields'] as $subKey => $subField) {
$subKey = trim($subKey, '.');
$subKey = trim((string) $subKey, '.');
$subValue = $item[$subKey] ?? null;
self::validate($subValue, $subField);
}
@@ -979,22 +956,20 @@ class Validation
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return array
*/
protected static function filterList($value, array $params, array $field)
protected static function filterList(mixed $value, array $params, array $field)
{
return (array) $value;
}
/**
* @param mixed $value
* @param array $params
* @return array
*/
public static function filterYaml($value, $params)
public static function filterYaml(mixed $value, $params)
{
if (!is_string($value)) {
return $value;
@@ -1011,18 +986,17 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeIgnore($value, array $params, array $field)
public static function typeIgnore(mixed $value, array $params, array $field)
{
return true;
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return mixed
*/
public static function filterIgnore($value, array $params, array $field)
public static function filterIgnore(mixed $value, array $params, array $field)
{
return $value;
}
@@ -1035,30 +1009,27 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeUnset($value, array $params, array $field)
public static function typeUnset(mixed $value, array $params, array $field)
{
return true;
}
/**
* @param mixed $value
* @param array $params
* @param array $field
* @return null
*/
public static function filterUnset($value, array $params, array $field)
public static function filterUnset(mixed $value, array $params, array $field)
{
return null;
}
// HTML5 attributes (min, max and range are handled inside the types)
/**
* @param mixed $value
* @param bool $params
* @return bool
*/
public static function validateRequired($value, $params)
public static function validateRequired(mixed $value, $params)
{
if (is_scalar($value)) {
return (bool) $params !== true || $value !== '';
@@ -1068,105 +1039,85 @@ class Validation
}
/**
* @param mixed $value
* @param string $params
* @return bool
*/
public static function validatePattern($value, $params)
public static function validatePattern(mixed $value, $params)
{
return (bool) preg_match("`^{$params}$`u", $value);
return (bool) preg_match("`^{$params}$`u", (string) $value);
}
// Internal types
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateAlpha($value, $params)
public static function validateAlpha(mixed $value, mixed $params)
{
return ctype_alpha($value);
return ctype_alpha((string) $value);
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateAlnum($value, $params)
public static function validateAlnum(mixed $value, mixed $params)
{
return ctype_alnum($value);
return ctype_alnum((string) $value);
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function typeBool($value, $params)
public static function typeBool(mixed $value, mixed $params)
{
return is_bool($value) || $value == 1 || $value == 0;
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateBool($value, $params)
public static function validateBool(mixed $value, mixed $params)
{
return is_bool($value) || $value == 1 || $value == 0;
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
protected static function filterBool($value, $params)
protected static function filterBool(mixed $value, mixed $params)
{
return (bool) $value;
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateDigit($value, $params)
public static function validateDigit(mixed $value, mixed $params)
{
return ctype_digit($value);
return ctype_digit((string) $value);
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateFloat($value, $params)
public static function validateFloat(mixed $value, mixed $params)
{
return is_float(filter_var($value, FILTER_VALIDATE_FLOAT));
}
/**
* @param mixed $value
* @param mixed $params
* @return float
*/
protected static function filterFloat($value, $params)
protected static function filterFloat(mixed $value, mixed $params)
{
return (float) $value;
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateHex($value, $params)
public static function validateHex(mixed $value, mixed $params)
{
return ctype_xdigit($value);
return ctype_xdigit((string) $value);
}
/**
@@ -1177,7 +1128,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeInt($value, array $params, array $field)
public static function typeInt(mixed $value, array $params, array $field)
{
$params['step'] = max(1, (int)($params['step'] ?? 0));
@@ -1185,54 +1136,42 @@ class Validation
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateInt($value, $params)
public static function validateInt(mixed $value, mixed $params)
{
return is_numeric($value) && (int)$value == $value;
}
/**
* @param mixed $value
* @param mixed $params
* @return int
*/
protected static function filterInt($value, $params)
protected static function filterInt(mixed $value, mixed $params)
{
return (int)$value;
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateArray($value, $params)
public static function validateArray(mixed $value, mixed $params)
{
return is_array($value) || ($value instanceof ArrayAccess && $value instanceof Traversable && $value instanceof Countable);
}
/**
* @param mixed $value
* @param mixed $params
* @return array
*/
public static function filterItem_List($value, $params)
public static function filterItem_List(mixed $value, mixed $params)
{
return array_values(array_filter($value, static function ($v) {
return !empty($v);
}));
return array_values(array_filter($value, static fn($v) => !empty($v)));
}
/**
* @param mixed $value
* @param mixed $params
* @return bool
*/
public static function validateJson($value, $params)
public static function validateJson(mixed $value, mixed $params)
{
return (bool) (@json_decode($value));
return (bool) (@json_decode((string) $value));
}
}

View File

@@ -37,7 +37,7 @@ class ValidationException extends RuntimeException implements JsonSerializable
foreach ($messages as $list) {
$list = array_unique($list);
foreach ($list as $message) {
$this->message .= '<br/>' . htmlspecialchars($message, ENT_QUOTES | ENT_HTML5, 'UTF-8');
$this->message .= '<br/>' . htmlspecialchars((string) $message, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
}
@@ -49,7 +49,7 @@ class ValidationException extends RuntimeException implements JsonSerializable
$first = reset($this->messages);
$message = reset($first);
$this->message = $escape ? htmlspecialchars($message, ENT_QUOTES | ENT_HTML5, 'UTF-8') : $message;
$this->message = $escape ? htmlspecialchars((string) $message, ENT_QUOTES | ENT_HTML5, 'UTF-8') : $message;
}
/**

View File

@@ -328,9 +328,7 @@ class Debugger
return new Response(404, $headers, json_encode($response));
}
$data = is_array($data) ? array_map(static function ($item) {
return $item->toArray();
}, $data) : $data->toArray();
$data = is_array($data) ? array_map(static fn($item) => $item->toArray(), $data) : $data->toArray();
return new Response(200, $headers, json_encode($data));
}
@@ -544,7 +542,7 @@ class Debugger
* @param string|null $message
* @return mixed
*/
public function profile(callable $callable, string $message = null)
public function profile(callable $callable, ?string $message = null)
{
$this->startProfiling();
$response = $callable();
@@ -585,7 +583,7 @@ class Debugger
* @param string|null $message
* @return array|null
*/
public function stopProfiling(string $message = null): ?array
public function stopProfiling(?string $message = null): ?array
{
$timings = null;
if ($this->enabled && extension_loaded('tideways_xhprof')) {
@@ -619,17 +617,13 @@ class Debugger
protected function buildProfilerTimings(array $timings): array
{
// Filter method calls which take almost no time.
$timings = array_filter($timings, function ($value) {
return $value['wt'] > 50;
});
$timings = array_filter($timings, fn($value) => $value['wt'] > 50);
uasort($timings, function (array $a, array $b) {
return $b['wt'] <=> $a['wt'];
});
uasort($timings, fn(array $a, array $b) => $b['wt'] <=> $a['wt']);
$table = [];
foreach ($timings as $key => $timing) {
$parts = explode('==>', $key);
$parts = explode('==>', (string) $key);
$method = $this->parseProfilerCall(array_pop($parts));
$context = $this->parseProfilerCall(array_pop($parts));
@@ -639,7 +633,7 @@ class Debugger
}
// Do not profile library calls.
if (strpos($context, 'Grav\\') !== 0) {
if (!str_starts_with((string) $context, 'Grav\\')) {
continue;
}
@@ -721,12 +715,11 @@ class Debugger
/**
* Dump variables into the Messages tab of the Debug Bar
*
* @param mixed $message
* @param string $label
* @param mixed|bool $isString
* @return $this
*/
public function addMessage($message, $label = 'info', $isString = true)
public function addMessage(mixed $message, $label = 'info', $isString = true)
{
if ($this->enabled) {
if ($this->censored) {
@@ -776,10 +769,10 @@ class Debugger
* @param float|null $time
* @return $this
*/
public function addEvent(string $name, $event, EventDispatcherInterface $dispatcher, float $time = null)
public function addEvent(string $name, $event, EventDispatcherInterface $dispatcher, ?float $time = null)
{
if ($this->enabled && $this->clockwork) {
$time = $time ?? microtime(true);
$time ??= microtime(true);
$duration = (microtime(true) - $time) * 1000;
$data = null;
@@ -829,7 +822,7 @@ class Debugger
public function setErrorHandler()
{
$this->errorHandler = set_error_handler(
[$this, 'deprecatedErrorHandler']
$this->deprecatedErrorHandler(...)
);
}
@@ -858,7 +851,7 @@ class Debugger
$scope = 'unknown';
if (stripos($errstr, 'grav') !== false) {
$scope = 'grav';
} elseif (strpos($errfile, '/twig/') !== false) {
} elseif (str_contains($errfile, '/twig/')) {
$scope = 'twig';
// TODO: remove when upgrading to Twig 2+
if (str_contains($errstr, '#[\ReturnTypeWillChange]') || str_contains($errstr, 'Passing null to parameter')) {
@@ -866,7 +859,7 @@ class Debugger
}
} elseif (stripos($errfile, '/yaml/') !== false) {
$scope = 'yaml';
} elseif (strpos($errfile, '/vendor/') !== false) {
} elseif (str_contains($errfile, '/vendor/')) {
$scope = 'vendor';
}
@@ -912,7 +905,7 @@ class Debugger
} elseif (is_scalar($arg)) {
$arg = $arg;
} elseif (is_object($arg)) {
$arg = get_class($arg) . ' $object';
$arg = $arg::class . ' $object';
} elseif (is_array($arg)) {
$arg = '$array';
} else {
@@ -931,14 +924,13 @@ class Debugger
if ($object instanceof TemplateWrapper) {
$reflection = new ReflectionObject($object);
$property = $reflection->getProperty('template');
$property->setAccessible(true);
$object = $property->getValue($object);
}
if ($object instanceof Template) {
$file = $current['file'] ?? null;
if (preg_match('`(Template.php|TemplateWrapper.php)$`', $file)) {
if (preg_match('`(Template.php|TemplateWrapper.php)$`', (string) $file)) {
$current = null;
continue;
}
@@ -998,7 +990,7 @@ class Debugger
if (!isset($current['file'])) {
continue;
}
if (strpos($current['file'], '/vendor/') !== false) {
if (str_contains($current['file'], '/vendor/')) {
$cut = $i + 1;
continue;
}
@@ -1073,7 +1065,7 @@ class Debugger
/** @var array $deprecated */
foreach ($this->deprecations as $deprecated) {
list($message, $scope) = $this->getDepracatedMessage($deprecated);
[$message, $scope] = $this->getDepracatedMessage($deprecated);
$collector->addMessage($message, $scope);
}
@@ -1140,7 +1132,7 @@ class Debugger
protected function resolveCallable(callable $callable)
{
if (is_array($callable)) {
return get_class($callable[0]) . '->' . $callable[1] . '()';
return $callable[0]::class . '->' . $callable[1] . '()';
}
return 'unknown';

View File

@@ -70,7 +70,7 @@ class Errors
$logger = $grav['log'];
$whoops->pushHandler(function ($exception, $inspector, $run) use ($logger) {
try {
$logger->addCritical($exception->getMessage() . ' - Trace: ' . $exception->getTraceAsString());
$logger->critical($exception->getMessage() . ' - Trace: ' . $exception->getTraceAsString());
} catch (Exception $e) {
echo $e;
}

View File

@@ -54,11 +54,7 @@ class SimplePageHandler extends Handler
$code = Misc::translateErrorCode($code);
}
$vars = array(
'stylesheet' => file_get_contents($cssFile),
'code' => $code,
'message' => htmlspecialchars(strip_tags(rawurldecode($message)), ENT_QUOTES, 'UTF-8'),
);
$vars = ['stylesheet' => file_get_contents($cssFile), 'code' => $code, 'message' => htmlspecialchars(strip_tags(rawurldecode($message)), ENT_QUOTES, 'UTF-8')];
$helper->setVariables($vars);
$helper->render($templateFile);

View File

@@ -28,28 +28,27 @@ trait CompiledFile
/**
* Get/set parsed file contents.
*
* @param mixed $var
* @return array
*/
public function content($var = null)
public function content(mixed $var = null)
{
try {
$filename = $this->filename;
// If nothing has been loaded, attempt to get pre-compiled version of the file first.
if ($var === null && $this->raw === null && $this->content === null) {
$key = md5($filename);
$key = md5((string) $filename);
$file = PhpFile::instance(CACHE_DIR . "compiled/files/{$key}{$this->extension}.php");
$modified = $this->modified();
if (!$modified) {
try {
return $this->decode($this->raw());
} catch (Throwable $e) {
} catch (Throwable) {
// If the compiled file is broken, we can safely ignore the error and continue.
}
}
$class = get_class($this);
$class = $this::class;
$size = filesize($filename);
$cache = $file->exists() ? $file->content() : null;
@@ -115,7 +114,7 @@ trait CompiledFile
* @return void
* @throws RuntimeException
*/
public function save($data = null)
public function save(mixed $data = null)
{
// Make sure that the cache file is always up to date!
$key = md5($this->filename);
@@ -135,7 +134,7 @@ trait CompiledFile
if ($locked) {
$modified = $this->modified();
$filename = $this->filename;
$class = get_class($this);
$class = $this::class;
$size = filesize($filename);
// windows doesn't play nicely with this as it can't read when locked

View File

@@ -75,21 +75,21 @@ abstract class Archiver
* @param callable|null $status
* @return $this
*/
abstract public function compress($folder, callable $status = null);
abstract public function compress($folder, ?callable $status = null);
/**
* @param string $destination
* @param callable|null $status
* @return $this
*/
abstract public function extract($destination, callable $status = null);
abstract public function extract($destination, ?callable $status = null);
/**
* @param array $folders
* @param callable|null $status
* @return $this
*/
abstract public function addEmptyFolders($folders, callable $status = null);
abstract public function addEmptyFolders($folders, ?callable $status = null);
/**
* @param string $rootPath

View File

@@ -153,8 +153,8 @@ abstract class Folder
if ($base) {
$base = preg_replace('![\\\/]+!', '/', $base);
$path = preg_replace('![\\\/]+!', '/', $path);
if (strpos($path, $base) === 0) {
$path = ltrim(substr($path, strlen($base)), '/');
if (str_starts_with((string) $path, (string) $base)) {
$path = ltrim(substr((string) $path, strlen((string) $base)), '/');
}
}
@@ -178,8 +178,8 @@ abstract class Folder
return '';
}
$baseParts = explode('/', ltrim($base, '/'));
$pathParts = explode('/', ltrim($path, '/'));
$baseParts = explode('/', ltrim((string) $base, '/'));
$pathParts = explode('/', ltrim((string) $path, '/'));
array_pop($baseParts);
$lastPart = array_pop($pathParts);
@@ -194,7 +194,7 @@ abstract class Folder
$path = str_repeat('../', count($baseParts)) . implode('/', $pathParts);
return '' === $path
|| strpos($path, '/') === 0
|| str_starts_with($path, '/')
|| false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
? "./$path" : $path;
}
@@ -266,7 +266,7 @@ abstract class Folder
/** @var RecursiveDirectoryIterator $file */
foreach ($iterator as $file) {
// Ignore hidden files.
if (strpos($file->getFilename(), '.') === 0 && $file->isFile()) {
if (str_starts_with($file->getFilename(), '.') && $file->isFile()) {
continue;
}
if (!$folders && $file->isDir()) {
@@ -275,7 +275,7 @@ abstract class Folder
if (!$files && $file->isFile()) {
continue;
}
if ($compare && $pattern && !preg_match($pattern, $file->{$compare}())) {
if ($compare && $pattern && !preg_match($pattern, (string) $file->{$compare}())) {
continue;
}
$fileKey = $key ? $file->{$key}() : null;
@@ -283,14 +283,14 @@ abstract class Folder
if ($filters) {
if (isset($filters['key'])) {
$pre = !empty($filters['pre-key']) ? $filters['pre-key'] : '';
$fileKey = $pre . preg_replace($filters['key'], '', $fileKey);
$fileKey = $pre . preg_replace($filters['key'], '', (string) $fileKey);
}
if (isset($filters['value'])) {
$filter = $filters['value'];
if (is_callable($filter)) {
$filePath = $filter($file);
} else {
$filePath = preg_replace($filter, '', $filePath);
$filePath = preg_replace($filter, '', (string) $filePath);
}
}
}
@@ -331,7 +331,7 @@ abstract class Folder
// Go through all sub-directories and copy everything.
$files = self::all($source);
foreach ($files as $file) {
if ($ignore && preg_match($ignore, $file)) {
if ($ignore && preg_match($ignore, (string) $file)) {
continue;
}
$src = $source .'/'. $file;
@@ -377,7 +377,7 @@ abstract class Folder
return;
}
if (strpos($target, $source . '/') === 0) {
if (str_starts_with($target, $source . '/')) {
throw new RuntimeException('Cannot move folder to itself');
}

View File

@@ -63,8 +63,8 @@ class RecursiveDirectoryFilterIterator extends RecursiveFilterIterator
}
// Check if any parent directory is in the ignore list
foreach ($this::$ignore_folders as $ignore_folder) {
$ignore_folder = trim($ignore_folder, '/');
if (strpos($relative_filename, $ignore_folder . '/') === 0 || $relative_filename === $ignore_folder) {
$ignore_folder = trim((string) $ignore_folder, '/');
if (str_starts_with($relative_filename, $ignore_folder . '/') || $relative_filename === $ignore_folder) {
return false;
}
}
@@ -92,12 +92,12 @@ class RecursiveDirectoryFilterIterator extends RecursiveFilterIterator
return true;
}
// Check for extension patterns like .pdf
if (strpos($pattern, '.') === 0 && substr($filename, -strlen($pattern)) === $pattern) {
if (str_starts_with((string) $pattern, '.') && str_ends_with($filename, (string) $pattern)) {
return true;
}
// Check for wildcard patterns
if (strpos($pattern, '*') !== false) {
$regex = '/^' . str_replace('\\*', '.*', preg_quote($pattern, '/')) . '$/';
if (str_contains((string) $pattern, '*')) {
$regex = '/^' . str_replace('\\*', '.*', preg_quote((string) $pattern, '/')) . '$/';
if (preg_match($regex, $filename)) {
return true;
}

View File

@@ -26,7 +26,7 @@ class ZipArchiver extends Archiver
* @param callable|null $status
* @return $this
*/
public function extract($destination, callable $status = null)
public function extract($destination, ?callable $status = null)
{
$zip = new ZipArchive();
$archive = $zip->open($this->archive_file);
@@ -51,7 +51,7 @@ class ZipArchiver extends Archiver
* @param callable|null $status
* @return $this
*/
public function compress($source, callable $status = null)
public function compress($source, ?callable $status = null)
{
if (!extension_loaded('zip')) {
throw new InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');
@@ -90,7 +90,7 @@ class ZipArchiver extends Archiver
foreach ($files as $file) {
$filePath = $file->getPathname();
$relativePath = ltrim(substr($filePath, strlen($rootPath)), '/');
$relativePath = ltrim(substr((string) $filePath, strlen($rootPath)), '/');
if ($file->isDir()) {
$zip->addEmptyDir($relativePath);
@@ -118,7 +118,7 @@ class ZipArchiver extends Archiver
* @param callable|null $status
* @return $this
*/
public function addEmptyFolders($folders, callable $status = null)
public function addEmptyFolders($folders, ?callable $status = null)
{
if (!extension_loaded('zip')) {
throw new InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');

View File

@@ -32,7 +32,7 @@ abstract class FlexObject extends \Grav\Framework\Flex\FlexObject implements Med
* {@inheritdoc}
* @see FlexObjectInterface::getFormValue()
*/
public function getFormValue(string $name, $default = null, string $separator = null)
public function getFormValue(string $name, $default = null, ?string $separator = null)
{
$value = $this->getNestedProperty($name, null, $separator);

View File

@@ -35,7 +35,7 @@ trait FlexCollectionTrait
'collection' => $this
]);
}
if (strpos($name, 'onFlexCollection') !== 0 && strpos($name, 'on') === 0) {
if (!str_starts_with($name, 'onFlexCollection') && str_starts_with($name, 'on')) {
$name = 'onFlexCollection' . substr($name, 2);
}

View File

@@ -46,7 +46,7 @@ trait FlexObjectTrait
if (isset($events['name'])) {
$name = $events['name'];
} elseif (strpos($name, 'onFlexObject') !== 0 && strpos($name, 'on') === 0) {
} elseif (!str_starts_with($name, 'onFlexObject') && str_starts_with($name, 'on')) {
$name = 'onFlexObject' . substr($name, 2);
}

View File

@@ -172,7 +172,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @return static
* @phpstan-return static<T>
*/
public function merge(PageCollectionInterface $collection)
public function merge(PageCollectionInterface $collection): never
{
throw new RuntimeException(__METHOD__ . '(): Not Implemented');
}
@@ -184,7 +184,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @return static
* @phpstan-return static<T>
*/
public function intersect(PageCollectionInterface $collection)
public function intersect(PageCollectionInterface $collection): never
{
throw new RuntimeException(__METHOD__ . '(): Not Implemented');
}
@@ -242,7 +242,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @return static
* @phpstan-return static<T>
*/
public function append($items)
public function append($items): never
{
throw new RuntimeException(__METHOD__ . '(): Not Implemented');
}
@@ -303,7 +303,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
// do this header query work only once
$header_query = null;
$header_default = null;
if (strpos($order_by, 'header.') === 0) {
if (str_starts_with($order_by, 'header.')) {
$query = explode('|', str_replace('header.', '', $order_by), 2);
$header_query = array_shift($query) ?? '';
$header_default = array_shift($query);
@@ -373,9 +373,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
if ($col) {
$col->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
if (($sort_flags & SORT_NATURAL) === SORT_NATURAL) {
$list = preg_replace_callback('~([0-9]+)\.~', static function ($number) {
return sprintf('%032d.', $number[0]);
}, $list);
$list = preg_replace_callback('~([0-9]+)\.~', static fn($number) => sprintf('%032d.', $number[0]), $list);
if (!is_array($list)) {
throw new RuntimeException('Internal Error');
}
@@ -457,7 +455,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
continue;
}
$date = $field ? strtotime($object->getNestedProperty($field)) : $object->date();
$date = $field ? strtotime((string) $object->getNestedProperty($field)) : $object->date();
if ((!$start || $date >= $start) && (!$end || $date <= $end)) {
$entries[$key] = $object;
@@ -766,7 +764,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @return static
* @phpstan-return static<T>
*/
public function withTranslation(bool $bool = true, string $languageCode = null, bool $fallback = null)
public function withTranslation(bool $bool = true, ?string $languageCode = null, ?bool $fallback = null)
{
$list = array_keys(array_filter($this->call('hasTranslation', [$languageCode, $fallback])));
@@ -778,7 +776,7 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
* @param bool|null $fallback
* @return PageIndex
*/
public function withTranslated(string $languageCode = null, bool $fallback = null)
public function withTranslated(?string $languageCode = null, ?bool $fallback = null)
{
return $this->getIndex()->withTranslated($languageCode, $fallback);
}

View File

@@ -57,7 +57,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
public const ORDER_LIST_REGEX = '/(\/\d+)\.[^\/]+/u';
public const PAGE_ROUTE_REGEX = '/\/\d+\./u';
/** @var PageObject|array */
/** @var T|array */
protected $_root;
/** @var array|null */
protected $_params;
@@ -66,7 +66,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param array $entries
* @param FlexDirectory|null $directory
*/
public function __construct(array $entries = [], FlexDirectory $directory = null)
public function __construct(array $entries = [], ?FlexDirectory $directory = null)
{
// Remove root if it's taken.
if (isset($entries[''])) {
@@ -181,7 +181,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @return static
* @phpstan-return static<T,C>
*/
public function withTranslated(string $languageCode = null, bool $fallback = null)
public function withTranslated(?string $languageCode = null, ?bool $fallback = null)
{
if (null === $languageCode) {
return $this;
@@ -239,10 +239,9 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* Set a parameter to the Collection
*
* @param string $name
* @param mixed $value
* @return $this
*/
public function setParam(string $name, $value)
public function setParam(string $name, mixed $value)
{
$this->_params[$name] = $value;
@@ -413,7 +412,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @return static
* @phpstan-return static<T,C>
*/
protected function createFrom(array $entries, string $keyField = null)
protected function createFrom(array $entries, ?string $keyField = null)
{
/** @var static $index */
$index = parent::createFrom($entries, $keyField);
@@ -428,7 +427,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param bool|null $fallback
* @return array
*/
protected function translateEntries(array $entries, string $lang, bool $fallback = null): array
protected function translateEntries(array $entries, string $lang, ?bool $fallback = null): array
{
$languages = $this->getFallbackLanguages($lang, $fallback);
foreach ($entries as $key => &$entry) {
@@ -493,9 +492,9 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param bool|null $fallback
* @return array
*/
protected function getFallbackLanguages(string $languageCode = null, bool $fallback = null): array
protected function getFallbackLanguages(?string $languageCode = null, ?bool $fallback = null): array
{
$fallback = $fallback ?? true;
$fallback ??= true;
if (!$fallback && null !== $languageCode) {
return [$languageCode];
}
@@ -504,7 +503,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
/** @var Language $language */
$language = $grav['language'];
$languageCode = $languageCode ?? '';
$languageCode ??= '';
if ($languageCode === '' && $fallback) {
return $language->getFallbackLanguages(null, true);
}
@@ -533,7 +532,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
// Handle leaf_route
$leaf = null;
if ($leaf_route && $route !== $leaf_route) {
$nodes = explode('/', $leaf_route);
$nodes = explode('/', (string) $leaf_route);
$sub_route = '/' . implode('/', array_slice($nodes, 1, $options['level']++));
$options['route'] = $sub_route;
@@ -544,7 +543,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
if (!$route) {
$page = $this->getRoot();
} else {
$page = $this->get(trim($route, '/'));
$page = $this->get(trim((string) $route, '/'));
}
$path = $page ? $page->path() : null;
@@ -558,7 +557,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
// Clean up filter.
$filter_type = (array)($filters['type'] ?? []);
unset($filters['type']);
$filters = array_filter($filters, static function($val) { return $val !== null && $val !== ''; });
$filters = array_filter($filters, static fn($val) => $val !== null && $val !== '');
if ($page) {
$status = 'success';
@@ -682,9 +681,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
'tags' => $tags,
'actions' => $this->getListingActions($child, $user),
];
$extras = array_filter($extras, static function ($v) {
return $v !== null;
});
$extras = array_filter($extras, static fn($v) => $v !== null);
/** @var PageIndex $tmp */
$tmp = $child->children()->getIndex();
@@ -698,7 +695,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
'title' => htmlspecialchars($child->menu()),
'route' => [
'display' => htmlspecialchars($route) ?: null,
'raw' => htmlspecialchars($child->rawRoute()),
'raw' => htmlspecialchars((string) $child->rawRoute()),
],
'modified' => $this->jsDate($child->modified()),
'child_count' => $child_count ?: null,
@@ -706,9 +703,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
'filters_hit' => $filters ? ($child->filterBy($filters, false) ?: null) : null,
'extras' => $extras
];
$payload = array_filter($payload, static function ($v) {
return $v !== null;
});
$payload = array_filter($payload, static fn($v) => $v !== null);
}
// Add children if any
@@ -781,7 +776,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
* @param int|null $timestamp
* @return string|null
*/
private function jsDate(int $timestamp = null): ?string
private function jsDate(?int $timestamp = null): ?string
{
if (!$timestamp) {
return null;

View File

@@ -129,7 +129,7 @@ class PageObject extends FlexPageObject
/**
* @inheritdoc PageInterface
*/
public function getFormValue(string $name, $default = null, string $separator = null)
public function getFormValue(string $name, $default = null, ?string $separator = null)
{
$test = new stdClass();
@@ -261,7 +261,7 @@ class PageObject extends FlexPageObject
/**
* @param UserInterface|null $user
*/
public function check(UserInterface $user = null): void
public function check(?UserInterface $user = null): void
{
parent::check($user);
@@ -521,7 +521,7 @@ class PageObject extends FlexPageObject
$template = $this->getProperty('template') . ($name ? '.' . $name : '');
$blueprint = $this->getFlexDirectory()->getBlueprint($template, 'blueprints://pages');
} catch (RuntimeException $e) {
} catch (RuntimeException) {
$template = 'default' . ($name ? '.' . $name : '');
$blueprint = $this->getFlexDirectory()->getBlueprint($template, 'blueprints://pages');
@@ -554,7 +554,7 @@ class PageObject extends FlexPageObject
$initial = $options['initial'] ?? null;
$var = $initial ? 'leaf_route' : 'route';
$route = $options[$var] ?? '';
if ($route !== '' && !str_starts_with($route, '/')) {
if ($route !== '' && !str_starts_with((string) $route, '/')) {
$filesystem = Filesystem::getInstance();
$route = "/{$this->getKey()}/{$route}";
@@ -600,7 +600,7 @@ class PageObject extends FlexPageObject
$matches = $test->search((string)$value) > 0.0;
break;
case 'page_type':
$types = $value ? explode(',', $value) : [];
$types = $value ? explode(',', (string) $value) : [];
$matches = in_array($test->template(), $types, true);
break;
case 'extension':
@@ -698,7 +698,7 @@ class PageObject extends FlexPageObject
} elseif (array_key_exists('ordering', $elements) && array_key_exists('order', $elements)) {
// Store ordering.
$ordering = $elements['order'] ?? null;
$this->_reorder = !empty($ordering) ? explode(',', $ordering) : [];
$this->_reorder = !empty($ordering) ? explode(',', (string) $ordering) : [];
$order = false;
if ((bool)($elements['ordering'] ?? false)) {

View File

@@ -394,14 +394,14 @@ class PageStorage extends FolderStorage
if ($oldFolder !== $newFolder && file_exists($oldFolder)) {
$isCopy = $row['__META']['copy'] ?? false;
if ($isCopy) {
if (strpos($newFolder, $oldFolder . '/') === 0) {
if (str_starts_with($newFolder, $oldFolder . '/')) {
throw new RuntimeException(sprintf('Page /%s cannot be copied to itself', $oldKey));
}
$this->copyRow($oldKey, $newKey);
$debugger->addMessage("Page copied: {$oldFolder} => {$newFolder}", 'debug');
} else {
if (strpos($newFolder, $oldFolder . '/') === 0) {
if (str_starts_with($newFolder, $oldFolder . '/')) {
throw new RuntimeException(sprintf('Page /%s cannot be moved to itself', $oldKey));
}
@@ -538,7 +538,7 @@ class PageStorage extends FolderStorage
if ($reload || !isset($this->meta[$key])) {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if (mb_strpos($key, '@@') === false) {
if (mb_strpos((string) $key, '@@') === false) {
$path = $this->getStoragePath($key);
if (is_string($path)) {
$path = $locator->isStream($path) ? $locator->findResource($path) : GRAV_ROOT . "/{$path}";

View File

@@ -32,7 +32,7 @@ trait PageRoutableTrait
* @return PageInterface|null the parent page object if it exists.
*/
public function parent(PageInterface $var = null)
public function parent(?PageInterface $var = null)
{
if (Utils::isAdminPlugin()) {
return parent::parent();

View File

@@ -92,9 +92,7 @@ trait PageTranslateTrait
$list[$languageCode ?: $defaultCode] = $route ?? '';
}
$list = array_filter($list, static function ($var) {
return null !== $var;
});
$list = array_filter($list, static fn($var) => null !== $var);
// Hack to get the same result as with old pages.
foreach ($list as &$path) {

View File

@@ -38,7 +38,7 @@ class UserGroupCollection extends FlexCollection
* @param string|null $scope
* @return bool|null
*/
public function authorize(string $action, string $scope = null): ?bool
public function authorize(string $action, ?string $scope = null): ?bool
{
$authorized = null;
/** @var UserGroupObject $object */

View File

@@ -57,7 +57,7 @@ class UserGroupObject extends FlexObject implements UserGroupInterface
* @param string|null $scope
* @return bool|null
*/
public function authorize(string $action, string $scope = null): ?bool
public function authorize(string $action, ?string $scope = null): ?bool
{
if ($scope === 'test') {
$scope = null;
@@ -100,10 +100,9 @@ class UserGroupObject extends FlexObject implements UserGroupInterface
}
/**
* @param mixed $value
* @return array
*/
protected function offsetLoad_access($value): array
protected function offsetLoad_access(mixed $value): array
{
if (!$value instanceof Access) {
$value = new Access($value);
@@ -115,10 +114,9 @@ class UserGroupObject extends FlexObject implements UserGroupInterface
}
/**
* @param mixed $value
* @return array
*/
protected function offsetPrepare_access($value): array
protected function offsetPrepare_access(mixed $value): array
{
return $this->offsetLoad_access($value);
}

View File

@@ -23,7 +23,7 @@ class UserFileStorage extends FileStorage
* {@inheritdoc}
* @see FlexStorageInterface::getMediaPath()
*/
public function getMediaPath(string $key = null): ?string
public function getMediaPath(?string $key = null): ?string
{
// There is no media support for file storage (fallback to common location).
return null;

View File

@@ -30,7 +30,7 @@ trait UserObjectLegacyTrait
*/
public function merge(array $data)
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->update($data) method instead', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->update($data) method instead', E_USER_DEPRECATED);
$this->setElements($this->getBlueprint()->mergeData($this->toArray(), $data));
@@ -45,7 +45,7 @@ trait UserObjectLegacyTrait
*/
public function getAvatarMedia()
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getAvatarImage() method instead', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getAvatarImage() method instead', E_USER_DEPRECATED);
return $this->getAvatarImage();
}
@@ -58,7 +58,7 @@ trait UserObjectLegacyTrait
*/
public function avatarUrl()
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getAvatarUrl() method instead', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getAvatarUrl() method instead', E_USER_DEPRECATED);
return $this->getAvatarUrl();
}
@@ -73,7 +73,7 @@ trait UserObjectLegacyTrait
*/
public function authorise($action)
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.5, use ->authorize() method instead', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.5, use ->authorize() method instead', E_USER_DEPRECATED);
return $this->authorize($action) ?? false;
}
@@ -87,7 +87,7 @@ trait UserObjectLegacyTrait
#[\ReturnTypeWillChange]
public function count()
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6', E_USER_DEPRECATED);
return count($this->jsonSerialize());
}

View File

@@ -67,7 +67,7 @@ class UserIndex extends FlexIndex implements UserCollectionInterface
// Username can also be number and stored as such.
$key = (string)($data['username'] ?? $meta['key'] ?? $meta['storage_key']);
$meta['key'] = static::filterUsername($key, $storage);
$meta['email'] = isset($data['email']) ? mb_strtolower($data['email']) : null;
$meta['email'] = isset($data['email']) ? mb_strtolower((string) $data['email']) : null;
}
/**
@@ -197,7 +197,7 @@ class UserIndex extends FlexIndex implements UserCollectionInterface
/** @var Logger $logger */
$logger = $grav['log'];
$logger->addDebug($message);
$logger->debug($message);
/** @var Debugger $debugger */
$debugger = $grav['debugger'];

View File

@@ -92,9 +92,9 @@ class UserObject extends FlexObject implements UserInterface, Countable
protected $_uploads_original;
/** @var FileInterface|null */
protected $_storage;
/** @var UserGroupIndex */
/** @var UserGroupIndex|null */
protected $_groups;
/** @var Access */
/** @var Access|null */
protected $_access;
/** @var array|null */
protected $access;
@@ -270,7 +270,7 @@ class UserObject extends FlexObject implements UserInterface, Countable
* @param string|null $scope
* @return bool|null
*/
public function authorize(string $action, string $scope = null): ?bool
public function authorize(string $action, ?string $scope = null): ?bool
{
if ($scope === 'test') {
// Special scope to test user permissions.
@@ -286,7 +286,7 @@ class UserObject extends FlexObject implements UserInterface, Countable
return false;
}
if (strpos($action, 'login') === false && !$this->getProperty('authorized')) {
if (!str_contains($action, 'login') && !$this->getProperty('authorized')) {
// User needs to be authorized (2FA).
return false;
}
@@ -401,7 +401,7 @@ class UserObject extends FlexObject implements UserInterface, Countable
*/
public function join($name, $value, $separator = null)
{
$separator = $separator ?? '.';
$separator ??= '.';
$old = $this->get($name, null, $separator);
if ($old !== null) {
if (!is_array($old)) {
@@ -557,7 +557,7 @@ class UserObject extends FlexObject implements UserInterface, Countable
* @param FileInterface|null $storage Optionally enter a new storage.
* @return FileInterface|null
*/
public function file(FileInterface $storage = null)
public function file(?FileInterface $storage = null)
{
if (null !== $storage) {
$this->_storage = $storage;
@@ -1027,10 +1027,9 @@ class UserObject extends FlexObject implements UserInterface, Countable
}
/**
* @param mixed $value
* @return array
*/
protected function offsetLoad_access($value): array
protected function offsetLoad_access(mixed $value): array
{
if (!$value instanceof Access) {
$value = new Access($value);
@@ -1040,10 +1039,9 @@ class UserObject extends FlexObject implements UserInterface, Countable
}
/**
* @param mixed $value
* @return array
*/
protected function offsetPrepare_access($value): array
protected function offsetPrepare_access(mixed $value): array
{
return $this->offsetLoad_access($value);
}

View File

@@ -28,7 +28,7 @@ class FormFlash extends FrameworkFormFlash
{
$fields = [];
foreach ($this->files as $field => $files) {
if (strpos($field, '/')) {
if (strpos((string) $field, '/')) {
continue;
}
foreach ($files as $file) {

View File

@@ -14,7 +14,7 @@ use Grav\Common\Data\Data;
/**
* @property string $name
*/
class Package
class Package implements \Stringable
{
/** @var Data */
protected $data;
@@ -53,11 +53,10 @@ class Package
/**
* @param string $key
* @param mixed $value
* @return void
*/
#[\ReturnTypeWillChange]
public function __set($key, $value)
public function __set($key, mixed $value)
{
$this->data->set($key, $value);
}
@@ -76,7 +75,7 @@ class Package
* @return string
*/
#[\ReturnTypeWillChange]
public function __toString()
public function __toString(): string
{
return $this->toJson();
}

View File

@@ -37,8 +37,6 @@ class GPM extends Iterator
private $repository;
/** @var Remote\GravCore|null Remove Grav Packages */
private $grav;
/** @var bool */
private $refresh;
/** @var callable|null */
private $callback;
@@ -57,7 +55,7 @@ class GPM extends Iterator
* @param bool $refresh Applies to Remote Packages only and forces a refetch of data
* @param callable|null $callback Either a function or callback in array notation
*/
public function __construct($refresh = false, $callback = null)
public function __construct(private $refresh = false, $callback = null)
{
parent::__construct();
@@ -65,7 +63,6 @@ class GPM extends Iterator
$this->cache = [];
$this->installed = new Local\Packages();
$this->refresh = $refresh;
$this->callback = $callback;
}
@@ -78,12 +75,10 @@ class GPM extends Iterator
#[\ReturnTypeWillChange]
public function __get($offset)
{
switch ($offset) {
case 'grav':
return $this->getGrav();
}
return parent::__get($offset);
return match ($offset) {
'grav' => $this->getGrav(),
default => parent::__get($offset),
};
}
/**
@@ -95,12 +90,10 @@ class GPM extends Iterator
#[\ReturnTypeWillChange]
public function __isset($offset)
{
switch ($offset) {
case 'grav':
return $this->getGrav() !== null;
}
return parent::__isset($offset);
return match ($offset) {
'grav' => $this->getGrav() !== null,
default => parent::__isset($offset),
};
}
/**
@@ -126,7 +119,7 @@ class GPM extends Iterator
if ($type_installed === false) {
continue;
}
$methodInstallableType = 'getInstalled' . ucfirst($type);
$methodInstallableType = 'getInstalled' . ucfirst((string) $type);
$to_install = $this->$methodInstallableType();
$items[$type] = $to_install;
$items['total'] += count($to_install);
@@ -286,7 +279,7 @@ class GPM extends Iterator
if ($type_updatable === false) {
continue;
}
$methodUpdatableType = 'getUpdatable' . ucfirst($type);
$methodUpdatableType = 'getUpdatable' . ucfirst((string) $type);
$to_update = $this->$methodUpdatableType();
$items[$type] = $to_update;
$items['total'] += count($to_update);
@@ -550,7 +543,7 @@ class GPM extends Iterator
if (null === $this->repository) {
try {
$this->repository = new Remote\Packages($this->refresh, $this->callback);
} catch (Exception $e) {}
} catch (Exception) {}
}
return $this->repository;
@@ -566,7 +559,7 @@ class GPM extends Iterator
if (null === $this->grav) {
try {
$this->grav = new Remote\GravCore($this->refresh, $this->callback);
} catch (Exception $e) {}
} catch (Exception) {}
}
return $this->grav;
@@ -1220,7 +1213,7 @@ class GPM extends Iterator
*/
public function versionFormatIsNextSignificantRelease($version): bool
{
return strpos($version, '~') === 0;
return str_starts_with($version, '~');
}
/**
@@ -1233,7 +1226,7 @@ class GPM extends Iterator
*/
public function versionFormatIsEqualOrHigher($version): bool
{
return strpos($version, '>=') === 0;
return str_starts_with($version, '>=');
}
/**

View File

@@ -81,7 +81,7 @@ class Installer
{
$destination = rtrim($destination, DS);
$options = array_merge(self::$options, $options);
$install_path = rtrim($destination . DS . ltrim($options['install_path'], DS), DS);
$install_path = rtrim($destination . DS . ltrim((string) $options['install_path'], DS), DS);
if (!self::isGravInstance($destination) || !self::isValidDestination(
$install_path,

View File

@@ -37,7 +37,7 @@ class Package extends BasePackage
$html_description = Parsedown::instance()->line($this->__get('description'));
$this->data->set('slug', $package->__get('slug'));
$this->data->set('description_html', $html_description);
$this->data->set('description_plain', strip_tags($html_description));
$this->data->set('description_plain', strip_tags((string) $html_description));
$this->data->set('symlink', is_link(USER_DIR . $package_type . DS . $this->__get('slug')));
}

View File

@@ -12,7 +12,7 @@ namespace Grav\Common\GPM\Remote;
use Grav\Common\Grav;
use Grav\Common\HTTP\Response;
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
use \Doctrine\Common\Cache\FilesystemCache;
use Doctrine\Common\Cache\FilesystemCache;
use RuntimeException;
/**
@@ -53,10 +53,10 @@ class AbstractPackageCollection extends BaseCollection
$this->raw = $this->cache->fetch(md5($this->repository));
$this->fetch($refresh, $callback);
foreach (json_decode($this->raw, true) as $slug => $data) {
foreach (json_decode((string) $this->raw, true) as $slug => $data) {
// Temporarily fix for using multi-sites
if (isset($data['install_path'])) {
$path = preg_replace('~^user/~i', 'user://', $data['install_path']);
$path = preg_replace('~^user/~i', 'user://', (string) $data['install_path']);
$data['install_path'] = Grav::instance()['locator']->findResource($path, false, true);
}
$this->items[$slug] = new Package($data, $this->type);

View File

@@ -46,7 +46,7 @@ class GravCore extends AbstractPackageCollection
$this->fetch($refresh, $callback);
$this->data = json_decode($this->raw, true);
$this->data = json_decode((string) $this->raw, true);
$this->version = $this->data['version'] ?? '-';
$this->date = $this->data['date'] ?? '-';
$this->min_php = $this->data['min_php'] ?? null;
@@ -82,7 +82,7 @@ class GravCore extends AbstractPackageCollection
$diffLog = [];
foreach ((array)$this->data['changelog'] as $version => $changelog) {
preg_match("/[\w\-\.]+/", $version, $cleanVersion);
preg_match("/[\w\-\.]+/", (string) $version, $cleanVersion);
if (!$cleanVersion || version_compare($diff, $cleanVersion[0], '>=')) {
continue;

View File

@@ -52,7 +52,7 @@ class Package extends BasePackage implements \JsonSerializable
$diffLog = [];
foreach ((array)$this->data['changelog'] as $version => $changelog) {
preg_match("/[\w\-.]+/", $version, $cleanVersion);
preg_match("/[\w\-.]+/", (string) $version, $cleanVersion);
if (!$cleanVersion || version_compare($diff, $cleanVersion[0], '>=')) {
continue;

View File

@@ -29,7 +29,7 @@ abstract class Getters implements ArrayAccess, Countable
* @param mixed $value Medium value
*/
#[\ReturnTypeWillChange]
public function __set($offset, $value)
public function __set($offset, mixed $value)
{
$this->offsetSet($offset, $value);
}
@@ -103,10 +103,9 @@ abstract class Getters implements ArrayAccess, Countable
/**
* @param int|string $offset
* @param mixed $value
*/
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
public function offsetSet($offset, mixed $value)
{
if ($this->gettersVariable) {
$var = $this->gettersVariable;

View File

@@ -202,7 +202,7 @@ class Grav extends Container
* @param string|null $environment
* @return $this
*/
public function setup(string $environment = null)
public function setup(?string $environment = null)
{
if (isset($this->initialized['setup'])) {
return $this;
@@ -263,51 +263,23 @@ class Grav extends Container
$container = new Container(
[
'multipartRequestSupport' => function () {
return new MultipartRequestSupport();
},
'initializeProcessor' => function () {
return new InitializeProcessor($this);
},
'backupsProcessor' => function () {
return new BackupsProcessor($this);
},
'pluginsProcessor' => function () {
return new PluginsProcessor($this);
},
'themesProcessor' => function () {
return new ThemesProcessor($this);
},
'schedulerProcessor' => function () {
return new SchedulerProcessor($this);
},
'requestProcessor' => function () {
return new RequestProcessor($this);
},
'tasksProcessor' => function () {
return new TasksProcessor($this);
},
'assetsProcessor' => function () {
return new AssetsProcessor($this);
},
'twigProcessor' => function () {
return new TwigProcessor($this);
},
'pagesProcessor' => function () {
return new PagesProcessor($this);
},
'debuggerAssetsProcessor' => function () {
return new DebuggerAssetsProcessor($this);
},
'renderProcessor' => function () {
return new RenderProcessor($this);
},
'multipartRequestSupport' => fn() => new MultipartRequestSupport(),
'initializeProcessor' => fn() => new InitializeProcessor($this),
'backupsProcessor' => fn() => new BackupsProcessor($this),
'pluginsProcessor' => fn() => new PluginsProcessor($this),
'themesProcessor' => fn() => new ThemesProcessor($this),
'schedulerProcessor' => fn() => new SchedulerProcessor($this),
'requestProcessor' => fn() => new RequestProcessor($this),
'tasksProcessor' => fn() => new TasksProcessor($this),
'assetsProcessor' => fn() => new AssetsProcessor($this),
'twigProcessor' => fn() => new TwigProcessor($this),
'pagesProcessor' => fn() => new PagesProcessor($this),
'debuggerAssetsProcessor' => fn() => new DebuggerAssetsProcessor($this),
'renderProcessor' => fn() => new RenderProcessor($this),
]
);
$default = static function () {
return new Response(404, ['Expires' => 0, 'Cache-Control' => 'no-store, max-age=0'], 'Not Found');
};
$default = static fn() => new Response(404, ['Expires' => 0, 'Cache-Control' => 'no-store, max-age=0'], 'Not Found');
$collection = new RequestHandler($this->middleware, $default, $container);
@@ -328,7 +300,7 @@ class Grav extends Container
$etag = md5($body);
$response = $response->withHeader('ETag', '"' . $etag . '"');
$search = trim($this['request']->getHeaderLine('If-None-Match'), '"');
$search = trim((string) $this['request']->getHeaderLine('If-None-Match'), '"');
if ($noCache === false && $search === $etag) {
$response = $response->withStatus(304);
$body = '';
@@ -405,7 +377,7 @@ class Grav extends Container
$etag = md5($body);
$response = $response->withHeader('ETag', '"' . $etag . '"');
$search = trim($this['request']->getHeaderLine('If-None-Match'), '"');
$search = trim((string) $this['request']->getHeaderLine('If-None-Match'), '"');
if ($noCache === false && $search === $etag) {
$response = $response->withStatus(304);
$body = '';
@@ -463,7 +435,7 @@ class Grav extends Container
if (null === $code) {
// Check for redirect code in the route: e.g. /new/[301], /new[301]/route or /new[301].html
$regex = '/.*(\[(30[1-7])\])(.\w+|\/.*?)?$/';
preg_match($regex, $route, $matches);
preg_match($regex, (string) $route, $matches);
if ($matches) {
$route = str_replace($matches[1], '', $matches[0]);
$code = $matches[2];
@@ -476,9 +448,9 @@ class Grav extends Container
$url = rtrim($uri->rootUrl(), '/') . '/';
if ($this['config']->get('system.pages.redirect_trailing_slash', true)) {
$url .= trim($route, '/'); // Remove trailing slash
$url .= trim((string) $route, '/'); // Remove trailing slash
} else {
$url .= ltrim($route, '/'); // Support trailing slash default routes
$url .= ltrim((string) $route, '/'); // Support trailing slash default routes
}
}
} elseif ($route instanceof Route) {
@@ -524,7 +496,7 @@ class Grav extends Container
* @param ResponseInterface|null $response
* @return void
*/
public function header(ResponseInterface $response = null): void
public function header(?ResponseInterface $response = null): void
{
if (null === $response) {
/** @var PageInterface $page */
@@ -535,7 +507,7 @@ class Grav extends Container
header("HTTP/{$response->getProtocolVersion()} {$response->getStatusCode()} {$response->getReasonPhrase()}");
foreach ($response->getHeaders() as $key => $values) {
// Skip internal Grav headers.
if (strpos($key, 'Grav-Internal-') === 0) {
if (str_starts_with((string) $key, 'Grav-Internal-')) {
continue;
}
foreach ($values as $i => $value) {
@@ -554,7 +526,7 @@ class Grav extends Container
// Initialize Locale if set and configured.
if ($this['language']->enabled() && $this['config']->get('system.languages.override_locale')) {
$language = $this['language']->getLanguage();
setlocale(LC_ALL, strlen($language) < 3 ? ($language . '_' . strtoupper($language)) : $language);
setlocale(LC_ALL, strlen((string) $language) < 3 ? ($language . '_' . strtoupper((string) $language)) : $language);
} elseif ($this['config']->get('system.default_locale')) {
setlocale(LC_ALL, $this['config']->get('system.default_locale'));
}
@@ -568,7 +540,7 @@ class Grav extends Container
{
/** @var EventDispatcherInterface $events */
$events = $this['events'];
$eventName = get_class($event);
$eventName = $event::class;
$timestamp = microtime(true);
$event = $events->dispatch($event);
@@ -587,7 +559,7 @@ class Grav extends Container
* @param Event|null $event
* @return Event
*/
public function fireEvent($eventName, Event $event = null)
public function fireEvent($eventName, ?Event $event = null)
{
/** @var EventDispatcherInterface $events */
$events = $this['events'];
@@ -736,9 +708,7 @@ class Grav extends Container
if (is_int($serviceKey)) {
$this->register(new $serviceClass);
} else {
$this[$serviceKey] = function ($c) use ($serviceClass) {
return new $serviceClass($c);
};
$this[$serviceKey] = fn($c) => new $serviceClass($c);
}
}
}
@@ -801,7 +771,7 @@ class Grav extends Container
$medium = $media[$media_file];
foreach ($uri->query(null, true) as $action => $params) {
if (in_array($action, ImageMedium::$magic_actions, true)) {
call_user_func_array([&$medium, $action], explode(',', $params));
call_user_func_array([&$medium, $action], explode(',', (string) $params));
}
}
Utils::download($medium->path(), false);
@@ -818,7 +788,7 @@ class Grav extends Container
if ($extension) {
$download = true;
if (in_array(ltrim($extension, '.'), $config->get('system.media.unsupported_inline_types', []), true)) {
if (in_array(ltrim((string) $extension, '.'), $config->get('system.media.unsupported_inline_types', []), true)) {
$download = false;
}
Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download);

View File

@@ -25,7 +25,7 @@ class Client
'User-Agent' => 'Grav CMS'
];
public static function getClient(array $overrides = [], int $connections = 6, callable $callback = null): HttpClientInterface
public static function getClient(array $overrides = [], int $connections = 6, ?callable $callback = null): HttpClientInterface
{
$config = Grav::instance()['config'];
$options = static::getOptions();
@@ -33,7 +33,7 @@ class Client
// Use callback if provided
if ($callback) {
self::$callback = $callback;
$options->setOnProgress([Client::class, 'progress']);
$options->setOnProgress(Client::progress(...));
}
$settings = array_merge($options->toArray(), $overrides);
@@ -43,17 +43,11 @@ class Client
$preferred_method = $config->get('system.gpm.method', 'auto');
}
switch ($preferred_method) {
case 'curl':
$client = new CurlHttpClient($settings, $connections);
break;
case 'fopen':
case 'native':
$client = new NativeHttpClient($settings, $connections);
break;
default:
$client = HttpClient::create($settings, $connections);
}
$client = match ($preferred_method) {
'curl' => new CurlHttpClient($settings, $connections),
'fopen', 'native' => new NativeHttpClient($settings, $connections),
default => HttpClient::create($settings, $connections),
};
return $client;
}

View File

@@ -41,7 +41,7 @@ class Response
* @return string
* @throws TransportExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface|ClientExceptionInterface
*/
public static function get(string $uri = '', array $overrides = [], callable $callback = null): string
public static function get(string $uri = '', array $overrides = [], ?callable $callback = null): string
{
$response = static::request('GET', $uri, $overrides, $callback);
return $response->getContent();
@@ -58,7 +58,7 @@ class Response
* @return ResponseInterface
* @throws TransportExceptionInterface
*/
public static function request(string $method, string $uri, array $overrides = [], callable $callback = null): ResponseInterface
public static function request(string $method, string $uri, array $overrides = [], ?callable $callback = null): ResponseInterface
{
if (empty($method)) {
throw new TransportException('missing method (GET, PUT, etc.)');
@@ -73,7 +73,7 @@ class Response
if (Utils::functionExists('set_time_limit')) {
@set_time_limit(0);
}
} catch (Exception $e) {}
} catch (Exception) {}
$client = Client::getClient($overrides, 6, $callback);

View File

@@ -30,7 +30,7 @@ class Excerpts
* @param PageInterface|null $page Page, defaults to the current page object
* @return string Returns final HTML string
*/
public static function processImageHtml($html, PageInterface $page = null)
public static function processImageHtml($html, ?PageInterface $page = null)
{
$excerpt = static::getExcerptFromHtml($html, 'img');
if (null === $excerpt) {
@@ -61,7 +61,7 @@ class Excerpts
* @param PageInterface|null $page Page, defaults to the current page object
* @return string Returns final HTML string
*/
public static function processLinkHtml($html, PageInterface $page = null)
public static function processLinkHtml($html, ?PageInterface $page = null)
{
$excerpt = static::getExcerptFromHtml($html, 'a');
if (null === $excerpt) {
@@ -158,7 +158,7 @@ class Excerpts
* @param string $type
* @return mixed
*/
public static function processLinkExcerpt($excerpt, PageInterface $page = null, $type = 'link')
public static function processLinkExcerpt($excerpt, ?PageInterface $page = null, $type = 'link')
{
$excerpts = new ExcerptsObject($page);
@@ -172,7 +172,7 @@ class Excerpts
* @param PageInterface|null $page Page, defaults to the current page object
* @return array
*/
public static function processImageExcerpt(array $excerpt, PageInterface $page = null)
public static function processImageExcerpt(array $excerpt, ?PageInterface $page = null)
{
$excerpts = new ExcerptsObject($page);
@@ -187,7 +187,7 @@ class Excerpts
* @param PageInterface|null $page Page, defaults to the current page object
* @return Medium|Link
*/
public static function processMediaActions($medium, $url, PageInterface $page = null)
public static function processMediaActions($medium, $url, ?PageInterface $page = null)
{
$excerpts = new ExcerptsObject($page);

View File

@@ -60,9 +60,9 @@ class Truncator
$words = $currentWordPosition[2];
$curNode->nodeValue = substr(
$curNode->nodeValue,
(string) $curNode->nodeValue,
0,
$words[$offset][1] + strlen($words[$offset][0])
$words[$offset][1] + strlen((string) $words[$offset][0])
);
self::removeProceedingNodes($curNode, $container);
@@ -110,7 +110,7 @@ class Truncator
// If we have exceeded the limit, we want to delete the remainder of this document.
if ($letters->key() >= $limit) {
$currentText = $letters->currentTextPosition();
$currentText[0]->nodeValue = mb_substr($currentText[0]->nodeValue, 0, $currentText[1] + 1);
$currentText[0]->nodeValue = mb_substr((string) $currentText[0]->nodeValue, 0, $currentText[1] + 1);
self::removeProceedingNodes($currentText[0], $container);
if (!empty($ellipsis)) {
@@ -216,7 +216,7 @@ class Truncator
*/
private static function insertEllipsis($domNode, $ellipsis)
{
$avoid = array('a', 'strong', 'em', 'h1', 'h2', 'h3', 'h4', 'h5'); //html tags to avoid appending the ellipsis to
$avoid = ['a', 'strong', 'em', 'h1', 'h2', 'h3', 'h4', 'h5']; //html tags to avoid appending the ellipsis to
if ($domNode->parentNode->parentNode !== null && in_array($domNode->parentNode->nodeName, $avoid, true)) {
// Append as text node to parent instead
@@ -231,7 +231,7 @@ class Truncator
}
} else {
// Append to current node
$domNode->nodeValue = rtrim($domNode->nodeValue) . $ellipsis;
$domNode->nodeValue = rtrim((string) $domNode->nodeValue) . $ellipsis;
}
}
@@ -252,7 +252,7 @@ class Truncator
) {
if ($considerHtml) {
// if the plain text is shorter than the maximum length, return the whole text
if (strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
if (strlen((string) preg_replace('/<.*?>/', '', $text)) <= $length) {
return $text;
}
@@ -284,7 +284,7 @@ class Truncator
$truncate .= $line_matchings[1];
}
// calculate the length of the plain text part of the line; handle entities as one character
$content_length = strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
$content_length = strlen((string) preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i', ' ', $line_matchings[2]));
if ($total_length+$content_length> $length) {
// the number of characters which are left
$left = $length - $total_length;

View File

@@ -29,7 +29,7 @@ class YamlLinter
* @param string|null $folder
* @return array
*/
public static function lint(string $folder = null)
public static function lint(?string $folder = null)
{
if (null !== $folder) {
$folder = $folder ?: GRAV_ROOT;

View File

@@ -72,7 +72,7 @@ class Inflector
if (is_array(static::$uncountable)) {
foreach (static::$uncountable as $_uncountable) {
if (substr($lowercased_word, -1 * strlen($_uncountable)) === $_uncountable) {
if (substr($lowercased_word, -1 * strlen((string) $_uncountable)) === $_uncountable) {
return $word;
}
}
@@ -81,7 +81,7 @@ class Inflector
if (is_array(static::$irregular)) {
foreach (static::$irregular as $_plural => $_singular) {
if (preg_match('/(' . $_plural . ')$/i', $word, $arr)) {
return preg_replace('/(' . $_plural . ')$/i', substr($arr[0], 0, 1) . substr($_singular, 1), $word);
return preg_replace('/(' . $_plural . ')$/i', substr($arr[0], 0, 1) . substr((string) $_singular, 1), $word);
}
}
}
@@ -89,7 +89,7 @@ class Inflector
if (is_array(static::$plural)) {
foreach (static::$plural as $rule => $replacement) {
if (preg_match($rule, $word)) {
return preg_replace($rule, $replacement, $word);
return preg_replace($rule, (string) $replacement, $word);
}
}
}
@@ -117,7 +117,7 @@ class Inflector
if (is_array(static::$uncountable)) {
foreach (static::$uncountable as $_uncountable) {
if (substr($lowercased_word, -1 * strlen($_uncountable)) === $_uncountable) {
if (substr($lowercased_word, -1 * strlen((string) $_uncountable)) === $_uncountable) {
return $word;
}
}
@@ -126,7 +126,7 @@ class Inflector
if (is_array(static::$irregular)) {
foreach (static::$irregular as $_plural => $_singular) {
if (preg_match('/(' . $_singular . ')$/i', $word, $arr)) {
return preg_replace('/(' . $_singular . ')$/i', substr($arr[0], 0, 1) . substr($_plural, 1), $word);
return preg_replace('/(' . $_singular . ')$/i', substr($arr[0], 0, 1) . substr((string) $_plural, 1), $word);
}
}
}
@@ -134,7 +134,7 @@ class Inflector
if (is_array(static::$singular)) {
foreach (static::$singular as $rule => $replacement) {
if (preg_match($rule, $word)) {
return preg_replace($rule, $replacement, $word);
return preg_replace($rule, (string) $replacement, $word);
}
}
}
@@ -186,7 +186,7 @@ class Inflector
*/
public static function camelize($word)
{
return str_replace(' ', '', ucwords(preg_replace('/[^\p{L}^0-9]+/', ' ', $word)));
return str_replace(' ', '', ucwords((string) preg_replace('/[^\p{L}^0-9]+/', ' ', $word)));
}
/**
@@ -203,10 +203,10 @@ class Inflector
public static function underscorize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1_\2', $regex1);
$regex3 = preg_replace('/[^\p{L}^0-9]+/u', '_', $regex2);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1_\2', (string) $regex1);
$regex3 = preg_replace('/[^\p{L}^0-9]+/u', '_', (string) $regex2);
return strtolower($regex3);
return strtolower((string) $regex3);
}
/**
@@ -223,11 +223,11 @@ class Inflector
public static function hyphenize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1-\2', $word);
$regex2 = preg_replace('/([a-z])([A-Z])/', '\1-\2', $regex1);
$regex3 = preg_replace('/([0-9])([A-Z])/', '\1-\2', $regex2);
$regex4 = preg_replace('/[^\p{L}^0-9]+/', '-', $regex3);
$regex2 = preg_replace('/([a-z])([A-Z])/', '\1-\2', (string) $regex1);
$regex3 = preg_replace('/([0-9])([A-Z])/', '\1-\2', (string) $regex2);
$regex4 = preg_replace('/[^\p{L}^0-9]+/', '-', (string) $regex3);
$regex4 = trim($regex4, '-');
$regex4 = trim((string) $regex4, '-');
return strtolower($regex4);
}
@@ -326,16 +326,12 @@ class Inflector
return $number . static::$ordinals['default'];
}
switch ($number % 10) {
case 1:
return $number . static::$ordinals['first'];
case 2:
return $number . static::$ordinals['second'];
case 3:
return $number . static::$ordinals['third'];
default:
return $number . static::$ordinals['default'];
}
return match ($number % 10) {
1 => $number . static::$ordinals['first'],
2 => $number . static::$ordinals['second'],
3 => $number . static::$ordinals['third'],
default => $number . static::$ordinals['default'],
};
}
/**

View File

@@ -24,7 +24,7 @@ use function is_object;
* Class Iterator
* @package Grav\Common
*/
class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable, \Stringable
{
use Constructor, ArrayAccessWithGetters, ArrayIterator, Countable, Serializable, Export;
@@ -35,11 +35,10 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
* Convert function calls for the existing keys into their values.
*
* @param string $key
* @param mixed $args
* @return mixed
*/
#[\ReturnTypeWillChange]
public function __call($key, $args)
public function __call($key, mixed $args)
{
return $this->items[$key] ?? null;
}
@@ -63,7 +62,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
* @return string
*/
#[\ReturnTypeWillChange]
public function __toString()
public function __toString(): string
{
return implode(',', $this->items);
}
@@ -143,7 +142,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
*
* @return string|int|false Key if found, otherwise false.
*/
public function indexOf($needle)
public function indexOf(mixed $needle)
{
foreach (array_values($this->items) as $key => $value) {
if ($value === $needle) {
@@ -230,7 +229,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
*
* @return $this
*/
public function filter(callable $callback = null)
public function filter(?callable $callback = null)
{
foreach ($this->items as $key => $value) {
if ((!$callback && !(bool)$value) || ($callback && !$callback($value, $key))) {
@@ -250,7 +249,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
* @return $this|array
*
*/
public function sort(callable $callback = null, $desc = false)
public function sort(?callable $callback = null, $desc = false)
{
if (!$callback || !is_callable($callback)) {
return $this;

View File

@@ -149,9 +149,7 @@ class Language
{
$languagesArray = $this->languages; //Make local copy
$languagesArray = array_map(static function ($value) use ($delimiter) {
return preg_quote($value, $delimiter);
}, $languagesArray);
$languagesArray = array_map(static fn($value) => preg_quote((string) $value, $delimiter), $languagesArray);
sort($languagesArray);
@@ -358,7 +356,7 @@ class Language
* @param bool $assoc Return values in ['en' => '.en.md', ...] format.
* @return array Key is the language code, value is the file extension to be used.
*/
public function getFallbackPageExtensions(string $fileExtension = null, string $languageCode = null, bool $assoc = false)
public function getFallbackPageExtensions(?string $fileExtension = null, ?string $languageCode = null, bool $assoc = false)
{
$fileExtension = $fileExtension ?: CONTENT_EXT;
$key = $fileExtension . '-' . ($languageCode ?? 'default') . '-' . (int)$assoc;
@@ -411,7 +409,7 @@ class Language
* @param bool $includeDefault If true, list contains '', which can be used for default
* @return array
*/
public function getFallbackLanguages(string $languageCode = null, bool $includeDefault = false)
public function getFallbackLanguages(?string $languageCode = null, bool $includeDefault = false)
{
// Handle default.
if ($languageCode === '' || !$this->enabled()) {
@@ -489,7 +487,7 @@ class Language
* @param bool $html_out
* @return string|string[]
*/
public function translate($args, array $languages = null, $array_support = false, $html_out = false)
public function translate($args, ?array $languages = null, $array_support = false, $html_out = false)
{
if (is_array($args)) {
$lookup = array_shift($args);
@@ -593,7 +591,7 @@ class Language
*/
public function getBrowserLanguages($accept_langs = [])
{
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, no longer used', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, no longer used', E_USER_DEPRECATED);
if (empty($this->http_accept_language)) {
if (empty($accept_langs) && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
@@ -604,7 +602,7 @@ class Language
$langs = [];
foreach (explode(',', $accept_langs) as $k => $pref) {
foreach (explode(',', (string) $accept_langs) as $k => $pref) {
// split $pref again by ';q='
// and decorate the language entries by inverted position
if (false !== ($i = strpos($pref, ';q='))) {

View File

@@ -35,7 +35,7 @@ class Parsedown extends \Parsedown
$defaults = ['markdown' => $defaults];
}
$excerpts = new Excerpts($excerpts, $defaults);
user_error(__CLASS__ . '::' . __FUNCTION__ . '($page, $defaults) is deprecated since Grav 1.6.10, use new ' . __CLASS__ . '(new ' . Excerpts::class . '($page, [\'markdown\' => $defaults])) instead.', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '($page, $defaults) is deprecated since Grav 1.6.10, use new ' . self::class . '(new ' . Excerpts::class . '($page, [\'markdown\' => $defaults])) instead.', E_USER_DEPRECATED);
}
$this->init($excerpts, $defaults);

View File

@@ -36,7 +36,7 @@ class ParsedownExtra extends \ParsedownExtra
$defaults = ['markdown' => $defaults];
}
$excerpts = new Excerpts($excerpts, $defaults);
user_error(__CLASS__ . '::' . __FUNCTION__ . '($page, $defaults) is deprecated since Grav 1.6.10, use new ' . __CLASS__ . '(new ' . Excerpts::class . '($page, [\'markdown\' => $defaults])) instead.', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '($page, $defaults) is deprecated since Grav 1.6.10, use new ' . self::class . '(new ' . Excerpts::class . '($page, [\'markdown\' => $defaults])) instead.', E_USER_DEPRECATED);
}
parent::__construct();

View File

@@ -49,7 +49,7 @@ trait ParsedownGravTrait
$defaults = ['markdown' => $defaults];
}
$this->excerpts = new Excerpts($excerpts, $defaults);
user_error(__CLASS__ . '::' . __FUNCTION__ . '($page, $defaults) is deprecated since Grav 1.6.10, use ->init(new ' . Excerpts::class . '($page, [\'markdown\' => $defaults])) instead.', E_USER_DEPRECATED);
user_error(self::class . '::' . __FUNCTION__ . '($page, $defaults) is deprecated since Grav 1.6.10, use ->init(new ' . Excerpts::class . '($page, [\'markdown\' => $defaults])) instead.', E_USER_DEPRECATED);
} else {
$this->excerpts = $excerpts;
}
@@ -133,7 +133,7 @@ trait ParsedownGravTrait
array_splice($this->InlineTypes[$type], $index, 0, [$tag]);
}
if (strpos($this->inlineMarkerList, $type) === false) {
if (!str_contains($this->inlineMarkerList, $type)) {
$this->inlineMarkerList .= $type;
}
}
@@ -199,7 +199,7 @@ trait ParsedownGravTrait
*/
protected function blockTwigTag($line)
{
if (preg_match('/(?:{{|{%|{#)(.*)(?:}}|%}|#})/', $line['body'], $matches)) {
if (preg_match('/(?:{{|{%|{#)(.*)(?:}}|%}|#})/', (string) $line['body'], $matches)) {
return ['markup' => $line['body']];
}
@@ -212,7 +212,7 @@ trait ParsedownGravTrait
*/
protected function inlineSpecialCharacter($excerpt)
{
if ($excerpt['text'][0] === '&' && !preg_match('/^&#?\w+;/', $excerpt['text'])) {
if ($excerpt['text'][0] === '&' && !preg_match('/^&#?\w+;/', (string) $excerpt['text'])) {
return [
'markup' => '&amp;',
'extent' => 1,
@@ -235,7 +235,7 @@ trait ParsedownGravTrait
*/
protected function inlineImage($excerpt)
{
if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) {
if (preg_match($this->twig_link_regex, (string) $excerpt['text'], $matches)) {
$excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']);
$excerpt = parent::inlineImage($excerpt);
$excerpt['element']['attributes']['src'] = $matches[1];
@@ -264,7 +264,7 @@ trait ParsedownGravTrait
$type = $excerpt['type'] ?? 'link';
// do some trickery to get around Parsedown requirement for valid URL if its Twig in there
if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) {
if (preg_match($this->twig_link_regex, (string) $excerpt['text'], $matches)) {
$excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']);
$excerpt = parent::inlineLink($excerpt);
$excerpt['element']['attributes']['href'] = $matches[1];

View File

@@ -105,7 +105,7 @@ interface MediaCollectionInterface extends \Grav\Framework\Media\Interfaces\Medi
* @param Blueprint|null $blueprint
* @return Medium|null
*/
public function createFromArray(array $items = [], Blueprint $blueprint = null);
public function createFromArray(array $items = [], ?Blueprint $blueprint = null);
/**
* @param MediaObjectInterface $mediaObject

View File

@@ -207,11 +207,10 @@ interface MediaObjectInterface extends \Grav\Framework\Media\Interfaces\MediaObj
* Allow any action to be called on this medium from twig or markdown
*
* @param string $method
* @param mixed $args
* @return $this
*/
#[\ReturnTypeWillChange]
public function __call($method, $args);
public function __call($method, mixed $args);
/**
* Set value by using dot notation for nested arrays/objects.
@@ -223,5 +222,5 @@ interface MediaObjectInterface extends \Grav\Framework\Media\Interfaces\MediaObj
* @param string|null $separator Separator, defaults to '.'
* @return $this
*/
public function set($name, $value, $separator = null);
public function set($name, mixed $value, $separator = null);
}

View File

@@ -32,7 +32,7 @@ interface MediaUploadInterface
* @return string
* @throws RuntimeException
*/
public function checkUploadedFile(UploadedFileInterface $uploadedFile, string $filename = null, array $settings = null): string;
public function checkUploadedFile(UploadedFileInterface $uploadedFile, ?string $filename = null, ?array $settings = null): string;
/**
* Copy uploaded file to the media collection.
@@ -51,7 +51,7 @@ interface MediaUploadInterface
* @return void
* @throws RuntimeException
*/
public function copyUploadedFile(UploadedFileInterface $uploadedFile, string $filename, array $settings = null): void;
public function copyUploadedFile(UploadedFileInterface $uploadedFile, string $filename, ?array $settings = null): void;
/**
* Delete real file from the media collection.
@@ -60,7 +60,7 @@ interface MediaUploadInterface
* @param array|null $settings
* @return void
*/
public function deleteFile(string $filename, array $settings = null): void;
public function deleteFile(string $filename, ?array $settings = null): void;
/**
* Rename file inside the media collection.
@@ -69,5 +69,5 @@ interface MediaUploadInterface
* @param string $to
* @param array|null $settings
*/
public function renameFile(string $from, string $to, array $settings = null): void;
public function renameFile(string $from, string $to, ?array $settings = null): void;
}

View File

@@ -97,7 +97,7 @@ trait ImageMediaTrait
}
$basename = $this->get('basename');
if (preg_match('/[a-z0-9]{40}-(.*)/', $basename, $matches)) {
if (preg_match('/[a-z0-9]{40}-(.*)/', (string) $basename, $matches)) {
$basename = $matches[1];
}
return $basename;

View File

@@ -88,7 +88,7 @@ trait MediaFileTrait
}
$path = $this->path(false);
$output = preg_replace('|^' . preg_quote(GRAV_ROOT, '|') . '|', '', $path) ?: $path;
$output = preg_replace('|^' . preg_quote(GRAV_ROOT, '|') . '|', '', (string) $path) ?: $path;
/** @var UniformResourceLocator $locator */
$locator = $this->getGrav()['locator'];

View File

@@ -182,7 +182,7 @@ trait MediaObjectTrait
// join the strings
$querystring = implode('&', $this->medium_querystring);
// explode all strings
$query_parts = explode('&', $querystring);
$query_parts = explode('&', (string) $querystring);
// Join them again now ensure the elements are unique
$querystring = implode('&', array_unique($query_parts));
@@ -598,7 +598,7 @@ trait MediaObjectTrait
* @param string|null $separator Separator, defaults to '.'
* @return mixed Value.
*/
abstract public function get($name, $default = null, $separator = null);
abstract public function get($name, mixed $default = null, $separator = null);
/**
* Set value by using dot notation for nested arrays/objects.
@@ -610,7 +610,7 @@ trait MediaObjectTrait
* @param string|null $separator Separator, defaults to '.'
* @return $this
*/
abstract public function set($name, $value, $separator = null);
abstract public function set($name, mixed $value, $separator = null);
/**
* @param string $thumb

View File

@@ -57,15 +57,15 @@ trait MediaTrait
return null;
}
if (strpos($folder, '://')) {
if (strpos((string) $folder, '://')) {
return $folder;
}
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$user = $locator->findResource('user://');
if (strpos($folder, $user) === 0) {
return 'user://' . substr($folder, strlen($user)+1);
if (str_starts_with((string) $folder, $user)) {
return 'user://' . substr((string) $folder, strlen($user)+1);
}
return null;

View File

@@ -71,7 +71,7 @@ trait MediaUploadTrait
* @return string
* @throws RuntimeException
*/
public function checkUploadedFile(UploadedFileInterface $uploadedFile, string $filename = null, array $settings = null): string
public function checkUploadedFile(UploadedFileInterface $uploadedFile, ?string $filename = null, ?array $settings = null): string
{
// Check if there is an upload error.
switch ($uploadedFile->getError()) {
@@ -115,7 +115,7 @@ trait MediaUploadTrait
* @return string
* @throws RuntimeException
*/
public function checkFileMetadata(array $metadata, string $filename = null, array $settings = null): string
public function checkFileMetadata(array $metadata, ?string $filename = null, ?array $settings = null): string
{
// Add the defaults to the settings.
$settings = $this->getUploadSettings($settings);
@@ -206,11 +206,11 @@ trait MediaUploadTrait
break;
}
$isMime = strstr($type, '/');
$isMime = strstr((string) $type, '/');
$find = str_replace(['.', '*', '+'], ['\.', '.*', '\+'], $type);
if ($isMime) {
$match = preg_match('#' . $find . '$#', $mime);
$match = preg_match('#' . $find . '$#', (string) $mime);
if (!$match) {
// TODO: translate
$errors[] = 'The MIME type "' . $mime . '" for the file "' . $filepath . '" is not an accepted.';
@@ -219,7 +219,7 @@ trait MediaUploadTrait
break;
}
} else {
$match = preg_match('#' . $find . '$#', $filename);
$match = preg_match('#' . $find . '$#', (string) $filename);
if (!$match) {
// TODO: translate
$errors[] = 'The File Extension for the file "' . $filepath . '" is not an accepted.';
@@ -252,7 +252,7 @@ trait MediaUploadTrait
* @return void
* @throws RuntimeException
*/
public function copyUploadedFile(UploadedFileInterface $uploadedFile, string $filename, array $settings = null): void
public function copyUploadedFile(UploadedFileInterface $uploadedFile, string $filename, ?array $settings = null): void
{
// Add the defaults to the settings.
$settings = $this->getUploadSettings($settings);
@@ -286,7 +286,7 @@ trait MediaUploadTrait
if ($uploadedFile->getError() === \UPLOAD_ERR_OK) {
// Move uploaded file.
$this->doMoveUploadedFile($uploadedFile, $filename, $path);
} elseif (strpos($filename, 'original/') === 0 && !$this->fileExists($filename, $path) && $this->fileExists($basename, $path)) {
} elseif (str_starts_with($filename, 'original/') && !$this->fileExists($filename, $path) && $this->fileExists($basename, $path)) {
// Original image support: override original image if it's the same as the uploaded image.
$this->doCopy($basename, $filename, $path);
}
@@ -329,7 +329,7 @@ trait MediaUploadTrait
* @return void
* @throws RuntimeException
*/
public function deleteFile(string $filename, array $settings = null): void
public function deleteFile(string $filename, ?array $settings = null): void
{
// Add the defaults to the settings.
$settings = $this->getUploadSettings($settings);
@@ -371,7 +371,7 @@ trait MediaUploadTrait
* @param string $to
* @param array|null $settings
*/
public function renameFile(string $from, string $to, array $settings = null): void
public function renameFile(string $from, string $to, ?array $settings = null): void
{
// Add the defaults to the settings.
$settings = $this->getUploadSettings($settings);
@@ -558,7 +558,7 @@ trait MediaUploadTrait
$fileParts = (array)$filesystem->pathinfo($filename);
foreach ($dir as $file) {
$preg_name = preg_quote($fileParts['filename'], '`');
$preg_name = preg_quote((string) $fileParts['filename'], '`');
$preg_ext = preg_quote($fileParts['extension'] ?? '.', '`');
$preg_filename = preg_quote($basename, '`');

View File

@@ -138,7 +138,7 @@ trait ThumbnailMediaTrait
$closure = [$parent, $method];
if (!is_callable($closure)) {
throw new BadMethodCallException(get_class($parent) . '::' . $method . '() not found.');
throw new BadMethodCallException($parent::class . '::' . $method . '() not found.');
}
return $closure(...$arguments);

View File

@@ -43,7 +43,7 @@ class Collection extends Iterator implements PageCollectionInterface
* @param array $params
* @param Pages|null $pages
*/
public function __construct($items = [], array $params = [], Pages $pages = null)
public function __construct($items = [], array $params = [], ?Pages $pages = null)
{
parent::__construct($items);
@@ -139,9 +139,7 @@ class Collection extends Iterator implements PageCollectionInterface
$array1 = $this->items;
$array2 = $collection->toArray();
$this->items = array_uintersect($array1, $array2, function ($val1, $val2) {
return strcmp($val1['slug'], $val2['slug']);
});
$this->items = array_uintersect($array1, $array2, fn($val1, $val2) => strcmp((string) $val1['slug'], (string) $val2['slug']));
return $this;
}
@@ -357,7 +355,7 @@ class Collection extends Iterator implements PageCollectionInterface
continue;
}
$date = $field ? strtotime($page->value($field)) : $page->date();
$date = $field ? strtotime((string) $page->value($field)) : $page->date();
if ((!$start || $date >= $start) && (!$end || $date <= $end)) {
$date_range[$path] = $slug;

View File

@@ -46,7 +46,7 @@ interface PageCollectionInterface extends Traversable, ArrayAccess, Countable, S
* Add a single page to a collection
*
* @param PageInterface $page
* @return $this
* @return $this|PageCollectionInterface<TKey,T>
*/
public function addPage(PageInterface $page);
@@ -63,7 +63,7 @@ interface PageCollectionInterface extends Traversable, ArrayAccess, Countable, S
*
* Create a copy of this collection
*
* @return static
* @return static<TKey,T>
*/
public function copy();

View File

@@ -43,9 +43,8 @@ interface PageLegacyInterface
* Modify a header value directly
*
* @param string $key
* @param mixed $value
*/
public function modifyHeader($key, $value);
public function modifyHeader($key, mixed $value);
/**
* @return int
@@ -68,9 +67,8 @@ interface PageLegacyInterface
* Add an entry to the page's contentMeta array
*
* @param string $name
* @param mixed $value
*/
public function addContentMeta($name, $value);
public function addContentMeta($name, mixed $value);
/**
* Return the whole contentMeta array as it currently stands

View File

@@ -133,7 +133,7 @@ interface PageRoutableInterface
* @param PageInterface|null $var the parent page object
* @return PageInterface|null the parent page object if it exists.
*/
public function parent(PageInterface $var = null);
public function parent(?PageInterface $var = null);
/**
* Gets the top parent object for this page. Can return page itself.

View File

@@ -52,5 +52,5 @@ interface PagesSourceInterface // extends \Iterator
* @param array|null $options
* @return array
*/
public function getChildren(string $route, array $options = null): array;
public function getChildren(string $route, ?array $options = null): array;
}

View File

@@ -42,14 +42,14 @@ class Excerpts
* @param PageInterface|null $page
* @param array|null $config
*/
public function __construct(PageInterface $page = null, array $config = null)
public function __construct(?PageInterface $page = null, ?array $config = null)
{
$this->page = $page ?? Grav::instance()['page'] ?? null;
// Add defaults to the configuration.
if (null === $config || !isset($config['markdown'], $config['images'])) {
$c = Grav::instance()['config'];
$config = $config ?? [];
$config ??= [];
$config += [
'markdown' => $c->get('system.pages.markdown', []),
'images' => $c->get('system.images', [])
@@ -96,13 +96,13 @@ class Excerpts
public function processLinkExcerpt(array $excerpt, string $type = 'link'): array
{
$grav = Grav::instance();
$url = htmlspecialchars_decode(rawurldecode($excerpt['element']['attributes']['href']));
$url = htmlspecialchars_decode(rawurldecode((string) $excerpt['element']['attributes']['href']));
$url_parts = $this->parseUrl($url);
// If there is a query, then parse it and build action calls.
if (isset($url_parts['query'])) {
$actions = array_reduce(
explode('&', $url_parts['query']),
explode('&', (string) $url_parts['query']),
static function ($carry, $item) {
$parts = explode('=', $item, 2);
$value = isset($parts[1]) ? rawurldecode($parts[1]) : true;
@@ -119,7 +119,7 @@ class Excerpts
$skip = [];
// Unless told to not process, go through actions.
if (array_key_exists('noprocess', $actions)) {
$skip = is_bool($actions['noprocess']) ? $actions : explode(',', $actions['noprocess']);
$skip = is_bool($actions['noprocess']) ? $actions : explode(',', (string) $actions['noprocess']);
unset($actions['noprocess']);
}
@@ -185,7 +185,7 @@ class Excerpts
*/
public function processImageExcerpt(array $excerpt): array
{
$url = htmlspecialchars_decode(urldecode($excerpt['element']['attributes']['src']));
$url = htmlspecialchars_decode(urldecode((string) $excerpt['element']['attributes']['src']));
$url_parts = $this->parseUrl($url);
$media = null;
@@ -207,7 +207,7 @@ class Excerpts
if ($local_file) {
$filename = Utils::basename($url_parts['path']);
$folder = dirname($url_parts['path']);
$folder = dirname((string) $url_parts['path']);
// Get the local path to page media if possible.
if ($this->page && $folder === $this->page->url(false, false, false)) {
@@ -268,7 +268,7 @@ class Excerpts
// if there is a query, then parse it and build action calls
if (isset($url_parts['query'])) {
$actions = array_reduce(
explode('&', $url_parts['query']),
explode('&', (string) $url_parts['query']),
static function ($carry, $item) {
$parts = explode('=', $item, 2);
$value = $parts[1] ?? null;
@@ -296,10 +296,10 @@ class Excerpts
foreach ($actions as $action) {
$matches = [];
if (preg_match('/\[(.*)\]/', $action['params'], $matches)) {
if (preg_match('/\[(.*)\]/', (string) $action['params'], $matches)) {
$args = [explode(',', $matches[1])];
} else {
$args = explode(',', $action['params']);
$args = explode(',', (string) $action['params']);
}
$medium = call_user_func_array([$medium, $action['method']], $args);

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