diff --git a/CHANGELOG.md b/CHANGELOG.md index c2996b161..955c87d34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,54 @@ +# v1.2.0 +## 03/31/2017 + +1. [](#new) + * Added file upload for user avatar in user/admin blueprint +1. [](#improved) + * Analysis fixes + * Switched to stable composer lib versions + +# v1.2.0-rc.3 +## 03/22/2017 + +1. [](#new) + * Refactored Page re-ordering to handle all siblings at once + * Added `language_codes` to Twig init to allow for easy language name/code/native-name lookup +1. [](#improved) + * Added an _Admin Overrides_ section with option to choose the order of children in Pages Management +1. [](#bugfix) + * Fixed loading issues with improperly named themes (use old broken method first) [#1373](https://github.com/getgrav/grav/issues/1373) + * Simplified modular/twig processing logic and fixed an issue with system process config [#1351](https://github.com/getgrav/grav/issues/1351) + * Cleanup package files via GPM install to make them more windows-friendly [#1361](https://github.com/getgrav/grav/pull/1361) + * Fix for page-level debugger override changing the option site-wide + * Allow `url()` twig function to pass-through external links + +# v1.2.0-rc.2 +## 03/17/2017 + +1. [](#improved) + * Updated vendor libraries to latest + * Added the ability to disable debugger on a per-page basis with `debugger: false` in page frontmatter +1. [](#bugfix) + * Fixed an issue with theme inheritance and hyphenated base themes [#1353](https://github.com/getgrav/grav/issues/1353) + * Fixed an issue when trying to use an `@2x` derivative on a non-image media file [#1341](https://github.com/getgrav/grav/issues/1341) + +# v1.2.0-rc.1 +## 03/13/2017 + +1. [](#new) + * Added default setting to only allow `direct-installs` from official GPM. Can be configured in `system.yaml` + * Added a new `Utils::isValidUrl()` method + * Added optional parameter to `|markdown(false)` filter to toggle block/line processing (default|true = `block`) + * Added new `Page::folderExists()` method +1. [](#improved) + * `Twig::evaluate()` now takes current environment and context into account + * Genericized `direct-install` so it can be called via Admin plugin +1. [](#bugfix) + * Fixed a minor bug in Number validation [#1329](https://github.com/getgrav/grav/issues/1329) + * Fixed exception when trying to find user account and there is no `user://accounts` folder + * Fixed issue when setting `Page::expires(0)` [Admin #1009](https://github.com/getgrav/grav-plugin-admin/issues/1009) + * Removed ID from `nonce_field()` Twig function causing validation errors [Form #115](https://github.com/getgrav/grav-plugin-form/issues/115) + # v1.1.17 ## 02/17/2017 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d5c52774..22362c8a5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -110,7 +110,7 @@ Good pull requests - patches, improvements, new features - are a fantastic help. They should remain focused in scope and avoid containing unrelated commits. -**Please ask first** in Gitter or in the Forum before embarking on any significant pull request (e.g. +**Please ask first** in [Slack](https://getgrav.org/slack) or in the Forum before embarking on any significant pull request (e.g. implementing features, refactoring code..), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project. diff --git a/composer.json b/composer.json index 832587378..d1e846396 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "require": { "php": ">=5.5.9", "twig/twig": "~1.24", - "erusev/parsedown": "dev-master as 1.6.0", + "erusev/parsedown": "~1.6", "erusev/parsedown-extra": "~0.7", "symfony/yaml": "~2.8", "symfony/console": "~2.8", @@ -19,7 +19,7 @@ "filp/whoops": "~2.0", "matthiasmullie/minify": "^1.3", "monolog/monolog": "~1.0", - "gregwar/image": "dev-master#72568cfbeb77515278f2ccb386fc344e874b7ae8", + "gregwar/image": "~2.0", "donatj/phpuseragentparser": "~0.3", "pimple/pimple": "~3.0", "rockettheme/toolbox": "~1.0", diff --git a/composer.lock b/composer.lock index 5b083f85d..1066c3520 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "4e5b9333d3ac2de823c68c9c8e0f2017", + "content-hash": "e981b23b44354d081ec1e1ac214656a1", "packages": [ { "name": "antoligy/dom-string-iterators", @@ -122,16 +122,16 @@ }, { "name": "donatj/phpuseragentparser", - "version": "v0.6.0", + "version": "v0.7.0", "source": { "type": "git", "url": "https://github.com/donatj/PhpUserAgent.git", - "reference": "a4f515619c8d9697f34dd8da2eb353bb4c57c5dc" + "reference": "73c819d4c7de034f1bfb7c7a36259192d7d7472a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/a4f515619c8d9697f34dd8da2eb353bb4c57c5dc", - "reference": "a4f515619c8d9697f34dd8da2eb353bb4c57c5dc", + "url": "https://api.github.com/repos/donatj/PhpUserAgent/zipball/73c819d4c7de034f1bfb7c7a36259192d7d7472a", + "reference": "73c819d4c7de034f1bfb7c7a36259192d7d7472a", "shasum": "" }, "require": { @@ -169,20 +169,20 @@ "user agent", "useragent" ], - "time": "2017-01-23T19:32:09+00:00" + "time": "2017-03-01T22:19:13+00:00" }, { "name": "erusev/parsedown", - "version": "dev-master", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/erusev/parsedown.git", - "reference": "4b6493999acfa7792efa3cb252d90168e6f266b9" + "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/4b6493999acfa7792efa3cb252d90168e6f266b9", - "reference": "4b6493999acfa7792efa3cb252d90168e6f266b9", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/1bf24f7334fe16c88bf9d467863309ceaf285b01", + "reference": "1bf24f7334fe16c88bf9d467863309ceaf285b01", "shasum": "" }, "require": { @@ -211,7 +211,7 @@ "markdown", "parser" ], - "time": "2017-01-23 07:45:19" + "time": "2017-03-29T16:04:15+00:00" }, { "name": "erusev/parsedown-extra", @@ -259,20 +259,21 @@ }, { "name": "filp/whoops", - "version": "2.1.5", + "version": "2.1.8", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "2abce9d956589122c6443d6265f01cf7e9388e3c" + "reference": "f2950be7da8b8d6c4e77821b6c9d486e36cdc4f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/2abce9d956589122c6443d6265f01cf7e9388e3c", - "reference": "2abce9d956589122c6443d6265f01cf7e9388e3c", + "url": "https://api.github.com/repos/filp/whoops/zipball/f2950be7da8b8d6c4e77821b6c9d486e36cdc4f3", + "reference": "f2950be7da8b8d6c4e77821b6c9d486e36cdc4f3", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0" + "php": "^5.5.9 || ^7.0", + "psr/log": "^1.0.1" }, "require-dev": { "mockery/mockery": "0.9.*", @@ -315,7 +316,7 @@ "whoops", "zf2" ], - "time": "2016-12-26T16:13:31+00:00" + "time": "2017-03-07T09:04:45+00:00" }, { "name": "gregwar/cache", @@ -362,17 +363,17 @@ }, { "name": "gregwar/image", - "version": "dev-master", + "version": "v2.0.21", "target-dir": "Gregwar/Image", "source": { "type": "git", "url": "https://github.com/Gregwar/Image.git", - "reference": "72568cfbeb77515278f2ccb386fc344e874b7ae8" + "reference": "c9899e4c71009338f89a8c63c12c681692533ede" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Gregwar/Image/zipball/72568cfbeb77515278f2ccb386fc344e874b7ae8", - "reference": "72568cfbeb77515278f2ccb386fc344e874b7ae8", + "url": "https://api.github.com/repos/Gregwar/Image/zipball/c9899e4c71009338f89a8c63c12c681692533ede", + "reference": "c9899e4c71009338f89a8c63c12c681692533ede", "shasum": "" }, "require": { @@ -410,7 +411,7 @@ "gd", "image" ], - "time": "2016-07-12 17:02:18" + "time": "2017-01-24T09:29:39+00:00" }, { "name": "league/climate", @@ -465,16 +466,16 @@ }, { "name": "matthiasmullie/minify", - "version": "1.3.43", + "version": "1.3.44", "source": { "type": "git", "url": "https://github.com/matthiasmullie/minify.git", - "reference": "aa50b2dab6fa7bfd402d334fe51005d6f2526ad7" + "reference": "a7fc4a98ef8f2cf38bba701b51f1a84a1d67bc5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/aa50b2dab6fa7bfd402d334fe51005d6f2526ad7", - "reference": "aa50b2dab6fa7bfd402d334fe51005d6f2526ad7", + "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/a7fc4a98ef8f2cf38bba701b51f1a84a1d67bc5c", + "reference": "a7fc4a98ef8f2cf38bba701b51f1a84a1d67bc5c", "shasum": "" }, "require": { @@ -518,7 +519,7 @@ "minifier", "minify" ], - "time": "2017-01-26T15:48:07+00:00" + "time": "2017-03-16T16:42:50+00:00" }, { "name": "matthiasmullie/path-converter", @@ -632,16 +633,16 @@ }, { "name": "monolog/monolog", - "version": "1.22.0", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558" + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1e044bc4b34e91743943479f1be7a1d5eb93add0", + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0", "shasum": "" }, "require": { @@ -706,7 +707,7 @@ "logging", "psr-3" ], - "time": "2016-11-26T00:15:39+00:00" + "time": "2017-03-13T07:08:03+00:00" }, { "name": "pimple/pimple", @@ -851,16 +852,16 @@ }, { "name": "seld/cli-prompt", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/Seldaek/cli-prompt.git", - "reference": "8cbe10923cae5bcd7c5a713f6703fc4727c8c1b4" + "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/8cbe10923cae5bcd7c5a713f6703fc4727c8c1b4", - "reference": "8cbe10923cae5bcd7c5a713f6703fc4727c8c1b4", + "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd", + "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd", "shasum": "" }, "require": { @@ -895,25 +896,25 @@ "input", "prompt" ], - "time": "2016-04-18T09:31:41+00:00" + "time": "2017-03-18T11:32:45+00:00" }, { "name": "symfony/console", - "version": "v2.8.17", + "version": "v2.8.18", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f3c234cd8db9f7e520a91d695db7d8bb5daeb7a4" + "reference": "81508e6fac4476771275a3f4f53c3fee9b956bfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f3c234cd8db9f7e520a91d695db7d8bb5daeb7a4", - "reference": "f3c234cd8db9f7e520a91d695db7d8bb5daeb7a4", + "url": "https://api.github.com/repos/symfony/console/zipball/81508e6fac4476771275a3f4f53c3fee9b956bfa", + "reference": "81508e6fac4476771275a3f4f53c3fee9b956bfa", "shasum": "" }, "require": { "php": ">=5.3.9", - "symfony/debug": "~2.7,>=2.7.2|~3.0.0", + "symfony/debug": "^2.7.2|~3.0.0", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -956,7 +957,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-02-06T12:04:06+00:00" + "time": "2017-03-04T11:00:12+00:00" }, { "name": "symfony/debug", @@ -1017,16 +1018,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.17", + "version": "v2.8.18", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "74877977f90fb9c3e46378d5764217c55f32df34" + "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74877977f90fb9c3e46378d5764217c55f32df34", - "reference": "74877977f90fb9c3e46378d5764217c55f32df34", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bb4ec47e8e109c1c1172145732d0aa468d967cd0", + "reference": "bb4ec47e8e109c1c1172145732d0aa468d967cd0", "shasum": "" }, "require": { @@ -1034,7 +1035,7 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5|~3.0.0", + "symfony/config": "^2.0.5|~3.0.0", "symfony/dependency-injection": "~2.6|~3.0.0", "symfony/expression-language": "~2.6|~3.0.0", "symfony/stopwatch": "~2.3|~3.0.0" @@ -1073,7 +1074,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:30:24+00:00" + "time": "2017-02-21T08:33:48+00:00" }, { "name": "symfony/polyfill-iconv", @@ -1195,22 +1196,25 @@ }, { "name": "symfony/var-dumper", - "version": "v2.8.17", + "version": "v2.8.18", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "eb4526a20ba9e691f50a7510ea3db3728ada958f" + "reference": "c51daca85371e30ce0e3dea99c7b08e2cb5dbf46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eb4526a20ba9e691f50a7510ea3db3728ada958f", - "reference": "eb4526a20ba9e691f50a7510ea3db3728ada958f", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c51daca85371e30ce0e3dea99c7b08e2cb5dbf46", + "reference": "c51daca85371e30ce0e3dea99c7b08e2cb5dbf46", "shasum": "" }, "require": { "php": ">=5.3.9", "symfony/polyfill-mbstring": "~1.0" }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, "require-dev": { "twig/twig": "~1.20|~2.0" }, @@ -1254,20 +1258,20 @@ "debug", "dump" ], - "time": "2017-01-24T13:02:12+00:00" + "time": "2017-02-20T13:37:30+00:00" }, { "name": "symfony/yaml", - "version": "v2.8.17", + "version": "v2.8.18", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153" + "reference": "2a7bab3c16f6f452c47818fdd08f3b1e49ffcf7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/322a8c2dfbca15ad6b1b27e182899f98ec0e0153", - "reference": "322a8c2dfbca15ad6b1b27e182899f98ec0e0153", + "url": "https://api.github.com/repos/symfony/yaml/zipball/2a7bab3c16f6f452c47818fdd08f3b1e49ffcf7d", + "reference": "2a7bab3c16f6f452c47818fdd08f3b1e49ffcf7d", "shasum": "" }, "require": { @@ -1303,33 +1307,34 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-01-21T16:40:50+00:00" + "time": "2017-03-01T18:13:50+00:00" }, { "name": "twig/twig", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7" + "reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddc9e3e20ee9c0b6908f401ac8353635b750eca7", - "reference": "ddc9e3e20ee9c0b6908f401ac8353635b750eca7", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a", + "reference": "05cf49921b13f6f01d3cfdf9018cfa7a8086fd5a", "shasum": "" }, "require": { "php": ">=5.2.7" }, "require-dev": { + "psr/container": "^1.0", "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.2" + "symfony/phpunit-bridge": "~3.3@dev" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.31-dev" + "dev-master": "1.33-dev" } }, "autoload": { @@ -1364,7 +1369,7 @@ "keywords": [ "templating" ], - "time": "2017-01-11T19:36:15+00:00" + "time": "2017-03-22T15:40:09+00:00" } ], "packages-dev": [ @@ -1429,16 +1434,16 @@ }, { "name": "codeception/codeception", - "version": "2.2.9", + "version": "2.2.10", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "0204f1362040d3e408404af2545e5fa27e8964e2" + "reference": "c32a3f92834db08ceedb4666ea2265c3aa43396e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/0204f1362040d3e408404af2545e5fa27e8964e2", - "reference": "0204f1362040d3e408404af2545e5fa27e8964e2", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/c32a3f92834db08ceedb4666ea2265c3aa43396e", + "reference": "c32a3f92834db08ceedb4666ea2265c3aa43396e", "shasum": "" }, "require": { @@ -1453,6 +1458,7 @@ "phpunit/phpunit": ">4.8.20 <6.0", "sebastian/comparator": "~1.1", "sebastian/diff": "^1.4", + "stecman/symfony-console-completion": "^0.7.0", "symfony/browser-kit": ">=2.7 <4.0", "symfony/console": ">=2.7 <4.0", "symfony/css-selector": ">=2.7 <4.0", @@ -1517,7 +1523,7 @@ "functional testing", "unit testing" ], - "time": "2017-02-04T02:04:21+00:00" + "time": "2017-03-25T03:19:52+00:00" }, { "name": "doctrine/instantiator", @@ -1575,34 +1581,37 @@ }, { "name": "facebook/webdriver", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/facebook/php-webdriver.git", - "reference": "77300c4ab2025d4316635f592ec849ca7323bd8c" + "reference": "3ea034c056189e11c0ce7985332a9f4b5b2b5db2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/77300c4ab2025d4316635f592ec849ca7323bd8c", - "reference": "77300c4ab2025d4316635f592ec849ca7323bd8c", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/3ea034c056189e11c0ce7985332a9f4b5b2b5db2", + "reference": "3ea034c056189e11c0ce7985332a9f4b5b2b5db2", "shasum": "" }, "require": { "ext-curl": "*", + "ext-zip": "*", "php": "^5.5 || ~7.0", "symfony/process": "^2.8 || ^3.1" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^1.11", + "friendsofphp/php-cs-fixer": "^2.0", "php-mock/php-mock-phpunit": "^1.1", "phpunit/phpunit": "4.6.* || ~5.0", "satooshi/php-coveralls": "^1.0", "squizlabs/php_codesniffer": "^2.6" }, - "suggest": { - "phpdocumentor/phpdocumentor": "2.*" - }, "type": "library", + "extra": { + "branch-alias": { + "dev-community": "1.5-dev" + } + }, "autoload": { "psr-4": { "Facebook\\WebDriver\\": "lib/" @@ -1612,7 +1621,7 @@ "license": [ "Apache-2.0" ], - "description": "A PHP client for WebDriver", + "description": "A PHP client for Selenium WebDriver", "homepage": "https://github.com/facebook/php-webdriver", "keywords": [ "facebook", @@ -1620,7 +1629,7 @@ "selenium", "webdriver" ], - "time": "2017-01-13T15:48:08+00:00" + "time": "2017-03-22T10:56:03+00:00" }, { "name": "fzaninotto/faker", @@ -1672,21 +1681,21 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.2.2", + "version": "6.2.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60" + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ebf29dee597f02f09f4d5bbecc68230ea9b08f60", - "reference": "ebf29dee597f02f09f4d5bbecc68230ea9b08f60", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", "shasum": "" }, "require": { "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.3.1", + "guzzlehttp/psr7": "^1.4", "php": ">=5.5" }, "require-dev": { @@ -1730,7 +1739,7 @@ "rest", "web service" ], - "time": "2016-10-08T15:01:37+00:00" + "time": "2017-02-28T22:50:30+00:00" }, { "name": "guzzlehttp/promises", @@ -1785,16 +1794,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.3.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", - "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", "shasum": "" }, "require": { @@ -1830,16 +1839,23 @@ "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" } ], - "description": "PSR-7 message implementation", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", + "request", + "response", "stream", - "uri" + "uri", + "url" ], - "time": "2016-06-24T23:00:38+00:00" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -1989,27 +2005,27 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", + "phpspec/phpspec": "^2.5|^3.2", "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", @@ -2048,7 +2064,7 @@ "spy", "stub" ], - "time": "2016-11-21T14:58:47+00:00" + "time": "2017-03-02T20:05:34+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2202,25 +2218,30 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2242,20 +2263,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12T18:03:57+00:00" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.9", + "version": "1.4.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { @@ -2291,7 +2312,7 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15T14:06:22+00:00" + "time": "2017-02-27T10:12:30+00:00" }, { "name": "phpunit/phpunit", @@ -2757,16 +2778,16 @@ }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", "shasum": "" }, "require": { @@ -2806,7 +2827,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11T19:50:13+00:00" + "time": "2016-10-03T07:41:43+00:00" }, { "name": "sebastian/version", @@ -2844,17 +2865,62 @@ "time": "2015-06-21T13:59:46+00:00" }, { - "name": "symfony/browser-kit", - "version": "v3.2.3", + "name": "stecman/symfony-console-completion", + "version": "0.7.0", "source": { "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "394a2475a3a89089353fde5714a7f402fbb83880" + "url": "https://github.com/stecman/symfony-console-completion.git", + "reference": "5461d43e53092b3d3b9dbd9d999f2054730f4bbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/394a2475a3a89089353fde5714a7f402fbb83880", - "reference": "394a2475a3a89089353fde5714a7f402fbb83880", + "url": "https://api.github.com/repos/stecman/symfony-console-completion/zipball/5461d43e53092b3d3b9dbd9d999f2054730f4bbb", + "reference": "5461d43e53092b3d3b9dbd9d999f2054730f4bbb", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "symfony/console": "~2.3 || ~3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Stecman\\Component\\Symfony\\Console\\BashCompletion\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Holdaway", + "email": "stephen@stecman.co.nz" + } + ], + "description": "Automatic BASH completion for Symfony Console Component based applications.", + "time": "2016-02-24T05:08:54+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v3.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "2fe0caa60c1a1dfeefd0425741182687a9b382b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/2fe0caa60c1a1dfeefd0425741182687a9b382b8", + "reference": "2fe0caa60c1a1dfeefd0425741182687a9b382b8", "shasum": "" }, "require": { @@ -2898,20 +2964,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2017-01-31T21:49:23+00:00" + "time": "2017-02-21T09:12:04+00:00" }, { "name": "symfony/css-selector", - "version": "v3.2.3", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "f0e628f04fc055c934b3211cfabdb1c59eefbfaa" + "reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/f0e628f04fc055c934b3211cfabdb1c59eefbfaa", - "reference": "f0e628f04fc055c934b3211cfabdb1c59eefbfaa", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/a48f13dc83c168f1253a5d2a5a4fb46c36244c4c", + "reference": "a48f13dc83c168f1253a5d2a5a4fb46c36244c4c", "shasum": "" }, "require": { @@ -2951,20 +3017,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:32:22+00:00" + "time": "2017-02-21T09:12:04+00:00" }, { "name": "symfony/dom-crawler", - "version": "v3.2.3", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "b814b41373fc4e535aff8c765abe39545216f391" + "reference": "403944e294cf4ceb3b8447f54cbad88ea7b99cee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b814b41373fc4e535aff8c765abe39545216f391", - "reference": "b814b41373fc4e535aff8c765abe39545216f391", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/403944e294cf4ceb3b8447f54cbad88ea7b99cee", + "reference": "403944e294cf4ceb3b8447f54cbad88ea7b99cee", "shasum": "" }, "require": { @@ -3007,20 +3073,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2017-01-21T17:14:11+00:00" + "time": "2017-02-21T09:12:04+00:00" }, { "name": "symfony/finder", - "version": "v3.2.3", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8c71141cae8e2957946b403cc71a67213c0380d6" + "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8c71141cae8e2957946b403cc71a67213c0380d6", - "reference": "8c71141cae8e2957946b403cc71a67213c0380d6", + "url": "https://api.github.com/repos/symfony/finder/zipball/92d7476d2df60cd851a3e13e078664b1deb8ce10", + "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10", "shasum": "" }, "require": { @@ -3056,20 +3122,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-01-02T20:32:22+00:00" + "time": "2017-02-21T09:12:04+00:00" }, { "name": "symfony/process", - "version": "v3.2.3", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "32646a7cf53f3956c76dcb5c82555224ae321858" + "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/32646a7cf53f3956c76dcb5c82555224ae321858", - "reference": "32646a7cf53f3956c76dcb5c82555224ae321858", + "url": "https://api.github.com/repos/symfony/process/zipball/68bfa8c83f24c0ac04ea7193bcdcda4519f41892", + "reference": "68bfa8c83f24c0ac04ea7193bcdcda4519f41892", "shasum": "" }, "require": { @@ -3105,7 +3171,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-02-03T12:11:38+00:00" + "time": "2017-03-04T12:23:14+00:00" }, { "name": "webmozart/assert", @@ -3158,19 +3224,9 @@ "time": "2016-11-23T20:04:58+00:00" } ], - "aliases": [ - { - "alias": "1.6.0", - "alias_normalized": "1.6.0.0", - "version": "9999999-dev", - "package": "erusev/parsedown" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "erusev/parsedown": 20, - "gregwar/image": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/system/blueprints/config/site.yaml b/system/blueprints/config/site.yaml index fe783f084..57fd3c57a 100644 --- a/system/blueprints/config/site.yaml +++ b/system/blueprints/config/site.yaml @@ -19,7 +19,7 @@ form: default_lang: type: text label: PLUGIN_ADMIN.SITE_DEFAULT_LANG - size: vsmall + size: x-small placeholder: PLUGIN_ADMIN.SITE_DEFAULT_LANG_PLACEHOLDER help: PLUGIN_ADMIN.SITE_DEFAULT_LANG_HELP diff --git a/system/blueprints/config/system.yaml b/system/blueprints/config/system.yaml index 6aa0d6012..4a7f69849 100644 --- a/system/blueprints/config/system.yaml +++ b/system/blueprints/config/system.yaml @@ -102,7 +102,7 @@ form: pages.order.by: type: select - size: long + size: large classes: fancy label: PLUGIN_ADMIN.DEFAULT_ORDERING help: PLUGIN_ADMIN.DEFAULT_ORDERING_HELP @@ -155,6 +155,7 @@ form: pages.append_url_extension: type: text + size: x-small placeholder: "e.g. .html" label: PLUGIN_ADMIN.APPEND_URL_EXT help: PLUGIN_ADMIN.APPEND_URL_EXT_HELP @@ -856,13 +857,12 @@ form: fields: images.default_image_quality: - type: text + type: range append: '%' label: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY help: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY_HELP classes: x-small validate: - type: number min: 1 max: 100 @@ -1057,6 +1057,19 @@ form: fopen: PLUGIN_ADMIN.FOPEN curl: PLUGIN_ADMIN.CURL + gpm.official_gpm_only: + type: toggle + label: PLUGIN_ADMIN.GPM_OFFICIAL_ONLY + highlight: auto + help: PLUGIN_ADMIN.GPM_OFFICIAL_ONLY_HELP + highlight: 1 + options: + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + default: true + validate: + type: bool + gpm.verify_peer: type: toggle label: PLUGIN_ADMIN.GPM_VERIFY_PEER diff --git a/system/blueprints/pages/default.yaml b/system/blueprints/pages/default.yaml index 4b96ac6a2..0806ba24f 100644 --- a/system/blueprints/pages/default.yaml +++ b/system/blueprints/pages/default.yaml @@ -117,17 +117,6 @@ form: title: PLUGIN_ADMIN.SETTINGS underline: true - ordering: - type: toggle - label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX - help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP - highlight: 1 - options: - 1: PLUGIN_ADMIN.ENABLED - 0: PLUGIN_ADMIN.DISABLED - validate: - type: bool - folder: type: text label: PLUGIN_ADMIN.FOLDER_NAME @@ -165,9 +154,20 @@ form: title: PLUGIN_ADMIN.ORDERING underline: true + ordering: + type: toggle + label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX + help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP + highlight: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + order: type: order - label: PLUGIN_ADMIN.PAGE_ORDER + label: PLUGIN_ADMIN.SORTABLE_PAGES sitemap: overrides: @@ -291,6 +291,18 @@ form: validate: type: bool + header.debugger: + type: toggle + toggleable: true + label: PLUGIN_ADMIN.DEBUGGER + help: PLUGIN_ADMIN.DEBUGGER_HELP + highlight: 1 + options: + 1: PLUGIN_ADMIN.ENABLED + 0: PLUGIN_ADMIN.DISABLED + validate: + type: bool + header.template: type: text toggleable: true @@ -302,6 +314,25 @@ form: toggleable: true help: PLUGIN_ADMIN.APPEND_URL_EXT_HELP + admin_only: + type: section + title: PLUGIN_ADMIN.ADMIN_SPECIFIC_OVERRIDES + underline: true + + fields: + + header.admin.children_display_order: + type: select + label: PLUGIN_ADMIN.ADMIN_CHILDREN_DISPLAY_ORDER + help: PLUGIN_ADMIN.ADMIN_CHILDREN_DISPLAY_ORDER_HELP + toggleable: true + classes: fancy + default: 'collection' + options: + 'default': 'Ordered by Folder name (default)' + 'collection': 'Ordered by Collection definition' + + header.order_by: type: hidden diff --git a/system/blueprints/user/account.yaml b/system/blueprints/user/account.yaml index ff657b4c4..7a7c82b57 100644 --- a/system/blueprints/user/account.yaml +++ b/system/blueprints/user/account.yaml @@ -8,6 +8,13 @@ form: type: userinfo size: large + avatar: + type: file + size: large + destination: 'user://accounts/avatars' + multiple: false + random_name: true + content: type: section title: PLUGIN_ADMIN.ACCOUNT diff --git a/system/config/system.yaml b/system/config/system.yaml index 7d4de30e0..99628151c 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -138,3 +138,4 @@ gpm: proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128) method: 'auto' # Either 'curl', 'fopen' or 'auto'. 'auto' will try fopen first and if not available cURL verify_peer: true # Sometimes on some systems (Windows most commonly) GPM is unable to connect because the SSL certificate cannot be verified. Disabling this setting might help. + official_gpm_only: true # By default GPM direct-install will only allow URLs via the official GPM proxy to ensure security diff --git a/system/defines.php b/system/defines.php index 387435b35..1865c871a 100644 --- a/system/defines.php +++ b/system/defines.php @@ -8,7 +8,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '1.1.17'); +define('GRAV_VERSION', '1.2.0'); define('GRAV_TESTING', false); define('DS', '/'); diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php index eeb3adabf..20b1fce26 100644 --- a/system/src/Grav/Common/Assets.php +++ b/system/src/Grav/Common/Assets.php @@ -1255,13 +1255,8 @@ class Assets $old_url = $matches[2]; - // ensure this is not a data url - if (strpos($old_url, 'data:') === 0) { - return $matches[0]; - } - - // ensure this is not a remote url - if ($this->isRemoteLink($old_url)) { + // Ensure link is not rooted to webserver, a data URL, or to a remote host + if (Utils::startsWith($old_url, '/') || Utils::startsWith($old_url, 'data:') || $this->isRemoteLink($old_url)) { return $matches[0]; } diff --git a/system/src/Grav/Common/Data/Validation.php b/system/src/Grav/Common/Data/Validation.php index b597cd642..a508312d0 100644 --- a/system/src/Grav/Common/Data/Validation.php +++ b/system/src/Grav/Common/Data/Validation.php @@ -339,7 +339,7 @@ class Validation protected static function filterNumber($value, array $params, array $field) { - return (int) $value; + return (string)(int)$value !== (string)(float)$value ? (float) $value : (int) $value; } protected static function filterDateTime($value, array $params, array $field) @@ -585,7 +585,7 @@ class Validation $values[$key] = array_map('trim', explode(',', $value)); } else { $values[$key] = trim($value); - } + } } } diff --git a/system/src/Grav/Common/GPM/GPM.php b/system/src/Grav/Common/GPM/GPM.php index 857dd8fc0..584adbdd7 100644 --- a/system/src/Grav/Common/GPM/GPM.php +++ b/system/src/Grav/Common/GPM/GPM.php @@ -9,6 +9,7 @@ namespace Grav\Common\GPM; use Grav\Common\Grav; +use Grav\Common\Filesystem\Folder; use Grav\Common\Inflector; use Grav\Common\Iterator; use Grav\Common\Utils; @@ -499,6 +500,151 @@ class GPM extends Iterator return false; } + /** + * Download the zip package via the URL + * + * @param $package_file + * @param $tmp + * @return null|string + */ + public static function downloadPackage($package_file, $tmp) + { + $package = parse_url($package_file); + $filename = basename($package['path']); + + if (Grav::instance()['config']->get('system.gpm.official_gpm_only') && $package['host'] !== 'getgrav.org') { + throw new \RuntimeException("Only offical GPM URLs are allowed. You can modify this behavior in the System configuration."); + } + + $output = Response::get($package_file, []); + + if ($output) { + Folder::mkdir($tmp); + file_put_contents($tmp . DS . $filename, $output); + return $tmp . DS . $filename; + } + + return null; + } + + /** + * Copy the local zip package to tmp + * + * @param $package_file + * @param $tmp + * @return null|string + */ + public static function copyPackage($package_file, $tmp) + { + $package_file = realpath($package_file); + + if (file_exists($package_file)) { + $filename = basename($package_file); + Folder::mkdir($tmp); + copy(realpath($package_file), $tmp . DS . $filename); + return $tmp . DS . $filename; + } + + return null; + } + + /** + * Try to guess the package type from the source files + * + * @param $source + * @return bool|string + */ + public static function getPackageType($source) + { + $plugin_regex = '/^class\\s{1,}[a-zA-Z0-9]{1,}\\s{1,}extends.+Plugin/m'; + $theme_regex = '/^class\\s{1,}[a-zA-Z0-9]{1,}\\s{1,}extends.+Theme/m'; + + if ( + file_exists($source . 'system/defines.php') && + file_exists($source . 'system/config/system.yaml') + ) { + return 'grav'; + } else { + // must have a blueprint + if (!file_exists($source . 'blueprints.yaml')) { + return false; + } + + // either theme or plugin + $name = basename($source); + if (Utils::contains($name, 'theme')) { + return 'theme'; + } elseif (Utils::contains($name, 'plugin')) { + return 'plugin'; + } + foreach (glob($source . "*.php") as $filename) { + $contents = file_get_contents($filename); + if (preg_match($theme_regex, $contents)) { + return 'theme'; + } elseif (preg_match($plugin_regex, $contents)) { + return 'plugin'; + } + } + + // Assume it's a theme + return 'theme'; + } + } + + /** + * Try to guess the package name from the source files + * + * @param $source + * @return bool|string + */ + public static function getPackageName($source) + { + foreach (glob($source . "*.yaml") as $filename) { + $name = strtolower(basename($filename, '.yaml')); + if ($name == 'blueprints') { + continue; + } + return $name; + } + return false; + } + + /** + * Find/Parse the blueprint file + * + * @param $source + * @return array|bool + */ + public static function getBlueprints($source) + { + $blueprint_file = $source . 'blueprints.yaml'; + if (!file_exists($blueprint_file)) { + return false; + } + + $blueprint = (array)Yaml::parse(file_get_contents($blueprint_file)); + return $blueprint; + } + + /** + * Get the install path for a name and a particular type of package + * + * @param $type + * @param $name + * @return string + */ + public static function getInstallPath($type, $name) + { + $locator = Grav::instance()['locator']; + + if ($type == 'theme') { + $install_path = $locator->findResource('themes://', false) . DS . $name; + } else { + $install_path = $locator->findResource('plugins://', false) . DS . $name; + } + return $install_path; + } + /** * Searches for a list of Packages in the repository * @param array $searches An array of either slugs or names diff --git a/system/src/Grav/Common/GPM/Response.php b/system/src/Grav/Common/GPM/Response.php index 6b3036ff7..f046352ac 100644 --- a/system/src/Grav/Common/GPM/Response.php +++ b/system/src/Grav/Common/GPM/Response.php @@ -189,6 +189,17 @@ class Response return preg_match('/1|yes|on|true/i', ini_get('allow_url_fopen')); } + /** + * Is this a remote file or not + * + * @param $file + * @return bool + */ + public static function isRemote($file) + { + return (bool) filter_var($file, FILTER_VALIDATE_URL); + } + /** * Progress normalized for cURL and Fopen * Accepts a variable length of arguments passed in by stream method diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php index eb12eeb1c..34396bff3 100644 --- a/system/src/Grav/Common/Page/Media.php +++ b/system/src/Grav/Common/Page/Media.php @@ -141,8 +141,12 @@ class Media extends AbstractMedia foreach ($types['alternative'] as $altMedium) { if ($altMedium['file'] != $medium) { - $ratio = $altMedium['file']->get('width') / $medium->get('width'); - $medium->addAlternative($ratio, $altMedium['file']); + $altWidth = $altMedium['file']->get('width'); + $medWidth = $medium->get('width'); + if ($altWidth && $medWidth) { + $ratio = $altWidth / $medWidth; + $medium->addAlternative($ratio, $altMedium['file']); + } } } } diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 010c906e1..e844a75b7 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -86,6 +86,7 @@ class Page protected $hide_home_route; protected $ssl; protected $template_format; + protected $debugger; /** * @var Page Unmodified (original) version of the page. Used for copying and moving the page. @@ -424,6 +425,9 @@ class Page if (isset($this->header->template_format)) { $this->template_format = $this->header->template_format; } + if (isset($this->header->debugger)) { + $this->debugger = (bool)$this->header->debugger; + } } return $this->header; @@ -566,7 +570,8 @@ class Page $process_markdown = $this->shouldProcess('markdown'); - $process_twig = $this->shouldProcess('twig'); + $process_twig = $this->shouldProcess('twig') || $this->modularTwig() ; + $cache_enable = isset($this->header->cache_enable) ? $this->header->cache_enable : $config->get('system.cache.enabled', true); $twig_first = isset($this->header->twig_first) ? $this->header->twig_first : $config->get('system.pages.twig_first', @@ -799,6 +804,9 @@ class Page if ($name == 'folder') { return preg_replace(PAGE_ORDER_PREFIX_REGEX, '', $this->folder); } + if ($name == 'slug') { + return $this->slug(); + } if ($name == 'name') { $language = $this->language() ? '.' . $this->language() : ''; $name_val = str_replace($language . '.md', '', $this->name()); @@ -882,12 +890,12 @@ class Page /** * Save page if there's a file assigned to it. * - * @param bool $reorder Internal use. + * @param bool|mixed $reorder Internal use. */ public function save($reorder = true) { - // Perform move, copy or reordering if needed. - $this->doRelocation($reorder); + // Perform move, copy [or reordering] if needed. + $this->doRelocation(); $file = $this->file(); if ($file) { @@ -896,6 +904,13 @@ class Page $file->markdown($this->raw_content); $file->save(); } + + // Perform reorder if required + if ($reorder && is_array($reorder)) { + $this->doReorder($reorder); + } + + $this->_original = null; } /** @@ -1208,7 +1223,7 @@ class Page $this->expires = $var; } - return empty($this->expires) ? Grav::instance()['config']->get('system.pages.expires') : $this->expires; + return !isset($this->expires) ? Grav::instance()['config']->get('system.pages.expires') : $this->expires; } /** @@ -1373,6 +1388,20 @@ class Page return $this->process; } + /** + * Returns the state of the debugger override etting for this page + * + * @return mixed + */ + public function debugger() + { + if (isset($this->debugger) && $this->debugger === false) { + return false; + } else { + return true; + } + } + /** * Function to merge page metadata tags and build an array of Metadata objects * that can then be rendered in the page. @@ -2027,7 +2056,6 @@ class Page if ($var !== null) { $this->modular_twig = (bool)$var; if ($var) { - $this->process['twig'] = true; $this->visible(false); // some routable logic if (empty($this->header->routable)) { @@ -2560,6 +2588,16 @@ class Page return $file && $file->exists(); } + /** + * Returns whether or not the current folder exists + * + * @return bool + */ + public function folderExists() + { + return file_exists($this->path()); + } + /** * Cleans the path. * @@ -2578,65 +2616,62 @@ class Page } /** - * Moves or copies the page in filesystem. + * Reorders all siblings according to a defined order * - * @internal - * - * @param bool $reorder - * - * @throws Exception + * @param $new_order */ - protected function doRelocation($reorder) + protected function doReorder($new_order) { if (!$this->_original) { return; } - // Do reordering. - if ($reorder && $this->order() != $this->_original->order()) { - /** @var Pages $pages */ - $pages = Grav::instance()['pages']; + $pages = Grav::instance()['pages']; + $pages->init(); - $parent = $this->parent(); + $this->_original->path($this->path()); - // Extract visible children from the parent page. - $list = []; - /** @var Page $page */ - foreach ($parent->children()->visible() as $page) { - if ($page->order()) { - $list[$page->slug] = $page->path(); - } - } + $siblings = $this->parent()->children(); + $siblings->order('slug', 'asc', $new_order); - // If page was moved, take it out of the list. - if ($this->_action == 'move') { - unset($list[$this->slug()]); - } + $counter = 0; - $list = array_values($list); + // Reorder all moved pages. + foreach ($siblings as $slug => $page) { + $order = intval(trim($page->order(),'.')); + $counter++; - // Then add it back to the new location (if needed). - if ($this->order()) { - array_splice($list, min($this->order() - 1, count($list)), 0, [$this->path()]); - } - - // Reorder all moved pages. - foreach ($list as $order => $path) { - if ($path == $this->path()) { + if ($order) { + if ($page->path() == $this->path() && $this->folderExists()) { // Handle current page; we do want to change ordering number, but nothing else. - $this->order($order + 1); + $this->order($counter); + $this->save(false); } else { // Handle all the other pages. - $page = $pages->get($path); - - if ($page && $page->exists() && !$page->_action && $page->order() != $order + 1) { - $page = $page->move($parent); - $page->order($order + 1); + $page = $pages->get($page->path()); + if ($page && $page->folderExists() && !$page->_action) { + $page = $page->move($this->parent()); + $page->order($counter); $page->save(false); } } } } + } + + /** + * Moves or copies the page in filesystem. + * + * @internal + * + * @throws Exception + */ + protected function doRelocation() + { + if (!$this->_original) { + return; + } + if (is_dir($this->_original->path())) { if ($this->_action == 'move') { Folder::move($this->_original->path(), $this->path()); @@ -2652,7 +2687,6 @@ class Page } } - $this->_original = null; } protected function setPublishState() diff --git a/system/src/Grav/Common/Service/PageServiceProvider.php b/system/src/Grav/Common/Service/PageServiceProvider.php index 0db18a298..a363411a1 100644 --- a/system/src/Grav/Common/Service/PageServiceProvider.php +++ b/system/src/Grav/Common/Service/PageServiceProvider.php @@ -39,6 +39,11 @@ class PageServiceProvider implements ServiceProviderInterface /** @var Language $language */ $language = $c['language']; + // some debugger override logic + if ($page->debugger() === false) { + Grav::instance()['debugger']->enabled(false); + } + if ($c['config']->get('system.force_ssl')) { if (!isset($_SERVER['HTTPS']) || $_SERVER["HTTPS"] != "on") { $url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php index e1db8d7db..4ce6162b7 100644 --- a/system/src/Grav/Common/Themes.php +++ b/system/src/Grav/Common/Themes.php @@ -311,17 +311,23 @@ class Themes extends Iterator */ protected function autoloadTheme($class) { - /** @var UniformResourceLocator $locator */ - $locator = $this->grav['locator']; - $prefix = "Grav\\Theme"; if (false !== strpos($class, $prefix)) { // Remove prefix from class $class = substr($class, strlen($prefix)); - // Replace namespace tokens to directory separators + // Try Old style theme classes $path = strtolower(ltrim(preg_replace('#\\\|_(?!.+\\\)#', '/', $class), '/')); - $file = $locator->findResource("themes://{$path}/{$path}.php"); + $file = $this->grav['locator']->findResource("themes://{$path}/{$path}.php"); + + // Load class + if (file_exists($file)) { + return include_once($file); + } + + // Replace namespace tokens to directory separators + $path = $this->grav['inflector']->hyphenize(ltrim($class,"\\")); + $file = $this->grav['locator']->findResource("themes://{$path}/{$path}.php"); // Load class if (file_exists($file)) { diff --git a/system/src/Grav/Common/Twig/Twig.php b/system/src/Grav/Common/Twig/Twig.php index 9ef9e3e6d..7eec5b775 100644 --- a/system/src/Grav/Common/Twig/Twig.php +++ b/system/src/Grav/Common/Twig/Twig.php @@ -11,6 +11,7 @@ namespace Grav\Common\Twig; use Grav\Common\Grav; use Grav\Common\Config\Config; use Grav\Common\Language\Language; +use Grav\Common\Language\LanguageCodes; use Grav\Common\Page\Page; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use RocketTheme\Toolbox\Event\Event; @@ -173,7 +174,7 @@ class Twig 'theme_dir' => $locator->findResource('theme://'), 'theme_url' => $this->grav['base_url'] . '/' . $locator->findResource('theme://', false), 'html_lang' => $this->grav['language']->getActive() ?: $config->get('site.default_lang', 'en'), - + 'language_codes' => new LanguageCodes, ]; } } @@ -229,25 +230,22 @@ class Twig $twig_vars['header'] = $item->header(); $local_twig = clone($this->twig); - $modular_twig = $item->modularTwig(); - $process_twig = isset($item->header()->process['twig']) ? $item->header()->process['twig'] : false; - - $output = ''; try { // Process Modular Twig - if ($modular_twig) { + if ($item->modularTwig()) { $twig_vars['content'] = $content; $template = $item->template() . TEMPLATE_EXT; $output = $content = $local_twig->render($template, $twig_vars); } // Process in-page Twig - if (!$modular_twig || ($modular_twig && $process_twig)) { + if ($item->shouldProcess('twig')) { $name = '@Page:' . $item->path(); $this->setTemplate($name, $content); $output = $local_twig->render($name, $twig_vars); } + } catch (\Twig_Error_Loader $e) { throw new \RuntimeException($e->getRawMessage(), 404, $e); } diff --git a/system/src/Grav/Common/Twig/TwigExtension.php b/system/src/Grav/Common/Twig/TwigExtension.php index fff032e9c..e12fa9a4c 100644 --- a/system/src/Grav/Common/Twig/TwigExtension.php +++ b/system/src/Grav/Common/Twig/TwigExtension.php @@ -104,7 +104,8 @@ class TwigExtension extends \Twig_Extension 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('evaluate', [$this, 'evaluateFunc']), + new \Twig_SimpleFunction('evaluate', [$this, 'evaluateStringFunc'], ['needs_context' => true, 'needs_environment' => true]), + new \Twig_SimpleFunction('evaluate_twig', [$this, 'evaluateTwigFunc'], ['needs_context' => true, 'needs_environment' => true]), new \Twig_SimpleFunction('gist', [$this, 'gistFunc']), new \Twig_SimpleFunction('nonce_field', [$this, 'nonceFieldFunc']), new \Twig_simpleFunction('random_string', [$this, 'randomStringFunc']), @@ -432,9 +433,10 @@ class TwigExtension extends \Twig_Extension /** * @param $string * + * @param bool $block Block or Line processing * @return mixed|string */ - public function markdownFilter($string) + public function markdownFilter($string, $block = true) { $page = $this->grav['page']; $defaults = $this->config->get('system.pages.markdown'); @@ -446,7 +448,12 @@ class TwigExtension extends \Twig_Extension $parsedown = new Parsedown($page, $defaults); } - $string = $parsedown->text($string); + if ($block) { + $string = $parsedown->text($string); + } else { + $string = $parsedown->line($string); + } + return $string; } @@ -563,15 +570,22 @@ class TwigExtension extends \Twig_Extension $domain = true; } + if (Grav::instance()['uri']->isExternal($input)) { + return $input; + } - if (strpos((string)$input, '://')) { + $input = ltrim((string)$input, '/'); + + if (Utils::contains((string)$input, '://')) { /** @var UniformResourceLocator $locator */ $locator = $this->grav['locator']; + + // Get relative path to the resource (or false if not found). - $resource = $locator->findResource((string)$input, false); + $resource = $locator->findResource($input, false); } else { - $resource = (string)$input; + $resource = $input; } /** @var Uri $uri */ @@ -581,22 +595,51 @@ class TwigExtension extends \Twig_Extension } /** - * Evaluate a string + * This function will evaluate Twig $twig through the $environment, and return its results. * - * @example {{ evaluate('grav.language.getLanguage') }} - * - * @param string $input String to be evaluated - * - * @return string Returns the evaluated string + * @param \Twig_Environment $environment + * @param array $context + * @param string $twig + * @return mixed */ - public function evaluateFunc($input) - { - if (!$input) { //prevent an obscure Twig error if $input is not set - $input = '""'; - } - return $this->grav['twig']->processString("{{ $input }}"); + public function evaluateTwigFunc( \Twig_Environment $environment, $context, $twig ) { + $loader = $environment->getLoader( ); + + $parsed = $this->parseString( $environment, $context, $twig ); + + $environment->setLoader( $loader ); + return $parsed; } + /** + * This function will evaluate a $string through the $environment, and return its results. + * + * @param \Twig_Environment $environment + * @param $context + * @param $string + * @return mixed + */ + public function evaluateStringFunc(\Twig_Environment $environment, $context, $string ) + { + $parsed = $this->evaluateTwigFunc($environment, $context, "{{ $string }}"); + return $parsed; + } + + /** + * Sets the parser for the environment to Twig_Loader_String, and parsed the string $string. + * + * @param \Twig_Environment $environment + * @param array $context + * @param string $string + * @return string + */ + protected function parseString( \Twig_Environment $environment, $context, $string ) { + $environment->setLoader( new \Twig_Loader_String( ) ); + return $environment->render( $string, $context ); + } + + + /** * Based on Twig_Extension_Debug / twig_var_dump * (c) 2011 Fabien Potencier @@ -778,7 +821,7 @@ class TwigExtension extends \Twig_Extension */ public function nonceFieldFunc($action, $nonceParamName = 'nonce') { - $string = ''; + $string = ''; return $string; } diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index dd8308db6..e1383688c 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -727,7 +727,7 @@ class Uri * * @return boolean is eternal state */ - public function isExternal($url) + public static function isExternal($url) { if (Utils::startsWith($url, 'http')) { return true; @@ -1086,4 +1086,20 @@ class Uri return $urlWithNonce; } + + /** + * Is the passed in URL a valid URL? + * + * @param $url + * @return bool + */ + public static function isValidUrl($url) + { + $regex = '/^(?:(https?|ftp|telnet):)?\/\/((?:[a-z0-9@:.-]|%[0-9A-F]{2}){3,})(?::(\d+))?((?:\/(?:[a-z0-9-._~!$&\'\(\)\*\+\,\;\=\:\@]|%[0-9A-F]{2})*)*)(?:\?((?:[a-z0-9-._~!$&\'\(\)\*\+\,\;\=\:\/?@]|%[0-9A-F]{2})*))?(?:#((?:[a-z0-9-._~!$&\'\(\)\*\+\,\;\=\:\/?@]|%[0-9A-F]{2})*))?/'; + if (preg_match($regex, $url)) { + return true; + } else { + return false; + } + } } diff --git a/system/src/Grav/Common/User/User.php b/system/src/Grav/Common/User/User.php index fcc8f6c43..d0c35eb31 100644 --- a/system/src/Grav/Common/User/User.php +++ b/system/src/Grav/Common/User/User.php @@ -57,14 +57,14 @@ class User extends Data /** * Find a user by username, email, etc * - * @param $query the query to search for + * @param string $query the query to search for * @param array $fields the fields to search * @return User */ public static function find($query, $fields = ['username', 'email']) { $account_dir = Grav::instance()['locator']->findResource('account://'); - $files = array_diff(scandir($account_dir), ['.', '..']); + $files = $account_dir ? array_diff(scandir($account_dir), ['.', '..']) : []; // Try with username first, you never know! if (in_array('username', $fields)) { @@ -100,7 +100,7 @@ class User extends Data public static function remove($username) { $file_path = Grav::instance()['locator']->findResource('account://' . $username . YAML_EXT); - if (file_exists($file_path) && unlink($file_path)) { + if ($file_path && unlink($file_path)) { return true; } @@ -239,4 +239,20 @@ class User extends Data { return $this->authorize($action); } + + /** + * Return the User's avatar URL + * + * @return string + */ + public function avatarUrl() + { + if ($this->avatar) { + $avatar = $this->avatar; + $avatar = array_shift($avatar); + return Grav::instance()['base_url'] . '/' . $avatar['path']; + } else { + return 'https://www.gravatar.com/avatar/' . md5($this->email); + } + } } diff --git a/system/src/Grav/Console/Gpm/DirectInstallCommand.php b/system/src/Grav/Console/Gpm/DirectInstallCommand.php index e23712e9f..679d5c635 100644 --- a/system/src/Grav/Console/Gpm/DirectInstallCommand.php +++ b/system/src/Grav/Console/Gpm/DirectInstallCommand.php @@ -9,14 +9,13 @@ namespace Grav\Console\Gpm; use Grav\Common\Grav; -use Grav\Common\Utils; use Grav\Common\Filesystem\Folder; +use Grav\Common\GPM\GPM; use Grav\Common\GPM\Installer; use Grav\Common\GPM\Response; use Grav\Console\ConsoleCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\Yaml\Yaml; class DirectInstallCommand extends ConsoleCommand { @@ -32,7 +31,7 @@ class DirectInstallCommand extends ConsoleCommand ->addArgument( 'package-file', InputArgument::REQUIRED, - 'The local location or remote URL to an installable package file' + 'Installable package local or remote . Can install specific version' ) ->setDescription("Installs Grav, plugin, or theme directly from a file or a URL") ->setHelp('The direct-install command installs Grav, plugin, or theme directly from a file or a URL'); @@ -63,10 +62,30 @@ class DirectInstallCommand extends ConsoleCommand $this->output->writeln("Preparing to install " . $package_file . ""); - if ($this->isRemote($package_file)) { - $zip = $this->downloadPackage($package_file, $tmp_zip); + if (Response::isRemote($package_file)) { + $this->output->write(" |- Downloading package... 0%"); + try { + $zip = GPM::downloadPackage($package_file, $tmp_zip); + } catch (\RuntimeException $e) { + $this->output->writeln(''); + $this->output->writeln(" `- ERROR: " . $e->getMessage() . ""); + $this->output->writeln(''); + exit; + } + + if ($zip) { + $this->output->write("\x0D"); + $this->output->write(" |- Downloading package... 100%"); + $this->output->writeln(''); + } } else { - $zip = $this->copyPackage($package_file, $tmp_zip); + $this->output->write(" |- Copying package... 0%"); + $zip = GPM::copyPackage($package_file, $tmp_zip); + if ($zip) { + $this->output->write("\x0D"); + $this->output->write(" |- Copying package... 100%"); + $this->output->writeln(''); + } } if (file_exists($zip)) { @@ -85,7 +104,7 @@ class DirectInstallCommand extends ConsoleCommand $this->output->writeln(" |- Extracting package... ok"); - $type = $this->getPackageType($extracted); + $type = GPM::getPackageType($extracted); if (!$type) { $this->output->writeln(" '- ERROR: Not a valid Grav package"); @@ -93,7 +112,7 @@ class DirectInstallCommand extends ConsoleCommand exit; } - $blueprint = $this->getBlueprints($extracted); + $blueprint = GPM::getBlueprints($extracted); if ($blueprint) { if (isset($blueprint['dependencies'])) { $depencencies = []; @@ -137,7 +156,7 @@ class DirectInstallCommand extends ConsoleCommand $this->output->write(" |- Installing package... "); Installer::install($zip, GRAV_ROOT, ['sophisticated' => true, 'overwrite' => true, 'ignore_symlinks' => true], $extracted); } else { - $name = $this->getPackageName($extracted); + $name = GPM::getPackageName($extracted); if (!$name) { $this->output->writeln("ERROR: Name could not be determined. Please specify with --name|-n"); @@ -145,7 +164,7 @@ class DirectInstallCommand extends ConsoleCommand exit; } - $install_path = $this->getInstallPath($type, $name); + $install_path = GPM::getInstallPath($type, $name); $is_update = file_exists($install_path); $this->output->write(" |- Checking destination... "); @@ -173,7 +192,7 @@ class DirectInstallCommand extends ConsoleCommand $this->output->write("\x0D"); if(Installer::lastErrorCode()) { - $this->output->writeln(" '- Installation failed or aborted."); + $this->output->writeln(" '- " . Installer::lastErrorMsg() . ""); $this->output->writeln(''); } else { $this->output->writeln(" |- Installing package... ok"); @@ -193,186 +212,4 @@ class DirectInstallCommand extends ConsoleCommand return true; } - - /** - * Get the install path for a name and a particular type of package - * - * @param $type - * @param $name - * @return string - */ - protected function getInstallPath($type, $name) - { - $locator = Grav::instance()['locator']; - - if ($type == 'theme') { - $install_path = $locator->findResource('themes://', false) . DS . $name; - } else { - $install_path = $locator->findResource('plugins://', false) . DS . $name; - } - return $install_path; - } - - /** - * Try to guess the package name from the source files - * - * @param $source - * @return bool|string - */ - protected function getPackageName($source) - { - foreach (glob($source . "*.yaml") as $filename) { - $name = strtolower(basename($filename, '.yaml')); - if ($name == 'blueprints') { - continue; - } - return $name; - } - return false; - } - - /** - * Try to guess the package type from the source files - * - * @param $source - * @return bool|string - */ - protected function getPackageType($source) - { - $plugin_regex = '/^class\\s{1,}[a-zA-Z0-9]{1,}\\s{1,}extends.+Plugin/m'; - $theme_regex = '/^class\\s{1,}[a-zA-Z0-9]{1,}\\s{1,}extends.+Theme/m'; - - if ( - file_exists($source . 'system/defines.php') && - file_exists($source . 'system/config/system.yaml') - ) { - return 'grav'; - } else { - // must have a blueprint - if (!file_exists($source . 'blueprints.yaml')) { - return false; - } - - // either theme or plugin - $name = basename($source); - if (Utils::contains($name, 'theme')) { - return 'theme'; - } elseif (Utils::contains($name, 'plugin')) { - return 'plugin'; - } - foreach (glob($source . "*.php") as $filename) { - $contents = file_get_contents($filename); - if (preg_match($theme_regex, $contents)) { - return 'theme'; - } elseif (preg_match($plugin_regex, $contents)) { - return 'plugin'; - } - } - - // Assume it's a theme - return 'theme'; - } - } - - /** - * Determine if this is a local or a remote file - * - * @param $file - * @return bool - */ - protected function isRemote($file) - { - return (bool) filter_var($file, FILTER_VALIDATE_URL); - } - - /** - * Find/Parse the blueprint file - * - * @param $source - * @return array|bool - */ - protected function getBlueprints($source) - { - $blueprint_file = $source . 'blueprints.yaml'; - if (!file_exists($blueprint_file)) { - return false; - } - - $blueprint = (array)Yaml::parse(file_get_contents($blueprint_file)); - return $blueprint; - } - - /** - * Download the zip package via the URL - * - * @param $package_file - * @param $tmp - * @return null|string - */ - private function downloadPackage($package_file, $tmp) - { - $this->output->write(" |- Downloading package... 0%"); - - $package = parse_url($package_file); - - - $filename = basename($package['path']); - $output = Response::get($package_file, [], [$this, 'progress']); - - if ($output) { - Folder::mkdir($tmp); - - $this->output->write("\x0D"); - $this->output->write(" |- Downloading package... 100%"); - $this->output->writeln(''); - - file_put_contents($tmp . DS . $filename, $output); - - return $tmp . DS . $filename; - } - - return null; - - } - - /** - * Copy the local zip package to tmp - * - * @param $package_file - * @param $tmp - * @return null|string - */ - private function copyPackage($package_file, $tmp) - { - $this->output->write(" |- Copying package... 0%"); - - $package_file = realpath($package_file); - - if (file_exists($package_file)) { - $filename = basename($package_file); - - Folder::mkdir($tmp); - - $this->output->write("\x0D"); - $this->output->write(" |- Copying package... 100%"); - $this->output->writeln(''); - - copy(realpath($package_file), $tmp . DS . $filename); - - return $tmp . DS . $filename; - } - - return null; - - } - - /** - * @param $progress - */ - public function progress($progress) - { - $this->output->write("\x0D"); - $this->output->write(" |- Downloading package... " . str_pad($progress['percent'], 5, " ", - STR_PAD_LEFT) . '%'); - } } diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index abf5e8163..bd01ead2b 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -80,7 +80,7 @@ class InstallCommand extends ConsoleCommand ->addArgument( 'package', InputArgument::IS_ARRAY | InputArgument::REQUIRED, - 'The package(s) that are desired to be installed. Use the "index" command for a list of packages' + 'Package(s) to install. Use "bin/gpm index" to list packages. Use "bin/gpm direct-install" to install a specific version' ) ->setDescription("Performs the installation of plugins and themes") ->setHelp('The install command allows to install plugins and themes'); @@ -563,6 +563,7 @@ class InstallCommand extends ConsoleCommand $tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true); $this->tmp = $tmp_dir . '/Grav-' . uniqid(); $filename = $package->slug . basename($package->zipball_url); + $filename = preg_replace('/[\\\\\/:"*?&<>|]+/mi', '-', $filename); $query = ''; if ($package->premium) { diff --git a/tests/unit/Grav/Common/Markdown/ParsedownTest.php b/tests/unit/Grav/Common/Markdown/ParsedownTest.php index bbd1cad3a..e73e11f01 100644 --- a/tests/unit/Grav/Common/Markdown/ParsedownTest.php +++ b/tests/unit/Grav/Common/Markdown/ParsedownTest.php @@ -675,6 +675,8 @@ class ParsedownTest extends \Codeception\TestCase\Test { $this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init(); + $this->assertSame('

Anchor Class

', + $this->parsedown->text('[Anchor Class](?classes=button#something)')); $this->assertSame('

Relative Class

', $this->parsedown->text('[Relative Class](../item2-3?classes=button)')); $this->assertSame('

Relative ID

',