Compare commits

...

74 Commits

Author SHA1 Message Date
Andy Miller
34dcd8c346 prepare for beta release 2019-06-14 14:45:29 -06:00
Andy Miller
5079077e1d Merge branch 'develop' into 1.7
# Conflicts:
#	CHANGELOG.md
#	system/defines.php
2019-06-14 14:43:00 -06:00
Andy Miller
1f120a0127 set to beta.1 2019-06-14 13:43:35 -06:00
Andy Miller
fe05c9b87b clockwork debugger by default 2019-06-14 13:43:24 -06:00
Andy Miller
f795a634b5 minor vendor updates 2019-06-14 13:43:13 -06:00
Andy Miller
888b93926c updated changelog 2019-06-14 13:42:47 -06:00
Matias Griese
687f29f912 Profiler: Remove even more noise 2019-06-14 15:17:15 +03:00
Matias Griese
273bc9d970 Profiler: remove some noise 2019-06-14 15:12:48 +03:00
Matias Griese
d593d5a392 Clockwork: Order profiler calls by the time used, some extra filtering 2019-06-14 15:00:17 +03:00
Matias Griese
18fb688cde Clockwork: Added xhprof profiler tab 2019-06-14 14:43:27 +03:00
Matias Griese
d8fccb0edd Clockwork: Added call traces to deprecated messages 2019-06-14 13:48:45 +03:00
Andy Miller
5843347c46 tidy up 2019-06-13 10:04:08 -06:00
Andy Miller
fedb0625b8 z-index fix 2019-06-06 12:09:04 -06:00
Andy Miller
72d012e401 minified 2 2019-06-04 20:11:41 -06:00
Andy Miller
8d77b50055 optimized clockwork css 2019-06-04 20:09:59 -06:00
Andy Miller
42eefbd34c Reworked debugger assets a little 2019-06-04 17:24:56 -06:00
Andy Miller
e5e5bf1bd8 minor twig update 2019-06-04 14:14:16 -06:00
Andy Miller
01ec334127 Merge branch '1.7' into feature/clockwork-twig 2019-06-04 14:07:43 -06:00
Matias Griese
916469a903 Fixed missing timer titles in clockwork 2019-06-04 10:09:57 +03:00
Matias Griese
55f205c801 Composer update 2019-06-04 10:03:54 +03:00
Matias Griese
8a3fc57cd8 Merge branch '1.7' into feature/clockwork-twig
# Conflicts:
#	composer.lock
2019-06-04 10:01:47 +03:00
Andy Miller
6cd1cca4fc Accidentally commited Twig 2 2019-06-03 15:32:28 -06:00
Andy Miller
1c9926ff38 Roll back to Symfony 4.2 until we have some deprecated errors sorted 2019-06-03 15:31:15 -06:00
Andy Miller
638477b06d Roll back to Symfony 4.2 until we have some deprecated errors sorted 2019-06-03 15:31:04 -06:00
Andy Miller
7e3ca73b0e removed unused use 2019-06-03 10:49:25 -06:00
Andy Miller
57a3a20868 Merge branch '1.7' into feature/clockwork-twig
# Conflicts:
#	system/src/Grav/Common/Debugger.php
2019-06-03 10:49:10 -06:00
Matias Griese
4e45c5be95 Properly handle termination in twig redirect and if theme does not exist 2019-06-03 13:05:15 +03:00
Matias Griese
ca89156c4f Added $grav->exit() method to properly terminate the request with a response 2019-06-03 12:10:43 +03:00
Matias Griese
dc5390b3dc Some code cleanup (debugger) 2019-06-03 11:14:22 +03:00
Matias Griese
0e8c7eae99 Added PHP profiling support for redirect responses 2019-06-03 11:08:47 +03:00
Matias Griese
115bdb7e10 Processor cleanup, moved logRequest() and debuggerRequest() into Debugger class 2019-06-03 10:44:10 +03:00
Matias Griese
9738c55633 Clockwork: Added request logging for Grav redirects 2019-06-03 10:29:59 +03:00
Matias Griese
23921c1a35 Some phpstan level 3 fixes 2019-06-03 08:53:25 +03:00
Andy Miller
1f3547b15b Merge branch '1.7' into feature/clockwork-twig 2019-06-02 14:23:40 -06:00
Matias Griese
6974a24669 Some phpstan fixes 2019-06-02 20:30:56 +03:00
Matias Griese
2cf35ec2c7 Composer update, fixed deprecated Twig (1.40 compatible) 2019-06-02 15:19:21 +03:00
Andy Miller
d21bb6b8c7 Merge branch '1.7' into feature/clockwork-twig 2019-05-31 10:59:12 -06:00
Matias Griese
9b8b480c8c Added basic overridable support for the fields 2019-05-31 13:39:23 +03:00
Matias Griese
ac654d56d0 Improved debugger message support 2019-05-31 13:24:06 +03:00
Matias Griese
db9e1a197e Minor fix to support toggleable on required form fields 2019-05-31 13:22:49 +03:00
Matias Griese
19bb9a6966 Regression: Fixed missing timeline name in debugbar 2019-05-30 14:44:02 +03:00
Matias Griese
b7a1c7b72a Added support for Tideways XHProf PHP Extension for profiling requests 2019-05-30 11:59:26 +03:00
Andy Miller
042486bc73 Merge branch 'feature/clockwork-twig' of github.com:getgrav/grav into feature/clockwork-twig 2019-05-30 05:43:48 +02:00
Andy Miller
42cc1c6b01 tweaked arrows 2019-05-30 00:06:45 +02:00
Matias Griese
407d2c8323 Merge branch 'feature/clockwork-twig' of github.com:getgrav/grav into feature/clockwork-twig 2019-05-29 13:54:18 +03:00
Matias Griese
8ab14c0639 Merge branch '1.7' of github.com:getgrav/grav into feature/clockwork-twig 2019-05-29 13:54:07 +03:00
Matias Griese
48c281024f Fixed Twig 2.10 errors 2019-05-29 13:53:29 +03:00
Andy Miller
f7e1bec0cf Very rought first working profiling 2019-05-29 12:33:24 +02:00
Matias Griese
41c7973fc7 Merge branches '1.7' and 'feature/clockwork-twig' of github.com:getgrav/grav into feature/clockwork-twig 2019-05-29 12:07:49 +03:00
Andy Miller
bc93e70d11 Force Twig 2.0 for now (testing and compatibility) 2019-05-29 10:17:59 +02:00
Andy Miller
320ab41435 Initial twig profiler integration..no output yet 2019-05-29 10:16:33 +02:00
Andy Miller
7213c393fd Force Twig 2.0 for now (testing and compatibility) 2019-05-29 10:16:03 +02:00
Andy Miller
6caadc8396 Merge branch '1.7' into feature/clockwork-twig 2019-05-29 09:48:32 +02:00
Andy Miller
e0d1385061 Added default to Utils::param() 2019-05-28 19:52:08 +02:00
Andy Miller
e1eed973a2 field sizes 2019-05-27 19:33:18 +03:00
Andy Miller
f4645fc77e Debugbar/Clockwork Toggle. 2019-05-27 19:20:21 +03:00
Andy Miller
136ec07450 1.7 version in defines 2019-05-27 14:54:16 +03:00
Andy Miller
e01605de55 Merge branch 'feature/clockwork' into feature/clockwork-twig 2019-05-27 13:45:16 +03:00
Andy Miller
5cc48c4e01 initial stuff 2019-05-27 13:45:00 +03:00
Matias Griese
5e2545c606 Improve debugger to have less impact when it's not enabled 2019-05-27 13:42:43 +03:00
Andy Miller
0fd2627cea Merge branch 'feature/clockwork' of github.com:getgrav/grav into feature/clockwork 2019-05-27 11:58:37 +03:00
Andy Miller
cfcd955cc2 Fixed regresssion issue of Utils::Url() not returning false on failure #2524 2019-05-27 11:58:31 +03:00
Matias Griese
7d59b69709 Debugger/Clockwork: add configuration, plugins and streams to the log 2019-05-27 11:26:34 +03:00
Matias Griese
e8eb1d9a44 Debugger: Fixed error if xdebug isn't installed 2019-05-26 17:25:59 +03:00
Andy Miller
2117748f18 updated composer.lock 2019-05-26 17:05:12 +03:00
Matias Griese
e76733e8c3 Optimization: Initialize debugbar only after the configuration has been loaded
Optimization: Combine some early Grav processors into a single one
2019-05-26 16:55:24 +03:00
Matias Griese
2da5f90e9c Merge branch 'develop' of github.com:getgrav/grav into feature/clockwork
# Conflicts:
#	CHANGELOG.md
2019-05-26 16:48:15 +03:00
Matias Griese
81b100cd3b Merge remote-tracking branch 'origin/feature/clockwork' into feature/clockwork 2019-05-26 16:42:56 +03:00
Matias Griese
19be8f5104 Fixed some phpstan level 2 issues 2019-05-26 16:42:36 +03:00
Matias Griese
ad64a9d857 Fixed reutrn type of processMediaActions 2019-05-26 16:24:58 +03:00
Andy Miller
331f416e36 Fixed bitwise operator in TwigExtension::exifFunc() #2518 2019-05-26 11:37:18 +03:00
Matias Griese
3a48c79b21 Merge branch 'develop' of github.com:getgrav/grav into feature/clockwork 2019-05-24 08:39:35 +03:00
Matias Griese
0c66de25c4 Improve clockwork debug messages, make it easier to disable debugbar or clockwork 2019-05-23 23:12:55 +03:00
Matias Griese
0bd227c22d Add basic clockwork support 2019-05-23 15:39:44 +03:00
70 changed files with 2896 additions and 2197 deletions

View File

@@ -1,3 +1,14 @@
# v1.7.0-beta.1
## 06/14/2019
1. [](#new)
* Added support for [Clockwork](https://underground.works/clockwork) developer tools (now default debugger)
* Added support for [Tideways XHProf](https://github.com/tideways/php-xhprof-extension) PHP Extension for profiling method calls
* Added Twig profiling for Clockwork debugger
* Updated Symfony Components to 4.3
* Added support for Twig 2.11 (compatible with Twig 1.40+)
* Added `$grav->exit()` method to properly terminate the request with a response
# v1.6.10
## 06/14/2019
@@ -6,6 +17,8 @@
* Removed `Gitter` and `Slack` [#2502](https://github.com/getgrav/grav/issues/2502)
* Optimizations for Plugin/Theme loading
* Generalized markdown classes so they can be used outside of `Page` scope with a custom `Excerpts` class instance
* Optimization: Initialize debugbar only after the configuration has been loaded
* Optimization: Combine some early Grav processors into a single one
* Change minimal port number to 0 (unix socket) [#2452](https://github.com/getgrav/grav/issues/2452)
1. [](#bugfix)
* Force question to install demo content in theme update [#2493](https://github.com/getgrav/grav/issues/2493)

View File

@@ -24,14 +24,14 @@
"kodus/psr7-server": "*",
"nyholm/psr7": "^1.0",
"twig/twig": "~1.40",
"twig/twig": "~1.0",
"erusev/parsedown": "1.6.4",
"erusev/parsedown-extra": "~0.7",
"symfony/yaml": "~4.2",
"symfony/console": "~4.2",
"symfony/event-dispatcher": "~4.2",
"symfony/var-dumper": "~4.2",
"symfony/process": "~4.2",
"symfony/console": "~4.2.0",
"symfony/event-dispatcher": "~4.2.0",
"symfony/var-dumper": "~4.2.0",
"symfony/process": "~4.2.0",
"doctrine/cache": "^1.8",
"doctrine/collections": "^1.5",
"guzzlehttp/psr7": "^1.4",
@@ -50,7 +50,8 @@
"composer/ca-bundle": "^1.0",
"dragonmantank/cron-expression": "^1.2",
"phive/twig-extensions-deferred": "^1.0",
"willdurand/negotiation": "^2.3"
"willdurand/negotiation": "^2.3",
"itsgoingd/clockwork": "dev-master"
},
"require-dev": {
"codeception/codeception": "^2.4",
@@ -77,6 +78,10 @@
{
"type": "vcs",
"url": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator"
},
{
"type": "vcs",
"url": "https://github.com/itsgoingd/clockwork"
}
],
"autoload": {

320
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f9429e7cd2e75a232f968b01a1024983",
"content-hash": "5be0830ffaa51ba054d7cfbf439fb383",
"packages": [
{
"name": "antoligy/dom-string-iterators",
@@ -183,16 +183,16 @@
},
{
"name": "doctrine/collections",
"version": "v1.6.1",
"version": "v1.6.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
"reference": "d2ae4ef05e25197343b6a39bae1d3c427a2f6956"
"reference": "c5e0bc17b1620e97c968ac409acbff28b8b850be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/collections/zipball/d2ae4ef05e25197343b6a39bae1d3c427a2f6956",
"reference": "d2ae4ef05e25197343b6a39bae1d3c427a2f6956",
"url": "https://api.github.com/repos/doctrine/collections/zipball/c5e0bc17b1620e97c968ac409acbff28b8b850be",
"reference": "c5e0bc17b1620e97c968ac409acbff28b8b850be",
"shasum": ""
},
"require": {
@@ -249,7 +249,7 @@
"iterators",
"php"
],
"time": "2019-03-25T19:03:48+00:00"
"time": "2019-06-09T13:48:14+00:00"
},
{
"name": "donatj/phpuseragentparser",
@@ -658,6 +658,67 @@
],
"time": "2018-12-04T20:46:45+00:00"
},
{
"name": "itsgoingd/clockwork",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/itsgoingd/clockwork.git",
"reference": "71f01a566211397afa67b0fa9f8b2405761c3dad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/71f01a566211397afa67b0fa9f8b2405761c3dad",
"reference": "71f01a566211397afa67b0fa9f8b2405761c3dad",
"shasum": ""
},
"require": {
"php": ">=5.5",
"psr/log": "1.*"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Clockwork\\Support\\Laravel\\ClockworkServiceProvider"
],
"aliases": {
"Clockwork": "Clockwork\\Support\\Laravel\\Facade"
}
}
},
"autoload": {
"psr-4": {
"Clockwork\\": "Clockwork/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "itsgoingd",
"email": "itsgoingd@luzer.sk",
"homepage": "https://twitter.com/itsgoingd"
}
],
"description": "php dev tools integrated to your browser",
"homepage": "https://underground.works/clockwork",
"keywords": [
"debugging",
"devtools",
"laravel",
"logging",
"lumen",
"profiling",
"slim"
],
"support": {
"source": "https://github.com/itsgoingd/clockwork/tree/master",
"issues": "https://github.com/itsgoingd/clockwork/issues"
},
"time": "2019-05-27T11:22:34+00:00"
},
{
"name": "kodus/psr7-server",
"version": "1.0.0",
@@ -1774,16 +1835,16 @@
},
{
"name": "symfony/console",
"version": "v4.2.8",
"version": "v4.2.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81"
"reference": "7a293c9a4587a92e6a0e81edb0bea54071b1b99d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/e2840bb38bddad7a0feaf85931e38fdcffdb2f81",
"reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81",
"url": "https://api.github.com/repos/symfony/console/zipball/7a293c9a4587a92e6a0e81edb0bea54071b1b99d",
"reference": "7a293c9a4587a92e6a0e81edb0bea54071b1b99d",
"shasum": ""
},
"require": {
@@ -1842,25 +1903,32 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2019-04-08T14:23:48+00:00"
"time": "2019-05-09T09:19:46+00:00"
},
{
"name": "symfony/contracts",
"version": "v1.1.0",
"version": "v1.1.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/contracts.git",
"reference": "d3636025e8253c6144358ec0a62773cae588395b"
"reference": "2d19b12caccbd80cf0c85624dc87b7021a0df1d5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/contracts/zipball/d3636025e8253c6144358ec0a62773cae588395b",
"reference": "d3636025e8253c6144358ec0a62773cae588395b",
"url": "https://api.github.com/repos/symfony/contracts/zipball/2d19b12caccbd80cf0c85624dc87b7021a0df1d5",
"reference": "2d19b12caccbd80cf0c85624dc87b7021a0df1d5",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"replace": {
"symfony/cache-contracts": "self.version",
"symfony/event-dispatcher-contracts": "self.version",
"symfony/http-client-contracts": "self.version",
"symfony/service-contracts": "self.version",
"symfony/translation-contracts": "self.version"
},
"require-dev": {
"psr/cache": "^1.0",
"psr/container": "^1.0",
@@ -1869,11 +1937,12 @@
"suggest": {
"psr/cache": "When using the Cache contracts",
"psr/container": "When using the Service contracts",
"symfony/cache-contracts-implementation": "",
"psr/event-dispatcher": "When using the EventDispatcher contracts",
"symfony/cache-implementation": "",
"symfony/event-dispatcher-implementation": "",
"symfony/http-client-contracts-implementation": "",
"symfony/service-contracts-implementation": "",
"symfony/translation-contracts-implementation": ""
"symfony/http-client-implementation": "",
"symfony/service-implementation": "",
"symfony/translation-implementation": ""
},
"type": "library",
"extra": {
@@ -1913,11 +1982,11 @@
"interoperability",
"standards"
],
"time": "2019-04-27T14:29:50+00:00"
"time": "2019-06-05T13:28:50+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.2.8",
"version": "v4.2.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@@ -2270,16 +2339,16 @@
},
{
"name": "symfony/process",
"version": "v4.2.8",
"version": "v4.2.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe"
"reference": "57f11a07b34f009ef64a3f95ad218f895ad95374"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/8cf39fb4ccff793340c258ee7760fd40bfe745fe",
"reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe",
"url": "https://api.github.com/repos/symfony/process/zipball/57f11a07b34f009ef64a3f95ad218f895ad95374",
"reference": "57f11a07b34f009ef64a3f95ad218f895ad95374",
"shasum": ""
},
"require": {
@@ -2315,11 +2384,11 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2019-04-10T16:20:36+00:00"
"time": "2019-05-26T20:47:34+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v4.2.8",
"version": "v4.2.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
@@ -2395,16 +2464,16 @@
},
{
"name": "symfony/yaml",
"version": "v4.2.8",
"version": "v4.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1"
"reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/6712daf03ee25b53abb14e7e8e0ede1a770efdb1",
"reference": "6712daf03ee25b53abb14e7e8e0ede1a770efdb1",
"url": "https://api.github.com/repos/symfony/yaml/zipball/c60ecf5ba842324433b46f58dc7afc4487dbab99",
"reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99",
"shasum": ""
},
"require": {
@@ -2423,7 +2492,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
"dev-master": "4.3-dev"
}
},
"autoload": {
@@ -2450,20 +2519,20 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2019-03-30T15:58:42+00:00"
"time": "2019-04-06T14:04:46+00:00"
},
{
"name": "twig/twig",
"version": "v1.41.0",
"version": "v1.42.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "575cd5028362da591facde1ef5d7b94553c375c9"
"reference": "671347603760a88b1e7288aaa9378f33687d7edf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/575cd5028362da591facde1ef5d7b94553c375c9",
"reference": "575cd5028362da591facde1ef5d7b94553c375c9",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/671347603760a88b1e7288aaa9378f33687d7edf",
"reference": "671347603760a88b1e7288aaa9378f33687d7edf",
"shasum": ""
},
"require": {
@@ -2473,12 +2542,12 @@
"require-dev": {
"psr/container": "^1.0",
"symfony/debug": "^2.7",
"symfony/phpunit-bridge": "^3.4.19|^4.1.8"
"symfony/phpunit-bridge": "^3.4.19|^4.1.8|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.41-dev"
"dev-master": "1.42-dev"
}
},
"autoload": {
@@ -2516,7 +2585,7 @@
"keywords": [
"templating"
],
"time": "2019-05-14T11:59:08+00:00"
"time": "2019-06-04T11:31:08+00:00"
},
{
"name": "willdurand/negotiation",
@@ -2798,16 +2867,16 @@
},
{
"name": "composer/xdebug-handler",
"version": "1.3.2",
"version": "1.3.3",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "d17708133b6c276d6e42ef887a877866b909d892"
"reference": "46867cbf8ca9fb8d60c506895449eb799db1184f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892",
"reference": "d17708133b6c276d6e42ef887a877866b909d892",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f",
"reference": "46867cbf8ca9fb8d60c506895449eb799db1184f",
"shasum": ""
},
"require": {
@@ -2838,7 +2907,7 @@
"Xdebug",
"performance"
],
"time": "2019-01-28T20:25:53+00:00"
"time": "2019-05-27T17:52:04+00:00"
},
{
"name": "doctrine/instantiator",
@@ -2898,16 +2967,16 @@
},
{
"name": "facebook/webdriver",
"version": "1.6.0",
"version": "1.7.1",
"source": {
"type": "git",
"url": "https://github.com/facebook/php-webdriver.git",
"reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e"
"reference": "e43de70f3c7166169d0f14a374505392734160e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/bd8c740097eb9f2fc3735250fc1912bc811a954e",
"reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/e43de70f3c7166169d0f14a374505392734160e5",
"reference": "e43de70f3c7166169d0f14a374505392734160e5",
"shasum": ""
},
"require": {
@@ -2954,7 +3023,7 @@
"selenium",
"webdriver"
],
"time": "2018-05-16T17:37:13+00:00"
"time": "2019-06-13T08:02:18+00:00"
},
{
"name": "fzaninotto/faker",
@@ -3746,16 +3815,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.2.1",
"version": "v4.2.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "5221f49a608808c1e4d436df32884cbc1b821ac0"
"reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/5221f49a608808c1e4d436df32884cbc1b821ac0",
"reference": "5221f49a608808c1e4d436df32884cbc1b821ac0",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bd73cc04c3843ad8d6b0bfc0956026a151fc420",
"reference": "1bd73cc04c3843ad8d6b0bfc0956026a151fc420",
"shasum": ""
},
"require": {
@@ -3793,7 +3862,7 @@
"parser",
"php"
],
"time": "2019-02-16T20:54:15+00:00"
"time": "2019-05-25T20:07:01+00:00"
},
{
"name": "ocramius/package-versions",
@@ -4101,16 +4170,16 @@
},
{
"name": "phpspec/prophecy",
"version": "1.8.0",
"version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06"
"reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
"reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
"reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
"shasum": ""
},
"require": {
@@ -4131,8 +4200,8 @@
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
"psr-4": {
"Prophecy\\": "src/Prophecy"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -4160,20 +4229,20 @@
"spy",
"stub"
],
"time": "2018-08-05T17:53:17+00:00"
"time": "2019-06-13T12:50:23+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "0.3.3",
"version": "0.3.5",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "472d3161d289f652713a5e353532fa4592663a57"
"reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/472d3161d289f652713a5e353532fa4592663a57",
"reference": "472d3161d289f652713a5e353532fa4592663a57",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/8c4ef2aefd9788238897b678a985e1d5c8df6db4",
"reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4",
"shasum": ""
},
"require": {
@@ -4207,20 +4276,20 @@
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"time": "2019-04-23T20:26:19+00:00"
"time": "2019-06-07T19:13:52+00:00"
},
{
"name": "phpstan/phpstan",
"version": "0.11.6",
"version": "0.11.8",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "7af8b9d02b3ab36444dbf4e1b9ca1c1bd5044d81"
"reference": "fcf0081bf3a254ddacffa03e78be87842d0c09c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/7af8b9d02b3ab36444dbf4e1b9ca1c1bd5044d81",
"reference": "7af8b9d02b3ab36444dbf4e1b9ca1c1bd5044d81",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/fcf0081bf3a254ddacffa03e78be87842d0c09c9",
"reference": "fcf0081bf3a254ddacffa03e78be87842d0c09c9",
"shasum": ""
},
"require": {
@@ -4229,10 +4298,11 @@
"nette/bootstrap": "^2.4 || ^3.0",
"nette/di": "^2.4.7 || ^3.0",
"nette/robot-loader": "^3.0.1",
"nette/schema": "^1.0",
"nette/utils": "^2.4.5 || ^3.0",
"nikic/php-parser": "^4.0.2",
"php": "~7.1",
"phpstan/phpdoc-parser": "^0.3",
"phpstan/phpdoc-parser": "^0.3.4",
"symfony/console": "~3.2 || ~4.0",
"symfony/finder": "~3.2 || ~4.0"
},
@@ -4280,26 +4350,26 @@
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"time": "2019-05-08T16:33:56+00:00"
"time": "2019-05-28T19:58:33+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
"version": "0.11",
"version": "0.11.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-deprecation-rules.git",
"reference": "449fee6223220b337760abca4444801ddcc8b38d"
"reference": "5685fe48873efc5af1f2cc95d9c1b8ae82c728fe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/449fee6223220b337760abca4444801ddcc8b38d",
"reference": "449fee6223220b337760abca4444801ddcc8b38d",
"url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/5685fe48873efc5af1f2cc95d9c1b8ae82c728fe",
"reference": "5685fe48873efc5af1f2cc95d9c1b8ae82c728fe",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.0",
"php": "~7.1",
"phpstan/phpstan": "^0.11"
"phpstan/phpstan": "^0.11.8"
},
"require-dev": {
"consistence/coding-standard": "^3.0.1",
@@ -4310,10 +4380,15 @@
"phpunit/phpunit": "^7.0",
"slevomat/coding-standard": "^4.5.2"
},
"type": "library",
"type": "phpstan-extension",
"extra": {
"branch-alias": {
"dev-master": "0.11-dev"
},
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"autoload": {
@@ -4326,7 +4401,7 @@
"MIT"
],
"description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
"time": "2018-12-05T18:04:16+00:00"
"time": "2019-05-28T19:54:04+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -4484,16 +4559,16 @@
},
{
"name": "phpunit/php-timer",
"version": "2.1.1",
"version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "8b389aebe1b8b0578430bda0c7c95a829608e059"
"reference": "1038454804406b0b5f5f520358e78c1c2f71501e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059",
"reference": "8b389aebe1b8b0578430bda0c7c95a829608e059",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e",
"reference": "1038454804406b0b5f5f520358e78c1c2f71501e",
"shasum": ""
},
"require": {
@@ -4529,7 +4604,7 @@
"keywords": [
"timer"
],
"time": "2019-02-20T10:12:59+00:00"
"time": "2019-06-07T04:22:29+00:00"
},
{
"name": "phpunit/php-token-stream",
@@ -4582,16 +4657,16 @@
},
{
"name": "phpunit/phpunit",
"version": "7.5.11",
"version": "7.5.12",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6"
"reference": "9ba59817745b0fe0c1a5a3032dfd4a6d2994ad1c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/64cb33f5b520da490a7b13149d39b43cf3c890c6",
"reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9ba59817745b0fe0c1a5a3032dfd4a6d2994ad1c",
"reference": "9ba59817745b0fe0c1a5a3032dfd4a6d2994ad1c",
"shasum": ""
},
"require": {
@@ -4662,7 +4737,7 @@
"testing",
"xunit"
],
"time": "2019-05-14T04:53:02+00:00"
"time": "2019-05-28T11:59:40+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@@ -5232,16 +5307,16 @@
},
{
"name": "symfony/browser-kit",
"version": "v4.2.8",
"version": "v4.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "c09c18cca96d7067152f78956faf55346c338283"
"reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/c09c18cca96d7067152f78956faf55346c338283",
"reference": "c09c18cca96d7067152f78956faf55346c338283",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/e07d50e84b8cf489590f22244f4f609579b4a2c4",
"reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4",
"shasum": ""
},
"require": {
@@ -5250,6 +5325,8 @@
},
"require-dev": {
"symfony/css-selector": "~3.4|~4.0",
"symfony/http-client": "^4.3",
"symfony/mime": "^4.3",
"symfony/process": "~3.4|~4.0"
},
"suggest": {
@@ -5258,7 +5335,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
"dev-master": "4.3-dev"
}
},
"autoload": {
@@ -5285,20 +5362,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2019-04-07T09:56:43+00:00"
"time": "2019-05-30T16:10:05+00:00"
},
{
"name": "symfony/css-selector",
"version": "v4.2.8",
"version": "v4.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "48eddf66950fa57996e1be4a55916d65c10c604a"
"reference": "105c98bb0c5d8635bea056135304bd8edcc42b4d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/48eddf66950fa57996e1be4a55916d65c10c604a",
"reference": "48eddf66950fa57996e1be4a55916d65c10c604a",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/105c98bb0c5d8635bea056135304bd8edcc42b4d",
"reference": "105c98bb0c5d8635bea056135304bd8edcc42b4d",
"shasum": ""
},
"require": {
@@ -5307,7 +5384,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
"dev-master": "4.3-dev"
}
},
"autoload": {
@@ -5338,20 +5415,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2019-01-16T20:31:39+00:00"
"time": "2019-01-16T21:53:39+00:00"
},
{
"name": "symfony/dom-crawler",
"version": "v4.2.8",
"version": "v4.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "53c97769814c80a84a8403efcf3ae7ae966d53bb"
"reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/53c97769814c80a84a8403efcf3ae7ae966d53bb",
"reference": "53c97769814c80a84a8403efcf3ae7ae966d53bb",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/06ee58fbc9a8130f1d35b5280e15235a0515d457",
"reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457",
"shasum": ""
},
"require": {
@@ -5359,7 +5436,11 @@
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"masterminds/html5": "<2.6"
},
"require-dev": {
"masterminds/html5": "^2.6",
"symfony/css-selector": "~3.4|~4.0"
},
"suggest": {
@@ -5368,7 +5449,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
"dev-master": "4.3-dev"
}
},
"autoload": {
@@ -5395,20 +5476,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2019-02-23T15:17:42+00:00"
"time": "2019-05-31T18:55:30+00:00"
},
{
"name": "symfony/finder",
"version": "v4.2.8",
"version": "v4.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "e45135658bd6c14b61850bf131c4f09a55133f69"
"reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/e45135658bd6c14b61850bf131c4f09a55133f69",
"reference": "e45135658bd6c14b61850bf131c4f09a55133f69",
"url": "https://api.github.com/repos/symfony/finder/zipball/b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176",
"reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176",
"shasum": ""
},
"require": {
@@ -5417,7 +5498,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
"dev-master": "4.3-dev"
}
},
"autoload": {
@@ -5444,20 +5525,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2019-04-06T13:51:08+00:00"
"time": "2019-05-26T20:47:49+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.1.2",
"version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8"
"reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8",
"reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
"reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
"shasum": ""
},
"require": {
@@ -5484,7 +5565,7 @@
}
],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"time": "2019-04-04T09:56:43+00:00"
"time": "2019-06-13T22:48:21+00:00"
},
{
"name": "victorjonsson/markdowndocs",
@@ -5587,6 +5668,7 @@
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"itsgoingd/clockwork": 20,
"victorjonsson/markdowndocs": 20
},
"prefer-stable": false,

View File

@@ -1,70 +0,0 @@
div.phpdebugbar {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.phpdebugbar pre {
padding: 1rem;
}
.phpdebugbar div.phpdebugbar-header > div > * {
padding: 5px 15px;
}
.phpdebugbar div.phpdebugbar-header > div.phpdebugbar-header-right > * {
padding: 5px 8px;
}
.phpdebugbar div.phpdebugbar-header, .phpdebugbar a.phpdebugbar-restore-btn {
background-image: url(grav.png);
}
.phpdebugbar a.phpdebugbar-restore-btn {
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

@@ -0,0 +1,2 @@
/** Clockwork Debugger CSS **/
.clockwork-badge{position:fixed;z-index:10;bottom:0;left:0;padding:2px 4px;background-color:#eee;border:1px solid #ddd;display:flex;align-items:center}.clockwork-badge:hover{width:auto}.clockwork-badge:hover:after{content:'Grav Clockwork Debugger Enabled...You need to install the Clockwork browser extensions to see output...'}.clockwork-badge:after{margin-left:10px;font-family:Monaco,Consolas,"Lucida Console",monospace;font-size:12px;line-height:1.5;color:#c00}.clockwork-badge i{display:block;float:left;height:22px;width:22px;background-size:contain;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==)}

View File

@@ -0,0 +1,2 @@
/** Clockwork Debugger JS **/
document.addEventListener("DOMContentLoaded",function(){var e=document.createElement("div");e.appendChild(document.createElement("i")),e.className="clockwork-badge",document.body.appendChild(e)});

View File

@@ -0,0 +1,70 @@
div.phpdebugbar {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.phpdebugbar pre {
padding: 1rem;
}
.phpdebugbar div.phpdebugbar-header > div > * {
padding: 5px 15px;
}
.phpdebugbar div.phpdebugbar-header > div.phpdebugbar-header-right > * {
padding: 5px 8px;
}
.phpdebugbar div.phpdebugbar-header, .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==);
}
.phpdebugbar a.phpdebugbar-restore-btn {
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;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -125,6 +125,7 @@ log:
debugger:
enabled: false # Enable Grav debugger and following settings
provider: clockwork # Debugger provider: debugbar | clockwork
shutdown:
close_connection: true # Close the connection before calling onShutdown(). false for debugging
@@ -154,7 +155,7 @@ session:
path:
gpm:
releases: stable # Set to either 'stable' or 'testing'
releases: testing # Set to either 'stable' or 'testing'
proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128)
method: 'auto' # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL
verify_peer: true # Sometimes on some systems (Windows most commonly) GPM is unable to connect because the SSL certificate cannot be verified. Disabling this setting might help.

View File

@@ -8,8 +8,8 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.6.10');
define('GRAV_TESTING', false);
define('GRAV_VERSION', '1.7.0-beta.1');
define('GRAV_TESTING', true);
define('DS', '/');
if (!defined('GRAV_PHP_MIN')) {

View File

@@ -244,8 +244,8 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|| !empty($field['disabled'])
// Field validation is set to be ignored
|| !empty($field['validate']['ignore'])
// Field is toggleable and the toggle is turned off
|| (!empty($field['toggleable']) && empty($toggles[$key]))
// Field is overridable and the toggle is turned off
|| (!empty($field['overridable']) && empty($toggles[$key]))
) {
continue;
}
@@ -279,6 +279,12 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
continue;
}
// Skip overridable fields without value.
// TODO: We need better overridable support, which is not just ignoring required values but also looking if defaults are good.
if (!empty($field['overridable']) && !isset($data[$name])) {
continue;
}
// Check if required.
if (isset($field['validate']['required'])
&& $field['validate']['required'] === true) {

View File

@@ -9,6 +9,14 @@
namespace Grav\Common;
use Clockwork\Clockwork;
use Clockwork\DataSource\MonologDataSource;
use Clockwork\DataSource\PhpDataSource;
use Clockwork\DataSource\PsrMessageDataSource;
use Clockwork\DataSource\XdebugDataSource;
use Clockwork\Helpers\ServerTiming;
use Clockwork\Request\UserData;
use Clockwork\Storage\FileStorage;
use DebugBar\DataCollector\ConfigCollector;
use DebugBar\DataCollector\DataCollectorInterface;
use DebugBar\DataCollector\ExceptionsCollector;
@@ -22,11 +30,23 @@ use DebugBar\JavascriptRenderer;
use DebugBar\StandardDebugBar;
use Grav\Common\Config\Config;
use Grav\Common\Processors\ProcessorInterface;
use Grav\Common\Twig\TwigClockworkDataSource;
use Grav\Framework\Psr7\Response;
use Monolog\Logger;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use RocketTheme\Toolbox\Event\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Twig\Environment;
use Twig\Template;
use Twig\TemplateWrapper;
class Debugger
{
/** @var static */
protected static $instance;
/** @var Grav $grav */
protected $grav;
@@ -39,8 +59,11 @@ class Debugger
/** @var StandardDebugBar $debugbar */
protected $debugbar;
/** @var Clockwork */
protected $clockwork;
/** @var bool */
protected $enabled;
protected $enabled = false;
protected $initialized = false;
@@ -53,36 +76,36 @@ class Debugger
/** @var callable */
protected $errorHandler;
protected $requestTime;
protected $currentTime;
/** @var int */
protected $profiling = 0;
/**
* Debugger constructor.
*/
public function __construct()
{
$currentTime = microtime(true);
static::$instance = $this;
$this->currentTime = microtime(true);
if (!\defined('GRAV_REQUEST_TIME')) {
\define('GRAV_REQUEST_TIME', $currentTime);
\define('GRAV_REQUEST_TIME', $this->currentTime);
}
// Enable debugger until $this->init() gets called.
$this->enabled = true;
$debugbar = new DebugBar();
$debugbar->addCollector(new PhpInfoCollector());
$debugbar->addCollector(new MessagesCollector());
$debugbar->addCollector(new RequestDataCollector());
$debugbar->addCollector(new TimeDataCollector($_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME));
$debugbar['time']->addMeasure('Server', $debugbar['time']->getRequestStartTime(), GRAV_REQUEST_TIME);
$debugbar['time']->addMeasure('Loading', GRAV_REQUEST_TIME, $currentTime);
$debugbar['time']->addMeasure('Debugger', $currentTime, microtime(true));
$this->debugbar = $debugbar;
$this->requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME;
// Set deprecation collector.
$this->setErrorHandler();
}
public function getClockwork(): ?Clockwork
{
return $this->enabled ? $this->clockwork : null;
}
/**
* Initialize the debugger
*
@@ -101,24 +124,214 @@ class Debugger
// Enable/disable debugger based on configuration.
$this->enabled = (bool)$this->config->get('system.debugger.enabled');
if ($this->enabled()) {
if ($this->enabled) {
$this->initialized = true;
$plugins_config = (array)$this->config->get('plugins');
$clockwork = $debugbar = null;
switch ($this->config->get('system.debugger.provider', 'debugbar')) {
case 'clockwork':
$this->clockwork = $clockwork = new Clockwork();
break;
default:
$this->debugbar = $debugbar = new DebugBar();
}
$plugins_config = (array)$this->config->get('plugins');
ksort($plugins_config);
$debugbar = $this->debugbar;
$debugbar->addCollector(new MemoryCollector());
$debugbar->addCollector(new ExceptionsCollector());
$debugbar->addCollector(new ConfigCollector((array)$this->config->get('system'), 'Config'));
$debugbar->addCollector(new ConfigCollector($plugins_config, 'Plugins'));
$this->addMessage('Grav v' . GRAV_VERSION);
if ($clockwork) {
$log = $this->grav['log'];
$clockwork->setStorage(new FileStorage(GRAV_ROOT . '/cache/clockwork'));
$clockwork->addDataSource(new PhpDataSource());
if (extension_loaded('xdebug')) {
$clockwork->addDataSource(new XdebugDataSource());
}
if ($log instanceof Logger) {
$clockwork->addDataSource(new MonologDataSource($log));
}
$clockwork->addDataSource(new TwigClockworkDataSource());
$timeLine = $clockwork->getTimeline();
if ($this->requestTime !== GRAV_REQUEST_TIME) {
$timeLine->addEvent('server', 'Server', $this->requestTime, GRAV_REQUEST_TIME);
}
if ($this->currentTime !== GRAV_REQUEST_TIME) {
$timeLine->addEvent('loading', 'Loading', GRAV_REQUEST_TIME, $this->currentTime);
}
$timeLine->addEvent('setup', 'Site Setup', $this->currentTime, microtime(true));
}
if ($debugbar) {
$debugbar->addCollector(new PhpInfoCollector());
$debugbar->addCollector(new MessagesCollector());
$debugbar->addCollector(new RequestDataCollector());
$debugbar->addCollector(new TimeDataCollector($this->requestTime));
$debugbar->addCollector(new MemoryCollector());
$debugbar->addCollector(new ExceptionsCollector());
$debugbar->addCollector(new ConfigCollector((array)$this->config->get('system'), 'Config'));
$debugbar->addCollector(new ConfigCollector($plugins_config, 'Plugins'));
if ($this->requestTime !== GRAV_REQUEST_TIME) {
$debugbar['time']->addMeasure('Server', $debugbar['time']->getRequestStartTime(), GRAV_REQUEST_TIME);
}
if ($this->currentTime !== GRAV_REQUEST_TIME) {
$debugbar['time']->addMeasure('Loading', GRAV_REQUEST_TIME, $this->currentTime);
}
$debugbar['time']->addMeasure('Site Setup', $this->currentTime, microtime(true));
}
$this->addMessage('Grav v' . GRAV_VERSION . ' - PHP ' . PHP_VERSION);
$this->config->debug();
if ($clockwork) {
$clockwork->info('System Configuration', $this->config->get('system'));
$clockwork->info('Plugins Configuration', $plugins_config);
$clockwork->info('Streams', $this->config->get('streams.schemes'));
}
}
return $this;
}
public function finalize(): void
{
if ($this->clockwork && $this->enabled) {
$this->stopProfiling('Profiler Analysis');
$this->addMeasures();
$deprecations = $this->getDeprecations();
$count = count($deprecations);
if (!$count) {
return;
}
/** @var UserData $userData */
$userData = $this->clockwork->userData('Deprecated');
$userData->counters([
'Deprecated' => count($deprecations)
]);
foreach ($deprecations as &$deprecation) {
if (0) {
$d = $deprecation;
unset($d['message']);
$this->clockwork->log('deprecated', $deprecation['message'], $d);
}
}
unset($deprecation);
$userData->table('Your site is using following deprecated features', $deprecations);
}
}
public function logRequest(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
if (!$this->enabled || !$this->clockwork) {
return $response;
}
$clockwork = $this->clockwork;
$this->finalize();
$clockwork->getTimeline()->finalize($request->getAttribute('request_time'));
$clockwork->addDataSource(new PsrMessageDataSource($request, $response));
$clockwork->resolveRequest();
$clockwork->storeRequest();
$clockworkRequest = $clockwork->getRequest();
$response = $response
->withHeader('X-Clockwork-Id', $clockworkRequest->id)
->withHeader('X-Clockwork-Version', $clockwork::VERSION);
$basePath = $request->getAttribute('base_uri');
if ($basePath) {
$response = $response->withHeader('X-Clockwork-Path', $basePath . '/__clockwork/');
}
return $response->withHeader('Server-Timing', ServerTiming::fromRequest($clockworkRequest)->value());
}
public function debuggerRequest(RequestInterface $request): Response
{
$clockwork = $this->clockwork;
$headers = [
'Content-Type' => 'application/json',
'Grav-Internal-SkipShutdown' => 1
];
$path = $request->getUri()->getPath();
$clockworkDataUri = '#/__clockwork(?:/(?<id>[0-9-]+))?(?:/(?<direction>(?:previous|next)))?(?:/(?<count>\d+))?#';
if (preg_match($clockworkDataUri, $path, $matches) === false) {
$response = ['message' => 'Bad Input'];
return new Response(400, $headers, json_encode($response));
}
$id = $matches['id'] ?? null;
$direction = $matches['direction'] ?? null;
$count = $matches['count'] ?? null;
$storage = $clockwork->getStorage();
if ($direction === 'previous') {
$data = $storage->previous($id, $count);
} elseif ($direction === 'next') {
$data = $storage->next($id, $count);
} elseif ($id === 'latest') {
$data = $storage->latest();
} else {
$data = $storage->find($id);
}
if (preg_match('#(?<id>[0-9-]+|latest)/extended#', $path)) {
$clockwork->extendRequest($data);
}
if (!$data) {
$response = ['message' => 'Not Found'];
return new Response(404, $headers, json_encode($response));
}
$data = is_array($data) ? array_map(function ($item) { return $item->toArray(); }, $data) : $data->toArray();
return new Response(200, $headers, json_encode($data));
}
protected function addMeasures()
{
if (!$this->enabled) {
return;
}
$nowTime = microtime(true);
$clkTimeLine = $this->clockwork ? $this->clockwork->getTimeline() : null;
$debTimeLine = $this->debugbar ? $this->debugbar['time'] : null;
foreach ($this->timers as $name => $data) {
$description = $data[0];
$startTime = $data[1] ?? null;
$endTime = $data[2] ?? $nowTime;
if ($endTime - $startTime < 0.001) {
continue;
}
if ($clkTimeLine) {
$clkTimeLine->addEvent($name, $description ?? $name, $startTime, $endTime);
}
if ($debTimeLine) {
$debTimeLine->addMeasure($description ?? $name, $startTime, $endTime);
}
}
$this->timers = [];
}
/**
* Set/get the enabled state of the debugger
*
@@ -142,7 +355,8 @@ class Debugger
*/
public function addAssets()
{
if ($this->enabled()) {
if ($this->enabled) {
// Only add assets if Page is HTML
$page = $this->grav['page'];
@@ -153,23 +367,35 @@ class Debugger
/** @var Assets $assets */
$assets = $this->grav['assets'];
// Add jquery library
$assets->add('jquery', 101);
$this->renderer = $this->debugbar->getJavascriptRenderer();
$this->renderer->setIncludeVendors(false);
// Get the required CSS files
list($css_files, $js_files) = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
foreach ((array)$css_files as $css) {
$assets->addCss($css);
// Clockwork specific assets
if ($this->clockwork) {
$assets->addCss('/system/assets/debugger/clockwork.css', ['loading' => 'inline']);
$assets->addJs('/system/assets/debugger/clockwork.js', ['loading' => 'inline']);
}
$assets->addCss('/system/assets/debugger.css');
foreach ((array)$js_files as $js) {
$assets->addJs($js);
// Debugbar specific assets
if ($this->debugbar) {
// Add jquery library
$assets->add('jquery', 101);
$this->renderer = $this->debugbar->getJavascriptRenderer();
$this->renderer->setIncludeVendors(false);
list($css_files, $js_files) = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
foreach ((array)$css_files as $css) {
$assets->addCss($css);
}
$assets->addCss('/system/assets/debugger/phpdebugbar.css', ['loading' => 'inline']);
foreach ((array)$js_files as $js) {
$assets->addJs($js);
}
}
}
return $this;
@@ -192,7 +418,9 @@ class Debugger
*/
public function addCollector($collector)
{
$this->debugbar->addCollector($collector);
if ($this->debugbar) {
$this->debugbar->addCollector($collector);
}
return $this;
}
@@ -207,7 +435,11 @@ class Debugger
*/
public function getCollector($collector)
{
return $this->debugbar->getCollector($collector);
if ($this->debugbar) {
return $this->debugbar->getCollector($collector);
}
return null;
}
/**
@@ -217,13 +449,14 @@ class Debugger
*/
public function render()
{
if ($this->enabled()) {
if ($this->enabled && $this->debugbar) {
// Only add assets if Page is HTML
$page = $this->grav['page'];
if (!$this->renderer || $page->templateFormat() !== 'html') {
return $this;
}
$this->addMeasures();
$this->addDeprecations();
echo $this->renderer->render();
@@ -239,7 +472,8 @@ class Debugger
*/
public function sendDataInHeaders()
{
if ($this->enabled()) {
if ($this->enabled && $this->debugbar) {
$this->addMeasures();
$this->addDeprecations();
$this->debugbar->sendDataInHeaders();
}
@@ -254,16 +488,146 @@ class Debugger
*/
public function getData()
{
if (!$this->enabled()) {
if (!$this->enabled || !$this->debugbar) {
return null;
}
$this->addMeasures();
$this->addDeprecations();
$this->timers = [];
return $this->debugbar->getData();
}
/**
* Hierarchical Profiler support.
*
* @param callable $callable
* @param string $message
* @return mixed
*/
public function profile(callable $callable, string $message = null)
{
$this->startProfiling();
$response = $callable();
$this->stopProfiling($message);
return $response;
}
/**
* Start profiling code.
*/
public function startProfiling(): void
{
if ($this->enabled && extension_loaded('tideways_xhprof')) {
$this->profiling++;
if ($this->profiling === 1) {
\tideways_xhprof_enable(TIDEWAYS_XHPROF_FLAGS_NO_BUILTINS);
}
}
}
/**
* Stop profiling code. Returns profiling array or null if profiling couldn't be done.
*
* @param string $message
* @return array|null
*/
public function stopProfiling(string $message = null): ?array
{
$timings = null;
if ($this->enabled && extension_loaded('tideways_xhprof')) {
$profiling = $this->profiling - 1;
if ($profiling === 0) {
$timings = \tideways_xhprof_disable();
$timings = $this->buildProfilerTimings($timings);
if ($this->clockwork) {
/** @var UserData $userData */
$userData = $this->clockwork->userData('Profiler');
$userData->counters([
'Calls' => count($timings)
]);
$userData->table('Profiler', $timings);
} else {
$this->addMessage($message ?? 'Profiler Analysis', 'debug', $timings);
}
}
$this->profiling = max(0, $profiling);
}
return $timings;
}
protected function buildProfilerTimings(array $timings): array
{
// Filter method calls which take almost no time.
$timings = array_filter($timings, function ($value) {
return $value['wt'] > 50;
});
uasort($timings, function (array $a, array $b) {
return $b['wt'] <=> $a['wt'];
});
$table = [];
foreach ($timings as $key => $timing) {
$parts = explode('==>', $key);
$method = $this->parseProfilerCall(array_pop($parts));
$context = $this->parseProfilerCall(array_pop($parts));
// Skip redundant method calls.
if ($context === 'Grav\Framework\RequestHandler\RequestHandler::handle()') {
continue;
}
// Do not profile library calls.
if (strpos($context, 'Grav\\') !== 0) {
continue;
}
$table[] = [
'Context' => $context,
'Method' => $method,
'Calls' => $timing['ct'],
'Time (ms)' => $timing['wt'] / 1000,
];
}
return $table;
}
protected function parseProfilerCall(?string $call)
{
if (null === $call) {
return '';
}
if (strpos($call, '@')) {
[$call,] = explode('@', $call);
}
if (strpos($call, '::')) {
[$class, $call] = explode('::', $call);
}
if (!isset($class)) {
return $call;
}
// It is also possible to display twig files, but they are being logged in views.
/*
if (strpos($class, '__TwigTemplate_') === 0 && class_exists($class)) {
$env = new Environment();
/ ** @var Template $template * /
$template = new $class($env);
return $template->getTemplateName();
}
*/
return "{$class}::{$call}()";
}
/**
* Start a timer with an associated name and description
*
@@ -274,10 +638,7 @@ class Debugger
*/
public function startTimer($name, $description = null)
{
if (strpos($name, '_') === 0 || $this->enabled()) {
$this->debugbar['time']->startMeasure($name, $description);
$this->timers[] = $name;
}
$this->timers[$name] = [$description, microtime(true)];
return $this;
}
@@ -291,8 +652,9 @@ class Debugger
*/
public function stopTimer($name)
{
if (\in_array($name, $this->timers, true) && (strpos($name, '_') === 0 || $this->enabled())) {
$this->debugbar['time']->stopMeasure($name);
if (isset($this->timers[$name])) {
$endTime = microtime(true);
$this->timers[$name][] = $endTime;
}
return $this;
@@ -303,14 +665,38 @@ class Debugger
*
* @param mixed $message
* @param string $label
* @param bool $isString
* @param array|bool $isString
*
* @return $this
*/
public function addMessage($message, $label = 'info', $isString = true)
{
if ($this->enabled()) {
$this->debugbar['messages']->addMessage($message, $label, $isString);
if ($this->enabled) {
if ($this->debugbar) {
$this->debugbar['messages']->addMessage($message, $label, is_bool($isString) ? $isString : true);
if (is_array($isString)) {
$this->debugbar['messages']->addMessage($isString, $label, false);
}
}
if ($this->clockwork) {
$this->clockwork->log($label, $message, is_array($isString) ? $isString : []);
}
}
return $this;
}
public function addEvent(string $name, ?Event $event, EventDispatcherInterface $dispatcher)
{
if ($this->enabled) {
if ($this->clockwork) {
$listeners = [];
foreach ($dispatcher->getListeners($name) as $listener) {
$listeners[] = $this->resolveCallable($listener);
}
$this->clockwork->addEvent($name, null, microtime(true), ['listeners' => $listeners]);
}
}
return $this;
@@ -324,8 +710,18 @@ class Debugger
*/
public function addException(\Exception $e)
{
if ($this->initialized && $this->enabled()) {
$this->debugbar['exceptions']->addException($e);
if ($this->initialized && $this->enabled) {
if ($this->debugbar) {
$this->debugbar['exceptions']->addException($e);
}
if ($this->clockwork) {
/** @var UserData $exceptions */
$exceptions = $this->clockwork->userData('Exceptions');
$exceptions->data(['message' => $e->getMessage()]);
$this->clockwork->alert($e->getMessage(), ['exception' => $e]);
}
}
return $this;
@@ -355,7 +751,7 @@ class Debugger
return true;
}
if (!$this->enabled()) {
if (!$this->enabled) {
return true;
}
@@ -540,6 +936,21 @@ class Debugger
return true;
}
protected function getDeprecations(): array
{
if (!$this->deprecations) {
return [];
}
$list = [];
/** @var array $deprecated */
foreach ($this->deprecations as $deprecated) {
$list[] = $this->getDepracatedMessage($deprecated)[0];
}
return $list;
}
protected function addDeprecations()
{
if (!$this->deprecations) {
@@ -603,4 +1014,13 @@ class Debugger
return $trace['function'] . '(' . implode(', ', $trace['args'] ?? []) . ')';
}
protected function resolveCallable(callable $callable)
{
if (is_array($callable)) {
return get_class($callable[0]) . '->' . $callable[1] . '()';
}
return 'unknown';
}
}

View File

@@ -11,6 +11,9 @@ namespace Grav\Common\GPM\Common;
use Grav\Common\Data\Data;
/**
* @property string $name
*/
class Package
{
/**

View File

@@ -16,12 +16,8 @@ use Grav\Common\Page\Medium\ImageMedium;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Processors\AssetsProcessor;
use Grav\Common\Processors\BackupsProcessor;
use Grav\Common\Processors\ConfigurationProcessor;
use Grav\Common\Processors\DebuggerAssetsProcessor;
use Grav\Common\Processors\DebuggerProcessor;
use Grav\Common\Processors\ErrorsProcessor;
use Grav\Common\Processors\InitializeProcessor;
use Grav\Common\Processors\LoggerProcessor;
use Grav\Common\Processors\PagesProcessor;
use Grav\Common\Processors\PluginsProcessor;
use Grav\Common\Processors\RenderProcessor;
@@ -90,10 +86,6 @@ class Grav extends Container
* @var array All middleware processors that are processed in $this->process()
*/
protected $middleware = [
'configurationProcessor',
'loggerProcessor',
'errorsProcessor',
'debuggerProcessor',
'initializeProcessor',
'pluginsProcessor',
'themesProcessor',
@@ -157,15 +149,13 @@ class Grav extends Container
$this->initialized['setup'] = true;
$this->measureTime('_setup', 'Site Setup', function () use ($environment) {
// Force environment if passed to the method.
if ($environment) {
Setup::$environment = $environment;
}
// Force environment if passed to the method.
if ($environment) {
Setup::$environment = $environment;
}
$this['setup'];
$this['streams'];
});
$this['setup'];
$this['streams'];
return $this;
}
@@ -186,18 +176,6 @@ class Grav extends Container
$container = new Container(
[
'configurationProcessor' => function () {
return new ConfigurationProcessor($this);
},
'loggerProcessor' => function () {
return new LoggerProcessor($this);
},
'errorsProcessor' => function () {
return new ErrorsProcessor($this);
},
'debuggerProcessor' => function () {
return new DebuggerProcessor($this);
},
'initializeProcessor' => function () {
return new InitializeProcessor($this);
},
@@ -237,13 +215,10 @@ class Grav extends Container
]
);
$default = function (ServerRequestInterface $request) {
$default = static function () {
return new Response(404);
};
/** @var Debugger $debugger */
$debugger = $this['debugger'];
$collection = new RequestHandler($this->middleware, $default, $container);
$response = $collection->handle($this['request']);
@@ -251,32 +226,56 @@ class Grav extends Container
$this->header($response);
echo $response->getBody();
$debugger->render();
$this['debugger']->render();
register_shutdown_function([$this, 'shutdown']);
}
/**
* Set the system locale based on the language and configuration
*/
public function setLocale()
{
// 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);
} elseif ($this['config']->get('system.default_locale')) {
setlocale(LC_ALL, $this['config']->get('system.default_locale'));
// Response object can turn off all shutdown processing. This can be used for example to speed up AJAX responses.
// Note that using this feature will also turn off response compression.
if ($response->getHeaderLine('Grav-Internal-SkipShutdown') !== '1') {
register_shutdown_function([$this, 'shutdown']);
}
}
/**
* Redirect browser to another location.
* Terminates Grav request with a response.
*
* Please use this method instead of calling `die();` or `exit();`. Note that you need to create a response object.
*
* @param ResponseInterface $response
*/
public function exit(ResponseInterface $response): void
{
// Make sure nothing extra gets written to the response.
while (ob_get_level()) {
ob_end_clean();
}
// Close the session.
if (isset($this['session'])) {
$this['session']->close();
}
/** @var ServerRequestInterface $request */
$request = $this['request'];
/** @var Debugger $debugger */
$debugger = $this['debugger'];
$response = $debugger->logRequest($request, $response);
// Send the response and terminate.
$this->header($response);
echo $response->getBody();
exit();
}
/**
* Terminates Grav request and redirects browser to another location.
*
* Please use this method instead of calling `header("Location: {$url}", true, 302); exit();`.
*
* @param string $route Internal route.
* @param int $code Redirection code (30x)
*/
public function redirect($route, $code = null)
public function redirect($route, $code = null): void
{
/** @var Uri $uri */
$uri = $this['uri'];
@@ -293,11 +292,7 @@ class Grav extends Container
$code = $this['config']->get('system.pages.redirect_default_code', 302);
}
if (isset($this['session'])) {
$this['session']->close();
}
if ($uri->isExternal($route)) {
if ($uri::isExternal($route)) {
$url = $route;
} else {
$url = rtrim($uri->rootUrl(), '/') . '/';
@@ -309,8 +304,9 @@ class Grav extends Container
}
}
header("Location: {$url}", true, $code);
exit();
$response = new Response($code, ['Location' => $url]);
$this->exit($response);
}
/**
@@ -343,12 +339,30 @@ 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) {
continue;
}
foreach ($values as $i => $value) {
header($key . ': ' . $value, $i === 0);
}
}
}
/**
* Set the system locale based on the language and configuration
*/
public function setLocale()
{
// 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);
} elseif ($this['config']->get('system.default_locale')) {
setlocale(LC_ALL, $this['config']->get('system.default_locale'));
}
}
/**
* Fires an event with optional parameters.
*
@@ -362,6 +376,10 @@ class Grav extends Container
/** @var EventDispatcher $events */
$events = $this['events'];
/** @var Debugger $debugger */
$debugger = $this['debugger'];
$debugger->addEvent($eventName, $event, $events);
return $events->dispatch($eventName, $event);
}
@@ -470,9 +488,7 @@ class Grav extends Container
return $container;
};
$container->measureTime('_services', 'Services', function () use ($container) {
$container->registerServices();
});
$container->registerServices();
return $container;
}

View File

@@ -190,7 +190,7 @@ class Truncator {
* Clean extra code
*
* @param DOMDocument $doc
* @param $container
* @param DOMDocument $container
* @return string
*/
private static function getCleanedHTML(DOMDocument $doc, $container)
@@ -203,8 +203,7 @@ class Truncator {
$doc->appendChild($container->firstChild);
}
$html = trim($doc->saveHTML());
return $html;
return trim($doc->saveHTML());
}
/**
@@ -242,17 +241,20 @@ class Truncator {
$ending = '...',
$exact = false,
$considerHtml = true
) {
)
{
if ($considerHtml) {
// if the plain text is shorter than the maximum length, return the whole text
if (strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
return $text;
}
// splits all html-tags to scanable lines
preg_match_all('/(<.+?>)?([^<>]*)/s', $text, $lines, PREG_SET_ORDER);
$total_length = strlen($ending);
$open_tags = array();
$truncate = '';
$open_tags = [];
foreach ($lines as $line_matchings) {
// if there is any html-tag in this line, handle it and add it (uncounted) to the output
if (!empty($line_matchings[1])) {
@@ -308,22 +310,22 @@ class Truncator {
} else {
if (strlen($text) <= $length) {
return $text;
} else {
$truncate = substr($text, 0, $length - strlen($ending));
}
$truncate = substr($text, 0, $length - strlen($ending));
}
// if the words shouldn't be cut in the middle...
if (!$exact) {
// ...search the last occurance of a space...
$spacepos = strrpos($truncate, ' ');
if (isset($spacepos)) {
if (false !== $spacepos) {
// ...and cut the text in this position
$truncate = substr($truncate, 0, $spacepos);
}
}
// add the defined ending to the text
$truncate .= $ending;
if($considerHtml) {
if (isset($open_tags)) {
// close all unclosed html-tags
foreach ($open_tags as $tag) {
$truncate .= '</' . $tag . '>';

View File

@@ -64,7 +64,7 @@ interface PageContentInterface
*
* @param string|null $var
*
* @return null
* @return string
*/
public function rawMarkdown($var = null);
@@ -167,7 +167,7 @@ interface PageContentInterface
*
* @param int $var
*
* @return int|bool
* @return string|bool
*/
public function order($var = null);

View File

@@ -229,9 +229,9 @@ interface PageLegacyInterface
* Allows a page to override the output render format, usually the extension provided
* in the URL. (e.g. `html`, `json`, `xml`, etc).
*
* @param null $var
* @param string|null $var
*
* @return null
* @return string
*/
public function templateFormat($var = null);

View File

@@ -109,7 +109,7 @@ class ImageFile extends Image
* Gets the hash.
* @param string $type
* @param int $quality
* @param [] $extras
* @param array $extras
* @return null
*/
public function getHash($type = 'guess', $quality = 80, $extras = [])

View File

@@ -97,7 +97,7 @@ class Page implements PageInterface
protected $forms;
/**
* @var PageInterface Unmodified (original) version of the page. Used for copying and moving the page.
* @var PageInterface|null Unmodified (original) version of the page. Used for copying and moving the page.
*/
private $_original;
@@ -784,7 +784,7 @@ class Page implements PageInterface
*
* @param string|null $name
*
* @return string
* @return string|null
*/
public function getContentMeta($name = null)
{
@@ -1374,9 +1374,9 @@ class Page implements PageInterface
* Allows a page to override the output render format, usually the extension provided
* in the URL. (e.g. `html`, `json`, `xml`, etc).
*
* @param null $var
* @param string|null $var
*
* @return null
* @return string
*/
public function templateFormat($var = null)
{
@@ -1784,7 +1784,7 @@ class Page implements PageInterface
*
* @param int $var
*
* @return int|bool
* @return string|bool
*/
public function order($var = null)
{

View File

@@ -28,81 +28,54 @@ use Collator;
class Pages
{
/**
* @var Grav
*/
/** @var Grav */
protected $grav;
/**
* @var array|PageInterface[]
*/
/** @var PageInterface[] */
protected $instances;
/**
* @var array|string[]
*/
/** @var array */
protected $children;
/**
* @var string
*/
/** @var string */
protected $base = '';
/**
* @var array|string[]
*/
/** @var string[] */
protected $baseRoute = [];
/**
* @var array|string[]
*/
/** @var string[] */
protected $routes = [];
/**
* @var array
*/
/** @var array */
protected $sort;
/**
* @var Blueprints
*/
/** @var Blueprints */
protected $blueprints;
/**
* @var int
*/
/** @var int */
protected $last_modified;
/**
* @var array|string[]
*/
/** @var string[] */
protected $ignore_files;
/**
* @var array|string[]
*/
/** @var string[] */
protected $ignore_folders;
/**
* @var bool
*/
/** @var bool */
protected $ignore_hidden;
/** @var string */
protected $check_method;
/**
* @var Types
*/
/** @var string */
protected $pages_cache_id;
/** @var Types */
static protected $types;
/**
* @var string
*/
/** @var string|null */
static protected $home_route;
protected $pages_cache_id;
/**
* Constructor
*
@@ -299,14 +272,16 @@ class Pages
*/
public function addPage(PageInterface $page, $route = null)
{
if (!isset($this->instances[$page->path()])) {
$this->instances[$page->path()] = $page;
$path = $page->path() ?? '';
if (!isset($this->instances[$path])) {
$this->instances[$path] = $page;
}
$route = $page->route($route);
if ($page->parent()) {
$this->children[$page->parent()->path()][$page->path()] = ['slug' => $page->slug()];
$parentPath = $page->parent()->path() ?? '';
$this->children[$parentPath][$path] = ['slug' => $page->slug()];
}
$this->routes[$route] = $page->path();
$this->routes[$route] = $path;
$this->grav->fireEvent('onPageProcessed', new Event(['page' => $page]));
}

View File

@@ -18,7 +18,7 @@ class AssetsProcessor extends ProcessorBase
public $id = '_assets';
public $title = 'Assets';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
$this->container['assets']->init();

View File

@@ -18,7 +18,7 @@ class BackupsProcessor extends ProcessorBase
public $id = '_backups';
public $title = 'Backups';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
$backups = $this->container['backups'];

View File

@@ -1,30 +0,0 @@
<?php
/**
* @package Grav\Common\Processors
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Processors;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ConfigurationProcessor extends ProcessorBase
{
public $id = '_config';
public $title = 'Configuration';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$this->startTimer();
$this->container['config']->init();
$this->container['plugins']->setup();
$this->stopTimer();
return $handler->handle($request);
}
}

View File

@@ -19,7 +19,7 @@ class DebuggerAssetsProcessor extends ProcessorBase
public $id = 'debugger_assets';
public $title = 'Debugger Assets';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
$this->container['debugger']->addAssets();

View File

@@ -1,29 +0,0 @@
<?php
/**
* @package Grav\Common\Processors
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Processors;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class DebuggerProcessor extends ProcessorBase
{
public $id = '_debugger';
public $title = 'Init Debugger';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$this->startTimer();
$this->container['debugger']->init();
$this->stopTimer();
return $handler->handle($request);
}
}

View File

@@ -1,29 +0,0 @@
<?php
/**
* @package Grav\Common\Processors
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Processors;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ErrorsProcessor extends ProcessorBase
{
public $id = '_errors';
public $title = 'Error Handlers Reset';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$this->startTimer();
$this->container['errors']->resetHandlers();
$this->stopTimer();
return $handler->handle($request);
}
}

View File

@@ -10,25 +10,121 @@
namespace Grav\Common\Processors;
use Grav\Common\Config\Config;
use Grav\Common\Debugger;
use Grav\Common\Uri;
use Grav\Common\Utils;
use Grav\Framework\Psr7\Response;
use Grav\Framework\Session\Exceptions\SessionException;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\SyslogHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class InitializeProcessor extends ProcessorBase
{
public $id = 'init';
public $id = '_init';
public $title = 'Initialize';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
$config = $this->initializeConfig();
$this->initializeLogger($config);
$this->initializeErrors();
$this->startTimer('_debugger', 'Init Debugger');
/** @var Debugger $debugger */
$debugger = $this->container['debugger']->init();
// Clockwork integration.
$clockwork = $debugger->getClockwork();
if ($clockwork) {
$server = $request->getServerParams();
$baseUri = parse_url(dirname($server['PHP_SELF']), PHP_URL_PATH);
if ($baseUri === '/') {
$baseUri = '';
}
$requestTime = $_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME;
$request = $request
->withAttribute('base_uri', $baseUri)
->withAttribute('request_time', $requestTime);
// Handle clockwork API calls.
$uri = $request->getUri();
if (mb_strpos($uri->getPath(), $baseUri . '/__clockwork/') === 0) {
return $debugger->debuggerRequest($request);
}
$this->container['clockwork'] = $clockwork;
}
$this->stopTimer('_debugger');
$this->initialize($config);
$this->initializeSession($config);
// Wrap call to next handler so that debugger can profile it.
/** @var Response $response */
$response = $debugger->profile(function () use ($handler, $request) {
return $handler->handle($request);
});
// Log both request and response and return the response.
return $debugger->logRequest($request, $response);
}
protected function initializeConfig(): Config
{
$this->startTimer('_config', 'Configuration');
// Initialize Configuration
$grav = $this->container;
/** @var Config $config */
$config = $this->container['config'];
$config->debug();
$config = $grav['config'];
$config->init();
$grav['plugins']->setup();
$this->stopTimer('_config');
return $config;
}
protected function initializeLogger(Config $config): void
{
$this->startTimer('_logger', 'Logger');
// Initialize Logging
$grav = $this->container;
switch ($config->get('system.log.handler', 'file')) {
case 'syslog':
$log = $grav['log'];
$log->popHandler();
$facility = $config->get('system.log.syslog.facility', 'local6');
$logHandler = new SyslogHandler('grav', $facility);
$formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
$logHandler->setFormatter($formatter);
$log->pushHandler($logHandler);
break;
}
$this->stopTimer('_logger');
}
protected function initializeErrors(): void
{
$this->startTimer('_errors', 'Error Handlers Reset');
// Initialize Error Handlers
$this->container['errors']->resetHandlers();
$this->stopTimer('_errors');
}
protected function initialize(Config $config): void
{
$this->startTimer('_init', 'Initialize');
// Use output buffering to prevent headers from being sent too early.
ob_start();
@@ -43,21 +139,6 @@ class InitializeProcessor extends ProcessorBase
date_default_timezone_set($timezone);
}
// FIXME: Initialize session should happen later after plugins have been loaded. This is a workaround to fix session issues in AWS.
if (isset($this->container['session']) && $config->get('system.session.initialize', true)) {
// TODO: remove in 2.0.
$this->container['accounts'];
try {
$this->container['session']->init();
} catch (SessionException $e) {
$this->container['session']->init();
$message = 'Session corruption detected, restarting session...';
$this->addMessage($message);
$this->container['messages']->add($message, 'error');
}
}
/** @var Uri $uri */
$uri = $this->container['uri'];
$uri->init();
@@ -73,8 +154,29 @@ class InitializeProcessor extends ProcessorBase
}
$this->container->setLocale();
$this->stopTimer();
return $handler->handle($request);
$this->stopTimer('_init');
}
protected function initializeSession(Config $config): void
{
// FIXME: Initialize session should happen later after plugins have been loaded. This is a workaround to fix session issues in AWS.
if (isset($this->container['session']) && $config->get('system.session.initialize', true)) {
$this->startTimer('_session', 'Start Session');
// TODO: remove in 2.0.
$this->container['accounts'];
try {
$this->container['session']->init();
} catch (SessionException $e) {
$this->container['session']->init();
$message = 'Session corruption detected, restarting session...';
$this->addMessage($message);
$this->container['messages']->add($message, 'error');
}
$this->stopTimer('_session');
}
}
}

View File

@@ -1,50 +0,0 @@
<?php
/**
* @package Grav\Common\Processors
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Processors;
use Grav\Common\Config\Config;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\SyslogHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class LoggerProcessor extends ProcessorBase
{
public $id = '_logger';
public $title = 'Logger';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
$this->startTimer();
$grav = $this->container;
/** @var Config $config */
$config = $grav['config'];
switch ($config->get('system.log.handler', 'file')) {
case 'syslog':
$log = $grav['log'];
$log->popHandler();
$facility = $config->get('system.log.syslog.facility', 'local6');
$logHandler = new SyslogHandler('grav', $facility);
$formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
$logHandler->setFormatter($formatter);
$log->pushHandler($logHandler);
break;
}
$this->stopTimer();
return $handler->handle($request);
}
}

View File

@@ -20,7 +20,7 @@ class PagesProcessor extends ProcessorBase
public $id = 'pages';
public $title = 'Pages';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();

View File

@@ -18,7 +18,7 @@ class PluginsProcessor extends ProcessorBase
public $id = 'plugins';
public $title = 'Plugins';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
// TODO: remove in 2.0.

View File

@@ -25,21 +25,21 @@ abstract class ProcessorBase implements ProcessorInterface
$this->container = $container;
}
protected function startTimer($id = null, $title = null)
protected function startTimer($id = null, $title = null): void
{
/** @var Debugger $debugger */
$debugger = $this->container['debugger'];
$debugger->startTimer($id ?? $this->id, $title ?? $this->title);
}
protected function stopTimer($id = null)
protected function stopTimer($id = null): void
{
/** @var Debugger $debugger */
$debugger = $this->container['debugger'];
$debugger->stopTimer($id ?? $this->id);
}
protected function addMessage($message, $label = 'info', $isString = true)
protected function addMessage($message, $label = 'info', $isString = true): void
{
/** @var Debugger $debugger */
$debugger = $this->container['debugger'];

View File

@@ -20,7 +20,7 @@ class RenderProcessor extends ProcessorBase
public $id = 'render';
public $title = 'Render';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();

View File

@@ -20,7 +20,7 @@ class RequestProcessor extends ProcessorBase
public $id = 'request';
public $title = 'Request';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();

View File

@@ -19,7 +19,7 @@ class SchedulerProcessor extends ProcessorBase
public $id = '_scheduler';
public $title = 'Scheduler';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
$scheduler = $this->container['scheduler'];

View File

@@ -19,7 +19,7 @@ class TasksProcessor extends ProcessorBase
public $id = 'tasks';
public $title = 'Tasks';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();

View File

@@ -18,7 +18,7 @@ class ThemesProcessor extends ProcessorBase
public $id = 'themes';
public $title = 'Themes';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
$this->container['themes']->init();

View File

@@ -18,7 +18,7 @@ class TwigProcessor extends ProcessorBase
public $id = 'twig';
public $title = 'Twig';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->startTimer();
$this->container['twig']->init();

View File

@@ -21,12 +21,20 @@ class Scheduler
/**
* The queued jobs.
*
* @var array
* @var Job[]
*/
private $jobs = [];
/** @var Job[] */
private $saved_jobs = [];
/** @var Job[] */
private $executed_jobs = [];
/** @var Job[] */
private $failed_jobs = [];
/** @var Job[] */
private $jobs_run = [];
private $output_schedule = [];
private $config;
@@ -49,6 +57,8 @@ class Scheduler
/**
* Load saved jobs from config/scheduler.yaml file
*
* @return $this
*/
public function loadSavedJobs()
{
@@ -65,7 +75,7 @@ class Scheduler
}
if (isset($j['output'])) {
$mode = isset($j['output_mode']) && $j['output_mode'] === 'append' ? true : false;
$mode = isset($j['output_mode']) && $j['output_mode'] === 'append';
$job->output($j['output'], $mode);
}
@@ -106,7 +116,7 @@ class Scheduler
/**
* Get all jobs if they are disabled or not as one array
*
* @return array
* @return Job[]
*/
public function getAllJobs()
{
@@ -184,6 +194,8 @@ class Scheduler
* Reset all collected data of last run.
*
* Call before run() if you call run() multiple times.
*
* @return $this
*/
public function resetRun()
{
@@ -199,7 +211,7 @@ class Scheduler
* Get the scheduler verbose output.
*
* @param string $type Allowed: text, html, array
* @return mixed The return depends on the requested $type
* @return string|array The return depends on the requested $type
*/
public function getVerboseOutput($type = 'text')
{
@@ -217,6 +229,8 @@ class Scheduler
/**
* Remove all queued Jobs.
*
* @return $this
*/
public function clearJobs()
{
@@ -263,7 +277,7 @@ class Scheduler
/**
* Get the Job states file
*
* @return \RocketTheme\Toolbox\File\FileInterface|YamlFile
* @return YamlFile
*/
public function getJobStates()
{
@@ -296,7 +310,6 @@ class Scheduler
* Queue a job for execution in the correct queue.
*
* @param Job $job
* @return void
*/
private function queueJob(Job $job)
{
@@ -309,7 +322,6 @@ class Scheduler
* Add an entry to the scheduler verbose output array.
*
* @param string $string
* @return void
*/
private function addSchedulerVerboseOutput($string)
{

View File

@@ -30,11 +30,11 @@ class Theme extends Plugin
/**
* Get configuration of the plugin.
*
* @return Config
* @return array
*/
public function config()
{
return $this->config["themes.{$this->name}"];
return $this->config["themes.{$this->name}"] ?? [];
}
/**
@@ -42,7 +42,7 @@ class Theme extends Plugin
*
* @param string $theme_name The name of the theme whose config it should store.
*
* @return true
* @return bool
*/
public static function saveConfig($theme_name)
{

View File

@@ -13,6 +13,7 @@ use Grav\Common\Config\Config;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Data\Blueprints;
use Grav\Common\Data\Data;
use Grav\Framework\Psr7\Response;
use RocketTheme\Toolbox\Event\EventDispatcher;
use RocketTheme\Toolbox\Event\EventSubscriberInterface;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
@@ -128,7 +129,7 @@ class Themes extends Iterator
*
* @param string $name
*
* @return Data
* @return Data|null
* @throws \RuntimeException
*/
public function get($name)
@@ -214,7 +215,9 @@ class Themes extends Iterator
}
}
} elseif (!$locator('theme://') && !defined('GRAV_CLI')) {
exit("Theme '$name' does not exist, unable to display page.");
$response = new Response(500, [], "Theme '$name' does not exist, unable to display page.");
$grav->exit($response);
}
$this->config->set('theme', $config->get('themes.' . $name));

View File

@@ -28,7 +28,7 @@ class TwigNodeMarkdown extends Node implements NodeOutputInterface
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig_Compiler instance
* @param Compiler $compiler A Twig Compiler instance
*/
public function compile(Compiler $compiler)
{

View File

@@ -33,12 +33,15 @@ class TwigNodeRender extends Node implements NodeCaptureInterface
$tag = null
)
{
parent::__construct(['object' => $object, 'layout' => $layout, 'context' => $context], [], $lineno, $tag);
$nodes = ['object' => $object, 'layout' => $layout, 'context' => $context];
$nodes = array_filter($nodes);
parent::__construct($nodes, [], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig_Compiler instance
* @param Compiler $compiler A Twig Compiler instance
* @throws \LogicException
*/
public function compile(Compiler $compiler)
@@ -46,15 +49,15 @@ class TwigNodeRender extends Node implements NodeCaptureInterface
$compiler->addDebugInfo($this);
$compiler->write('$object = ')->subcompile($this->getNode('object'))->raw(';' . PHP_EOL);
$layout = $this->getNode('layout');
if ($layout) {
if ($this->hasNode('layout')) {
$layout = $this->getNode('layout');
$compiler->write('$layout = ')->subcompile($layout)->raw(';' . PHP_EOL);
} else {
$compiler->write('$layout = null;' . PHP_EOL);
}
$context = $this->getNode('context');
if ($context) {
if ($this->hasNode('context')) {
$context = $this->getNode('context');
$compiler->write('$attributes = ')->subcompile($context)->raw(';' . PHP_EOL);
} else {
$compiler->write('$attributes = null;' . PHP_EOL);

View File

@@ -29,21 +29,24 @@ class TwigNodeScript extends Node implements NodeCaptureInterface
* @param string|null $tag
*/
public function __construct(
Node $body = null,
AbstractExpression $file = null,
AbstractExpression $group = null,
AbstractExpression $priority = null,
AbstractExpression $attributes = null,
?Node $body,
?AbstractExpression $file,
?AbstractExpression $group,
?AbstractExpression $priority,
?AbstractExpression $attributes,
$lineno = 0,
$tag = null
)
{
parent::__construct(['body' => $body, 'file' => $file, 'group' => $group, 'priority' => $priority, 'attributes' => $attributes], [], $lineno, $tag);
$nodes = ['body' => $body, 'file' => $file, 'group' => $group, 'priority' => $priority, 'attributes' => $attributes];
$nodes = array_filter($nodes);
parent::__construct($nodes, [], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig_Compiler instance
* @param Compiler $compiler A Twig Compiler instance
* @throws \LogicException
*/
public function compile(Compiler $compiler)
@@ -52,7 +55,7 @@ class TwigNodeScript extends Node implements NodeCaptureInterface
$compiler->write("\$assets = \\Grav\\Common\\Grav::instance()['assets'];\n");
if ($this->getNode('attributes') !== null) {
if ($this->hasNode('attributes')) {
$compiler
->write('$attributes = ')
->subcompile($this->getNode('attributes'))
@@ -66,7 +69,7 @@ class TwigNodeScript extends Node implements NodeCaptureInterface
$compiler->write('$attributes = [];' . "\n");
}
if ($this->getNode('group') !== null) {
if ($this->hasNode('group')) {
$compiler
->write("\$attributes['group'] = ")
->subcompile($this->getNode('group'))
@@ -78,14 +81,14 @@ class TwigNodeScript extends Node implements NodeCaptureInterface
->write("}\n");
}
if ($this->getNode('priority') !== null) {
if ($this->hasNode('priority')) {
$compiler
->write("\$attributes['priority'] = (int)(")
->subcompile($this->getNode('priority'))
->raw(");\n");
}
if ($this->getNode('file') !== null) {
if ($this->hasNode('file')) {
$compiler
->write('$assets->addJs(')
->subcompile($this->getNode('file'))

View File

@@ -29,21 +29,24 @@ class TwigNodeStyle extends Node implements NodeCaptureInterface
* @param string|null $tag
*/
public function __construct(
Node $body = null,
AbstractExpression $file = null,
AbstractExpression $group = null,
AbstractExpression $priority = null,
AbstractExpression $attributes = null,
?Node $body,
?AbstractExpression $file,
?AbstractExpression $group,
?AbstractExpression $priority,
?AbstractExpression $attributes,
$lineno = 0,
$tag = null
)
{
parent::__construct(['body' => $body, 'file' => $file, 'group' => $group, 'priority' => $priority, 'attributes' => $attributes], [], $lineno, $tag);
$nodes = ['body' => $body, 'file' => $file, 'group' => $group, 'priority' => $priority, 'attributes' => $attributes];
$nodes = array_filter($nodes);
parent::__construct($nodes, [], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig_Compiler instance
* @param Compiler $compiler A Twig Compiler instance
* @throws \LogicException
*/
public function compile(Compiler $compiler)
@@ -52,7 +55,7 @@ class TwigNodeStyle extends Node implements NodeCaptureInterface
$compiler->write("\$assets = \\Grav\\Common\\Grav::instance()['assets'];\n");
if ($this->getNode('attributes') !== null) {
if ($this->hasNode('attributes')) {
$compiler
->write('$attributes = ')
->subcompile($this->getNode('attributes'))
@@ -66,7 +69,7 @@ class TwigNodeStyle extends Node implements NodeCaptureInterface
$compiler->write('$attributes = [];' . "\n");
}
if ($this->getNode('group') !== null) {
if ($this->hasNode('group')) {
$compiler
->write("\$attributes['group'] = ")
->subcompile($this->getNode('group'))
@@ -78,14 +81,14 @@ class TwigNodeStyle extends Node implements NodeCaptureInterface
->write("}\n");
}
if ($this->getNode('priority') !== null) {
if ($this->hasNode('priority')) {
$compiler
->write("\$attributes['priority'] = (int)(")
->subcompile($this->getNode('priority'))
->raw(");\n");
}
if ($this->getNode('file') !== null) {
if ($this->hasNode('file')) {
$compiler
->write('$assets->addCss(')
->subcompile($this->getNode('file'))

View File

@@ -30,13 +30,16 @@ class TwigNodeSwitch extends Node
$tag = null
)
{
parent::__construct(array('value' => $value, 'cases' => $cases, 'default' => $default), array(), $lineno, $tag);
$nodes = ['value' => $value, 'cases' => $cases, 'default' => $default];
$nodes = array_filter($nodes);
parent::__construct($nodes, [], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig_Compiler instance
* @param Compiler $compiler A Twig Compiler instance
*/
public function compile(Compiler $compiler)
{
@@ -68,7 +71,7 @@ class TwigNodeSwitch extends Node
->write("}\n");
}
if ($this->hasNode('default') && $this->getNode('default') !== null) {
if ($this->hasNode('default')) {
$compiler
->write("default:\n")
->write("{\n")

View File

@@ -34,7 +34,7 @@ class TwigNodeThrow extends Node
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig_Compiler instance
* @param Compiler $compiler A Twig Compiler instance
* @throws \LogicException
*/
public function compile(Compiler $compiler)

View File

@@ -28,13 +28,16 @@ class TwigNodeTryCatch extends Node
$tag = null
)
{
parent::__construct(['try' => $try, 'catch' => $catch], [], $lineno, $tag);
$nodes = ['try' => $try, 'catch' => $catch];
$nodes = array_filter($nodes);
parent::__construct($nodes, [], $lineno, $tag);
}
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig_Compiler instance
* @param Compiler $compiler A Twig Compiler instance
* @throws \LogicException
*/
public function compile(Compiler $compiler)
@@ -50,7 +53,7 @@ class TwigNodeTryCatch extends Node
->subcompile($this->getNode('try'))
;
if ($this->hasNode('catch') && null !== $this->getNode('catch')) {
if ($this->hasNode('catch')) {
$compiler
->outdent()
->write('} catch (\Exception $e) {' . "\n")

View File

@@ -24,9 +24,9 @@ class TwigTokenParserRender extends AbstractTokenParser
/**
* Parses a token and returns a node.
*
* @param Token $token A Twig_Token instance
* @param Token $token A Twig Token instance
*
* @return Node A Twig_Node instance
* @return Node A Twig Node instance
*/
public function parse(Token $token)
{

View File

@@ -29,9 +29,9 @@ class TwigTokenParserScript extends AbstractTokenParser
/**
* Parses a token and returns a node.
*
* @param Token $token A Twig_Token instance
* @param Token $token A Twig Token instance
*
* @return Node A Twig_Node instance
* @return Node A Twig Node instance
*/
public function parse(Token $token)
{

View File

@@ -28,9 +28,9 @@ class TwigTokenParserStyle extends AbstractTokenParser
/**
* Parses a token and returns a node.
*
* @param Token $token A Twig_Token instance
* @param Token $token A Twig Token instance
*
* @return Node A Twig_Node instance
* @return Node A Twig Node instance
*/
public function parse(Token $token)
{

View File

@@ -26,9 +26,9 @@ class TwigTokenParserThrow extends AbstractTokenParser
/**
* Parses a token and returns a node.
*
* @param Token $token A Twig_Token instance
* @param Token $token A Twig Token instance
*
* @return Node A Twig_Node instance
* @return Node A Twig Node instance
*/
public function parse(Token $token)
{

View File

@@ -30,9 +30,9 @@ class TwigTokenParserTryCatch extends AbstractTokenParser
/**
* Parses a token and returns a node.
*
* @param Token $token A Twig_Token instance
* @param Token $token A Twig Token instance
*
* @return Node A Twig_Node instance
* @return Node A Twig Node instance
*/
public function parse(Token $token)
{

View File

@@ -18,11 +18,21 @@ use Grav\Common\Page\Pages;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RocketTheme\Toolbox\Event\Event;
use Phive\Twig\Extensions\Deferred\DeferredExtension;
use Twig\Cache\FilesystemCache;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Extension\CoreExtension;
use Twig\Extension\DebugExtension;
use Twig\Loader\ArrayLoader;
use Twig\Loader\ChainLoader;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFilter;
use Twig\TwigFunction;
class Twig
{
/**
* @var \Twig_Environment
* @var Environment
*/
public $twig;
@@ -47,18 +57,20 @@ class Twig
protected $grav;
/**
* @var \Twig_Loader_Filesystem
* @var FilesystemLoader
*/
protected $loader;
/**
* @var \Twig_Loader_Array
* @var ArrayLoader
*/
protected $loaderArray;
protected $autoescape;
protected $profile;
/**
* Constructor
*
@@ -102,7 +114,7 @@ class Twig
$core_templates = array_merge($locator->findResources('system://templates'), $locator->findResources('system://templates/testing'));
$this->twig_paths = array_merge($this->twig_paths, $core_templates);
$this->loader = new \Twig_Loader_Filesystem($this->twig_paths);
$this->loader = new FilesystemLoader($this->twig_paths);
// Register all other prefixes as namespaces in twig
foreach ($locator->getPaths('theme') as $prefix => $_) {
@@ -128,13 +140,13 @@ class Twig
$this->grav->fireEvent('onTwigLoader');
$this->loaderArray = new \Twig_Loader_Array([]);
$loader_chain = new \Twig_Loader_Chain([$this->loaderArray, $this->loader]);
$this->loaderArray = new ArrayLoader([]);
$loader_chain = new ChainLoader([$this->loaderArray, $this->loader]);
$params = $config->get('system.twig');
if (!empty($params['cache'])) {
$cachePath = $locator->findResource('cache://twig', true, true);
$params['cache'] = new \Twig_Cache_Filesystem($cachePath, \Twig_Cache_Filesystem::FORCE_BYTECODE_INVALIDATION);
$params['cache'] = new FilesystemCache($cachePath, FilesystemCache::FORCE_BYTECODE_INVALIDATION);
}
if (!$config->get('system.strict_mode.twig_compat', true)) {
@@ -153,10 +165,10 @@ class Twig
if ($config->get('system.twig.undefined_functions')) {
$this->twig->registerUndefinedFunctionCallback(function ($name) {
if (function_exists($name)) {
return new \Twig_SimpleFunction($name, $name);
return new TwigFunction($name, $name);
}
return new \Twig_SimpleFunction($name, function () {
return new TwigFunction($name, function () {
});
});
}
@@ -164,10 +176,10 @@ class Twig
if ($config->get('system.twig.undefined_filters')) {
$this->twig->registerUndefinedFilterCallback(function ($name) {
if (function_exists($name)) {
return new \Twig_SimpleFilter($name, $name);
return new TwigFilter($name, $name);
}
return new \Twig_SimpleFilter($name, function () {
return new TwigFilter($name, function () {
});
});
}
@@ -176,17 +188,21 @@ class Twig
// set default date format if set in config
if ($config->get('system.pages.dateformat.long')) {
/** @var \Twig_Extension_Core $extension */
$extension = $this->twig->getExtension('Twig_Extension_Core');
/** @var CoreExtension $extension */
$extension = $this->twig->getExtension(CoreExtension::class);
$extension->setDateFormat($config->get('system.pages.dateformat.long'));
}
// enable the debug extension if required
if ($config->get('system.twig.debug')) {
$this->twig->addExtension(new \Twig_Extension_Debug());
$this->twig->addExtension(new DebugExtension());
}
$this->twig->addExtension(new TwigExtension());
$this->twig->addExtension(new DeferredExtension());
$this->profile = new \Twig\Profiler\Profile();
$this->twig->addExtension(new \Twig\Extension\ProfilerExtension($this->profile));
$this->grav->fireEvent('onTwigExtensions');
/** @var Pages $pages */
@@ -219,7 +235,7 @@ class Twig
}
/**
* @return \Twig_Environment
* @return Environment
*/
public function twig()
{
@@ -227,13 +243,19 @@ class Twig
}
/**
* @return \Twig_Loader_Filesystem
* @return FilesystemLoader
*/
public function loader()
{
return $this->loader;
}
public function profile()
{
return $this->profile;
}
/**
* Adds or overrides a template.
*
@@ -254,7 +276,6 @@ class Twig
* @param string $content Optional content override
*
* @return string The rendered output
* @throws \Twig_Error_Loader
*/
public function processPage(PageInterface $item, $content = null)
{
@@ -288,7 +309,7 @@ class Twig
$output = $local_twig->render($name, $twig_vars);
}
} catch (\Twig_Error_Loader $e) {
} catch (LoaderError $e) {
throw new \RuntimeException($e->getRawMessage(), 404, $e);
}
@@ -312,7 +333,7 @@ class Twig
try {
$output = $this->twig->render($template, $vars);
} catch (\Twig_Error_Loader $e) {
} catch (LoaderError $e) {
throw new \RuntimeException($e->getRawMessage(), 404, $e);
}
@@ -341,7 +362,7 @@ class Twig
try {
$output = $this->twig->render($name, $vars);
} catch (\Twig_Error_Loader $e) {
} catch (LoaderError $e) {
throw new \RuntimeException($e->getRawMessage(), 404, $e);
}
@@ -386,14 +407,14 @@ class Twig
try {
$output = $this->twig->render($template, $vars + $twig_vars);
} catch (\Twig_Error_Loader $e) {
} catch (LoaderError $e) {
$error_msg = $e->getMessage();
// Try html version of this template if initial template was NOT html
if ($ext !== '.html' . TWIG_EXT) {
try {
$page->templateFormat('html');
$output = $this->twig->render($page->template() . '.html' . TWIG_EXT, $vars + $twig_vars);
} catch (\Twig_Error_Loader $e) {
} catch (LoaderError $e) {
throw new \RuntimeException($error_msg, 400, $e);
}
} else {
@@ -405,9 +426,10 @@ class Twig
}
/**
* Wraps the Twig_Loader_Filesystem addPath method (should be used only in `onTwigLoader()` event
* Wraps the FilesystemLoader addPath method (should be used only in `onTwigLoader()` event
* @param string $template_path
* @param string $namespace
* @throws LoaderError
*/
public function addPath($template_path, $namespace = '__main__')
{
@@ -415,9 +437,10 @@ class Twig
}
/**
* Wraps the Twig_Loader_Filesystem prependPath method (should be used only in `onTwigLoader()` event
* Wraps the FilesystemLoader prependPath method (should be used only in `onTwigLoader()` event
* @param string $template_path
* @param string $namespace
* @throws LoaderError
*/
public function prependPath($template_path, $namespace = '__main__')
{

View File

@@ -0,0 +1,53 @@
<?php
/**
* @package Grav\Common\Twig
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Twig;
use Clockwork\DataSource\DataSource;
use Clockwork\Request\Request;
use Clockwork\Request\Timeline;
use Grav\Common\Grav;
class TwigClockworkDataSource extends DataSource
{
/**
* Views data structure
*/
protected $views;
protected $root;
/**
* TwigClockworkDataSource constructor.
*/
public function __construct()
{
$this->views = new Timeline();
}
/**
* Resolves and adds the Twig profiler data to the request
*
* @param Request $request
* @return Request
*/
public function resolve(Request $request)
{
$profile = Grav::instance()['twig']->profile();
if ($profile) {
$processor = new TwigProfileProcessor();
$processor->process($profile, $this->views);
$request->viewsData = $this->views->finalize();
}
return $request;
}
}

View File

@@ -9,7 +9,9 @@
namespace Grav\Common\Twig;
class TwigEnvironment extends \Twig_Environment
use Twig\Environment;
class TwigEnvironment extends Environment
{
use WriteCacheFileTrait;
}

View File

@@ -29,9 +29,16 @@ use Grav\Common\User\Interfaces\UserInterface;
use Grav\Common\Utils;
use Grav\Common\Yaml;
use Grav\Common\Helpers\Base32;
use Grav\Framework\Psr7\Response;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Twig\Environment;
use Twig\Extension\AbstractExtension;
use Twig\Extension\GlobalsInterface;
use Twig\Loader\FilesystemLoader;
use Twig\TwigFilter;
use Twig\TwigFunction;
class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsInterface
class TwigExtension extends AbstractExtension implements GlobalsInterface
{
/** @var Grav */
protected $grav;
@@ -72,60 +79,60 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
public function getFilters()
{
return [
new \Twig_SimpleFilter('*ize', [$this, 'inflectorFilter']),
new \Twig_SimpleFilter('absolute_url', [$this, 'absoluteUrlFilter']),
new \Twig_SimpleFilter('contains', [$this, 'containsFilter']),
new \Twig_SimpleFilter('chunk_split', [$this, 'chunkSplitFilter']),
new \Twig_SimpleFilter('nicenumber', [$this, 'niceNumberFunc']),
new \Twig_SimpleFilter('nicefilesize', [$this, 'niceFilesizeFunc']),
new \Twig_SimpleFilter('nicetime', [$this, 'nicetimeFunc']),
new \Twig_SimpleFilter('defined', [$this, 'definedDefaultFilter']),
new \Twig_SimpleFilter('ends_with', [$this, 'endsWithFilter']),
new \Twig_SimpleFilter('fieldName', [$this, 'fieldNameFilter']),
new \Twig_SimpleFilter('ksort', [$this, 'ksortFilter']),
new \Twig_SimpleFilter('ltrim', [$this, 'ltrimFilter']),
new \Twig_SimpleFilter('markdown', [$this, 'markdownFunction'], ['is_safe' => ['html']]),
new \Twig_SimpleFilter('md5', [$this, 'md5Filter']),
new \Twig_SimpleFilter('base32_encode', [$this, 'base32EncodeFilter']),
new \Twig_SimpleFilter('base32_decode', [$this, 'base32DecodeFilter']),
new \Twig_SimpleFilter('base64_encode', [$this, 'base64EncodeFilter']),
new \Twig_SimpleFilter('base64_decode', [$this, 'base64DecodeFilter']),
new \Twig_SimpleFilter('randomize', [$this, 'randomizeFilter']),
new \Twig_SimpleFilter('modulus', [$this, 'modulusFilter']),
new \Twig_SimpleFilter('rtrim', [$this, 'rtrimFilter']),
new \Twig_SimpleFilter('pad', [$this, 'padFilter']),
new \Twig_SimpleFilter('regex_replace', [$this, 'regexReplace']),
new \Twig_SimpleFilter('safe_email', [$this, 'safeEmailFilter']),
new \Twig_SimpleFilter('safe_truncate', ['\Grav\Common\Utils', 'safeTruncate']),
new \Twig_SimpleFilter('safe_truncate_html', ['\Grav\Common\Utils', 'safeTruncateHTML']),
new \Twig_SimpleFilter('sort_by_key', [$this, 'sortByKeyFilter']),
new \Twig_SimpleFilter('starts_with', [$this, 'startsWithFilter']),
new \Twig_SimpleFilter('truncate', ['\Grav\Common\Utils', 'truncate']),
new \Twig_SimpleFilter('truncate_html', ['\Grav\Common\Utils', 'truncateHTML']),
new \Twig_SimpleFilter('json_decode', [$this, 'jsonDecodeFilter']),
new \Twig_SimpleFilter('array_unique', 'array_unique'),
new \Twig_SimpleFilter('basename', 'basename'),
new \Twig_SimpleFilter('dirname', 'dirname'),
new \Twig_SimpleFilter('print_r', 'print_r'),
new \Twig_SimpleFilter('yaml_encode', [$this, 'yamlEncodeFilter']),
new \Twig_SimpleFilter('yaml_decode', [$this, 'yamlDecodeFilter']),
new \Twig_SimpleFilter('nicecron', [$this, 'niceCronFilter']),
new TwigFilter('*ize', [$this, 'inflectorFilter']),
new TwigFilter('absolute_url', [$this, 'absoluteUrlFilter']),
new TwigFilter('contains', [$this, 'containsFilter']),
new TwigFilter('chunk_split', [$this, 'chunkSplitFilter']),
new TwigFilter('nicenumber', [$this, 'niceNumberFunc']),
new TwigFilter('nicefilesize', [$this, 'niceFilesizeFunc']),
new TwigFilter('nicetime', [$this, 'nicetimeFunc']),
new TwigFilter('defined', [$this, 'definedDefaultFilter']),
new TwigFilter('ends_with', [$this, 'endsWithFilter']),
new TwigFilter('fieldName', [$this, 'fieldNameFilter']),
new TwigFilter('ksort', [$this, 'ksortFilter']),
new TwigFilter('ltrim', [$this, 'ltrimFilter']),
new TwigFilter('markdown', [$this, 'markdownFunction'], ['is_safe' => ['html']]),
new TwigFilter('md5', [$this, 'md5Filter']),
new TwigFilter('base32_encode', [$this, 'base32EncodeFilter']),
new TwigFilter('base32_decode', [$this, 'base32DecodeFilter']),
new TwigFilter('base64_encode', [$this, 'base64EncodeFilter']),
new TwigFilter('base64_decode', [$this, 'base64DecodeFilter']),
new TwigFilter('randomize', [$this, 'randomizeFilter']),
new TwigFilter('modulus', [$this, 'modulusFilter']),
new TwigFilter('rtrim', [$this, 'rtrimFilter']),
new TwigFilter('pad', [$this, 'padFilter']),
new TwigFilter('regex_replace', [$this, 'regexReplace']),
new TwigFilter('safe_email', [$this, 'safeEmailFilter']),
new TwigFilter('safe_truncate', ['\Grav\Common\Utils', 'safeTruncate']),
new TwigFilter('safe_truncate_html', ['\Grav\Common\Utils', 'safeTruncateHTML']),
new TwigFilter('sort_by_key', [$this, 'sortByKeyFilter']),
new TwigFilter('starts_with', [$this, 'startsWithFilter']),
new TwigFilter('truncate', ['\Grav\Common\Utils', 'truncate']),
new TwigFilter('truncate_html', ['\Grav\Common\Utils', 'truncateHTML']),
new TwigFilter('json_decode', [$this, 'jsonDecodeFilter']),
new TwigFilter('array_unique', 'array_unique'),
new TwigFilter('basename', 'basename'),
new TwigFilter('dirname', 'dirname'),
new TwigFilter('print_r', 'print_r'),
new TwigFilter('yaml_encode', [$this, 'yamlEncodeFilter']),
new TwigFilter('yaml_decode', [$this, 'yamlDecodeFilter']),
new TwigFilter('nicecron', [$this, 'niceCronFilter']),
// Translations
new \Twig_SimpleFilter('t', [$this, 'translate'], ['needs_environment' => true]),
new \Twig_SimpleFilter('tl', [$this, 'translateLanguage']),
new \Twig_SimpleFilter('ta', [$this, 'translateArray']),
new TwigFilter('t', [$this, 'translate'], ['needs_environment' => true]),
new TwigFilter('tl', [$this, 'translateLanguage']),
new TwigFilter('ta', [$this, 'translateArray']),
// Casting values
new \Twig_SimpleFilter('string', [$this, 'stringFilter']),
new \Twig_SimpleFilter('int', [$this, 'intFilter'], ['is_safe' => ['all']]),
new \Twig_SimpleFilter('bool', [$this, 'boolFilter']),
new \Twig_SimpleFilter('float', [$this, 'floatFilter'], ['is_safe' => ['all']]),
new \Twig_SimpleFilter('array', [$this, 'arrayFilter']),
new TwigFilter('string', [$this, 'stringFilter']),
new TwigFilter('int', [$this, 'intFilter'], ['is_safe' => ['all']]),
new TwigFilter('bool', [$this, 'boolFilter']),
new TwigFilter('float', [$this, 'floatFilter'], ['is_safe' => ['all']]),
new TwigFilter('array', [$this, 'arrayFilter']),
// Object Types
new \Twig_SimpleFilter('get_type', [$this, 'getTypeFunc']),
new \Twig_SimpleFilter('of_type', [$this, 'ofTypeFunc'])
new TwigFilter('get_type', [$this, 'getTypeFunc']),
new TwigFilter('of_type', [$this, 'ofTypeFunc'])
];
}
@@ -137,54 +144,54 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
public function getFunctions()
{
return [
new \Twig_SimpleFunction('array', [$this, 'arrayFilter']),
new \Twig_SimpleFunction('array_key_value', [$this, 'arrayKeyValueFunc']),
new \Twig_SimpleFunction('array_key_exists', 'array_key_exists'),
new \Twig_SimpleFunction('array_unique', 'array_unique'),
new \Twig_SimpleFunction('array_intersect', [$this, 'arrayIntersectFunc']),
new \Twig_SimpleFunction('authorize', [$this, 'authorize']),
new \Twig_SimpleFunction('debug', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
new \Twig_SimpleFunction('dump', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
new \Twig_SimpleFunction('vardump', [$this, 'vardumpFunc']),
new \Twig_SimpleFunction('print_r', 'print_r'),
new \Twig_SimpleFunction('http_response_code', 'http_response_code'),
new \Twig_SimpleFunction('evaluate', [$this, 'evaluateStringFunc'], ['needs_context' => true]),
new \Twig_SimpleFunction('evaluate_twig', [$this, 'evaluateTwigFunc'], ['needs_context' => true]),
new \Twig_SimpleFunction('gist', [$this, 'gistFunc']),
new \Twig_SimpleFunction('nonce_field', [$this, 'nonceFieldFunc']),
new \Twig_SimpleFunction('pathinfo', 'pathinfo'),
new \Twig_SimpleFunction('random_string', [$this, 'randomStringFunc']),
new \Twig_SimpleFunction('repeat', [$this, 'repeatFunc']),
new \Twig_SimpleFunction('regex_replace', [$this, 'regexReplace']),
new \Twig_SimpleFunction('regex_filter', [$this, 'regexFilter']),
new \Twig_SimpleFunction('string', [$this, 'stringFunc']),
new \Twig_SimpleFunction('url', [$this, 'urlFunc']),
new \Twig_SimpleFunction('json_decode', [$this, 'jsonDecodeFilter']),
new \Twig_SimpleFunction('get_cookie', [$this, 'getCookie']),
new \Twig_SimpleFunction('redirect_me', [$this, 'redirectFunc']),
new \Twig_SimpleFunction('range', [$this, 'rangeFunc']),
new \Twig_SimpleFunction('isajaxrequest', [$this, 'isAjaxFunc']),
new \Twig_SimpleFunction('exif', [$this, 'exifFunc']),
new \Twig_SimpleFunction('media_directory', [$this, 'mediaDirFunc']),
new \Twig_SimpleFunction('body_class', [$this, 'bodyClassFunc']),
new \Twig_SimpleFunction('theme_var', [$this, 'themeVarFunc']),
new \Twig_SimpleFunction('header_var', [$this, 'pageHeaderVarFunc']),
new \Twig_SimpleFunction('read_file', [$this, 'readFileFunc']),
new \Twig_SimpleFunction('nicenumber', [$this, 'niceNumberFunc']),
new \Twig_SimpleFunction('nicefilesize', [$this, 'niceFilesizeFunc']),
new \Twig_SimpleFunction('nicetime', [$this, 'nicetimeFunc']),
new \Twig_SimpleFunction('cron', [$this, 'cronFunc']),
new \Twig_SimpleFunction('xss', [$this, 'xssFunc']),
new TwigFunction('array', [$this, 'arrayFilter']),
new TwigFunction('array_key_value', [$this, 'arrayKeyValueFunc']),
new TwigFunction('array_key_exists', 'array_key_exists'),
new TwigFunction('array_unique', 'array_unique'),
new TwigFunction('array_intersect', [$this, 'arrayIntersectFunc']),
new TwigFunction('authorize', [$this, 'authorize']),
new TwigFunction('debug', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
new TwigFunction('dump', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
new TwigFunction('vardump', [$this, 'vardumpFunc']),
new TwigFunction('print_r', 'print_r'),
new TwigFunction('http_response_code', 'http_response_code'),
new TwigFunction('evaluate', [$this, 'evaluateStringFunc'], ['needs_context' => true]),
new TwigFunction('evaluate_twig', [$this, 'evaluateTwigFunc'], ['needs_context' => true]),
new TwigFunction('gist', [$this, 'gistFunc']),
new TwigFunction('nonce_field', [$this, 'nonceFieldFunc']),
new TwigFunction('pathinfo', 'pathinfo'),
new TwigFunction('random_string', [$this, 'randomStringFunc']),
new TwigFunction('repeat', [$this, 'repeatFunc']),
new TwigFunction('regex_replace', [$this, 'regexReplace']),
new TwigFunction('regex_filter', [$this, 'regexFilter']),
new TwigFunction('string', [$this, 'stringFunc']),
new TwigFunction('url', [$this, 'urlFunc']),
new TwigFunction('json_decode', [$this, 'jsonDecodeFilter']),
new TwigFunction('get_cookie', [$this, 'getCookie']),
new TwigFunction('redirect_me', [$this, 'redirectFunc']),
new TwigFunction('range', [$this, 'rangeFunc']),
new TwigFunction('isajaxrequest', [$this, 'isAjaxFunc']),
new TwigFunction('exif', [$this, 'exifFunc']),
new TwigFunction('media_directory', [$this, 'mediaDirFunc']),
new TwigFunction('body_class', [$this, 'bodyClassFunc']),
new TwigFunction('theme_var', [$this, 'themeVarFunc']),
new TwigFunction('header_var', [$this, 'pageHeaderVarFunc']),
new TwigFunction('read_file', [$this, 'readFileFunc']),
new TwigFunction('nicenumber', [$this, 'niceNumberFunc']),
new TwigFunction('nicefilesize', [$this, 'niceFilesizeFunc']),
new TwigFunction('nicetime', [$this, 'nicetimeFunc']),
new TwigFunction('cron', [$this, 'cronFunc']),
new TwigFunction('xss', [$this, 'xssFunc']),
// Translations
new \Twig_SimpleFunction('t', [$this, 'translate'], ['needs_environment' => true]),
new \Twig_SimpleFunction('tl', [$this, 'translateLanguage']),
new \Twig_SimpleFunction('ta', [$this, 'translateArray']),
new TwigFunction('t', [$this, 'translate'], ['needs_environment' => true]),
new TwigFunction('tl', [$this, 'translateLanguage']),
new TwigFunction('ta', [$this, 'translateArray']),
// Object Types
new \Twig_SimpleFunction('get_type', [$this, 'getTypeFunc']),
new \Twig_SimpleFunction('of_type', [$this, 'ofTypeFunc'])
new TwigFunction('get_type', [$this, 'getTypeFunc']),
new TwigFunction('of_type', [$this, 'ofTypeFunc'])
];
}
@@ -455,9 +462,9 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
}
/**
* Gets a human readable output for cron sytnax
* Gets a human readable output for cron syntax
*
* @param $at
* @param string $at
* @return string
*/
public function niceCronFilter($at)
@@ -484,7 +491,7 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
* @param bool $long_strings
*
* @param bool $show_tense
* @return bool
* @return string
*/
public function nicetimeFunc($date, $long_strings = true, $show_tense = true)
{
@@ -651,7 +658,7 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
*/
public function definedDefaultFilter($value, $default = null)
{
return null !== $value ? $value : $default;
return $value ?? $default;
}
/**
@@ -733,9 +740,10 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
}
/**
* @param Environment $twig
* @return string
*/
public function translate(\Twig_Environment $twig)
public function translate(Environment $twig)
{
// shift off the environment
$args = func_get_args();
@@ -828,8 +836,8 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
*/
public function evaluateTwigFunc($context, $twig ) {
$loader = new \Twig_Loader_Filesystem('.');
$env = new \Twig_Environment($loader);
$loader = new FilesystemLoader('.');
$env = new Environment($loader);
$template = $env->createTemplate($twig);
@@ -848,15 +856,14 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
return $this->evaluateTwigFunc($context, "{{ $string }}");
}
/**
* Based on Twig_Extension_Debug / twig_var_dump
* Based on Twig\Extension\Debug / twig_var_dump
* (c) 2011 Fabien Potencier
*
* @param \Twig_Environment $env
* @param string $context
* @param Environment $env
* @param array $context
*/
public function dump(\Twig_Environment $env, $context)
public function dump(Environment $env, $context)
{
if (!$env->isDebug() || !$this->debugger) {
return;
@@ -1104,8 +1111,9 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
*/
public function redirectFunc($url, $statusCode = 303)
{
header('Location: ' . $url, true, $statusCode);
exit();
$response = new Response($statusCode, ['location' => $url]);
$this->grav->exit($response);
}
/**

View File

@@ -0,0 +1,74 @@
<?php
/**
* @package Grav\Common\Twig
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Twig;
use Grav\Common\Utils;
use Twig\Profiler\Profile;
use Clockwork\Request\Timeline;
class TwigProfileProcessor
{
private $root;
public function process(Profile $profile, Timeline $views, $counter = 0, $prefix = '', $sibling = false)
{
if ($profile->isRoot()) {
$this->root = $profile->getDuration();
$name = $profile->getName();
} else {
if ($profile->isTemplate()) {
$name = $this->formatTemplate($profile, $prefix);
} else {
$name = $this->formatNonTemplate($profile, $prefix);
}
$prefix .= '⎯⎯';
}
$percent = $this->root ? $profile->getDuration() / $this->root * 100 : 0;
$data = [
'tm' => $this->formatTime($profile, $percent),
'mu' => Utils::prettySize($profile->getMemoryUsage())
];
if ($profile->isRoot()) {
$data += ['pmu' => Utils::prettySize($profile->getPeakMemoryUsage())];
}
$views->addEvent(
$counter,
$profile->getTemplate(),
0,
$profile->getDuration(),
[ 'name' => $name, 'data' => $data ]
);
$nCount = count($profile->getProfiles());
foreach ($profile as $i => $p) {
$this->process($p, $views, ++$counter, $prefix, $i + 1 !== $nCount);
}
}
protected function formatTemplate(Profile $profile, $prefix)
{
return sprintf('%s⤍ %s', $prefix, $profile->getTemplate());
}
protected function formatNonTemplate(Profile $profile, $prefix)
{
return sprintf('%s⤍ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName());
}
protected function formatTime(Profile $profile, $percent)
{
return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent);
}
}

View File

@@ -300,16 +300,17 @@ class Uri
* Get URI parameter.
*
* @param string $id
* @param bool $default
*
* @return bool|string
*/
public function param($id)
public function param($id, $default = false)
{
if (isset($this->params[$id])) {
return html_entity_decode(rawurldecode($this->params[$id]));
}
return false;
return $default;
}
/**
@@ -1340,7 +1341,7 @@ class Uri
/**
* Check if this is a valid Grav extension
*
* @param $extension
* @param string $extension
* @return bool
*/
public function isValidExtension($extension)
@@ -1357,7 +1358,7 @@ class Uri
/**
* Allow overriding of any element (be careful!)
*
* @param $data
* @param array $data
* @return Uri
*/
public function setUriProperties($data)

View File

@@ -59,6 +59,7 @@ class UserCollection extends FlexCollection implements UserCollectionInterface
*/
public function find($query, $fields = ['username', 'email']): UserInterface
{
// FIXME: $fields is incompatible to parent class -- add support for finding value from multiple properties.
foreach ((array)$fields as $field) {
if ($field === 'key') {
$user = $this->get($query);

View File

@@ -28,7 +28,7 @@ abstract class Utils
/**
* Simple helper method to make getting a Grav URL easier
*
* @param string $input
* @param string|object $input
* @param bool $domain
* @param bool $fail_gracefully
* @return bool|null|string
@@ -1260,7 +1260,7 @@ abstract class Utils
*/
public static function sortArrayByArray(array $array, array $orderArray)
{
$ordered = array();
$ordered = [];
foreach ($orderArray as $key) {
if (array_key_exists($key, $array)) {
$ordered[$key] = $array[$key];
@@ -1415,16 +1415,16 @@ abstract class Utils
/**
* Parse a readable file size and return a value in bytes
*
* @param string|int $size
* @param string|int|float $size
* @return int
*/
public static function parseSize($size)
{
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size);
$size = preg_replace('/[^0-9\.]/', '', $size);
$size = (float)preg_replace('/[^0-9\.]/', '', $size);
if ($unit) {
$size = $size * pow(1024, stripos('bkmgtpezy', $unit[0]));
$size *= 1024 ** stripos('bkmgtpezy', $unit[0]);
}
return (int) abs(round($size));
@@ -1511,7 +1511,7 @@ abstract class Utils
}
// Packed representation of IP
$ip = inet_pton($ip);
$ip = (string)inet_pton($ip);
// Maximum netmask length = same as packed address
$len = 8*strlen($ip);

View File

@@ -74,7 +74,7 @@ class SchedulerCommand extends ConsoleCommand
// Show jobs list
$jobs = $scheduler->getAllJobs();
$job_states = $scheduler->getJobStates()->content();
$job_states = (array)$scheduler->getJobStates()->content();
$rows = [];
$table = new Table($this->output);
@@ -113,7 +113,7 @@ class SchedulerCommand extends ConsoleCommand
$io->newLine();
} elseif ($this->input->getOption('details')) {
$jobs = $scheduler->getAllJobs();
$job_states = $scheduler->getJobStates()->content();
$job_states = (array)$scheduler->getJobStates()->content();
$io->title('Job Details');

View File

@@ -19,7 +19,7 @@ use Symfony\Component\Console\Input\InputOption;
class IndexCommand extends ConsoleCommand
{
/** @var array */
/** @var Packages */
protected $data;
/** @var GPM */
@@ -188,9 +188,9 @@ class IndexCommand extends ConsoleCommand
}
/**
* @param array $data
* @param Packages $data
*
* @return mixed
* @return Packages
*/
public function filter($data)
{
@@ -245,6 +245,7 @@ class IndexCommand extends ConsoleCommand
/**
* @param Packages $packages
* @return Packages
*/
public function sort($packages)
{

View File

@@ -551,10 +551,9 @@ class InstallCommand extends ConsoleCommand
/**
* @param Package $package
* @param string|null $license
*
* @param string $license
*
* @return string
* @return string|null
*/
private function downloadPackage($package, $license = null)
{
@@ -586,7 +585,7 @@ class InstallCommand extends ConsoleCommand
$this->output->writeln(' |- Downloading package... <red>error</red> ');
$this->output->writeln(" | '- " . $error);
return false;
return null;
}
Folder::create($this->tmp);

View File

@@ -185,17 +185,17 @@ class SelfupgradeCommand extends ConsoleCommand
{
$tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true);
$this->tmp = $tmp_dir . '/Grav-' . uniqid('', false);
$output = Response::get($package['download'], [], [$this, 'progress']);
$output = Response::get($package->download, [], [$this, 'progress']);
Folder::create($this->tmp);
$this->output->write("\x0D");
$this->output->write(" |- Downloading upgrade [{$this->formatBytes($package['size'])}]... 100%");
$this->output->write(" |- Downloading upgrade [{$this->formatBytes($package->size)}]... 100%");
$this->output->writeln('');
file_put_contents($this->tmp . DS . $package['name'], $output);
file_put_contents($this->tmp . DS . $package->name, $output);
return $this->tmp . DS . $package['name'];
return $this->tmp . DS . $package->name;
}
/**

View File

@@ -330,12 +330,12 @@ class FlexForm implements FlexFormInterface
$this->object = $data['object'];
}
/**
/**
* Filter validated data.
*
* @param \ArrayAccess $data
* @param \ArrayAccess|Data $data
*/
protected function filterData(\ArrayAccess $data): void
protected function filterData($data): void
{
if ($data instanceof Data) {
$data->filter(true, true);

View File

@@ -9,7 +9,6 @@ namespace Grav\Framework\Flex\Traits;
* @license MIT License; see LICENSE file for details.
*/
use Grav\Common\Cache;
use Grav\Common\Config\Config;
use Grav\Common\Filesystem\Folder;
use Grav\Common\Grav;
@@ -19,6 +18,7 @@ use Grav\Common\Page\Medium\AbstractMedia;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Page\Medium\MediumFactory;
use Grav\Common\Utils;
use Grav\Framework\Cache\CacheInterface;
use Grav\Framework\Flex\FlexDirectory;
use Grav\Framework\Form\FormFlashFile;
use Psr\Http\Message\UploadedFileInterface;
@@ -70,7 +70,7 @@ trait FlexMediaTrait
$media = $this->getExistingMedia();
// Include uploaded media to the object media.
/** @var FormFlashFile $upload */
/** @var FormFlashFile|null $upload */
foreach ($this->getUpdatedMedia() as $filename => $upload) {
// Just make sure we do not include removed or moved media.
if ($upload && $upload->getError() === \UPLOAD_ERR_OK && !$upload->isMoved()) {
@@ -260,7 +260,7 @@ trait FlexMediaTrait
{
$list = [];
foreach ($files as $field => $group) {
if ($field === '' || \strpos($field, '/', true)) {
if ($field === '' || \strpos($field, '/')) {
continue;
}
foreach ($group as $filename => $file) {
@@ -272,7 +272,7 @@ trait FlexMediaTrait
}
/**
* @return array
* @return array<UploadedFileInterface,null>
*/
protected function getUpdatedMedia(): array
{
@@ -283,7 +283,7 @@ trait FlexMediaTrait
{
/**
* @var string $filename
* @var UploadedFileInterface $file
* @var UploadedFileInterface|null $file
*/
foreach ($this->getUpdatedMedia() as $filename => $file) {
if ($file) {
@@ -313,7 +313,7 @@ trait FlexMediaTrait
}
/**
* @return Cache
* @return CacheInterface
*/
protected function getMediaCache()
{

View File

@@ -32,7 +32,7 @@ trait FormTrait
{
/** @var string */
public $status = 'success';
/** @var string */
/** @var string|null */
public $message;
/** @var string[] */
public $messages = [];
@@ -45,7 +45,7 @@ trait FormTrait
private $uniqueid;
/** @var bool */
private $submitted;
/** @var Data|object|null */
/** @var \ArrayAccess|Data|null */
private $data;
/** @var array|UploadedFileInterface[] */
private $files;
@@ -485,11 +485,11 @@ trait FormTrait
/**
* Validate data and throw validation exceptions if validation fails.
*
* @param \ArrayAccess $data
* @param \ArrayAccess|Data $data
* @throws ValidationException
* @throws \Exception
*/
protected function validateData(\ArrayAccess $data): void
protected function validateData($data): void
{
if ($data instanceof Data) {
$data->validate();
@@ -499,9 +499,9 @@ trait FormTrait
/**
* Filter validated data.
*
* @param \ArrayAccess $data
* @param \ArrayAccess|Data $data
*/
protected function filterData(\ArrayAccess $data): void
protected function filterData($data): void
{
if ($data instanceof Data) {
$data->filter();

View File

@@ -65,64 +65,64 @@ trait UriDecorationTrait
public function withScheme($scheme): UriInterface
{
/** @var UriInterface|UriDecorationTrait $new */
$new = clone $this;
$new->uri = $this->uri->withScheme($scheme);
/** @var UriInterface $new */
return $new;
}
public function withUserInfo($user, $password = null): UriInterface
{
/** @var UriInterface|UriDecorationTrait $new */
$new = clone $this;
$new->uri = $this->uri->withUserInfo($user, $password);
/** @var UriInterface $new */
return $new;
}
public function withHost($host): UriInterface
{
/** @var UriInterface|UriDecorationTrait $new */
$new = clone $this;
$new->uri = $this->uri->withHost($host);
/** @var UriInterface $new */
return $new;
}
public function withPort($port): UriInterface
{
/** @var UriInterface|UriDecorationTrait $new */
$new = clone $this;
$new->uri = $this->uri->withPort($port);
/** @var UriInterface $new */
return $new;
}
public function withPath($path): UriInterface
{
/** @var UriInterface|UriDecorationTrait $new */
$new = clone $this;
$new->uri = $this->uri->withPath($path);
/** @var UriInterface $new */
return $new;
}
public function withQuery($query): UriInterface
{
/** @var UriInterface|UriDecorationTrait $new */
$new = clone $this;
$new->uri = $this->uri->withQuery($query);
/** @var UriInterface $new */
return $new;
}
public function withFragment($fragment): UriInterface
{
/** @var UriInterface|UriDecorationTrait $new */
$new = clone $this;
$new->uri = $this->uri->withFragment($fragment);
/** @var UriInterface $new */
return $new;
}
}

View File

@@ -35,12 +35,18 @@ parameters:
-
message: '#Call to deprecated method writeCacheFile\(\) of class Twig\\Environment#'
path: 'system/src/Grav/Common/Twig/WriteCacheFileTrait.php'
-
message: '#Call to an undefined static method Twig\\Environment::writeCacheFile#'
path: 'system/src/Grav/Common/Twig/WriteCacheFileTrait.php'
# Needed: full coverage (probably with admin plugin...) then redesign constructor
-
message: '#Grav\\Common\\GPM\\Remote\\GravCore::__construct\(\) does not call parent constructor from Grav\\Common\\GPM\\Remote\\AbstractPackageCollection#'
path: 'system/src/Grav/Common/GPM/Remote/GravCore.php'
# XHprof
- '#tideways_xhprof_enable#'
# PSR-16 Exception interfaces do not extend \Throwable
- '#PHPDoc tag \@throws with type Psr\\SimpleCache\\(CacheException|InvalidArgumentException) is not subtype of Throwable#'
- '#expects Exception, Psr\\SimpleCache\\InvalidArgumentException&Throwable given#'