diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bd694330..02fb45e09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +# v1.6.9 +## 05/09/2019 + +1. [](#new) + * Added `Route::withoutParams()` methods + * Added `Pages::setCheckMethod()` method to override page configuration in Admin Plugin + * Added `Cache::clearCache('invalidate')` parameter for just invalidating the cache without deleting any cached files + * Made `UserCollectionInderface` to extend `Countable` to get the count of existing users +1. [](#improved) + * Flex admin: added default search options for flex objects + * Flex collection and object now fall back to the default template if template file doesn't exist + * Updated Vendor libraries including Twig 1.40.1 + * Updated language files from `https://crowdin.com/project/grav-core` +1. [](#bugfix) + * Fixed `$grav['route']` from being modified when the route instance gets modified + * Fixed Assets options array mixed with standalone priority [#2477](https://github.com/getgrav/grav/issues/2477) + * Fix for `avatar_url` provided by 3rd party providers + * Fixed non standard `lang` code lengths in `Utils` and `Session` detection + * Fixed saving a new object in Flex `SimpleStorage` + * Fixed exception in `Flex::getDirectories()` if the first parameter is set + * Output correct "Last Updated" in `bin/gpm info` command + * Checkbox getting interpreted as string, so created new `Validation::filterCheckbox()` + * Fixed backwards compatibility to `select` field with `selectize.create` set to true [git-sync#141](https://github.com/trilbymedia/grav-plugin-git-sync/issues/141) + * Fixed `YamlFormatter::decode()` to always return array [#2494](https://github.com/getgrav/grav/pull/2494) + * Fixed empty `$grav['request']->getAttribute('route')->getExtension()` + # v1.6.8 ## 04/23/2019 @@ -25,18 +51,18 @@ ## 04/17/2019 1. [](#new) - * `FormInterface` now implements `RenderInterface` - * Added new `FormInterface::getTask()` method which reads the task from `form.task` in the blueprint + * `FormInterface` now implements `RenderInterface` + * Added new `FormInterface::getTask()` method which reads the task from `form.task` in the blueprint 1. [](#improved) * Updated vendor libraries to latest 1. [](#bugfix) * Rollback `redirect_default_route` logic as it has issues with multi-lang [#2459](https://github.com/getgrav/grav/issues/2459) - * Fix potential issue with `|contains` Twig filter on PHP 7.3 + * Fix potential issue with `|contains` Twig filter on PHP 7.3 * Fixed bug in text field filtering: return empty string if value isn't a string or number [#2460](https://github.com/getgrav/grav/issues/2460) * Force Asset `priority` to be an integer and not throw error if invalid string passed [#2461](https://github.com/getgrav/grav/issues/2461) * Fixed bug in text field filtering: return empty string if value isn't a string or number * Fixed `FlexForm` missing getter methods for defining form variables - + # v1.6.5 ## 04/15/2019 @@ -97,7 +123,7 @@ * Added `Grav\Framework\Object\ObjectIndex` class * Added `Grav\Framework\Flex` classes * Added support for hiding form fields in blueprints by using dynamic property like `security@: admin.foobar`, `scope@: object` or `scope-ignore@: object` to any field - * New experimental **FlexObjects** powered `Users` for increased performance and capability (**disabled** by default) + * New experimental **FlexObjects** powered `Users` for increased performance and capability (**disabled** by default) * Added PSR-7 and PSR-15 classes * Added `Grav\Framework\DI\Container` class * Added `Grav\Framework\RequestHandler\RequestHandler` class @@ -173,7 +199,7 @@ * Added ability to reset `Page::metadata` to allow rebuilding from automatically generated values * Added back missing `page.types` field in system content configuration [admin#1612](https://github.com/getgrav/grav-plugin-admin/issues/1612) * Console commands: add method for invalidating cache - * Updated languages + * Updated languages * Improved `$page->forms()` call, added `$page->addForms()` * Updated languages from crowdin * Fixed `ImageMedium` constructor warning when file does not exist @@ -194,7 +220,7 @@ * Added apcu autoloader optimization * Additional helper methods in `Language`, `Languages`, and `LanguageCodes` classes * Call `onFatalException` event also on internal PHP errors - * Built-in PHP Webserver: log requests before handling them + * Built-in PHP Webserver: log requests before handling them * Added support for syslog and syslog facility logging (default: 'file') * Improved usability of `System` configuration blueprint with side-tabs 1. [](#bugfix) @@ -219,7 +245,7 @@ * Fixed failed login if user attempts to log in with upper case non-english letters * Removed extra authenticated/authorized fields when saving existing user from a form * Fixed `Grav\Framework\Route::__toString()` returning relative URL, not relative route - * Fixed handling of `append_url_extension` inside of `Page::templateFormat()` [#2264](https://github.com/getgrav/grav/issues/2264) + * Fixed handling of `append_url_extension` inside of `Page::templateFormat()` [#2264](https://github.com/getgrav/grav/issues/2264) * Fixed a broken language string [#2261](https://github.com/getgrav/grav/issues/2261) * Fixed clearing cache having no effect on Doctrine cache * Fixed `Medium::relativePath()` for streams @@ -272,7 +298,7 @@ * Updated vendor libraries 1. [](#bugfix) * Support spaces with filenames in responsive images [#2300](https://github.com/getgrav/grav/pull/2300) - + # v1.5.6 ## 12/14/2018 diff --git a/composer.json b/composer.json index 951814625..df4501f7e 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "kodus/psr7-server": "*", "nyholm/psr7": "^1.0", - "twig/twig": "~1.35", + "twig/twig": "~1.40", "erusev/parsedown": "1.6.4", "erusev/parsedown-extra": "~0.7", "symfony/yaml": "~4.2", @@ -89,6 +89,8 @@ "exclude": ["VERSION"] }, "scripts": { + "api-16": "vendor/bin/phpdoc-md generate system/src > user/pages/14.api/default.16.md", + "api-15": "vendor/bin/phpdoc-md generate system/src > user/pages/14.api/default.md", "post-create-project-cmd": "bin/grav install", "phpstan": "vendor/bin/phpstan analyse -l 2 -c ./tests/phpstan/phpstan.neon system/src --memory-limit=256M", "phpstan-framework": "vendor/bin/phpstan analyse -l 5 -c ./tests/phpstan/phpstan.neon system/src/Grav/Framework --memory-limit=256M", diff --git a/composer.lock b/composer.lock index 2e2f47653..5c247be35 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a65d66d9ce6844a3743c992e74c1c55d", + "content-hash": "f9429e7cd2e75a232f968b01a1024983", "packages": [ { "name": "antoligy/dom-string-iterators", @@ -1333,16 +1333,16 @@ }, { "name": "psr/http-factory", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "378bfe27931ecc54ff824a20d6f6bfc303bbd04c" + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/378bfe27931ecc54ff824a20d6f6bfc303bbd04c", - "reference": "378bfe27931ecc54ff824a20d6f6bfc303bbd04c", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", "shasum": "" }, "require": { @@ -1381,7 +1381,7 @@ "request", "response" ], - "time": "2018-07-30T21:54:04+00:00" + "time": "2019-04-30T12:38:16+00:00" }, { "name": "psr/http-message", @@ -1774,7 +1774,7 @@ }, { "name": "symfony/console", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", @@ -1914,7 +1914,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -2267,7 +2267,7 @@ }, { "name": "symfony/process", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -2316,16 +2316,16 @@ }, { "name": "symfony/var-dumper", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "e760a38e12b15032325e64be63f7ffc1817af617" + "reference": "3c4084cb1537c0e2ad41aad622bbf55a44a5c9ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e760a38e12b15032325e64be63f7ffc1817af617", - "reference": "e760a38e12b15032325e64be63f7ffc1817af617", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3c4084cb1537c0e2ad41aad622bbf55a44a5c9ce", + "reference": "3c4084cb1537c0e2ad41aad622bbf55a44a5c9ce", "shasum": "" }, "require": { @@ -2388,11 +2388,11 @@ "debug", "dump" ], - "time": "2019-04-17T14:57:01+00:00" + "time": "2019-05-01T12:55:36+00:00" }, { "name": "symfony/yaml", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", @@ -2451,16 +2451,16 @@ }, { "name": "twig/twig", - "version": "v1.39.1", + "version": "v1.40.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "23e7b6f0cfa1d7ba3de69f30d8e05cf957412fec" + "reference": "35889516bbd6bbe46a600c2c33b03515df4a076e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/23e7b6f0cfa1d7ba3de69f30d8e05cf957412fec", - "reference": "23e7b6f0cfa1d7ba3de69f30d8e05cf957412fec", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/35889516bbd6bbe46a600c2c33b03515df4a076e", + "reference": "35889516bbd6bbe46a600c2c33b03515df4a076e", "shasum": "" }, "require": { @@ -2475,7 +2475,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.39-dev" + "dev-master": "1.40-dev" } }, "autoload": { @@ -2513,7 +2513,7 @@ "keywords": [ "templating" ], - "time": "2019-04-16T17:12:57+00:00" + "time": "2019-04-29T14:12:28+00:00" }, { "name": "willdurand/negotiation", @@ -2630,16 +2630,16 @@ }, { "name": "codeception/codeception", - "version": "2.5.5", + "version": "2.5.6", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "547a64cb31edcf1902b296c511f5ca74101bcb4c" + "reference": "b83a9338296e706fab2ceb49de8a352fbca3dc98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/547a64cb31edcf1902b296c511f5ca74101bcb4c", - "reference": "547a64cb31edcf1902b296c511f5ca74101bcb4c", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/b83a9338296e706fab2ceb49de8a352fbca3dc98", + "reference": "b83a9338296e706fab2ceb49de8a352fbca3dc98", "shasum": "" }, "require": { @@ -2718,7 +2718,7 @@ "functional testing", "unit testing" ], - "time": "2019-03-23T17:57:45+00:00" + "time": "2019-04-24T11:28:19+00:00" }, { "name": "codeception/phpunit-wrapper", @@ -3416,7 +3416,7 @@ "homepage": "https://nette.org/contributors" } ], - "description": "🔍 Nette Finder: find files and directories with an intuitive API.", + "description": "? Nette Finder: find files and directories with an intuitive API.", "homepage": "https://nette.org", "keywords": [ "filesystem", @@ -3476,7 +3476,7 @@ "homepage": "https://nette.org/contributors" } ], - "description": "🍸 Nette NEON: encodes and decodes NEON file format.", + "description": "? Nette NEON: encodes and decodes NEON file format.", "homepage": "http://ne-on.org", "keywords": [ "export", @@ -4000,16 +4000,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", + "version": "4.3.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", "shasum": "" }, "require": { @@ -4047,7 +4047,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" + "time": "2019-04-30T17:48:53+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -4161,28 +4161,29 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "0.3.1", + "version": "0.3.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74" + "reference": "472d3161d289f652713a5e353532fa4592663a57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/2cc49f47c69b023eaf05b48e6529389893b13d74", - "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/472d3161d289f652713a5e353532fa4592663a57", + "reference": "472d3161d289f652713a5e353532fa4592663a57", "shasum": "" }, "require": { "php": "~7.1" }, "require-dev": { - "consistence/coding-standard": "^2.0.0", + "consistence/coding-standard": "^3.5", "jakub-onderka/php-parallel-lint": "^0.9.2", "phing/phing": "^2.16.0", "phpstan/phpstan": "^0.10", "phpunit/phpunit": "^6.3", - "slevomat/coding-standard": "^3.3.0", + "slevomat/coding-standard": "^4.7.2", + "squizlabs/php_codesniffer": "^3.3.2", "symfony/process": "^3.4 || ^4.0" }, "type": "library", @@ -4203,7 +4204,7 @@ "MIT" ], "description": "PHPDoc parser with support for nullable, intersection and generic types", - "time": "2019-01-14T12:26:23+00:00" + "time": "2019-04-23T20:26:19+00:00" }, { "name": "phpstan/phpstan", @@ -4578,16 +4579,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.5.8", + "version": "7.5.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c29c0525cf4572c11efe1db49a8b8aee9dfac58a" + "reference": "134669cf0eeac3f79bc7f0c793efbc158bffc160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c29c0525cf4572c11efe1db49a8b8aee9dfac58a", - "reference": "c29c0525cf4572c11efe1db49a8b8aee9dfac58a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/134669cf0eeac3f79bc7f0c793efbc158bffc160", + "reference": "134669cf0eeac3f79bc7f0c793efbc158bffc160", "shasum": "" }, "require": { @@ -4658,7 +4659,7 @@ "testing", "xunit" ], - "time": "2019-03-26T13:23:54+00:00" + "time": "2019-04-19T15:50:46+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -4827,16 +4828,16 @@ }, { "name": "sebastian/environment", - "version": "4.1.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6fda8ce1974b62b14935adc02a9ed38252eca656" + "reference": "3095910f0f0fb155ac4021fc51a4a7a39ac04e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6fda8ce1974b62b14935adc02a9ed38252eca656", - "reference": "6fda8ce1974b62b14935adc02a9ed38252eca656", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/3095910f0f0fb155ac4021fc51a4a7a39ac04e8a", + "reference": "3095910f0f0fb155ac4021fc51a4a7a39ac04e8a", "shasum": "" }, "require": { @@ -4851,7 +4852,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -4876,7 +4877,7 @@ "environment", "hhvm" ], - "time": "2019-02-01T05:27:49+00:00" + "time": "2019-04-25T07:55:20+00:00" }, { "name": "sebastian/exporter", @@ -5228,7 +5229,7 @@ }, { "name": "symfony/browser-kit", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", @@ -5285,7 +5286,7 @@ }, { "name": "symfony/css-selector", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -5338,7 +5339,7 @@ }, { "name": "symfony/dom-crawler", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", @@ -5395,7 +5396,7 @@ }, { "name": "symfony/finder", - "version": "v4.2.7", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", diff --git a/system/defines.php b/system/defines.php index 3af6edef8..7a4df5cce 100644 --- a/system/defines.php +++ b/system/defines.php @@ -8,7 +8,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '1.6.8'); +define('GRAV_VERSION', '1.6.9'); define('GRAV_TESTING', false); define('DS', '/'); diff --git a/system/languages/es.yaml b/system/languages/es.yaml index ce990eea5..7bacfeb98 100644 --- a/system/languages/es.yaml +++ b/system/languages/es.yaml @@ -23,7 +23,7 @@ GRAV: BAD_DATE: Fecha errónea AGO: antes FROM_NOW: desde ahora - JUST_NOW: justo ahora + JUST_NOW: hace un momento SECOND: segundo MINUTE: minuto HOUR: hora diff --git a/system/languages/et.yaml b/system/languages/et.yaml index fd794ada0..619aa1a73 100644 --- a/system/languages/et.yaml +++ b/system/languages/et.yaml @@ -1,11 +1,30 @@ --- GRAV: FRONTMATTER_ERROR_PAGE: "---\npealkiri: %1$s\n---\n\n# Viga: vigane Frontmatter'i\n\nasukoht: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```" + INFLECTOR_UNCOUNTABLE: + - 'equipment' + - 'informatsioon' + - 'rice' + - 'money' + - 'species' + - 'series' + - 'kala' + - 'lammas' + INFLECTOR_IRREGULAR: + 'person': 'inimesed' + 'man': 'mees' + 'child': 'lapsed' + INFLECTOR_ORDINALS: + 'default': '.' + 'first': '.' + 'second': '.' + 'third': '.' NICETIME: NO_DATE_PROVIDED: Kuupäev määramata BAD_DATE: Vigane kuupäev AGO: tagasi FROM_NOW: praegusest + JUST_NOW: just nüüd SECOND: sekund MINUTE: minut HOUR: tundi @@ -60,3 +79,7 @@ GRAV: - 'reede' - 'laupäev' - 'pühapäev' + CRON: + EVERY: iga + EVERY_MONTH: iga kuu + TEXT_PERIOD: Iga diff --git a/system/languages/fr.yaml b/system/languages/fr.yaml index fe2cbb768..9284f7e6d 100644 --- a/system/languages/fr.yaml +++ b/system/languages/fr.yaml @@ -14,6 +14,8 @@ GRAV: '/sis$/i': 'ses' '/([ti])um$/i': '\1a' '/(buffal|tomat)o$/i': '\1es' + '/(bu)s$/i': 'Bus' + '/(alias|status)/i': 'alias|status' '/(ax|test)is$/i': '\1s' '/s$/i': 's' '/$/': 's' diff --git a/system/languages/is.yaml b/system/languages/is.yaml index 55384faf7..6f9761ca1 100644 --- a/system/languages/is.yaml +++ b/system/languages/is.yaml @@ -11,6 +11,8 @@ GRAV: - 'fish' - 'sheep' NICETIME: + NO_DATE_PROVIDED: Engin dagsetning gefin + BAD_DATE: Röng dagsetning AGO: síðan JUST_NOW: í þessu SECOND: sekúndu @@ -45,6 +47,7 @@ GRAV: DEC_PLURAL: árat FORM: VALIDATION_FAIL: Sannvottun mistókst: + INVALID_INPUT: Ógilt inntak í MISSING_REQUIRED_FIELD: 'Vantar nauðsynlegan reit:' MONTHS_OF_THE_YEAR: - 'janúar' @@ -67,3 +70,11 @@ GRAV: - 'Föstudagur' - 'Laugardagur' - 'Sunnudagur' + CRON: + TEXT_TIME: ' á :' + TEXT_DOW: ' á ' + TEXT_MONTH: ' af ' + TEXT_DOM: ' á ' + ERROR1: Merkið %s er ekki stutt! + ERROR3: Það ætti að setja jquery_element inn í stillingar jqCron + ERROR4: Óþekkt segð diff --git a/system/languages/pt.yaml b/system/languages/pt.yaml index bddd85620..590b5e581 100644 --- a/system/languages/pt.yaml +++ b/system/languages/pt.yaml @@ -35,3 +35,12 @@ GRAV: - 'Outubro' - 'Novembro' - 'Dezembro' + INFLECTOR_UNCOUNTABLE: + - 'equipment' + - 'information' + - 'arroz' + - 'money' + - 'species' + - 'series' + - 'fish' + - 'sheep' diff --git a/system/languages/sk.yaml b/system/languages/sk.yaml index 3defc36ed..89a7f563e 100644 --- a/system/languages/sk.yaml +++ b/system/languages/sk.yaml @@ -1,10 +1,75 @@ --- GRAV: + FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Chyba: Chybný frontmatter\n\nPath: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```" + INFLECTOR_PLURALS: + '/(quiz)$/i': '\1zes' + '/^(ox)$/i': '\1en' + '/([m|l])ouse$/i': '\1ice' + '/(matr|vert|ind)ix|ex$/i': '\1ices' + '/(x|ch|ss|sh)$/i': '\1es' + '/([^aeiouy]|qu)ies$/i': '\1y' + '/([^aeiouy]|qu)y$/i': '\1ies' + '/(hive)$/i': '\1s' + '/(?:([^f])fe|([lr])f)$/i': '\1\2ves' + '/sis$/i': 'ses' + '/([ti])um$/i': '\1a' + '/(buffal|tomat)o$/i': '\1oes' + '/(bu)s$/i': '\1ses' + '/(alias|status)/i': '\1es' + '/(octop|vir)us$/i': '\1i' + '/(ax|test)is$/i': '\1es' + '/s$/i': 's' + '/$/': 's' + INFLECTOR_SINGULAR: + '/(quiz)zes$/i': '\1' + '/(matr)ices$/i': '\1ix' + '/(vert|ind)ices$/i': '\1ex' + '/^(ox)en/i': '\1' + '/(alias|status)es$/i': '\1' + '/([octop|vir])i$/i': '\1us' + '/(cris|ax|test)es$/i': '\1is' + '/(shoe)s$/i': '\1' + '/(o)es$/i': '\1' + '/(bus)es$/i': '\1' + '/([m|l])ice$/i': '\1ouse' + '/(x|ch|ss|sh)es$/i': '\1' + '/(m)ovies$/i': '\1ovie' + '/(s)eries$/i': '\1eries' + '/([^aeiouy]|qu)ies$/i': '\1y' + '/([lr])ves$/i': '\1f' + '/(tive)s$/i': '\1' + '/(hive)s$/i': '\1' + '/([^f])ves$/i': '\1fe' + '/(^analy)ses$/i': '\1sis' + '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2sis' + '/([ti])a$/i': '\1um' + '/(n)ews$/i': '\1ews' + INFLECTOR_UNCOUNTABLE: + - 'vybavenie' + - 'informácie' + - 'ryža' + - 'peniaze' + - 'druhy' + - 'séria' + - 'ryba' + - 'ovce' + INFLECTOR_IRREGULAR: + 'person': 'ľudia' + 'man': 'muži' + 'child': 'deti' + 'sex': 'pohlavia' + 'move': 'pohyby' + INFLECTOR_ORDINALS: + 'default': '.' + 'first': '.' + 'second': '.' + 'third': '.' NICETIME: NO_DATE_PROVIDED: Neposkytnutý žiaden dátum BAD_DATE: Nesprávny dátum AGO: pred FROM_NOW: odteraz + JUST_NOW: práve teraz SECOND: sekunda MINUTE: minúta HOUR: hodina @@ -14,10 +79,12 @@ GRAV: YEAR: rok DECADE: desaťročie SEC: sek + MIN: min HR: hod WK: t MO: m YR: r + DEC: dec SECOND_PLURAL: sekúnd MINUTE_PLURAL: minút HOUR_PLURAL: hodín @@ -58,3 +125,20 @@ GRAV: - 'Piatok' - 'Sobota' - 'Nedeľa' + CRON: + EVERY: každý + EVERY_HOUR: každú hodinu + EVERY_MINUTE: každú minútu + EVERY_DAY_OF_WEEK: každý deň v týždni + EVERY_DAY_OF_MONTH: každý deň v mesiaci + EVERY_MONTH: každý mesiac + TEXT_PERIOD: Každý + TEXT_MINS: ' at minute(s) past the hour' + TEXT_TIME: ' at :' + TEXT_DOW: ' on ' + TEXT_MONTH: ' of ' + TEXT_DOM: ' on ' + ERROR1: Tag %s nieje podporovaný! + ERROR2: Chybný počet položiek + ERROR3: jquery_element musí byť nastavený v nastaveniach pre jqCron + ERROR4: Neznámy výraz diff --git a/system/languages/sv.yaml b/system/languages/sv.yaml index e386c8c13..16afa1650 100644 --- a/system/languages/sv.yaml +++ b/system/languages/sv.yaml @@ -1,6 +1,17 @@ --- GRAV: FRONTMATTER_ERROR_PAGE: "--- titel: %1$s --- # Fel: Ogiltig Frontmatter-sökväg: `%2$s` **%3$s** ``` %4$s ```" + INFLECTOR_UNCOUNTABLE: + - 'utrustning' + - 'information' + - 'ris' + - 'pengar' + - 'arter' + - 'serier' + - 'fisk' + - 'får' + INFLECTOR_IRREGULAR: + 'person': 'personer' NICETIME: NO_DATE_PROVIDED: Inget datum har angivits BAD_DATE: Ogiltigt datum diff --git a/system/languages/zh-tw.yaml b/system/languages/zh-tw.yaml index 6ecfcc375..6cb39c9ad 100644 --- a/system/languages/zh-tw.yaml +++ b/system/languages/zh-tw.yaml @@ -1,24 +1,44 @@ --- GRAV: + FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# 錯誤: 不正確的 Frontmatter\n\n路徑: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```" NICETIME: + NO_DATE_PROVIDED: 沒有提供日期 + BAD_DATE: 錯誤日期 + AGO: 之前 + FROM_NOW: 之後 + JUST_NOW: 剛剛 SECOND: 秒 MINUTE: 分 HOUR: 小時 + DAY: 天 + WEEK: 週 + MONTH: 月 + YEAR: 年 + DECADE: 十年 + SEC: 秒 + MIN: 分 + HR: 小時 + WK: 週 + MO: 月 + YR: 年 + DEC: 十年 SECOND_PLURAL: 秒 MINUTE_PLURAL: 分 - HOUR_PLURAL: 時 - DAY_PLURAL: 日 - WEEK_PLURAL: 周 + HOUR_PLURAL: 小時 + DAY_PLURAL: 天 + WEEK_PLURAL: 週 MONTH_PLURAL: 月 YEAR_PLURAL: 年 DECADE_PLURAL: 十年 SEC_PLURAL: 秒 MIN_PLURAL: 分 HR_PLURAL: 時 - WK_PLURAL: 周 + WK_PLURAL: 週 MO_PLURAL: 月 YR_PLURAL: 年 DEC_PLURAL: 十年 + FORM: + MISSING_REQUIRED_FIELD: 遺漏必填欄位: MONTHS_OF_THE_YEAR: - '一月' - '二月' diff --git a/system/languages/zh.yaml b/system/languages/zh.yaml index 9ae1cdb86..4912aa9ed 100644 --- a/system/languages/zh.yaml +++ b/system/languages/zh.yaml @@ -1,57 +1,122 @@ --- GRAV: - FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# 錯誤: 不正確的 Frontmatter\n\n路徑: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```" + FRONTMATTER_ERROR_PAGE: "---\n标题: %1$s\n---\n\n# 错误:无效参数\n\n位置: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```" + INFLECTOR_PLURALS: + '/(quiz)$/i': '\1zes' + '/^(ox)$/i': '\1en' + '/([m|l])ouse$/i': '\1ice' + '/(matr|vert|ind)ix|ex$/i': '\1ices' + '/(x|ch|ss|sh)$/i': '\1es' + '/([^aeiouy]|qu)ies$/i': '\1y' + '/([^aeiouy]|qu)y$/i': '\1ies' + '/(hive)$/i': '\1s' + '/(?:([^f])fe|([lr])f)$/i': '\1\2ves' + '/sis$/i': 'ses' + '/([ti])um$/i': '\1a' + '/(buffal|tomat)o$/i': '\1oes' + '/(bu)s$/i': '\1ses' + '/(alias|status)/i': '\1es' + '/(octop|vir)us$/i': '\1i' + '/(ax|test)is$/i': '\1es' + '/s$/i': 's' + '/$/': 's' + INFLECTOR_SINGULAR: + '/(quiz)zes$/i': '\1' + '/(matr)ices$/i': '\1ix' + '/(vert|ind)ices$/i': '\1ex' + '/^(ox)en/i': '\1' + '/(alias|status)es$/i': '\1' + '/([octop|vir])i$/i': '\1us' + '/(cris|ax|test)es$/i': '\1is' + '/(shoe)s$/i': '\1' + '/(o)es$/i': '\1' + '/(bus)es$/i': '\1' + '/([m|l])ice$/i': '\1ouse' + '/(x|ch|ss|sh)es$/i': '\1' + '/(m)ovies$/i': '\1ovie' + '/(s)eries$/i': '\1eries' + '/([^aeiouy]|qu)ies$/i': '\1y' + '/([lr])ves$/i': '\1f' + '/(tive)s$/i': '\1' + '/(hive)s$/i': '\1' + '/([^f])ves$/i': '\1fe' + '/(^analy)ses$/i': '\1sis' + '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2sis' + '/([ti])a$/i': '\1um' + '/(n)ews$/i': '\1ews' + INFLECTOR_UNCOUNTABLE: + - '装备' + - '信息' + - '大米' + - '钱' + - '物种' + - '系列' + - '鱼' + - '羊' + INFLECTOR_IRREGULAR: + 'person': '人员' + 'man': '男人' + 'child': '儿童' + 'sex': '性别' + 'move': '移动' + INFLECTOR_ORDINALS: + 'default': 'th' + 'first': 'st' + 'second': 'md' + 'third': 'rd' NICETIME: - NO_DATE_PROVIDED: 沒有提供日期 - BAD_DATE: 錯誤日期 - AGO: 之前 - FROM_NOW: 之後 - JUST_NOW: 剛剛 + NO_DATE_PROVIDED: 无日期信息 + BAD_DATE: 无效日期 + AGO: 前 + FROM_NOW: 距今 + JUST_NOW: 刚刚 SECOND: 秒 - MINUTE: 分 - HOUR: 小時 + MINUTE: 分钟 + HOUR: 小时 DAY: 天 - WEEK: 週 + WEEK: 周 MONTH: 月 YEAR: 年 DECADE: 十年 SEC: 秒 - MIN: 分 - HR: 小時 - WK: 週 + MIN: 分钟 + HR: 小时 + WK: 周 MO: 月 YR: 年 - DEC: 十年 + DEC: 年代 SECOND_PLURAL: 秒 MINUTE_PLURAL: 分 - HOUR_PLURAL: 小時 + HOUR_PLURAL: 小时 DAY_PLURAL: 天 - WEEK_PLURAL: 週 + WEEK_PLURAL: 周 MONTH_PLURAL: 月 YEAR_PLURAL: 年 DECADE_PLURAL: 十年 SEC_PLURAL: 秒 MIN_PLURAL: 分 - HR_PLURAL: 時 - WK_PLURAL: 週 + HR_PLURAL: 时 + WK_PLURAL: 周 MO_PLURAL: 月 YR_PLURAL: 年 - DEC_PLURAL: 十年 + DEC_PLURAL: 年代 FORM: - MISSING_REQUIRED_FIELD: 遺漏必填欄位: + VALIDATION_FAIL: 验证失败: + INVALID_INPUT: 无效输入 + MISSING_REQUIRED_FIELD: 必填字段缺失: MONTHS_OF_THE_YEAR: - - '一月' - - '二月' - - '三月' - - '四月' - - '五月' - - '六月' - - '七月' - - '八月' - - '九月' - - '十月' - - '十一月' - - '十二月' + - '1月' + - '2月' + - '3月' + - '4月' + - '5月' + - '6月' + - '7月' + - '8月' + - '9月' + - '10月' + - '11月' + - '12月' DAYS_OF_THE_WEEK: - '星期一' - '星期二' @@ -60,4 +125,20 @@ GRAV: - '星期五' - '星期六' - '星期日' - + CRON: + EVERY: 每隔 + EVERY_HOUR: 每小时 + EVERY_MINUTE: 每分钟 + EVERY_DAY_OF_WEEK: 一周中的每一天 + EVERY_DAY_OF_MONTH: 月份中的每一天 + EVERY_MONTH: 每月 + TEXT_PERIOD: 所有 + TEXT_MINS: ' 在 小时过后的分钟' + TEXT_TIME: ' 在 :' + TEXT_DOW: ' on ' + TEXT_MONTH: ' of ' + TEXT_DOM: ' on ' + ERROR1: 不支持分享类型 %s + ERROR2: 无效数字 + ERROR3: 请在 jqCron 设置中设定 jquery_element + ERROR4: 无法识别表达式 diff --git a/system/src/Grav/Common/Assets/Traits/LegacyAssetsTrait.php b/system/src/Grav/Common/Assets/Traits/LegacyAssetsTrait.php index ccf9da298..229c2abae 100644 --- a/system/src/Grav/Common/Assets/Traits/LegacyAssetsTrait.php +++ b/system/src/Grav/Common/Assets/Traits/LegacyAssetsTrait.php @@ -24,19 +24,21 @@ trait LegacyAssetsTrait // First argument is always the asset array_shift($args); - if (\count($args) === 0) { + if (count($args) === 0) { return []; } - if (\count($args) === 1 && \is_array($args[0])) { + // New options array format + if (count($args) === 1 && is_array($args[0])) { return $args[0]; } + // Handle obscure case where options array is mixed with a priority + if (count($args) === 2 && is_array($args[0]) && is_int($args[1])) { + $arguments = $args[0]; + $arguments['priority'] = $args[1]; + return $arguments; + } switch ($type) { - case(Assets::INLINE_CSS_TYPE): - $defaults = ['priority' => null, 'group' => null]; - $arguments = $this->createArgumentsFromLegacy($args, $defaults); - break; - case(Assets::JS_TYPE): $defaults = ['priority' => null, 'pipeline' => true, 'loading' => null, 'group' => null]; $arguments = $this->createArgumentsFromLegacy($args, $defaults); @@ -55,6 +57,11 @@ trait LegacyAssetsTrait break; + case(Assets::INLINE_CSS_TYPE): + $defaults = ['priority' => null, 'group' => null]; + $arguments = $this->createArgumentsFromLegacy($args, $defaults); + break; + default: case(Assets::CSS_TYPE): $defaults = ['priority' => null, 'pipeline' => true, 'group' => null, 'loading' => null]; diff --git a/system/src/Grav/Common/Cache.php b/system/src/Grav/Common/Cache.php index 314ab1184..8b8317736 100644 --- a/system/src/Grav/Common/Cache.php +++ b/system/src/Grav/Common/Cache.php @@ -437,6 +437,9 @@ class Cache extends Getters case 'tmp-only': $remove_paths = self::$tmp_remove; break; + case 'invalidate': + $remove_paths = []; + break; default: if (Grav::instance()['config']->get('system.cache.clear_images_by_default')) { $remove_paths = self::$standard_remove; diff --git a/system/src/Grav/Common/Data/Validation.php b/system/src/Grav/Common/Data/Validation.php index 8ff199bd9..b1c4cd373 100644 --- a/system/src/Grav/Common/Data/Validation.php +++ b/system/src/Grav/Common/Data/Validation.php @@ -165,6 +165,11 @@ class Validation return (string) $value; } + protected static function filterCheckbox($value, array $params, array $field) + { + return (bool) $value; + } + protected static function filterCommaList($value, array $params, array $field) { return \is_array($value) ? $value : preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY); @@ -571,6 +576,11 @@ class Validation } } + // If creating new values is allowed, no further checks are needed. + if (!empty($field['selectize']['create'])) { + return true; + } + $options = $field['options'] ?? []; $use = $field['use'] ?? 'values'; diff --git a/system/src/Grav/Common/Helpers/Truncator.php b/system/src/Grav/Common/Helpers/Truncator.php index 4c7d7f969..d116bb341 100644 --- a/system/src/Grav/Common/Helpers/Truncator.php +++ b/system/src/Grav/Common/Helpers/Truncator.php @@ -234,7 +234,7 @@ class Truncator { } /** - * @inheritDoc + * */ public function truncate( $text, diff --git a/system/src/Grav/Common/Language/Language.php b/system/src/Grav/Common/Language/Language.php index cbc1b5d1b..81abbc11a 100644 --- a/system/src/Grav/Common/Language/Language.php +++ b/system/src/Grav/Common/Language/Language.php @@ -104,6 +104,11 @@ class Language public function getAvailable() { $languagesArray = $this->languages; //Make local copy + + $languagesArray = array_map(function($value) { + return preg_quote($value); + }, $languagesArray); + sort($languagesArray); return implode('|', array_reverse($languagesArray)); diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php index d4642788d..e7e6cf03f 100644 --- a/system/src/Grav/Common/Page/Pages.php +++ b/system/src/Grav/Common/Page/Pages.php @@ -88,6 +88,9 @@ class Pages */ protected $ignore_hidden; + /** @var string */ + protected $check_method; + /** * @var Types */ @@ -226,6 +229,11 @@ class Pages return $this->baseUrl($lang, $absolute) . Uri::filterPath($route); } + public function setCheckMethod($method) + { + $this->check_method = strtolower($method); + } + /** * Class initialization. Must be called before using this class. */ @@ -240,6 +248,10 @@ class Pages $this->children = []; $this->routes = []; + if (!$this->check_method) { + $this->setCheckMethod($config->get('system.cache.check.method', 'file')); + } + $this->buildPages(); } @@ -947,7 +959,7 @@ class Pages $taxonomy = $this->grav['taxonomy']; // how should we check for last modified? Default is by file - switch (strtolower($config->get('system.cache.check.method', 'file'))) { + switch ($this->check_method) { case 'none': case 'off': $hash = 0; diff --git a/system/src/Grav/Common/Processors/RequestProcessor.php b/system/src/Grav/Common/Processors/RequestProcessor.php index 8cb876a39..97564e69b 100644 --- a/system/src/Grav/Common/Processors/RequestProcessor.php +++ b/system/src/Grav/Common/Processors/RequestProcessor.php @@ -30,10 +30,13 @@ class RequestProcessor extends ProcessorBase $request = $request->withParsedBody(json_decode($request->getBody()->getContents(), true)); } + $uri = $request->getUri(); + $ext = mb_strtolower(pathinfo($uri->getPath(), PATHINFO_EXTENSION)); + $request = $request ->withAttribute('grav', $this->container) ->withAttribute('time', $_SERVER['REQUEST_TIME_FLOAT'] ?? GRAV_REQUEST_TIME) - ->withAttribute('route', Uri::getCurrentRoute()) + ->withAttribute('route', Uri::getCurrentRoute()->withExtension($ext)) ->withAttribute('referrer', $this->container['uri']->referrer()); $event = new RequestHandlerEvent(['request' => $request, 'handler' => $handler]); diff --git a/system/src/Grav/Common/Service/RequestServiceProvider.php b/system/src/Grav/Common/Service/RequestServiceProvider.php index d7b496d86..6410ef725 100644 --- a/system/src/Grav/Common/Service/RequestServiceProvider.php +++ b/system/src/Grav/Common/Service/RequestServiceProvider.php @@ -31,8 +31,8 @@ class RequestServiceProvider implements ServiceProviderInterface return $creator->fromGlobals(); }; - $container['route'] = function() { - return Uri::getCurrentRoute(); - }; + $container['route'] = $container->factory(function() { + return clone Uri::getCurrentRoute(); + }); } } diff --git a/system/src/Grav/Common/Service/SessionServiceProvider.php b/system/src/Grav/Common/Service/SessionServiceProvider.php index 96cbec97f..856ec3596 100644 --- a/system/src/Grav/Common/Service/SessionServiceProvider.php +++ b/system/src/Grav/Common/Service/SessionServiceProvider.php @@ -13,6 +13,7 @@ use Grav\Common\Config\Config; use Grav\Common\Debugger; use Grav\Common\Session; use Grav\Common\Uri; +use Grav\Common\Utils; use Pimple\Container; use Pimple\ServiceProviderInterface; use RocketTheme\Toolbox\Session\Message; @@ -55,8 +56,7 @@ class SessionServiceProvider implements ServiceProviderInterface $current_route = str_replace(Uri::filterPath($uri->rootUrl(false)), '', parse_url($uri->url(true), PHP_URL_PATH)); // Check no language, simple language prefix (en) and region specific language prefix (en-US). - $pos = strpos($current_route, $base); - if ($pos === 0 || $pos === 3 || $pos === 6) { + if (Utils::startsWith($current_route, $base) || Utils::pathPrefixedByLangCode($current_route)) { $cookie_lifetime = $config->get('plugins.admin.session.timeout', 1800); $enabled = $is_admin = true; } diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index 3e28280f4..0bcba9a8c 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -1154,7 +1154,7 @@ class Uri $this->scheme = $env['X-FORWARDED-PROTO']; } elseif (isset($env['HTTP_CLOUDFRONT_FORWARDED_PROTO'])) { $this->scheme = $env['HTTP_CLOUDFRONT_FORWARDED_PROTO']; - } elseif (isset($env['REQUEST_SCHEME'])) { + } elseif (isset($env['REQUEST_SCHEME']) && empty($env['HTTPS'])) { $this->scheme = $env['REQUEST_SCHEME']; } else { $https = $env['HTTPS'] ?? ''; diff --git a/system/src/Grav/Common/User/DataUser/UserCollection.php b/system/src/Grav/Common/User/DataUser/UserCollection.php index 0970ce7d3..800322a9f 100644 --- a/system/src/Grav/Common/User/DataUser/UserCollection.php +++ b/system/src/Grav/Common/User/DataUser/UserCollection.php @@ -118,4 +118,13 @@ class UserCollection implements UserCollectionInterface return $file_path && unlink($file_path); } + + public function count(): int + { + // check for existence of a user account + $account_dir = $file_path = Grav::instance()['locator']->findResource('account://'); + $accounts = glob($account_dir . '/*.yaml') ?: []; + + return count($accounts); + } } diff --git a/system/src/Grav/Common/User/Interfaces/UserCollectionInterface.php b/system/src/Grav/Common/User/Interfaces/UserCollectionInterface.php index a8cc7d65c..37b9009a5 100644 --- a/system/src/Grav/Common/User/Interfaces/UserCollectionInterface.php +++ b/system/src/Grav/Common/User/Interfaces/UserCollectionInterface.php @@ -9,7 +9,7 @@ namespace Grav\Common\User\Interfaces; -interface UserCollectionInterface +interface UserCollectionInterface extends \Countable { /** * Load user account. diff --git a/system/src/Grav/Common/User/Traits/UserTrait.php b/system/src/Grav/Common/User/Traits/UserTrait.php index 2b6976880..f711cc92b 100644 --- a/system/src/Grav/Common/User/Traits/UserTrait.php +++ b/system/src/Grav/Common/User/Traits/UserTrait.php @@ -148,12 +148,13 @@ trait UserTrait // Try looking for provider. $provider = $this->get('provider'); - if (\is_array($provider)) { - if (isset($provider['avatar_url']) && \is_string($provider['avatar_url'])) { - return $provider['avatar_url']; + $provider_options = $this->get($provider); + if (\is_array($provider_options)) { + if (isset($provider_options['avatar_url']) && \is_string($provider_options['avatar_url'])) { + return $provider_options['avatar_url']; } - if (isset($provider['avatar']) && \is_string($provider['avatar'])) { - return $provider['avatar']; + if (isset($provider_options['avatar']) && \is_string($provider_options['avatar'])) { + return $provider_options['avatar']; } } diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index c254009e5..811f2f433 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -975,6 +975,7 @@ abstract class Utils * @param string $string The path * * @return bool + * */ public static function pathPrefixedByLangCode($string) { @@ -983,8 +984,13 @@ abstract class Utils } $languages_enabled = Grav::instance()['config']->get('system.languages.supported', []); + $parts = explode('/', trim($string, '/')); - return $string[0] === '/' && $string[3] === '/' && \in_array(substr($string, 1, 2), $languages_enabled, true); + if (count($parts) > 0 && in_array($parts[0], $languages_enabled)) { + return true; + } + + return false; } /** @@ -1341,6 +1347,8 @@ abstract class Utils $post_max_size = static::parseSize(ini_get('post_max_size')); if ($post_max_size > 0) { $max_size = $post_max_size; + } else { + $max_size = 0; } $upload_max = static::parseSize(ini_get('upload_max_filesize')); @@ -1404,11 +1412,12 @@ abstract class Utils { $unit = preg_replace('/[^bkmgtpezy]/i', '', $size); $size = preg_replace('/[^0-9\.]/', '', $size); + if ($unit) { - return round($size * pow(1024, stripos('bkmgtpezy', $unit[0]))); - } else { - return round($size); + $size = $size * pow(1024, stripos('bkmgtpezy', $unit[0])); } + + return (int) abs(round($size)); } /** diff --git a/system/src/Grav/Console/Cli/ClearCacheCommand.php b/system/src/Grav/Console/Cli/ClearCacheCommand.php index 0ab4128b9..8ef6f4ff6 100644 --- a/system/src/Grav/Console/Cli/ClearCacheCommand.php +++ b/system/src/Grav/Console/Cli/ClearCacheCommand.php @@ -21,6 +21,7 @@ class ClearCacheCommand extends ConsoleCommand ->setName('cache') ->setAliases(['clearcache', 'cache-clear']) ->setDescription('Clears Grav cache') + ->addOption('invalidate', null, InputOption::VALUE_NONE, 'Invalidate cache, but do not remove any files') ->addOption('purge', null, InputOption::VALUE_NONE, 'If set purge old caches') ->addOption('all', null, InputOption::VALUE_NONE, 'If set will remove all including compiled, twig, doctrine caches') ->addOption('assets-only', null, InputOption::VALUE_NONE, 'If set will remove only assets/*') @@ -64,6 +65,8 @@ class ClearCacheCommand extends ConsoleCommand $remove = 'cache-only'; } elseif ($this->input->getOption('tmp-only')) { $remove = 'tmp-only'; + } elseif ($this->input->getOption('invalidate')) { + $remove = 'invalidate'; } else { $remove = 'standard'; } diff --git a/system/src/Grav/Console/Gpm/InfoCommand.php b/system/src/Grav/Console/Gpm/InfoCommand.php index ee8958405..2fe1a2ee1 100644 --- a/system/src/Grav/Console/Gpm/InfoCommand.php +++ b/system/src/Grav/Console/Gpm/InfoCommand.php @@ -114,7 +114,7 @@ class InfoCommand extends ConsoleCommand if ($info === 'date') { $name = 'Last Update'; - $data = date('D, j M Y, H:i:s, P ', strtotime('2014-09-16T00:07:16Z')); + $data = date('D, j M Y, H:i:s, P ', strtotime($data)); } $name = str_pad($name, 12); diff --git a/system/src/Grav/Framework/File/Formatter/YamlFormatter.php b/system/src/Grav/Framework/File/Formatter/YamlFormatter.php index a5193835b..05b09a515 100644 --- a/system/src/Grav/Framework/File/Formatter/YamlFormatter.php +++ b/system/src/Grav/Framework/File/Formatter/YamlFormatter.php @@ -102,7 +102,7 @@ class YamlFormatter extends AbstractFormatter } try { - return YamlParser::parse($data); + return (array) YamlParser::parse($data); } catch (ParseException $e) { if ($this->useCompatibleDecoder()) { return (array) FallbackYamlParser::parse($data); diff --git a/system/src/Grav/Framework/Flex/Flex.php b/system/src/Grav/Framework/Flex/Flex.php index 8e71b2a84..e87e903e3 100644 --- a/system/src/Grav/Framework/Flex/Flex.php +++ b/system/src/Grav/Framework/Flex/Flex.php @@ -91,7 +91,7 @@ class Flex implements \Countable // Return the directories in the given order. $directories = []; foreach ($types as $type) { - $directories = $this->types[$type] ?? null; + $directories[$type] = $this->types[$type] ?? null; } return $keepMissing ? $directories : array_filter($directories); diff --git a/system/src/Grav/Framework/Flex/FlexCollection.php b/system/src/Grav/Framework/Flex/FlexCollection.php index ac87f7cbf..5f2cbd844 100644 --- a/system/src/Grav/Framework/Flex/FlexCollection.php +++ b/system/src/Grav/Framework/Flex/FlexCollection.php @@ -490,7 +490,12 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface $twig = $grav['twig']; try { - return $twig->twig()->resolveTemplate(["flex-objects/layouts/{$this->getFlexType()}/collection/{$layout}.html.twig"]); + return $twig->twig()->resolveTemplate( + [ + "flex-objects/layouts/{$this->getFlexType()}/collection/{$layout}.html.twig", + "flex-objects/layouts/_default/collection/{$layout}.html.twig" + ] + ); } catch (LoaderError $e) { /** @var Debugger $debugger */ $debugger = Grav::instance()['debugger']; diff --git a/system/src/Grav/Framework/Flex/FlexObject.php b/system/src/Grav/Framework/Flex/FlexObject.php index 0db2cabdd..51f622a7a 100644 --- a/system/src/Grav/Framework/Flex/FlexObject.php +++ b/system/src/Grav/Framework/Flex/FlexObject.php @@ -162,6 +162,13 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface { $options = $options ?? $this->getFlexDirectory()->getConfig('data.search.options', []); $properties = $properties ?? $this->getFlexDirectory()->getConfig('data.search.fields', []); + if (!$properties) { + foreach ($this->getFlexDirectory()->getConfig('admin.list.fields', []) as $property => $value) { + if (!empty($value['link'])) { + $properties[] = $property; + } + } + } $weight = 0; foreach ((array)$properties as $property) { @@ -273,7 +280,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface return (float)$options['ends_with']; } if ((!$tested || !empty($options['contains'])) && Utils::contains($value, $search, $options['case_sensitive'] ?? false)) { - return (float)$options['contains']; + return (float)($options['contains'] ?? 1); } return 0; @@ -812,7 +819,12 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface $twig = $grav['twig']; try { - return $twig->twig()->resolveTemplate(["flex-objects/layouts/{$this->getFlexType()}/object/{$layout}.html.twig"]); + return $twig->twig()->resolveTemplate( + [ + "flex-objects/layouts/{$this->getFlexType()}/object/{$layout}.html.twig", + "flex-objects/layouts/_default/object/{$layout}.html.twig" + ] + ); } catch (LoaderError $e) { /** @var Debugger $debugger */ $debugger = Grav::instance()['debugger']; diff --git a/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php b/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php index 7f37b1a98..209ba3382 100644 --- a/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php +++ b/system/src/Grav/Framework/Flex/Storage/SimpleStorage.php @@ -192,6 +192,9 @@ class SimpleStorage extends AbstractFilesystemStorage $list = []; foreach ($rows as $key => $row) { + if (strpos($key, '@@')) { + $key = $this->getNewKey(); + } $this->data[$key] = $list[$key] = $row; } diff --git a/system/src/Grav/Framework/Flex/Traits/FlexAuthorizeTrait.php b/system/src/Grav/Framework/Flex/Traits/FlexAuthorizeTrait.php index 66a467d2c..0029d9fe0 100644 --- a/system/src/Grav/Framework/Flex/Traits/FlexAuthorizeTrait.php +++ b/system/src/Grav/Framework/Flex/Traits/FlexAuthorizeTrait.php @@ -13,6 +13,7 @@ namespace Grav\Framework\Flex\Traits; use Grav\Common\Grav; use Grav\Common\User\Interfaces\UserInterface; +use Grav\Framework\Flex\FlexDirectory; use Grav\Framework\Flex\Interfaces\FlexObjectInterface; /** @@ -44,7 +45,11 @@ trait FlexAuthorizeTrait $action = $this->exists() ? 'update' : 'create'; } - return $user->authorize(sprintf($this->_authorize, $scope, $action)); + $directory = $this instanceof FlexDirectory ? $this : $this->getFlexDirectory(); + $config = $directory->getConfig(); + $allowed = $config->get("{$scope}.actions.{$action}") ?? $config->get("actions.{$action}") ?? true; + + return $allowed && $user->authorize(sprintf($this->_authorize, $scope, $action)); } protected function setAuthorizeRule(string $authorize) : void diff --git a/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php b/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php index d95774f03..6d3f873de 100644 --- a/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php +++ b/system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php @@ -229,7 +229,6 @@ trait FlexMediaTrait } // Remove Extra Files - foreach (scandir($targetPath, SCANDIR_SORT_NONE) as $file) { $preg_name = preg_quote($fileParts['filename'], '`'); $preg_ext =preg_quote($fileParts['extension'], '`'); diff --git a/system/src/Grav/Framework/Route/Route.php b/system/src/Grav/Framework/Route/Route.php index f287694c8..a75234077 100644 --- a/system/src/Grav/Framework/Route/Route.php +++ b/system/src/Grav/Framework/Route/Route.php @@ -193,6 +193,7 @@ class Route public function withRoute($route) { $this->route = $route; + return $this; } @@ -205,6 +206,7 @@ class Route public function withRoot($root) { $this->root = $root; + return $this; } @@ -250,6 +252,25 @@ class Route return $this->withParam('queryParams', $param, $value); } + public function withoutParams() + { + return $this->withoutGravParams()->withoutQueryParams(); + } + + public function withoutGravParams() + { + $this->gravParams = []; + + return $this; + } + + public function withoutQueryParams() + { + $this->queryParams = []; + + return $this; + } + /** * @return \Grav\Framework\Uri\Uri */ @@ -298,7 +319,7 @@ class Route return $this; } - $new = clone $this; + $new = $this->copy(); if ($value === null) { unset($new->{$type}[$param]); } else { @@ -308,6 +329,11 @@ class Route return $new; } + protected function copy() + { + return clone $this; + } + /** * @param bool $includeRoot * @return string diff --git a/user/pages/01.home/default.md b/user/pages/01.home/default.md index 9616b6276..13b237671 100644 --- a/user/pages/01.home/default.md +++ b/user/pages/01.home/default.md @@ -26,7 +26,7 @@ To edit this page, simply navigate to the folder you installed **Grav** into, an Creating a new page is a simple affair in **Grav**. Simply follow these simple steps: -1. Navigate to your pages folder: `user/pages/` and create a new folder. In this example, we will use [explicit default ordering](http://learn.getgrav.org/content/content-pages) and call the folder `02.mypage`. +1. Navigate to your pages folder: `user/pages/` and create a new folder. In this example, we will use [explicit default ordering](http://learn.getgrav.org/content/content-pages) and call the folder `03.mypage`. 2. Launch your text editor and paste in the following sample code: --- @@ -36,7 +36,7 @@ Creating a new page is a simple affair in **Grav**. Simply follow these simple This is the body of **my new page** and I can easily use _Markdown_ syntax here. -3. Save this file in the `user/pages/02.mypage/` folder as `default.md`. This will tell **Grav** to render the page using the **default** template. +3. Save this file in the `user/pages/03.mypage/` folder as `default.md`. This will tell **Grav** to render the page using the **default** template. 4. That is it! Reload your browser to see your new page in the menu. -! NOTE: The page will automatically show up in the Menu after the "Home" menu item. If you wish to change the name that shows up in the Menu, simple add: `menu: My Page` between the dashes in the page content. This is called the YAML front matter, and it is where you configure page-specific options. +! NOTE: The page will automatically show up in the Menu after the "Typography" menu item. If you wish to change the name that shows up in the Menu, simple add: `menu: My Page` between the dashes in the page content. This is called the YAML front matter, and it is where you configure page-specific options.