diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dc494da8..93342d1dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +# v1.4.6 +## 06/19/2018 + +1. [](#improved) + * Manually re-added the improved SSL off-loading that was lost with Grav v1.4.0 merge [#1888](https://github.com/getgrav/grav/pull/1888) + * Handle multibyte strings in `truncateLetters()` [#2007](https://github.com/getgrav/grav/pull/2007) + * Updated robots.txt to include `/user/images/` folder [#2043](https://github.com/getgrav/grav/pull/2043) + * Add getter methods for original and action to the Page object [#2005](https://github.com/getgrav/grav/pull/2005) + * Modular template extension follows the master page extension [#2044](https://github.com/getgrav/grav/pull/2044) + * Vendor library updates +1. [](#bugfix) + * Handle `errors.display` system property better in admin plugin [admin#1452](https://github.com/getgrav/grav-plugin-admin/issues/1452) + * Fix classes on non-http based protocol links [#2034](https://github.com/getgrav/grav/issues/2034) + * Fixed crash on IIS (Windows) with open_basedir in effect [#2053](https://github.com/getgrav/grav/issues/2053) + * Fixed incorrect routing with setup.php based base [#1892](https://github.com/getgrav/grav/issues/1892) + # v1.4.5 ## 05/15/2018 @@ -5,6 +21,7 @@ * Fixed an issue with some users getting **2FA** prompt after upgrade [admin#1442](https://github.com/getgrav/grav-plugin-admin/issues/1442) * Do not crash when generating URLs with arrays as parameters [#2018](https://github.com/getgrav/grav/pull/2018) * Utils::truncateHTML removes whitespace when generating summaries [#2004](https://github.com/getgrav/grav/pull/2004) + * Fixed issue with Errors `display:` option not handling integers properly [admin#1452](https://github.com/getgrav/grav-plugin-admin/issues/1452) # v1.4.4 ## 05/11/2018 diff --git a/composer.lock b/composer.lock index dff7ccb1b..cb8fe4129 100644 --- a/composer.lock +++ b/composer.lock @@ -1,7 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], "content-hash": "c71dffc7daccd08aba7a52a476569d4c", @@ -384,16 +384,16 @@ }, { "name": "filp/whoops", - "version": "2.1.14", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6" + "reference": "181c4502d8f34db7aed7bfe88d4f87875b8e947a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/c6081b8838686aa04f1e83ba7e91f78b7b2a23e6", - "reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6", + "url": "https://api.github.com/repos/filp/whoops/zipball/181c4502d8f34db7aed7bfe88d4f87875b8e947a", + "reference": "181c4502d8f34db7aed7bfe88d4f87875b8e947a", "shasum": "" }, "require": { @@ -401,9 +401,9 @@ "psr/log": "^1.0.1" }, "require-dev": { - "mockery/mockery": "0.9.*", + "mockery/mockery": "^0.9 || ^1.0", "phpunit/phpunit": "^4.8.35 || ^5.7", - "symfony/var-dumper": "^2.6 || ^3.0" + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0" }, "suggest": { "symfony/var-dumper": "Pretty print complex values better with var-dumper available", @@ -412,7 +412,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -441,7 +441,7 @@ "throwable", "whoops" ], - "time": "2017-11-23T18:22:44+00:00" + "time": "2018-03-03T17:56:25+00:00" }, { "name": "gregwar/cache", @@ -656,16 +656,16 @@ }, { "name": "matthiasmullie/minify", - "version": "1.3.59", + "version": "1.3.60", "source": { "type": "git", "url": "https://github.com/matthiasmullie/minify.git", - "reference": "62dac3bce06de66f0d71fe6490cf1c508d3c3ff7" + "reference": "ab7fea80ce5ce6549baaf272bc8bd926a7e08f90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/62dac3bce06de66f0d71fe6490cf1c508d3c3ff7", - "reference": "62dac3bce06de66f0d71fe6490cf1c508d3c3ff7", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/ab7fea80ce5ce6549baaf272bc8bd926a7e08f90", + "reference": "ab7fea80ce5ce6549baaf272bc8bd926a7e08f90", "shasum": "" }, "require": { @@ -712,7 +712,7 @@ "minifier", "minify" ], - "time": "2018-02-02T12:44:18+00:00" + "time": "2018-04-18T08:50:35+00:00" }, { "name": "matthiasmullie/path-converter", @@ -1203,16 +1203,16 @@ }, { "name": "rockettheme/toolbox", - "version": "1.3.9", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/rockettheme/toolbox.git", - "reference": "1deea4b45e09f6e0c3e6e075e175e50d05ccbf70" + "reference": "ca12fcc980dc7bdf3f955beb74278a070448a485" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rockettheme/toolbox/zipball/1deea4b45e09f6e0c3e6e075e175e50d05ccbf70", - "reference": "1deea4b45e09f6e0c3e6e075e175e50d05ccbf70", + "url": "https://api.github.com/repos/rockettheme/toolbox/zipball/ca12fcc980dc7bdf3f955beb74278a070448a485", + "reference": "ca12fcc980dc7bdf3f955beb74278a070448a485", "shasum": "" }, "require": { @@ -1229,6 +1229,7 @@ "psr-4": { "RocketTheme\\Toolbox\\ArrayTraits\\": "ArrayTraits/src", "RocketTheme\\Toolbox\\Blueprints\\": "Blueprints/src", + "RocketTheme\\Toolbox\\Compat\\": "Compat/src", "RocketTheme\\Toolbox\\DI\\": "DI/src", "RocketTheme\\Toolbox\\Event\\": "Event/src", "RocketTheme\\Toolbox\\File\\": "File/src", @@ -1247,7 +1248,7 @@ "php", "rockettheme" ], - "time": "2018-03-09T00:03:18+00:00" + "time": "2018-06-13T17:11:52+00:00" }, { "name": "seld/cli-prompt", @@ -1299,16 +1300,16 @@ }, { "name": "symfony/console", - "version": "v2.8.38", + "version": "v2.8.41", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "7f78892d900c72a40acd1fe793c856ef0c110f26" + "reference": "e8e59b74ad1274714dad2748349b55e3e6e630c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/7f78892d900c72a40acd1fe793c856ef0c110f26", - "reference": "7f78892d900c72a40acd1fe793c856ef0c110f26", + "url": "https://api.github.com/repos/symfony/console/zipball/e8e59b74ad1274714dad2748349b55e3e6e630c7", + "reference": "e8e59b74ad1274714dad2748349b55e3e6e630c7", "shasum": "" }, "require": { @@ -1322,7 +1323,7 @@ "symfony/process": "~2.1|~3.0.0" }, "suggest": { - "psr/log": "For using the console logger", + "psr/log-implementation": "For using the console logger", "symfony/event-dispatcher": "", "symfony/process": "" }, @@ -1356,7 +1357,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:20:27+00:00" + "time": "2018-05-15T21:17:45+00:00" }, { "name": "symfony/debug", @@ -1417,7 +1418,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.38", + "version": "v2.8.41", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -1476,17 +1477,72 @@ "time": "2018-04-06T07:35:03+00:00" }, { - "name": "symfony/polyfill-iconv", - "version": "v1.7.0", + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "bd515d8f392730c833bc1ba993a4f598da64fa5b" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/bd515d8f392730c833bc1ba993a4f598da64fa5b", - "reference": "bd515d8f392730c833bc1ba993a4f598da64fa5b", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30T19:57:29+00:00" + }, + { + "name": "symfony/polyfill-iconv", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-iconv.git", + "reference": "7cb8436a814d5b0fcf292810ee26f8b0cb47584d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/7cb8436a814d5b0fcf292810ee26f8b0cb47584d", + "reference": "7cb8436a814d5b0fcf292810ee26f8b0cb47584d", "shasum": "" }, "require": { @@ -1498,7 +1554,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -1532,20 +1588,20 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { @@ -1557,7 +1613,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -1591,20 +1647,20 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { "name": "symfony/var-dumper", - "version": "v2.8.38", + "version": "v2.8.41", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "942a8142104deb3254f7da292a923b6d4eac8081" + "reference": "c3d7a096ccaba86e2fadeb444ca32fcbc5a31ebd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/942a8142104deb3254f7da292a923b6d4eac8081", - "reference": "942a8142104deb3254f7da292a923b6d4eac8081", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c3d7a096ccaba86e2fadeb444ca32fcbc5a31ebd", + "reference": "c3d7a096ccaba86e2fadeb444ca32fcbc5a31ebd", "shasum": "" }, "require": { @@ -1659,24 +1715,25 @@ "debug", "dump" ], - "time": "2018-04-03T05:20:27+00:00" + "time": "2018-04-25T14:40:02+00:00" }, { "name": "symfony/yaml", - "version": "v2.8.38", + "version": "v2.8.41", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "be720fcfae4614df204190d57795351059946a77" + "reference": "51356b7a2ff7c9fd06b2f1681cc463bb62b5c1ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/be720fcfae4614df204190d57795351059946a77", - "reference": "be720fcfae4614df204190d57795351059946a77", + "url": "https://api.github.com/repos/symfony/yaml/zipball/51356b7a2ff7c9fd06b2f1681cc463bb62b5c1ff", + "reference": "51356b7a2ff7c9fd06b2f1681cc463bb62b5c1ff", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { @@ -1708,7 +1765,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:36:31+00:00" + "time": "2018-05-01T22:52:40+00:00" }, { "name": "twig/twig", @@ -1975,16 +2032,16 @@ }, { "name": "codeception/stub", - "version": "1.0.2", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/Codeception/Stub.git", - "reference": "95fb7a36b81890dd2e5163e7ab31310df6f1bb99" + "reference": "681b62348837a5ef07d10d8a226f5bc358cc8805" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Stub/zipball/95fb7a36b81890dd2e5163e7ab31310df6f1bb99", - "reference": "95fb7a36b81890dd2e5163e7ab31310df6f1bb99", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/681b62348837a5ef07d10d8a226f5bc358cc8805", + "reference": "681b62348837a5ef07d10d8a226f5bc358cc8805", "shasum": "" }, "require": { @@ -2004,7 +2061,7 @@ "MIT" ], "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", - "time": "2018-02-18T13:56:56+00:00" + "time": "2018-05-17T09:31:08+00:00" }, { "name": "doctrine/instantiator", @@ -2164,16 +2221,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.3.2", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90" + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/68d0ea14d5a3f42a20e87632a5f84931e2709c90", - "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { @@ -2183,7 +2240,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "psr/log": "^1.0" }, "suggest": { @@ -2225,7 +2282,7 @@ "rest", "web service" ], - "time": "2018-03-26T16:33:04+00:00" + "time": "2018-04-22T15:46:56+00:00" }, { "name": "guzzlehttp/promises", @@ -2426,23 +2483,23 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.5", + "version": "1.7.6", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { @@ -2485,7 +2542,7 @@ "spy", "stub" ], - "time": "2018-02-19T10:16:54+00:00" + "time": "2018-04-18T13:57:24+00:00" }, { "name": "phpunit/php-code-coverage", @@ -3237,7 +3294,7 @@ }, { "name": "symfony/browser-kit", - "version": "v3.4.8", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", @@ -3294,16 +3351,16 @@ }, { "name": "symfony/css-selector", - "version": "v3.4.8", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0" + "reference": "d2ce52290b648ae33b5301d09bc14ee378612914" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/519a80d7c1d95c6cc0b67f686d15fe27c6910de0", - "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/d2ce52290b648ae33b5301d09bc14ee378612914", + "reference": "d2ce52290b648ae33b5301d09bc14ee378612914", "shasum": "" }, "require": { @@ -3343,24 +3400,25 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:32:39+00:00" + "time": "2018-05-16T12:49:49+00:00" }, { "name": "symfony/dom-crawler", - "version": "v3.4.8", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff" + "reference": "201b210fafcdd193c1e45b2994bf7133fb6263e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1a4cffeb059226ff6bee9f48acb388faf674afff", - "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/201b210fafcdd193c1e45b2994bf7133fb6263e8", + "reference": "201b210fafcdd193c1e45b2994bf7133fb6263e8", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -3399,20 +3457,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:32:39+00:00" + "time": "2018-05-01T22:53:27+00:00" }, { "name": "symfony/finder", - "version": "v3.4.8", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "bd14efe8b1fabc4de82bf50dce62f05f9a102433" + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/bd14efe8b1fabc4de82bf50dce62f05f9a102433", - "reference": "bd14efe8b1fabc4de82bf50dce62f05f9a102433", + "url": "https://api.github.com/repos/symfony/finder/zipball/472a92f3df8b247b49ae364275fb32943b9656c6", + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6", "shasum": "" }, "require": { @@ -3448,20 +3506,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-04-04T05:07:11+00:00" + "time": "2018-05-16T08:49:21+00:00" }, { "name": "symfony/process", - "version": "v3.4.8", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b" + "reference": "4cbf2db9abcb01486a21b7a059e03a62fae63187" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b", - "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b", + "url": "https://api.github.com/repos/symfony/process/zipball/4cbf2db9abcb01486a21b7a059e03a62fae63187", + "reference": "4cbf2db9abcb01486a21b7a059e03a62fae63187", "shasum": "" }, "require": { @@ -3497,7 +3555,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:22:50+00:00" + "time": "2018-05-16T08:49:21+00:00" }, { "name": "victorjonsson/markdowndocs", diff --git a/robots.txt b/robots.txt index 3b558d635..41ea9dafe 100644 --- a/robots.txt +++ b/robots.txt @@ -9,3 +9,4 @@ Disallow: /vendor/ Disallow: /user/ Allow: /user/pages/ Allow: /user/themes/ +Allow: /user/images/ diff --git a/system/blueprints/config/system.yaml b/system/blueprints/config/system.yaml index d5e5cccf6..53f8ba179 100644 --- a/system/blueprints/config/system.yaml +++ b/system/blueprints/config/system.yaml @@ -835,6 +835,8 @@ form: -1: PLUGIN_ADMIN.ERROR_SYSTEM 0: PLUGIN_ADMIN.ERROR_SIMPLE 1: PLUGIN_ADMIN.ERROR_FULL_BACKTRACE + validate: + type: int errors.log: diff --git a/system/config/site.yaml b/system/config/site.yaml index 1142a5dd2..bb2ee6e86 100644 --- a/system/config/site.yaml +++ b/system/config/site.yaml @@ -3,7 +3,7 @@ default_lang: en # Default language for site (potenti author: name: John Appleseed # Default author name - email: 'john@email.com' # Default author email + email: 'john@example.com' # Default author email taxonomies: [category,tag] # Arbitrary list of taxonomy types diff --git a/system/defines.php b/system/defines.php index 5d02c474c..28c4434f0 100644 --- a/system/defines.php +++ b/system/defines.php @@ -8,7 +8,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '1.4.5'); +define('GRAV_VERSION', '1.4.6'); define('GRAV_TESTING', false); define('DS', '/'); diff --git a/system/src/Grav/Common/Helpers/Excerpts.php b/system/src/Grav/Common/Helpers/Excerpts.php index 3561bc365..697e61905 100644 --- a/system/src/Grav/Common/Helpers/Excerpts.php +++ b/system/src/Grav/Common/Helpers/Excerpts.php @@ -172,10 +172,9 @@ class Excerpts if ($type !== 'image' && !empty($url_parts['stream']) && !empty($url_parts['path'])) { $url_parts['path'] = Grav::instance()['base_url_relative'] . '/' . static::resolveStream("{$url_parts['scheme']}://{$url_parts['path']}"); unset($url_parts['stream'], $url_parts['scheme']); - - $excerpt['element']['attributes']['href'] = Uri::buildUrl($url_parts); } + $excerpt['element']['attributes']['href'] = Uri::buildUrl($url_parts); return $excerpt; } diff --git a/system/src/Grav/Common/Helpers/Truncator.php b/system/src/Grav/Common/Helpers/Truncator.php index b2a19dbc2..474aae1bc 100644 --- a/system/src/Grav/Common/Helpers/Truncator.php +++ b/system/src/Grav/Common/Helpers/Truncator.php @@ -113,7 +113,7 @@ class Truncator { if ($letters->key() >= $limit) { $currentText = $letters->currentTextPosition(); - $currentText[0]->nodeValue = substr($currentText[0]->nodeValue, 0, $currentText[1] + 1); + $currentText[0]->nodeValue = mb_substr($currentText[0]->nodeValue, 0, $currentText[1] + 1); self::removeProceedingNodes($currentText[0], $body); if (!empty($ellipsis)) { diff --git a/system/src/Grav/Common/Page/Medium/AbstractMedia.php b/system/src/Grav/Common/Page/Medium/AbstractMedia.php index fe0ac62ed..4c95938c3 100644 --- a/system/src/Grav/Common/Page/Medium/AbstractMedia.php +++ b/system/src/Grav/Common/Page/Medium/AbstractMedia.php @@ -44,6 +44,21 @@ abstract class AbstractMedia extends Getters return $this->offsetGet($filename); } + /** + * @param mixed $offset + * + * @return mixed + */ + public function offsetGet($offset) + { + $object = parent::offsetGet($offset); + + // It would be nice if previous image modification would not affect the later ones. + //$object = $object ? clone($object) : null; + + return $object; + } + /** * Get a list of all media. * @@ -168,8 +183,8 @@ abstract class AbstractMedia extends Getters $type = 'base'; while (($part = array_shift($fileParts)) !== null) { - if ($part != 'meta' && $part != 'thumb') { - if (isset($extension)) { + if ($part !== 'meta' && $part !== 'thumb') { + if (null !== $extension) { $name .= '.' . $extension; } $extension = $part; diff --git a/system/src/Grav/Common/Page/Medium/ImageFile.php b/system/src/Grav/Common/Page/Medium/ImageFile.php index 683448872..85f2459ed 100644 --- a/system/src/Grav/Common/Page/Medium/ImageFile.php +++ b/system/src/Grav/Common/Page/Medium/ImageFile.php @@ -11,10 +11,16 @@ namespace Grav\Common\Page\Medium; use Grav\Common\Grav; use Gregwar\Image\Exceptions\GenerationError; use Gregwar\Image\Image; +use Gregwar\Image\Source; use RocketTheme\Toolbox\Event\Event; class ImageFile extends Image { + public function __destruct() + { + $this->getAdapter()->deinit(); + } + /** * Clear previously applied operations */ @@ -30,15 +36,15 @@ class ImageFile extends Image * @param int $quality the quality (for JPEG) * @param bool $actual * - * @return mixed|string + * @return string */ public function cacheFile($type = 'jpg', $quality = 80, $actual = false) { - if ($type == 'guess') { + if ($type === 'guess') { $type = $this->guessType(); } - if (!count($this->operations) && $type == $this->guessType() && !$this->forceCache) { + if (!$this->forceCache && !count($this->operations) && $type === $this->guessType()) { return $this->getFilename($this->getFilePath()); } @@ -60,8 +66,7 @@ class ImageFile extends Image $cacheFile .= $this->prettyName; } - - $cacheFile .= '.'.$type; + $cacheFile .= '.' . $type; // If the files does not exists, save it $image = $this; @@ -76,7 +81,7 @@ class ImageFile extends Image $generate = function ($target) use ($image, $type, $quality) { $result = $image->save($target, $type, $quality); - if ($result != $target) { + if ($result !== $target) { throw new GenerationError($result); } @@ -87,15 +92,19 @@ class ImageFile extends Image try { $perms = Grav::instance()['config']->get('system.images.cache_perms', '0755'); $perms = octdec($perms); - $file = $this->cache->setDirectoryMode($perms)->getOrCreateFile($cacheFile, $conditions, $generate, $actual); + $file = $this->getCacheSystem()->setDirectoryMode($perms)->getOrCreateFile($cacheFile, $conditions, $generate, $actual); } catch (GenerationError $e) { $file = $e->getNewFile(); } + // Nulling the resource + $this->getAdapter()->setSource(new Source\File($file)); + $this->getAdapter()->deinit(); + if ($actual) { return $file; - } else { - return $this->getFilename($file); } + + return $this->getFilename($file); } } diff --git a/system/src/Grav/Common/Page/Medium/ImageMedium.php b/system/src/Grav/Common/Page/Medium/ImageMedium.php index 05bc4c486..2851225dd 100644 --- a/system/src/Grav/Common/Page/Medium/ImageMedium.php +++ b/system/src/Grav/Common/Page/Medium/ImageMedium.php @@ -103,6 +103,18 @@ class ImageMedium extends Medium } } + public function __destruct() + { + unset($this->image); + } + + public function __clone() + { + $this->image = $this->image ? clone $this->image : null; + + parent::__clone(); + } + /** * Add meta file for the medium. * @@ -156,10 +168,10 @@ class ImageMedium extends Medium $image_dir = Grav::instance()['locator']->findResource('cache://images', false); $saved_image_path = $this->saveImage(); - $output = preg_replace('|^' . preg_quote(GRAV_ROOT) . '|', '', $saved_image_path); + $output = preg_replace('|^' . preg_quote(GRAV_ROOT, '|') . '|', '', $saved_image_path); if (Utils::startsWith($output, $image_path)) { - $output = '/' . $image_dir . preg_replace('|^' . preg_quote($image_path) . '|', '', $output); + $output = '/' . $image_dir . preg_replace('|^' . preg_quote($image_path, '|') . '|', '', $output); } if ($reset) { @@ -226,13 +238,13 @@ class ImageMedium extends Medium { if ($this->get('prettyname')) { return $this->get('prettyname'); - } else { - $basename = $this->get('basename'); - if (preg_match('/[a-z0-9]{40}-(.*)/', $basename, $matches)) { - $basename = $matches[1]; - } - return $basename; } + + $basename = $this->get('basename'); + if (preg_match('/[a-z0-9]{40}-(.*)/', $basename, $matches)) { + $basename = $matches[1]; + } + return $basename; } /** @@ -280,7 +292,7 @@ class ImageMedium extends Medium // It's possible that MediumFactory::fromFile returns null if the // original image file no longer exists and this class instance was // retrieved from the page cache - if (isset($derivative)) { + if (null !== $derivative) { $index = 2; $alt_widths = array_keys($this->alternatives); sort($alt_widths); @@ -339,7 +351,6 @@ class ImageMedium extends Medium if ($this->image) { $this->image(); - $this->image->clearOperations(); // Clear previously applied operations $this->querystring(''); $this->filter(); $this->clearAlternatives(); @@ -432,7 +443,7 @@ class ImageMedium extends Medium * Set or get sizes parameter for srcset media action * * @param string $sizes - * @return $this + * @return string */ public function sizes($sizes = null) { @@ -459,7 +470,7 @@ class ImageMedium extends Medium */ public function width($value = 'auto') { - if (!$value || $value == 'auto') + if (!$value || $value === 'auto') $this->attributes['width'] = $this->get('width'); else $this->attributes['width'] = $value; @@ -480,7 +491,7 @@ class ImageMedium extends Medium */ public function height($value = 'auto') { - if (!$value || $value == 'auto') + if (!$value || $value === 'auto') $this->attributes['height'] = $this->get('height'); else $this->attributes['height'] = $value; @@ -496,11 +507,11 @@ class ImageMedium extends Medium */ public function __call($method, $args) { - if ($method == 'cropZoom') { + if ($method === 'cropZoom') { $method = 'zoomCrop'; } - if (!in_array($method, self::$magic_actions)) { + if (!\in_array($method, self::$magic_actions, true)) { return parent::__call($method, $args); } @@ -551,6 +562,9 @@ class ImageMedium extends Medium // Use existing cache folder or if it doesn't exist, create it. $cacheDir = $locator->findResource('cache://images', true) ?: $locator->findResource('cache://images', true, true); + // Make sure we free previous image. + unset($this->image); + $this->image = ImageFile::open($file) ->setCacheDir($cacheDir) ->setActualCacheDir($cacheDir) @@ -562,7 +576,7 @@ class ImageMedium extends Medium /** * Save the image with cache. * - * @return mixed|string + * @return string */ protected function saveImage() { @@ -576,7 +590,7 @@ class ImageMedium extends Medium return $this->result; } - if ($this->get('debug') && !$this->debug_watermarked) { + if (!$this->debug_watermarked && $this->get('debug')) { $ratio = $this->get('ratio'); if (!$ratio) { $ratio = 1; @@ -623,9 +637,9 @@ class ImageMedium extends Medium } return $max; - } else { - return $this; } + + return $this; } } diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php index 673368054..36b893c4b 100644 --- a/system/src/Grav/Common/Page/Medium/Medium.php +++ b/system/src/Grav/Common/Page/Medium/Medium.php @@ -73,6 +73,11 @@ class Medium extends Data implements RenderableInterface $this->reset(); } + public function __clone() + { + // Allows future compatibility as parent::__clone() works. + } + /** * Create a copy of this media object * @@ -80,7 +85,7 @@ class Medium extends Data implements RenderableInterface */ public function copy() { - return clone($this); + return clone $this; } /** diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index a4027a514..e92e03bff 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -2955,4 +2955,26 @@ class Page return $route; } } + + /** + * Gets the Page Unmodified (original) version of the page. + * + * @return Page + * The original version of the page. + */ + public function getOriginal() + { + return $this->_original; + } + + /** + * Gets the action. + * + * @return string + * The Action string. + */ + public function getAction() + { + return $this->_action; + } } diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index 2ff049d9e..12afa7e88 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -1007,32 +1007,63 @@ class Pages throw new \RuntimeException('Fatal error when creating page instances.'); } - $content_exists = false; - $pages_found = new \GlobIterator($directory . '/*' . CONTENT_EXT); + // Build regular expression for all the allowed page extensions. + $page_extensions = $language->getFallbackPageExtensions(); + $regex = '/^[^\.]*(' . implode('|', array_map( + function ($str) { + return preg_quote($str, '/'); + }, + $page_extensions + )) . ')$/'; + + $folders = []; $page_found = null; - $page_extension = ''; + $last_modified = 0; - if ($pages_found && count($pages_found) > 0) { + $iterator = new \FilesystemIterator($directory); + /** @var \FilesystemIterator $file */ + foreach ($iterator as $file) { + $filename = $file->getFilename(); - $page_extensions = $language->getFallbackPageExtensions(); + // Ignore all hidden files if set. + if ($this->ignore_hidden && $filename && $filename[0] === '.') { + continue; + } - foreach ($page_extensions as $extension) { - foreach ($pages_found as $found) { - if ($found->isDir()) { - continue; - } - $regex = '/^[^\.]*' . preg_quote($extension, '/') . '$/'; - if (preg_match($regex, $found->getFilename())) { - $page_found = $found; - $page_extension = $extension; - break 2; - } + // Handle folders later. + if ($file->isDir()) { + // But ignore all folders in ignore list. + if (!\in_array($filename, $this->ignore_folders, true)) { + $folders[] = $file; + } + continue; + } + + // Ignore all files in ignore list. + if (\in_array($file->getBasename(), $this->ignore_files, true)) { + continue; + } + + // Update last modified date to match the last updated file in the folder. + $modified = $file->getMTime(); + if ($modified > $last_modified) { + $last_modified = $modified; + } + + // Page is the one that matches to $page_extensions list with the lowest index number. + if (preg_match($regex, $filename, $matches, PREG_OFFSET_CAPTURE)) { + $ext = $matches[1][0]; + + if ($page_found === null || array_search($ext, $page_extensions, true) < array_search($page_extension, $page_extensions, true)) { + $page_found = $file; + $page_extension = $ext; } } } - if ($parent && !empty($page_found)) { + $content_exists = false; + if ($parent && $page_found) { $page->init($page_found, $page_extension); $content_exists = true; @@ -1042,48 +1073,31 @@ class Pages } } - // set current modified of page - $last_modified = $page->modified(); + // Now handle all the folders under the page. + /** @var \FilesystemIterator $file */ + foreach ($folders as $file) { + $filename = $file->getFilename(); - $iterator = new \FilesystemIterator($directory); - - /** @var \DirectoryIterator $file */ - foreach ($iterator as $file) { - $name = $file->getFilename(); - - // Ignore all hidden files if set. - if ($this->ignore_hidden && $name && $name[0] === '.') { + // if folder contains separator, continue + if (Utils::contains($file->getFilename(), $config->get('system.param_sep', ':'))) { continue; } - if ($file->isFile()) { - // Update the last modified if it's newer than already found - if (!in_array($file->getBasename(), $this->ignore_files) && ($modified = $file->getMTime()) > $last_modified) { - $last_modified = $modified; - } - } elseif ($file->isDir() && !in_array($file->getFilename(), $this->ignore_folders)) { + if (!$page->path()) { + $page->path($file->getPath()); + } - // if folder contains separator, continue - if (Utils::contains($file->getFilename(), $config->get('system.param_sep', ':'))) { - continue; - } + $path = $directory . DS . $filename; + $child = $this->recurse($path, $page); - if (!$page->path()) { - $page->path($file->getPath()); - } + if (Utils::startsWith($filename, '_')) { + $child->routable(false); + } - $path = $directory . DS . $name; - $child = $this->recurse($path, $page); + $this->children[$page->path()][$child->path()] = ['slug' => $child->slug()]; - if (Utils::startsWith($name, '_')) { - $child->routable(false); - } - - $this->children[$page->path()][$child->path()] = ['slug' => $child->slug()]; - - if ($config->get('system.pages.events.page')) { - $this->grav->fireEvent('onFolderProcessed', new Event(['page' => $page])); - } + if ($config->get('system.pages.events.page')) { + $this->grav->fireEvent('onFolderProcessed', new Event(['page' => $page])); } } diff --git a/system/src/Grav/Common/Twig/Twig.php b/system/src/Grav/Common/Twig/Twig.php index e1ba281f4..a47a2b7aa 100644 --- a/system/src/Grav/Common/Twig/Twig.php +++ b/system/src/Grav/Common/Twig/Twig.php @@ -238,7 +238,9 @@ class Twig // Process Modular Twig if ($item->modularTwig()) { $twig_vars['content'] = $content; - $template = $item->template() . TEMPLATE_EXT; + $extension = $this->grav['uri']->extension(); + $extension = $extension ? ".{$extension}.twig" : TEMPLATE_EXT; + $template = $item->template() . $extension; $output = $content = $local_twig->render($template, $twig_vars); } diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index 412a3abd5..8017ecb88 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -150,11 +150,10 @@ class Uri $uri = str_replace(static::filterPath($this->root), '', $this->url); - // remove the setup.php based base if set: $setup_base = $grav['pages']->base(); if ($setup_base) { - $uri = str_replace($setup_base, '', $uri); + $uri = preg_replace('|^' . preg_quote($setup_base, '|') . '|', '', $uri); } // If configured to, redirect trailing slash URI's with a 302 redirect @@ -687,18 +686,19 @@ class Uri */ public static function buildUrl($parsed_url) { - $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : (isset($parsed_url['host']) ? '//' : ''); - $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; - $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; - $user = isset($parsed_url['user']) ? $parsed_url['user'] : ''; - $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : ''; - $pass = ($user || $pass) ? "{$pass}@" : ''; - $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; - $path = !empty($parsed_url['params']) ? rtrim($path, '/') . static::buildParams($parsed_url['params']) : $path; - $query = !empty($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; - $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : ''; + $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . ':' : ''; + $authority = isset($parsed_url['host']) ? '//' : ''; + $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; + $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; + $user = isset($parsed_url['user']) ? $parsed_url['user'] : ''; + $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : ''; + $pass = ($user || $pass) ? "{$pass}@" : ''; + $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; + $path = !empty($parsed_url['params']) ? rtrim($path, '/') . static::buildParams($parsed_url['params']) : $path; + $query = !empty($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; + $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : ''; - return "{$scheme}{$user}{$pass}{$host}{$port}{$path}{$query}{$fragment}"; + return "{$scheme}{$authority}{$user}{$pass}{$host}{$port}{$path}{$query}{$fragment}"; } /** @@ -1119,8 +1119,12 @@ class Uri protected function createFromEnvironment(array $env) { // Build scheme. - if (isset($env['REQUEST_SCHEME'])) { - $this->scheme = $env['REQUEST_SCHEME']; + if (isset($env['HTTP_X_FORWARDED_PROTO'])) { + $this->scheme = $env['HTTP_X_FORWARDED_PROTO']; + } elseif (isset($env['X-FORWARDED-PROTO'])) { + $this->scheme = $env['X-FORWARDED-PROTO']; + } elseif (isset($env['REQUEST_SCHEME'])) { + $this->scheme = $env['REQUEST_SCHEME']; } else { $https = isset($env['HTTPS']) ? $env['HTTPS'] : ''; $this->scheme = (empty($https) || strtolower($https) === 'off') ? 'http' : 'https'; @@ -1143,7 +1147,16 @@ class Uri $this->host = $this->validateHostname($hostname) ? $hostname : 'unknown'; // Build port. - $this->port = isset($env['SERVER_PORT']) ? (int)$env['SERVER_PORT'] : null; + if (isset($env['HTTP_X_FORWARDED_PORT'])) { + $this->port = (int)$env['HTTP_X_FORWARDED_PORT']; + } elseif (isset($env['X-FORWARDED-PORT'])) { + $this->port = (int)$env['X-FORWARDED-PORT']; + } elseif (isset($env['SERVER_PORT'])) { + $this->port = (int)$env['SERVER_PORT']; + } else { + $this->port = null; + } + if ($this->hasStandardPort()) { $this->port = null; } diff --git a/user/config/site.yaml b/user/config/site.yaml index c45818de4..4be78edc9 100644 --- a/user/config/site.yaml +++ b/user/config/site.yaml @@ -1,7 +1,7 @@ title: Grav author: name: Joe Bloggs - email: 'joe@test.com' + email: 'joe@example.com' metadata: description: 'Grav is an easy to use, yet powerful, open source flat-file CMS' diff --git a/webserver-configs/nginx.conf b/webserver-configs/nginx.conf index 0696c8439..89dd1051e 100644 --- a/webserver-configs/nginx.conf +++ b/webserver-configs/nginx.conf @@ -30,7 +30,8 @@ server { ## Begin - PHP location ~ \.php$ { # Choose either a socket or TCP/IP address - fastcgi_pass unix:/var/run/php5-fpm.sock; + fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; + # fastcgi_pass unix:/var/run/php5-fpm.sock; #legacy # fastcgi_pass 127.0.0.1:9000; fastcgi_split_path_info ^(.+\.php)(/.+)$;