Merge branch 'release/1.1.2'

This commit is contained in:
Andy Miller
2016-08-11 12:42:55 -06:00
23 changed files with 370 additions and 145 deletions

View File

@@ -1,3 +1,20 @@
# v1.1.2
## 08/10/2016
1. [](#new)
* Allow forcing SSL by setting `system.force_ssl` (Force SSL in the Admin System Config) [#899](https://github.com/getgrav/grav/pull/899)
1. [](#improved)
* Improved `authorize` Twig extension to accept a nested array of authorizations [#948](https://github.com/getgrav/grav/issues/948)
* Don't add timestamps on remote assets as it can cause conflicts
* Grav now looks at types from `media.yaml` when retrieving page mime types [#966](https://github.com/getgrav/grav/issues/966)
* Added support for dumping exceptions in the Debugger
1. [](#bugfix)
* Fixed `Folder::delete` method to recursively remove files and folders and causing Upgrade to fail.
* Fix [#952](https://github.com/getgrav/grav/issues/952) hyphenize the session name.
* If no parent is set and siblings collection is called, return a new and empty collection [grav-plugin-sitemap/issues/22](https://github.com/getgrav/grav-plugin-sitemap/issues/22)
* Prevent exception being thrown when calling the Collator constructor failed in a Windows environment with the Intl PHP Extension enabled [#961](https://github.com/getgrav/grav/issues/961)
* Fix for markdown images not properly rendering `id` attribute [#956](https://github.com/getgrav/grav/issues/956)
# v1.1.1
## 07/16/2016
@@ -817,7 +834,7 @@
* Improved query string handling
* Optimization to image handling supporting URL encoded filenames
* Use global `composer` when available rather than Grv provided one
* Use `PHP_BINARY` contant rather than `php` executable
* Use `PHP_BINARY` constant rather than `php` executable
* Updated Doctrine Cache library
* Updated Symfony libraries
* Moved `convertUrl()` method to Uri object

171
composer.lock generated
View File

@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "9c19c674a6ce22978364e1327bab1bbd",
"content-hash": "4b371a1eaef8d32d9ce9536c7c317625",
"hash": "65cd6cc2a20addb345acc1f84d5ae3ab",
"content-hash": "0ddb599b8e9fb7f0fb76619343180ef9",
"packages": [
{
"name": "doctrine/cache",
@@ -533,16 +533,16 @@
},
{
"name": "monolog/monolog",
"version": "1.19.0",
"version": "1.20.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf"
"reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/5f56ed5212dc509c8dc8caeba2715732abb32dbf",
"reference": "5f56ed5212dc509c8dc8caeba2715732abb32dbf",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037",
"reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037",
"shasum": ""
},
"require": {
@@ -561,8 +561,8 @@
"php-console/php-console": "^3.1.3",
"phpunit/phpunit": "~4.5",
"phpunit/phpunit-mock-objects": "2.3.0",
"raven/raven": "^0.13",
"ruflin/elastica": ">=0.90 <3.0",
"sentry/sentry": "^0.13",
"swiftmailer/swiftmailer": "~5.3"
},
"suggest": {
@@ -574,9 +574,9 @@
"mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"php-console/php-console": "Allow sending log messages to Google Chrome",
"raven/raven": "Allow sending log messages to a Sentry server",
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"sentry/sentry": "Allow sending log messages to a Sentry server"
},
"type": "library",
"extra": {
@@ -607,7 +607,7 @@
"logging",
"psr-3"
],
"time": "2016-04-12 18:29:35"
"time": "2016-07-02 14:02:10"
},
{
"name": "pimple/pimple",
@@ -743,16 +743,16 @@
},
{
"name": "symfony/console",
"version": "v2.8.7",
"version": "v2.8.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3"
"reference": "c392a6ec72f2122748032c2ad6870420561ffcfa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
"reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
"url": "https://api.github.com/repos/symfony/console/zipball/c392a6ec72f2122748032c2ad6870420561ffcfa",
"reference": "c392a6ec72f2122748032c2ad6870420561ffcfa",
"shasum": ""
},
"require": {
@@ -799,20 +799,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2016-06-06 15:06:25"
"time": "2016-06-29 07:02:14"
},
{
"name": "symfony/event-dispatcher",
"version": "v2.8.7",
"version": "v2.8.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "2a6b8713f8bdb582058cfda463527f195b066110"
"reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2a6b8713f8bdb582058cfda463527f195b066110",
"reference": "2a6b8713f8bdb582058cfda463527f195b066110",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b180b70439dca70049b6b9b7e21d75e6e5d7aca9",
"reference": "b180b70439dca70049b6b9b7e21d75e6e5d7aca9",
"shasum": ""
},
"require": {
@@ -859,7 +859,7 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2016-06-06 11:11:27"
"time": "2016-06-29 05:29:29"
},
{
"name": "symfony/polyfill-iconv",
@@ -981,16 +981,16 @@
},
{
"name": "symfony/var-dumper",
"version": "v2.8.7",
"version": "v2.8.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "0c5970fc6cb9222b78559f20858f76db1e5ac326"
"reference": "eb21798f1cd2d3a1c1e1e4d0632b6d04a798f210"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/0c5970fc6cb9222b78559f20858f76db1e5ac326",
"reference": "0c5970fc6cb9222b78559f20858f76db1e5ac326",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/eb21798f1cd2d3a1c1e1e4d0632b6d04a798f210",
"reference": "eb21798f1cd2d3a1c1e1e4d0632b6d04a798f210",
"shasum": ""
},
"require": {
@@ -1040,20 +1040,20 @@
"debug",
"dump"
],
"time": "2016-05-24 10:00:02"
"time": "2016-06-29 05:29:29"
},
{
"name": "symfony/yaml",
"version": "v2.8.7",
"version": "v2.8.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34"
"reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/815fabf3f48c7d1df345a69d1ad1a88f59757b34",
"reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34",
"url": "https://api.github.com/repos/symfony/yaml/zipball/dba4bb5846798cd12f32e2d8f3f35d77045773c8",
"reference": "dba4bb5846798cd12f32e2d8f3f35d77045773c8",
"shasum": ""
},
"require": {
@@ -1089,7 +1089,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2016-06-06 11:11:27"
"time": "2016-06-29 05:29:29"
},
{
"name": "twig/twig",
@@ -1214,16 +1214,16 @@
},
{
"name": "codeception/codeception",
"version": "2.2.1",
"version": "2.2.2",
"source": {
"type": "git",
"url": "https://github.com/Codeception/Codeception.git",
"reference": "f137636f0c185e7d4a495b9cea70c1afae27dfc7"
"reference": "8d80bb4ec7470e8df5de0e4c401785bc3fa1f4f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/f137636f0c185e7d4a495b9cea70c1afae27dfc7",
"reference": "f137636f0c185e7d4a495b9cea70c1afae27dfc7",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/8d80bb4ec7470e8df5de0e4c401785bc3fa1f4f6",
"reference": "8d80bb4ec7470e8df5de0e4c401785bc3fa1f4f6",
"shasum": ""
},
"require": {
@@ -1236,6 +1236,8 @@
"php": ">=5.4.0 <8.0",
"phpunit/php-code-coverage": ">=2.1.3",
"phpunit/phpunit": ">4.8.20 <5.5",
"sebastian/comparator": "~1.1",
"sebastian/diff": "^1.4",
"symfony/browser-kit": ">=2.7 <4.0",
"symfony/console": ">=2.7 <4.0",
"symfony/css-selector": ">=2.7 <4.0",
@@ -1299,7 +1301,7 @@
"functional testing",
"unit testing"
],
"time": "2016-06-03 12:44:06"
"time": "2016-06-29 00:59:28"
},
{
"name": "doctrine/instantiator",
@@ -1357,19 +1359,20 @@
},
{
"name": "facebook/webdriver",
"version": "1.1.1",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/facebook/php-webdriver.git",
"reference": "1c98108ba3eb435b681655764de11502a0653705"
"reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/1c98108ba3eb435b681655764de11502a0653705",
"reference": "1c98108ba3eb435b681655764de11502a0653705",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/0b889d7de7461439f8a3bbcca46e0f696cb27986",
"reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.19"
},
"require-dev": {
@@ -1396,7 +1399,7 @@
"selenium",
"webdriver"
],
"time": "2015-12-31 15:58:49"
"time": "2016-06-04 00:02:34"
},
{
"name": "fzaninotto/faker",
@@ -1448,27 +1451,27 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "6.2.0",
"version": "6.2.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "d094e337976dff9d8e2424e8485872194e768662"
"reference": "3f808fba627f2c5b69e2501217bf31af349c1427"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662",
"reference": "d094e337976dff9d8e2424e8485872194e768662",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427",
"reference": "3f808fba627f2c5b69e2501217bf31af349c1427",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "~1.0",
"guzzlehttp/psr7": "~1.1",
"php": ">=5.5.0"
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.3.1",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "~4.0",
"psr/log": "~1.0"
"phpunit/phpunit": "^4.0",
"psr/log": "^1.0"
},
"type": "library",
"extra": {
@@ -1506,7 +1509,7 @@
"rest",
"web service"
],
"time": "2016-03-21 20:02:09"
"time": "2016-07-15 17:22:37"
},
{
"name": "guzzlehttp/promises",
@@ -1561,16 +1564,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "1.3.0",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "31382fef2889136415751badebbd1cb022a4ed72"
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/31382fef2889136415751badebbd1cb022a4ed72",
"reference": "31382fef2889136415751badebbd1cb022a4ed72",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
"reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b",
"shasum": ""
},
"require": {
@@ -1586,7 +1589,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
"dev-master": "1.4-dev"
}
},
"autoload": {
@@ -1615,7 +1618,7 @@
"stream",
"uri"
],
"time": "2016-04-13 19:56:01"
"time": "2016-06-24 23:00:38"
},
{
"name": "phpdocumentor/reflection-common",
@@ -2413,16 +2416,16 @@
},
{
"name": "sebastian/exporter",
"version": "1.2.1",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "7ae5513327cb536431847bcc0c10edba2701064e"
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
"reference": "7ae5513327cb536431847bcc0c10edba2701064e",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
"shasum": ""
},
"require": {
@@ -2430,12 +2433,13 @@
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"ext-mbstring": "*",
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
"dev-master": "1.3.x-dev"
}
},
"autoload": {
@@ -2475,7 +2479,7 @@
"export",
"exporter"
],
"time": "2015-06-21 07:55:53"
"time": "2016-06-17 09:04:28"
},
{
"name": "sebastian/global-state",
@@ -2618,16 +2622,16 @@
},
{
"name": "symfony/browser-kit",
"version": "v3.1.0",
"version": "v3.1.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "b645a9b23d6c0eeba5ac823fa87bf010db9aff22"
"reference": "dcf41ed026b0499254385b5c88f03247b2ba010b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/b645a9b23d6c0eeba5ac823fa87bf010db9aff22",
"reference": "b645a9b23d6c0eeba5ac823fa87bf010db9aff22",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/dcf41ed026b0499254385b5c88f03247b2ba010b",
"reference": "dcf41ed026b0499254385b5c88f03247b2ba010b",
"shasum": ""
},
"require": {
@@ -2671,20 +2675,20 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2016-03-04 07:56:56"
"time": "2016-06-29 05:41:56"
},
{
"name": "symfony/css-selector",
"version": "v3.1.0",
"version": "v3.1.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "e17f386efef7258ac671c24e727673abd086b0cf"
"reference": "2851e1932d77ce727776154d659b232d061e816a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/e17f386efef7258ac671c24e727673abd086b0cf",
"reference": "e17f386efef7258ac671c24e727673abd086b0cf",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/2851e1932d77ce727776154d659b232d061e816a",
"reference": "2851e1932d77ce727776154d659b232d061e816a",
"shasum": ""
},
"require": {
@@ -2724,20 +2728,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2016-03-04 07:56:56"
"time": "2016-06-29 05:41:56"
},
{
"name": "symfony/dom-crawler",
"version": "v3.1.0",
"version": "v3.1.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "12aa63fd41b060d2bee9a34623d29eda70bc8fe3"
"reference": "99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/12aa63fd41b060d2bee9a34623d29eda70bc8fe3",
"reference": "12aa63fd41b060d2bee9a34623d29eda70bc8fe3",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0",
"reference": "99ec4a23330fcd0c8667095f3ef7aa204ffd9dc0",
"shasum": ""
},
"require": {
@@ -2780,20 +2784,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2016-05-13 15:49:09"
"time": "2016-06-29 05:41:56"
},
{
"name": "symfony/finder",
"version": "v3.1.0",
"version": "v3.1.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "40d17ed287bf51a2f884c4619ce8ff2a1c5cd219"
"reference": "8201978de88a9fa0923e18601bb17f1df9c721e7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/40d17ed287bf51a2f884c4619ce8ff2a1c5cd219",
"reference": "40d17ed287bf51a2f884c4619ce8ff2a1c5cd219",
"url": "https://api.github.com/repos/symfony/finder/zipball/8201978de88a9fa0923e18601bb17f1df9c721e7",
"reference": "8201978de88a9fa0923e18601bb17f1df9c721e7",
"shasum": ""
},
"require": {
@@ -2829,7 +2833,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2016-05-13 18:06:41"
"time": "2016-06-29 05:41:56"
},
{
"name": "webmozart/assert",
@@ -2900,7 +2904,8 @@
"php": ">=5.5.9",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-curl": "*"
"ext-curl": "*",
"ext-zip": "*"
},
"platform-dev": []
}

View File

@@ -513,7 +513,7 @@ form:
label: PLUGIN_ADMIN.MEMCACHED_PORT
help: PLUGIN_ADMIN.MEMCACHED_PORT_HELP
placeholder: "11211"
cache.redis.server:
type: text
size: medium
@@ -1018,3 +1018,14 @@ form:
options:
':': ': (default)'
';': '; (for Apache running on Windows)'
force_ssl:
type: toggle
label: PLUGIN_ADMIN.FORCE_SSL
highlight: 0
help: PLUGIN_ADMIN.FORCE_SSL_HELP
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool

View File

@@ -16,12 +16,12 @@ summary:
delimiter: === # The summary delimiter
redirects:
# /redirect-test: / # Redirect test goes to home page
# /old/(.*): /new/$1 # Would redirect /old/my-page to /new/my-page
# '/redirect-test': '/' # Redirect test goes to home page
# '/old/(.*)': '/new/$1' # Would redirect /old/my-page to /new/my-page
routes:
# /something/else: '/blog/sample-3' # Alias for /blog/sample-3
# /new/(.*): '/blog/$1' # Regex any /new/my-page URL to /blog/my-page Route
# '/something/else': '/blog/sample-3' # Alias for /blog/sample-3
# '/new/(.*)': '/blog/$1' # Regex any /new/my-page URL to /blog/my-page Route
blog:
route: '/blog' # Custom value added (accessible via system.blog.route)

View File

@@ -4,7 +4,7 @@ default_locale: # Default locale (defaults to system
param_sep: ':' # Parameter separator, use ';' for Apache on windows
wrapped_site: false # For themes/plugins to know if Grav is wrapped by another platform
reverse_proxy_setup: false # Running in a reverse proxy scenario with different webserver ports than proxy
force_ssl: false # If enabled, Grav forces to be accessed via HTTPS
languages:
supported: [] # List of languages supported. eg: [en, fr, de]

View File

@@ -8,7 +8,7 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.1.1');
define('GRAV_VERSION', '1.1.2');
define('GRAV_TESTING', false);
define('DS', '/');
define('GRAV_PHP_MIN', '5.5.9');

View File

@@ -281,8 +281,9 @@ class Assets
return $this;
}
$modified = 0;
if (!$this->isRemoteLink($asset)) {
$modified = false;
$remote = $this->isRemoteLink($asset);
if (!$remote) {
$modified = $this->getLastModificationTime($asset);
$asset = $this->buildLocalLink($asset);
}
@@ -294,6 +295,7 @@ class Assets
$data = [
'asset' => $asset,
'remote' => $remote,
'priority' => intval($priority ?: 10),
'order' => count($this->css),
'pipeline' => (bool) $pipeline,
@@ -345,8 +347,9 @@ class Assets
return $this;
}
$modified = 0;
if (!$this->isRemoteLink($asset)) {
$modified = false;
$remote = $this->isRemoteLink($asset);
if (!$remote) {
$modified = $this->getLastModificationTime($asset);
$asset = $this->buildLocalLink($asset);
}
@@ -358,6 +361,7 @@ class Assets
$data = [
'asset' => $asset,
'remote' => $remote ,
'priority' => intval($priority ?: 10),
'order' => count($this->js),
'pipeline' => (bool) $pipeline,
@@ -558,7 +562,7 @@ class Assets
foreach ($this->css_no_pipeline as $file) {
if ($group && $file['group'] == $group) {
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . $media . ' />' . "\n";
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
}
}
if (!$this->css_pipeline_before_excludes && $pipeline_result) {
@@ -568,7 +572,7 @@ class Assets
foreach ($this->css as $file) {
if ($group && $file['group'] == $group) {
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . $media . ' />' . "\n";
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
}
}
}
@@ -636,7 +640,7 @@ class Assets
}
foreach ($this->js_no_pipeline as $file) {
if ($group && $file['group'] == $group) {
$output .= '<script src="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
}
}
if (!$this->js_pipeline_before_excludes && $pipeline_result) {
@@ -645,7 +649,7 @@ class Assets
} else {
foreach ($this->js as $file) {
if ($group && $file['group'] == $group) {
$output .= '<script src="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
}
}
}
@@ -693,14 +697,14 @@ class Assets
// If pipeline exist return it
if (file_exists($this->assets_dir . $file)) {
return $relative_path . $this->timestamp;
return $relative_path . $this->getTimestamp();
}
// Remove any non-pipeline files
foreach ($this->css as $id => $asset) {
if ($asset['group'] == $group) {
if (!$asset['pipeline'] ||
($this->isRemoteLink($asset['asset']) && $this->css_pipeline_include_externals === false)) {
($asset['remote'] && $this->css_pipeline_include_externals === false)) {
$this->css_no_pipeline[$id] = $asset;
} else {
$temp_css[$id] = $asset;
@@ -740,7 +744,7 @@ class Assets
if (strlen(trim($buffer)) > 0) {
file_put_contents($this->assets_dir . $file, $buffer);
return $relative_path . $this->timestamp;
return $relative_path . $this->getTimestamp();
} else {
return false;
}
@@ -775,14 +779,14 @@ class Assets
// If pipeline exist return it
if (file_exists($this->assets_dir . $file)) {
return $relative_path . $this->timestamp;
return $relative_path . $this->getTimestamp();
}
// Remove any non-pipeline files
foreach ($this->js as $id => $asset) {
if ($asset['group'] == $group) {
if (!$asset['pipeline'] ||
($this->isRemoteLink($asset['asset']) && $this->js_pipeline_include_externals === false)) {
($asset['remote'] && $this->js_pipeline_include_externals === false)) {
$this->js_no_pipeline[] = $asset;
} else {
$temp_js[$id] = $asset;
@@ -812,7 +816,7 @@ class Assets
if (strlen(trim($buffer)) > 0) {
file_put_contents($this->assets_dir . $file, $buffer);
return $relative_path . $this->timestamp;
return $relative_path . $this->getTimestamp();
} else {
return false;
}
@@ -1342,6 +1346,21 @@ class Assets
$this->timestamp = '?' . $value;
}
public function getTimestamp($asset = null)
{
if (is_array($asset)) {
if ($asset['remote'] == false) {
if (Utils::contains($asset['asset'], '?')) {
return str_replace('?', '&', $this->timestamp);
} else {
return $this->timestamp;
}
}
} elseif (empty($asset)) {
return $this->timestamp;
}
}
/**
* @return string
*/

View File

@@ -217,4 +217,19 @@ class Debugger
return $this;
}
/**
* Dump exception into the Messages tab of the Debug Bar
*
* @param \Exception $e
* @return Debugger
*/
public function addException(\Exception $e)
{
if ($this->enabled()) {
$this->debugbar['exceptions']->addException($e);
}
return $this;
}
}

View File

@@ -436,22 +436,11 @@ abstract class Folder
return @unlink($folder);
}
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($folder, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
);
/** @var \DirectoryIterator $fileinfo */
foreach ($files as $fileinfo) {
if ($fileinfo->isDir()) {
if (false === @rmdir($fileinfo->getRealPath())) {
return false;
}
} else {
if (false === @unlink($fileinfo->getRealPath())) {
return false;
}
}
// Go through all items in filesystem and recursively remove everything.
$files = array_diff(scandir($folder), array('.', '..'));
foreach ($files as $file) {
$path = "{$folder}/{$file}";
(is_dir($path)) ? self::doDelete($path) : @unlink($path);
}
return $include_target ? @rmdir($folder) : true;

View File

@@ -217,7 +217,10 @@ class Grav extends Container
*/
public function mime($format)
{
// look for some standard types
switch ($format) {
case null:
return 'text/html';
case 'json':
return 'application/json';
case 'html':
@@ -230,6 +233,16 @@ class Grav extends Container
return 'application/xml';
}
// Try finding mime type from media
$media_types = $this['config']->get('media.types');
if (key_exists($format, $media_types)) {
$type = $media_types[$format];
if (isset($type['mime'])) {
return $type['mime'];
}
}
// Can't find the mime type, send as HTML
return 'text/html';
}

View File

@@ -212,6 +212,7 @@ trait ParsedownGravTrait
$alt = $excerpt['element']['attributes']['alt'] ?: '';
$title = $excerpt['element']['attributes']['title'] ?: '';
$class = isset($excerpt['element']['attributes']['class']) ? $excerpt['element']['attributes']['class'] : '';
$id = isset($excerpt['element']['attributes']['id']) ? $excerpt['element']['attributes']['id'] : '';
//get the url and parse it
$url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['src']));
@@ -264,7 +265,7 @@ trait ParsedownGravTrait
$medium->urlHash($url['fragment']);
}
$excerpt['element'] = $medium->parseDownElement($title, $alt, $class, true);
$excerpt['element'] = $medium->parseDownElement($title, $alt, $class, $id, true);
} else {
// not a current page media file, see if it needs converting to relative

View File

@@ -36,12 +36,13 @@ class Link implements RenderableInterface
* @param string $title
* @param string $alt
* @param string $class
* @param string $id
* @param boolean $reset
* @return array
*/
public function parsedownElement($title = null, $alt = null, $class = null, $reset = true)
public function parsedownElement($title = null, $alt = null, $class = null, $id = null, $reset = true)
{
$innerElement = $this->source->parsedownElement($title, $alt, $class, $reset);
$innerElement = $this->source->parsedownElement($title, $alt, $class, $id, $reset);
return [
'name' => 'a',

View File

@@ -199,10 +199,11 @@ class Medium extends Data implements RenderableInterface
* @param string $title
* @param string $alt
* @param string $class
* @param string $id
* @param boolean $reset
* @return array
*/
public function parsedownElement($title = null, $alt = null, $class = null, $reset = true)
public function parsedownElement($title = null, $alt = null, $class = null, $id = null, $reset = true)
{
$attributes = $this->attributes;
@@ -241,6 +242,14 @@ class Medium extends Data implements RenderableInterface
}
}
if (empty($attributes['id'])) {
if (!empty($id)) {
$attributes['id'] = $id;
} elseif (!empty($this->items['id'])) {
$attributes['id'] = $this->items['id'];
}
}
switch ($this->mode) {
case 'text':
$element = $this->textParsedownElement($attributes, false);
@@ -417,6 +426,7 @@ class Medium extends Data implements RenderableInterface
*/
public function id($id)
{
xdebug_break();
if (is_string($id)) {
$this->attributes['id'] = trim($id);
}

View File

@@ -21,13 +21,15 @@ trait ParsedownHtmlTrait
* Return HTML markup from the medium.
*
* @param string $title
* @param string $alt
* @param string $class
* @param string $id
* @param bool $reset
* @return string
*/
public function html($title = null, $alt = null, $class = null, $reset = true)
public function html($title = null, $alt = null, $class = null, $id = null, $reset = true)
{
$element = $this->parsedownElement($title, $alt, $class, $reset);
$element = $this->parsedownElement($title, $alt, $class, $id, $reset);
if (!$this->parsedown) {
$this->parsedown = new Parsedown(null, null);

View File

@@ -27,8 +27,9 @@ interface RenderableInterface
* @param string $title
* @param string $alt
* @param string $class
* @param string $id
* @param bool $reset
* @return string
*/
public function parsedownElement($title = null, $alt = null, $class = null, $reset = true);
public function parsedownElement($title = null, $alt = null, $class = null, $id = null, $reset = true);
}

View File

@@ -34,15 +34,16 @@ class ThumbnailImageMedium extends ImageMedium
/**
* Get an element (is array) that can be rendered by the Parsedown engine
*
* @param string $title
* @param string $alt
* @param string $class
* @param string $title
* @param string $alt
* @param string $class
* @param string $id
* @param boolean $reset
* @return array
*/
public function parsedownElement($title = null, $alt = null, $class = null, $reset = true)
public function parsedownElement($title = null, $alt = null, $class = null, $id = null, $reset = true)
{
return $this->bubble('parsedownElement', [$title, $alt, $class, $reset]);
return $this->bubble('parsedownElement', [$title, $alt, $class, $id, $reset]);
}
/**

View File

@@ -2337,6 +2337,9 @@ class Page
$results = $collection->addPage($this->parent());
break;
case 'siblings':
if (!$this->parent()) {
return new Collection();
}
$results = $this->parent()->children()->remove($this->path());
break;
case 'descendants':

View File

@@ -1065,8 +1065,13 @@ class Pages
} else {
// else just sort the list according to specified key
if (extension_loaded('intl')) {
$col = new \Collator(setlocale(LC_COLLATE, 0)); //`setlocale` with a 0 param returns the current locale set
$col->asort($list, $sort_flags);
$locale = setlocale(LC_COLLATE, 0); //`setlocale` with a 0 param returns the current locale set
$col = \Collator::create($locale);
if ($col) {
$col->asort($list, $sort_flags);
} else {
asort($list, $sort_flags);
}
} else {
asort($list, $sort_flags);
}

View File

@@ -33,6 +33,12 @@ class PageServiceProvider implements ServiceProviderInterface
// Redirection tests
if ($page) {
if ($c['config']->get('system.force_ssl')) {
if (!isset($_SERVER['HTTPS']) || $_SERVER["HTTPS"] != "on") {
$url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
$c->redirect($url);
}
}
$url = $page->route();

View File

@@ -67,7 +67,8 @@ class Session extends BaseSession
$httponly = $config->get('system.session.httponly', true);
$unique_identifier = GRAV_ROOT;
$this->setName($config->get('system.session.name', 'grav_site') . '-' . substr(md5($unique_identifier), 0, 7) . ($is_admin ? '-admin' : ''));
$inflector = new Inflector();
$this->setName($inflector->hyphenize($config->get('system.session.name', 'grav_site')) . '-' . substr(md5($unique_identifier), 0, 7) . ($is_admin ? '-admin' : ''));
$this->start();
setcookie(session_name(), session_id(), time() + $session_timeout, $session_path, $domain, $secure, $httponly);
}

View File

@@ -729,11 +729,15 @@ class TwigExtension extends \Twig_Extension
}
/**
* Authorize an action. Returns true if the user is logged in and has the right to execute $action.
* Authorize an action. Returns true if the user is logged in and
* has the right to execute $action.
*
* @param string $action
*
* @return bool
* @param string|array $action An action or a list of actions. Each
* entry can be a string like 'group.action'
* or without dot notation an associative
* array.
* @return bool Returns TRUE if the user is authorized to
* perform the action, FALSE otherwise.
*/
public function authorize($action)
{
@@ -741,11 +745,14 @@ class TwigExtension extends \Twig_Extension
return false;
}
$action = (array)$action;
foreach ($action as $a) {
if ($this->grav['user']->authorize($a)) {
return true;
$action = (array) $action;
foreach ($action as $key => $perms) {
$prefix = is_int($key) ? '' : $key . '.';
$perms = $prefix ? (array) $perms : [$perms => true];
foreach ($perms as $action => $authenticated) {
if ($this->grav['user']->authorize($prefix . $action)) {
return $authenticated;
}
}
}

View File

@@ -37,6 +37,7 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getCss();
$this->assertSame([
'asset' => '/test.css',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -51,6 +52,7 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getCss();
$this->assertSame([
'asset' => '/test.css',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -67,6 +69,24 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getCss();
$this->assertSame([
'asset' => '/test.css',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
'group' => 'head',
'modified' => false
], reset($array));
//test addCss(). Testing with remote URL
$this->assets->reset();
$this->assets->addCSS('http://www.somesite.com/test.css');
$css = $this->assets->css();
$this->assertSame('<link href="http://www.somesite.com/test.css" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
$array = $this->assets->getCss();
$this->assertSame([
'asset' => 'http://www.somesite.com/test.css',
'remote' => true,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -89,6 +109,7 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getJs();
$this->assertSame([
'asset' => '/test.js',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -108,6 +129,7 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getCss();
$this->assertSame([
'asset' => '/test.css',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -126,6 +148,7 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getJs();
$this->assertSame([
'asset' => '/test.js',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -143,6 +166,7 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getJs();
$this->assertSame([
'asset' => '/test.js',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -159,6 +183,7 @@ class AssetsTest extends \Codeception\TestCase\Test
$array = $this->assets->getJs();
$this->assertSame([
'asset' => '/test.js',
'remote' => false,
'priority' => 10,
'order' => 0,
'pipeline' => true,
@@ -298,6 +323,19 @@ class AssetsTest extends \Codeception\TestCase\Test
$this->assertContains('type="text/css" rel="stylesheet" />', $css);
}
public function testPipelineWithTimestamp()
{
$this->assets->reset();
$this->assets->setTimestamp('foo');
//Add a core Grav CSS file, which is found. Pipeline will now return a file
$this->assets->add('/system/assets/debugger.css', null, true);
$css = $this->assets->css();
$this->assertContains('<link href=', $css);
$this->assertContains('type="text/css" rel="stylesheet" />', $css);
$this->assertContains($this->assets->getTimestamp(), $css);
}
public function testAddAsyncJs()
{
$this->assets->reset();
@@ -314,6 +352,65 @@ class AssetsTest extends \Codeception\TestCase\Test
$this->assertSame('<script src="/system/assets/jquery/jquery-2.x.min.js" type="text/javascript" defer></script>' . PHP_EOL, $js);
}
public function testTimestamps()
{
// local CSS nothing extra
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addCSS('test.css');
$css = $this->assets->css();
$this->assertSame('<link href="/test.css?foo" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
// local CSS already with param
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addCSS('test.css?bar');
$css = $this->assets->css();
$this->assertSame('<link href="/test.css?bar&foo" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
// external CSS already
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addCSS('http://somesite.com/test.css');
$css = $this->assets->css();
$this->assertSame('<link href="http://somesite.com/test.css" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
// external CSS already with param
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addCSS('http://somesite.com/test.css?bar');
$css = $this->assets->css();
$this->assertSame('<link href="http://somesite.com/test.css?bar" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
// local JS nothing extra
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addJs('test.js');
$css = $this->assets->js();
$this->assertSame('<script src="/test.js?foo" type="text/javascript" ></script>' . PHP_EOL, $css);
// local JS already with param
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addJs('test.js?bar');
$css = $this->assets->js();
$this->assertSame('<script src="/test.js?bar&foo" type="text/javascript" ></script>' . PHP_EOL, $css);
// external JS already
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addJs('http://somesite.com/test.js');
$css = $this->assets->js();
$this->assertSame('<script src="http://somesite.com/test.js" type="text/javascript" ></script>' . PHP_EOL, $css);
// external JS already with param
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addJs('http://somesite.com/test.js?bar');
$css = $this->assets->js();
$this->assertSame('<script src="http://somesite.com/test.js?bar" type="text/javascript" ></script>' . PHP_EOL, $css);
}
public function testAddInlineCss()
{
$this->assets->reset();

View File

@@ -148,6 +148,27 @@ class ParsedownTest extends \Codeception\TestCase\Test
$this->parsedown->text('![](/home-missing-image.jpg)'));
}
public function testImagesAttributes()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><img title="My Title" src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg "My Title")'));
$this->assertSame('<p><img class="foo" src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg?classes=foo)'));
$this->assertSame('<p><img class="foo bar" src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg?classes=foo,bar)'));
$this->assertSame('<p><img id="foo" src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg?id=foo)'));
$this->assertSame('<p><img alt="Alt Text" id="foo" src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![Alt Text](sample-image.jpg?id=foo)'));
$this->assertSame('<p><img alt="Alt Text" class="bar" id="foo" src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![Alt Text](sample-image.jpg?class=bar&id=foo)'));
$this->assertSame('<p><img title="My Title" alt="Alt Text" class="bar" id="foo" src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![Alt Text](sample-image.jpg?class=bar&id=foo "My Title")'));
}
public function testRootImages()
{
$this->uri->initializeWithURL('http://testing.dev/')->init();