mirror of
https://github.com/getgrav/grav.git
synced 2025-12-05 23:39:58 +01:00
Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4204f13f8 | ||
|
|
0554b25c78 | ||
|
|
f4e7cbaa6e | ||
|
|
83bfc1fd0f | ||
|
|
30439b864d | ||
|
|
80999121a9 | ||
|
|
ca0d0bb373 | ||
|
|
345578a05d | ||
|
|
1f0537124a | ||
|
|
2a2b9a12a7 | ||
|
|
5a19e05931 | ||
|
|
6ae4680fcb | ||
|
|
b4cf7899bb | ||
|
|
eac16911d0 | ||
|
|
21bef62b82 | ||
|
|
a1eccfdb61 | ||
|
|
90e05694d3 | ||
|
|
b97ac503a1 | ||
|
|
2cc34151df | ||
|
|
4c160533c2 | ||
|
|
59dd0d1212 | ||
|
|
3bf7e38e52 | ||
|
|
362ee4c9eb | ||
|
|
2462331884 | ||
|
|
cb4147a4bd | ||
|
|
72f3a01abf | ||
|
|
31e3c1c295 | ||
|
|
37891a1032 | ||
|
|
70284e1517 | ||
|
|
0bca1dcb48 | ||
|
|
36f9865c0b | ||
|
|
cd48551630 | ||
|
|
0ff130650f | ||
|
|
9b445ac5b6 | ||
|
|
c21248fcc2 | ||
|
|
88aa4c5ec9 | ||
|
|
0fd22ad933 | ||
|
|
00b56da220 | ||
|
|
fef6bdde5f | ||
|
|
6f7938e939 | ||
|
|
2cd469cd7c | ||
|
|
0895b15489 | ||
|
|
d9062b60d6 | ||
|
|
3f4049031d | ||
|
|
c81ce71074 | ||
|
|
f84ffd235b | ||
|
|
1ca6181856 | ||
|
|
f17954a5db | ||
|
|
acea401a3d | ||
|
|
e9e4106d22 | ||
|
|
0ec7158102 | ||
|
|
d3695b2faa | ||
|
|
0668a47758 | ||
|
|
ca645ef476 | ||
|
|
3ff5f79561 | ||
|
|
b5c8b70163 | ||
|
|
173a70c017 | ||
|
|
eb52f670b9 | ||
|
|
dd166ce25c | ||
|
|
ea6423226a | ||
|
|
85bf4406ed | ||
|
|
0cb8e0664e | ||
|
|
2842b8fa39 | ||
|
|
317615854a | ||
|
|
a9c82710a6 | ||
|
|
3856a2a719 | ||
|
|
880128c339 | ||
|
|
444b48f788 | ||
|
|
cc69591799 | ||
|
|
0d6f774386 | ||
|
|
474ca513ae | ||
|
|
f37c08f341 | ||
|
|
92afba0e28 | ||
|
|
974fc552c5 | ||
|
|
9e1170bd50 |
54
CHANGELOG.md
54
CHANGELOG.md
@@ -1,3 +1,57 @@
|
||||
# v1.3.9
|
||||
## 12/05/2017
|
||||
|
||||
1. [](#new)
|
||||
* Added new core Twig templates for `partials/metadata.html.twig` and `partials/messages.html.twig`
|
||||
* Added ability to work with GPM locally [#1742](https://github.com/getgrav/grav/issues/1742)
|
||||
* Added new HTML5 audio controls [#1756](https://github.com/getgrav/grav/issues/1756)
|
||||
* Added `Medium::copy()` method to create a copy of a medium object
|
||||
* Added new `force_lowercase_urls` functionality on routes and slugs
|
||||
* Added new `item-list` filter type to remove empty items
|
||||
* Added new `setFlashCookieObject()` and `getFlashCookieObject()` methods to `Session` object
|
||||
* Added new `intl_enabled` option to disable PHP intl module collation when not needed
|
||||
1. [](#bugfix)
|
||||
* Fixed an issue with checkbox field validation [form#216](https://github.com/getgrav/grav-plugin-form/issues/216)
|
||||
* Fixed issue with multibyte Markdown link URLs [#1749](https://github.com/getgrav/grav/issues/1749)
|
||||
* Fixed issue with multibyte folder names [#1751](https://github.com/getgrav/grav/issues/1751)
|
||||
* Fixed several issues related to `system.custom_base_url` that were broken [#1736](https://github.com/getgrav/grav/issues/1736)
|
||||
* Dynamically added pages via `Pages::addPage()` were not firing `onPageProcessed()` event causing forms not to be processed
|
||||
* Fixed `Page::active()` and `Page::activeChild()` to work with UTF-8 characters in the URL [#1727](https://github.com/getgrav/grav/issues/1727)
|
||||
* Fixed typo in `modular.yaml` causing media to be ignored [#1725](https://github.com/getgrav/grav/issues/1725)
|
||||
* Reverted `case_insensitive_urls` option as it was causing issues with taxonomy [#1733](https://github.com/getgrav/grav/pull/1733)
|
||||
* Removed an extra `/` in `CompileFile.php` [#1693](https://github.com/getgrav/grav/pull/1693)
|
||||
* Uri::Encode user and password to prevent issues in browsers
|
||||
* Fixed "Invalid AJAX response" When using Built-in PHP Webserver in Windows [#1258](https://github.com/getgrav/grav-plugin-admin/issues/1258)
|
||||
* Remove support for `config.user`, it was broken and bad practise
|
||||
* Make sure that `clean cache` uses valid path [#1745](https://github.com/getgrav/grav/pull/1745)
|
||||
* Fixed token creation issue with `Uri` params like `/id:3`
|
||||
* Fixed CSS Pipeline failing with Google remote fonts if the file was minified [#1261](https://github.com/getgrav/grav-plugin-admin/issues/1261)
|
||||
* Forced `field.multiple: true` to allow use of min/max options in `checkboxes.validate`
|
||||
|
||||
# v1.3.8
|
||||
## 10/26/2017
|
||||
|
||||
1. [](#new)
|
||||
* Added Page `media_order` capability to manually order page media via a page header
|
||||
1. [](#bugfix)
|
||||
* Fixed GPM update issue with filtered slugs [#1711](https://github.com/getgrav/grav/issues/1711)
|
||||
* Fixed issue with missing image file not throwing 404 properly [#1713](https://github.com/getgrav/grav/issues/1713)
|
||||
|
||||
# v1.3.7
|
||||
## 10/18/2017
|
||||
|
||||
1. [](#bugfix)
|
||||
* Regression Uri: `base_url_absolute` always has the port number [#1690](https://github.com/getgrav/grav-plugin-admin/issues/1690)
|
||||
* Uri: Prefer using REQUEST_SCHEME instead of HTTPS [#1698](https://github.com/getgrav/grav-plugin-admin/issues/1698)
|
||||
* Fixed routing paths with urlencoded spaces and non-latin letters [#1688](https://github.com/getgrav/grav-plugin-admin/issues/1688)
|
||||
|
||||
# v1.3.6
|
||||
## 10/12/2017
|
||||
|
||||
1. [](#bugfix)
|
||||
* Regression: Ajax error in Nginx [admin#1244](https://github.com/getgrav/grav-plugin-admin/issues/1244)
|
||||
* Remove the `_url=$uri` portion of the the Nginx `try_files` command [admin#1244](https://github.com/getgrav/grav-plugin-admin/issues/1244)
|
||||
|
||||
# v1.3.5
|
||||
## 10/11/2017
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ patches and features.
|
||||
|
||||
## Grav, Plugins, Themes and Skeletons
|
||||
|
||||
Grav is a large open source project—it's made up of over 100 repositories. When you initially consider contributing to Grav, you might be unsure about which of those 200 repositories implements the functionality you want to change or report a bug for.
|
||||
Grav is a large open source project — it's made up of over 100 repositories. When you initially consider contributing to Grav, you might be unsure about which of those 200 repositories implements the functionality you want to change or report a bug for.
|
||||
|
||||
[https://github.com/getgrav/grav](https://github.com/getgrav/grav) is the main Grav repository. The core of Grav is provided by this repo.
|
||||
|
||||
@@ -60,20 +60,20 @@ Guidelines for bug reports:
|
||||
A good bug report shouldn't leave others needing to chase you up for more
|
||||
information. Please try to be as detailed as possible in your report.
|
||||
|
||||
What is your environment? Is it localhost, OSX, Linux, on a remote server? Same happening locally and or the server, or just locally or just on Linux?
|
||||
- What is your environment? Is it localhost, OSX, Linux, on a remote server? Same happening locally and or the server, or just locally or just on Linux?
|
||||
|
||||
What steps will reproduce the issue? What browser(s) and OS experience the problem?
|
||||
- What steps will reproduce the issue? What browser(s) and OS experience the problem?
|
||||
|
||||
What would you expect to be the outcome?
|
||||
- What would you expect to be the outcome?
|
||||
|
||||
Did the problem start happening recently (e.g. after updating to a new version of Grav) or was this always a problem?
|
||||
- Did the problem start happening recently (e.g. after updating to a new version of Grav) or was this always a problem?
|
||||
|
||||
If the problem started happening recently, can you reproduce the problem in an older version of Grav? What's the most recent version in which the problem doesn't happen? You can download older versions of Grav from the releases page on Github.
|
||||
- If the problem started happening recently, can you reproduce the problem in an older version of Grav? What's the most recent version in which the problem doesn't happen? You can download older versions of Grav from the releases page on Github.
|
||||
|
||||
Can you reliably reproduce the issue? If not, provide details about how often the problem happens and under which conditions it normally happens.
|
||||
- Can you reliably reproduce the issue? If not, provide details about how often the problem happens and under which conditions it normally happens.
|
||||
|
||||
|
||||
All these details will help people to fix any potential bugs.
|
||||
All these details will help contributors to fix any potential bugs.
|
||||
|
||||
Important: [include Code Samples in triple backticks](https://help.github.com/articles/github-flavored-markdown/#fenced-code-blocks) so that Github will provide a proper indentation. [Add the language name after the backticks](https://help.github.com/articles/github-flavored-markdown/#syntax-highlighting) to add syntax highlighting to the code snippets.
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ $ bin/gpm update
|
||||
We appreciate any contribution to Grav, whether it is related to bugs, grammar, or simply a suggestion or improvement! Please refer to the [Contributing guide](CONTRIBUTING.md) for more guidance on this topic.
|
||||
|
||||
## Security issues
|
||||
If you discover a possible security issue related to Grav or one of its plugins, please send an email to the core team at contact@getgrav.org and we'll address it as soon as possible.
|
||||
If you discover a possible security issue related to Grav or one of its plugins, please email the core team at contact@getgrav.org and we'll address it as soon as possible.
|
||||
|
||||
# Getting Started
|
||||
|
||||
@@ -101,9 +101,11 @@ If you discover a possible security issue related to Grav or one of its plugins,
|
||||
|
||||
* Have a look at our [Basic Tutorial](https://learn.getgrav.org/basics/basic-tutorial)
|
||||
* Dive into more [advanced](https://learn.getgrav.org/advanced) functions
|
||||
* Learn about the [Grav CLI](https://learn.getgrav.org/cli-console/grav-cli)
|
||||
* Review examples in the [Grav Cookbook](https://learn.getgrav.org/cookbook)
|
||||
|
||||
# Backers
|
||||
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/grav#backer)]
|
||||
Support Grav with a monthly donation to help us continue development. [[Become a backer](https://opencollective.com/grav#backer)]
|
||||
|
||||
<a href="https://opencollective.com/grav/backer/0/website" target="_blank"><img src="https://opencollective.com/grav/backer/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/grav/backer/1/website" target="_blank"><img src="https://opencollective.com/grav/backer/1/avatar.svg"></a>
|
||||
|
||||
@@ -1131,6 +1131,16 @@ form:
|
||||
label: PLUGIN_ADMIN.PWD_REGEX
|
||||
help: PLUGIN_ADMIN.PWD_REGEX_HELP
|
||||
|
||||
intl_enabled:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.INTL_ENABLED
|
||||
highlight: 1
|
||||
help: PLUGIN_ADMIN.INTL_ENABLED_HELP
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
wrapped_site:
|
||||
type: toggle
|
||||
@@ -1154,17 +1164,6 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
case_insensitive_urls:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.CASE_INSENSITIVE_URLS
|
||||
highlight: 0
|
||||
help: PLUGIN_ADMIN.CASE_INSENSITIVE_URLS_HELP
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
param_sep:
|
||||
type: select
|
||||
size: medium
|
||||
@@ -1187,6 +1186,18 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
force_lowercase_urls:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.FORCE_LOWERCASE_URLS
|
||||
highlight: 1
|
||||
default: 1
|
||||
help: PLUGIN_ADMIN.FORCE_LOWERCASE_URLS_HELP
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
custom_base_url:
|
||||
type: text
|
||||
size: medium
|
||||
|
||||
@@ -32,7 +32,7 @@ form:
|
||||
validate:
|
||||
type: textarea
|
||||
|
||||
uploads:
|
||||
header.media_order:
|
||||
type: pagemedia
|
||||
label: PLUGIN_ADMIN.PAGE_MEDIA
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ form:
|
||||
content:
|
||||
unset@: true
|
||||
|
||||
uploads:
|
||||
header.media_order:
|
||||
unset@: true
|
||||
|
||||
header.external_url:
|
||||
|
||||
@@ -42,6 +42,6 @@ form:
|
||||
type: ignore
|
||||
content:
|
||||
type: ignore
|
||||
uploads:
|
||||
header.media_order:
|
||||
type: ignore
|
||||
|
||||
|
||||
@@ -5,9 +5,11 @@ param_sep: ':' # Parameter separator, use ';'
|
||||
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 (NOTE: Not an ideal solution)
|
||||
force_lowercase_urls: true # If you want to support mixed cased URLs set this to false
|
||||
custom_base_url: '' # Set the base_url manually, e.g. http://yoursite.com/yourpath
|
||||
username_regex: '^[a-z0-9_-]{3,16}$' # Only lowercase chars, digits, dashes, underscores. 3 - 16 chars
|
||||
pwd_regex: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}' # At least one number, one uppercase and lowercase letter, and be at least 8+ chars
|
||||
intl_enabled: true # Special logic for PHP International Extension (mod_intl)
|
||||
|
||||
languages:
|
||||
supported: [] # List of languages supported. eg: [en, fr, de]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.3.5');
|
||||
define('GRAV_VERSION', '1.3.9');
|
||||
//define('GRAV_TESTING', true);
|
||||
define('DS', '/');
|
||||
|
||||
|
||||
@@ -35,11 +35,15 @@ class Assets
|
||||
const CSS_URL_REGEX = '{url\(([\'\"]?)(.*?)\1\)}';
|
||||
|
||||
/** @const Regex to match CSS sourcemap comments */
|
||||
const CSS_SOURCEMAP_REGEX = '{\/\*# (.*) \*\/}';
|
||||
const CSS_SOURCEMAP_REGEX = '{\/\*# (.*?) \*\/}';
|
||||
|
||||
/** @const Regex to match CSS import content */
|
||||
const CSS_IMPORT_REGEX = '{@import(.*);}';
|
||||
const CSS_IMPORT_REGEX = '{@import(.*?);}';
|
||||
|
||||
/**
|
||||
* @const Regex to match <script> or <style> tag when adding inline style/script. Note that this only supports a
|
||||
* single tag, so the check is greedy to avoid issues in JS.
|
||||
*/
|
||||
const HTML_TAG_REGEX = '#(<([A-Z][A-Z0-9]*)>)+(.*)(<\/\2>)#is';
|
||||
|
||||
|
||||
|
||||
@@ -390,6 +390,7 @@ class Cache extends Getters
|
||||
// Convert stream to a real path
|
||||
try {
|
||||
$path = $locator->findResource($stream, true, true);
|
||||
if($path === false) continue;
|
||||
|
||||
$anything = false;
|
||||
$files = glob($path . '/*');
|
||||
|
||||
@@ -28,9 +28,12 @@ class Validation
|
||||
$messages = [];
|
||||
|
||||
$validate = isset($field['validate']) ? (array) $field['validate'] : [];
|
||||
// Validate type with fallback type text.
|
||||
$type = (string) isset($validate['type']) ? $validate['type'] : $field['type'];
|
||||
$method = 'type'.strtr($type, '-', '_');
|
||||
|
||||
// If value isn't required, we will stop validation if empty value is given.
|
||||
if (empty($validate['required']) && ($value === null || $value === '')) {
|
||||
if ((empty($validate['required']) || (isset($validate['required']) && $validate['required'] !== true)) && ($value === null || $value === '' || ($field['type'] === 'checkbox' && $value == false))) {
|
||||
return $messages;
|
||||
}
|
||||
|
||||
@@ -46,10 +49,6 @@ class Validation
|
||||
// Get language class.
|
||||
$language = Grav::instance()['language'];
|
||||
|
||||
// Validate type with fallback type text.
|
||||
$type = (string) isset($field['validate']['type']) ? $field['validate']['type'] : $field['type'];
|
||||
$method = 'type'.strtr($type, '-', '_');
|
||||
|
||||
$name = ucfirst(isset($field['label']) ? $field['label'] : $field['name']);
|
||||
$message = (string) isset($field['validate']['message'])
|
||||
? $language->translate($field['validate']['message'])
|
||||
@@ -161,7 +160,7 @@ class Validation
|
||||
return is_array($value) ? $value : preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
protected static function typeCommaList($value, array $params, array $field)
|
||||
public static function typeCommaList($value, array $params, array $field)
|
||||
{
|
||||
return is_array($value) ? true : self::typeText($value, $params, $field);
|
||||
}
|
||||
@@ -230,6 +229,8 @@ class Validation
|
||||
*/
|
||||
public static function typeCheckboxes($value, array $params, array $field)
|
||||
{
|
||||
// Set multiple: true so checkboxes can easily use min/max counts to control number of options required
|
||||
$field['multiple'] = true;
|
||||
return self::typeArray((array) $value, $params, $field);
|
||||
}
|
||||
|
||||
@@ -253,7 +254,7 @@ class Validation
|
||||
if (!isset($field['value'])) {
|
||||
$field['value'] = 1;
|
||||
}
|
||||
if ($value && $value != $field['value']) {
|
||||
if (isset($value) && $value != $field['value']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -758,6 +759,11 @@ class Validation
|
||||
&& $value instanceof \Countable);
|
||||
}
|
||||
|
||||
public static function filterItem_List($value, $params)
|
||||
{
|
||||
return array_values(array_filter($value, function($v) { return !empty($v); } ));
|
||||
}
|
||||
|
||||
public static function validateJson($value, $params)
|
||||
{
|
||||
return (bool) (@json_decode($value));
|
||||
|
||||
@@ -27,7 +27,7 @@ trait CompiledFile
|
||||
// If nothing has been loaded, attempt to get pre-compiled version of the file first.
|
||||
if ($var === null && $this->raw === null && $this->content === null) {
|
||||
$key = md5($this->filename);
|
||||
$file = PhpFile::instance(CACHE_DIR . DS . "compiled/files/{$key}{$this->extension}.php");
|
||||
$file = PhpFile::instance(CACHE_DIR . "compiled/files/{$key}{$this->extension}.php");
|
||||
|
||||
$modified = $this->modified();
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class GPM extends Iterator
|
||||
{
|
||||
/** @var callable */
|
||||
private $callback;
|
||||
|
||||
/**
|
||||
* Local installed Packages
|
||||
* @var Local\Packages
|
||||
@@ -29,6 +32,9 @@ class GPM extends Iterator
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/** @var bool */
|
||||
private $shouldRefresh;
|
||||
|
||||
/**
|
||||
* @var Remote\GravCore
|
||||
*/
|
||||
@@ -47,18 +53,33 @@ class GPM extends Iterator
|
||||
];
|
||||
|
||||
/**
|
||||
* Creates a new GPM instance with Local and Remote packages available
|
||||
* Loads Remote Packages available
|
||||
*/
|
||||
private function retrieveRemoteRepository()
|
||||
{
|
||||
if (!$this->repository) {
|
||||
$this->repository = new Remote\Packages($this->shouldRefresh, $this->callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GPM instance with Local packages available
|
||||
* @param boolean $refresh Applies to Remote Packages only and forces a refetch of data
|
||||
* @param callable $callback Either a function or callback in array notation
|
||||
*/
|
||||
public function __construct($refresh = false, $callback = null)
|
||||
{
|
||||
$this->installed = new Local\Packages();
|
||||
try {
|
||||
$this->repository = new Remote\Packages($refresh, $callback);
|
||||
$this->grav = new Remote\GravCore($refresh, $callback);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
$this->shouldRefresh = $refresh;
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads Remote Grav package available
|
||||
*/
|
||||
public function loadRemoteGrav()
|
||||
{
|
||||
$this->grav = new Remote\GravCore($this->refresh, $this->callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,6 +289,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getLatestVersionOfPackage($package_name)
|
||||
{
|
||||
$this->retrieveRemoteRepository();
|
||||
$repository = $this->repository['plugins'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->available ?: $repository[$package_name]->version;
|
||||
@@ -310,6 +332,7 @@ class GPM extends Iterator
|
||||
public function getUpdatableThemes()
|
||||
{
|
||||
$items = [];
|
||||
$this->retrieveRemoteRepository();
|
||||
$repository = $this->repository['themes'];
|
||||
|
||||
// local cache to speed things up
|
||||
@@ -357,6 +380,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getReleaseType($package_name)
|
||||
{
|
||||
$this->retrieveRemoteRepository();
|
||||
$repository = $this->repository['plugins'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->release_type;
|
||||
@@ -405,6 +429,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getRepositoryPlugin($slug)
|
||||
{
|
||||
$this->retrieveRemoteRepository();
|
||||
return @$this->repository['plugins'][$slug];
|
||||
}
|
||||
|
||||
@@ -443,6 +468,7 @@ class GPM extends Iterator
|
||||
*/
|
||||
public function getRepository()
|
||||
{
|
||||
$this->retrieveRemoteRepository();
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ class Grav extends Container
|
||||
// Initialize Locale if set and configured.
|
||||
if ($this['language']->enabled() && $this['config']->get('system.languages.override_locale')) {
|
||||
$language = $this['language']->getLanguage();
|
||||
setlocale(LC_ALL, count($language < 3) ? ($language . '_' . strtoupper($language)) : $language);
|
||||
setlocale(LC_ALL, strlen($language) < 3 ? ($language . '_' . strtoupper($language)) : $language);
|
||||
} elseif ($this['config']->get('system.default_locale')) {
|
||||
setlocale(LC_ALL, $this['config']->get('system.default_locale'));
|
||||
}
|
||||
@@ -499,6 +499,9 @@ class Grav extends Container
|
||||
}
|
||||
Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download);
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
return false;
|
||||
}
|
||||
|
||||
return $page;
|
||||
|
||||
@@ -12,6 +12,7 @@ use Grav\Common\Grav;
|
||||
use Grav\Common\Page\Page;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Common\Page\Medium\Medium;
|
||||
use Grav\Common\Utils;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
|
||||
@@ -321,7 +322,7 @@ class Excerpts
|
||||
*/
|
||||
protected static function parseUrl($url)
|
||||
{
|
||||
$url_parts = parse_url($url);
|
||||
$url_parts = Utils::multibyteParseUrl($url);
|
||||
|
||||
if (isset($url_parts['scheme'])) {
|
||||
/** @var UniformResourceLocator $locator */
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
namespace Grav\Common\Page\Medium;
|
||||
|
||||
use Grav\Common\Getters;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Utils;
|
||||
|
||||
abstract class AbstractMedia extends Getters
|
||||
{
|
||||
@@ -49,7 +51,8 @@ abstract class AbstractMedia extends Getters
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
ksort($this->instances, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
$this->instances = $this->orderMedia($this->instances);
|
||||
|
||||
return $this->instances;
|
||||
}
|
||||
|
||||
@@ -60,7 +63,7 @@ abstract class AbstractMedia extends Getters
|
||||
*/
|
||||
public function images()
|
||||
{
|
||||
ksort($this->images, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
$this->images = $this->orderMedia($this->images);
|
||||
return $this->images;
|
||||
}
|
||||
|
||||
@@ -71,7 +74,7 @@ abstract class AbstractMedia extends Getters
|
||||
*/
|
||||
public function videos()
|
||||
{
|
||||
ksort($this->videos, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
$this->videos = $this->orderMedia($this->videos);
|
||||
return $this->videos;
|
||||
}
|
||||
|
||||
@@ -82,7 +85,7 @@ abstract class AbstractMedia extends Getters
|
||||
*/
|
||||
public function audios()
|
||||
{
|
||||
ksort($this->audios, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
$this->audios = $this->orderMedia($this->audios);
|
||||
return $this->audios;
|
||||
}
|
||||
|
||||
@@ -93,7 +96,7 @@ abstract class AbstractMedia extends Getters
|
||||
*/
|
||||
public function files()
|
||||
{
|
||||
ksort($this->files, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
$this->files = $this->orderMedia($this->files);
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
@@ -119,6 +122,25 @@ abstract class AbstractMedia extends Getters
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Order the media based on the page's media_order
|
||||
*
|
||||
* @param $media
|
||||
* @return array
|
||||
*/
|
||||
protected function orderMedia($media)
|
||||
{
|
||||
$page = Grav::instance()['pages']->get($this->path);
|
||||
|
||||
if ($page && isset($page->header()->media_order)) {
|
||||
$media_order = array_map('trim', explode(',', $page->header()->media_order));
|
||||
$media = Utils::sortArrayByArray($media, $media_order);
|
||||
} else {
|
||||
ksort($media, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
}
|
||||
return $media;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filename, extension and meta part.
|
||||
*
|
||||
|
||||
@@ -30,6 +30,114 @@ class AudioMedium extends Medium
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set or remove the HTML5 default controls
|
||||
*
|
||||
* @param bool $display
|
||||
* @return $this
|
||||
*/
|
||||
public function controls($display = true)
|
||||
{
|
||||
if($display)
|
||||
{
|
||||
$this->attributes['controls'] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($this->attributes['controls']);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set the preload behaviour
|
||||
*
|
||||
* @param $preload
|
||||
* @return $this
|
||||
*/
|
||||
public function preload($preload)
|
||||
{
|
||||
$validPreloadAttrs = array('auto','metadata','none');
|
||||
|
||||
if (in_array($preload, $validPreloadAttrs))
|
||||
{
|
||||
$this->attributes['preload'] = $preload;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set the controlsList behaviour
|
||||
* Separate multiple values with a hyphen
|
||||
*
|
||||
* @param $controlsList
|
||||
* @return $this
|
||||
*/
|
||||
public function controlsList($controlsList)
|
||||
{
|
||||
$controlsList = str_replace('-', ' ', $controlsList);
|
||||
$this->attributes['controlsList'] = $controlsList;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set the muted attribute
|
||||
*
|
||||
* @param bool $status
|
||||
* @return $this
|
||||
*/
|
||||
public function muted($status = false)
|
||||
{
|
||||
if($status)
|
||||
{
|
||||
$this->attributes['muted'] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($this->attributes['muted']);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set the loop attribute
|
||||
*
|
||||
* @param bool $status
|
||||
* @return $this
|
||||
*/
|
||||
public function loop($status = false)
|
||||
{
|
||||
if($status)
|
||||
{
|
||||
$this->attributes['loop'] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($this->attributes['loop']);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to set the autoplay attribute
|
||||
*
|
||||
* @param bool $status
|
||||
* @return $this
|
||||
*/
|
||||
public function autoplay($status = false)
|
||||
{
|
||||
if($status)
|
||||
{
|
||||
$this->attributes['autoplay'] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($this->attributes['autoplay']);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset medium.
|
||||
*
|
||||
|
||||
@@ -72,6 +72,16 @@ class Medium extends Data implements RenderableInterface
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of this media object
|
||||
*
|
||||
* @return Medium
|
||||
*/
|
||||
public function copy()
|
||||
{
|
||||
return clone($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return just metadata from the Medium object
|
||||
*
|
||||
|
||||
@@ -125,7 +125,7 @@ class Page
|
||||
$config = Grav::instance()['config'];
|
||||
|
||||
$this->hide_home_route = $config->get('system.home.hide_in_urls', false);
|
||||
$this->home_route = $config->get('system.home.alias');
|
||||
$this->home_route = $this->adjustRouteCase($config->get('system.home.alias'));
|
||||
$this->filePath($file->getPathName());
|
||||
$this->modified($file->getMTime());
|
||||
$this->id($this->modified() . md5($this->filePath()));
|
||||
@@ -135,7 +135,7 @@ class Page
|
||||
$this->metadata();
|
||||
$this->url();
|
||||
$this->visible();
|
||||
$this->modularTwig($this->slug[0] == '_');
|
||||
$this->modularTwig($this->slug[0] === '_');
|
||||
$this->setPublishState();
|
||||
$this->published();
|
||||
$this->urlExtension();
|
||||
@@ -517,17 +517,18 @@ class Page
|
||||
// Return entire page content on wrong/ unknown format
|
||||
if (!in_array($format, ['short', 'long'])) {
|
||||
return $content;
|
||||
} elseif (($format === 'short') && isset($summary_size)) {
|
||||
}
|
||||
if (($format === 'short') && isset($summary_size)) {
|
||||
// Use mb_strimwidth to slice the string
|
||||
if (mb_strwidth($content, 'utf8') > $summary_size) {
|
||||
return mb_substr($content, 0, $summary_size);
|
||||
} else {
|
||||
return $content;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
// Get summary size from site config's file
|
||||
if (is_null($size)) {
|
||||
if ($size === null) {
|
||||
$size = $config['size'];
|
||||
}
|
||||
|
||||
@@ -535,7 +536,8 @@ class Page
|
||||
if ($size === 0) {
|
||||
return $content;
|
||||
// Return calculated summary based on defaults
|
||||
} elseif (!is_numeric($size) || ($size < 0)) {
|
||||
}
|
||||
if (!is_numeric($size) || ($size < 0)) {
|
||||
$size = 300;
|
||||
}
|
||||
|
||||
@@ -726,10 +728,9 @@ class Page
|
||||
if ($name) {
|
||||
if (isset($this->content_meta[$name])) {
|
||||
return $this->content_meta[$name];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->content_meta;
|
||||
@@ -825,27 +826,27 @@ class Page
|
||||
*/
|
||||
public function value($name, $default = null)
|
||||
{
|
||||
if ($name == 'content') {
|
||||
if ($name === 'content') {
|
||||
return $this->raw_content;
|
||||
}
|
||||
if ($name == 'route') {
|
||||
if ($name === 'route') {
|
||||
return $this->parent()->rawRoute();
|
||||
}
|
||||
if ($name == 'order') {
|
||||
if ($name === 'order') {
|
||||
$order = $this->order();
|
||||
|
||||
return $order ? (int)$this->order() : '';
|
||||
}
|
||||
if ($name == 'ordering') {
|
||||
if ($name === 'ordering') {
|
||||
return (bool)$this->order();
|
||||
}
|
||||
if ($name == 'folder') {
|
||||
if ($name === 'folder') {
|
||||
return preg_replace(PAGE_ORDER_PREFIX_REGEX, '', $this->folder);
|
||||
}
|
||||
if ($name == 'slug') {
|
||||
if ($name === 'slug') {
|
||||
return $this->slug();
|
||||
}
|
||||
if ($name == 'name') {
|
||||
if ($name === 'name') {
|
||||
$language = $this->language() ? '.' . $this->language() : '';
|
||||
$name_val = str_replace($language . '.md', '', $this->name());
|
||||
if ($this->modular()) {
|
||||
@@ -854,30 +855,30 @@ class Page
|
||||
|
||||
return $name_val;
|
||||
}
|
||||
if ($name == 'media') {
|
||||
if ($name === 'media') {
|
||||
return $this->media()->all();
|
||||
}
|
||||
if ($name == 'media.file') {
|
||||
if ($name === 'media.file') {
|
||||
return $this->media()->files();
|
||||
}
|
||||
if ($name == 'media.video') {
|
||||
if ($name === 'media.video') {
|
||||
return $this->media()->videos();
|
||||
}
|
||||
if ($name == 'media.image') {
|
||||
if ($name === 'media.image') {
|
||||
return $this->media()->images();
|
||||
}
|
||||
if ($name == 'media.audio') {
|
||||
if ($name === 'media.audio') {
|
||||
return $this->media()->audios();
|
||||
}
|
||||
|
||||
$path = explode('.', $name);
|
||||
$scope = array_shift($path);
|
||||
|
||||
if ($name == 'frontmatter') {
|
||||
if ($name === 'frontmatter') {
|
||||
return $this->frontmatter;
|
||||
}
|
||||
|
||||
if ($scope == 'header') {
|
||||
if ($scope === 'header') {
|
||||
$current = $this->header();
|
||||
foreach ($path as $field) {
|
||||
if (is_object($current) && isset($current->{$field})) {
|
||||
@@ -969,7 +970,7 @@ class Page
|
||||
|
||||
$this->_action = 'move';
|
||||
|
||||
if ($this->route() == $parent->route()) {
|
||||
if ($this->route() === $parent->route()) {
|
||||
throw new Exception('Failed: Cannot set page parent to self');
|
||||
}
|
||||
if (Utils::startsWith($parent->rawRoute(), $this->rawRoute())) {
|
||||
@@ -1029,12 +1030,12 @@ class Page
|
||||
$edit_mode = isset($grav['admin']) ? $grav['config']->get('plugins.admin.edit_mode') : null;
|
||||
|
||||
// override if you only want 'normal' mode
|
||||
if (empty($fields) && ($edit_mode == 'auto' || $edit_mode == 'normal')) {
|
||||
if (empty($fields) && ($edit_mode === 'auto' || $edit_mode === 'normal')) {
|
||||
$blueprint = $pages->blueprints('default');
|
||||
}
|
||||
|
||||
// override if you only want 'expert' mode
|
||||
if (!empty($fields) && $edit_mode == 'expert') {
|
||||
if (!empty($fields) && $edit_mode === 'expert') {
|
||||
$blueprint = $pages->blueprints('');
|
||||
}
|
||||
|
||||
@@ -1459,9 +1460,9 @@ class Page
|
||||
{
|
||||
if (isset($this->debugger) && $this->debugger === false) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1502,7 +1503,7 @@ class Page
|
||||
// Backward compatibility for nested arrays in metas
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $property => $prop_value) {
|
||||
$prop_key = $key . ":" . $property;
|
||||
$prop_key = $key . ':' . $property;
|
||||
$this->metadata[$prop_key] = [
|
||||
'name' => $prop_key,
|
||||
'property' => $prop_key,
|
||||
@@ -1517,7 +1518,7 @@ class Page
|
||||
'http_equiv' => $key,
|
||||
'content' => htmlspecialchars($value, ENT_QUOTES, 'UTF-8')
|
||||
];
|
||||
} elseif ($key == 'charset') {
|
||||
} elseif ($key === 'charset') {
|
||||
$this->metadata[$key] = ['charset' => htmlspecialchars($value, ENT_QUOTES, 'UTF-8')];
|
||||
} else {
|
||||
// if it's a social metadata with separator, render as property
|
||||
@@ -1552,12 +1553,12 @@ class Page
|
||||
*/
|
||||
public function slug($var = null)
|
||||
{
|
||||
if ($var !== null && $var !== "") {
|
||||
if ($var !== null && $var !== '') {
|
||||
$this->slug = $var;
|
||||
}
|
||||
|
||||
if (empty($this->slug)) {
|
||||
$this->slug = strtolower(preg_replace(PAGE_ORDER_PREFIX_REGEX, '', $this->folder));
|
||||
$this->slug = $this->adjustRouteCase(preg_replace(PAGE_ORDER_PREFIX_REGEX, '', $this->folder));
|
||||
}
|
||||
|
||||
|
||||
@@ -1679,7 +1680,7 @@ class Page
|
||||
$url = rtrim($url, '/');
|
||||
}
|
||||
|
||||
return $url;
|
||||
return Uri::filterPath($url);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1702,7 +1703,7 @@ class Page
|
||||
// calculate route based on parent slugs
|
||||
$parent = $this->parent();
|
||||
if (isset($parent)) {
|
||||
if ($this->hide_home_route && $parent->route() == $this->home_route) {
|
||||
if ($this->hide_home_route && $parent->route() === $this->home_route) {
|
||||
$baseRoute = '';
|
||||
} else {
|
||||
$baseRoute = (string)$parent->route();
|
||||
@@ -1747,7 +1748,7 @@ class Page
|
||||
if (empty($this->raw_route)) {
|
||||
$baseRoute = $this->parent ? (string)$this->parent()->rawRoute() : null;
|
||||
|
||||
$slug = preg_replace(PAGE_ORDER_PREFIX_REGEX, '', $this->folder);
|
||||
$slug = $this->adjustRouteCase(preg_replace(PAGE_ORDER_PREFIX_REGEX, '', $this->folder));
|
||||
|
||||
$this->raw_route = isset($baseRoute) ? $baseRoute . '/' . $slug : null;
|
||||
}
|
||||
@@ -1770,9 +1771,9 @@ class Page
|
||||
|
||||
if (!empty($this->routes) && isset($this->routes['aliases'])) {
|
||||
return $this->routes['aliases'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2294,11 +2295,11 @@ class Page
|
||||
*/
|
||||
public function active()
|
||||
{
|
||||
$uri_path = rtrim(Grav::instance()['uri']->path(), '/') ?: '/';
|
||||
$uri_path = rtrim(urldecode(Grav::instance()['uri']->path()), '/') ?: '/';
|
||||
$routes = Grav::instance()['pages']->routes();
|
||||
|
||||
if (isset($routes[$uri_path])) {
|
||||
if ($routes[$uri_path] == $this->path()) {
|
||||
if ($routes[$uri_path] === $this->path()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2317,7 +2318,7 @@ class Page
|
||||
{
|
||||
$uri = Grav::instance()['uri'];
|
||||
$pages = Grav::instance()['pages'];
|
||||
$uri_path = rtrim($uri->path(), '/');
|
||||
$uri_path = rtrim(urldecode($uri->path()), '/');
|
||||
$routes = Grav::instance()['pages']->routes();
|
||||
|
||||
if (isset($routes[$uri_path])) {
|
||||
@@ -2325,7 +2326,7 @@ class Page
|
||||
$child_page = $pages->dispatch($uri->route())->parent();
|
||||
if ($child_page) {
|
||||
while (!$child_page->root()) {
|
||||
if ($this->path() == $child_page->path()) {
|
||||
if ($this->path() === $child_page->path()) {
|
||||
return true;
|
||||
}
|
||||
$child_page = $child_page->parent();
|
||||
@@ -2344,7 +2345,7 @@ class Page
|
||||
public function home()
|
||||
{
|
||||
$home = Grav::instance()['config']->get('system.home.alias');
|
||||
$is_home = ($this->route() == $home || $this->rawRoute() == $home);
|
||||
$is_home = ($this->route() === $home || $this->rawRoute() === $home);
|
||||
|
||||
return $is_home;
|
||||
}
|
||||
@@ -2358,9 +2359,9 @@ class Page
|
||||
{
|
||||
if (!$this->parent && !$this->name && !$this->visible) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2587,7 +2588,7 @@ class Page
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param string|array $value
|
||||
*
|
||||
* @return mixed
|
||||
* @internal
|
||||
@@ -2605,7 +2606,7 @@ class Page
|
||||
$params = (array)current($value);
|
||||
} else {
|
||||
$result = [];
|
||||
foreach ($value as $key => $val) {
|
||||
foreach ((array)$value as $key => $val) {
|
||||
if (is_int($key)) {
|
||||
$result = $result + $this->evaluate($val)->toArray();
|
||||
} else {
|
||||
@@ -2711,7 +2712,7 @@ class Page
|
||||
|
||||
case 'root@':
|
||||
case '@root':
|
||||
if (!empty($parts) && $parts[0] == 'descendants') {
|
||||
if (!empty($parts) && $parts[0] === 'descendants') {
|
||||
$results = $pages->all($pages->root())->nonModular()->published();
|
||||
} else {
|
||||
$results = $pages->root()->children()->nonModular()->published();
|
||||
@@ -2824,11 +2825,11 @@ class Page
|
||||
|
||||
// Reorder all moved pages.
|
||||
foreach ($siblings as $slug => $page) {
|
||||
$order = intval(trim($page->order(), '.'));
|
||||
$order = (int)trim($page->order(), '.');
|
||||
$counter++;
|
||||
|
||||
if ($order) {
|
||||
if ($page->path() == $this->path() && $this->folderExists()) {
|
||||
if ($page->path() === $this->path() && $this->folderExists()) {
|
||||
// Handle current page; we do want to change ordering number, but nothing else.
|
||||
$this->order($counter);
|
||||
$this->save(false);
|
||||
@@ -2859,14 +2860,14 @@ class Page
|
||||
}
|
||||
|
||||
if (is_dir($this->_original->path())) {
|
||||
if ($this->_action == 'move') {
|
||||
if ($this->_action === 'move') {
|
||||
Folder::move($this->_original->path(), $this->path());
|
||||
} elseif ($this->_action == 'copy') {
|
||||
} elseif ($this->_action === 'copy') {
|
||||
Folder::copy($this->_original->path(), $this->path());
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->name() != $this->_original->name()) {
|
||||
if ($this->name() !== $this->_original->name()) {
|
||||
$path = $this->path();
|
||||
if (is_file($path . '/' . $this->_original->name())) {
|
||||
rename($path . '/' . $this->_original->name(), $path . '/' . $this->name());
|
||||
@@ -2889,10 +2890,21 @@ class Page
|
||||
}
|
||||
}
|
||||
// publish if required, if not clear cache right before page is published
|
||||
if ($this->publishDate() && $this->publishDate() && $this->publishDate() > time()) {
|
||||
if ($this->publishDate() && $this->publishDate() > time()) {
|
||||
$this->published(false);
|
||||
Grav::instance()['cache']->setLifeTime($this->publishDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function adjustRouteCase($route)
|
||||
{
|
||||
$case_insensitive = Grav::instance()['config']->get('system.force_lowercase_urls');
|
||||
|
||||
if ($case_insensitive) {
|
||||
return mb_strtolower($route);
|
||||
} else {
|
||||
return $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,13 @@ use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Language\Language;
|
||||
use Grav\Common\Taxonomy;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Plugin\Admin;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
use Whoops\Exception\ErrorException;
|
||||
use Collator as Collator;
|
||||
use Collator;
|
||||
|
||||
class Pages
|
||||
{
|
||||
@@ -152,7 +153,7 @@ class Pages
|
||||
}
|
||||
|
||||
$path_append = rtrim($this->grav['pages']->base(), '/');
|
||||
if ($language->getDefault() != $lang || $config->get('system.languages.include_default_lang') === true) {
|
||||
if ($language->getDefault() !== $lang || $config->get('system.languages.include_default_lang') === true) {
|
||||
$path_append .= $lang ? '/' . $lang : '';
|
||||
}
|
||||
|
||||
@@ -192,7 +193,7 @@ class Pages
|
||||
return $this->homeUrl($lang, $absolute);
|
||||
}
|
||||
|
||||
return $this->baseUrl($lang, $absolute) . $route;
|
||||
return $this->baseUrl($lang, $absolute) . Uri::filterPath($route);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,6 +265,8 @@ class Pages
|
||||
$this->children[$page->parent()->path()][$page->path()] = ['slug' => $page->slug()];
|
||||
}
|
||||
$this->routes[$route] = $page->path();
|
||||
|
||||
$this->grav->fireEvent('onPageProcessed', new Event(['page' => $page]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,7 +300,7 @@ class Pages
|
||||
|
||||
$sort = $this->sort[$path][$order_by];
|
||||
|
||||
if ($order_dir != 'asc') {
|
||||
if ($order_dir !== 'asc') {
|
||||
$sort = array_reverse($sort);
|
||||
}
|
||||
|
||||
@@ -327,7 +330,7 @@ class Pages
|
||||
|
||||
$sort = $this->sort[$lookup][$orderBy];
|
||||
|
||||
if ($orderDir != 'asc') {
|
||||
if ($orderDir !== 'asc') {
|
||||
$sort = array_reverse($sort);
|
||||
}
|
||||
|
||||
@@ -345,10 +348,6 @@ class Pages
|
||||
*/
|
||||
public function get($path)
|
||||
{
|
||||
if (!is_null($path) && !is_string($path)) {
|
||||
throw new \Exception();
|
||||
}
|
||||
|
||||
return isset($this->instances[(string)$path]) ? $this->instances[(string)$path] : null;
|
||||
}
|
||||
|
||||
@@ -376,13 +375,13 @@ class Pages
|
||||
*/
|
||||
public function ancestor($route, $path = null)
|
||||
{
|
||||
if (!is_null($path)) {
|
||||
|
||||
if ($path !== null) {
|
||||
$page = $this->dispatch($route, true);
|
||||
|
||||
if ($page->path() == $path) {
|
||||
if ($page && $page->path() === $path) {
|
||||
return $page;
|
||||
} elseif (!$page->parent()->root()) {
|
||||
}
|
||||
if ($page && !$page->parent()->root()) {
|
||||
return $this->ancestor($page->parent()->route(), $path);
|
||||
}
|
||||
}
|
||||
@@ -400,15 +399,14 @@ class Pages
|
||||
*/
|
||||
public function inherited($route, $field = null)
|
||||
{
|
||||
if (!is_null($field)) {
|
||||
if ($field !== null) {
|
||||
|
||||
$page = $this->dispatch($route, true);
|
||||
|
||||
$ancestorField = $page->parent()->value('header.' . $field);
|
||||
|
||||
if ($ancestorField !== null) {
|
||||
if ($page && $page->parent()->value('header.' . $field) !== null) {
|
||||
return $page->parent();
|
||||
} elseif (!$page->parent()->root()) {
|
||||
}
|
||||
if ($page && !$page->parent()->root()) {
|
||||
return $this->inherited($page->parent()->route(), $field);
|
||||
}
|
||||
}
|
||||
@@ -441,6 +439,8 @@ class Pages
|
||||
*/
|
||||
public function dispatch($route, $all = false, $redirect = true)
|
||||
{
|
||||
$route = urldecode($route);
|
||||
|
||||
// Fetch page if there's a defined route to it.
|
||||
$page = isset($this->routes[$route]) ? $this->get($this->routes[$route]) : null;
|
||||
// Try without trailing slash
|
||||
@@ -499,7 +499,7 @@ class Pages
|
||||
$pattern = '#^' . str_replace('/', '\/', ltrim($pattern, '^')) . '#';
|
||||
try {
|
||||
$found = preg_replace($pattern, $replace, $source_url);
|
||||
if ($found != $source_url) {
|
||||
if ($found !== $source_url) {
|
||||
$page = $this->dispatch($found, $all);
|
||||
}
|
||||
} catch (ErrorException $e) {
|
||||
@@ -535,7 +535,7 @@ class Pages
|
||||
*/
|
||||
public function blueprints($type)
|
||||
{
|
||||
if (!isset($this->blueprints)) {
|
||||
if ($this->blueprints === null) {
|
||||
$this->blueprints = new Blueprints(self::getTypes());
|
||||
}
|
||||
|
||||
@@ -970,7 +970,7 @@ class Pages
|
||||
* @throws \RuntimeException
|
||||
* @internal
|
||||
*/
|
||||
protected function recurse($directory, Page &$parent = null)
|
||||
protected function recurse($directory, Page $parent = null)
|
||||
{
|
||||
$directory = rtrim($directory, DS);
|
||||
$page = new Page;
|
||||
@@ -1023,7 +1023,7 @@ class Pages
|
||||
if ($found->isDir()) {
|
||||
continue;
|
||||
}
|
||||
$regex = '/^[^\.]*' . preg_quote($extension) . '$/';
|
||||
$regex = '/^[^\.]*' . preg_quote($extension, '/') . '$/';
|
||||
if (preg_match($regex, $found->getFilename())) {
|
||||
$page_found = $found;
|
||||
$page_extension = $extension;
|
||||
@@ -1053,10 +1053,8 @@ class Pages
|
||||
$name = $file->getFilename();
|
||||
|
||||
// Ignore all hidden files if set.
|
||||
if ($this->ignore_hidden) {
|
||||
if ($name && $name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
if ($this->ignore_hidden && $name && $name[0] === '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($file->isFile()) {
|
||||
@@ -1096,7 +1094,7 @@ class Pages
|
||||
}
|
||||
|
||||
// Override the modified time if modular
|
||||
if ($page->template() == 'modular') {
|
||||
if ($page->template() === 'modular') {
|
||||
foreach ($page->collection() as $child) {
|
||||
$modified = $child->modified();
|
||||
|
||||
@@ -1174,6 +1172,7 @@ class Pages
|
||||
* @param array $pages
|
||||
* @param string $order_by
|
||||
* @param array $manual
|
||||
* @param int $sort_flags
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @internal
|
||||
@@ -1224,6 +1223,9 @@ class Pages
|
||||
case 'basename':
|
||||
$list[$key] = basename($key);
|
||||
break;
|
||||
case 'folder':
|
||||
$list[$key] = $child->folder();
|
||||
break;
|
||||
case (is_string($header_query[0])):
|
||||
$child_header = new Header((array)$child->header());
|
||||
$header_value = $child_header->get($header_query[0]);
|
||||
@@ -1249,11 +1251,11 @@ class Pages
|
||||
}
|
||||
|
||||
// handle special case when order_by is random
|
||||
if ($order_by == 'random') {
|
||||
if ($order_by === 'random') {
|
||||
$list = $this->arrayShuffle($list);
|
||||
} else {
|
||||
// else just sort the list according to specified key
|
||||
if (extension_loaded('intl')) {
|
||||
if (extension_loaded('intl') && $this->grav['config']->get('system.intl_enabled')) {
|
||||
$locale = setlocale(LC_COLLATE, 0); //`setlocale` with a 0 param returns the current locale set
|
||||
$col = Collator::create($locale);
|
||||
if ($col) {
|
||||
@@ -1261,6 +1263,13 @@ class Pages
|
||||
$list = preg_replace_callback('~([0-9]+)\.~', function($number) {
|
||||
return sprintf('%032d.', $number[0]);
|
||||
}, $list);
|
||||
|
||||
$list_vals = array_values($list);
|
||||
if (is_numeric(array_shift($list_vals))) {
|
||||
$sort_flags = Collator::SORT_REGULAR;
|
||||
} else {
|
||||
$sort_flags = Collator::SORT_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
$col->asort($list, $sort_flags);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace Grav\Common\Processors;
|
||||
|
||||
use Grav\Common\Page\Page;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
|
||||
class PagesProcessor extends ProcessorBase implements ProcessorInterface
|
||||
{
|
||||
@@ -21,15 +22,15 @@ class PagesProcessor extends ProcessorBase implements ProcessorInterface
|
||||
$this->container['debugger']->addMessage($this->container['cache']->getCacheStatus());
|
||||
|
||||
$this->container['pages']->init();
|
||||
$this->container->fireEvent('onPagesInitialized');
|
||||
$this->container->fireEvent('onPageInitialized');
|
||||
$this->container->fireEvent('onPagesInitialized', new Event(['pages' => $this->container['pages']]));
|
||||
$this->container->fireEvent('onPageInitialized', new Event(['page' => $this->container['page']]));
|
||||
|
||||
/** @var Page $page */
|
||||
$page = $this->container['page'];
|
||||
|
||||
if (!$page->routable()) {
|
||||
// If no page found, fire event
|
||||
$event = $this->container->fireEvent('onPageNotFound');
|
||||
$event = $this->container->fireEvent('onPageNotFound', new Event(['page' => $page]));
|
||||
|
||||
if (isset($event->page)) {
|
||||
unset ($this->container['page']);
|
||||
|
||||
@@ -105,4 +105,20 @@ class Session extends BaseSession
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
// Store something in cookie temporarily
|
||||
public function setFlashCookieObject($name, $object, $time = 60)
|
||||
{
|
||||
setcookie($name, json_encode($object), time() + $time, '/');
|
||||
}
|
||||
|
||||
// Return object and remove it from the cookie
|
||||
public function getFlashCookieObject($name)
|
||||
{
|
||||
if (isset($_COOKIE[$name])) {
|
||||
$object = json_decode($_COOKIE[$name]);
|
||||
setcookie($name, '', time() - 3600, '/');
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,9 @@ class Twig
|
||||
|
||||
$this->grav->fireEvent('onTwigTemplatePaths');
|
||||
|
||||
// Add Grav core templates location
|
||||
$this->twig_paths = array_merge($this->twig_paths, $locator->findResources('system://templates'));
|
||||
|
||||
$this->loader = new \Twig_Loader_Filesystem($this->twig_paths);
|
||||
|
||||
$this->grav->fireEvent('onTwigLoader');
|
||||
|
||||
@@ -58,8 +58,12 @@ class Uri
|
||||
protected function createFromEnvironment(array $env)
|
||||
{
|
||||
// Build scheme.
|
||||
$https = isset($env['HTTPS']) ? $env['HTTPS'] : '';
|
||||
$this->scheme = (empty($https) || strtolower($https) === 'off') ? 'http' : 'https';
|
||||
if (isset($env['REQUEST_SCHEME'])) {
|
||||
$this->scheme = $env['REQUEST_SCHEME'];
|
||||
} else {
|
||||
$https = isset($env['HTTPS']) ? $env['HTTPS'] : '';
|
||||
$this->scheme = (empty($https) || strtolower($https) === 'off') ? 'http' : 'https';
|
||||
}
|
||||
|
||||
// Build user and password.
|
||||
$this->user = isset($env['PHP_AUTH_USER']) ? $env['PHP_AUTH_USER'] : null;
|
||||
@@ -79,6 +83,9 @@ class Uri
|
||||
|
||||
// Build port.
|
||||
$this->port = isset($env['SERVER_PORT']) ? (int)$env['SERVER_PORT'] : null;
|
||||
if ($this->hasStandardPort()) {
|
||||
$this->port = null;
|
||||
}
|
||||
|
||||
// Build path.
|
||||
$request_uri = isset($env['REQUEST_URI']) ? $env['REQUEST_URI'] : '';
|
||||
@@ -90,16 +97,35 @@ class Uri
|
||||
$this->query = parse_url('http://example.com' . $request_uri, PHP_URL_QUERY);
|
||||
}
|
||||
|
||||
// Support ngnix routes.
|
||||
if (strpos($this->query, '_url=') === 0) {
|
||||
parse_str($this->query, $query);
|
||||
unset($query['_url']);
|
||||
$this->query = http_build_query($query);
|
||||
}
|
||||
|
||||
// Build fragment.
|
||||
$this->fragment = null;
|
||||
|
||||
// Filter path and query string.
|
||||
// Filter userinfo, path and query string.
|
||||
$this->user = $this->user !== null ? static::filterUserInfo($this->user) : null;
|
||||
$this->password = $this->password !== null ? static::filterUserInfo($this->password) : null;
|
||||
$this->path = empty($this->path) ? '/' : static::filterPath($this->path);
|
||||
$this->query = static::filterQuery($this->query);
|
||||
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this Uri use a standard port?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasStandardPort()
|
||||
{
|
||||
return ($this->scheme === 'http' && $this->port === 80) || ($this->scheme === 'https' && $this->port === 443);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*/
|
||||
@@ -124,7 +150,9 @@ class Uri
|
||||
$this->host = $this->validateHostname($this->host) ? $this->host : 'unknown';
|
||||
}
|
||||
|
||||
// Filter path, query string and fragment.
|
||||
// Filter userinfo, path, query string and fragment.
|
||||
$this->user = $this->user !== null ? static::filterUserInfo($this->user) : null;
|
||||
$this->password = $this->password !== null ? static::filterUserInfo($this->password) : null;
|
||||
$this->path = empty($this->path) ? '/' : static::filterPath($this->path);
|
||||
$this->query = static::filterQuery($this->query);
|
||||
$this->fragment = $this->fragment !== null ? static::filterQuery($this->fragment) : null;
|
||||
@@ -221,7 +249,8 @@ class Uri
|
||||
*/
|
||||
private function buildRootPath()
|
||||
{
|
||||
$scriptPath = $_SERVER['PHP_SELF'];
|
||||
// In Windows script path uses backslash, convert it:
|
||||
$scriptPath = str_replace('\\', '/', $_SERVER['PHP_SELF']);
|
||||
$rootPath = str_replace(' ', '%20', rtrim(substr($scriptPath, 0, strpos($scriptPath, 'index.php')), '/'));
|
||||
|
||||
// check if userdir in the path and workaround PHP bug with PHP_SELF
|
||||
@@ -257,22 +286,21 @@ class Uri
|
||||
$this->base .= ':' . (string)$this->port;
|
||||
}
|
||||
|
||||
// Set some defaults
|
||||
if ($grav['config']->get('system.custom_base_url')) {
|
||||
$this->root_path = parse_url($grav['config']->get('system.custom_base_url'), PHP_URL_PATH);
|
||||
$this->root = $grav['config']->get('system.custom_base_url');
|
||||
// Handle custom base
|
||||
$custom_base = rtrim($grav['config']->get('system.custom_base_url'), '/');
|
||||
|
||||
if ($custom_base) {
|
||||
$custom_parts = parse_url($custom_base);
|
||||
$orig_root_path = $this->root_path;
|
||||
$this->root_path = isset($custom_parts['path']) ? rtrim($custom_parts['path'], '/') : '';
|
||||
$this->root = isset($custom_parts['scheme']) ? $custom_base : $this->base . $this->root_path;
|
||||
$this->uri = Utils::replaceFirstOccurrence($orig_root_path, $this->root_path, $this->uri);
|
||||
} else {
|
||||
$this->root = $this->base . $this->root_path;
|
||||
}
|
||||
|
||||
$this->url = $this->base . $this->uri;
|
||||
|
||||
// if case insensitive urls is enabled, lowercase the url
|
||||
if( $grav['config']->get('system.case_insensitive_urls') ){
|
||||
$this->url = strtolower($this->url);
|
||||
}
|
||||
|
||||
// get any params and remove them
|
||||
$uri = str_replace($this->root, '', $this->url);
|
||||
|
||||
// remove the setup.php based base if set:
|
||||
@@ -282,8 +310,9 @@ class Uri
|
||||
}
|
||||
|
||||
// If configured to, redirect trailing slash URI's with a 302 redirect
|
||||
if ($uri !== '/' && $config->get('system.pages.redirect_trailing_slash', false) && Utils::endsWith($uri, '/')) {
|
||||
$grav->redirect(str_replace($this->root, '', rtrim($uri, '/')), 302);
|
||||
$redirect = str_replace($this->root, '', rtrim($uri, '/'));
|
||||
if ($redirect && $uri !== '/' && $redirect !== $this->base() && $config->get('system.pages.redirect_trailing_slash', false) && Utils::endsWith($uri, '/')) {
|
||||
$grav->redirect($redirect, 302);
|
||||
}
|
||||
|
||||
// process params
|
||||
@@ -1114,11 +1143,20 @@ class Uri
|
||||
*/
|
||||
public static function addNonce($url, $action, $nonceParamName = 'nonce')
|
||||
{
|
||||
$fake = $url && $url[0] === '/';
|
||||
|
||||
if ($fake) {
|
||||
$url = 'http://domain.com' . $url;
|
||||
}
|
||||
$uri = new static($url);
|
||||
$parts = $uri->toArray();
|
||||
$nonce = Utils::getNonce($action);
|
||||
$parts['params'] = (isset($parts['params']) ? $parts['params'] : []) + [$nonceParamName => $nonce];
|
||||
|
||||
if ($fake) {
|
||||
unset($parts['scheme'], $parts['host']);
|
||||
}
|
||||
|
||||
return static::buildUrl($parts);
|
||||
}
|
||||
|
||||
@@ -1153,6 +1191,23 @@ class Uri
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the user info string.
|
||||
*
|
||||
* @param string $info The raw user or password.
|
||||
* @return string The percent-encoded user or password string.
|
||||
*/
|
||||
public static function filterUserInfo($info)
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=]+|%(?![A-Fa-f0-9]{2}))/u',
|
||||
function ($match) {
|
||||
return rawurlencode($match[0]);
|
||||
},
|
||||
$info
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter Uri path.
|
||||
*
|
||||
@@ -1168,7 +1223,7 @@ class Uri
|
||||
public static function filterPath($path)
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/',
|
||||
'/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/u',
|
||||
function ($match) {
|
||||
return rawurlencode($match[0]);
|
||||
},
|
||||
@@ -1185,7 +1240,7 @@ class Uri
|
||||
public static function filterQuery($query)
|
||||
{
|
||||
return preg_replace_callback(
|
||||
'/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/',
|
||||
'/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/u',
|
||||
function ($match) {
|
||||
return rawurlencode($match[0]);
|
||||
},
|
||||
|
||||
@@ -29,7 +29,6 @@ class User extends Data
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
$locator = $grav['locator'];
|
||||
$config = $grav['config'];
|
||||
|
||||
// force lowercase of username
|
||||
$username = strtolower($username);
|
||||
@@ -38,7 +37,7 @@ class User extends Data
|
||||
$blueprint = $blueprints->get('user/account');
|
||||
$file_path = $locator->findResource('account://' . $username . YAML_EXT);
|
||||
$file = CompiledYamlFile::instance($file_path);
|
||||
$content = $file->content();
|
||||
$content = (array)$file->content();
|
||||
if (!isset($content['username'])) {
|
||||
$content['username'] = $username;
|
||||
}
|
||||
@@ -48,9 +47,6 @@ class User extends Data
|
||||
$user = new User($content, $blueprint);
|
||||
$user->file($file);
|
||||
|
||||
// add user to config
|
||||
$config->set("user", $user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ abstract class Utils
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the substring of a string up to a specified needle. if not found, return the whole haytack
|
||||
* Returns the substring of a string up to a specified needle. if not found, return the whole haystack
|
||||
*
|
||||
* @param $haystack
|
||||
* @param $needle
|
||||
@@ -96,6 +96,46 @@ abstract class Utils
|
||||
return $haystack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to replace only the first occurrence in a string
|
||||
*
|
||||
* @param $search
|
||||
* @param $replace
|
||||
* @param $subject
|
||||
* @return mixed
|
||||
*/
|
||||
public static function replaceFirstOccurrence($search, $replace, $subject)
|
||||
{
|
||||
if (!$search) {
|
||||
return $subject;
|
||||
}
|
||||
$pos = strpos($subject, $search);
|
||||
if ($pos !== false) {
|
||||
$subject = substr_replace($subject, $replace, $pos, strlen($search));
|
||||
}
|
||||
return $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to replace only the last occurrence in a string
|
||||
*
|
||||
* @param $search
|
||||
* @param $replace
|
||||
* @param $subject
|
||||
* @return mixed
|
||||
*/
|
||||
public static function replaceLastOccurrence($search, $replace, $subject)
|
||||
{
|
||||
$pos = strrpos($subject, $search);
|
||||
|
||||
if($pos !== false)
|
||||
{
|
||||
$subject = substr_replace($subject, $replace, $pos, strlen($search));
|
||||
}
|
||||
|
||||
return $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two objects into one.
|
||||
*
|
||||
@@ -852,6 +892,24 @@ abstract class Utils
|
||||
return strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a multidimensional array by another array of ordered keys
|
||||
*
|
||||
* @param array $array
|
||||
* @param array $orderArray
|
||||
* @return array
|
||||
*/
|
||||
public static function sortArrayByArray(array $array, array $orderArray) {
|
||||
$ordered = array();
|
||||
foreach ($orderArray as $key) {
|
||||
if (array_key_exists($key, $array)) {
|
||||
$ordered[$key] = $array[$key];
|
||||
unset($array[$key]);
|
||||
}
|
||||
}
|
||||
return $ordered + $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's path based on a token
|
||||
*
|
||||
@@ -939,4 +997,36 @@ abstract class Utils
|
||||
return intval($size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multibyte-safe Parse URL function
|
||||
*
|
||||
* @param $url
|
||||
* @return mixed
|
||||
*/
|
||||
public static function multibyteParseUrl($url)
|
||||
{
|
||||
$enc_url = preg_replace_callback(
|
||||
'%[^:/@?&=#]+%usD',
|
||||
function ($matches)
|
||||
{
|
||||
return urlencode($matches[0]);
|
||||
},
|
||||
$url
|
||||
);
|
||||
|
||||
$parts = parse_url($enc_url);
|
||||
|
||||
if($parts === false)
|
||||
{
|
||||
throw new \InvalidArgumentException('Malformed URL: ' . $url);
|
||||
}
|
||||
|
||||
foreach($parts as $name => $value)
|
||||
{
|
||||
$parts[$name] = urldecode($value);
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ class InstallCommand extends ConsoleCommand
|
||||
$this->destination = rtrim($this->destination, DS);
|
||||
$path = $this->destination . DS . $data['path'];
|
||||
if (!file_exists($path)) {
|
||||
exec('cd "' . $this->destination . '" && git clone -b ' . $data['branch'] . ' ' . $data['url'] . ' ' . $data['path'], $output, $return);
|
||||
exec('cd "' . $this->destination . '" && git clone -b ' . $data['branch'] . ' --depth 1 ' . $data['url'] . ' ' . $data['path'], $output, $return);
|
||||
|
||||
if (!$return) {
|
||||
$this->output->writeln('<green>SUCCESS</green> cloned <magenta>' . $data['url'] . '</magenta> -> <cyan>' . $path . '</cyan>');
|
||||
|
||||
@@ -182,7 +182,7 @@ class UpdateCommand extends ConsoleCommand
|
||||
$index = 0;
|
||||
foreach ($this->data as $packages) {
|
||||
foreach ($packages as $slug => $package) {
|
||||
if (count($limit_to) && !array_key_exists($slug, $limit_to)) {
|
||||
if (count($only_packages) && !array_key_exists($slug, $limit_to)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -276,6 +276,7 @@ class UpdateCommand extends ConsoleCommand
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln("Packages not found or not requiring updates: <red>" . implode('</red>, <red>',
|
||||
$ignore) . "</red>");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
14
system/templates/partials/messages.html.twig
Normal file
14
system/templates/partials/messages.html.twig
Normal file
@@ -0,0 +1,14 @@
|
||||
{% set status_mapping = {'info':'green', 'error': 'red', 'warning': 'yellow'} %}
|
||||
|
||||
{% if grav.messages.all %}
|
||||
<div id="messages">
|
||||
{% for message in grav.messages.fetch %}
|
||||
|
||||
{% set scope = message.scope|e %}
|
||||
{% set color = status_mapping[scope] %}
|
||||
|
||||
<div class="notices {{ scope }} {{ color }}"><p>{{ message.message|raw }}</p></div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
3
system/templates/partials/metadata.html.twig
Normal file
3
system/templates/partials/metadata.html.twig
Normal file
@@ -0,0 +1,3 @@
|
||||
{% for meta in page.metadata %}
|
||||
<meta {% if meta.name %}name="{{ meta.name }}" {% endif %}{% if meta.http_equiv %}http-equiv="{{ meta.http_equiv }}" {% endif %}{% if meta.charset %}charset="{{ meta.charset }}" {% endif %}{% if meta.property %}property="{{ meta.property }}" {% endif %}{% if meta.content %}content="{{ meta.content }}" {% endif %}/>
|
||||
{% endfor %}
|
||||
@@ -320,4 +320,47 @@ class GpmTest extends \Codeception\TestCase\Test
|
||||
$this->assertSame(null, $this->gpm->calculateVersionNumberFromDependencyVersion('*'));
|
||||
$this->assertSame('2.0.2', $this->gpm->calculateVersionNumberFromDependencyVersion('2.0.2'));
|
||||
}
|
||||
|
||||
public function testRemoteRepositoryIsEmptyAfterConstruct()
|
||||
{
|
||||
$gpm = new GPM();
|
||||
$reflection = new \ReflectionClass(get_class($gpm));
|
||||
$repository = $reflection->getProperty('repository');
|
||||
$repository->setAccessible(true);
|
||||
|
||||
$this->assertSame(null, $repository->getValue($gpm));
|
||||
}
|
||||
|
||||
public function testLocalRepositoryIsNotEmptyAfterConstruct()
|
||||
{
|
||||
$gpm = new GPM();
|
||||
$reflection = new \ReflectionClass(get_class($gpm));
|
||||
$repository = $reflection->getProperty('installed');
|
||||
$repository->setAccessible(true);
|
||||
|
||||
$this->assertInstanceOf( '\Grav\Common\GPM\Local\Packages', $repository->getValue($gpm));
|
||||
}
|
||||
|
||||
public function testGetRepository()
|
||||
{
|
||||
$this->assertInstanceOf('\Grav\Common\GPM\Remote\Packages', $this->gpm->getRepository());
|
||||
}
|
||||
|
||||
public function testLatestVersionOfPackage()
|
||||
{
|
||||
$gpm = new GPM();
|
||||
$this->assertNotNull($gpm->getLatestVersionOfPackage('admin'));
|
||||
}
|
||||
|
||||
public function testReleaseType()
|
||||
{
|
||||
$gpm = new GPM();
|
||||
$this->assertNotNull($gpm->getReleaseType('admin'));
|
||||
}
|
||||
|
||||
public function testGetRepositoryPlugin()
|
||||
{
|
||||
$gpm = new GPM();
|
||||
$this->assertNotNull($gpm->getRepositoryPlugin('admin'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +371,52 @@ class UriTest extends \Codeception\TestCase\Test
|
||||
'extension' => null,
|
||||
'addNonce' => 'http://localhost:8080/a/b/c/d/e/f/a/b/c/d/e/f/a/b/c/d/e/f/nonce:{{nonce}}',
|
||||
],
|
||||
'http://localhost/this is the path/my page' => [
|
||||
'scheme' => 'http://',
|
||||
'user' => null,
|
||||
'password' => null,
|
||||
'host' => 'localhost',
|
||||
'port' => 80,
|
||||
'path' => '/this%20is%20the%20path/my%20page',
|
||||
'query' => '',
|
||||
'fragment' => null,
|
||||
|
||||
'route' => '/this%20is%20the%20path/my%20page',
|
||||
'paths' => ['this%20is%20the%20path', 'my%20page'],
|
||||
'params' => null,
|
||||
'url' => '/this%20is%20the%20path/my%20page',
|
||||
'environment' => 'localhost',
|
||||
'basename' => 'my%20page',
|
||||
'base' => 'http://localhost',
|
||||
'currentPage' => 1,
|
||||
'rootUrl' => 'http://localhost',
|
||||
'extension' => null,
|
||||
'addNonce' => 'http://localhost/this%20is%20the%20path/my%20page/nonce:{{nonce}}',
|
||||
'__toString' => 'http://localhost/this%20is%20the%20path/my%20page'
|
||||
],
|
||||
'http://localhost/pölöpölö/päläpälä' => [
|
||||
'scheme' => 'http://',
|
||||
'user' => null,
|
||||
'password' => null,
|
||||
'host' => 'localhost',
|
||||
'port' => 80,
|
||||
'path' => '/p%C3%B6l%C3%B6p%C3%B6l%C3%B6/p%C3%A4l%C3%A4p%C3%A4l%C3%A4',
|
||||
'query' => '',
|
||||
'fragment' => null,
|
||||
|
||||
'route' => '/p%C3%B6l%C3%B6p%C3%B6l%C3%B6/p%C3%A4l%C3%A4p%C3%A4l%C3%A4',
|
||||
'paths' => ['p%C3%B6l%C3%B6p%C3%B6l%C3%B6', 'p%C3%A4l%C3%A4p%C3%A4l%C3%A4'],
|
||||
'params' => null,
|
||||
'url' => '/p%C3%B6l%C3%B6p%C3%B6l%C3%B6/p%C3%A4l%C3%A4p%C3%A4l%C3%A4',
|
||||
'environment' => 'localhost',
|
||||
'basename' => 'p%C3%A4l%C3%A4p%C3%A4l%C3%A4',
|
||||
'base' => 'http://localhost',
|
||||
'currentPage' => 1,
|
||||
'rootUrl' => 'http://localhost',
|
||||
'extension' => null,
|
||||
'addNonce' => 'http://localhost/p%C3%B6l%C3%B6p%C3%B6l%C3%B6/p%C3%A4l%C3%A4p%C3%A4l%C3%A4/nonce:{{nonce}}',
|
||||
'__toString' => 'http://localhost/p%C3%B6l%C3%B6p%C3%B6l%C3%B6/p%C3%A4l%C3%A4p%C3%A4l%C3%A4'
|
||||
],
|
||||
// Query params tests.
|
||||
'http://localhost:8080/grav/it/ueper?test=x&test2=y' => [
|
||||
'scheme' => 'http://',
|
||||
@@ -550,7 +596,53 @@ class UriTest extends \Codeception\TestCase\Test
|
||||
'rootUrl' => 'http://localhost',
|
||||
'extension' => 'json',
|
||||
'addNonce' => 'http://localhost/a-page.json/nonce:{{nonce}}',
|
||||
'__toString' => 'http://localhost/a-page', // FIXME <-
|
||||
'__toString' => 'http://localhost/a-page', // FIX ME <-
|
||||
],
|
||||
'http://localhost/admin/ajax.json/task:getnewsfeed' => [
|
||||
'scheme' => 'http://',
|
||||
'user' => null,
|
||||
'password' => null,
|
||||
'host' => 'localhost',
|
||||
'port' => 80,
|
||||
'path' => '/admin/ajax',
|
||||
'query' => '',
|
||||
'fragment' => null,
|
||||
|
||||
'route' => '/admin/ajax',
|
||||
'paths' => ['admin', 'ajax'],
|
||||
'params' => '/task:getnewsfeed',
|
||||
'url' => '/admin/ajax',
|
||||
'environment' => 'localhost',
|
||||
'basename' => 'ajax.json',
|
||||
'base' => 'http://localhost',
|
||||
'currentPage' => 1,
|
||||
'rootUrl' => 'http://localhost',
|
||||
'extension' => 'json',
|
||||
'addNonce' => 'http://localhost/admin/ajax.json/task:getnewsfeed/nonce:{{nonce}}',
|
||||
'__toString' => 'http://localhost/admin/ajax/task:getnewsfeed',
|
||||
],
|
||||
'http://localhost/grav/admin/media.json/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==' => [
|
||||
'scheme' => 'http://',
|
||||
'user' => null,
|
||||
'password' => null,
|
||||
'host' => 'localhost',
|
||||
'port' => 80,
|
||||
'path' => '/grav/admin/media',
|
||||
'query' => '',
|
||||
'fragment' => null,
|
||||
|
||||
'route' => '/grav/admin/media',
|
||||
'paths' => ['grav','admin','media'],
|
||||
'params' => '/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==',
|
||||
'url' => '/grav/admin/media',
|
||||
'environment' => 'localhost',
|
||||
'basename' => 'media.json',
|
||||
'base' => 'http://localhost',
|
||||
'currentPage' => 1,
|
||||
'rootUrl' => 'http://localhost',
|
||||
'extension' => 'json',
|
||||
'addNonce' => 'http://localhost/grav/admin/media.json/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==/nonce:{{nonce}}',
|
||||
'__toString' => 'http://localhost/grav/admin/media/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==', // FIXME <-
|
||||
],
|
||||
'http://localhost/a-page.foo' => [
|
||||
'scheme' => 'http://',
|
||||
@@ -573,6 +665,7 @@ class UriTest extends \Codeception\TestCase\Test
|
||||
'rootUrl' => 'http://localhost',
|
||||
'extension' => 'foo',
|
||||
'addNonce' => 'http://localhost/a-page.foo/nonce:{{nonce}}',
|
||||
'__toString' => 'http://localhost/a-page.foo'
|
||||
],
|
||||
// Fragment tests.
|
||||
'http://localhost:8080/a/b/c#my-fragment' => [
|
||||
|
||||
@@ -12,7 +12,7 @@ server {
|
||||
# `location /subfolder {`
|
||||
# and the rewrite to use `/subfolder/index.php`
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?_url=$uri&$query_string;
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
## End - Index
|
||||
|
||||
|
||||
Reference in New Issue
Block a user