mirror of
https://github.com/getgrav/grav.git
synced 2026-07-08 14:33:04 +02:00
Merge branches 'develop' and 'feature/objects' of https://github.com/getgrav/grav into feature/objects
# Conflicts: # composer.lock
This commit is contained in:
@@ -55,6 +55,7 @@ before_install:
|
||||
fi
|
||||
- if [ $TRAVIS_BRANCH != 'develop' ] && [ $TRAVIS_PHP_VERSION == "5.6" ] && [ $TRAVIS_PULL_REQUEST == "false" ]; then
|
||||
export TRAVIS_TAG=$(curl --fail --user "${GH_API_USER}" -s https://api.github.com/repos/getgrav/grav/releases/latest | grep tag_name | head -n 1 | cut -d '"' -f 4);
|
||||
eval "$(curl -sL https://raw.githubusercontent.com/travis-ci/gimme/master/gimme | GIMME_GO_VERSION=1.8 bash)";
|
||||
go get github.com/aktau/github-release;
|
||||
git clone --quiet --depth=50 --branch=master https://${BB_TOKEN}bitbucket.org/rockettheme/grav-devtools.git $RT_DEVTOOLS &>/dev/null;
|
||||
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||
|
||||
61
CHANGELOG.md
61
CHANGELOG.md
@@ -1,5 +1,61 @@
|
||||
# v1.1.18
|
||||
## 02/xx/2017
|
||||
# v1.2.2
|
||||
## 04/11/2017
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fix for redirects breaking [#1420](https://github.com/getgrav/grav/issues/1420)
|
||||
* Fix issue in direct-install with github-style dependencies [#1405](https://github.com/getgrav/grav/issues/1405)
|
||||
|
||||
# v1.2.1
|
||||
## 04/10/2017
|
||||
|
||||
1. [](#improved)
|
||||
* Added various `ancestor` helper methods in Page and Pages classes [#1362](https://github.com/getgrav/grav/pull/1362)
|
||||
* Added new `parents` field and switched Page blueprints to use this
|
||||
* Added `isajaxrequest()` Twig function [#1400](https://github.com/getgrav/grav/issues/1400)
|
||||
* Added ability to inline CSS and JS code via Asset manager [#1377](https://github.com/getgrav/grav/pull/1377)
|
||||
* Add query string in lighttpd default config [#1393](https://github.com/getgrav/grav/issues/1393)
|
||||
* Add `--all-yes` and `--destination` options for `bin/gpm direct-install` [#1397](https://github.com/getgrav/grav/pull/1397)
|
||||
1. [](#bugfix)
|
||||
* Fix for direct-install of plugins with `languages.yaml` [#1396](https://github.com/getgrav/grav/issues/1396)
|
||||
* When determining language from HTTP_ACCEPT_LANGUAGE, also try base language only [#1402](https://github.com/getgrav/grav/issues/1402)
|
||||
* Fixed a bad method signature causing warning when running tests on `GPMTest` object
|
||||
|
||||
# v1.2.0
|
||||
## 03/31/2017
|
||||
|
||||
1. [](#new)
|
||||
* Added file upload for user avatar in user/admin blueprint
|
||||
1. [](#improved)
|
||||
* Analysis fixes
|
||||
* Switched to stable composer lib versions
|
||||
|
||||
# v1.2.0-rc.3
|
||||
## 03/22/2017
|
||||
|
||||
1. [](#new)
|
||||
* Refactored Page re-ordering to handle all siblings at once
|
||||
* Added `language_codes` to Twig init to allow for easy language name/code/native-name lookup
|
||||
1. [](#improved)
|
||||
* Added an _Admin Overrides_ section with option to choose the order of children in Pages Management
|
||||
1. [](#bugfix)
|
||||
* Fixed loading issues with improperly named themes (use old broken method first) [#1373](https://github.com/getgrav/grav/issues/1373)
|
||||
* Simplified modular/twig processing logic and fixed an issue with system process config [#1351](https://github.com/getgrav/grav/issues/1351)
|
||||
* Cleanup package files via GPM install to make them more windows-friendly [#1361](https://github.com/getgrav/grav/pull/1361)
|
||||
* Fix for page-level debugger override changing the option site-wide
|
||||
* Allow `url()` twig function to pass-through external links
|
||||
|
||||
# v1.2.0-rc.2
|
||||
## 03/17/2017
|
||||
|
||||
1. [](#improved)
|
||||
* Updated vendor libraries to latest
|
||||
* Added the ability to disable debugger on a per-page basis with `debugger: false` in page frontmatter
|
||||
1. [](#bugfix)
|
||||
* Fixed an issue with theme inheritance and hyphenated base themes [#1353](https://github.com/getgrav/grav/issues/1353)
|
||||
* Fixed an issue when trying to use an `@2x` derivative on a non-image media file [#1341](https://github.com/getgrav/grav/issues/1341)
|
||||
|
||||
# v1.2.0-rc.1
|
||||
## 03/13/2017
|
||||
|
||||
1. [](#new)
|
||||
* Added default setting to only allow `direct-installs` from official GPM. Can be configured in `system.yaml`
|
||||
@@ -7,6 +63,7 @@
|
||||
* Added optional parameter to `|markdown(false)` filter to toggle block/line processing (default|true = `block`)
|
||||
* Added new `Page::folderExists()` method
|
||||
1. [](#improved)
|
||||
* `Twig::evaluate()` now takes current environment and context into account
|
||||
* Genericized `direct-install` so it can be called via Admin plugin
|
||||
1. [](#bugfix)
|
||||
* Fixed a minor bug in Number validation [#1329](https://github.com/getgrav/grav/issues/1329)
|
||||
|
||||
@@ -110,7 +110,7 @@ Good pull requests - patches, improvements, new features - are a fantastic
|
||||
help. They should remain focused in scope and avoid containing unrelated
|
||||
commits.
|
||||
|
||||
**Please ask first** in Gitter or in the Forum before embarking on any significant pull request (e.g.
|
||||
**Please ask first** in [Slack](https://getgrav.org/slack) or in the Forum before embarking on any significant pull request (e.g.
|
||||
implementing features, refactoring code..),
|
||||
otherwise you risk spending a lot of time working on something that the
|
||||
project's developers might not want to merge into the project.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"twig/twig": "~1.24",
|
||||
"erusev/parsedown": "dev-master as 1.6.0",
|
||||
"erusev/parsedown": "~1.6",
|
||||
"erusev/parsedown-extra": "~0.7",
|
||||
"symfony/yaml": "~2.8",
|
||||
"symfony/console": "~2.8",
|
||||
@@ -20,7 +20,7 @@
|
||||
"filp/whoops": "~2.0",
|
||||
"matthiasmullie/minify": "^1.3",
|
||||
"monolog/monolog": "~1.0",
|
||||
"gregwar/image": "dev-master#72568cfbeb77515278f2ccb386fc344e874b7ae8",
|
||||
"gregwar/image": "~2.0",
|
||||
"donatj/phpuseragentparser": "~0.3",
|
||||
"pimple/pimple": "~3.0",
|
||||
"rockettheme/toolbox": "~1.0",
|
||||
|
||||
441
composer.lock
generated
441
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@ form:
|
||||
default_lang:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.SITE_DEFAULT_LANG
|
||||
size: vsmall
|
||||
size: x-small
|
||||
placeholder: PLUGIN_ADMIN.SITE_DEFAULT_LANG_PLACEHOLDER
|
||||
help: PLUGIN_ADMIN.SITE_DEFAULT_LANG_HELP
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ form:
|
||||
|
||||
pages.order.by:
|
||||
type: select
|
||||
size: long
|
||||
size: large
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.DEFAULT_ORDERING
|
||||
help: PLUGIN_ADMIN.DEFAULT_ORDERING_HELP
|
||||
@@ -155,6 +155,7 @@ form:
|
||||
|
||||
pages.append_url_extension:
|
||||
type: text
|
||||
size: x-small
|
||||
placeholder: "e.g. .html"
|
||||
label: PLUGIN_ADMIN.APPEND_URL_EXT
|
||||
help: PLUGIN_ADMIN.APPEND_URL_EXT_HELP
|
||||
@@ -856,13 +857,12 @@ form:
|
||||
|
||||
fields:
|
||||
images.default_image_quality:
|
||||
type: text
|
||||
type: range
|
||||
append: '%'
|
||||
label: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY
|
||||
help: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY_HELP
|
||||
classes: x-small
|
||||
validate:
|
||||
type: number
|
||||
min: 1
|
||||
max: 100
|
||||
|
||||
|
||||
@@ -117,17 +117,6 @@ form:
|
||||
title: PLUGIN_ADMIN.SETTINGS
|
||||
underline: true
|
||||
|
||||
ordering:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
|
||||
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
folder:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.FOLDER_NAME
|
||||
@@ -135,13 +124,9 @@ form:
|
||||
rule: slug
|
||||
|
||||
route:
|
||||
type: select
|
||||
type: parents
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::rawRoute'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
|
||||
name:
|
||||
type: select
|
||||
@@ -165,9 +150,20 @@ form:
|
||||
title: PLUGIN_ADMIN.ORDERING
|
||||
underline: true
|
||||
|
||||
ordering:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
|
||||
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
order:
|
||||
type: order
|
||||
label: PLUGIN_ADMIN.PAGE_ORDER
|
||||
label: PLUGIN_ADMIN.SORTABLE_PAGES
|
||||
sitemap:
|
||||
|
||||
overrides:
|
||||
@@ -291,6 +287,18 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
header.debugger:
|
||||
type: toggle
|
||||
toggleable: true
|
||||
label: PLUGIN_ADMIN.DEBUGGER
|
||||
help: PLUGIN_ADMIN.DEBUGGER_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
header.template:
|
||||
type: text
|
||||
toggleable: true
|
||||
@@ -302,6 +310,25 @@ form:
|
||||
toggleable: true
|
||||
help: PLUGIN_ADMIN.APPEND_URL_EXT_HELP
|
||||
|
||||
admin_only:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.ADMIN_SPECIFIC_OVERRIDES
|
||||
underline: true
|
||||
|
||||
fields:
|
||||
|
||||
header.admin.children_display_order:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.ADMIN_CHILDREN_DISPLAY_ORDER
|
||||
help: PLUGIN_ADMIN.ADMIN_CHILDREN_DISPLAY_ORDER_HELP
|
||||
toggleable: true
|
||||
classes: fancy
|
||||
default: 'collection'
|
||||
options:
|
||||
'default': 'Ordered by Folder name (default)'
|
||||
'collection': 'Ordered by Collection definition'
|
||||
|
||||
|
||||
header.order_by:
|
||||
type: hidden
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
rules:
|
||||
slug:
|
||||
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
|
||||
min: 1
|
||||
max: 200
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
fields:
|
||||
|
||||
section:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.ADD_MODULAR_CONTENT
|
||||
|
||||
title:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.PAGE_TITLE
|
||||
validate:
|
||||
required: true
|
||||
|
||||
folder:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.FOLDER_NAME
|
||||
validate:
|
||||
rule: slug
|
||||
required: true
|
||||
|
||||
route:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PAGE
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::rawRoute'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
name:
|
||||
type: select
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
|
||||
help: PLUGIN_ADMIN.PAGE_FILE_HELP
|
||||
default: default
|
||||
data-options@: '\Grav\Common\Page\Pages::modularTypes'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
modular:
|
||||
type: hidden
|
||||
default: 1
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
blueprint:
|
||||
type: blueprint
|
||||
@@ -1,106 +0,0 @@
|
||||
rules:
|
||||
slug:
|
||||
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
|
||||
min: 1
|
||||
max: 200
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
fields:
|
||||
|
||||
tabs:
|
||||
type: tabs
|
||||
active: 1
|
||||
|
||||
fields:
|
||||
content:
|
||||
type: tab
|
||||
title: PLUGIN_ADMIN.CONTENT
|
||||
|
||||
fields:
|
||||
frontmatter:
|
||||
classes: frontmatter
|
||||
type: editor
|
||||
label: PLUGIN_ADMIN.FRONTMATTER
|
||||
autofocus: true
|
||||
codemirror:
|
||||
mode: 'yaml'
|
||||
indentUnit: 4
|
||||
autofocus: true
|
||||
indentWithTabs: false
|
||||
lineNumbers: true
|
||||
styleActiveLine: true
|
||||
gutters: ['CodeMirror-lint-markers']
|
||||
lint: true
|
||||
|
||||
content:
|
||||
type: markdown
|
||||
|
||||
uploads:
|
||||
type: pagemedia
|
||||
label: PLUGIN_ADMIN.PAGE_MEDIA
|
||||
|
||||
|
||||
options:
|
||||
type: tab
|
||||
title: PLUGIN_ADMIN.OPTIONS
|
||||
|
||||
fields:
|
||||
|
||||
columns:
|
||||
type: columns
|
||||
|
||||
fields:
|
||||
column1:
|
||||
type: column
|
||||
|
||||
fields:
|
||||
|
||||
ordering:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
|
||||
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
folder:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.FILENAME
|
||||
validate:
|
||||
rule: slug
|
||||
required: true
|
||||
|
||||
route:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::rawRoute'
|
||||
options:
|
||||
'': PLUGIN_ADMIN.DEFAULT_OPTION_SELECT
|
||||
validate:
|
||||
required: true
|
||||
|
||||
name:
|
||||
type: select
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
|
||||
default: default
|
||||
data-options@: '\Grav\Common\Page\Pages::modularTypes'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
column2:
|
||||
type: column
|
||||
|
||||
fields:
|
||||
order:
|
||||
type: order
|
||||
label: PLUGIN_ADMIN.ORDERING
|
||||
|
||||
blueprint:
|
||||
type: blueprint
|
||||
@@ -1,11 +0,0 @@
|
||||
form:
|
||||
validation: loose
|
||||
fields:
|
||||
route:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::rawRoute'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
@@ -1,66 +0,0 @@
|
||||
rules:
|
||||
slug:
|
||||
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
|
||||
min: 1
|
||||
max: 200
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
fields:
|
||||
|
||||
section:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.ADD_PAGE
|
||||
|
||||
title:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.PAGE_TITLE
|
||||
help: PLUGIN_ADMIN.PAGE_TITLE_HELP
|
||||
validate:
|
||||
required: true
|
||||
|
||||
folder:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.FOLDER_NAME
|
||||
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
|
||||
validate:
|
||||
rule: slug
|
||||
required: true
|
||||
|
||||
route:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT_PAGE
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::getLastPageRoute'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
validate:
|
||||
required: true
|
||||
|
||||
name:
|
||||
type: select
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.PAGE_FILE
|
||||
help: PLUGIN_ADMIN.PAGE_FILE_HELP
|
||||
data-options@: '\Grav\Common\Page\Pages::types'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::getLastPageName'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
visible:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.VISIBLE
|
||||
help: PLUGIN_ADMIN.VISIBLE_HELP
|
||||
highlight: ''
|
||||
default: ''
|
||||
options:
|
||||
'': Auto
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
required: true
|
||||
|
||||
blueprint:
|
||||
type: blueprint
|
||||
@@ -1,35 +0,0 @@
|
||||
rules:
|
||||
slug:
|
||||
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
|
||||
min: 1
|
||||
max: 200
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
fields:
|
||||
|
||||
section:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.ADD_FOLDER
|
||||
|
||||
folder:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.FOLDER_NAME
|
||||
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
|
||||
validate:
|
||||
rule: slug
|
||||
required: true
|
||||
|
||||
route:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT_PAGE
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::getLastPageRoute'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
validate:
|
||||
required: true
|
||||
|
||||
blueprint:
|
||||
type: blueprint
|
||||
@@ -1,105 +0,0 @@
|
||||
rules:
|
||||
slug:
|
||||
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
|
||||
min: 1
|
||||
max: 200
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
fields:
|
||||
|
||||
tabs:
|
||||
type: tabs
|
||||
active: 1
|
||||
|
||||
fields:
|
||||
content:
|
||||
type: tab
|
||||
title: PLUGIN_ADMIN.CONTENT
|
||||
|
||||
fields:
|
||||
frontmatter:
|
||||
classes: frontmatter
|
||||
type: editor
|
||||
label: PLUGIN_ADMIN.FRONTMATTER
|
||||
autofocus: true
|
||||
codemirror:
|
||||
mode: 'yaml'
|
||||
indentUnit: 4
|
||||
autofocus: true
|
||||
indentWithTabs: false
|
||||
lineNumbers: true
|
||||
styleActiveLine: true
|
||||
gutters: ['CodeMirror-lint-markers']
|
||||
lint: true
|
||||
|
||||
content:
|
||||
type: markdown
|
||||
|
||||
uploads:
|
||||
type: pagemedia
|
||||
label: PLUGIN_ADMIN.PAGE_MEDIA
|
||||
|
||||
options:
|
||||
type: tab
|
||||
title: PLUGIN_ADMIN.OPTIONS
|
||||
|
||||
fields:
|
||||
|
||||
columns:
|
||||
type: columns
|
||||
|
||||
fields:
|
||||
column1:
|
||||
type: column
|
||||
|
||||
fields:
|
||||
|
||||
ordering:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
|
||||
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.ENABLED
|
||||
0: PLUGIN_ADMIN.DISABLED
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
folder:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.FOLDER_NAME
|
||||
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
|
||||
validate:
|
||||
rule: slug
|
||||
required: true
|
||||
|
||||
route:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\Admin\Admin::rawRoute'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
|
||||
name:
|
||||
type: select
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
|
||||
help: PLUGIN_ADMIN.DISPLAY_TEMPLATE_HELP
|
||||
default: default
|
||||
data-options@: '\Grav\Common\Page\Pages::types'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
column2:
|
||||
type: column
|
||||
|
||||
fields:
|
||||
order:
|
||||
type: order
|
||||
label: PLUGIN_ADMIN.ORDERING
|
||||
|
||||
blueprint:
|
||||
type: blueprint
|
||||
@@ -8,6 +8,13 @@ form:
|
||||
type: userinfo
|
||||
size: large
|
||||
|
||||
avatar:
|
||||
type: file
|
||||
size: large
|
||||
destination: 'user://accounts/avatars'
|
||||
multiple: false
|
||||
random_name: true
|
||||
|
||||
content:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.ACCOUNT
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.1.17');
|
||||
define('GRAV_VERSION', '1.2.2');
|
||||
define('GRAV_TESTING', false);
|
||||
define('DS', '/');
|
||||
|
||||
|
||||
@@ -255,28 +255,32 @@ class Assets
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a CSS asset.
|
||||
* Add an asset to its assembly.
|
||||
*
|
||||
* It checks for duplicates.
|
||||
* You may add more than one asset passing an array as argument.
|
||||
* The third argument may alternatively contain an array of options which take precedence over positional
|
||||
* arguments.
|
||||
*
|
||||
* @param mixed $asset
|
||||
* @param int $priority the priority, bigger comes first
|
||||
* @param bool $pipeline false if this should not be pipelined
|
||||
* @param null $group
|
||||
* @param array $assembly the array assembling the assets
|
||||
* @param mixed $asset
|
||||
* @param int $priority the priority, bigger comes first
|
||||
* @param bool $pipeline false if this should not be pipelined
|
||||
* @param string $loading how the asset is loaded (async/defer/inline, for CSS: only inline)
|
||||
* @param string $group name of the group
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addCss($asset, $priority = null, $pipeline = true, $group = null)
|
||||
public function addTo(&$assembly, $asset, $priority = null, $pipeline = true, $loading = null, $group = null)
|
||||
{
|
||||
if (is_array($asset)) {
|
||||
foreach ($asset as $a) {
|
||||
$this->addCss($a, $priority, $pipeline, $group);
|
||||
$this->addTo($assembly, $a, $priority, $pipeline, $loading, $group);
|
||||
}
|
||||
|
||||
return $this;
|
||||
} elseif (isset($this->collections[$asset])) {
|
||||
$this->addCss($this->collections[$asset], $priority, $pipeline, $group);
|
||||
$this->addTo($assembly, $this->collections[$asset], $priority, $pipeline, $loading, $group);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -297,15 +301,16 @@ class Assets
|
||||
'asset' => $asset,
|
||||
'remote' => $remote,
|
||||
'priority' => intval($priority ?: 10),
|
||||
'order' => count($this->css),
|
||||
'order' => count($assembly),
|
||||
'pipeline' => (bool) $pipeline,
|
||||
'loading' => $loading ?: '',
|
||||
'group' => $group ?: 'head',
|
||||
'modified' => $modified
|
||||
];
|
||||
|
||||
// check for dynamic array and merge with defaults
|
||||
if (func_num_args() > 1) {
|
||||
$dynamic_arg = func_get_arg(1);
|
||||
if (func_num_args() > 2) {
|
||||
$dynamic_arg = func_get_arg(2);
|
||||
if (is_array($dynamic_arg)) {
|
||||
$data = array_merge($data, $dynamic_arg);
|
||||
}
|
||||
@@ -313,17 +318,40 @@ class Assets
|
||||
|
||||
$key = md5($asset);
|
||||
if ($asset) {
|
||||
$this->css[$key] = $data;
|
||||
$assembly[$key] = $data;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a CSS asset.
|
||||
*
|
||||
* It checks for duplicates.
|
||||
* You may add more than one asset passing an array as argument.
|
||||
* The second argument may alternatively contain an array of options which take precedence over positional
|
||||
* arguments.
|
||||
*
|
||||
* @param mixed $asset
|
||||
* @param int $priority the priority, bigger comes first
|
||||
* @param bool $pipeline false if this should not be pipelined
|
||||
* @param string $group
|
||||
* @param string $loading how the asset is loaded (async/defer/inline, for CSS: only inline)
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addCss($asset, $priority = null, $pipeline = true, $group = null, $loading = null)
|
||||
{
|
||||
return $this->addTo($this->css, $asset, $priority, $pipeline, $loading, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a JavaScript asset.
|
||||
*
|
||||
* It checks for duplicates.
|
||||
* You may add more than one asset passing an array as argument.
|
||||
* The second argument may alternatively contain an array of options which take precedence over positional
|
||||
* arguments.
|
||||
*
|
||||
* @param mixed $asset
|
||||
* @param int $priority the priority, bigger comes first
|
||||
@@ -335,55 +363,7 @@ class Assets
|
||||
*/
|
||||
public function addJs($asset, $priority = null, $pipeline = true, $loading = null, $group = null)
|
||||
{
|
||||
if (is_array($asset)) {
|
||||
foreach ($asset as $a) {
|
||||
$this->addJs($a, $priority, $pipeline, $loading, $group);
|
||||
}
|
||||
|
||||
return $this;
|
||||
} elseif (isset($this->collections[$asset])) {
|
||||
$this->addJs($this->collections[$asset], $priority, $pipeline, $loading, $group);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$modified = false;
|
||||
$remote = $this->isRemoteLink($asset);
|
||||
if (!$remote) {
|
||||
$modified = $this->getLastModificationTime($asset);
|
||||
$asset = $this->buildLocalLink($asset);
|
||||
}
|
||||
|
||||
// Check for existence
|
||||
if ($asset === false) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'asset' => $asset,
|
||||
'remote' => $remote ,
|
||||
'priority' => intval($priority ?: 10),
|
||||
'order' => count($this->js),
|
||||
'pipeline' => (bool) $pipeline,
|
||||
'loading' => $loading ?: '',
|
||||
'group' => $group ?: 'head',
|
||||
'modified' => $modified
|
||||
];
|
||||
|
||||
// check for dynamic array and merge with defaults
|
||||
if (func_num_args() > 1) {
|
||||
$dynamic_arg = func_get_arg(1);
|
||||
if (is_array($dynamic_arg)) {
|
||||
$data = array_merge($data, $dynamic_arg);
|
||||
}
|
||||
}
|
||||
|
||||
$key = md5($asset);
|
||||
if ($asset) {
|
||||
$this->js[$key] = $data;
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $this->addTo($this->js, $asset, $priority, $pipeline, $loading, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -547,32 +527,54 @@ class Assets
|
||||
$this->css = array_reverse($this->css);
|
||||
$this->inline_css = array_reverse($this->inline_css);
|
||||
|
||||
$inlineGroup = array_key_exists('loading', $attributes) && $attributes['loading'] === 'inline';
|
||||
|
||||
$attributes = $this->attributes(array_merge(['type' => 'text/css', 'rel' => 'stylesheet'], $attributes));
|
||||
|
||||
$output = '';
|
||||
$inline_css = '';
|
||||
|
||||
if ($this->css_pipeline) {
|
||||
$pipeline_result = $this->pipelineCss($group);
|
||||
$pipeline_html = '<link href="' . $pipeline_result . '"' . $attributes . ' />' . "\n";
|
||||
$pipeline_result = $this->pipelineCss($group, !$inlineGroup);
|
||||
$pipeline_html = ($inlineGroup ? '' : '<link href="' . $pipeline_result . '"' . $attributes . ' />' . "\n");
|
||||
|
||||
if ($this->css_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
if ($inlineGroup) {
|
||||
$inline_css .= $pipeline_result;
|
||||
}
|
||||
else {
|
||||
$output .= $pipeline_html;
|
||||
}
|
||||
}
|
||||
foreach ($this->css_no_pipeline as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
||||
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
|
||||
if ($file['loading'] === 'inline') {
|
||||
$inline_css .= $this->gatherLinks([$file], CSS_ASSET) . "\n";
|
||||
}
|
||||
else {
|
||||
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
||||
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->css_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
if ($inlineGroup) {
|
||||
$inline_css .= $pipeline_result;
|
||||
}
|
||||
else {
|
||||
$output .= $pipeline_html;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($this->css as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
||||
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
|
||||
if ($inlineGroup || $file['loading'] === 'inline') {
|
||||
$inline_css .= $this->gatherLinks([$file], CSS_ASSET) . "\n";
|
||||
}
|
||||
else {
|
||||
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
|
||||
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,30 +628,52 @@ class Assets
|
||||
$this->js = array_reverse($this->js);
|
||||
$this->inline_js = array_reverse($this->inline_js);
|
||||
|
||||
$inlineGroup = array_key_exists('loading', $attributes) && $attributes['loading'] === 'inline';
|
||||
|
||||
$attributes = $this->attributes(array_merge(['type' => 'text/javascript'], $attributes));
|
||||
|
||||
$output = '';
|
||||
$inline_js = '';
|
||||
|
||||
if ($this->js_pipeline) {
|
||||
$pipeline_result = $this->pipelineJs($group);
|
||||
$pipeline_html = '<script src="' . $pipeline_result . '"' . $attributes . ' ></script>' . "\n";
|
||||
$pipeline_result = $this->pipelineJs($group, !$inlineGroup);
|
||||
$pipeline_html = ($inlineGroup ? '' : '<script src="' . $pipeline_result . '"' . $attributes . ' ></script>' . "\n");
|
||||
|
||||
if ($this->js_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
if ($inlineGroup) {
|
||||
$inline_js .= $pipeline_result;
|
||||
}
|
||||
else {
|
||||
$output .= $pipeline_html;
|
||||
}
|
||||
}
|
||||
foreach ($this->js_no_pipeline as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
|
||||
if ($file['loading'] === 'inline') {
|
||||
$inline_js .= $this->gatherLinks([$file], JS_ASSET) . "\n";
|
||||
}
|
||||
else {
|
||||
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->js_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
if ($inlineGroup) {
|
||||
$inline_js .= $pipeline_result;
|
||||
}
|
||||
else {
|
||||
$output .= $pipeline_html;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($this->js as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
|
||||
if ($inlineGroup || $file['loading'] === 'inline') {
|
||||
$inline_js .= $this->gatherLinks([$file], JS_ASSET) . "\n";
|
||||
}
|
||||
else {
|
||||
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -672,10 +696,11 @@ class Assets
|
||||
* Minify and concatenate CSS
|
||||
*
|
||||
* @param string $group
|
||||
* @param bool $returnURL true if pipeline should return the URL, otherwise the content
|
||||
*
|
||||
* @return bool|string
|
||||
* @return bool|string URL or generated content if available, else false
|
||||
*/
|
||||
protected function pipelineCss($group = 'head')
|
||||
protected function pipelineCss($group = 'head', $returnURL = true)
|
||||
{
|
||||
// temporary list of assets to pipeline
|
||||
$temp_css = [];
|
||||
@@ -695,9 +720,14 @@ class Assets
|
||||
$this->css_no_pipeline = json_decode(file_get_contents($this->assets_dir . $inline_file), true);
|
||||
}
|
||||
|
||||
// If pipeline exist return it
|
||||
// If pipeline exist return its URL or content
|
||||
if (file_exists($this->assets_dir . $file)) {
|
||||
return $relative_path . $this->getTimestamp();
|
||||
if ($returnURL) {
|
||||
return $relative_path . $this->getTimestamp();
|
||||
}
|
||||
else {
|
||||
return file_get_contents($this->assets_dir . $file) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any non-pipeline files
|
||||
@@ -744,7 +774,12 @@ class Assets
|
||||
if (strlen(trim($buffer)) > 0) {
|
||||
file_put_contents($this->assets_dir . $file, $buffer);
|
||||
|
||||
return $relative_path . $this->getTimestamp();
|
||||
if ($returnURL) {
|
||||
return $relative_path . $this->getTimestamp();
|
||||
}
|
||||
else {
|
||||
return $buffer . "\n";
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -754,10 +789,11 @@ class Assets
|
||||
* Minify and concatenate JS files.
|
||||
*
|
||||
* @param string $group
|
||||
* @param bool $returnURL true if pipeline should return the URL, otherwise the content
|
||||
*
|
||||
* @return string
|
||||
* @return bool|string URL or generated content if available, else false
|
||||
*/
|
||||
protected function pipelineJs($group = 'head')
|
||||
protected function pipelineJs($group = 'head', $returnURL = true)
|
||||
{
|
||||
// temporary list of assets to pipeline
|
||||
$temp_js = [];
|
||||
@@ -777,9 +813,14 @@ class Assets
|
||||
$this->js_no_pipeline = json_decode(file_get_contents($this->assets_dir . $inline_file), true);
|
||||
}
|
||||
|
||||
// If pipeline exist return it
|
||||
// If pipeline exist return its URL or content
|
||||
if (file_exists($this->assets_dir . $file)) {
|
||||
return $relative_path . $this->getTimestamp();
|
||||
if ($returnURL) {
|
||||
return $relative_path . $this->getTimestamp();
|
||||
}
|
||||
else {
|
||||
return file_get_contents($this->assets_dir . $file) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any non-pipeline files
|
||||
@@ -816,7 +857,12 @@ class Assets
|
||||
if (strlen(trim($buffer)) > 0) {
|
||||
file_put_contents($this->assets_dir . $file, $buffer);
|
||||
|
||||
return $relative_path . $this->getTimestamp();
|
||||
if ($returnURL) {
|
||||
return $relative_path . $this->getTimestamp();
|
||||
}
|
||||
else {
|
||||
return $buffer . "\n";
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -1255,13 +1301,8 @@ class Assets
|
||||
|
||||
$old_url = $matches[2];
|
||||
|
||||
// ensure this is not a data url
|
||||
if (strpos($old_url, 'data:') === 0) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
// ensure this is not a remote url
|
||||
if ($this->isRemoteLink($old_url)) {
|
||||
// Ensure link is not rooted to webserver, a data URL, or to a remote host
|
||||
if (Utils::startsWith($old_url, '/') || Utils::startsWith($old_url, 'data:') || $this->isRemoteLink($old_url)) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -599,9 +599,11 @@ class GPM extends Iterator
|
||||
*/
|
||||
public static function getPackageName($source)
|
||||
{
|
||||
$ignore_yaml_files = ['blueprints', 'languages'];
|
||||
|
||||
foreach (glob($source . "*.yaml") as $filename) {
|
||||
$name = strtolower(basename($filename, '.yaml'));
|
||||
if ($name == 'blueprints') {
|
||||
if (in_array($name, $ignore_yaml_files)) {
|
||||
continue;
|
||||
}
|
||||
return $name;
|
||||
|
||||
@@ -203,6 +203,15 @@ class Language
|
||||
}
|
||||
}
|
||||
|
||||
// repeat if not found, try base language only - fixes Safari sending the language code always
|
||||
// with a locale (e.g. it-it or fr-fr)
|
||||
foreach ($preferred as $lang) {
|
||||
$lang = substr($lang, 0, 2);
|
||||
if ($this->validate($lang)) {
|
||||
$this->active = $lang;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +141,12 @@ class Media extends AbstractMedia
|
||||
|
||||
foreach ($types['alternative'] as $altMedium) {
|
||||
if ($altMedium['file'] != $medium) {
|
||||
$ratio = $altMedium['file']->get('width') / $medium->get('width');
|
||||
$medium->addAlternative($ratio, $altMedium['file']);
|
||||
$altWidth = $altMedium['file']->get('width');
|
||||
$medWidth = $medium->get('width');
|
||||
if ($altWidth && $medWidth) {
|
||||
$ratio = $altWidth / $medWidth;
|
||||
$medium->addAlternative($ratio, $altMedium['file']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ class Page
|
||||
protected $hide_home_route;
|
||||
protected $ssl;
|
||||
protected $template_format;
|
||||
protected $debugger;
|
||||
|
||||
/**
|
||||
* @var Page Unmodified (original) version of the page. Used for copying and moving the page.
|
||||
@@ -424,6 +425,9 @@ class Page
|
||||
if (isset($this->header->template_format)) {
|
||||
$this->template_format = $this->header->template_format;
|
||||
}
|
||||
if (isset($this->header->debugger)) {
|
||||
$this->debugger = (bool)$this->header->debugger;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->header;
|
||||
@@ -566,7 +570,8 @@ class Page
|
||||
|
||||
|
||||
$process_markdown = $this->shouldProcess('markdown');
|
||||
$process_twig = $this->shouldProcess('twig');
|
||||
$process_twig = $this->shouldProcess('twig') || $this->modularTwig() ;
|
||||
|
||||
$cache_enable = isset($this->header->cache_enable) ? $this->header->cache_enable : $config->get('system.cache.enabled',
|
||||
true);
|
||||
$twig_first = isset($this->header->twig_first) ? $this->header->twig_first : $config->get('system.pages.twig_first',
|
||||
@@ -799,6 +804,9 @@ class Page
|
||||
if ($name == 'folder') {
|
||||
return preg_replace(PAGE_ORDER_PREFIX_REGEX, '', $this->folder);
|
||||
}
|
||||
if ($name == 'slug') {
|
||||
return $this->slug();
|
||||
}
|
||||
if ($name == 'name') {
|
||||
$language = $this->language() ? '.' . $this->language() : '';
|
||||
$name_val = str_replace($language . '.md', '', $this->name());
|
||||
@@ -882,12 +890,12 @@ class Page
|
||||
/**
|
||||
* Save page if there's a file assigned to it.
|
||||
*
|
||||
* @param bool $reorder Internal use.
|
||||
* @param bool|mixed $reorder Internal use.
|
||||
*/
|
||||
public function save($reorder = true)
|
||||
{
|
||||
// Perform move, copy or reordering if needed.
|
||||
$this->doRelocation($reorder);
|
||||
// Perform move, copy [or reordering] if needed.
|
||||
$this->doRelocation();
|
||||
|
||||
$file = $this->file();
|
||||
if ($file) {
|
||||
@@ -896,6 +904,13 @@ class Page
|
||||
$file->markdown($this->raw_content);
|
||||
$file->save();
|
||||
}
|
||||
|
||||
// Perform reorder if required
|
||||
if ($reorder && is_array($reorder)) {
|
||||
$this->doReorder($reorder);
|
||||
}
|
||||
|
||||
$this->_original = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1111,7 +1126,7 @@ class Page
|
||||
*/
|
||||
public function childType()
|
||||
{
|
||||
return isset($this->header->child_type) ? (string)$this->header->child_type : 'default';
|
||||
return isset($this->header->child_type) ? (string)$this->header->child_type : '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1373,6 +1388,20 @@ class Page
|
||||
return $this->process;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of the debugger override etting for this page
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function debugger()
|
||||
{
|
||||
if (isset($this->debugger) && $this->debugger === false) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to merge page metadata tags and build an array of Metadata objects
|
||||
* that can then be rendered in the page.
|
||||
@@ -2027,7 +2056,6 @@ class Page
|
||||
if ($var !== null) {
|
||||
$this->modular_twig = (bool)$var;
|
||||
if ($var) {
|
||||
$this->process['twig'] = true;
|
||||
$this->visible(false);
|
||||
// some routable logic
|
||||
if (empty($this->header->routable)) {
|
||||
@@ -2254,6 +2282,74 @@ class Page
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to return an ancestor page.
|
||||
*
|
||||
* @param string $url The url of the page
|
||||
* @param bool $lookup Name of the parent folder
|
||||
*
|
||||
* @return \Grav\Common\Page\Page page you were looking for if it exists
|
||||
*/
|
||||
public function ancestor($lookup = null)
|
||||
{
|
||||
/** @var Pages $pages */
|
||||
$pages = Grav::instance()['pages'];
|
||||
|
||||
return $pages->ancestor($this->route, $lookup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to return an ancestor page to inherit from. The current
|
||||
* page object is returned.
|
||||
*
|
||||
* @param string $field Name of the parent folder
|
||||
*
|
||||
* @return Page
|
||||
*/
|
||||
public function inherited($field)
|
||||
{
|
||||
list($inherited, $currentParams) = $this->getInheritedParams($field);
|
||||
|
||||
$this->modifyHeader($field, $currentParams);
|
||||
|
||||
return $inherited;
|
||||
}
|
||||
/**
|
||||
* Helper method to return an ancestor field only to inherit from. The
|
||||
* first occurrence of an ancestor field will be returned if at all.
|
||||
*
|
||||
* @param string $field Name of the parent folder
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function inheritedField($field)
|
||||
{
|
||||
list($inherited, $currentParams) = $this->getInheritedParams($field);
|
||||
|
||||
return $currentParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that contains shared logic for inherited() and inheritedField()
|
||||
*
|
||||
* @param string $field Name of the parent folder
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getInheritedParams($field)
|
||||
{
|
||||
$pages = Grav::instance()['pages'];
|
||||
|
||||
/** @var Pages $pages */
|
||||
$inherited = $pages->inherited($this->route, $field);
|
||||
$inheritedParams = (array) $inherited->value('header.' . $field);
|
||||
$currentParams = (array) $this->value('header.' . $field);
|
||||
if($inheritedParams && is_array($inheritedParams)) {
|
||||
$currentParams = array_replace_recursive($inheritedParams, $currentParams);
|
||||
}
|
||||
return [$inherited, $currentParams];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to return a page.
|
||||
*
|
||||
@@ -2588,65 +2684,62 @@ class Page
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves or copies the page in filesystem.
|
||||
* Reorders all siblings according to a defined order
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param bool $reorder
|
||||
*
|
||||
* @throws Exception
|
||||
* @param $new_order
|
||||
*/
|
||||
protected function doRelocation($reorder)
|
||||
protected function doReorder($new_order)
|
||||
{
|
||||
if (!$this->_original) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do reordering.
|
||||
if ($reorder && $this->order() != $this->_original->order()) {
|
||||
/** @var Pages $pages */
|
||||
$pages = Grav::instance()['pages'];
|
||||
$pages = Grav::instance()['pages'];
|
||||
$pages->init();
|
||||
|
||||
$parent = $this->parent();
|
||||
$this->_original->path($this->path());
|
||||
|
||||
// Extract visible children from the parent page.
|
||||
$list = [];
|
||||
/** @var Page $page */
|
||||
foreach ($parent->children()->visible() as $page) {
|
||||
if ($page->order()) {
|
||||
$list[$page->slug] = $page->path();
|
||||
}
|
||||
}
|
||||
$siblings = $this->parent()->children();
|
||||
$siblings->order('slug', 'asc', $new_order);
|
||||
|
||||
// If page was moved, take it out of the list.
|
||||
if ($this->_action == 'move') {
|
||||
unset($list[$this->slug()]);
|
||||
}
|
||||
$counter = 0;
|
||||
|
||||
$list = array_values($list);
|
||||
// Reorder all moved pages.
|
||||
foreach ($siblings as $slug => $page) {
|
||||
$order = intval(trim($page->order(),'.'));
|
||||
$counter++;
|
||||
|
||||
// Then add it back to the new location (if needed).
|
||||
if ($this->order()) {
|
||||
array_splice($list, min($this->order() - 1, count($list)), 0, [$this->path()]);
|
||||
}
|
||||
|
||||
// Reorder all moved pages.
|
||||
foreach ($list as $order => $path) {
|
||||
if ($path == $this->path()) {
|
||||
if ($order) {
|
||||
if ($page->path() == $this->path() && $this->folderExists()) {
|
||||
// Handle current page; we do want to change ordering number, but nothing else.
|
||||
$this->order($order + 1);
|
||||
$this->order($counter);
|
||||
$this->save(false);
|
||||
} else {
|
||||
// Handle all the other pages.
|
||||
$page = $pages->get($path);
|
||||
|
||||
if ($page && $page->exists() && !$page->_action && $page->order() != $order + 1) {
|
||||
$page = $page->move($parent);
|
||||
$page->order($order + 1);
|
||||
$page = $pages->get($page->path());
|
||||
if ($page && $page->folderExists() && !$page->_action) {
|
||||
$page = $page->move($this->parent());
|
||||
$page->order($counter);
|
||||
$page->save(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves or copies the page in filesystem.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function doRelocation()
|
||||
{
|
||||
if (!$this->_original) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_dir($this->_original->path())) {
|
||||
if ($this->_action == 'move') {
|
||||
Folder::move($this->_original->path(), $this->path());
|
||||
@@ -2662,7 +2755,6 @@ class Page
|
||||
}
|
||||
}
|
||||
|
||||
$this->_original = null;
|
||||
}
|
||||
|
||||
protected function setPublishState()
|
||||
|
||||
@@ -291,36 +291,86 @@ class Pages
|
||||
return new Collection($children, [], $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a page ancestor.
|
||||
*
|
||||
* @param string $route The relative URL of the page
|
||||
* @param string $path The relative path of the ancestor folder
|
||||
*
|
||||
* @return Page|null
|
||||
*/
|
||||
public function ancestor($route, $path = null)
|
||||
{
|
||||
if (!is_null($path)) {
|
||||
|
||||
$page = $this->dispatch($route, true);
|
||||
|
||||
if ($page->path() == $path) {
|
||||
return $page;
|
||||
} elseif (!$page->parent()->root()) {
|
||||
return $this->ancestor($page->parent()->route(), $path);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a page ancestor trait.
|
||||
*
|
||||
* @param string $route The relative route of the page
|
||||
* @param string $field The field name of the ancestor to query for
|
||||
*
|
||||
* @return Page|null
|
||||
*/
|
||||
public function inherited($route, $field = null)
|
||||
{
|
||||
if (!is_null($field)) {
|
||||
|
||||
$page = $this->dispatch($route, true);
|
||||
|
||||
$ancestorField = $page->parent()->value('header.' . $field);
|
||||
|
||||
if ($ancestorField != null) {
|
||||
return $page->parent();
|
||||
} elseif (!$page->parent()->root()) {
|
||||
return $this->inherited($page->parent()->route(), $field);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* alias method to return find a page.
|
||||
*
|
||||
* @param string $url The relative URL of the page
|
||||
* @param string $route The relative URL of the page
|
||||
* @param bool $all
|
||||
*
|
||||
* @return Page|null
|
||||
*/
|
||||
public function find($url, $all = false)
|
||||
public function find($route, $all = false)
|
||||
{
|
||||
return $this->dispatch($url, $all, false);
|
||||
return $this->dispatch($route, $all, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch URI to a page.
|
||||
*
|
||||
* @param string $url The relative URL of the page
|
||||
* @param string $route The relative URL of the page
|
||||
* @param bool $all
|
||||
*
|
||||
* @param bool $redirect
|
||||
* @return Page|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function dispatch($url, $all = false, $redirect = true)
|
||||
public function dispatch($route, $all = false, $redirect = true)
|
||||
{
|
||||
// Fetch page if there's a defined route to it.
|
||||
$page = isset($this->routes[$url]) ? $this->get($this->routes[$url]) : null;
|
||||
$page = isset($this->routes[$route]) ? $this->get($this->routes[$route]) : null;
|
||||
// Try without trailing slash
|
||||
if (!$page && Utils::endsWith($url, '/')) {
|
||||
$page = isset($this->routes[rtrim($url, '/')]) ? $this->get($this->routes[rtrim($url, '/')]) : null;
|
||||
if (!$page && Utils::endsWith($route, '/')) {
|
||||
$page = isset($this->routes[rtrim($route, '/')]) ? $this->get($this->routes[rtrim($route, '/')]) : null;
|
||||
}
|
||||
|
||||
// Are we in the admin? this is important!
|
||||
@@ -340,13 +390,13 @@ class Pages
|
||||
$config = $this->grav['config'];
|
||||
|
||||
// See if route matches one in the site configuration
|
||||
$route = $config->get("site.routes.{$url}");
|
||||
if ($route) {
|
||||
$page = $this->dispatch($route, $all);
|
||||
$site_route = $config->get("site.routes.{$route}");
|
||||
if ($site_route) {
|
||||
$page = $this->dispatch($site_route, $all);
|
||||
} else {
|
||||
// Try Regex style redirects
|
||||
$uri = $this->grav['uri'];
|
||||
$source_url = $url;
|
||||
$source_url = $route;
|
||||
$extension = $uri->extension();
|
||||
if (isset($extension) && !Utils::endsWith($uri->url(), $extension)) {
|
||||
$source_url.= '.' . $extension;
|
||||
|
||||
@@ -39,6 +39,11 @@ class PageServiceProvider implements ServiceProviderInterface
|
||||
/** @var Language $language */
|
||||
$language = $c['language'];
|
||||
|
||||
// some debugger override logic
|
||||
if ($page->debugger() === false) {
|
||||
Grav::instance()['debugger']->enabled(false);
|
||||
}
|
||||
|
||||
if ($c['config']->get('system.force_ssl')) {
|
||||
if (!isset($_SERVER['HTTPS']) || $_SERVER["HTTPS"] != "on") {
|
||||
$url = "https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
|
||||
|
||||
@@ -311,17 +311,23 @@ class Themes extends Iterator
|
||||
*/
|
||||
protected function autoloadTheme($class)
|
||||
{
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $this->grav['locator'];
|
||||
|
||||
$prefix = "Grav\\Theme";
|
||||
if (false !== strpos($class, $prefix)) {
|
||||
// Remove prefix from class
|
||||
$class = substr($class, strlen($prefix));
|
||||
|
||||
// Replace namespace tokens to directory separators
|
||||
// Try Old style theme classes
|
||||
$path = strtolower(ltrim(preg_replace('#\\\|_(?!.+\\\)#', '/', $class), '/'));
|
||||
$file = $locator->findResource("themes://{$path}/{$path}.php");
|
||||
$file = $this->grav['locator']->findResource("themes://{$path}/{$path}.php");
|
||||
|
||||
// Load class
|
||||
if (file_exists($file)) {
|
||||
return include_once($file);
|
||||
}
|
||||
|
||||
// Replace namespace tokens to directory separators
|
||||
$path = $this->grav['inflector']->hyphenize(ltrim($class,"\\"));
|
||||
$file = $this->grav['locator']->findResource("themes://{$path}/{$path}.php");
|
||||
|
||||
// Load class
|
||||
if (file_exists($file)) {
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Grav\Common\Twig;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Language\Language;
|
||||
use Grav\Common\Language\LanguageCodes;
|
||||
use Grav\Common\Page\Page;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
@@ -173,7 +174,7 @@ class Twig
|
||||
'theme_dir' => $locator->findResource('theme://'),
|
||||
'theme_url' => $this->grav['base_url'] . '/' . $locator->findResource('theme://', false),
|
||||
'html_lang' => $this->grav['language']->getActive() ?: $config->get('site.default_lang', 'en'),
|
||||
|
||||
'language_codes' => new LanguageCodes,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -229,25 +230,22 @@ class Twig
|
||||
$twig_vars['header'] = $item->header();
|
||||
|
||||
$local_twig = clone($this->twig);
|
||||
$modular_twig = $item->modularTwig();
|
||||
$process_twig = isset($item->header()->process['twig']) ? $item->header()->process['twig'] : false;
|
||||
|
||||
$output = '';
|
||||
|
||||
try {
|
||||
// Process Modular Twig
|
||||
if ($modular_twig) {
|
||||
if ($item->modularTwig()) {
|
||||
$twig_vars['content'] = $content;
|
||||
$template = $item->template() . TEMPLATE_EXT;
|
||||
$output = $content = $local_twig->render($template, $twig_vars);
|
||||
}
|
||||
|
||||
// Process in-page Twig
|
||||
if (!$modular_twig || ($modular_twig && $process_twig)) {
|
||||
if ($item->shouldProcess('twig')) {
|
||||
$name = '@Page:' . $item->path();
|
||||
$this->setTemplate($name, $content);
|
||||
$output = $local_twig->render($name, $twig_vars);
|
||||
}
|
||||
|
||||
} catch (\Twig_Error_Loader $e) {
|
||||
throw new \RuntimeException($e->getRawMessage(), 404, $e);
|
||||
}
|
||||
|
||||
@@ -104,7 +104,8 @@ class TwigExtension extends \Twig_Extension
|
||||
new \Twig_simpleFunction('authorize', [$this, 'authorize']),
|
||||
new \Twig_SimpleFunction('debug', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
|
||||
new \Twig_SimpleFunction('dump', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
|
||||
new \Twig_SimpleFunction('evaluate', [$this, 'evaluateFunc']),
|
||||
new \Twig_SimpleFunction('evaluate', [$this, 'evaluateStringFunc'], ['needs_context' => true, 'needs_environment' => true]),
|
||||
new \Twig_SimpleFunction('evaluate_twig', [$this, 'evaluateTwigFunc'], ['needs_context' => true, 'needs_environment' => true]),
|
||||
new \Twig_SimpleFunction('gist', [$this, 'gistFunc']),
|
||||
new \Twig_SimpleFunction('nonce_field', [$this, 'nonceFieldFunc']),
|
||||
new \Twig_simpleFunction('random_string', [$this, 'randomStringFunc']),
|
||||
@@ -118,6 +119,7 @@ class TwigExtension extends \Twig_Extension
|
||||
new \Twig_SimpleFunction('get_cookie', [$this, 'getCookie']),
|
||||
new \Twig_SimpleFunction('redirect_me', [$this, 'redirectFunc']),
|
||||
new \Twig_SimpleFunction('range', [$this, 'rangeFunc']),
|
||||
new \Twig_SimpleFunction('isajaxrequest', [$this, 'isAjaxFunc']),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -569,15 +571,22 @@ class TwigExtension extends \Twig_Extension
|
||||
$domain = true;
|
||||
}
|
||||
|
||||
if (Grav::instance()['uri']->isExternal($input)) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
if (strpos((string)$input, '://')) {
|
||||
$input = ltrim((string)$input, '/');
|
||||
|
||||
if (Utils::contains((string)$input, '://')) {
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $this->grav['locator'];
|
||||
|
||||
|
||||
|
||||
// Get relative path to the resource (or false if not found).
|
||||
$resource = $locator->findResource((string)$input, false);
|
||||
$resource = $locator->findResource($input, false);
|
||||
} else {
|
||||
$resource = (string)$input;
|
||||
$resource = $input;
|
||||
}
|
||||
|
||||
/** @var Uri $uri */
|
||||
@@ -587,22 +596,51 @@ class TwigExtension extends \Twig_Extension
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a string
|
||||
* This function will evaluate Twig $twig through the $environment, and return its results.
|
||||
*
|
||||
* @example {{ evaluate('grav.language.getLanguage') }}
|
||||
*
|
||||
* @param string $input String to be evaluated
|
||||
*
|
||||
* @return string Returns the evaluated string
|
||||
* @param \Twig_Environment $environment
|
||||
* @param array $context
|
||||
* @param string $twig
|
||||
* @return mixed
|
||||
*/
|
||||
public function evaluateFunc($input)
|
||||
{
|
||||
if (!$input) { //prevent an obscure Twig error if $input is not set
|
||||
$input = '""';
|
||||
}
|
||||
return $this->grav['twig']->processString("{{ $input }}");
|
||||
public function evaluateTwigFunc( \Twig_Environment $environment, $context, $twig ) {
|
||||
$loader = $environment->getLoader( );
|
||||
|
||||
$parsed = $this->parseString( $environment, $context, $twig );
|
||||
|
||||
$environment->setLoader( $loader );
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will evaluate a $string through the $environment, and return its results.
|
||||
*
|
||||
* @param \Twig_Environment $environment
|
||||
* @param $context
|
||||
* @param $string
|
||||
* @return mixed
|
||||
*/
|
||||
public function evaluateStringFunc(\Twig_Environment $environment, $context, $string )
|
||||
{
|
||||
$parsed = $this->evaluateTwigFunc($environment, $context, "{{ $string }}");
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parser for the environment to Twig_Loader_String, and parsed the string $string.
|
||||
*
|
||||
* @param \Twig_Environment $environment
|
||||
* @param array $context
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
protected function parseString( \Twig_Environment $environment, $context, $string ) {
|
||||
$environment->setLoader( new \Twig_Loader_String( ) );
|
||||
return $environment->render( $string, $context );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Based on Twig_Extension_Debug / twig_var_dump
|
||||
* (c) 2011 Fabien Potencier
|
||||
@@ -855,4 +893,17 @@ class TwigExtension extends \Twig_Extension
|
||||
{
|
||||
return range($start, $end, $step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if HTTP_X_REQUESTED_WITH has been set to xmlhttprequest,
|
||||
* in which case we may unsafely assume ajax. Non critical use only.
|
||||
*
|
||||
* @return true if HTTP_X_REQUESTED_WITH exists and has been set to xmlhttprequest
|
||||
*/
|
||||
public function isAjaxFunc()
|
||||
{
|
||||
return (
|
||||
!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
|
||||
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,4 +239,20 @@ class User extends Data
|
||||
{
|
||||
return $this->authorize($action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the User's avatar URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function avatarUrl()
|
||||
{
|
||||
if ($this->avatar) {
|
||||
$avatar = $this->avatar;
|
||||
$avatar = array_shift($avatar);
|
||||
return Grav::instance()['base_url'] . '/' . $avatar['path'];
|
||||
} else {
|
||||
return 'https://www.gravatar.com/avatar/' . md5($this->email);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use Grav\Common\GPM\Installer;
|
||||
use Grav\Common\GPM\Response;
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
|
||||
class DirectInstallCommand extends ConsoleCommand
|
||||
@@ -31,7 +32,20 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
->addArgument(
|
||||
'package-file',
|
||||
InputArgument::REQUIRED,
|
||||
'The local location or remote URL to an installable package file'
|
||||
'Installable package local <path> or remote <URL>. Can install specific version'
|
||||
)
|
||||
->addOption(
|
||||
'all-yes',
|
||||
'y',
|
||||
InputOption::VALUE_NONE,
|
||||
'Assumes yes (or best approach) instead of prompting'
|
||||
)
|
||||
->addOption(
|
||||
'destination',
|
||||
'd',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The destination where the package should be installed at. By default this would be where the grav instance has been launched from',
|
||||
GRAV_ROOT
|
||||
)
|
||||
->setDescription("Installs Grav, plugin, or theme directly from a file or a URL")
|
||||
->setHelp('The <info>direct-install</info> command installs Grav, plugin, or theme directly from a file or a URL');
|
||||
@@ -42,12 +56,26 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
*/
|
||||
protected function serve()
|
||||
{
|
||||
// Making sure the destination is usable
|
||||
$this->destination = realpath($this->input->getOption('destination'));
|
||||
|
||||
if (
|
||||
!Installer::isGravInstance($this->destination) ||
|
||||
!Installer::isValidDestination($this->destination, [Installer::EXISTS, Installer::IS_LINK])
|
||||
) {
|
||||
$this->output->writeln("<red>ERROR</red>: " . Installer::lastErrorMsg());
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$this->all_yes = $this->input->getOption('all-yes');
|
||||
|
||||
$package_file = $this->input->getArgument('package-file');
|
||||
|
||||
$helper = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion('Are you sure you want to direct-install <cyan>'.$package_file.'</cyan> [y|N] ', false);
|
||||
|
||||
$answer = $helper->ask($this->input, $this->output, $question);
|
||||
$answer = $this->all_yes ? true : $helper->ask($this->input, $this->output, $question);
|
||||
|
||||
if (!$answer) {
|
||||
$this->output->writeln("exiting...");
|
||||
@@ -72,7 +100,7 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
$this->output->writeln('');
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if ($zip) {
|
||||
$this->output->write("\x0D");
|
||||
$this->output->write(" |- Downloading package... 100%");
|
||||
@@ -97,6 +125,8 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
if (!$extracted) {
|
||||
$this->output->write("\x0D");
|
||||
$this->output->writeln(" |- Extracting package... <red>failed</red>");
|
||||
Folder::delete($tmp_source);
|
||||
Folder::delete($tmp_zip);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -109,6 +139,8 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
if (!$type) {
|
||||
$this->output->writeln(" '- <red>ERROR: Not a valid Grav package</red>");
|
||||
$this->output->writeln('');
|
||||
Folder::delete($tmp_source);
|
||||
Folder::delete($tmp_zip);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -117,22 +149,27 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
if (isset($blueprint['dependencies'])) {
|
||||
$depencencies = [];
|
||||
foreach ($blueprint['dependencies'] as $dependency) {
|
||||
if (is_array($dependency) && isset($dependency['name'])) {
|
||||
$depencencies[] = $dependency['name'];
|
||||
if (is_array($dependency)){
|
||||
if (isset($dependency['name'])) {
|
||||
$depencencies[] = $dependency['name'];
|
||||
}
|
||||
if (isset($dependency['github'])) {
|
||||
$depencencies[] = $dependency['github'];
|
||||
}
|
||||
} else {
|
||||
$depencencies[] = $dependency;
|
||||
$depencencies[] = $dependency;
|
||||
}
|
||||
}
|
||||
$this->output->writeln(" |- Dependencies found... <cyan>[" . implode(',', $depencencies) . "]</cyan>");
|
||||
|
||||
|
||||
|
||||
$question = new ConfirmationQuestion(" | '- Dependencies will not be satisfied. Continue ? [y|N] ", false);
|
||||
$answer = $helper->ask($this->input, $this->output, $question);
|
||||
$answer = $this->all_yes ? true : $helper->ask($this->input, $this->output, $question);
|
||||
|
||||
if (!$answer) {
|
||||
$this->output->writeln("exiting...");
|
||||
$this->output->writeln('');
|
||||
Folder::delete($tmp_source);
|
||||
Folder::delete($tmp_zip);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -147,6 +184,8 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
$this->output->writeln(" |- Checking destination... <yellow>symbolic link</yellow>");
|
||||
$this->output->writeln(" '- <red>ERROR: symlinks found...</red> <yellow>" . GRAV_ROOT."</yellow>");
|
||||
$this->output->writeln('');
|
||||
Folder::delete($tmp_source);
|
||||
Folder::delete($tmp_zip);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -161,6 +200,8 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
if (!$name) {
|
||||
$this->output->writeln("<red>ERROR: Name could not be determined.</red> Please specify with --name|-n");
|
||||
$this->output->writeln('');
|
||||
Folder::delete($tmp_source);
|
||||
Folder::delete($tmp_zip);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -175,6 +216,8 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
$this->output->writeln(" |- Checking destination... <yellow>symbolic link</yellow>");
|
||||
$this->output->writeln(" '- <red>ERROR: symlink found...</red> <yellow>" . GRAV_ROOT . DS . $install_path . '</yellow>');
|
||||
$this->output->writeln('');
|
||||
Folder::delete($tmp_source);
|
||||
Folder::delete($tmp_zip);
|
||||
exit;
|
||||
|
||||
} else {
|
||||
@@ -184,7 +227,16 @@ class DirectInstallCommand extends ConsoleCommand
|
||||
|
||||
$this->output->write(" |- Installing package... ");
|
||||
|
||||
Installer::install($zip, GRAV_ROOT, ['install_path' => $install_path, 'theme' => (($type == 'theme')), 'is_update' => $is_update], $extracted);
|
||||
Installer::install(
|
||||
$zip,
|
||||
$this->destination,
|
||||
$options = [
|
||||
'install_path' => $install_path,
|
||||
'theme' => (($type == 'theme')),
|
||||
'is_update' => $is_update
|
||||
],
|
||||
$extracted
|
||||
);
|
||||
}
|
||||
|
||||
Folder::delete($tmp_source);
|
||||
|
||||
@@ -80,7 +80,7 @@ class InstallCommand extends ConsoleCommand
|
||||
->addArgument(
|
||||
'package',
|
||||
InputArgument::IS_ARRAY | InputArgument::REQUIRED,
|
||||
'The package(s) that are desired to be installed. Use the "index" command for a list of packages'
|
||||
'Package(s) to install. Use "bin/gpm index" to list packages. Use "bin/gpm direct-install" to install a specific version'
|
||||
)
|
||||
->setDescription("Performs the installation of plugins and themes")
|
||||
->setHelp('The <info>install</info> command allows to install plugins and themes');
|
||||
@@ -563,6 +563,7 @@ class InstallCommand extends ConsoleCommand
|
||||
$tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true);
|
||||
$this->tmp = $tmp_dir . '/Grav-' . uniqid();
|
||||
$filename = $package->slug . basename($package->zipball_url);
|
||||
$filename = preg_replace('/[\\\\\/:"*?&<>|]+/mi', '-', $filename);
|
||||
$query = '';
|
||||
|
||||
if ($package->premium) {
|
||||
|
||||
40
tests/functional/Grav/Console/DirectInstallCommandTest.php
Normal file
40
tests/functional/Grav/Console/DirectInstallCommandTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Codeception\Util\Fixtures;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Console\Gpm\DirectInstallCommand;
|
||||
|
||||
|
||||
/**
|
||||
* Class DirectInstallCommandTest
|
||||
*/
|
||||
class DirectInstallCommandTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
/** @var Grav $grav */
|
||||
protected $grav;
|
||||
|
||||
/** @var DirectInstallCommand */
|
||||
protected $directInstall;
|
||||
|
||||
|
||||
protected function _before()
|
||||
{
|
||||
$this->grav = Fixtures::get('grav');
|
||||
$this->directInstallCommand = new DirectInstallCommand();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Why this test file is empty
|
||||
*
|
||||
* Wasn't able to call a symfony\console. Kept having $output problem.
|
||||
* symfony console \NullOutput didn't cut it.
|
||||
*
|
||||
* We would also need to Mock tests since downloading packages would
|
||||
* make tests slow and unreliable. But it's not worth the time ATM.
|
||||
*
|
||||
* Look at Gpm/InstallCommandTest.php
|
||||
*
|
||||
* For the full story: https://git.io/vSlI3
|
||||
*/
|
||||
@@ -41,6 +41,7 @@ class AssetsTest extends \Codeception\TestCase\Test
|
||||
'priority' => 10,
|
||||
'order' => 0,
|
||||
'pipeline' => true,
|
||||
'loading' => '',
|
||||
'group' => 'head',
|
||||
'modified' => false
|
||||
], reset($array));
|
||||
@@ -56,6 +57,7 @@ class AssetsTest extends \Codeception\TestCase\Test
|
||||
'priority' => 10,
|
||||
'order' => 0,
|
||||
'pipeline' => true,
|
||||
'loading' => '',
|
||||
'group' => 'head',
|
||||
'modified' => false
|
||||
], reset($array));
|
||||
@@ -73,6 +75,7 @@ class AssetsTest extends \Codeception\TestCase\Test
|
||||
'priority' => 10,
|
||||
'order' => 0,
|
||||
'pipeline' => true,
|
||||
'loading' => '',
|
||||
'group' => 'head',
|
||||
'modified' => false
|
||||
], reset($array));
|
||||
@@ -90,6 +93,7 @@ class AssetsTest extends \Codeception\TestCase\Test
|
||||
'priority' => 10,
|
||||
'order' => 0,
|
||||
'pipeline' => true,
|
||||
'loading' => '',
|
||||
'group' => 'head',
|
||||
'modified' => false
|
||||
], reset($array));
|
||||
@@ -133,6 +137,7 @@ class AssetsTest extends \Codeception\TestCase\Test
|
||||
'priority' => 10,
|
||||
'order' => 0,
|
||||
'pipeline' => true,
|
||||
'loading' => '',
|
||||
'group' => 'footer',
|
||||
'modified' => false
|
||||
], reset($array));
|
||||
@@ -192,6 +197,22 @@ class AssetsTest extends \Codeception\TestCase\Test
|
||||
'modified' => false
|
||||
], reset($array));
|
||||
|
||||
//Test inline
|
||||
$this->assets->reset();
|
||||
$this->assets->addJs('/system/assets/jquery/jquery-2.x.min.js', null, true, 'inline', null);
|
||||
$js = $this->assets->js();
|
||||
$this->assertContains('jQuery Foundation', $js);
|
||||
|
||||
$this->assets->reset();
|
||||
$this->assets->addCss('/system/assets/debugger.css', null, true, null, 'inline');
|
||||
$css = $this->assets->css();
|
||||
$this->assertContains('div.phpdebugbar', $css);
|
||||
|
||||
$this->assets->reset();
|
||||
$this->assets->addCss('https://fonts.googleapis.com/css?family=Roboto', null, true, null, 'inline');
|
||||
$css = $this->assets->css();
|
||||
$this->assertContains('font-family: \'Roboto\';', $css);
|
||||
|
||||
//Test adding media queries
|
||||
$this->assets->reset();
|
||||
$this->assets->add('test.css', ['media' => 'only screen and (min-width: 640px)']);
|
||||
@@ -336,6 +357,24 @@ class AssetsTest extends \Codeception\TestCase\Test
|
||||
$this->assertContains($this->assets->getTimestamp(), $css);
|
||||
}
|
||||
|
||||
public function testInlinePipeline()
|
||||
{
|
||||
$this->assets->reset();
|
||||
|
||||
//File not existing. Pipeline searches for that file without reaching it. Output is empty.
|
||||
$this->assets->add('test.css', null, true);
|
||||
$this->assets->setCssPipeline(true);
|
||||
$css = $this->assets->css('head', ['loading' => 'inline']);
|
||||
$this->assertSame('', $css);
|
||||
|
||||
//Add a core Grav CSS file, which is found. Pipeline will now return its content.
|
||||
$this->assets->addCss('https://fonts.googleapis.com/css?family=Roboto', null, true);
|
||||
$this->assets->add('/system/assets/debugger.css', null, true);
|
||||
$css = $this->assets->css('head', ['loading' => 'inline']);
|
||||
$this->assertContains('font-family:\'Roboto\';', $css);
|
||||
$this->assertContains('div.phpdebugbar', $css);
|
||||
}
|
||||
|
||||
public function testAddAsyncJs()
|
||||
{
|
||||
$this->assets->reset();
|
||||
|
||||
@@ -11,7 +11,7 @@ class GpmStub extends GPM
|
||||
{
|
||||
public $data;
|
||||
|
||||
public function findPackage($packageName)
|
||||
public function findPackage($packageName, $ignore_exception = false)
|
||||
{
|
||||
if (isset($this->data[$packageName])) {
|
||||
return $this->data[$packageName];
|
||||
@@ -320,4 +320,4 @@ class GpmTest extends \Codeception\TestCase\Test
|
||||
$this->assertSame(null, $this->gpm->calculateVersionNumberFromDependencyVersion('*'));
|
||||
$this->assertSame('2.0.2', $this->gpm->calculateVersionNumberFromDependencyVersion('2.0.2'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ $HTTP["querystring"] =~ "_REQUEST(=|\[|\%[0-9A-Z])" {
|
||||
|
||||
#REROUTING TO THE INDEX PAGE
|
||||
url.rewrite-if-not-file = (
|
||||
"^/grav_path/(.*)$" => "/grav_path/index.php"
|
||||
"^/grav_path/(.*)$" => "/grav_path/index.php$1"
|
||||
)
|
||||
|
||||
#IMPROVING SECURITY
|
||||
|
||||
Reference in New Issue
Block a user