Compare commits
11 Commits
1.1.0-rc.1
...
1.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7696b61d3 | ||
|
|
2bb23efa7c | ||
|
|
e4e0c06ea8 | ||
|
|
dba7347c1e | ||
|
|
50c6e81c09 | ||
|
|
e62ff07726 | ||
|
|
695793b752 | ||
|
|
8de55a745d | ||
|
|
8bba0fd332 | ||
|
|
a7a5625a8b | ||
|
|
f65633043a |
@@ -7,10 +7,6 @@ git:
|
||||
url: https://github.com/getgrav/grav-plugin-error
|
||||
path: user/plugins/error
|
||||
branch: master
|
||||
markdown-notices:
|
||||
url: https://github.com/getgrav/grav-plugin-markdown-notices
|
||||
path: user/plugins/markdown-notices
|
||||
branch: master
|
||||
antimatter:
|
||||
url: https://github.com/getgrav/grav-theme-antimatter
|
||||
path: user/themes/antimatter
|
||||
@@ -24,10 +20,6 @@ links:
|
||||
src: grav-plugin-error
|
||||
path: user/plugins/error
|
||||
scm: github
|
||||
markdown-notices:
|
||||
src: grav-plugin-markdown-notices
|
||||
path: user/plugins/markdown-notices
|
||||
scm: github
|
||||
antimatter:
|
||||
src: grav-theme-antimatter
|
||||
path: user/themes/antimatter
|
||||
|
||||
8
.gitignore
vendored
@@ -1,6 +1,6 @@
|
||||
# Composer
|
||||
.composer
|
||||
/vendor
|
||||
vendor/
|
||||
|
||||
# Sass
|
||||
.sass-cache
|
||||
@@ -35,9 +35,3 @@ Thumbs.db
|
||||
|
||||
# phpstorm
|
||||
.idea/*
|
||||
user/config/security.yaml
|
||||
|
||||
tests/_output/*
|
||||
tests/_support/_generated/*
|
||||
tests/cache/*
|
||||
tests/error.log
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
RewriteEngine On
|
||||
|
||||
## Begin RewriteBase
|
||||
# If you are getting 500 or 404 errors on subpages, you may have to uncomment the RewriteBase entry
|
||||
# If you are getting 404 errors on subpages, you may have to uncomment the RewriteBase entry
|
||||
# You should change the '/' to your appropriate subfolder. For example if you have
|
||||
# your Grav install at the root of your site '/' should work, else it might be something
|
||||
# along the lines of: RewriteBase /<your_sub_folder>
|
||||
@@ -44,7 +44,7 @@ RewriteRule .* index.php [L]
|
||||
|
||||
## Begin - Security
|
||||
# Block all direct access for these folders
|
||||
RewriteRule ^(.git|cache|bin|logs|backup|webserver-configs|tests)/(.*) error [F]
|
||||
RewriteRule ^(.git|cache|bin|logs|backup)/(.*) error [F]
|
||||
# Block access to specific file types for these system folders
|
||||
RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|yaml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||
# Block access to specific file types for these user folders
|
||||
@@ -52,9 +52,9 @@ RewriteRule ^(user)/(.*)\.(txt|md|yaml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||
# Block all direct access to .md files:
|
||||
RewriteRule \.md$ error [F]
|
||||
# Block all direct access to files and folders beginning with a dot
|
||||
RewriteRule (^|/)\.(?!well-known) - [F]
|
||||
RewriteRule (^\.|/\.) - [F]
|
||||
# Block access to specific files in the root folder
|
||||
RewriteRule ^(LICENSE.txt|composer.lock|composer.json|\.htaccess)$ error [F]
|
||||
RewriteRule ^(LICENSE.txt|composer.lock|composer.json|nginx.conf|web.config|htaccess.txt|\.htaccess)$ error [F]
|
||||
## End - Security
|
||||
|
||||
</IfModule>
|
||||
|
||||
42
.travis.yml
@@ -1,12 +1,7 @@
|
||||
language: php
|
||||
php:
|
||||
- '5.5'
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- hhvm
|
||||
php: 5.6
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- master
|
||||
- build_test
|
||||
notifications:
|
||||
@@ -18,10 +13,8 @@ notifications:
|
||||
rooms:
|
||||
- secure: "bqO0wM1B7bJnQw2fuhquSXEqI9gw6WmFytIh9sEWXzbYTzTUP5t0PcKOd3FT2BNMRaDxPJLVl+vG/oqmqDUBkEmOGcG504IQjeNzZqnMz0tXQMIcCc22Las9tFfc4Jf6RVi/qGomFtHGE9Wgii+TAN4zqZaufbNjwd8SyjO0+W8="
|
||||
template:
|
||||
- '%{repository}#%{build_number} (%{branch}): Travis Job Finished [%{duration}] (<a href="%{build_url}">Details</a>)'
|
||||
- '%{repository}#%{build_number} (%{branch}): Grav Core and Skeletons packages have been uploaded. (<a href="%{build_url}">Details</a>)'
|
||||
format: html
|
||||
slack:
|
||||
secure: dowksPsxxCxGKT6nis5hUgkp6+ZDAhoqzQHF9rJnx4hx0iEygPhVBs7pKl9yL2jubYJoLs+EXwE7z1dYgDAEJh4BnfrCokCMLpFGcxVxQC/HeAUdSQ2/RtdBYR5PRT75ScaFpqM/SfXXZVtnwVXAw9Z+JC6BjQ9vmn23m51Jw4k=
|
||||
env:
|
||||
global:
|
||||
# Colors!
|
||||
@@ -42,35 +35,20 @@ env:
|
||||
# BB_TOKEN value => "user:pass@"
|
||||
- secure: "einUtSEkUWy2IrqLXyVjwUU+mwaaoiOXRRVdLBpA3Zye6bZx8cm5h/5AplkPWhM/NmCJoW/MwNZHHkFhlr3mDRov5iOxVmTTYfnXB+I5lxYTSgduOLLErS7mU8hfADpVDU8bHNU44fNGD3UEiG1PD4qQBX4DMlqIFmR20mjs81k="
|
||||
# GH_API_USER [for curl]
|
||||
- secure: "AQGcX1B2NrI8ajflY4AimZDNcK2kBA3F6mbtEFQ78NkDoWhMipsQHayWXiSTzRc0YJKvQl2Y16MTwQF4VHzjTAiiZFATgA8J88vQUjIPabi/kKjqSmcLFoaAOAxStQbW6e0z2GiQ6KBMcNF1y5iUuI63xVrBvtKrYX/w5y+ako8="
|
||||
- secure: "Xbk/V9aIys0NxccJGR3Zrm2GRxDnA0RuazBs1puIboTYDhbi0Z7JTL+mOx3xp5Kfoniad/xAuijQESTM9MMrKqq/qCzhAMaC1+vcL4pCHZH4NSG6DBxB9BPkKVFq+1llu5FTEf8bkxHzwGR0l1ARW6TVRcgTHr5B58bCEIwEOrI="
|
||||
# Latest Release version
|
||||
- TRAVIS_TAG=$(curl --fail -s https://api.github.com/repos/getgrav/grav/releases/latest | grep tag_name | head -n 1 | cut -d '"' -f 4)
|
||||
- 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)
|
||||
|
||||
before_install:
|
||||
- export TZ=Pacific/Honolulu
|
||||
- echo $TRAVIS_PHP_VERSION
|
||||
- echo $TRAVIS_BRANCH
|
||||
- echo $TRAVIS_PULL_REQUEST
|
||||
- composer self-update
|
||||
- if [ $TRAVIS_BRANCH == 'develop' ] || [ $TRAVIS_PULL_REQUEST != 'false' ]; then
|
||||
composer install --dev --prefer-dist;
|
||||
- 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
|
||||
cd "${RT_DEVTOOLS}";
|
||||
./build-grav.sh skeletons.txt;
|
||||
fi
|
||||
- if [ $TRAVIS_BRANCH != 'develop' ] && [ $TRAVIS_PHP_VERSION == "5.6" ] && [ $TRAVIS_PULL_REQUEST == "false" ]; then
|
||||
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
|
||||
cd ${RT_DEVTOOLS};
|
||||
./build-grav.sh skeletons.txt;
|
||||
fi;
|
||||
fi
|
||||
before_script:
|
||||
- if [ $TRAVIS_PHP_VERSION != 'hhvm' ]; then phpenv config-rm xdebug.ini; fi
|
||||
script:
|
||||
- if [ $TRAVIS_BRANCH == 'develop' ] || [ $TRAVIS_PULL_REQUEST != 'false' ]; then
|
||||
vendor/bin/codecept run;
|
||||
fi
|
||||
- echo $TRAVIS_TAG
|
||||
- if [ ! -z "$TRAVIS_TAG" ] && [ $TRAVIS_BRANCH != 'develop' ] && [ $TRAVIS_PHP_VERSION == "5.6" ] && [ $TRAVIS_PULL_REQUEST == "false" ]; then
|
||||
- if [ ! -z "$TRAVIS_TAG" ]; then
|
||||
FILES="$RT_DEVTOOLS/grav-dist/*.zip";
|
||||
for file in ${FILES[@]}; do
|
||||
NAME=${file##*/};
|
||||
|
||||
282
CHANGELOG.md
@@ -1,279 +1,3 @@
|
||||
# v1.1.0-rc.1
|
||||
## 06/01/2016
|
||||
|
||||
1. [](#new)
|
||||
* Added `Utils::getDotNotation()` and `Utils::setDotNotation()` methods + tests
|
||||
* Added support for `xx-XX` locale language lookups in `LanguageCodes` class [#854](https://github.com/getgrav/grav/issues/854)
|
||||
* New CSS/JS Minify library that does a more reliable job [#864](https://github.com/getgrav/grav/issues/864)
|
||||
1. [](#improved)
|
||||
* GPM installation of plugins and themes into correct multisite folders [#841](https://github.com/getgrav/grav/issues/841)
|
||||
* Use `Page::rawRoute()` in blueprints for more reliable mulit-language support
|
||||
1. [](#bugfix)
|
||||
* Fixes for `zlib.output_compression` as well as `mod_deflate` GZIP compression
|
||||
* Fix for corner-case redirect logic causing infinite loops and out-of-memory errors
|
||||
* Fix for saving fields in expert mode that have no `Validation::typeX()` methods [#626](https://github.com/getgrav/grav-plugin-admin/issues/626)
|
||||
* Detect if user really meant to extend parent blueprint, not another one (fixes old page type blueprints)
|
||||
* Fixed a bug in `Page::relativePagePath()` when `Page::$name` is not defined
|
||||
* Fix for poor handling of params + query element in `Uri::processParams()` [#859](https://github.com/getgrav/grav/issues/859)
|
||||
* Fix for double encoding in markdown links [#860](https://github.com/getgrav/grav/issues/860)
|
||||
* Correctly handle language strings to determine if it's in admin or not [#627](https://github.com/getgrav/grav-plugin-admin/issues/627)
|
||||
|
||||
# v1.1.0-beta.5
|
||||
## 05/23/2016
|
||||
|
||||
1. [](#improved)
|
||||
* Updated jQuery from 2.2.0 to 2.2.3
|
||||
* Set `Uri::ip()` to static by default so it can be used in form fields
|
||||
* Improved `Session` class with flash storage
|
||||
* `Page::getContentMeta()` now supports an optional key.
|
||||
1. [](#bugfix)
|
||||
* Fixed "Invalid slug set in YAML frontmatter" when setting `Page::slug()` with empty string [#580](https://github.com/getgrav/grav-plugin-admin/issues/580)
|
||||
* Only `.gitignore` Grav's vendor folder
|
||||
* Fix trying to remove Grav with `GPM uninstall` of a plugin with Grav dependency
|
||||
* Fix Page Type blueprints not being able to extend their parents
|
||||
* `filterFile` validation method always returns an array of files, behaving like `multiple="multiple"`
|
||||
* Fixed [#835](https://github.com/getgrav/grav-plugin-admin/issues/835) check for empty image file first to prevent getimagesize() fatal error
|
||||
* Avoid throwing an error when Grav's Gzip and mod_deflate are enabled at the same time on a non php-fpm setup
|
||||
|
||||
# v1.1.0-beta.4
|
||||
## 05/09/2016
|
||||
|
||||
1. [](#bugfix)
|
||||
* Drop dependencies calculations if plugin is installed via symlink
|
||||
* Drop Grav from dependencies calculations
|
||||
* Send slug name as part of installed packages
|
||||
* Fix for summary entities not being properly decoded [#825](https://github.com/getgrav/grav/issues/825)
|
||||
|
||||
|
||||
# v1.1.0-beta.3
|
||||
## 05/04/2016
|
||||
|
||||
1. [](#improved)
|
||||
* Pass the Page type when calling `onBlueprintCreated`
|
||||
* Changed `Page::cachePageContent()` form **private** to **public** so a page can be recached via plugin
|
||||
1. [](#bugfix)
|
||||
* Fixed handling of `{'loading':'async'}` with Assets Pipeline
|
||||
* Fix for new modular page modal `Page` field requiring a value [#529](https://github.com/getgrav/grav-plugin-admin/issues/529)
|
||||
* Fix for broken `bin/gpm version` command
|
||||
* Fix handling "grav" as a dependency
|
||||
* Fix when installing multiple packages and one is the dependency of another, don't try to install it twice
|
||||
* Fix using name instead of the slug to determine a package folder. Broke for packages whose name was 2+ words
|
||||
|
||||
# v1.1.0-beta.2
|
||||
## 04/27/2016
|
||||
|
||||
1. [](#new)
|
||||
* Added new `Plugin::getBlueprint()` and `Theme::getBlueprint()` method
|
||||
* Allow **page blueprints** to be added via Plugins.
|
||||
1. [](#improved)
|
||||
* Moved to new `data-*@` format in blueprints
|
||||
* Updated composer-based libraries
|
||||
* Moved some hard-coded `CACHE_DIR` references to use locator
|
||||
* Set `twig.debug: true` by default
|
||||
1. [](#bugfix)
|
||||
* Fixed issue with link rewrites and local assets pipeline with `absolute_urls: true`
|
||||
* Allow Cyrillic slugs [#520](https://github.com/getgrav/grav-plugin-admin/issues/520)
|
||||
* Fix ordering issue with accented letters [#784](https://github.com/getgrav/grav/issues/784)
|
||||
* Fix issue with Assets pipeline and missing newlines causing invalid JavaScript
|
||||
|
||||
# v1.1.0-beta.1
|
||||
## 04/20/2016
|
||||
|
||||
1. [](#new)
|
||||
* **Blueprint Improvements**: The main improvements to Grav take the form of a major rewrite of our blueprint functionality. Blueprints are an essential piece of functionality within Grav that helps define configuration fields. These allow us to create a definition of a form field that can be rendered in the administrator plugin and allow the input, validation, and storage of values into the various configuration and page files that power Grav. Grav 1.0 had extensive support for building and extending blueprints, but Grav 1.1 takes this even further and adds improvements to our existing system.
|
||||
* **Extending Blueprints**: You could extend forms in Grav 1.0, but now you can use a newer `extends@:` default syntax rather than the previous `'@extends'` string that needed to be quoted in YAML. Also this new format allows for the defining of a `context` which lets you define where to look for the base blueprint. Another new feature is the ability to extend from multiple blueprints.
|
||||
* **Embedding/Importing Blueprints**: One feature that has been requested is the ability to embed or import one blueprint into another blueprint. This allows you to share fields or sub-form between multiple forms. This is accomplished via the `import@` syntax.
|
||||
* **Removing Existing Fields and Properties**: Another new feature is the ability to remove completely existing fields or properties from an extended blueprint. This allows the user a lot more flexibility when creating custom forms by simply using the new `unset@: true` syntax. To remove a field property you would use `unset-<property>@: true` in your extended field definition, for example: `unset-options@: true`.
|
||||
* **Replacing Existing Fields and Properties**: Similar to removing, you can now replace an existing field or property with the `replace@: true` syntax for the whole field, and `replace-<property>@: true` for a specific property.
|
||||
* **Field Ordering**: Probably the most frequently requested blueprint functionality that we have added is the ability to change field ordering. Imagine that you want to extend the default page blueprint but add a new tab. Previously, this meant your tab would be added at the end of the form, but now you can define that you wish the new tab to be added right after the `content` tab. This works for any field too, so you can extend a blueprint and add your own custom fields anywhere you wish! This is accomplished by using the new `ordering@:` syntax with either an existing property name or an integer.
|
||||
* **Configuration Properties**: Another useful new feature is the ability to directly access Grav configuration in blueprints with `config-<property>@` syntax. For example you can set a default for a field via `config-default@: site.author.name` which will use the author.name value from the `site.yaml` file as the `default` value for this field.
|
||||
* **Function Calls**: The ability to call PHP functions for values has been improved in Grav 1.1 to be more powerful. You can use the `data-<property>@` syntax to call static methods to obtain values. For example: `data-default@: '\Grav\Plugin\Admin::route'`. You can now even pass parameters to these methods.
|
||||
* **Validation Rules**: You can now define a custom blueprint-level validation rule and assign this rule to a form field.
|
||||
* **Custom Form Field Types**: This advanced new functionality allows you to create a custom field type via a new plugin event called getFormFieldTypes(). This allows you to provide extra functionality or instructions on how to handle the form form field.
|
||||
* **GPM Versioning**: A new feature that we have wanted to add to our GPM package management system is the ability to control dependencies by version. We have opted to use a syntax very similar to the Composer Package Manager that is already familiar to most PHP developers. This new versioning system allows you to define specific minimum version requirements of dependent packages within Grav. This should ensure that we have less (hopefully none!) issues when you update one package that also requires a specific minimum version of another package. The admin plugin for example may have an update that requires a specific version of Grav itself.
|
||||
* **GPM Testing Channel**: GPM repository now comes with both a `stable` and `testing` channel. A new setting in `system.gpm.releases` allow to switch between the two channels. Developers will be able to decide whether their resource is going to be in a pre-release state or stable. Only users who switch to the **testing** channel will be able to install a pre-release version.
|
||||
* **GPM Events**: Packages (plugins and themes) can now add event handlers to hook in the package GPM events: install, update, uninstall. A package can listen for events before and after each of these events, and can execute any PHP code, and optionally halt the procedure or return a message.
|
||||
* Refactor of the process chain breaking out `Processors` into individual classes to allow for easier modification and addition. Thanks to toovy for this work. - [#745](https://github.com/getgrav/grav/pull/745)
|
||||
* Added multipart downloads, resumable downloads, download throttling, and video streaming in the `Utils::download()` method.
|
||||
* Added optional config to allow Twig processing in page frontmatter - [#788](https://github.com/getgrav/grav/pull/788)
|
||||
* Added the ability to provide blueprints via a plugin (previously limited to Themes only).
|
||||
* Added Developer CLI Tools to easily create a new theme or plugin
|
||||
* Allow authentication for proxies - [#698](https://github.com/getgrav/grav/pull/698)
|
||||
* Allow to override the default Parsedown behavior - [#747](https://github.com/getgrav/grav/pull/747)
|
||||
* Added an option to allow to exclude external files from the pipeline, and to render the pipeline before/after excluded files
|
||||
* Added the possibility to store translations of themes in separate files inside the `languages` folder
|
||||
* Added a method to the Uri class to return the base relative URL including the language prefix, or the base relative url if multilanguage is not enabled
|
||||
* Added a shortcut for pages.find() alias
|
||||
1. [](#improved)
|
||||
* Now supporting hostnames with localhost environments for better vhost support/development
|
||||
* Refactor hard-coded paths to use PHP Streams that allow a setup file to configure where certain parts of Grav are stored in the physical filesystem.
|
||||
* If multilanguage is active, include the Intl Twig Extension to allow translating dates automatically (http://twig.sensiolabs.org/doc/extensions/intl.html)
|
||||
* Allow having local themes with the same name as GPM themes, by adding `gpm: false` to the theme blueprint - [#767](https://github.com/getgrav/grav/pull/767)
|
||||
* Caddyfile and Lighttpd config files updated
|
||||
* Removed `node_modules` folder from backups to make them faster
|
||||
* Display error when `bin/grav install` hasn't been run instead of throwing exception. Prevents "white page" errors if error display is off
|
||||
* Improved command line flow when installing multiple packages: don't reinstall packages if already installed, ask once if should use symlinks if symlinks are found
|
||||
* Added more tests to our testing suite
|
||||
* Added x-ua-compatible to http_equiv metadata processing
|
||||
* Added ability to have a per-page `frontmatter.yaml` file to set header frontmatter defaults. Especially useful for multilang scenarios - [#775](https://github.com/getgrav/grav/pull/775)
|
||||
* Removed deprecated `bin/grav newuser` CLI command. use `bin/plugin login newuser` instead.
|
||||
* Added `webm` and `ogv` video types to the default media types list.
|
||||
1. [](#bugfix)
|
||||
* Fix Zend Opcache `opcache.validate_timestamps=0` not detecting changes in compiled yaml and twig files
|
||||
* Avoid losing params, query and fragment from the URL when auto-redirecting to a language-specific route - [#759](https://github.com/getgrav/grav/pull/759)
|
||||
* Fix for non-pipeline assets getting lost when pipeline is cached to filesystem
|
||||
* Fix for double encoding resulting from Markdown Extra
|
||||
* Fix for a remote link breaking all CSS rewrites for pipeline
|
||||
* Fix an issue with Retina alternatives not clearing properly between repeat uses
|
||||
* Fix for non standard http/s external markdown links - [#738](https://github.com/getgrav/grav/issues/738)
|
||||
* Fix for `find()` calling redirects via `dispatch()` causing infinite loops - [#781](https://github.com/getgrav/grav/issues/781)
|
||||
|
||||
# v1.0.10
|
||||
## 02/11/2016
|
||||
|
||||
1. [](#new)
|
||||
* Added new `Page::contentMeta()` mechanism to store content-level meta data alongside content
|
||||
* Added Japanese language translation
|
||||
1. [](#improved)
|
||||
* Updated some vendor libraries
|
||||
1. [](#bugfix)
|
||||
* Hide `streams` blueprint from Admin plugin
|
||||
* Fix translations of languages with `---` in YAML files
|
||||
|
||||
# v1.0.9
|
||||
## 02/05/2016
|
||||
|
||||
1. [](#new)
|
||||
* New **Unit Testing** via Codeception http://codeception.com/
|
||||
* New **page-level SSL** functionality when using `absolute_urls`
|
||||
* Added `reverse_proxy` config option for issues with non-standard ports
|
||||
* Added `proxy_url` config option to support GPM behind proxy servers #639
|
||||
* New `Pages::parentsRawRoutes()` method
|
||||
* Enhanced `bin/gpm info` CLI command with Changelog support #559
|
||||
* Ability to add empty *Folder* via admin plugin
|
||||
* Added latest `jQuery 2.2.0` library to core
|
||||
* Added translations from Crowdin
|
||||
1. [](#improved)
|
||||
* [BC] Metadata now supports only flat arrays. To use open graph metas and the likes (ie, 'og:title'), simply specify it in the key.
|
||||
* Refactored `Uri::convertUrl()` method to be more reliable + tests created
|
||||
* Date for last update of a modular sub-page sets modified date of modular page itself
|
||||
* Split configuration up into two steps
|
||||
* Moved Grav-based `base_uri` variables into `Uri::init()`
|
||||
* Refactored init in `URI` to better support testing
|
||||
* Allow `twig_vars` to be exposed earlier and merged later
|
||||
* Avoid setting empty metadata
|
||||
* Accept single group access as a string rather than requiring an array
|
||||
* Return `$this` in Page constructor and init to allow chaining
|
||||
* Added `ext-*` PHP requirements to `composer.json`
|
||||
* Use Whoops 2.0 library while supporting old style
|
||||
* Removed redundant old default-hash fallback mechanisms
|
||||
* Commented out default redirects and routes in `site.yaml`
|
||||
* Added `/tests` folder to deny's of all `webserver-configs/*` files
|
||||
* Various PS and code style fixes
|
||||
1. [](#bugfix)
|
||||
* Fix default generator metadata
|
||||
* Fix for broken image processing caused by `Uri::convertUrl()` bugs
|
||||
* Fix loading JS and CSS from collections #623
|
||||
* Fix stream overriding
|
||||
* Remove the URL extension for home link
|
||||
* Fix permissions when the user has no access level set at all
|
||||
* Fix issue with user with multiple groups getting denied on first group
|
||||
* Fixed an issue with `Pages()` internal cache lookup not being unique enough
|
||||
* Fix for bug with `site.redirects` and `site.routes` being an empty list
|
||||
* [Markdown] Don't process links for **special protocols**
|
||||
* [Whoops] serve JSON errors when request is JSON
|
||||
|
||||
|
||||
# v1.0.8
|
||||
## 01/08/2016
|
||||
|
||||
1. [](#new)
|
||||
* Added `rotate`, `flip` and `fixOrientation` image medium methods
|
||||
1. [](#bugfix)
|
||||
* Removed IP from Nonce generation. Should be more reliable in a variety of scenarios
|
||||
|
||||
# v1.0.7
|
||||
## 01/07/2016
|
||||
|
||||
1. [](#new)
|
||||
* Added `composer create-project` as an additional installation method #585
|
||||
* New optional system config setting to strip home from page routs and urls #561
|
||||
* Added Greek, Finnish, Norwegian, Polish, Portuguese, and Romanian languages
|
||||
* Added new `Page->topParent()` method to return top most parent of a page
|
||||
* Added plugins configuration tab to debugger
|
||||
* Added support for APCu and PHP7.0 via new Doctrine Cache release
|
||||
* Added global setting for `twig_first` processing (false by default)
|
||||
* New configuration options for Session settings #553
|
||||
1. [](#improved)
|
||||
* Switched to SSL for GPM calls
|
||||
* Use `URI->host()` for session domain
|
||||
* Add support for `open_basedir` when installing packages via GPM
|
||||
* Improved `Utils::generateNonceString()` method to handle reverse proxies
|
||||
* Optimized core thumbnails saving 38% in file size
|
||||
* Added new `bin/gpm index --installed-only` option
|
||||
* Improved GPM errors to provider more helpful diagnostic of issues
|
||||
* Removed old hardcoded PHP version references
|
||||
* Moved `onPageContentProcessed()` event so it's fired more reliably
|
||||
* Maintain md5 keys during sorting of Assets #566
|
||||
* Update to Caddyfile for Caddy web server
|
||||
1. [](#bugfix)
|
||||
* Fixed an issue with cache/config checksum not being set on cache load
|
||||
* Fix for page blueprint and theme inheritance issue #534
|
||||
* Set `ZipBackup` timeout to 10 minutes if possible
|
||||
* Fix case where we only have inline data for CSS or JS #565
|
||||
* Fix `bin/grav sandbox` command to work with new `webserver-config` folder
|
||||
* Fix for markdown attributes on external URLs
|
||||
* Fixed issue where `data:` page header was acting as `publish_date:`
|
||||
* Fix for special characters in URL parameters (e.g. /tag:c++) #541
|
||||
* Safety check for an array of nonces to only use the first one
|
||||
|
||||
# v1.0.6
|
||||
## 12/22/2015
|
||||
|
||||
1. [](#new)
|
||||
* Set minimum requirements to [PHP 5.5.9](http://bit.ly/1Jt9OXO)
|
||||
* Added `saveConfig` to Themes
|
||||
1. [](#improved)
|
||||
* Updated Whoops to new 2.0 version (PHP 7.0 compatible)
|
||||
* Moved sample web server configs into dedicated directory
|
||||
* FastCGI will use Apache's `mod_deflate` if gzip turned off
|
||||
1. [](#bugfix)
|
||||
* Fix broken media image operators
|
||||
* Only call extra method of blueprints if blueprints exist
|
||||
* Fix lang prefix in url twig variables #523
|
||||
* Fix case insensitive HTTPS check #535
|
||||
* Field field validation handles case `multiple` missing
|
||||
|
||||
# v1.0.5
|
||||
## 12/18/2015
|
||||
|
||||
1. [](#new)
|
||||
* Add ability to extend markdown with plugins
|
||||
* Added support for plugins to have individual language files
|
||||
* Added `7z` to media formats
|
||||
* Use Grav's fork of Parsedown until PR is merged
|
||||
* New function to persist plugin configuration to disk
|
||||
* GPM `selfupgrade` will now check PHP version requirements
|
||||
1. [](#improved)
|
||||
* If the field allows multiple files, return array
|
||||
* Handle non-array values in file validation
|
||||
1. [](#bugfix)
|
||||
* Fix when looping `fields` param in a `list` field
|
||||
* Properly convert commas to spaces for media attributes
|
||||
* Forcing Travis VM to HI timezone to address future files in zip file
|
||||
|
||||
# v1.0.4
|
||||
## 12/12/2015
|
||||
|
||||
1. [](#bugfix)
|
||||
* Needed to put default image folder permissions for YAML compatibility
|
||||
|
||||
# v1.0.3
|
||||
## 12/11/2015
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed issue when saving config causing incorrect image cache folder perms
|
||||
|
||||
# v1.0.2
|
||||
## 12/11/2015
|
||||
|
||||
@@ -283,7 +7,7 @@
|
||||
# v1.0.1
|
||||
## 12/11/2015
|
||||
|
||||
1. [](#improved)
|
||||
1. [](#improved)
|
||||
* Reduced package sizes by removing extra vendor dev bits
|
||||
1. [](#bugfix)
|
||||
* Fix issue when you enable debugger from admin plugin
|
||||
@@ -296,7 +20,7 @@
|
||||
* Added setters to set state of CSS/JS pipelining
|
||||
* Added `user/accounts` to `.gitignore`
|
||||
* Added configurable permissions option for Image cache
|
||||
1. [](#improved)
|
||||
1. [](#improved)
|
||||
* Hungarian translation updated
|
||||
* Refactored Theme initialization for improved flexibility
|
||||
* Wrapped security section of account blueprints in an 'super user' authorize check
|
||||
@@ -330,7 +54,7 @@
|
||||
* Automatically create unique security salt for each configuration
|
||||
* Added Hungarian translation
|
||||
* Added support for User groups
|
||||
1. [](#improved)
|
||||
1. [](#improved)
|
||||
* Improved robots.txt to disallow crawling of non-user folders
|
||||
* Nonces only generated once per action and process
|
||||
* Added IP into Nonce string calculation
|
||||
|
||||
122
CONTRIBUTING.md
@@ -1,122 +0,0 @@
|
||||
# Contributing to Grav
|
||||
|
||||
:+1::tada: First, thanks for getting involved with Grav! :tada::+1:
|
||||
|
||||
Please take a moment to review this document in order to make the contribution
|
||||
process easy and effective for everyone involved.
|
||||
|
||||
Following these guidelines helps to communicate that you respect the time of
|
||||
the developers managing and developing this open source project. In return,
|
||||
they should reciprocate that respect in addressing your issue or assessing
|
||||
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.
|
||||
|
||||
[https://github.com/getgrav/grav](https://github.com/getgrav/grav) is the main Grav repository. The core of Grav is provided by this repo.
|
||||
|
||||
[https://github.com/getgrav/grav-plugin-admin](https://github.com/getgrav/grav-plugin-admin) is the Admin Plugin repository.
|
||||
|
||||
Every Plugin and Theme has its own repository. If you have a problem you think is specific to a Theme or Plugin, please report it in its corresponding repository. Please read the Plugin or Theme documentation to ensure the problem is not addressed there already.
|
||||
|
||||
Every Skeleton also has its own repository, so if an issue is not specific to a theme or plugin but rather to its usage in the skeleton, report it in the skeleton repository.
|
||||
|
||||
## Using the issue tracker
|
||||
|
||||
The issue tracker is the preferred channel for [bug reports](#bugs),
|
||||
[features requests](#features) and [submitting pull
|
||||
requests](#pull-requests), but please respect the following restrictions:
|
||||
|
||||
* Please **do not** use the issue tracker for support requests. Use
|
||||
[the Forum](http://getgrav.org/forum) or [the Gitter chat](https://gitter.im/getgrav/grav).
|
||||
|
||||
|
||||
<a name="bugs"></a>
|
||||
## Bug reports
|
||||
|
||||
A bug is a _demonstrable problem_ that is caused by the code in the repository.
|
||||
Good bug reports are extremely helpful - thank you!
|
||||
|
||||
Guidelines for bug reports:
|
||||
|
||||
1. **Check you satisfy the Grav requirements** — [http://learn.getgrav.org/basics/requirements](http://learn.getgrav.org/basics/requirements)
|
||||
|
||||
2. **Check this happens on a clean Grav install** — check if the issue happens on any Grav site, or just with a specific configuration of plugins / theme
|
||||
|
||||
3. **Use the GitHub issue search** — check if the issue has already been
|
||||
reported.
|
||||
|
||||
4. **Check if the issue is already being solved in a PR** — check the open Pull Requests to see if one already solves the problem you're having
|
||||
|
||||
5. **Check if the issue has been fixed** — try to reproduce it using the
|
||||
latest `develop` branch in the repository.
|
||||
|
||||
6. **Isolate the problem** — create a [reduced test
|
||||
case](http://css-tricks.com/reduced-test-cases/) and provide a step-by-step instruction set on how to recreate the problem. Include code samples, page snippets or yaml configurations if needed.
|
||||
|
||||
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 steps will reproduce the issue? What browser(s) and OS experience the problem?
|
||||
|
||||
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?
|
||||
|
||||
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.
|
||||
|
||||
|
||||
All these details will help people 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.
|
||||
|
||||
Example:
|
||||
|
||||
> Short and descriptive example bug report title
|
||||
>
|
||||
> A summary of the issue and the browser/OS environment in which it occurs. If
|
||||
> suitable, include the steps required to reproduce the bug.
|
||||
>
|
||||
> 1. This is the first step
|
||||
> 2. This is the second step
|
||||
> 3. Further steps, etc.
|
||||
>>
|
||||
> Any other information you want to share that is relevant to the issue being
|
||||
> reported. This might include the lines of code that you have identified as
|
||||
> causing the bug, and potential solutions (and your opinions on their
|
||||
> merits).
|
||||
|
||||
|
||||
<a name="features"></a>
|
||||
## Feature requests
|
||||
|
||||
Feature requests are welcome. But take a moment to find out whether your idea
|
||||
fits with the scope and aims of the project. It's up to *you* to make a strong
|
||||
case to convince the project's developers of the merits of this feature. Please
|
||||
provide as much detail and context as possible.
|
||||
|
||||
|
||||
<a name="pull-requests"></a>
|
||||
## Pull requests
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Please adhere to the coding conventions used throughout the project (indentation,
|
||||
accurate comments, etc.) and any other requirements.
|
||||
|
||||
See [Using Pull Request](https://help.github.com/articles/using-pull-requests/) and [Fork a Repo](https://help.github.com/articles/fork-a-repo/) if you're not familiar with Pull Requests.
|
||||
|
||||
**IMPORTANT**: By submitting a patch, you agree to allow the project owner to
|
||||
license your work under the same license as that used by the project.
|
||||
27
README.md
@@ -1,6 +1,6 @@
|
||||
#  Grav
|
||||
|
||||
[](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad) [](https://gitter.im/getgrav/grav?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://travis-ci.org/getgrav/grav)
|
||||
[](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad) [](https://gitter.im/getgrav/grav?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Grav is a **Fast**, **Simple**, and **Flexible**, file-based Web-platform. There is **Zero** installation required. Just extract the ZIP archive, and you are already up and running. It follows similar principles to other flat-file CMS platforms, but has a different design philosophy than most. Grav comes with a powerful **Package Management System** to allow for simple installation and upgrading of plugins and themes, as well as simple updating of Grav itself.
|
||||
|
||||
@@ -18,25 +18,17 @@ The underlying architecture of Grav is designed to use well-established and _bes
|
||||
|
||||
# Requirements
|
||||
|
||||
- PHP 5.5.9 or higher. Check the [required modules list](http://learn.getgrav.org/basics/requirements#php-requirements)
|
||||
- PHP 5.4 or higher. Check the [required modules list](http://learn.getgrav.org/basics/requirements#php-requirements)
|
||||
- Check the [Apache](http://learn.getgrav.org/basics/requirements#apache-requirements) or [IIS](http://learn.getgrav.org/basics/requirements#iis-requirements) requirements
|
||||
|
||||
# QuickStart
|
||||
|
||||
These are the options to get Grav:
|
||||
You have two options to get Grav:
|
||||
|
||||
### Downloading a Grav Package
|
||||
|
||||
You can download a **ready-built** package from the [Downloads page on http://getgrav.org](http://getgrav.org/downloads)
|
||||
|
||||
### With Composer
|
||||
|
||||
You can create a new project with the latest **stable** Grav release with the following command:
|
||||
|
||||
```
|
||||
$ composer create-project getgrav/grav ~/webroot/grav
|
||||
```
|
||||
|
||||
### From GitHub
|
||||
|
||||
1. Clone the Grav repository from [https://github.com/getgrav/grav]() to a folder in the webroot of your server, e.g. `~/webroot/grav`. Launch a **terminal** or **console** and navigate to the webroot folder:
|
||||
@@ -100,11 +92,11 @@ What you mainly want to know is that:
|
||||
* [What is Grav?](http://learn.getgrav.org/basics/what-is-grav)
|
||||
* [Install](http://learn.getgrav.org/basics/installation) Grav in few seconds
|
||||
* Understand the [Configuration](http://learn.getgrav.org/basics/grav-configuration)
|
||||
* Take a peek at our available free [Skeletons](http://getgrav.org/downloads/skeletons)
|
||||
* If you have questions, jump on our [Gitter Room](https://gitter.im/getgrav/grav)!
|
||||
* Take a peek at our available free [Skeletons](http://getgrav.org/downloads/skeletons#extras)
|
||||
* If you have questions, check out `#grav` on irc.freenode.net
|
||||
* Have fun!
|
||||
|
||||
# Exploring More
|
||||
# Exploring more
|
||||
|
||||
* Have a look at our [Basic Tutorial](http://learn.getgrav.org/basics/basic-tutorial)
|
||||
* Dive into more [advanced](http://learn.getgrav.org/advanced) functions
|
||||
@@ -116,10 +108,3 @@ See [LICENSE](LICENSE.txt)
|
||||
|
||||
[gitflow-model]: http://nvie.com/posts/a-successful-git-branching-model/
|
||||
[gitflow-extensions]: https://github.com/nvie/gitflow
|
||||
|
||||
# Running Tests
|
||||
|
||||
First install the dev dependencies by running `composer update` from the Grav root.
|
||||
Then `composer test` will run the Unit Tests, which should be always executed successfully on any site.
|
||||
|
||||
You can also run a single unit test file, e.g. `composer test tests/unit/Grav/Common/AssetsTest.php`
|
||||
|
||||
11
bin/gpm
@@ -2,6 +2,10 @@
|
||||
<?php
|
||||
define('GRAV_CLI', true);
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
|
||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
||||
}
|
||||
|
||||
if (!file_exists(__DIR__ . '/../vendor')){
|
||||
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
||||
}
|
||||
@@ -21,10 +25,6 @@ use Grav\Common\Grav;
|
||||
|
||||
$autoload = require_once(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
|
||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
||||
}
|
||||
|
||||
if (!ini_get('date.timezone')) {
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
@@ -39,7 +39,6 @@ if (!function_exists('curl_version')) {
|
||||
|
||||
$grav = Grav::instance(array('loader' => $autoload));
|
||||
$grav['config']->init();
|
||||
$grav['uri']->init();
|
||||
$grav['streams'];
|
||||
|
||||
$app = new Application('Grav Package Manager', GRAV_VERSION);
|
||||
@@ -52,6 +51,4 @@ $app->addCommands(array(
|
||||
new \Grav\Console\Gpm\UpdateCommand(),
|
||||
new \Grav\Console\Gpm\SelfupgradeCommand(),
|
||||
));
|
||||
|
||||
$app->setDefaultCommand('index');
|
||||
$app->run();
|
||||
|
||||
25
bin/grav
@@ -2,6 +2,10 @@
|
||||
<?php
|
||||
define('GRAV_CLI', true);
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
|
||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
||||
}
|
||||
|
||||
if (!file_exists(__DIR__ . '/../vendor')){
|
||||
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
||||
}
|
||||
@@ -20,10 +24,6 @@ use Symfony\Component\Console\Application;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
|
||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
||||
}
|
||||
|
||||
if (!ini_get('date.timezone')) {
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
@@ -32,14 +32,15 @@ if (!file_exists(ROOT_DIR . 'index.php')) {
|
||||
exit('FATAL: Must be run from ROOT directory of Grav!');
|
||||
}
|
||||
|
||||
$app = new Application('Grav CLI Application', GRAV_VERSION);
|
||||
$app = new Application('Grav CLI Application', '0.1.0');
|
||||
$app->addCommands(array(
|
||||
new \Grav\Console\Cli\InstallCommand(),
|
||||
new \Grav\Console\Cli\ComposerCommand(),
|
||||
new \Grav\Console\Cli\SandboxCommand(),
|
||||
new \Grav\Console\Cli\CleanCommand(),
|
||||
new \Grav\Console\Cli\ClearCacheCommand(),
|
||||
new \Grav\Console\Cli\BackupCommand(),
|
||||
new \Grav\Console\Cli\NewProjectCommand(),
|
||||
new Grav\Console\Cli\InstallCommand(),
|
||||
new Grav\Console\Cli\ComposerCommand(),
|
||||
new Grav\Console\Cli\SandboxCommand(),
|
||||
new Grav\Console\Cli\CleanCommand(),
|
||||
new Grav\Console\Cli\ClearCacheCommand(),
|
||||
new Grav\Console\Cli\BackupCommand(),
|
||||
new Grav\Console\Cli\NewProjectCommand(),
|
||||
new Grav\Console\Cli\NewUserCommand(),
|
||||
));
|
||||
$app->run();
|
||||
|
||||
18
bin/plugin
@@ -2,6 +2,10 @@
|
||||
<?php
|
||||
define('GRAV_CLI', true);
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
|
||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
||||
}
|
||||
|
||||
if (!file_exists(__DIR__ . '/../vendor')) {
|
||||
require_once __DIR__ . '/../system/src/Grav/Common/Composer.php';
|
||||
}
|
||||
@@ -25,10 +29,6 @@ use Grav\Common\Filesystem\Folder;
|
||||
|
||||
$autoload = require_once(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
|
||||
exit(sprintf("You are running PHP %s, but Grav needs at least PHP %s to run.\n", $ver, $req));
|
||||
}
|
||||
|
||||
if (!ini_get('date.timezone')) {
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
@@ -107,12 +107,10 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
foreach ($commands as $command_path) {
|
||||
require_once "plugins://{$name}/cli/{$command_path}";
|
||||
|
||||
$command_class = 'Grav\Plugin\Console\\' . preg_replace('/.php$/', '', $command_path);
|
||||
$command = new $command_class();
|
||||
$app->add($command);
|
||||
foreach ($commands as $command) {
|
||||
require_once "plugins://{$name}/cli/{$command}";
|
||||
$command = 'Grav\Plugin\Console\\' . preg_replace('/.php$/', '', $command);
|
||||
$app->add(new $command());
|
||||
}
|
||||
|
||||
$app->run($input);
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
actor: Tester
|
||||
paths:
|
||||
tests: tests
|
||||
log: tests/_output
|
||||
data: tests/_data
|
||||
support: tests/_support
|
||||
envs: tests/_envs
|
||||
settings:
|
||||
bootstrap: _bootstrap.php
|
||||
colors: true
|
||||
memory_limit: 1024M
|
||||
extensions:
|
||||
enabled:
|
||||
- Codeception\Extension\RunFailed
|
||||
modules:
|
||||
config:
|
||||
@@ -1,14 +1,13 @@
|
||||
{
|
||||
"name": "getgrav/grav",
|
||||
"type": "project",
|
||||
"type": "library",
|
||||
"description": "Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS",
|
||||
"keywords": ["cms","flat-file cms","flat cms","flatfile cms","php"],
|
||||
"homepage": "http://getgrav.org",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"twig/twig": "~1.24",
|
||||
"erusev/parsedown": "dev-master as 1.6.0",
|
||||
"php": ">=5.4.0",
|
||||
"twig/twig": "~1.23",
|
||||
"erusev/parsedown-extra": "~0.7",
|
||||
"symfony/yaml": "~2.8",
|
||||
"symfony/console": "~2.8",
|
||||
@@ -16,22 +15,15 @@
|
||||
"symfony/var-dumper": "~2.8",
|
||||
"symfony/polyfill-iconv": "~1.0",
|
||||
"doctrine/cache": "~1.5",
|
||||
"filp/whoops": "~2.0",
|
||||
"matthiasmullie/minify": "^1.3",
|
||||
"filp/whoops": "1.1.10",
|
||||
"monolog/monolog": "~1.0",
|
||||
"gregwar/image": "~2.0",
|
||||
"ircmaxell/password-compat": "1.0.*",
|
||||
"mrclay/minify": "~2.2",
|
||||
"donatj/phpuseragentparser": "~0.3",
|
||||
"pimple/pimple": "~3.0",
|
||||
"rockettheme/toolbox": "dev-develop",
|
||||
"maximebf/debugbar": "~1.10",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "^2.1",
|
||||
"phpunit/php-code-coverage": "~2.0",
|
||||
"fzaninotto/faker": "^1.5"
|
||||
"rockettheme/toolbox": "~1.2",
|
||||
"maximebf/debugbar": "~1.10"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -41,15 +33,5 @@
|
||||
},
|
||||
"archive": {
|
||||
"exclude": ["VERSION"]
|
||||
},
|
||||
"scripts": {
|
||||
"post-create-project-cmd": "bin/grav install",
|
||||
"test": "vendor/bin/codecept run unit",
|
||||
"test-windows": "vendor\\bin\\codecept run unit"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-develop": "1.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1891
composer.lock
generated
@@ -44,7 +44,7 @@ RewriteRule .* index.php [L]
|
||||
|
||||
## Begin - Security
|
||||
# Block all direct access for these folders
|
||||
RewriteRule ^(.git|cache|bin|logs|backup|webserver-configs|tests)/(.*) error [F]
|
||||
RewriteRule ^(.git|cache|bin|logs|backup)/(.*) error [F]
|
||||
# Block access to specific file types for these system folders
|
||||
RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|yaml|php|pl|py|cgi|twig|sh|bat)$ error [F]
|
||||
# Block access to specific file types for these user folders
|
||||
@@ -54,7 +54,7 @@ RewriteRule \.md$ error [F]
|
||||
# Block all direct access to files and folders beginning with a dot
|
||||
RewriteRule (^\.|/\.) - [F]
|
||||
# Block access to specific files in the root folder
|
||||
RewriteRule ^(LICENSE.txt|composer.lock|composer.json|\.htaccess)$ error [F]
|
||||
RewriteRule ^(LICENSE.txt|composer.lock|composer.json|nginx.conf|web.config|htaccess.txt|\.htaccess)$ error [F]
|
||||
## End - Security
|
||||
|
||||
</IfModule>
|
||||
13
index.php
@@ -1,10 +1,14 @@
|
||||
<?php
|
||||
namespace Grav;
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
|
||||
throw new \RuntimeException(sprintf('You are running PHP %s, but Grav needs at least <strong>PHP %s</strong> to run.', $ver, $req));
|
||||
}
|
||||
|
||||
// Ensure vendor libraries exist
|
||||
$autoload = __DIR__ . '/vendor/autoload.php';
|
||||
if (!is_file($autoload)) {
|
||||
die("Please run: <i>bin/grav install</i>");
|
||||
throw new \RuntimeException("Please run: <i>bin/grav install</i>");
|
||||
}
|
||||
|
||||
use Grav\Common\Grav;
|
||||
@@ -12,16 +16,12 @@ use Grav\Common\Grav;
|
||||
// Register the auto-loader.
|
||||
$loader = require_once $autoload;
|
||||
|
||||
if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
|
||||
die(sprintf('You are running PHP %s, but Grav needs at least <strong>PHP %s</strong> to run.', $ver, $req));
|
||||
}
|
||||
|
||||
// Set timezone to default, falls back to system if php.ini not set
|
||||
date_default_timezone_set(@date_default_timezone_get());
|
||||
|
||||
// Set internal encoding if mbstring loaded
|
||||
if (!extension_loaded('mbstring')) {
|
||||
die("'mbstring' extension is not loaded. This is required for Grav to run correctly");
|
||||
throw new \RuntimeException("'mbstring' extension is not loaded. This is required for Grav to run correctly");
|
||||
}
|
||||
mb_internal_encoding('UTF-8');
|
||||
|
||||
@@ -39,3 +39,4 @@ try {
|
||||
$grav->fireEvent('onFatalException');
|
||||
throw $e;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@ url.rewrite-if-not-file = (
|
||||
$HTTP["url"] =~ "^/grav_path/(LICENSE.txt|composer.json|composer.lock|nginx.conf|web.config)$" {
|
||||
url.access-deny = ("")
|
||||
}
|
||||
$HTTP["url"] =~ "^/grav_path/(.git|cache|bin|logs|backup|tests)/(.*)" {
|
||||
$HTTP["url"] =~ "^/grav_path/(.git|cache|bin|logs|backup)/(.*)" {
|
||||
url.access-deny = ("")
|
||||
}
|
||||
$HTTP["url"] =~ "^/grav_path/(system|user|vendor)/(.*)\.(txt|md|html|yaml|php|twig|sh|bat)$" {
|
||||
url.access-deny = ("")
|
||||
}
|
||||
$HTTP["url"] =~ "^/grav_path/(\.(.*))" {
|
||||
$HTTP["url"] =~ "^/grav_path/(\.(.*))|(\.(.*)/)" {
|
||||
url.access-deny = ("")
|
||||
}
|
||||
url.access-deny = (".md","~",".inc")
|
||||
@@ -3,7 +3,7 @@ server {
|
||||
index index.html index.php;
|
||||
|
||||
## Begin - Server Info
|
||||
root /home/USER/www/html;
|
||||
root /home/user/www/html;
|
||||
server_name localhost;
|
||||
## End - Server Info
|
||||
|
||||
@@ -32,7 +32,7 @@ server {
|
||||
|
||||
## Begin - Security
|
||||
# deny all direct access for these folders
|
||||
location ~* /(.git|cache|bin|logs|backups|tests)/.*$ { return 403; }
|
||||
location ~* /(.git|cache|bin|logs|backups)/.*$ { return 403; }
|
||||
# deny running scripts inside core system folders
|
||||
location ~* /(system|vendor)/.*\.(txt|xml|md|html|yaml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
|
||||
# deny running scripts inside user folder
|
||||
4
system/assets/jquery/jquery-2.x.min.js
vendored
@@ -1,19 +1,110 @@
|
||||
body header {
|
||||
background: #8552A2;
|
||||
body {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
body .left-panel {
|
||||
background: inherit;
|
||||
body header {
|
||||
background: #349886;
|
||||
border-left: 8px solid #29796B;
|
||||
}
|
||||
|
||||
body .clipboard {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcAQMAAABIw03XAAAAA3NCSVQICAjb4U/gAAAABlBMVEX///////9VfPVsAAAAAnRSTlP/AOW3MEoAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAFnRFWHRDcmVhdGlvbiBUaW1lADEwLzE1LzE0xr/LJAAAADhJREFUCJlj+P///wcGBPGDQR5E8OMi2IEEczOIaAQRHSCioQBGHAAR/7AT/z+DiA8MMALVXhABAJf9Sr5aY+UFAAAAAElFTkSuQmCC);
|
||||
}
|
||||
|
||||
body .exc-title-primary {
|
||||
color: #fff;
|
||||
color: #1C3631;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
body .exc-title {
|
||||
color: #ddd;
|
||||
color: #2F5B52;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
body .data-table-container label {
|
||||
color: #0082BA;
|
||||
}
|
||||
|
||||
body .frame {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
body .frames-container {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body .active .frame-class {
|
||||
color: #E3D8E9;
|
||||
}
|
||||
|
||||
body .frame-class {
|
||||
color: #9055AF;
|
||||
}
|
||||
|
||||
body .frame.active {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
background-color: #9055AF;
|
||||
}
|
||||
|
||||
body .frame:not(.active):hover {
|
||||
background: #e6e6e6;
|
||||
background: #e9e9e9;
|
||||
}
|
||||
|
||||
body .frame-file, body .data-table tbody {
|
||||
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
body .frame-code {
|
||||
background: #305669;
|
||||
border-left: 8px solid #253A47;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
body .frame-code .frame-file {
|
||||
background: #253A47;
|
||||
color: #eee;
|
||||
text-shadow: none;
|
||||
box-shadow: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
body .frame-code .frame-file strong {
|
||||
color: #fff;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body .frame-comments {
|
||||
background: #283E4D;
|
||||
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
body .frame-comments.empty:before {
|
||||
color: #789AAB;
|
||||
}
|
||||
|
||||
body .details-container {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
body .details {
|
||||
background-color: #eee;
|
||||
border-left: 8px solid #ddd;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
body .code-block {
|
||||
background: #2C4454;
|
||||
box-shadow: none;
|
||||
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
body .handler.active {
|
||||
background: #666;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ form:
|
||||
summary.size:
|
||||
type: text
|
||||
size: x-small
|
||||
append: PLUGIN_ADMIN.CHARACTERS
|
||||
label: PLUGIN_ADMIN.SUMMARY_SIZE
|
||||
help: PLUGIN_ADMIN.SUMMARY_SIZE_HELP
|
||||
validate:
|
||||
|
||||
@@ -2,7 +2,6 @@ title: PLUGIN_ADMIN.FILE_STREAMS
|
||||
|
||||
form:
|
||||
validation: loose
|
||||
hidden: true
|
||||
fields:
|
||||
schemes.xxx:
|
||||
type: array
|
||||
|
||||
@@ -20,18 +20,6 @@ form:
|
||||
show_root: false
|
||||
help: PLUGIN_ADMIN.HOME_PAGE_HELP
|
||||
|
||||
home.hide_in_urls:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.HIDE_HOME_IN_URLS
|
||||
help: PLUGIN_ADMIN.HIDE_HOME_IN_URLS_HELP
|
||||
highlight: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
|
||||
pages.theme:
|
||||
type: themeselect
|
||||
classes: fancy
|
||||
@@ -56,7 +44,7 @@ form:
|
||||
size: medium
|
||||
classes: fancy
|
||||
help: PLUGIN_ADMIN.TIMEZONE_HELP
|
||||
data-options@: '\Grav\Common\Utils::timezones'
|
||||
'@data-options': '\Grav\Common\Utils::timezones'
|
||||
default: ''
|
||||
options:
|
||||
'': 'Default (Server Timezone)'
|
||||
@@ -69,7 +57,9 @@ form:
|
||||
label: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT
|
||||
help: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT_HELP
|
||||
placeholder: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT_PLACEHOLDER
|
||||
data-options@: '\Grav\Common\Utils::dateFormats'
|
||||
'@data-options': '\Grav\Common\Utils::dateFormats'
|
||||
options:
|
||||
"": Auto Guess or Enter Custom
|
||||
validate:
|
||||
type: string
|
||||
|
||||
@@ -125,7 +115,6 @@ form:
|
||||
pages.list.count:
|
||||
type: text
|
||||
size: x-small
|
||||
append: PLUGIN_ADMIN.PAGES
|
||||
label: PLUGIN_ADMIN.DEFAULT_PAGE_COUNT
|
||||
help: PLUGIN_ADMIN.DEFAULT_PAGE_COUNT_HELP
|
||||
validate:
|
||||
@@ -232,38 +221,6 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
pages.twig_first:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.TWIG_FIRST
|
||||
help: PLUGIN_ADMIN.TWIG_FIRST_HELP
|
||||
highlight: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
pages.frontmatter.process_twig:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.FRONTMATTER_PROCESS_TWIG
|
||||
help: PLUGIN_ADMIN.FRONTMATTER_PROCESS_TWIG_HELP
|
||||
highlight: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
pages.frontmatter.ignore_fields:
|
||||
type: selectize
|
||||
size: large
|
||||
placeholder: "e.g. forms"
|
||||
label: PLUGIN_ADMIN.FRONTMATTER_IGNORE_FIELDS
|
||||
help: PLUGIN_ADMIN.FRONTMATTER_IGNORE_FIELDS_HELP
|
||||
classes: fancy
|
||||
validate:
|
||||
type: commalist
|
||||
|
||||
languages:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.LANGUAGES
|
||||
@@ -357,7 +314,6 @@ form:
|
||||
pages.expires:
|
||||
type: text
|
||||
size: small
|
||||
append: NICETIME.SECOND_PLURAL
|
||||
label: PLUGIN_ADMIN.EXPIRES
|
||||
help: PLUGIN_ADMIN.EXPIRES_HELP
|
||||
validate:
|
||||
@@ -493,7 +449,6 @@ form:
|
||||
cache.lifetime:
|
||||
type: text
|
||||
size: small
|
||||
append: NICETIME.SECOND_PLURAL
|
||||
label: PLUGIN_ADMIN.LIFETIME
|
||||
help: PLUGIN_ADMIN.LIFETIME_HELP
|
||||
validate:
|
||||
@@ -532,7 +487,7 @@ form:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.TWIG_DEBUG
|
||||
help: PLUGIN_ADMIN.TWIG_DEBUG_HELP
|
||||
highlight: 1
|
||||
highlight: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
@@ -589,28 +544,6 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
assets.css_pipeline_include_externals:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.CSS_PIPELINE_INCLUDE_EXTERNALS
|
||||
help: PLUGIN_ADMIN.CSS_PIPELINE_INCLUDE_EXTERNALS_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
assets.css_pipeline_before_excludes:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.CSS_PIPELINE_BEFORE_EXCLUDES
|
||||
help: PLUGIN_ADMIN.CSS_PIPELINE_BEFORE_EXCLUDES_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
assets.css_minify:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.CSS_MINIFY
|
||||
@@ -655,28 +588,6 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
assets.js_pipeline_include_externals:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.JAVASCRIPT_PIPELINE_INCLUDE_EXTERNALS
|
||||
help: PLUGIN_ADMIN.JAVASCRIPT_PIPELINE_INCLUDE_EXTERNALS_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
assets.js_pipeline_before_excludes:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.JAVASCRIPT_PIPELINE_BEFORE_EXCLUDES
|
||||
help: PLUGIN_ADMIN.JAVASCRIPT_PIPELINE_BEFORE_EXCLUDES_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
assets.js_minify:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.JAVASCRIPT_MINIFY
|
||||
@@ -769,7 +680,6 @@ form:
|
||||
fields:
|
||||
images.default_image_quality:
|
||||
type: text
|
||||
append: '%'
|
||||
label: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY
|
||||
help: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY_HELP
|
||||
classes: x-small
|
||||
@@ -796,8 +706,8 @@ form:
|
||||
help: PLUGIN_ADMIN.CACHE_PERMS_HELP
|
||||
highlight: '0755'
|
||||
options:
|
||||
'0755': '0755'
|
||||
'0775': '0775'
|
||||
1: '0755'
|
||||
0: '0775'
|
||||
|
||||
|
||||
images.debug:
|
||||
@@ -813,7 +723,6 @@ form:
|
||||
|
||||
media.upload_limit:
|
||||
type: text
|
||||
append: bytes
|
||||
label: PLUGIN_ADMIN.UPLOAD_LIMIT
|
||||
help: PLUGIN_ADMIN.UPLOAD_LIMIT_HELP
|
||||
classes: small
|
||||
@@ -872,7 +781,6 @@ form:
|
||||
session.timeout:
|
||||
type: text
|
||||
size: small
|
||||
append: NICETIME.SECOND_PLURAL
|
||||
label: PLUGIN_ADMIN.TIMEOUT
|
||||
help: PLUGIN_ADMIN.TIMEOUT_HELP
|
||||
validate:
|
||||
@@ -885,29 +793,6 @@ form:
|
||||
label: PLUGIN_ADMIN.NAME
|
||||
help: PLUGIN_ADMIN.SESSION_NAME_HELP
|
||||
|
||||
session.secure:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.SESSION_SECURE
|
||||
help: PLUGIN_ADMIN.SESSION_SECURE_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
default: false
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
session.httponly:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.SESSION_HTTPONLY
|
||||
help: PLUGIN_ADMIN.SESSION_HTTPONLY_HELP
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
default: true
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
advanced:
|
||||
type: section
|
||||
@@ -915,33 +800,6 @@ form:
|
||||
underline: true
|
||||
|
||||
fields:
|
||||
gpm.releases:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.GPM_RELEASES
|
||||
highlight: stable
|
||||
help: PLUGIN_ADMIN.GPM_RELEASES_HELP
|
||||
options:
|
||||
stable: PLUGIN_ADMIN.STABLE
|
||||
testing: PLUGIN_ADMIN.TESTING
|
||||
|
||||
gpm.proxy_url:
|
||||
type: text
|
||||
size: medium
|
||||
placeholder: "e.g. 127.0.0.1:3128"
|
||||
label: PLUGIN_ADMIN.PROXY_URL
|
||||
help: PLUGIN_ADMIN.PROXY_URL_HELP
|
||||
|
||||
reverse_proxy_setup:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.REVERSE_PROXY
|
||||
highlight: 0
|
||||
help: PLUGIN_ADMIN.REVERSE_PROXY_HELP
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
wrapped_site:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.WRAPPED_SITE
|
||||
|
||||
@@ -5,4 +5,4 @@ form:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PAGE
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parents'
|
||||
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||
|
||||
@@ -2,7 +2,7 @@ title: PLUGIN_ADMIN.DEFAULT
|
||||
|
||||
rules:
|
||||
slug:
|
||||
pattern: "[a-zа-я][a-zа-я0-9_\-]+"
|
||||
pattern: "[a-z][a-z0-9_\-]+"
|
||||
min: 2
|
||||
max: 80
|
||||
|
||||
@@ -29,6 +29,7 @@ form:
|
||||
|
||||
content:
|
||||
type: markdown
|
||||
showPreview: true
|
||||
validate:
|
||||
type: textarea
|
||||
|
||||
@@ -44,7 +45,7 @@ form:
|
||||
|
||||
publishing:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.PUBLISHING
|
||||
title: Publishing
|
||||
underline: true
|
||||
|
||||
fields:
|
||||
@@ -138,8 +139,8 @@ form:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\admin::rawRoute'
|
||||
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||
'@data-default': '\Grav\Plugin\admin::route'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
|
||||
@@ -149,7 +150,7 @@ form:
|
||||
label: PLUGIN_ADMIN.PAGE_FILE
|
||||
help: PLUGIN_ADMIN.PAGE_FILE_HELP
|
||||
default: default
|
||||
data-options@: '\Grav\Common\Page\Pages::pageTypes'
|
||||
'@data-options': '\Grav\Common\Page\Pages::pageTypes'
|
||||
|
||||
header.body_classes:
|
||||
type: text
|
||||
@@ -177,19 +178,6 @@ form:
|
||||
|
||||
fields:
|
||||
|
||||
header.dateformat:
|
||||
toggleable: true
|
||||
type: select
|
||||
size: medium
|
||||
selectize:
|
||||
create: true
|
||||
label: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT
|
||||
help: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT_HELP
|
||||
placeholder: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT_PLACEHOLDER
|
||||
data-options@: '\Grav\Common\Utils::dateFormats'
|
||||
validate:
|
||||
type: string
|
||||
|
||||
header.menu:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.MENU
|
||||
@@ -215,7 +203,7 @@ form:
|
||||
type: checkboxes
|
||||
label: PLUGIN_ADMIN.PROCESS
|
||||
toggleable: true
|
||||
config-default@: system.pages.process
|
||||
'@config-default': system.pages.process
|
||||
default:
|
||||
markdown: true
|
||||
twig: false
|
||||
@@ -230,7 +218,7 @@ form:
|
||||
label: PLUGIN_ADMIN.DEFAULT_CHILD_TYPE
|
||||
default: default
|
||||
placeholder: PLUGIN_ADMIN.USE_GLOBAL
|
||||
data-options@: '\Grav\Common\Page\Pages::types'
|
||||
'@data-options': '\Grav\Common\Page\Pages::types'
|
||||
|
||||
header.routable:
|
||||
type: toggle
|
||||
@@ -268,9 +256,12 @@ form:
|
||||
type: bool
|
||||
|
||||
header.template:
|
||||
type: text
|
||||
type: select
|
||||
toggleable: true
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
|
||||
default: default
|
||||
'@data-options': '\Grav\Common\Page\Pages::types'
|
||||
|
||||
header.append_url_extension:
|
||||
type: text
|
||||
|
||||
@@ -18,7 +18,7 @@ form:
|
||||
label: PLUGIN_ADMIN.ITEMS
|
||||
default: '@self.modular'
|
||||
options:
|
||||
'@self.modular': Modular Children
|
||||
'@self.modular': Children
|
||||
|
||||
header.content.order.by:
|
||||
type: select
|
||||
|
||||
@@ -29,8 +29,10 @@ form:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PAGE
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\admin::rawRoute'
|
||||
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||
'@data-default': '\Grav\Plugin\admin::route'
|
||||
options:
|
||||
'': PLUGIN_ADMIN.DEFAULT_OPTION_SELECT
|
||||
validate:
|
||||
required: true
|
||||
|
||||
@@ -40,7 +42,7 @@ form:
|
||||
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
|
||||
help: PLUGIN_ADMIN.PAGE_FILE_HELP
|
||||
default: default
|
||||
data-options@: '\Grav\Common\Page\Pages::modularTypes'
|
||||
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -19,22 +19,13 @@ form:
|
||||
|
||||
fields:
|
||||
frontmatter:
|
||||
classes: frontmatter
|
||||
type: editor
|
||||
type: frontmatter
|
||||
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
|
||||
showPreview: true
|
||||
|
||||
uploads:
|
||||
type: pagemedia
|
||||
@@ -78,8 +69,8 @@ form:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\admin::rawRoute'
|
||||
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||
'@data-default': '\Grav\Plugin\admin::route'
|
||||
options:
|
||||
'': PLUGIN_ADMIN.DEFAULT_OPTION_SELECT
|
||||
validate:
|
||||
@@ -90,7 +81,7 @@ form:
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
|
||||
default: default
|
||||
data-options@: '\Grav\Common\Page\Pages::modularTypes'
|
||||
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ form:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\admin::rawRoute'
|
||||
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||
'@data-default': '\Grav\Plugin\admin::route'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
|
||||
@@ -31,8 +31,8 @@ form:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT_PAGE
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\admin::getLastPageRoute'
|
||||
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||
'@data-default': '\Grav\Plugin\admin::getLastPageRoute'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
validate:
|
||||
@@ -43,8 +43,8 @@ form:
|
||||
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::getLastPageName'
|
||||
'@data-options': '\Grav\Common\Page\Pages::types'
|
||||
'@data-default': '\Grav\Plugin\admin::getLastPageName'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
rules:
|
||||
slug:
|
||||
pattern: "[a-z][a-z0-9_\-]+"
|
||||
min: 2
|
||||
max: 80
|
||||
|
||||
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:
|
||||
type: 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::getLastPageRoute'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
validate:
|
||||
required: true
|
||||
|
||||
blueprint:
|
||||
type: blueprint
|
||||
@@ -19,22 +19,13 @@ form:
|
||||
|
||||
fields:
|
||||
frontmatter:
|
||||
classes: frontmatter
|
||||
type: editor
|
||||
type: frontmatter
|
||||
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
|
||||
showPreview: true
|
||||
|
||||
uploads:
|
||||
type: pagemedia
|
||||
@@ -78,8 +69,8 @@ form:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.PARENT
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
|
||||
data-default@: '\Grav\Plugin\admin::rawRoute'
|
||||
'@data-options': '\Grav\Common\Page\Pages::parents'
|
||||
'@data-default': '\Grav\Plugin\admin::route'
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
|
||||
@@ -89,7 +80,7 @@ form:
|
||||
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
|
||||
help: PLUGIN_ADMIN.DISPLAY_TEMPLATE_HELP
|
||||
default: default
|
||||
data-options@: '\Grav\Common\Page\Pages::types'
|
||||
'@data-options': '\Grav\Common\Page\Pages::types'
|
||||
validate:
|
||||
required: true
|
||||
|
||||
|
||||
@@ -1,92 +1,85 @@
|
||||
title: Site
|
||||
form:
|
||||
validation: loose
|
||||
|
||||
fields:
|
||||
|
||||
info:
|
||||
type: userinfo
|
||||
size: large
|
||||
content:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.ACCOUNT
|
||||
|
||||
content:
|
||||
type: section
|
||||
title: PLUGIN_ADMIN.ACCOUNT
|
||||
underline: true
|
||||
fields:
|
||||
username:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.USERNAME
|
||||
disabled: true
|
||||
readonly: true
|
||||
|
||||
email:
|
||||
type: email
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.EMAIL
|
||||
validate:
|
||||
type: email
|
||||
message: PLUGIN_ADMIN.EMAIL_VALIDATION_MESSAGE
|
||||
required: true
|
||||
|
||||
username:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.USERNAME
|
||||
disabled: true
|
||||
readonly: true
|
||||
password:
|
||||
type: password
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.PASSWORD
|
||||
validate:
|
||||
required: false
|
||||
message: PLUGIN_ADMIN.PASSWORD_VALIDATION_MESSAGE
|
||||
pattern: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}'
|
||||
|
||||
email:
|
||||
type: email
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.EMAIL
|
||||
validate:
|
||||
type: email
|
||||
message: PLUGIN_ADMIN.EMAIL_VALIDATION_MESSAGE
|
||||
required: true
|
||||
fullname:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.FULL_NAME
|
||||
validate:
|
||||
required: true
|
||||
|
||||
password:
|
||||
type: password
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.PASSWORD
|
||||
validate:
|
||||
required: false
|
||||
message: PLUGIN_ADMIN.PASSWORD_VALIDATION_MESSAGE
|
||||
pattern: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}'
|
||||
title:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.TITLE
|
||||
|
||||
fullname:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.FULL_NAME
|
||||
validate:
|
||||
required: true
|
||||
language:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.LANGUAGE
|
||||
size: medium
|
||||
classes: fancy
|
||||
'@data-options': '\Grav\Plugin\admin::adminLanguages'
|
||||
default: 'en'
|
||||
help: PLUGIN_ADMIN.LANGUAGE_HELP
|
||||
|
||||
title:
|
||||
type: text
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.TITLE
|
||||
security:
|
||||
title: Security
|
||||
type: section
|
||||
security: admin.super
|
||||
|
||||
language:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.LANGUAGE
|
||||
size: medium
|
||||
classes: fancy
|
||||
data-options@: '\Grav\Plugin\admin::adminLanguages'
|
||||
default: 'en'
|
||||
help: PLUGIN_ADMIN.LANGUAGE_HELP
|
||||
fields:
|
||||
groups:
|
||||
type: selectize
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.GROUPS
|
||||
'@data-options': '\Grav\User\Groups::groups'
|
||||
classes: fancy
|
||||
help: PLUGIN_ADMIN.GROUPS_HELP
|
||||
validate:
|
||||
type: commalist
|
||||
|
||||
security:
|
||||
title: PLUGIN_ADMIN.ACCESS_LEVELS
|
||||
type: section
|
||||
security: admin.super
|
||||
underline: true
|
||||
|
||||
fields:
|
||||
groups:
|
||||
type: selectize
|
||||
size: large
|
||||
label: PLUGIN_ADMIN.GROUPS
|
||||
data-options@: '\Grav\User\Groups::groups'
|
||||
classes: fancy
|
||||
help: PLUGIN_ADMIN.GROUPS_HELP
|
||||
validate:
|
||||
type: commalist
|
||||
|
||||
access.admin:
|
||||
type: array
|
||||
label: PLUGIN_ADMIN.ADMIN_ACCESS
|
||||
multiple: false
|
||||
validate:
|
||||
access.admin:
|
||||
type: array
|
||||
label: PLUGIN_ADMIN.ADMIN_ACCESS
|
||||
multiple: false
|
||||
validate:
|
||||
type: array
|
||||
|
||||
access.site:
|
||||
type: array
|
||||
label: PLUGIN_ADMIN.SITE_ACCESS
|
||||
multiple: false
|
||||
validate:
|
||||
access.site:
|
||||
type: array
|
||||
label: PLUGIN_ADMIN.SITE_ACCESS
|
||||
multiple: false
|
||||
validate:
|
||||
type: array
|
||||
@@ -41,4 +41,4 @@ form:
|
||||
label: PLUGIN_ADMIN.SITE_ACCESS
|
||||
multiple: false
|
||||
validate:
|
||||
type: array
|
||||
type: array
|
||||
@@ -30,7 +30,7 @@ gif:
|
||||
|
||||
svg:
|
||||
type: vector
|
||||
thumb: media/thumb.png
|
||||
thumb: media/thumb-gif.png
|
||||
mime: image/svg+xml
|
||||
|
||||
mp4:
|
||||
@@ -53,14 +53,6 @@ flv:
|
||||
type: video
|
||||
thumb: media/thumb-flv.png
|
||||
mime: video/x-flv
|
||||
webm:
|
||||
type: video
|
||||
thumb: media/thumb.png
|
||||
mime: video/webm
|
||||
ogv:
|
||||
type: video
|
||||
thumb: media/thumb-ogg.png
|
||||
mime: video/ogg
|
||||
|
||||
mp3:
|
||||
type: audio
|
||||
@@ -176,10 +168,6 @@ zip:
|
||||
type: file
|
||||
thumb: media/thumb-zip.png
|
||||
mime: application/zip
|
||||
7z:
|
||||
type: file
|
||||
thumb: media/thumb-7zip.png
|
||||
mime: application/x-7z-compressed
|
||||
gz:
|
||||
type: file
|
||||
thumb: media/thumb-gz.png
|
||||
|
||||
@@ -16,12 +16,12 @@ summary:
|
||||
delimiter: === # The summary delimiter
|
||||
|
||||
redirects:
|
||||
# /redirect-test: / # Redirect test goes to home page
|
||||
# /old/(.*): /new/$1 # Would redirect /old/my-page to /new/my-page
|
||||
/redirect-test: / # Redirect test goes to home page
|
||||
/old/(.*): /new/$1 # Would redirect /old/my-page to /new/my-page
|
||||
|
||||
routes:
|
||||
# /something/else: '/blog/sample-3' # Alias for /blog/sample-3
|
||||
# /new/(.*): '/blog/$1' # Regex any /new/my-page URL to /blog/my-page Route
|
||||
/something/else: '/blog/sample-3' # Alias for /blog/sample-3
|
||||
/new/(.*): '/blog/$1' # Regex any /new/my-page URL to /blog/my-page Route
|
||||
|
||||
blog:
|
||||
route: '/blog' # Custom value added (accessible via system.blog.route)
|
||||
|
||||
@@ -3,8 +3,6 @@ timezone: '' # Valid values: http://php.net/manua
|
||||
default_locale: # Default locale (defaults to system)
|
||||
param_sep: ':' # Parameter separator, use ';' for Apache on windows
|
||||
wrapped_site: false # For themes/plugins to know if Grav is wrapped by another platform
|
||||
reverse_proxy_setup: false # Running in a reverse proxy scenario with different webserver ports than proxy
|
||||
|
||||
|
||||
languages:
|
||||
supported: [] # List of languages supported. eg: [en, fr, de]
|
||||
@@ -17,7 +15,6 @@ languages:
|
||||
|
||||
home:
|
||||
alias: '/home' # Default path for home, ie /
|
||||
hide_in_urls: false # Hide the home route in URLs
|
||||
|
||||
pages:
|
||||
theme: antimatter # Default theme (defaults to "antimatter" theme)
|
||||
@@ -34,7 +31,6 @@ pages:
|
||||
process:
|
||||
markdown: true # Process Markdown
|
||||
twig: false # Process Twig
|
||||
twig_first: false # Process Twig before markdown when processing both on a page
|
||||
events:
|
||||
page: true # Enable page level events
|
||||
twig: true # Enable twig level events
|
||||
@@ -59,9 +55,6 @@ pages:
|
||||
ignore_folders: [.git, .idea] # Folders to ignore in Pages
|
||||
ignore_hidden: true # Ignore all Hidden files and folders
|
||||
url_taxonomy_filters: true # Enable auto-magic URL-based taxonomy filters for page collections
|
||||
frontmatter:
|
||||
process_twig: false # Should the frontmatter be processed to replace Twig variables?
|
||||
ignore_fields: ['form'] # Fields that might contain Twig variables and should not be processed
|
||||
|
||||
cache:
|
||||
enabled: true # Set to true to enable caching
|
||||
@@ -74,7 +67,7 @@ cache:
|
||||
|
||||
twig:
|
||||
cache: true # Set to true to enable twig caching
|
||||
debug: true # Enable Twig debug
|
||||
debug: false # Enable Twig debug
|
||||
auto_reload: true # Refresh cache on changes
|
||||
autoescape: false # Autoescape Twig vars
|
||||
undefined_functions: true # Allow undefined functions
|
||||
@@ -83,18 +76,14 @@ twig:
|
||||
|
||||
assets: # Configuration for Assets Manager (JS, CSS)
|
||||
css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file
|
||||
css_pipeline_include_externals: true # Include external URLs in the pipeline by default
|
||||
css_pipeline_before_excludes: true # Render the pipeline before any excluded files
|
||||
css_minify: true # Minify the CSS during pipelining
|
||||
css_minify_windows: false # Minify Override for Windows platforms. False by default due to ThreadStackSize
|
||||
css_rewrite: true # Rewrite any CSS relative URLs during pipelining
|
||||
js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file
|
||||
js_pipeline_include_externals: true # Include external URLs in the pipeline by default
|
||||
js_pipeline_before_excludes: true # Render the pipeline before any excluded files
|
||||
js_minify: true # Minify the JS during pipelining
|
||||
enable_asset_timestamp: false # Enable asset timestamps
|
||||
collections:
|
||||
jquery: system://assets/jquery/jquery-2.x.min.js
|
||||
jquery: system://assets/jquery/jquery-2.1.4.min.js
|
||||
|
||||
errors:
|
||||
display: false # Display full backtrace-style error page
|
||||
@@ -108,7 +97,7 @@ debugger:
|
||||
images:
|
||||
default_image_quality: 85 # Default image quality to use when resampling images (85%)
|
||||
cache_all: false # Cache all image by default
|
||||
cache_perms: '0755' # MUST BE IN QUOTES!! Default cache folder perms. Usually '0755' or '0775'
|
||||
cache_perms: 0755 # Default cache folder perms. Usually 0755 or 0775 depending on setup
|
||||
debug: false # Show an overlay over images indicating the pixel depth of the image when working with retina for example
|
||||
|
||||
media:
|
||||
@@ -121,9 +110,5 @@ session:
|
||||
enabled: true # Enable Session support
|
||||
timeout: 1800 # Timeout in seconds
|
||||
name: grav-site # Name prefix of the session cookie. Use alphanumeric, dashes or underscores only. Do not use dots in the session name
|
||||
secure: false # Set session secure. If true, indicates that communication for this cookie must be over an encrypted transmission. Enable this only on sites that run exclusively on HTTPS
|
||||
httponly: true # Set session HTTP only. If true, indicates that cookies should be used only over HTTP, and JavaScript modification is not allowed.
|
||||
|
||||
gpm:
|
||||
releases: testing # Set to either 'stable' or 'testing'
|
||||
proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128)
|
||||
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.1.0-rc.1');
|
||||
define('GRAV_TESTING', true);
|
||||
define('GRAV_VERSION', '1.0.2');
|
||||
define('DS', '/');
|
||||
define('GRAV_PHP_MIN', '5.5.9');
|
||||
|
||||
// Directories and Paths
|
||||
if (!defined('GRAV_ROOT')) {
|
||||
@@ -14,7 +12,9 @@ if (!defined('GRAV_ROOT')) {
|
||||
define('ROOT_DIR', GRAV_ROOT . '/');
|
||||
define('USER_PATH', 'user/');
|
||||
define('USER_DIR', ROOT_DIR . USER_PATH);
|
||||
define('SYSTEM_DIR', ROOT_DIR .'system/');
|
||||
define('CACHE_DIR', ROOT_DIR . 'cache/');
|
||||
define('LOG_DIR', ROOT_DIR .'logs/');
|
||||
|
||||
// DEPRECATED: Do not use!
|
||||
define('ASSETS_DIR', ROOT_DIR . 'assets/');
|
||||
@@ -22,12 +22,10 @@ define('IMAGES_DIR', ROOT_DIR . 'images/');
|
||||
define('ACCOUNTS_DIR', USER_DIR .'accounts/');
|
||||
define('PAGES_DIR', USER_DIR .'pages/');
|
||||
define('DATA_DIR', USER_DIR .'data/');
|
||||
define('SYSTEM_DIR', ROOT_DIR .'system/');
|
||||
define('LIB_DIR', SYSTEM_DIR .'src/');
|
||||
define('PLUGINS_DIR', USER_DIR .'plugins/');
|
||||
define('THEMES_DIR', USER_DIR .'themes/');
|
||||
define('VENDOR_DIR', ROOT_DIR .'vendor/');
|
||||
define('LOG_DIR', ROOT_DIR .'logs/');
|
||||
// END DEPRECATED
|
||||
|
||||
// Some extensions
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 123 B |
@@ -1,79 +1,37 @@
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- vybavení
|
||||
- informace
|
||||
- rýže
|
||||
- peníze
|
||||
- druhy
|
||||
- série
|
||||
- ryba
|
||||
- ovce
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: lidé
|
||||
man: muži
|
||||
child: děti
|
||||
sex: pohlaví
|
||||
move: pohyby
|
||||
INFLECTOR_ORDINALS:
|
||||
default: '.'
|
||||
first: '.'
|
||||
second: '.'
|
||||
third: '.'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Datum nebylo vloženo
|
||||
BAD_DATE: Chybné datum
|
||||
AGO: zpět
|
||||
FROM_NOW: od teď
|
||||
SECOND: sekunda
|
||||
MINUTE: minuta
|
||||
HOUR: hodina
|
||||
DAY: den
|
||||
WEEK: týden
|
||||
MONTH: měsíc
|
||||
YEAR: rok
|
||||
DECADE: dekáda
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: hod
|
||||
WK: t
|
||||
MO: m
|
||||
YR: r
|
||||
DEC: dek
|
||||
SECOND_PLURAL: sekundy
|
||||
MINUTE_PLURAL: minuty
|
||||
HOUR_PLURAL: hodiny
|
||||
DAY_PLURAL: dny
|
||||
WEEK_PLURAL: týdny
|
||||
MONTH_PLURAL: měsíce
|
||||
YEAR_PLURAL: roky
|
||||
DECADE_PLURAL: dekády
|
||||
SEC_PLURAL: sek
|
||||
MIN_PLURAL: min
|
||||
HR_PLURAL: hod
|
||||
WK_PLURAL: t
|
||||
MO_PLURAL: m
|
||||
YR_PLURAL: r
|
||||
DEC_PLURAL: dek
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Ověření se nezdařilo:</b>'
|
||||
MISSING_REQUIRED_FIELD: 'Chybí požadované pole:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- ledna
|
||||
- února
|
||||
- března
|
||||
- dubna
|
||||
- května
|
||||
- června
|
||||
- července
|
||||
- srpna
|
||||
- září
|
||||
- října
|
||||
- listopadu
|
||||
- prosince
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Pondělí
|
||||
- Úterý
|
||||
- Středa
|
||||
- Čtvrtek
|
||||
- Pátek
|
||||
- Sobota
|
||||
- Neděle
|
||||
NO_DATE_PROVIDED: Datum nebylo vloženo
|
||||
BAD_DATE: Chybné datum
|
||||
AGO: zpět
|
||||
FROM_NOW: od teď
|
||||
SECOND: sekunda
|
||||
MINUTE: minuta
|
||||
HOUR: hodina
|
||||
DAY: den
|
||||
WEEK: týden
|
||||
MONTH: měsíc
|
||||
YEAR: rok
|
||||
DECADE: dekáda
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: hod
|
||||
DAY: den
|
||||
WK: t
|
||||
MO: m
|
||||
YR: r
|
||||
DEC: dek
|
||||
SECOND_PLURAL: sekundy
|
||||
MINUTE_PLURAL: minuty
|
||||
HOUR_PLURAL: hodiny
|
||||
DAY_PLURAL: dny
|
||||
WEEK_PLURAL: týdny
|
||||
MONTH_PLURAL: měsíce
|
||||
YEAR_PLURAL: roky
|
||||
DECADE_PLURAL: dekády
|
||||
SEC_PLURAL: sek
|
||||
MIN_PLURAL: min
|
||||
HR_PLURAL: hod
|
||||
DAY_PLURAL: dny
|
||||
WK_PLURAL: t
|
||||
MO_PLURAL: m
|
||||
YR_PLURAL: r
|
||||
DEC_PLURAL: dek
|
||||
|
||||
@@ -1,82 +1,43 @@
|
||||
FRONTMATTER_ERROR_PAGE: |
|
||||
---
|
||||
title: %1$s
|
||||
---
|
||||
# Fehler: Frontmatter enthält Fehler
|
||||
|
||||
Pfad: `%2$s`
|
||||
|
||||
**%3$s **
|
||||
|
||||
```
|
||||
%4$s
|
||||
```
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
1: Informationen
|
||||
2: Reis
|
||||
3: Geld
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: Personen
|
||||
man: Menschen
|
||||
child: Kinder
|
||||
sex: Geschlecht
|
||||
move: Züge
|
||||
'person': 'Personen'
|
||||
'man': 'Menschen'
|
||||
'child': 'Kinder'
|
||||
'sex': 'Geschlecht'
|
||||
'move': 'Züge'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Keine Daten vorhanden
|
||||
BAD_DATE: Falsches Datum
|
||||
AGO: her
|
||||
FROM_NOW: ab jetzt
|
||||
SECOND: Sekunde
|
||||
MINUTE: Minute
|
||||
HOUR: Stunde
|
||||
DAY: Tag
|
||||
WEEK: Woche
|
||||
MONTH: Monat
|
||||
YEAR: Jahr
|
||||
DECADE: Dekade
|
||||
SEC: sek
|
||||
MIN: Min
|
||||
HR: std
|
||||
WK: wo
|
||||
YR: yh
|
||||
DEC: Jz
|
||||
SECOND_PLURAL: Sekunden
|
||||
MINUTE_PLURAL: Minuten
|
||||
HOUR_PLURAL: Stunden
|
||||
DAY_PLURAL: Tage
|
||||
WEEK_PLURAL: Wochen
|
||||
MONTH_PLURAL: Monate
|
||||
YEAR_PLURAL: Jahre
|
||||
DECADE_PLURAL: Dekaden
|
||||
SEC_PLURAL: Sekunden
|
||||
MIN_PLURAL: Minuten
|
||||
HR_PLURAL: Stunden
|
||||
WK_PLURAL: Wochen
|
||||
MO_PLURAL: Monate
|
||||
YR_PLURAL: Jahre
|
||||
DEC_PLURAL: Dekaden
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Überprüfung fehlgeschlagen:</b>'
|
||||
INVALID_INPUT: Ungültige Eingabe in
|
||||
MISSING_REQUIRED_FIELD: 'Erforderliches Feld fehlt:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Januar
|
||||
- Februar
|
||||
- März
|
||||
- April
|
||||
- Mai
|
||||
- Juni
|
||||
- Juli
|
||||
- August
|
||||
- Semptember
|
||||
- Oktober
|
||||
- November
|
||||
- Dezember
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Montag
|
||||
- Dienstag
|
||||
- Mittwoch
|
||||
- Donnerstag
|
||||
- Freitag
|
||||
- Samstag
|
||||
- Sonntag
|
||||
NO_DATE_PROVIDED: Keine Daten vorhanden
|
||||
BAD_DATE: Falsches Datum
|
||||
AGO: her
|
||||
FROM_NOW: ab jetzt
|
||||
SECOND: Sekunde
|
||||
MINUTE: Minute
|
||||
HOUR: Stunde
|
||||
DAY: Tag
|
||||
WEEK: Woche
|
||||
MONTH: Monat
|
||||
YEAR: Jahr
|
||||
DECADE: Dekade
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: std
|
||||
DAY: Tag
|
||||
WK: wo
|
||||
MO: mo
|
||||
YR: yh
|
||||
DEC: dec
|
||||
SECOND_PLURAL: Sekunden
|
||||
MINUTE_PLURAL: Minuten
|
||||
HOUR_PLURAL: Stunden
|
||||
DAY_PLURAL: Tage
|
||||
WEEK_PLURAL: Wochen
|
||||
MONTH_PLURAL: Monate
|
||||
YEAR_PLURAL: Jahre
|
||||
DECADE_PLURAL: Dekaden
|
||||
SEC_PLURAL: Sekunden
|
||||
MIN_PLURAL: Minuten
|
||||
HR_PLURAL: Stunden
|
||||
DAY_PLURAL: Tage
|
||||
WK_PLURAL: Wochen
|
||||
MO_PLURAL: Monate
|
||||
YR_PLURAL: Jahre
|
||||
DEC_PLURAL: Dekaden
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Ιανουάριος
|
||||
- Φεβρουάριος
|
||||
- Μάρτιος
|
||||
- Απρίλιος
|
||||
- Μάιος
|
||||
- Ιούνιος
|
||||
- Ιούλιος
|
||||
- Αύγουστος
|
||||
- Σεπτέμβριος
|
||||
- Οκτώβριος
|
||||
- Νοέμβριος
|
||||
- Δεκέμβριος
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Δευτέρα
|
||||
- Τρλιτη
|
||||
- Τετάρτη
|
||||
- Πέμπτη
|
||||
- Παρασκευή
|
||||
- Σαββάτο
|
||||
- Κυριακή
|
||||
@@ -96,5 +96,3 @@ FORM:
|
||||
VALIDATION_FAIL: <b>Validation failed:</b>
|
||||
INVALID_INPUT: Invalid input in
|
||||
MISSING_REQUIRED_FIELD: Missing required field:
|
||||
MONTHS_OF_THE_YEAR: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
||||
DAYS_OF_THE_WEEK: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
|
||||
|
||||
@@ -1,75 +1,42 @@
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
0: equipo
|
||||
1: información
|
||||
3: dinero
|
||||
5: series
|
||||
6: pescado
|
||||
7: oveja
|
||||
INFLECTOR_IRREGULAR:
|
||||
man: hombres
|
||||
child: niños
|
||||
sex: sexos
|
||||
INFLECTOR_ORDINALS:
|
||||
first: ro
|
||||
second: do
|
||||
third: ro
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: No se proporcionó fecha
|
||||
BAD_DATE: Fecha erronea
|
||||
AGO: antes
|
||||
FROM_NOW: desde ahora
|
||||
SECOND: segundo
|
||||
MINUTE: minuto
|
||||
HOUR: hora
|
||||
DAY: día
|
||||
WEEK: semana
|
||||
MONTH: mes
|
||||
YEAR: año
|
||||
DECADE: década
|
||||
SEC: seg
|
||||
MIN: min
|
||||
HR: h
|
||||
WK: sem
|
||||
MO: mes
|
||||
YR: año
|
||||
DEC: dec
|
||||
SECOND_PLURAL: segundos
|
||||
MINUTE_PLURAL: minutos
|
||||
HOUR_PLURAL: horas
|
||||
DAY_PLURAL: días
|
||||
WEEK_PLURAL: semanas
|
||||
MONTH_PLURAL: meses
|
||||
YEAR_PLURAL: años
|
||||
DECADE_PLURAL: décadas
|
||||
SEC_PLURAL: segs
|
||||
MIN_PLURAL: mins
|
||||
HR_PLURAL: hs
|
||||
WK_PLURAL: sem
|
||||
MO_PLURAL: mes
|
||||
YR_PLURAL: años
|
||||
DEC_PLURAL: décadas
|
||||
NO_DATE_PROVIDED: No se proporcionó fecha
|
||||
BAD_DATE: Fecha erronea
|
||||
AGO: antes
|
||||
FROM_NOW: desde ahora
|
||||
SECOND: segundo
|
||||
MINUTE: minuto
|
||||
HOUR: hora
|
||||
DAY: dia
|
||||
WEEK: semana
|
||||
MONTH: mes
|
||||
YEAR: año
|
||||
DECADE: decada
|
||||
SEC: seg
|
||||
MIN: min
|
||||
HR: hr
|
||||
DAY: dia
|
||||
WK: sem
|
||||
MO: mes
|
||||
YR: yr
|
||||
DEC: dec
|
||||
SECOND_PLURAL: segundos
|
||||
MINUTE_PLURAL: minutos
|
||||
HOUR_PLURAL: horas
|
||||
DAY_PLURAL: días
|
||||
WEEK_PLURAL: semanas
|
||||
MONTH_PLURAL: meses
|
||||
YEAR_PLURAL: años
|
||||
DECADE_PLURAL: decadas
|
||||
SEC_PLURAL: segs
|
||||
MIN_PLURAL: mins
|
||||
HR_PLURAL: hrs
|
||||
DAY_PLURAL: dias
|
||||
WK_PLURAL: sem
|
||||
MO_PLURAL: mes
|
||||
YR_PLURAL: años
|
||||
DEC_PLURAL: decs
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Falló la validación. </b>'
|
||||
INVALID_INPUT: 'Dato inválido en: '
|
||||
MISSING_REQUIRED_FIELD: 'Falta el campo requerido: '
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Enero
|
||||
- Febrero
|
||||
- Marzo
|
||||
- Abril
|
||||
- Mayo
|
||||
- Junio
|
||||
- Julio
|
||||
- Agosto
|
||||
- Septiembre
|
||||
- Octubre
|
||||
- Noviembre
|
||||
- Diciembre
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Lunes
|
||||
- Martes
|
||||
- Miércoles
|
||||
- Jueves
|
||||
- Viernes
|
||||
- Sábado
|
||||
- Domingo
|
||||
VALIDATION_FAIL: <b>Falló la validación. </b>
|
||||
INVALID_INPUT: "Dato inválido en: "
|
||||
MISSING_REQUIRED_FIELD: "Falta el campo requerido: "
|
||||
|
||||
|
||||
@@ -1,137 +1,98 @@
|
||||
FRONTMATTER_ERROR_PAGE: |
|
||||
---
|
||||
title: %1$s
|
||||
---
|
||||
|
||||
# Erreur : Frontmatter invalide
|
||||
|
||||
Path: `%2$s`
|
||||
|
||||
**%3$s**
|
||||
|
||||
```
|
||||
%4$s
|
||||
```
|
||||
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Erreur : Frontmatter invalide\n\nPath: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_PLURALS:
|
||||
/(quiz)$/i: '\1zes'
|
||||
/^(ox)$/i: '\1en'
|
||||
"/([m|l])ouse$/i": '\1ice'
|
||||
/(matr|vert|ind)ix|ex$/i: '\1ices'
|
||||
/(x|ch|ss|sh)$/i: '\1es'
|
||||
"/([^aeiouy]|qu)ies$/i": '\1y'
|
||||
"/([^aeiouy]|qu)y$/i": '\1ies'
|
||||
/(hive)$/i: '\1s'
|
||||
"/(?:([^f])fe|([lr])f)$/i": '\1\2ves'
|
||||
/sis$/i: ses
|
||||
"/([ti])um$/i": '\1a'
|
||||
/(buffal|tomat)o$/i: '\1oes'
|
||||
/(bu)s$/i: '\1ses'
|
||||
/(alias|status)/i: '\1es'
|
||||
/(octop|vir)us$/i: '\1i'
|
||||
/(ax|test)is$/i: '\1es'
|
||||
/s$/i: s
|
||||
/$/: s
|
||||
'/(quiz)$/i': '\1zes'
|
||||
'/^(ox)$/i': '\1en'
|
||||
'/([m|l])ouse$/i': '\1ice'
|
||||
'/(matr|vert|ind)ix|ex$/i': '\1ices'
|
||||
'/(x|ch|ss|sh)$/i': '\1es'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([^aeiouy]|qu)y$/i': '\1ies'
|
||||
'/(hive)$/i': '\1s'
|
||||
'/(?:([^f])fe|([lr])f)$/i': '\1\2ves'
|
||||
'/sis$/i': 'ses'
|
||||
'/([ti])um$/i': '\1a'
|
||||
'/(buffal|tomat)o$/i': '\1oes'
|
||||
'/(bu)s$/i': '\1ses'
|
||||
'/(alias|status)/i': '\1es'
|
||||
'/(octop|vir)us$/i': '\1i'
|
||||
'/(ax|test)is$/i': '\1es'
|
||||
'/s$/i': 's'
|
||||
'/$/': 's'
|
||||
INFLECTOR_SINGULAR:
|
||||
/(quiz)zes$/i: '\1'
|
||||
/(matr)ices$/i: '\1ix'
|
||||
/(vert|ind)ices$/i: '\1ex'
|
||||
/^(ox)en/i: '\1'
|
||||
/(alias|status)es$/i: '\1'
|
||||
"/([octop|vir])i$/i": '\1us'
|
||||
/(cris|ax|test)es$/i: '\1is'
|
||||
/(shoe)s$/i: '\1'
|
||||
/(o)es$/i: '\1'
|
||||
/(bus)es$/i: '\1'
|
||||
"/([m|l])ice$/i": '\1ouse'
|
||||
/(x|ch|ss|sh)es$/i: '\1'
|
||||
/(m)ovies$/i: '\1ovie'
|
||||
/(s)eries$/i: '\1eries'
|
||||
"/([^aeiouy]|qu)ies$/i": '\1y'
|
||||
"/([lr])ves$/i": '\1f'
|
||||
/(tive)s$/i: '\1'
|
||||
/(hive)s$/i: '\1'
|
||||
"/([^f])ves$/i": '\1fe'
|
||||
/(^analy)ses$/i: '\1sis'
|
||||
/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i: '\1\2sis'
|
||||
"/([ti])a$/i": '\1um'
|
||||
/(n)ews$/i: '\1ews'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- équipement
|
||||
- informations
|
||||
- riz
|
||||
- argent
|
||||
- espèces
|
||||
- séries
|
||||
- poisson
|
||||
- mouton
|
||||
'/(quiz)zes$/i': '\1'
|
||||
'/(matr)ices$/i': '\1ix'
|
||||
'/(vert|ind)ices$/i': '\1ex'
|
||||
'/^(ox)en/i': '\1'
|
||||
'/(alias|status)es$/i': '\1'
|
||||
'/([octop|vir])i$/i': '\1us'
|
||||
'/(cris|ax|test)es$/i': '\1is'
|
||||
'/(shoe)s$/i': '\1'
|
||||
'/(o)es$/i': '\1'
|
||||
'/(bus)es$/i': '\1'
|
||||
'/([m|l])ice$/i': '\1ouse'
|
||||
'/(x|ch|ss|sh)es$/i': '\1'
|
||||
'/(m)ovies$/i': '\1ovie'
|
||||
'/(s)eries$/i': '\1eries'
|
||||
'/([^aeiouy]|qu)ies$/i': '\1y'
|
||||
'/([lr])ves$/i': '\1f'
|
||||
'/(tive)s$/i': '\1'
|
||||
'/(hive)s$/i': '\1'
|
||||
'/([^f])ves$/i': '\1fe'
|
||||
'/(^analy)ses$/i': '\1sis'
|
||||
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2sis'
|
||||
'/([ti])a$/i': '\1um'
|
||||
'/(n)ews$/i': '\1ews'
|
||||
'/s$/i': ''
|
||||
INFLECTOR_UNCOUNTABLE: ['équipment', 'information', 'riz', 'argent', 'espèces', 'séries', 'poisson', 'mouton']
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: personnes
|
||||
man: hommes
|
||||
child: enfants
|
||||
sex: sexes
|
||||
move: déplacements
|
||||
'person': 'personnes'
|
||||
'man': 'Hommes'
|
||||
'child': 'enfants'
|
||||
'sex': 'sexes'
|
||||
'move': 'déplacemements'
|
||||
INFLECTOR_ORDINALS:
|
||||
default: ème
|
||||
first: er
|
||||
second: ème
|
||||
third: ème
|
||||
'default': 'ème'
|
||||
'first': 'er'
|
||||
'second': 'nd'
|
||||
'third': 'ème'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Aucune date fournie
|
||||
BAD_DATE: Date erronée
|
||||
AGO: plus tôt
|
||||
FROM_NOW: à partir de maintenant
|
||||
SECOND: seconde
|
||||
MINUTE: minute
|
||||
HOUR: heure
|
||||
DAY: jour
|
||||
WEEK: semaine
|
||||
MONTH: mois
|
||||
YEAR: année
|
||||
DECADE: décennie
|
||||
SEC: s
|
||||
MIN: m
|
||||
HR: h
|
||||
WK: sem
|
||||
MO: m
|
||||
YR: an
|
||||
DEC: déc
|
||||
SECOND_PLURAL: secondes
|
||||
MINUTE_PLURAL: minutes
|
||||
HOUR_PLURAL: heures
|
||||
DAY_PLURAL: jours
|
||||
WEEK_PLURAL: semaines
|
||||
MONTH_PLURAL: mois
|
||||
YEAR_PLURAL: années
|
||||
DECADE_PLURAL: décennies
|
||||
SEC_PLURAL: s
|
||||
MIN_PLURAL: m
|
||||
HR_PLURAL: h
|
||||
WK_PLURAL: sem
|
||||
MO_PLURAL: mois
|
||||
YR_PLURAL: a
|
||||
DEC_PLURAL: décs
|
||||
NO_DATE_PROVIDED: Aucune date
|
||||
BAD_DATE: Date erronée
|
||||
AGO: plus tôt
|
||||
FROM_NOW: à partir de maintenant
|
||||
SECOND: seconde
|
||||
MINUTE: minute
|
||||
HOUR: heure
|
||||
DAY: jour
|
||||
WEEK: semaine
|
||||
MONTH: mois
|
||||
YEAR: an
|
||||
DECADE: décennie
|
||||
SEC: s
|
||||
MIN: m
|
||||
HR: h
|
||||
DAY: j
|
||||
WK: s
|
||||
MO: m
|
||||
YR: a
|
||||
DEC: d
|
||||
SECOND_PLURAL: secondes
|
||||
MINUTE_PLURAL: minutes
|
||||
HOUR_PLURAL: heures
|
||||
DAY_PLURAL: jours
|
||||
WEEK_PLURAL: semaines
|
||||
MONTH_PLURAL: mois
|
||||
YEAR_PLURAL: années
|
||||
DECADE_PLURAL: décennies
|
||||
SEC_PLURAL: s
|
||||
MIN_PLURAL: m
|
||||
HR_PLURAL: h
|
||||
DAY_PLURAL: j
|
||||
WK_PLURAL: s
|
||||
MO_PLURAL: m
|
||||
YR_PLURAL: a
|
||||
DEC_PLURAL: d
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>La validation a échoué :</b>'
|
||||
INVALID_INPUT: Saisie non valide
|
||||
MISSING_REQUIRED_FIELD: 'Champ obligatoire manquant :'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Janvier
|
||||
- Février
|
||||
- Mars
|
||||
- Avril
|
||||
- Mai
|
||||
- Juin
|
||||
- Juillet
|
||||
- Août
|
||||
- Septembre
|
||||
- Octobre
|
||||
- Novembre
|
||||
- Décembre
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Lundi
|
||||
- Mardi
|
||||
- Mercredi
|
||||
- Jeudi
|
||||
- Vendredi
|
||||
- Samedi
|
||||
- Dimanche
|
||||
VALIDATION_FAIL: <b>La validation a échoué :</b>
|
||||
INVALID_INPUT: Saisie non valide
|
||||
MISSING_REQUIRED_FIELD: Champ obligatoire manquant :
|
||||
|
||||
@@ -1,74 +1,52 @@
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- oprema
|
||||
- informacije
|
||||
- riža
|
||||
- novac
|
||||
- vrsta
|
||||
- serija
|
||||
- riba
|
||||
- ovca
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: osobe
|
||||
man: ljudi
|
||||
child: djeca
|
||||
sex: spolovi
|
||||
move: Pomakni
|
||||
'person': 'Osoba'
|
||||
'man': 'Čovjek'
|
||||
'child': 'Dijete'
|
||||
'sex': 'Spol'
|
||||
'move': 'Pomakni'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Datum nije upisan
|
||||
BAD_DATE: Pogrešan datum
|
||||
AGO: prije
|
||||
FROM_NOW: od sada
|
||||
SECOND: sekunda
|
||||
MINUTE: minuta
|
||||
HOUR: sat
|
||||
DAY: dan
|
||||
WEEK: tjedan
|
||||
MONTH: mjesec
|
||||
YEAR: godina
|
||||
DECADE: desetljeće
|
||||
SEC: sek
|
||||
HR: sat
|
||||
WK: t
|
||||
MO: m
|
||||
YR: g
|
||||
DEC: des
|
||||
SECOND_PLURAL: sekundi
|
||||
MINUTE_PLURAL: minuta
|
||||
HOUR_PLURAL: sati
|
||||
DAY_PLURAL: dan
|
||||
WEEK_PLURAL: tjedana
|
||||
MONTH_PLURAL: mjeseci
|
||||
YEAR_PLURAL: godina
|
||||
DECADE_PLURAL: desetljeća
|
||||
SEC_PLURAL: sek
|
||||
MIN_PLURAL: min
|
||||
HR_PLURAL: sat
|
||||
WK_PLURAL: t
|
||||
MO_PLURAL: m
|
||||
YR_PLURAL: g
|
||||
DEC_PLURAL: des
|
||||
NO_DATE_PROVIDED: Datum nije upisan
|
||||
BAD_DATE: Pogrešan datum
|
||||
AGO: prije
|
||||
FROM_NOW: od sad
|
||||
SECOND: sekundi
|
||||
MINUTE: minuta
|
||||
HOUR: godina
|
||||
DAY: dan
|
||||
WEEK: tjedan
|
||||
MONTH: mjesec
|
||||
YEAR: godina
|
||||
DECADE: desetljeće
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: sat
|
||||
DAY: dan
|
||||
WK: t
|
||||
MO: m
|
||||
YR: g
|
||||
DEC: des
|
||||
SECOND_PLURAL: sekundi
|
||||
SECOND_PLURAL_MORE_THAN_TWO: sekunde
|
||||
MINUTE_PLURAL: minuta
|
||||
MINUTE_PLURAL_MORE_THAN_TWO: minute
|
||||
HOUR_PLURAL: sati
|
||||
HOUR_PLURAL_MORE_THAN_TWO: sata
|
||||
DAY_PLURAL: dana
|
||||
WEEK_PLURAL: tjedana
|
||||
WEEK_PLURAL_MORE_THAN_TWO: tjedna
|
||||
MONTH_PLURAL: mjeseci
|
||||
MONTH_PLURAL_MORE_THAN_TWO: mjeseca
|
||||
YEAR_PLURAL: godina
|
||||
YEAR_PLURAL_MORE_THAN_TWO: godine
|
||||
DECADE_PLURAL: desetljeća
|
||||
SEC_PLURAL: sek
|
||||
MIN_PLURAL: min
|
||||
HR_PLURAL: sat
|
||||
DAY_PLURAL: dan
|
||||
WK_PLURAL: t
|
||||
MO_PLURAL: m
|
||||
YR_PLURAL: g
|
||||
DEC_PLURAL: des
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Validacija nije uspjela:</b>'
|
||||
INVALID_INPUT: Pogrešan unos u
|
||||
MISSING_REQUIRED_FIELD: 'Nedostaje obavezno polje:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Siječanj
|
||||
- Veljača
|
||||
- Ožujak
|
||||
- Travanj
|
||||
- Svibanj
|
||||
- Lipanj
|
||||
- Srpanj
|
||||
- Kolovoz
|
||||
- Rujan
|
||||
- Listopad
|
||||
- Studeni
|
||||
- Prosinac
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Ponedjeljak
|
||||
- Utorak
|
||||
- Srijeda
|
||||
- Četvrtak
|
||||
- Petak
|
||||
- Subota
|
||||
- Nedjelja
|
||||
VALIDATION_FAIL: <b>Validacija nije uspjela:</b>
|
||||
INVALID_INPUT: Unos nije valjan
|
||||
|
||||
@@ -1,64 +1,53 @@
|
||||
FRONTMATTER_ERROR_PAGE: |
|
||||
---
|
||||
cím: %1$s
|
||||
---
|
||||
|
||||
# Hiba: Érvénytelen Frontmatter
|
||||
|
||||
Elérési út: `%2$s`
|
||||
|
||||
**%3$s**
|
||||
|
||||
```
|
||||
%4$s
|
||||
```
|
||||
FRONTMATTER_ERROR_PAGE: "---\ncím: %1$s\n---\n\n# Hiba: Érvénytelen Frontmatter\n\nElérési út: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: személyek
|
||||
man: férfiak
|
||||
child: gyerekek
|
||||
sex: nemek
|
||||
move: lépések
|
||||
'person': 'személyek'
|
||||
'man': 'férfiak'
|
||||
'child': 'gyerekek'
|
||||
'sex': 'nemek'
|
||||
'move': 'lépések'
|
||||
INFLECTOR_ORDINALS:
|
||||
default: '.'
|
||||
first: '.'
|
||||
second: '.'
|
||||
third: '.'
|
||||
'default': '.'
|
||||
'first': '.'
|
||||
'second': '.'
|
||||
'third': '.'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Nincs dátum megadva
|
||||
BAD_DATE: Hibás dátum
|
||||
AGO: elteltével
|
||||
FROM_NOW: mostantól
|
||||
SECOND: másodperc
|
||||
MINUTE: perc
|
||||
HOUR: óra
|
||||
DAY: nap
|
||||
WEEK: hét
|
||||
MONTH: hónap
|
||||
YEAR: év
|
||||
DECADE: évtized
|
||||
SEC: mp
|
||||
MIN: p
|
||||
HR: ó
|
||||
WK: hét
|
||||
MO: hó
|
||||
YR: év
|
||||
DEC: évt
|
||||
SECOND_PLURAL: másodperc
|
||||
MINUTE_PLURAL: perc
|
||||
HOUR_PLURAL: óra
|
||||
DAY_PLURAL: nap
|
||||
WEEK_PLURAL: hét
|
||||
MONTH_PLURAL: hónap
|
||||
YEAR_PLURAL: év
|
||||
DECADE_PLURAL: évtized
|
||||
SEC_PLURAL: mp
|
||||
MIN_PLURAL: perc
|
||||
HR_PLURAL: ó
|
||||
WK_PLURAL: hét
|
||||
MO_PLURAL: hó
|
||||
YR_PLURAL: év
|
||||
DEC_PLURAL: évt
|
||||
NO_DATE_PROVIDED: Nincs dátum megadva
|
||||
BAD_DATE: Hibás dátum
|
||||
AGO: elteltével
|
||||
FROM_NOW: mostantól
|
||||
SECOND: másodperc
|
||||
MINUTE: perc
|
||||
HOUR: óra
|
||||
DAY: nap
|
||||
WEEK: hét
|
||||
MONTH: hónap
|
||||
YEAR: év
|
||||
DECADE: évtized
|
||||
SEC: mp
|
||||
MIN: p
|
||||
HR: ó
|
||||
DAY: nap
|
||||
WK: hét
|
||||
MO: hó
|
||||
YR: év
|
||||
DEC: évt
|
||||
SECOND_PLURAL: másodperc
|
||||
MINUTE_PLURAL: perc
|
||||
HOUR_PLURAL: óra
|
||||
DAY_PLURAL: nap
|
||||
WEEK_PLURAL: hét
|
||||
MONTH_PLURAL: hónap
|
||||
YEAR_PLURAL: év
|
||||
DECADE_PLURAL: évtized
|
||||
SEC_PLURAL: mp
|
||||
MIN_PLURAL: perc
|
||||
HR_PLURAL: ó
|
||||
DAY_PLURAL: nap
|
||||
WK_PLURAL: hét
|
||||
MO_PLURAL: hó
|
||||
YR_PLURAL: év
|
||||
DEC_PLURAL: évt
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>A validáció hibát talált:</b>'
|
||||
INVALID_INPUT: 'Az itt megadott érték érvénytelen:'
|
||||
MISSING_REQUIRED_FIELD: 'Ez a kötelező mező nincs kitöltve:'
|
||||
VALIDATION_FAIL: <b>A validáció hibát talált:</b>
|
||||
INVALID_INPUT: Az itt megadott érték érvénytelen:
|
||||
MISSING_REQUIRED_FIELD: Ez a kötelező mező nincs kitöltve:
|
||||
|
||||
@@ -1,45 +1,25 @@
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Nessuna data fornita
|
||||
BAD_DATE: Data errata
|
||||
AGO: fa
|
||||
FROM_NOW: da adesso
|
||||
SECOND: secondo
|
||||
MINUTE: minuto
|
||||
HOUR: ora
|
||||
DAY: giorno
|
||||
WEEK: settimana
|
||||
MONTH: mese
|
||||
YEAR: anno
|
||||
SECOND_PLURAL: secondi
|
||||
MINUTE_PLURAL: minuti
|
||||
HOUR_PLURAL: ore
|
||||
DAY_PLURAL: giorni
|
||||
WEEK_PLURAL: settimane
|
||||
MONTH_PLURAL: mesi
|
||||
YEAR_PLURAL: anni
|
||||
DECADE_PLURAL: decadi
|
||||
NO_DATE_PROVIDED: Nessuna data fornita
|
||||
BAD_DATE: Data errata
|
||||
AGO: fa
|
||||
FROM_NOW: da adesso
|
||||
SECOND: secondo
|
||||
MINUTE: minuto
|
||||
HOUR: ora
|
||||
DAY: giorno
|
||||
WEEK: settimana
|
||||
MONTH: mese
|
||||
YEAR: anno
|
||||
DECADE: decade
|
||||
SECOND_PLURAL: secondi
|
||||
MINUTE_PLURAL: minuti
|
||||
HOUR_PLURAL: ore
|
||||
DAY_PLURAL: giorni
|
||||
WEEK_PLURAL: settimane
|
||||
MONTH_PLURAL: mesi
|
||||
YEAR_PLURAL: anni
|
||||
DECADE_PLURAL: decadi
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Validazione fallita:</b>'
|
||||
INVALID_INPUT: Input invalido in
|
||||
MISSING_REQUIRED_FIELD: 'Campo richiesto mancante:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Gennaio
|
||||
- Febbraio
|
||||
- Marzo
|
||||
- Aprile
|
||||
- Maggio
|
||||
- Giugno
|
||||
- Luglio
|
||||
- Agosto
|
||||
- Settembre
|
||||
- Ottobre
|
||||
- Novembre
|
||||
- Dicembre
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Lunedi
|
||||
- Martedi
|
||||
- Mercoledi
|
||||
- Giovedi
|
||||
- Venerdi
|
||||
- Sabato
|
||||
- Domenica
|
||||
VALIDATION_FAIL: <b>Validazione fallita:</b>
|
||||
INVALID_INPUT: Input invalido in
|
||||
MISSING_REQUIRED_FIELD: Campo richiesto mancante:
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Error: Invalid Frontmatter\n\nPath: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
|
||||
INFLECTOR_PLURALS: []
|
||||
|
||||
INFLECTOR_SINGULAR: []
|
||||
|
||||
INFLECTOR_UNCOUNTABLE: []
|
||||
|
||||
INFLECTOR_IRREGULAR:
|
||||
'person': 'みんな'
|
||||
'man': '人'
|
||||
'child': '子供'
|
||||
'sex': '性別'
|
||||
'move': '移動'
|
||||
|
||||
INFLECTOR_ORDINALS: []
|
||||
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: 日付が設定されていません
|
||||
BAD_DATE: 不正な日付
|
||||
AGO: 前
|
||||
FROM_NOW: from now
|
||||
SECOND: 秒
|
||||
MINUTE: 分
|
||||
HOUR: 時
|
||||
DAY: 日
|
||||
WEEK: 週
|
||||
MONTH: 月
|
||||
YEAR: 年
|
||||
DECADE: 10年
|
||||
SEC: 秒
|
||||
MIN: 分
|
||||
HR: 時
|
||||
DAY: 日
|
||||
WK: 週
|
||||
MO: 月
|
||||
YR: 年
|
||||
DEC: dec
|
||||
SECOND_PLURAL: 秒
|
||||
MINUTE_PLURAL: 分
|
||||
HOUR_PLURAL: 時
|
||||
DAY_PLURAL: 日
|
||||
WEEK_PLURAL: 週
|
||||
MONTH_PLURAL: 月
|
||||
YEAR_PLURAL: 年
|
||||
DECADE_PLURAL: 10年
|
||||
SEC_PLURAL: 秒
|
||||
MIN_PLURAL: 分
|
||||
HR_PLURAL: 時
|
||||
DAY_PLURAL: 日
|
||||
WK_PLURAL: 週
|
||||
MO_PLURAL: 月
|
||||
YR_PLURAL: 年
|
||||
DEC_PLURAL: 10年
|
||||
FORM:
|
||||
VALIDATION_FAIL: <b>バリデーション失敗 :</b>
|
||||
INVALID_INPUT: 不正な入力:
|
||||
MISSING_REQUIRED_FIELD: 必須項目が入力されていません:
|
||||
MONTHS_OF_THE_YEAR: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
|
||||
DAYS_OF_THE_WEEK: ['月', '火', '水', '木', '金', '土', '日']
|
||||
@@ -1,68 +0,0 @@
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
2: ryžiai
|
||||
3: pinigai
|
||||
4: prieskoniai
|
||||
5: serijos
|
||||
6: žuvis
|
||||
7: avis
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: žmonės
|
||||
man: žmogus
|
||||
child: vaikai
|
||||
sex: lytys
|
||||
move: juda
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Nenurodyta data
|
||||
BAD_DATE: Neteisinga data
|
||||
AGO: prieš
|
||||
FROM_NOW: nuo dabar
|
||||
SECOND: sekundė
|
||||
MINUTE: minutė
|
||||
HOUR: valanda
|
||||
DAY: diena
|
||||
WEEK: savaitė
|
||||
MONTH: mėnuo
|
||||
YEAR: metai
|
||||
DECADE: dešimtmetis
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: val
|
||||
WK: sav
|
||||
MO: mėn
|
||||
YR: m
|
||||
MINUTE_PLURAL: minutės
|
||||
HOUR_PLURAL: valandos
|
||||
DAY_PLURAL: dienos
|
||||
WEEK_PLURAL: savaitės
|
||||
MONTH_PLURAL: mėnesiai
|
||||
YEAR_PLURAL: metai
|
||||
DECADE_PLURAL: dešimtmečiai
|
||||
SEC_PLURAL: sek
|
||||
MIN_PLURAL: min
|
||||
HR_PLURAL: val
|
||||
WK_PLURAL: sav
|
||||
MO_PLURAL: mėn
|
||||
YR_PLURAL: m
|
||||
FORM:
|
||||
MISSING_REQUIRED_FIELD: 'Būtina užpildyti laukelį:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Sausis
|
||||
- Vasaris
|
||||
- Kovas
|
||||
- Balandis
|
||||
- Gegužė
|
||||
- Birželis
|
||||
- Liepa
|
||||
- Rugpjūtis
|
||||
- Rugsėjis
|
||||
- Spalis
|
||||
- Lakpritis
|
||||
- Gruodis
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Pirmadienis
|
||||
- Antradienis
|
||||
- Trečiadienis
|
||||
- Ketvirtadienis
|
||||
- Penktadienis
|
||||
- Šeštadienis
|
||||
- Sekmadienis
|
||||
@@ -1,2 +0,0 @@
|
||||
MONTHS_OF_THE_YEAR: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember']
|
||||
DAYS_OF_THE_WEEK: ['mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag', 'søndag']
|
||||
@@ -1,50 +1,43 @@
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: personen
|
||||
man: mensen
|
||||
child: kinderen
|
||||
sex: geslacht
|
||||
move: verplaatsen
|
||||
'person': 'personen'
|
||||
'man': 'mensen'
|
||||
'child': 'kinderen'
|
||||
'sex': 'geslacht'
|
||||
'move': 'verplaatsen'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: geen datum opgegeven
|
||||
BAD_DATE: Datumformaat onjuist
|
||||
AGO: geleden
|
||||
FROM_NOW: vanaf nu
|
||||
SECOND: seconde
|
||||
MINUTE: minuut
|
||||
HOUR: uur
|
||||
DAY: dag
|
||||
MONTH: maand
|
||||
YEAR: jaar
|
||||
DECADE: decenium
|
||||
MO: ma
|
||||
SECOND_PLURAL: seconden
|
||||
MINUTE_PLURAL: minuten
|
||||
HOUR_PLURAL: uren
|
||||
DAY_PLURAL: dagen
|
||||
WEEK_PLURAL: weken
|
||||
MONTH_PLURAL: maanden
|
||||
YEAR_PLURAL: jaren
|
||||
DECADE_PLURAL: decennia
|
||||
SEC_PLURAL: seconden
|
||||
MIN_PLURAL: minuten
|
||||
HR_PLURAL: uren
|
||||
WK_PLURAL: weken
|
||||
MO_PLURAL: maanden
|
||||
YR_PLURAL: jaren
|
||||
MONTHS_OF_THE_YEAR:
|
||||
0: Januari
|
||||
1: Februari
|
||||
2: Maart
|
||||
4: Mei
|
||||
5: Juni
|
||||
6: Juli
|
||||
7: Augustus
|
||||
9: Oktober
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Maandag
|
||||
- Dinsdag
|
||||
- Woensdag
|
||||
- Donderdag
|
||||
- Vrijdag
|
||||
- Zaterdag
|
||||
- Zondag
|
||||
NO_DATE_PROVIDED: geen datum opgegeven
|
||||
BAD_DATE: Datumformaat onjuist
|
||||
AGO: geleden
|
||||
FROM_NOW: vanaf nu
|
||||
SECOND: seconde
|
||||
MINUTE: minuut
|
||||
HOUR: uur
|
||||
DAY: dag
|
||||
WEEK: week
|
||||
MONTH: maand
|
||||
YEAR: jaar
|
||||
DECADE: decenium
|
||||
SEC: sec
|
||||
MIN: min
|
||||
HR: hr
|
||||
DAY: dag
|
||||
WK: wk
|
||||
MO: ma
|
||||
YR: yr
|
||||
DEC: dec
|
||||
SECOND_PLURAL: seconden
|
||||
MINUTE_PLURAL: minuten
|
||||
HOUR_PLURAL: uren
|
||||
DAY_PLURAL: dagen
|
||||
WEEK_PLURAL: weken
|
||||
MONTH_PLURAL: maanden
|
||||
YEAR_PLURAL: jaren
|
||||
DECADE_PLURAL: decennia
|
||||
SEC_PLURAL: seconden
|
||||
MIN_PLURAL: minuten
|
||||
HR_PLURAL: uren
|
||||
DAY_PLURAL: dagen
|
||||
WK_PLURAL: weken
|
||||
MO_PLURAL: maanden
|
||||
YR_PLURAL: jaren
|
||||
DEC_PLURAL: decs
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
FRONTMATTER_ERROR_PAGE: |
|
||||
---
|
||||
Tittel: %1$s
|
||||
---
|
||||
|
||||
# Feilmelding: Ugyldig Frontmatter
|
||||
|
||||
Pane: '%2$s'
|
||||
|
||||
**%3$s **
|
||||
|
||||
```
|
||||
%4$s
|
||||
```
|
||||
INFLECTOR_PLURALS:
|
||||
/(quiz)$/i: '\1zes'
|
||||
/^(ox)$/i: '\1en'
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
- utstyr
|
||||
- informasjon
|
||||
- ris
|
||||
- penger
|
||||
- arter
|
||||
- serier
|
||||
- fisk
|
||||
- sau
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: folk
|
||||
man: menn
|
||||
child: barn
|
||||
sex: kjønn
|
||||
move: trekk
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Ingen dato gitt
|
||||
BAD_DATE: Dårlig dato
|
||||
AGO: siden
|
||||
FROM_NOW: fra nå
|
||||
SECOND: sekund
|
||||
MINUTE: minutt
|
||||
HOUR: time
|
||||
DAY: dag
|
||||
WEEK: uke
|
||||
MONTH: måned
|
||||
YEAR: år
|
||||
DECADE: tiår
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: t
|
||||
WK: uke
|
||||
MO: må
|
||||
YR: år
|
||||
DEC: des
|
||||
SECOND_PLURAL: sekunder
|
||||
MINUTE_PLURAL: minutter
|
||||
HOUR_PLURAL: timer
|
||||
DAY_PLURAL: dager
|
||||
WEEK_PLURAL: uker
|
||||
MONTH_PLURAL: måneder
|
||||
YEAR_PLURAL: år
|
||||
DECADE_PLURAL: tiår
|
||||
SEC_PLURAL: sek
|
||||
MIN_PLURAL: min
|
||||
HR_PLURAL: timer
|
||||
WK_PLURAL: uker
|
||||
YR_PLURAL: år
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Validering mislyktes:</b>'
|
||||
INVALID_INPUT: Ugyldig innhold i
|
||||
MISSING_REQUIRED_FIELD: 'Mangler påkrevd felt:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- januar
|
||||
- februar
|
||||
- mars
|
||||
- april
|
||||
- mai
|
||||
- juni
|
||||
- juli
|
||||
- august
|
||||
- september
|
||||
- oktober
|
||||
- november
|
||||
- desember
|
||||
DAYS_OF_THE_WEEK:
|
||||
- mandag
|
||||
- tirsdag
|
||||
- onsdag
|
||||
- torsdag
|
||||
- fredag
|
||||
- lørdag
|
||||
- søndag
|
||||
@@ -1,74 +0,0 @@
|
||||
FRONTMATTER_ERROR_PAGE: |
|
||||
---
|
||||
title: %1$s
|
||||
---
|
||||
|
||||
# Error: Nieprawidłowy Frontmatter
|
||||
|
||||
Path: `%2$s`
|
||||
|
||||
**%3$s**
|
||||
|
||||
```
|
||||
%4$s
|
||||
```
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Nie podano daty
|
||||
BAD_DATE: Zła data
|
||||
AGO: temu
|
||||
FROM_NOW: od teraz
|
||||
SECOND: sekunda
|
||||
MINUTE: minuta
|
||||
HOUR: godzina
|
||||
DAY: dzień
|
||||
WEEK: tydzień
|
||||
MONTH: miesiąc
|
||||
YEAR: rok
|
||||
DECADE: dekada
|
||||
SEC: sek
|
||||
MIN: min
|
||||
HR: godz
|
||||
WK: tydź
|
||||
MO: mieś
|
||||
YR: rok
|
||||
DEC: dekada
|
||||
SECOND_PLURAL: sekund
|
||||
MINUTE_PLURAL: minut
|
||||
HOUR_PLURAL: godzin
|
||||
DAY_PLURAL: dni
|
||||
WEEK_PLURAL: tygodnie
|
||||
MONTH_PLURAL: miesięcy
|
||||
YEAR_PLURAL: lat
|
||||
DECADE_PLURAL: dekad
|
||||
SEC_PLURAL: sekund
|
||||
MIN_PLURAL: minut
|
||||
HR_PLURAL: godz
|
||||
WK_PLURAL: tyg
|
||||
MO_PLURAL: mieś
|
||||
YR_PLURAL: lat
|
||||
DEC_PLURAL: dekad
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Weryfikacja nie powiodła się:</b>'
|
||||
INVALID_INPUT: Nieprawidłowe dane w
|
||||
MISSING_REQUIRED_FIELD: 'Opuszczono wymagane pole:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Styczeń
|
||||
- Luty
|
||||
- Marzec
|
||||
- Kwiecień
|
||||
- Maj
|
||||
- Czerwiec
|
||||
- Lipiec
|
||||
- Sierpień
|
||||
- Wrzesień
|
||||
- Październik
|
||||
- Listopad
|
||||
- Grudzień
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Poniedziałek
|
||||
- Wtorek
|
||||
- Środa
|
||||
- Czwartek
|
||||
- Piątek
|
||||
- Sobota
|
||||
- Niedziela
|
||||
@@ -1,55 +0,0 @@
|
||||
INFLECTOR_UNCOUNTABLE:
|
||||
1: informação
|
||||
2: arroz
|
||||
3: dinheiro
|
||||
INFLECTOR_IRREGULAR:
|
||||
man: homens
|
||||
sex: sexos
|
||||
NICETIME:
|
||||
SECOND: segundo
|
||||
MINUTE: minuto
|
||||
HOUR: hora
|
||||
DAY: dia
|
||||
WEEK: semana
|
||||
MONTH: mês
|
||||
YEAR: ano
|
||||
DECADE: década
|
||||
SEC: seg
|
||||
MIN: mín
|
||||
MO: mês
|
||||
YR: ano
|
||||
SECOND_PLURAL: segundos
|
||||
MINUTE_PLURAL: minutos
|
||||
HOUR_PLURAL: horas
|
||||
DAY_PLURAL: dias
|
||||
WEEK_PLURAL: semanas
|
||||
MONTH_PLURAL: meses
|
||||
YEAR_PLURAL: anos
|
||||
DECADE_PLURAL: décadas
|
||||
SEC_PLURAL: seg
|
||||
MIN_PLURAL: mins
|
||||
HR_PLURAL: hrs
|
||||
YR_PLURAL: anos
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Validação falhada: </b>'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Janeiro
|
||||
- Fevereiro
|
||||
- Março
|
||||
- Abril
|
||||
- Maio
|
||||
- Junho
|
||||
- Julho
|
||||
- Agosto
|
||||
- Setembro
|
||||
- Outubro
|
||||
- Novembro
|
||||
- Dezembro
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Segunda
|
||||
- Terça
|
||||
- Quarta
|
||||
- Quinta
|
||||
- Sexta
|
||||
- Sábado
|
||||
- Domingo
|
||||
@@ -1,20 +0,0 @@
|
||||
MONTHS_OF_THE_YEAR:
|
||||
0: Ianuarie
|
||||
1: Februarie
|
||||
2: Martie
|
||||
3: Aprilue
|
||||
4: Mai
|
||||
5: Iunie
|
||||
6: Iulie
|
||||
8: Septembrie
|
||||
9: Octombrie
|
||||
10: Noiembrie
|
||||
11: Decembrie
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Luni
|
||||
- Marti
|
||||
- Miercuri
|
||||
- Joi
|
||||
- Vineri
|
||||
- Sâmbătă
|
||||
- Duminică
|
||||
@@ -1,66 +1,43 @@
|
||||
INFLECTOR_IRREGULAR:
|
||||
person: люди
|
||||
man: человек
|
||||
child: ребенок
|
||||
sex: пол
|
||||
move: движется
|
||||
'person': 'люди'
|
||||
'man': 'человек'
|
||||
'child': 'ребенок'
|
||||
'sex': 'пол'
|
||||
'move': 'движется'
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Дата не указана
|
||||
BAD_DATE: Неверная дата
|
||||
AGO: назад
|
||||
FROM_NOW: теперь
|
||||
SECOND: секунда
|
||||
MINUTE: минута
|
||||
HOUR: час
|
||||
DAY: д
|
||||
WEEK: неделя
|
||||
MONTH: месяц
|
||||
YEAR: год
|
||||
DECADE: десятилетие
|
||||
SEC: с
|
||||
MIN: мин
|
||||
HR: ч
|
||||
WK: нед
|
||||
MO: мес
|
||||
YR: г.
|
||||
DEC: гг.
|
||||
SECOND_PLURAL: секунды
|
||||
MINUTE_PLURAL: минуты
|
||||
HOUR_PLURAL: часы
|
||||
DAY_PLURAL: д
|
||||
WEEK_PLURAL: недели
|
||||
MONTH_PLURAL: месяцы
|
||||
YEAR_PLURAL: годы
|
||||
DECADE_PLURAL: десятилетия
|
||||
SEC_PLURAL: с
|
||||
MIN_PLURAL: мин
|
||||
HR_PLURAL: ч
|
||||
WK_PLURAL: нед
|
||||
MO_PLURAL: мес
|
||||
YR_PLURAL: г.
|
||||
DEC_PLURAL: гг.
|
||||
FORM:
|
||||
VALIDATION_FAIL: '<b>Проверка не удалась:</b>'
|
||||
INVALID_INPUT: Неверный ввод в
|
||||
MISSING_REQUIRED_FIELD: 'Отсутствует необходимое поле:'
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- Январь
|
||||
- Февраль
|
||||
- Март
|
||||
- Апрель
|
||||
- Май
|
||||
- Июнь
|
||||
- Июль
|
||||
- Август
|
||||
- Сентябрь
|
||||
- Октябрь
|
||||
- Ноябрь
|
||||
- Декабрь
|
||||
DAYS_OF_THE_WEEK:
|
||||
- Понедельник
|
||||
- Вторник
|
||||
- Среда
|
||||
- Четверг
|
||||
- Пятница
|
||||
- Суббота
|
||||
- Воскресенье
|
||||
NO_DATE_PROVIDED: Дата не указана
|
||||
BAD_DATE: Неверная дата
|
||||
AGO: назад
|
||||
FROM_NOW: теперь
|
||||
SECOND: секунда
|
||||
MINUTE: минута
|
||||
HOUR: час
|
||||
DAY: день
|
||||
WEEK: неделя
|
||||
MONTH: месяц
|
||||
YEAR: год
|
||||
DECADE: десятилетие
|
||||
SEC: с
|
||||
MIN: мин
|
||||
HR: ч
|
||||
DAY: д
|
||||
WK: нед
|
||||
MO: мес
|
||||
YR: г.
|
||||
DEC: гг.
|
||||
SECOND_PLURAL: секунды
|
||||
MINUTE_PLURAL: минуты
|
||||
HOUR_PLURAL: часы
|
||||
DAY_PLURAL: дни
|
||||
WEEK_PLURAL: недели
|
||||
MONTH_PLURAL: месяцы
|
||||
YEAR_PLURAL: годы
|
||||
DECADE_PLURAL: десятилетия
|
||||
SEC_PLURAL: с
|
||||
MIN_PLURAL: мин
|
||||
HR_PLURAL: ч
|
||||
DAY_PLURAL: д
|
||||
WK_PLURAL: нед
|
||||
MO_PLURAL: мес
|
||||
YR_PLURAL: г.
|
||||
DEC_PLURAL: гг.
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
NICETIME:
|
||||
DAY: dag
|
||||
@@ -1,35 +1,37 @@
|
||||
NICETIME:
|
||||
NO_DATE_PROVIDED: Tarih yok
|
||||
BAD_DATE: Yanlış tarih
|
||||
AGO: önce
|
||||
FROM_NOW: (şimdiden)
|
||||
SECOND: saniye
|
||||
MINUTE: dakika
|
||||
HOUR: saat
|
||||
DAY: gün
|
||||
WEEK: hafta
|
||||
MONTH: ay
|
||||
YEAR: yıl
|
||||
DECADE: onyıl
|
||||
SEC: sn
|
||||
MIN: dk
|
||||
HR: sa
|
||||
WK: hft
|
||||
MO: ay
|
||||
YR: yl
|
||||
DEC: onyl
|
||||
SECOND_PLURAL: saniye
|
||||
MINUTE_PLURAL: dakika
|
||||
HOUR_PLURAL: saat
|
||||
DAY_PLURAL: gün
|
||||
WEEK_PLURAL: hafta
|
||||
MONTH_PLURAL: ay
|
||||
YEAR_PLURAL: yıl
|
||||
DECADE_PLURAL: onyıl
|
||||
SEC_PLURAL: sn
|
||||
MIN_PLURAL: dk
|
||||
HR_PLURAL: sa
|
||||
WK_PLURAL: hft
|
||||
MO_PLURAL: ay
|
||||
YR_PLURAL: yl
|
||||
DEC_PLURAL: onyl
|
||||
NO_DATE_PROVIDED: Tarih yok
|
||||
BAD_DATE: Yanlış tarih
|
||||
AGO: önce
|
||||
FROM_NOW: (şimdiden)
|
||||
SECOND: saniye
|
||||
MINUTE: dakika
|
||||
HOUR: saat
|
||||
DAY: gün
|
||||
WEEK: hafta
|
||||
MONTH: ay
|
||||
YEAR: yıl
|
||||
DECADE: onyıl
|
||||
SEC: sn
|
||||
MIN: dk
|
||||
HR: sa
|
||||
DAY: gün
|
||||
WK: hft
|
||||
MO: ay
|
||||
YR: yl
|
||||
DEC: onyl
|
||||
SECOND_PLURAL: saniye
|
||||
MINUTE_PLURAL: dakika
|
||||
HOUR_PLURAL: saat
|
||||
DAY_PLURAL: gün
|
||||
WEEK_PLURAL: hafta
|
||||
MONTH_PLURAL: ay
|
||||
YEAR_PLURAL: yıl
|
||||
DECADE_PLURAL: onyıl
|
||||
SEC_PLURAL: sn
|
||||
MIN_PLURAL: dk
|
||||
HR_PLURAL: sa
|
||||
DAY_PLURAL: gün
|
||||
WK_PLURAL: hft
|
||||
MO_PLURAL: ay
|
||||
YR_PLURAL: yl
|
||||
DEC_PLURAL: onyl
|
||||
|
||||
@@ -8,7 +8,6 @@ use Grav\Common\Config\Config;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use RegexIterator;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
|
||||
define('CSS_ASSET', true);
|
||||
define('JS_ASSET', false);
|
||||
@@ -23,6 +22,8 @@ define('JS_ASSET', false);
|
||||
*/
|
||||
class Assets
|
||||
{
|
||||
use GravTrait;
|
||||
|
||||
/** @const Regex to match CSS and JavaScript files */
|
||||
const DEFAULT_REGEX = '/.\.(css|js)$/i';
|
||||
|
||||
@@ -33,7 +34,7 @@ class Assets
|
||||
const JS_REGEX = '/.\.js$/i';
|
||||
|
||||
/** @const Regex to match CSS urls */
|
||||
const CSS_URL_REGEX = '{url\(([\'\"]?)(.*?)\1\)}';
|
||||
const CSS_URL_REGEX = '{url\([\'\"]?((?!http|//).*?)[\'\"]?\)}';
|
||||
|
||||
/** @const Regex to match CSS sourcemap comments */
|
||||
const CSS_SOURCEMAP_REGEX = '{\/\*# (.*) \*\/}';
|
||||
@@ -60,19 +61,14 @@ class Assets
|
||||
|
||||
// Configuration toggles to enable/disable the pipelining feature
|
||||
protected $css_pipeline = false;
|
||||
protected $css_pipeline_include_externals = true;
|
||||
protected $css_pipeline_before_excludes = true;
|
||||
protected $js_pipeline = false;
|
||||
protected $js_pipeline_include_externals = true;
|
||||
protected $js_pipeline_before_excludes = true;
|
||||
|
||||
// The asset holding arrays
|
||||
protected $collections = [];
|
||||
protected $css = [];
|
||||
protected $js = [];
|
||||
protected $inline_css = [];
|
||||
protected $inline_js = [];
|
||||
protected $imports = [];
|
||||
protected $collections = array();
|
||||
protected $css = array();
|
||||
protected $js = array();
|
||||
protected $inline_css = array();
|
||||
protected $inline_js = array();
|
||||
|
||||
// Some configuration variables
|
||||
protected $config;
|
||||
@@ -88,15 +84,10 @@ class Assets
|
||||
protected $js_minify = true;
|
||||
|
||||
// Arrays to hold assets that should NOT be pipelined
|
||||
protected $css_no_pipeline = [];
|
||||
protected $js_no_pipeline = [];
|
||||
protected $css_no_pipeline = array();
|
||||
protected $js_no_pipeline = array();
|
||||
|
||||
/**
|
||||
* Assets constructor.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
// Forward config options
|
||||
if ($options) {
|
||||
@@ -123,26 +114,10 @@ class Assets
|
||||
$this->css_pipeline = $config['css_pipeline'];
|
||||
}
|
||||
|
||||
if (isset($config['css_pipeline_include_externals'])) {
|
||||
$this->css_pipeline_include_externals = $config['css_pipeline_include_externals'];
|
||||
}
|
||||
|
||||
if (isset($config['css_pipeline_before_excludes'])) {
|
||||
$this->css_pipeline_before_excludes = $config['css_pipeline_before_excludes'];
|
||||
}
|
||||
|
||||
if (isset($config['js_pipeline'])) {
|
||||
$this->js_pipeline = $config['js_pipeline'];
|
||||
}
|
||||
|
||||
if (isset($config['js_pipeline_include_externals'])) {
|
||||
$this->js_pipeline_include_externals = $config['js_pipeline_include_externals'];
|
||||
}
|
||||
|
||||
if (isset($config['js_pipeline_before_excludes'])) {
|
||||
$this->js_pipeline_before_excludes = $config['js_pipeline_before_excludes'];
|
||||
}
|
||||
|
||||
// Pipeline requires public dir
|
||||
if (($this->js_pipeline || $this->css_pipeline) && !is_dir($this->assets_dir)) {
|
||||
throw new \Exception('Assets: Public dir not found');
|
||||
@@ -185,9 +160,10 @@ class Assets
|
||||
|
||||
// Set timestamp
|
||||
if (isset($config['enable_asset_timestamp']) && $config['enable_asset_timestamp'] === true) {
|
||||
$this->timestamp = '?' . Grav::instance()['cache']->getKey();
|
||||
$this->timestamp = '?' . self::getGrav()['cache']->getKey();
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -196,22 +172,21 @@ class Assets
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
/** @var Config $config */
|
||||
$config = $grav['config'];
|
||||
$base_url = $grav['base_url'];
|
||||
$config = self::getGrav()['config'];
|
||||
$base_url = self::getGrav()['base_url'];
|
||||
$asset_config = (array)$config->get('system.assets');
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $grav['locator'];
|
||||
$this->assets_dir = $locator->findResource('asset://') . DS;
|
||||
$this->assets_url = $locator->findResource('asset://', false);
|
||||
/** @var Locator $locator */
|
||||
$locator = self::$grav['locator'];
|
||||
$this->assets_dir = self::getGrav()['locator']->findResource('asset://') . DS;
|
||||
$this->assets_url = self::getGrav()['locator']->findResource('asset://', false);
|
||||
|
||||
$this->config($asset_config);
|
||||
$this->base_url = $base_url . '/';
|
||||
|
||||
// Register any preconfigured collections
|
||||
foreach ($config->get('system.assets.collections', []) as $name => $collection) {
|
||||
foreach ($config->get('system.assets.collections') as $name => $collection) {
|
||||
$this->registerCollection($name, (array)$collection);
|
||||
}
|
||||
}
|
||||
@@ -262,9 +237,9 @@ class Assets
|
||||
* You may add more than one asset passing an array as argument.
|
||||
*
|
||||
* @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 int $priority the priority, bigger comes first
|
||||
* @param bool $pipeline false if this should not be pipelined
|
||||
* @param null $group
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -274,11 +249,9 @@ class Assets
|
||||
foreach ($asset as $a) {
|
||||
$this->addCss($a, $priority, $pipeline, $group);
|
||||
}
|
||||
|
||||
return $this;
|
||||
} elseif (isset($this->collections[$asset])) {
|
||||
$this->addCss($this->collections[$asset], $priority, $pipeline, $group);
|
||||
|
||||
$this->add($this->collections[$asset], $priority, $pipeline, $group);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -295,12 +268,12 @@ class Assets
|
||||
'asset' => $asset,
|
||||
'priority' => intval($priority ?: 10),
|
||||
'order' => count($this->css),
|
||||
'pipeline' => (bool)$pipeline,
|
||||
'group' => $group ?: 'head'
|
||||
'pipeline' => (bool) $pipeline,
|
||||
'group' => $group ?: 'head'
|
||||
];
|
||||
|
||||
// check for dynamic array and merge with defaults
|
||||
if (func_num_args() > 1) {
|
||||
if (func_num_args() == 2) {
|
||||
$dynamic_arg = func_get_arg(1);
|
||||
if (is_array($dynamic_arg)) {
|
||||
$data = array_merge($data, $dynamic_arg);
|
||||
@@ -321,12 +294,11 @@ class Assets
|
||||
* It checks for duplicates.
|
||||
* You may add more than one asset passing an array as argument.
|
||||
*
|
||||
* @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)
|
||||
* @param string $group name of the group
|
||||
*
|
||||
* @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)
|
||||
* @param string $group name of the group
|
||||
* @return $this
|
||||
*/
|
||||
public function addJs($asset, $priority = null, $pipeline = true, $loading = null, $group = null)
|
||||
@@ -335,11 +307,9 @@ class Assets
|
||||
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);
|
||||
|
||||
$this->add($this->collections[$asset], $priority, $pipeline, $loading, $group);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -356,16 +326,16 @@ class Assets
|
||||
'asset' => $asset,
|
||||
'priority' => intval($priority ?: 10),
|
||||
'order' => count($this->js),
|
||||
'pipeline' => (bool)$pipeline,
|
||||
'pipeline' => (bool) $pipeline,
|
||||
'loading' => $loading ?: '',
|
||||
'group' => $group ?: 'head'
|
||||
'group' => $group ?: 'head'
|
||||
];
|
||||
|
||||
// check for dynamic array and merge with defaults
|
||||
if (func_num_args() > 1) {
|
||||
if (func_num_args() == 2) {
|
||||
$dynamic_arg = func_get_arg(1);
|
||||
if (is_array($dynamic_arg)) {
|
||||
$data = array_merge($data, $dynamic_arg);
|
||||
$data = array_merge($data, $dynamic_arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,9 +350,9 @@ class Assets
|
||||
/**
|
||||
* Convenience wrapper for async loading of JavaScript
|
||||
*
|
||||
* @param $asset
|
||||
* @param int $priority
|
||||
* @param bool $pipeline
|
||||
* @param $asset
|
||||
* @param int $priority
|
||||
* @param bool $pipeline
|
||||
* @param string $group name of the group
|
||||
*
|
||||
* @deprecated Please use dynamic method with ['loading' => 'async']
|
||||
@@ -397,9 +367,9 @@ class Assets
|
||||
/**
|
||||
* Convenience wrapper for deferred loading of JavaScript
|
||||
*
|
||||
* @param $asset
|
||||
* @param int $priority
|
||||
* @param bool $pipeline
|
||||
* @param $asset
|
||||
* @param int $priority
|
||||
* @param bool $pipeline
|
||||
* @param string $group name of the group
|
||||
*
|
||||
* @deprecated Please use dynamic method with ['loading' => 'defer']
|
||||
@@ -418,8 +388,8 @@ class Assets
|
||||
* For adding chunks of string-based inline CSS
|
||||
*
|
||||
* @param mixed $asset
|
||||
* @param int $priority the priority, bigger comes first
|
||||
* @param null $group
|
||||
* @param int $priority the priority, bigger comes first
|
||||
* @param null $group
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -428,20 +398,21 @@ class Assets
|
||||
$asset = trim($asset);
|
||||
|
||||
if (is_a($asset, 'Twig_Markup')) {
|
||||
preg_match(self::HTML_TAG_REGEX, $asset, $matches);
|
||||
if (isset($matches[3])) {
|
||||
preg_match(self::HTML_TAG_REGEX, $asset, $matches );
|
||||
if (isset($matches[3])) {
|
||||
$asset = $matches[3];
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
'priority' => intval($priority ?: 10),
|
||||
'order' => count($this->inline_css),
|
||||
'asset' => $asset,
|
||||
'group' => $group ?: 'head'
|
||||
'priority' => intval($priority ?: 10),
|
||||
'order' => count($this->inline_css),
|
||||
'asset' => $asset,
|
||||
'group' => $group ?: 'head'
|
||||
];
|
||||
|
||||
// check for dynamic array and merge with defaults
|
||||
$count_args = func_num_args();
|
||||
if (func_num_args() == 2) {
|
||||
$dynamic_arg = func_get_arg(1);
|
||||
if (is_array($dynamic_arg)) {
|
||||
@@ -465,7 +436,7 @@ class Assets
|
||||
*
|
||||
* @param mixed $asset
|
||||
* @param int $priority the priority, bigger comes first
|
||||
* @param string $group name of the group
|
||||
* @param string $group name of the group
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -474,8 +445,8 @@ class Assets
|
||||
$asset = trim($asset);
|
||||
|
||||
if (is_a($asset, 'Twig_Markup')) {
|
||||
preg_match(self::HTML_TAG_REGEX, $asset, $matches);
|
||||
if (isset($matches[3])) {
|
||||
preg_match(self::HTML_TAG_REGEX, $asset, $matches );
|
||||
if (isset($matches[3])) {
|
||||
$asset = $matches[3];
|
||||
}
|
||||
}
|
||||
@@ -484,10 +455,11 @@ class Assets
|
||||
'asset' => $asset,
|
||||
'priority' => intval($priority ?: 10),
|
||||
'order' => count($this->js),
|
||||
'group' => $group ?: 'head'
|
||||
'group' => $group ?: 'head'
|
||||
];
|
||||
|
||||
// check for dynamic array and merge with defaults
|
||||
$count_args = func_num_args();
|
||||
if (func_num_args() == 2) {
|
||||
$dynamic_arg = func_get_arg(1);
|
||||
if (is_array($dynamic_arg)) {
|
||||
@@ -507,31 +479,29 @@ class Assets
|
||||
* Build the CSS link tags.
|
||||
*
|
||||
* @param string $group name of the group
|
||||
* @param array $attributes
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function css($group = 'head', $attributes = [])
|
||||
{
|
||||
if (!$this->css && !$this->inline_css) {
|
||||
if (!$this->css) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Sort array by priorities (larger priority first)
|
||||
if (Grav::instance()) {
|
||||
uasort($this->css, function ($a, $b) {
|
||||
if (self::getGrav()) {
|
||||
usort($this->css, function ($a, $b) {
|
||||
if ($a['priority'] == $b['priority']) {
|
||||
return $b['order'] - $a['order'];
|
||||
}
|
||||
|
||||
return $a['priority'] - $b['priority'];
|
||||
});
|
||||
|
||||
uasort($this->inline_css, function ($a, $b) {
|
||||
usort($this->inline_css, function ($a, $b) {
|
||||
if ($a['priority'] == $b['priority']) {
|
||||
return $b['order'] - $a['order'];
|
||||
}
|
||||
|
||||
return $a['priority'] - $b['priority'];
|
||||
});
|
||||
}
|
||||
@@ -545,10 +515,8 @@ class Assets
|
||||
|
||||
if ($this->css_pipeline) {
|
||||
$pipeline_result = $this->pipelineCss($group);
|
||||
$pipeline_html = '<link href="' . $pipeline_result . '"' . $attributes . ' />' . "\n";
|
||||
|
||||
if ($this->css_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
if ($pipeline_result) {
|
||||
$output .= '<link href="' . $pipeline_result . '"' . $attributes . ' />' . "\n";
|
||||
}
|
||||
foreach ($this->css_no_pipeline as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
@@ -556,9 +524,6 @@ class Assets
|
||||
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . $media . ' />' . "\n";
|
||||
}
|
||||
}
|
||||
if (!$this->css_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
}
|
||||
} else {
|
||||
foreach ($this->css as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
@@ -587,30 +552,28 @@ class Assets
|
||||
* Build the JavaScript script tags.
|
||||
*
|
||||
* @param string $group name of the group
|
||||
* @param array $attributes
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function js($group = 'head', $attributes = [])
|
||||
{
|
||||
if (!$this->js && !$this->inline_js) {
|
||||
if (!$this->js) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Sort array by priorities (larger priority first)
|
||||
uasort($this->js, function ($a, $b) {
|
||||
usort($this->js, function ($a, $b) {
|
||||
if ($a['priority'] == $b['priority']) {
|
||||
return $b['order'] - $a['order'];
|
||||
}
|
||||
|
||||
return $a['priority'] - $b['priority'];
|
||||
});
|
||||
|
||||
uasort($this->inline_js, function ($a, $b) {
|
||||
usort($this->inline_js, function ($a, $b) {
|
||||
if ($a['priority'] == $b['priority']) {
|
||||
return $b['order'] - $a['order'];
|
||||
}
|
||||
|
||||
return $a['priority'] - $b['priority'];
|
||||
});
|
||||
|
||||
@@ -624,19 +587,14 @@ class Assets
|
||||
|
||||
if ($this->js_pipeline) {
|
||||
$pipeline_result = $this->pipelineJs($group);
|
||||
$pipeline_html = '<script src="' . $pipeline_result . '"' . $attributes . ' ></script>' . "\n";
|
||||
|
||||
if ($this->js_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
if ($pipeline_result) {
|
||||
$output .= '<script src="' . $pipeline_result . '"' . $attributes . ' ></script>' . "\n";
|
||||
}
|
||||
foreach ($this->js_no_pipeline as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
$output .= '<script src="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
|
||||
$output .= '<script src="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' ' . $file['loading']. '></script>' . "\n";
|
||||
}
|
||||
}
|
||||
if (!$this->js_pipeline_before_excludes && $pipeline_result) {
|
||||
$output .= $pipeline_html;
|
||||
}
|
||||
} else {
|
||||
foreach ($this->js as $file) {
|
||||
if ($group && $file['group'] == $group) {
|
||||
@@ -660,16 +618,14 @@ class Assets
|
||||
}
|
||||
|
||||
/**
|
||||
* Minify and concatenate CSS
|
||||
* Minify and concatenate CSS.
|
||||
*
|
||||
* @param string $group
|
||||
*
|
||||
* @return bool|string
|
||||
* @return string
|
||||
*/
|
||||
protected function pipelineCss($group = 'head')
|
||||
{
|
||||
/** @var Cache $cache */
|
||||
$cache = Grav::instance()['cache'];
|
||||
$cache = self::getGrav()['cache'];
|
||||
$key = '?' . $cache->getKey();
|
||||
|
||||
// temporary list of assets to pipeline
|
||||
@@ -678,27 +634,20 @@ class Assets
|
||||
// clear no-pipeline assets lists
|
||||
$this->css_no_pipeline = [];
|
||||
|
||||
$uid = md5(json_encode($this->css) . $this->css_minify . $this->css_rewrite . $group);
|
||||
$file = $uid . '.css';
|
||||
$inline_file = $uid . '-inline.css';
|
||||
$file = md5(json_encode($this->css) . $this->css_minify . $this->css_rewrite . $group) . '.css';
|
||||
|
||||
$relative_path = "{$this->base_url}{$this->assets_url}/{$file}";
|
||||
|
||||
// If inline files exist set them on object
|
||||
if (file_exists($this->assets_dir . $inline_file)) {
|
||||
$this->css_no_pipeline = json_decode(file_get_contents($this->assets_dir . $inline_file), true);
|
||||
}
|
||||
$absolute_path = $this->assets_dir . $file;
|
||||
|
||||
// If pipeline exist return it
|
||||
if (file_exists($this->assets_dir . $file)) {
|
||||
if (file_exists($absolute_path)) {
|
||||
return $relative_path . $key;
|
||||
}
|
||||
|
||||
// Remove any non-pipeline files
|
||||
foreach ($this->css as $id => $asset) {
|
||||
if ($asset['group'] == $group) {
|
||||
if (!$asset['pipeline'] ||
|
||||
($this->isRemoteLink($asset['asset']) && $this->css_pipeline_include_externals === false)) {
|
||||
if (!$asset['pipeline']) {
|
||||
$this->css_no_pipeline[$id] = $asset;
|
||||
} else {
|
||||
$temp_css[$id] = $asset;
|
||||
@@ -711,12 +660,6 @@ class Assets
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write non-pipeline files out
|
||||
if (!empty($this->css_no_pipeline)) {
|
||||
file_put_contents($this->assets_dir . $inline_file, json_encode($this->css_no_pipeline));
|
||||
}
|
||||
|
||||
|
||||
$css_minify = $this->css_minify;
|
||||
|
||||
// If this is a Windows server, and minify_windows is false (default value) skip the
|
||||
@@ -729,15 +672,13 @@ class Assets
|
||||
// Concatenate files
|
||||
$buffer = $this->gatherLinks($temp_css, CSS_ASSET);
|
||||
if ($css_minify) {
|
||||
$minifier = new \MatthiasMullie\Minify\CSS();
|
||||
$minifier->add($buffer);
|
||||
$buffer = $minifier->minify();
|
||||
$min = new \CSSmin();
|
||||
$buffer = $min->run($buffer);
|
||||
}
|
||||
|
||||
// Write file
|
||||
if (strlen(trim($buffer)) > 0) {
|
||||
file_put_contents($this->assets_dir . $file, $buffer);
|
||||
|
||||
file_put_contents($absolute_path, $buffer);
|
||||
return $relative_path . $key;
|
||||
} else {
|
||||
return false;
|
||||
@@ -747,14 +688,12 @@ class Assets
|
||||
/**
|
||||
* Minify and concatenate JS files.
|
||||
*
|
||||
* @param string $group
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function pipelineJs($group = 'head')
|
||||
{
|
||||
/** @var Cache $cache */
|
||||
$cache = Grav::instance()['cache'];
|
||||
$cache = self::getGrav()['cache'];
|
||||
$key = '?' . $cache->getKey();
|
||||
|
||||
// temporary list of assets to pipeline
|
||||
@@ -763,27 +702,20 @@ class Assets
|
||||
// clear no-pipeline assets lists
|
||||
$this->js_no_pipeline = [];
|
||||
|
||||
$uid = md5(json_encode($this->js) . $this->js_minify . $group);
|
||||
$file = $uid . '.js';
|
||||
$inline_file = $uid . '-inline.js';
|
||||
$file = md5(json_encode($this->js) . $this->js_minify . $group) . '.js';
|
||||
|
||||
$relative_path = "{$this->base_url}{$this->assets_url}/{$file}";
|
||||
|
||||
// If inline files exist set them on object
|
||||
if (file_exists($this->assets_dir . $inline_file)) {
|
||||
$this->js_no_pipeline = json_decode(file_get_contents($this->assets_dir . $inline_file), true);
|
||||
}
|
||||
$absolute_path = $this->assets_dir . $file;
|
||||
|
||||
// If pipeline exist return it
|
||||
if (file_exists($this->assets_dir . $file)) {
|
||||
if (file_exists($absolute_path)) {
|
||||
return $relative_path . $key;
|
||||
}
|
||||
|
||||
// Remove any non-pipeline files
|
||||
foreach ($this->js as $id => $asset) {
|
||||
if ($asset['group'] == $group) {
|
||||
if (!$asset['pipeline'] ||
|
||||
($this->isRemoteLink($asset['asset']) && $this->js_pipeline_include_externals === false)) {
|
||||
if (!$asset['pipeline']) {
|
||||
$this->js_no_pipeline[] = $asset;
|
||||
} else {
|
||||
$temp_js[$id] = $asset;
|
||||
@@ -796,23 +728,15 @@ class Assets
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write non-pipeline files out
|
||||
if (!empty($this->js_no_pipeline)) {
|
||||
file_put_contents($this->assets_dir . $inline_file, json_encode($this->js_no_pipeline));
|
||||
}
|
||||
|
||||
// Concatenate files
|
||||
$buffer = $this->gatherLinks($temp_js, JS_ASSET);
|
||||
if ($this->js_minify) {
|
||||
$minifier = new \MatthiasMullie\Minify\JS();
|
||||
$minifier->add($buffer);
|
||||
$buffer = $minifier->minify();
|
||||
$buffer = \JSMin::minify($buffer);
|
||||
}
|
||||
|
||||
// Write file
|
||||
if (strlen(trim($buffer)) > 0) {
|
||||
file_put_contents($this->assets_dir . $file, $buffer);
|
||||
|
||||
file_put_contents($absolute_path, $buffer);
|
||||
return $relative_path . $key;
|
||||
} else {
|
||||
return false;
|
||||
@@ -858,7 +782,9 @@ class Assets
|
||||
*/
|
||||
public function exists($asset)
|
||||
{
|
||||
if (isset($this->collections[$asset]) || isset($this->css[$asset]) || isset($this->js[$asset])) {
|
||||
if (isset($this->collections[$asset]) ||
|
||||
isset($this->css[$asset]) ||
|
||||
isset($this->js[$asset])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -900,8 +826,7 @@ class Assets
|
||||
*/
|
||||
public function resetJs()
|
||||
{
|
||||
$this->js = [];
|
||||
$this->inline_js = [];
|
||||
$this->js = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -913,28 +838,15 @@ class Assets
|
||||
*/
|
||||
public function resetCss()
|
||||
{
|
||||
$this->css = [];
|
||||
$this->inline_css = [];
|
||||
$this->css = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all JavaScript assets within $directory
|
||||
* Add all CSS assets within $directory (relative to public dir).
|
||||
*
|
||||
* @param string $directory Relative to the Grav root path, or a stream identifier
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addDirJs($directory)
|
||||
{
|
||||
return $this->addDir($directory, self::JS_REGEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all CSS assets within $directory
|
||||
*
|
||||
* @param string $directory Relative to the Grav root path, or a stream identifier
|
||||
* @param string $directory Relative to $this->public_dir
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -946,7 +858,7 @@ class Assets
|
||||
/**
|
||||
* Add all assets matching $pattern within $directory.
|
||||
*
|
||||
* @param string $directory Relative to the Grav root path, or a stream identifier
|
||||
* @param string $directory Relative to $this->public_dir
|
||||
* @param string $pattern (regex)
|
||||
*
|
||||
* @return $this
|
||||
@@ -954,15 +866,13 @@ class Assets
|
||||
*/
|
||||
public function addDir($directory, $pattern = self::DEFAULT_REGEX)
|
||||
{
|
||||
$root_dir = rtrim(ROOT_DIR, '/');
|
||||
|
||||
// Check if $directory is a stream.
|
||||
if (strpos($directory, '://')) {
|
||||
$directory = Grav::instance()['locator']->findResource($directory, null);
|
||||
// Check if public_dir exists
|
||||
if (!is_dir($this->assets_dir)) {
|
||||
throw new Exception('Assets: Public dir not found');
|
||||
}
|
||||
|
||||
// Get files
|
||||
$files = $this->rglob($root_dir . DIRECTORY_SEPARATOR . $directory, $pattern, $root_dir . '/');
|
||||
$files = $this->rglob($this->assets_dir . DIRECTORY_SEPARATOR . $directory, $pattern, $this->assets_dir);
|
||||
|
||||
// No luck? Nothing to do
|
||||
if (!$files) {
|
||||
@@ -971,25 +881,27 @@ class Assets
|
||||
|
||||
// Add CSS files
|
||||
if ($pattern === self::CSS_REGEX) {
|
||||
foreach ($files as $file) {
|
||||
$this->addCss($file);
|
||||
}
|
||||
|
||||
$this->css = array_unique(array_merge($this->css, $files));
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Add JavaScript files
|
||||
if ($pattern === self::JS_REGEX) {
|
||||
foreach ($files as $file) {
|
||||
$this->addJs($file);
|
||||
}
|
||||
|
||||
$this->js = array_unique(array_merge($this->js, $files));
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Unknown pattern.
|
||||
// Unknown pattern. We must poll to know the extension :(
|
||||
foreach ($files as $asset) {
|
||||
$this->add($asset);
|
||||
$info = pathinfo($asset);
|
||||
if (isset($info['extension'])) {
|
||||
$ext = strtolower($info['extension']);
|
||||
if ($ext === 'css' && !in_array($asset, $this->css)) {
|
||||
$this->css[] = $asset;
|
||||
} elseif ($ext === 'js' && !in_array($asset, $this->js)) {
|
||||
$this->js[] = $asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -1006,15 +918,8 @@ class Assets
|
||||
*/
|
||||
protected function isRemoteLink($link)
|
||||
{
|
||||
$base = Grav::instance()['uri']->rootUrl(true);
|
||||
|
||||
// sanity check for local URLs with absolute URL's enabled
|
||||
if (Utils::startsWith($link, $base)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ('http://' === substr($link, 0, 7) || 'https://' === substr($link, 0, 8) || '//' === substr($link, 0,
|
||||
2));
|
||||
return ('http://' === substr($link, 0, 7) || 'https://' === substr($link, 0, 8)
|
||||
|| '//' === substr($link, 0, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1027,7 +932,7 @@ class Assets
|
||||
protected function buildLocalLink($asset)
|
||||
{
|
||||
try {
|
||||
$asset = Grav::instance()['locator']->findResource($asset, false);
|
||||
$asset = self::getGrav()['locator']->findResource($asset, false);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
@@ -1044,7 +949,6 @@ class Assets
|
||||
protected function attributes(array $attributes)
|
||||
{
|
||||
$html = '';
|
||||
$no_key = ['loading'];
|
||||
|
||||
foreach ($attributes as $key => $value) {
|
||||
// For numeric keys we will assume that the key and the value are the same
|
||||
@@ -1057,12 +961,7 @@ class Assets
|
||||
$value = implode(' ', $value);
|
||||
}
|
||||
|
||||
if (in_array($key, $no_key)) {
|
||||
$element = htmlentities($value, ENT_QUOTES, 'UTF-8', false);
|
||||
} else {
|
||||
$element = $key . '="' . htmlentities($value, ENT_QUOTES, 'UTF-8', false) . '"';
|
||||
}
|
||||
|
||||
$element = $key . '="' . htmlentities($value, ENT_QUOTES, 'UTF-8', false) . '"';
|
||||
$html .= ' ' . $element;
|
||||
}
|
||||
|
||||
@@ -1073,19 +972,18 @@ class Assets
|
||||
* Download and concatenate the content of several links.
|
||||
*
|
||||
* @param array $links
|
||||
* @param bool $css
|
||||
* @param bool $css
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function gatherLinks(array $links, $css = true)
|
||||
{
|
||||
$buffer = '';
|
||||
|
||||
|
||||
$buffer = '';
|
||||
$local = true;
|
||||
|
||||
foreach ($links as $asset) {
|
||||
$relative_dir = '';
|
||||
$local = true;
|
||||
|
||||
$link = $asset['asset'];
|
||||
$relative_path = $link;
|
||||
|
||||
@@ -1122,7 +1020,6 @@ class Assets
|
||||
$file = $this->cssRewrite($file, $relative_dir);
|
||||
}
|
||||
|
||||
$file = rtrim($file) . PHP_EOL;
|
||||
$buffer .= $file;
|
||||
}
|
||||
|
||||
@@ -1137,8 +1034,8 @@ class Assets
|
||||
/**
|
||||
* Finds relative CSS urls() and rewrites the URL with an absolute one
|
||||
*
|
||||
* @param string $file the css source file
|
||||
* @param string $relative_path relative path to the css file
|
||||
* @param $file the css source file
|
||||
* @param $relative_path relative path to the css file
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
@@ -1149,24 +1046,23 @@ class Assets
|
||||
|
||||
// Find any css url() elements, grab the URLs and calculate an absolute path
|
||||
// Then replace the old url with the new one
|
||||
$file = preg_replace_callback(self::CSS_URL_REGEX, function ($matches) use ($relative_path) {
|
||||
$file = preg_replace_callback(
|
||||
self::CSS_URL_REGEX,
|
||||
function ($matches) use ($relative_path) {
|
||||
|
||||
$old_url = $matches[2];
|
||||
$old_url = $matches[1];
|
||||
|
||||
// ensure this is not a data url
|
||||
if (strpos($old_url, 'data:') === 0) {
|
||||
return $matches[0];
|
||||
}
|
||||
// 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)) {
|
||||
return $matches[0];
|
||||
}
|
||||
$new_url = $this->base_url . ltrim(Utils::normalizePath($relative_path . '/' . $old_url), '/');
|
||||
|
||||
$new_url = $this->base_url . ltrim(Utils::normalizePath($relative_path . '/' . $old_url), '/');
|
||||
|
||||
return str_replace($old_url, $new_url, $matches[0]);
|
||||
}, $file);
|
||||
return str_replace($old_url, $new_url, $matches[0]);
|
||||
},
|
||||
$file
|
||||
);
|
||||
|
||||
return $file;
|
||||
}
|
||||
@@ -1180,13 +1076,16 @@ class Assets
|
||||
*/
|
||||
protected function moveImports($file)
|
||||
{
|
||||
$this->imports = [];
|
||||
$this->imports = array();
|
||||
|
||||
$file = preg_replace_callback(self::CSS_IMPORT_REGEX, function ($matches) {
|
||||
$this->imports[] = $matches[0];
|
||||
|
||||
return '';
|
||||
}, $file);
|
||||
$file = preg_replace_callback(
|
||||
self::CSS_IMPORT_REGEX,
|
||||
function ($matches) {
|
||||
$this->imports[] = $matches[0];
|
||||
return '';
|
||||
},
|
||||
$file
|
||||
);
|
||||
|
||||
return implode("\n", $this->imports) . "\n\n" . $file;
|
||||
}
|
||||
@@ -1202,10 +1101,17 @@ class Assets
|
||||
*/
|
||||
protected function rglob($directory, $pattern, $ltrim = null)
|
||||
{
|
||||
$iterator = new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory,
|
||||
FilesystemIterator::SKIP_DOTS)), $pattern);
|
||||
$iterator = new RegexIterator(
|
||||
new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$directory,
|
||||
FilesystemIterator::SKIP_DOTS
|
||||
)
|
||||
),
|
||||
$pattern
|
||||
);
|
||||
$offset = strlen($ltrim);
|
||||
$files = [];
|
||||
$files = array();
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
$files[] = substr($file->getPathname(), $offset);
|
||||
@@ -1214,6 +1120,18 @@ class Assets
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all JavaScript assets within $directory.
|
||||
*
|
||||
* @param string $directory Relative to $this->public_dir
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addDirJs($directory)
|
||||
{
|
||||
return $this->addDir($directory, self::JS_REGEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of CSS Pipeline
|
||||
*
|
||||
@@ -1221,7 +1139,7 @@ class Assets
|
||||
*/
|
||||
public function setCssPipeline($value)
|
||||
{
|
||||
$this->css_pipeline = (bool)$value;
|
||||
$this->css_pipeline = (bool) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1231,7 +1149,7 @@ class Assets
|
||||
*/
|
||||
public function setJsPipeline($value)
|
||||
{
|
||||
$this->js_pipeline = (bool)$value;
|
||||
$this->js_pipeline = (bool) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1241,12 +1159,9 @@ class Assets
|
||||
*/
|
||||
public function setTimestamp($value)
|
||||
{
|
||||
$this->timestamp = '?' . $value;
|
||||
$this->timestamp = '?'.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return '';
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
namespace Grav\Common\Backup;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\GravTrait;
|
||||
use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\Inflector;
|
||||
|
||||
/**
|
||||
@@ -12,6 +13,8 @@ use Grav\Common\Inflector;
|
||||
*/
|
||||
class ZipBackup
|
||||
{
|
||||
use GravTrait;
|
||||
|
||||
protected static $ignorePaths = [
|
||||
'backup',
|
||||
'cache',
|
||||
@@ -23,29 +26,21 @@ class ZipBackup
|
||||
'.git',
|
||||
'.svn',
|
||||
'.hg',
|
||||
'.idea',
|
||||
'node_modules'
|
||||
'.idea'
|
||||
];
|
||||
|
||||
/**
|
||||
* Backup
|
||||
*
|
||||
* @param null $destination
|
||||
* @param callable|null $messager
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public static function backup($destination = null, callable $messager = null)
|
||||
{
|
||||
if (!$destination) {
|
||||
$destination = Grav::instance()['locator']->findResource('backup://', true);
|
||||
$destination = self::getGrav()['locator']->findResource('backup://', true);
|
||||
|
||||
if (!$destination) {
|
||||
if (!$destination)
|
||||
throw new \RuntimeException('The backup folder is missing.');
|
||||
}
|
||||
|
||||
Folder::mkdir($destination);
|
||||
}
|
||||
|
||||
$name = Grav::instance()['config']->get('site.title', basename(GRAV_ROOT));
|
||||
$name = self::getGrav()['config']->get('site.title', basename(GRAV_ROOT));
|
||||
|
||||
$inflector = new Inflector();
|
||||
|
||||
@@ -69,8 +64,6 @@ class ZipBackup
|
||||
$zip = new \ZipArchive();
|
||||
$zip->open($destination, \ZipArchive::CREATE);
|
||||
|
||||
$max_execution_time = ini_set('max_execution_time', 600);
|
||||
|
||||
static::folderToZip(GRAV_ROOT, $zip, strlen(rtrim(GRAV_ROOT, DS) . DS), $messager);
|
||||
|
||||
$messager && $messager([
|
||||
@@ -92,10 +85,6 @@ class ZipBackup
|
||||
|
||||
$zip->close();
|
||||
|
||||
if ($max_execution_time !== false) {
|
||||
ini_set('max_execution_time', $max_execution_time);
|
||||
}
|
||||
|
||||
return $destination;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,13 @@
|
||||
namespace Grav\Common;
|
||||
|
||||
/**
|
||||
* Handles browser and platform versions
|
||||
*
|
||||
* Internally uses the PhpUserAgent package https://github.com/donatj/PhpUserAgent
|
||||
*
|
||||
* @author RocketTheme
|
||||
* @license MIT
|
||||
* Simple wrapper for the very simple parse_user_agent() function
|
||||
*/
|
||||
class Browser
|
||||
{
|
||||
|
||||
protected $useragent = [];
|
||||
|
||||
/**
|
||||
* Browser constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
try {
|
||||
@@ -25,99 +18,29 @@ class Browser
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current browser identifier
|
||||
*
|
||||
* Currently detected browsers:
|
||||
*
|
||||
* Android Browser
|
||||
* BlackBerry Browser
|
||||
* Camino
|
||||
* Kindle / Silk
|
||||
* Firefox / Iceweasel
|
||||
* Safari
|
||||
* Internet Explorer
|
||||
* IEMobile
|
||||
* Chrome
|
||||
* Opera
|
||||
* Midori
|
||||
* Vivaldi
|
||||
* TizenBrowser
|
||||
* Lynx
|
||||
* Wget
|
||||
* Curl
|
||||
*
|
||||
* @return string the lowercase browser name
|
||||
*/
|
||||
public function getBrowser()
|
||||
{
|
||||
return strtolower($this->useragent['browser']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current platform identifier
|
||||
*
|
||||
* Currently detected platforms:
|
||||
*
|
||||
* Desktop
|
||||
* -> Windows
|
||||
* -> Linux
|
||||
* -> Macintosh
|
||||
* -> Chrome OS
|
||||
* Mobile
|
||||
* -> Android
|
||||
* -> iPhone
|
||||
* -> iPad / iPod Touch
|
||||
* -> Windows Phone OS
|
||||
* -> Kindle
|
||||
* -> Kindle Fire
|
||||
* -> BlackBerry
|
||||
* -> Playbook
|
||||
* -> Tizen
|
||||
* Console
|
||||
* -> Nintendo 3DS
|
||||
* -> New Nintendo 3DS
|
||||
* -> Nintendo Wii
|
||||
* -> Nintendo WiiU
|
||||
* -> PlayStation 3
|
||||
* -> PlayStation 4
|
||||
* -> PlayStation Vita
|
||||
* -> Xbox 360
|
||||
* -> Xbox One
|
||||
*
|
||||
* @return string the lowercase platform name
|
||||
*/
|
||||
public function getPlatform()
|
||||
{
|
||||
return strtolower($this->useragent['platform']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current full version identifier
|
||||
*
|
||||
* @return string the browser full version identifier
|
||||
*/
|
||||
public function getLongVersion()
|
||||
{
|
||||
return $this->useragent['version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current major version identifier
|
||||
*
|
||||
* @return string the browser major version identifier
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$version = explode('.', $this->getLongVersion());
|
||||
|
||||
return intval($version[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request comes from a human, or from a bot/crawler
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isHuman()
|
||||
{
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
namespace Grav\Common;
|
||||
|
||||
use \Doctrine\Common\Cache as DoctrineCache;
|
||||
use \Doctrine\Common\Cache\Cache as DoctrineCache;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\Grav;
|
||||
|
||||
/**
|
||||
* The GravCache object is used throughout Grav to store and retrieve cached data.
|
||||
@@ -17,11 +16,13 @@ use Grav\Common\Grav;
|
||||
* MemCacheD
|
||||
* FileSystem
|
||||
*
|
||||
* @author RocketTheme
|
||||
* @author RocketTheme
|
||||
* @license MIT
|
||||
*/
|
||||
class Cache extends Getters
|
||||
{
|
||||
use GravTrait;
|
||||
|
||||
/**
|
||||
* @var string Cache key.
|
||||
*/
|
||||
@@ -30,18 +31,15 @@ class Cache extends Getters
|
||||
protected $lifetime;
|
||||
protected $now;
|
||||
|
||||
/** @var Config $config */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var DoctrineCache\CacheProvider
|
||||
* @var DoctrineCache
|
||||
*/
|
||||
protected $driver;
|
||||
|
||||
protected $driver_name;
|
||||
|
||||
protected $driver_setting;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
@@ -79,7 +77,7 @@ class Cache extends Getters
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Grav $grav
|
||||
* @params Grav $grav
|
||||
*/
|
||||
public function __construct(Grav $grav)
|
||||
{
|
||||
@@ -90,7 +88,6 @@ class Cache extends Getters
|
||||
* Initialization that sets a base key and the driver based on configuration settings
|
||||
*
|
||||
* @param Grav $grav
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function init(Grav $grav)
|
||||
@@ -106,13 +103,10 @@ class Cache extends Getters
|
||||
|
||||
$prefix = $this->config->get('system.cache.prefix');
|
||||
|
||||
$this->enabled = (bool)$this->config->get('system.cache.enabled');
|
||||
$this->enabled = (bool) $this->config->get('system.cache.enabled');
|
||||
|
||||
// Cache key allows us to invalidate all cache on configuration changes.
|
||||
$this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION),
|
||||
2, 8);
|
||||
|
||||
$this->driver_setting = $this->config->get('system.cache.driver');
|
||||
$this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION), 2, 8);
|
||||
|
||||
$this->driver = $this->getCacheDriver();
|
||||
|
||||
@@ -120,7 +114,7 @@ class Cache extends Getters
|
||||
$this->driver->setNamespace($this->key);
|
||||
|
||||
// Dump Cache state
|
||||
$grav['debugger']->addMessage('Cache: [' . ($this->enabled ? 'true' : 'false') . '] Setting: [' . $this->driver_setting . '] Driver: [' . $this->driver_name . ']');
|
||||
$grav['debugger']->addMessage('Cache: [' . ($this->enabled ? 'true' : 'false') . '] Driver: [' . $this->driver_name . ']');
|
||||
|
||||
}
|
||||
|
||||
@@ -129,17 +123,15 @@ class Cache extends Getters
|
||||
* If there is no config option for $driver in the config, or it's set to 'auto', it will
|
||||
* pick the best option based on which cache extensions are installed.
|
||||
*
|
||||
* @return DoctrineCache\CacheProvider The cache driver to use
|
||||
* @return DoctrineCacheDriver The cache driver to use
|
||||
*/
|
||||
public function getCacheDriver()
|
||||
{
|
||||
$setting = $this->driver_setting;
|
||||
$setting = $this->config->get('system.cache.driver');
|
||||
$driver_name = 'file';
|
||||
|
||||
if (!$setting || $setting == 'auto') {
|
||||
if (extension_loaded('apcu')) {
|
||||
$driver_name = 'apcu';
|
||||
} elseif (extension_loaded('apc')) {
|
||||
if (extension_loaded('apc')) {
|
||||
$driver_name = 'apc';
|
||||
} elseif (extension_loaded('wincache')) {
|
||||
$driver_name = 'wincache';
|
||||
@@ -154,40 +146,36 @@ class Cache extends Getters
|
||||
|
||||
switch ($driver_name) {
|
||||
case 'apc':
|
||||
$driver = new DoctrineCache\ApcCache();
|
||||
break;
|
||||
|
||||
case 'apcu':
|
||||
$driver = new DoctrineCache\ApcuCache();
|
||||
$driver = new \Doctrine\Common\Cache\ApcCache();
|
||||
break;
|
||||
|
||||
case 'wincache':
|
||||
$driver = new DoctrineCache\WinCacheCache();
|
||||
$driver = new \Doctrine\Common\Cache\WinCacheCache();
|
||||
break;
|
||||
|
||||
case 'xcache':
|
||||
$driver = new DoctrineCache\XcacheCache();
|
||||
$driver = new \Doctrine\Common\Cache\XcacheCache();
|
||||
break;
|
||||
|
||||
case 'memcache':
|
||||
$memcache = new \Memcache();
|
||||
$memcache->connect($this->config->get('system.cache.memcache.server', 'localhost'),
|
||||
$this->config->get('system.cache.memcache.port', 11211));
|
||||
$driver = new DoctrineCache\MemcacheCache();
|
||||
$memcache->connect($this->config->get('system.cache.memcache.server','localhost'),
|
||||
$this->config->get('system.cache.memcache.port', 11211));
|
||||
$driver = new \Doctrine\Common\Cache\MemcacheCache();
|
||||
$driver->setMemcache($memcache);
|
||||
break;
|
||||
|
||||
case 'redis':
|
||||
$redis = new \Redis();
|
||||
$redis->connect($this->config->get('system.cache.redis.server', 'localhost'),
|
||||
$this->config->get('system.cache.redis.port', 6379));
|
||||
$redis->connect($this->config->get('system.cache.redis.server','localhost'),
|
||||
$this->config->get('system.cache.redis.port', 6379));
|
||||
|
||||
$driver = new DoctrineCache\RedisCache();
|
||||
$driver = new \Doctrine\Common\Cache\RedisCache();
|
||||
$driver->setRedis($redis);
|
||||
break;
|
||||
|
||||
default:
|
||||
$driver = new DoctrineCache\FilesystemCache($this->cache_dir);
|
||||
$driver = new \Doctrine\Common\Cache\FilesystemCache($this->cache_dir);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -198,7 +186,6 @@ class Cache extends Getters
|
||||
* Gets a cached entry if it exists based on an id. If it does not exist, it returns false
|
||||
*
|
||||
* @param string $id the id of the cached entry
|
||||
*
|
||||
* @return object returns the cached entry, can be any type, or false if doesn't exist
|
||||
*/
|
||||
public function fetch($id)
|
||||
@@ -213,9 +200,9 @@ class Cache extends Getters
|
||||
/**
|
||||
* Stores a new cached entry.
|
||||
*
|
||||
* @param string $id the id of the cached entry
|
||||
* @param string $id the id of the cached entry
|
||||
* @param array|object $data the data for the cached entry to store
|
||||
* @param int $lifetime the lifetime to store the entry in seconds
|
||||
* @param int $lifetime the lifetime to store the entry in seconds
|
||||
*/
|
||||
public function save($id, $data, $lifetime = null)
|
||||
{
|
||||
@@ -227,34 +214,6 @@ class Cache extends Getters
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an item in the cache based on the id
|
||||
*
|
||||
* @param string $id the id of the cached data entry
|
||||
* @return bool true if the item was deleted successfully
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
if ($this->enabled) {
|
||||
return $this->driver->delete($id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean state of whether or not the item exists in the cache based on id key
|
||||
*
|
||||
* @param string $id the id of the cached data entry
|
||||
* @return bool true if the cached items exists
|
||||
*/
|
||||
public function contains($id)
|
||||
{
|
||||
if ($this->enabled) {
|
||||
return $this->driver->contains(($id));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method to get the cache key
|
||||
*/
|
||||
@@ -263,29 +222,20 @@ class Cache extends Getters
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter method to set key (Advanced)
|
||||
*/
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->driver->setNamespace($this->key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to clear all Grav caches
|
||||
*
|
||||
* @param string $remove standard|all|assets-only|images-only|cache-only
|
||||
* @param string $remove standard|all|assets-only|images-only|cache-only
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function clearCache($remove = 'standard')
|
||||
{
|
||||
$locator = Grav::instance()['locator'];
|
||||
$locator = self::getGrav()['locator'];
|
||||
$output = [];
|
||||
$user_config = USER_DIR . 'config/system.yaml';
|
||||
|
||||
switch ($remove) {
|
||||
switch($remove) {
|
||||
case 'all':
|
||||
$remove_paths = self::$all_remove;
|
||||
break;
|
||||
@@ -308,9 +258,8 @@ class Cache extends Getters
|
||||
// Convert stream to a real path
|
||||
$path = $locator->findResource($stream, true, true);
|
||||
// Make sure path exists before proceeding, otherwise we would wipe ROOT_DIR
|
||||
if (!$path) {
|
||||
if (!$path)
|
||||
throw new \RuntimeException("Stream '{$stream}' not found", 500);
|
||||
}
|
||||
|
||||
$anything = false;
|
||||
$files = glob($path . '/*');
|
||||
@@ -322,7 +271,7 @@ class Cache extends Getters
|
||||
$anything = true;
|
||||
}
|
||||
} elseif (is_dir($file)) {
|
||||
if (Folder::delete($file)) {
|
||||
if (@Folder::delete($file)) {
|
||||
$anything = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,6 @@ class Composer
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the composer executable file path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getComposerExecutor()
|
||||
{
|
||||
$executor = PHP_BINARY . ' ';
|
||||
|
||||
@@ -192,9 +192,7 @@ abstract class CompiledBase
|
||||
}
|
||||
|
||||
$this->createObject($cache['data']);
|
||||
|
||||
$this->finalizeObject();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -226,7 +224,7 @@ abstract class CompiledBase
|
||||
'timestamp' => time(),
|
||||
'checksum' => $this->checksum(),
|
||||
'files' => $this->files,
|
||||
'data' => $this->getState()
|
||||
'data' => $this->object->toArray()
|
||||
];
|
||||
|
||||
$file->save($cache);
|
||||
@@ -235,9 +233,4 @@ abstract class CompiledBase
|
||||
|
||||
$this->modified();
|
||||
}
|
||||
|
||||
protected function getState()
|
||||
{
|
||||
return $this->object->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
namespace Grav\Common\Config;
|
||||
|
||||
use Grav\Common\Data\Blueprint;
|
||||
use Grav\Common\Data\BlueprintSchema;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\File\CompiledYamlFile;
|
||||
use RocketTheme\Toolbox\Blueprints\Blueprints;
|
||||
|
||||
/**
|
||||
* The Compiled Blueprints class.
|
||||
@@ -13,29 +12,13 @@ class CompiledBlueprints extends CompiledBase
|
||||
/**
|
||||
* @var int Version number for the compiled file.
|
||||
*/
|
||||
public $version = 2;
|
||||
public $version = 1;
|
||||
|
||||
/**
|
||||
* @var BlueprintSchema Blueprints object.
|
||||
* @var Blueprints Blueprints object.
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Returns checksum from the configuration files.
|
||||
*
|
||||
* You can set $this->checksum = false to disable this check.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function checksum()
|
||||
{
|
||||
if (!isset($this->checksum)) {
|
||||
$this->checksum = md5(json_encode($this->files) . json_encode($this->getTypes()) . $this->version);
|
||||
}
|
||||
|
||||
return $this->checksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create configuration object.
|
||||
*
|
||||
@@ -43,70 +26,24 @@ class CompiledBlueprints extends CompiledBase
|
||||
*/
|
||||
protected function createObject(array $data = [])
|
||||
{
|
||||
$this->object = (new BlueprintSchema($data))->setTypes($this->getTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of form field types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getTypes()
|
||||
{
|
||||
return Grav::instance()['plugins']->formFieldTypes ?: [];
|
||||
$this->object = new Blueprints($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize configuration object.
|
||||
*/
|
||||
protected function finalizeObject()
|
||||
{
|
||||
}
|
||||
protected function finalizeObject() {}
|
||||
|
||||
/**
|
||||
* Load single configuration file and append it to the correct position.
|
||||
*
|
||||
* @param string $name Name of the position.
|
||||
* @param array $files Files to be loaded.
|
||||
* @param string $filename File to be loaded.
|
||||
*/
|
||||
protected function loadFile($name, $files)
|
||||
protected function loadFile($name, $filename)
|
||||
{
|
||||
// Load blueprint file.
|
||||
$blueprint = new Blueprint($files);
|
||||
|
||||
$this->object->embed($name, $blueprint->load()->toArray(), '/', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and join all configuration files.
|
||||
*
|
||||
* @return bool
|
||||
* @internal
|
||||
*/
|
||||
protected function loadFiles()
|
||||
{
|
||||
$this->createObject();
|
||||
|
||||
// Convert file list into parent list.
|
||||
$list = [];
|
||||
foreach ($this->files as $files) {
|
||||
foreach ($files as $name => $item) {
|
||||
$list[$name][] = $this->path . $item['file'];
|
||||
}
|
||||
}
|
||||
|
||||
// Load files.
|
||||
foreach ($list as $name => $files) {
|
||||
$this->loadFile($name, $files);
|
||||
}
|
||||
|
||||
$this->finalizeObject();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getState()
|
||||
{
|
||||
return $this->object->getState();
|
||||
$file = CompiledYamlFile::instance($filename);
|
||||
$this->object->embed($name, $file->content(), '/');
|
||||
$file->free();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Grav\Common\Config;
|
||||
use Grav\Common\File\CompiledYamlFile;
|
||||
use Grav\Common\Data\Data;
|
||||
use Grav\Common\Utils;
|
||||
use Pimple\Container;
|
||||
use RocketTheme\Toolbox\File\YamlFile;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
|
||||
@@ -114,12 +113,12 @@ class Setup extends Data
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Container|array $container
|
||||
*/
|
||||
public function __construct($container)
|
||||
{
|
||||
$environment = $container['uri']->environment() ?: 'localhost';
|
||||
$environment = $container['uri']->environment();
|
||||
if (!$environment) {
|
||||
$environment = 'localhost';
|
||||
}
|
||||
|
||||
// Pre-load setup.php which contains our initial configuration.
|
||||
// Configuration may contain dynamic parts, which is why we need to always load it.
|
||||
@@ -159,7 +158,7 @@ class Setup extends Data
|
||||
}
|
||||
|
||||
// Update streams.
|
||||
foreach (array_reverse($files) as $path) {
|
||||
foreach ($files as $path) {
|
||||
$file = CompiledYamlFile::instance($path);
|
||||
$content = $file->content();
|
||||
if (!empty($content['schemes'])) {
|
||||
|
||||
@@ -1,55 +1,87 @@
|
||||
<?php
|
||||
namespace Grav\Common\Data;
|
||||
|
||||
use Grav\Common\File\CompiledYamlFile;
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\Blueprints\BlueprintForm;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
use Grav\Common\GravTrait;
|
||||
use RocketTheme\Toolbox\ArrayTraits\Export;
|
||||
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
|
||||
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
|
||||
|
||||
/**
|
||||
* The Config class contains configuration information.
|
||||
* Blueprint handles the inside logic of blueprints.
|
||||
*
|
||||
* @author RocketTheme
|
||||
* @license MIT
|
||||
*/
|
||||
class Blueprint extends BlueprintForm
|
||||
class Blueprint implements \ArrayAccess, ExportInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $context = 'blueprints://';
|
||||
use Export, NestedArrayAccessWithGetters, GravTrait;
|
||||
|
||||
public $name;
|
||||
|
||||
public $initialized = false;
|
||||
|
||||
protected $items;
|
||||
protected $context;
|
||||
protected $fields;
|
||||
protected $rules = array();
|
||||
protected $nested = array();
|
||||
protected $filter = ['validation' => 1];
|
||||
|
||||
/**
|
||||
* @var BlueprintSchema
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
* @param Blueprints $context
|
||||
*/
|
||||
protected $blueprintSchema;
|
||||
|
||||
/**
|
||||
* Set default values for field types.
|
||||
*
|
||||
* @param array $types
|
||||
* @return $this
|
||||
*/
|
||||
public function setTypes(array $types)
|
||||
public function __construct($name, array $data = array(), Blueprints $context = null)
|
||||
{
|
||||
$this->initInternals();
|
||||
|
||||
$this->blueprintSchema->setTypes($types);
|
||||
|
||||
return $this;
|
||||
$this->name = $name;
|
||||
$this->items = $data;
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nested structure containing default values defined in the blueprints.
|
||||
* Set filter for inherited properties.
|
||||
*
|
||||
* Fields without default value are ignored in the list.
|
||||
* @param array $filter List of field names to be inherited.
|
||||
*/
|
||||
public function setFilter(array $filter)
|
||||
{
|
||||
$this->filter = array_flip($filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all form fields.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaults()
|
||||
public function fields()
|
||||
{
|
||||
$this->initInternals();
|
||||
if (!isset($this->fields)) {
|
||||
$this->fields = [];
|
||||
$this->embed('', $this->items);
|
||||
}
|
||||
|
||||
return $this->blueprintSchema->getDefaults();
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate data against blueprints.
|
||||
*
|
||||
* @param array $data
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function validate(array $data)
|
||||
{
|
||||
// Initialize data
|
||||
$this->fields();
|
||||
|
||||
try {
|
||||
$this->validateArray($data, $this->nested);
|
||||
} catch (\RuntimeException $e) {
|
||||
$language = self::getGrav()['language'];
|
||||
$message = sprintf($language->translate('FORM.VALIDATION_FAIL', null, true) . ' %s', $e->getMessage());
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,15 +89,26 @@ class Blueprint extends BlueprintForm
|
||||
*
|
||||
* @param array $data1
|
||||
* @param array $data2
|
||||
* @param string $name Optional
|
||||
* @param string $separator Optional
|
||||
* @return array
|
||||
*/
|
||||
public function mergeData(array $data1, array $data2, $name = null, $separator = '.')
|
||||
public function mergeData(array $data1, array $data2)
|
||||
{
|
||||
$this->initInternals();
|
||||
// Initialize data
|
||||
$this->fields();
|
||||
return $this->mergeArrays($data1, $data2, $this->nested);
|
||||
}
|
||||
|
||||
return $this->blueprintSchema->mergeData($data1, $data2, $name, $separator);
|
||||
/**
|
||||
* Filter data by using blueprints.
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function filter(array $data)
|
||||
{
|
||||
// Initialize data
|
||||
$this->fields();
|
||||
return $this->filterArray($data, $this->nested);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,164 +120,355 @@ class Blueprint extends BlueprintForm
|
||||
*/
|
||||
public function extra(array $data, $prefix = '')
|
||||
{
|
||||
$this->initInternals();
|
||||
// Initialize data
|
||||
$this->fields();
|
||||
$rules = $this->nested;
|
||||
|
||||
return $this->blueprintSchema->extra($data, $prefix);
|
||||
// Drill down to prefix level
|
||||
if (!empty($prefix)) {
|
||||
$parts = explode('.', trim($prefix, '.'));
|
||||
foreach ($parts as $part) {
|
||||
$rules = isset($rules[$part]) ? $rules[$part] : [];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->extraArray($data, $rules, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate data against blueprints.
|
||||
* Extend blueprint with another blueprint.
|
||||
*
|
||||
* @param array $data
|
||||
* @param Blueprint $extends
|
||||
* @param bool $append
|
||||
*/
|
||||
public function extend(Blueprint $extends, $append = false)
|
||||
{
|
||||
$blueprints = $append ? $this->items : $extends->toArray();
|
||||
$appended = $append ? $extends->toArray() : $this->items;
|
||||
|
||||
$bref_stack = array(&$blueprints);
|
||||
$head_stack = array($appended);
|
||||
|
||||
do {
|
||||
end($bref_stack);
|
||||
|
||||
$bref = &$bref_stack[key($bref_stack)];
|
||||
$head = array_pop($head_stack);
|
||||
|
||||
unset($bref_stack[key($bref_stack)]);
|
||||
|
||||
foreach (array_keys($head) as $key) {
|
||||
if (isset($key, $bref[$key]) && is_array($bref[$key]) && is_array($head[$key])) {
|
||||
$bref_stack[] = &$bref[$key];
|
||||
$head_stack[] = $head[$key];
|
||||
} else {
|
||||
$bref = array_merge($bref, array($key => $head[$key]));
|
||||
}
|
||||
}
|
||||
} while (count($head_stack));
|
||||
|
||||
$this->items = $blueprints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert object into an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getState()
|
||||
{
|
||||
return ['name' => $this->name, 'items' => $this->items, 'rules' => $this->rules, 'nested' => $this->nested];
|
||||
}
|
||||
|
||||
/**
|
||||
* Embed an array to the blueprint.
|
||||
*
|
||||
* @param $name
|
||||
* @param array $value
|
||||
* @param string $separator
|
||||
*/
|
||||
public function embed($name, array $value, $separator = '.')
|
||||
{
|
||||
|
||||
if (!isset($value['form']['fields']) || !is_array($value['form']['fields'])) {
|
||||
return;
|
||||
}
|
||||
// Initialize data
|
||||
$this->fields();
|
||||
$prefix = $name ? strtr($name, $separator, '.') . '.' : '';
|
||||
$params = array_intersect_key($this->filter, $value);
|
||||
$this->parseFormFields($value['form']['fields'], $params, $prefix, $this->fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @throws \RuntimeException
|
||||
* @internal
|
||||
*/
|
||||
public function validate(array $data)
|
||||
protected function validateArray(array $data, array $rules)
|
||||
{
|
||||
$this->initInternals();
|
||||
$this->checkRequired($data, $rules);
|
||||
|
||||
$this->blueprintSchema->validate($data);
|
||||
foreach ($data as $key => $field) {
|
||||
$val = isset($rules[$key]) ? $rules[$key] : null;
|
||||
$rule = is_string($val) ? $this->rules[$val] : null;
|
||||
|
||||
if ($rule) {
|
||||
// Item has been defined in blueprints.
|
||||
Validation::validate($field, $rule);
|
||||
} elseif (is_array($field) && is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$this->validateArray($field, $val);
|
||||
} elseif (isset($this->items['form']['validation']) && $this->items['form']['validation'] == 'strict') {
|
||||
// Undefined/extra item.
|
||||
throw new \RuntimeException(sprintf('%s is not defined in blueprints', $key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter data by using blueprints.
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @return array
|
||||
* @internal
|
||||
*/
|
||||
protected function filterArray(array $data, array $rules)
|
||||
{
|
||||
$results = array();
|
||||
foreach ($data as $key => $field) {
|
||||
$val = isset($rules[$key]) ? $rules[$key] : null;
|
||||
$rule = is_string($val) ? $this->rules[$val] : null;
|
||||
|
||||
if ($rule) {
|
||||
// Item has been defined in blueprints.
|
||||
$field = Validation::filter($field, $rule);
|
||||
} elseif (is_array($field) && is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$field = $this->filterArray($field, $val);
|
||||
} elseif (isset($this->items['form']['validation']) && $this->items['form']['validation'] == 'strict') {
|
||||
$field = null;
|
||||
}
|
||||
|
||||
if (isset($field) && (!is_array($field) || !empty($field))) {
|
||||
$results[$key] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data1
|
||||
* @param array $data2
|
||||
* @param array $rules
|
||||
* @return array
|
||||
* @internal
|
||||
*/
|
||||
protected function mergeArrays(array $data1, array $data2, array $rules)
|
||||
{
|
||||
foreach ($data2 as $key => $field) {
|
||||
$val = isset($rules[$key]) ? $rules[$key] : null;
|
||||
$rule = is_string($val) ? $this->rules[$val] : null;
|
||||
|
||||
if (!$rule && array_key_exists($key, $data1) && is_array($field) && is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$data1[$key] = $this->mergeArrays($data1[$key], $field, $val);
|
||||
} else {
|
||||
// Otherwise just take value from the data2.
|
||||
$data1[$key] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $data1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @param string $prefix
|
||||
* @return array
|
||||
* @internal
|
||||
*/
|
||||
protected function extraArray(array $data, array $rules, $prefix)
|
||||
{
|
||||
$array = array();
|
||||
foreach ($data as $key => $field) {
|
||||
$val = isset($rules[$key]) ? $rules[$key] : null;
|
||||
$rule = is_string($val) ? $this->rules[$val] : null;
|
||||
|
||||
if ($rule) {
|
||||
// Item has been defined in blueprints.
|
||||
} elseif (is_array($field) && is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$array += $this->ExtraArray($field, $val, $prefix . $key . '.');
|
||||
} else {
|
||||
// Undefined/extra item.
|
||||
$array[$prefix.$key] = $field;
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all field definitions from the blueprints.
|
||||
*
|
||||
* @param array $fields
|
||||
* @param array $params
|
||||
* @param string $prefix
|
||||
* @param array $current
|
||||
* @internal
|
||||
*/
|
||||
protected function parseFormFields(array &$fields, $params, $prefix, array &$current)
|
||||
{
|
||||
// Go though all the fields in current level.
|
||||
foreach ($fields as $key => &$field) {
|
||||
$current[$key] = &$field;
|
||||
// Set name from the array key.
|
||||
$field['name'] = $prefix . $key;
|
||||
$field += $params;
|
||||
|
||||
if (isset($field['fields']) && (!isset($field['type']) || $field['type'] !== 'list')) {
|
||||
// Recursively get all the nested fields.
|
||||
$newParams = array_intersect_key($this->filter, $field);
|
||||
$this->parseFormFields($field['fields'], $newParams, $prefix, $current[$key]['fields']);
|
||||
} else if ($field['type'] !== 'ignore') {
|
||||
$this->rules[$prefix . $key] = &$field;
|
||||
$this->addProperty($prefix . $key);
|
||||
|
||||
if ($field['type'] === 'list') {
|
||||
// we loop through list to get the actual field
|
||||
foreach($field['fields'] as $subName => &$subField) {
|
||||
$this->parseFormField($subField);
|
||||
}
|
||||
} else {
|
||||
$this->parseFormField($field);
|
||||
}
|
||||
|
||||
if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') {
|
||||
$field['validate'] += $this->getRule($field['validate']['rule']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parses individual field definition
|
||||
*
|
||||
* @param array $field
|
||||
* @internal
|
||||
*/
|
||||
protected function parseFormField(&$field) {
|
||||
foreach ($field as $name => $value) {
|
||||
// Support nested blueprints.
|
||||
if ($this->context && $name == '@import') {
|
||||
$values = (array) $value;
|
||||
if (!isset($field['fields'])) {
|
||||
$field['fields'] = array();
|
||||
}
|
||||
foreach ($values as $bname) {
|
||||
$b = $this->context->get($bname);
|
||||
$field['fields'] = array_merge($field['fields'], $b->fields());
|
||||
}
|
||||
}
|
||||
|
||||
// Support for callable data values.
|
||||
elseif (substr($name, 0, 6) == '@data-') {
|
||||
$property = substr($name, 6);
|
||||
if (is_array($value)) {
|
||||
$func = array_shift($value);
|
||||
} else {
|
||||
$func = $value;
|
||||
$value = array();
|
||||
}
|
||||
list($o, $f) = preg_split('/::/', $func);
|
||||
if (!$f && function_exists($o)) {
|
||||
$data = call_user_func_array($o, $value);
|
||||
} elseif ($f && method_exists($o, $f)) {
|
||||
$data = call_user_func_array(array($o, $f), $value);
|
||||
}
|
||||
|
||||
// If function returns a value,
|
||||
if (isset($data)) {
|
||||
if (isset($field[$property]) && is_array($field[$property]) && is_array($data)) {
|
||||
// Combine field and @data-field together.
|
||||
$field[$property] += $data;
|
||||
} else {
|
||||
// Or create/replace field with @data-field.
|
||||
$field[$property] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elseif (substr($name, 0, 8) == '@config-') {
|
||||
$property = substr($name, 8);
|
||||
$default = isset($field[$property]) ? $field[$property] : null;
|
||||
$config = self::getGrav()['config']->get($value, $default);
|
||||
|
||||
if (!is_null($config)) {
|
||||
$field[$property] = $config;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add property to the definition.
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $path Comma separated path to the property.
|
||||
* @internal
|
||||
*/
|
||||
protected function addProperty($path)
|
||||
{
|
||||
$parts = explode('.', $path);
|
||||
$item = array_pop($parts);
|
||||
|
||||
$nested = &$this->nested;
|
||||
foreach ($parts as $part) {
|
||||
if (!isset($nested[$part])) {
|
||||
$nested[$part] = array();
|
||||
}
|
||||
$nested = &$nested[$part];
|
||||
}
|
||||
|
||||
if (!isset($nested[$item])) {
|
||||
$nested[$item] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $rule
|
||||
* @return array
|
||||
* @internal
|
||||
*/
|
||||
public function filter(array $data)
|
||||
protected function getRule($rule)
|
||||
{
|
||||
$this->initInternals();
|
||||
|
||||
return $this->blueprintSchema->filter($data);
|
||||
if (isset($this->items['rules'][$rule]) && is_array($this->items['rules'][$rule])) {
|
||||
return $this->items['rules'][$rule];
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize validator.
|
||||
* @param array $data
|
||||
* @param array $fields
|
||||
* @throws \RuntimeException
|
||||
* @internal
|
||||
*/
|
||||
protected function initInternals()
|
||||
protected function checkRequired(array $data, array $fields)
|
||||
{
|
||||
if (!isset($this->blueprintSchema)) {
|
||||
$types = Grav::instance()['plugins']->formFieldTypes;
|
||||
|
||||
$this->blueprintSchema = new BlueprintSchema;
|
||||
if ($types) {
|
||||
$this->blueprintSchema->setTypes($types);
|
||||
foreach ($fields as $name => $field) {
|
||||
if (!is_string($field)) {
|
||||
continue;
|
||||
}
|
||||
$this->blueprintSchema->embed('', $this->items);
|
||||
$this->blueprintSchema->init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
protected function loadFile($filename)
|
||||
{
|
||||
$file = CompiledYamlFile::instance($filename);
|
||||
$content = $file->content();
|
||||
$file->free();
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $path
|
||||
* @param string $context
|
||||
* @return array
|
||||
*/
|
||||
protected function getFiles($path, $context = null)
|
||||
{
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = Grav::instance()['locator'];
|
||||
|
||||
if (is_string($path) && !$locator->isStream($path)) {
|
||||
// Find path overrides.
|
||||
$paths = isset($this->overrides[$path]) ? (array) $this->overrides[$path] : [];
|
||||
|
||||
// Add path pointing to default context.
|
||||
if ($context === null) {
|
||||
$context = $this->context;
|
||||
$field = $this->rules[$field];
|
||||
if (isset($field['validate']['required'])
|
||||
&& $field['validate']['required'] === true
|
||||
&& empty($data[$name])) {
|
||||
$value = isset($field['label']) ? $field['label'] : $field['name'];
|
||||
$language = self::getGrav()['language'];
|
||||
$message = sprintf($language->translate('FORM.MISSING_REQUIRED_FIELD', null, true) . ' %s', $value);
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
if ($context && $context[strlen($context)-1] !== '/') {
|
||||
$context .= '/';
|
||||
}
|
||||
$path = $context . $path;
|
||||
|
||||
if (!preg_match('/\.yaml$/', $path)) {
|
||||
$path .= '.yaml';
|
||||
}
|
||||
|
||||
$paths[] = $path;
|
||||
} else {
|
||||
$paths = (array) $path;
|
||||
}
|
||||
|
||||
$files = [];
|
||||
foreach ($paths as $lookup) {
|
||||
if (is_string($lookup) && strpos($lookup, '://')) {
|
||||
$files = array_merge($files, $locator->findResources($lookup));
|
||||
} else {
|
||||
$files[] = $lookup;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($files));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $field
|
||||
* @param string $property
|
||||
* @param array $call
|
||||
*/
|
||||
protected function dynamicData(array &$field, $property, array &$call)
|
||||
{
|
||||
$params = $call['params'];
|
||||
|
||||
if (is_array($params)) {
|
||||
$function = array_shift($params);
|
||||
} else {
|
||||
$function = $params;
|
||||
$params = [];
|
||||
}
|
||||
|
||||
list($o, $f) = preg_split('/::/', $function, 2);
|
||||
if (!$f) {
|
||||
if (function_exists($o)) {
|
||||
$data = call_user_func_array($o, $params);
|
||||
}
|
||||
} else {
|
||||
if (method_exists($o, $f)) {
|
||||
$data = call_user_func_array(array($o, $f), $params);
|
||||
}
|
||||
}
|
||||
|
||||
// If function returns a value,
|
||||
if (isset($data)) {
|
||||
if (isset($field[$property]) && is_array($field[$property]) && is_array($data)) {
|
||||
// Combine field and @data-field together.
|
||||
$field[$property] += $data;
|
||||
} else {
|
||||
// Or create/replace field with @data-field.
|
||||
$field[$property] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $field
|
||||
* @param string $property
|
||||
* @param array $call
|
||||
*/
|
||||
protected function dynamicConfig(array &$field, $property, array &$call)
|
||||
{
|
||||
$value = $call['params'];
|
||||
|
||||
$default = isset($field[$property]) ? $field[$property] : null;
|
||||
$config = Grav::instance()['config']->get($value, $default);
|
||||
|
||||
if (!is_null($config)) {
|
||||
$field[$property] = $config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
<?php
|
||||
namespace Grav\Common\Data;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\ArrayTraits\Export;
|
||||
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
|
||||
use RocketTheme\Toolbox\Blueprints\BlueprintSchema as BlueprintSchemaBase;
|
||||
|
||||
/**
|
||||
* Blueprint schema handles the internal logic of blueprints.
|
||||
*
|
||||
* @author RocketTheme
|
||||
* @license MIT
|
||||
*/
|
||||
class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
{
|
||||
use Export;
|
||||
|
||||
protected $ignoreFormKeys = [
|
||||
'title' => true,
|
||||
'help' => true,
|
||||
'placeholder' => true,
|
||||
'placeholder_key' => true,
|
||||
'placeholder_value' => true,
|
||||
'fields' => true
|
||||
];
|
||||
|
||||
/**
|
||||
* Validate data against blueprints.
|
||||
*
|
||||
* @param array $data
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function validate(array $data)
|
||||
{
|
||||
try {
|
||||
$messages = $this->validateArray($data, $this->nested);
|
||||
|
||||
} catch (\RuntimeException $e) {
|
||||
throw (new ValidationException($e->getMessage(), $e->getCode(), $e))->setMessages();
|
||||
}
|
||||
|
||||
if (!empty($messages)) {
|
||||
throw (new ValidationException())->setMessages($messages);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter data by using blueprints.
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function filter(array $data)
|
||||
{
|
||||
return $this->filterArray($data, $this->nested);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @returns array
|
||||
* @throws \RuntimeException
|
||||
* @internal
|
||||
*/
|
||||
protected function validateArray(array $data, array $rules)
|
||||
{
|
||||
$messages = $this->checkRequired($data, $rules);
|
||||
|
||||
foreach ($data as $key => $field) {
|
||||
$val = isset($rules[$key]) ? $rules[$key] : (isset($rules['*']) ? $rules['*'] : null);
|
||||
$rule = is_string($val) ? $this->items[$val] : null;
|
||||
|
||||
if ($rule) {
|
||||
// Item has been defined in blueprints.
|
||||
$messages += Validation::validate($field, $rule);
|
||||
} elseif (is_array($field) && is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$messages += $this->validateArray($field, $val);
|
||||
} elseif (isset($rules['validation']) && $rules['validation'] == 'strict') {
|
||||
// Undefined/extra item.
|
||||
throw new \RuntimeException(sprintf('%s is not defined in blueprints', $key));
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $rules
|
||||
* @return array
|
||||
* @internal
|
||||
*/
|
||||
protected function filterArray(array $data, array $rules)
|
||||
{
|
||||
$results = array();
|
||||
foreach ($data as $key => $field) {
|
||||
$val = isset($rules[$key]) ? $rules[$key] : (isset($rules['*']) ? $rules['*'] : null);
|
||||
$rule = is_string($val) ? $this->items[$val] : null;
|
||||
|
||||
if ($rule) {
|
||||
// Item has been defined in blueprints.
|
||||
$field = Validation::filter($field, $rule);
|
||||
} elseif (is_array($field) && is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$field = $this->filterArray($field, $val);
|
||||
} elseif (isset($rules['validation']) && $rules['validation'] == 'strict') {
|
||||
$field = null;
|
||||
}
|
||||
|
||||
if (isset($field) && (!is_array($field) || !empty($field))) {
|
||||
$results[$key] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $fields
|
||||
* @return array
|
||||
*/
|
||||
protected function checkRequired(array $data, array $fields)
|
||||
{
|
||||
$messages = [];
|
||||
|
||||
foreach ($fields as $name => $field) {
|
||||
if (!is_string($field)) {
|
||||
continue;
|
||||
}
|
||||
$field = $this->items[$field];
|
||||
if (isset($field['validate']['required'])
|
||||
&& $field['validate']['required'] === true
|
||||
&& !isset($data[$name])) {
|
||||
$value = isset($field['label']) ? $field['label'] : $field['name'];
|
||||
$language = Grav::instance()['language'];
|
||||
$message = sprintf($language->translate('FORM.MISSING_REQUIRED_FIELD', null, true) . ' %s', $language->translate($value));
|
||||
$messages[$field['name']][] = $message;
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $field
|
||||
* @param string $property
|
||||
* @param array $call
|
||||
*/
|
||||
protected function dynamicConfig(array &$field, $property, array &$call)
|
||||
{
|
||||
$value = $call['params'];
|
||||
|
||||
$default = isset($field[$property]) ? $field[$property] : null;
|
||||
$config = Grav::instance()['config']->get($value, $default);
|
||||
|
||||
if (!is_null($config)) {
|
||||
$field[$property] = $config;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
namespace Grav\Common\Data;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\File\CompiledYamlFile;
|
||||
use Grav\Common\GravTrait;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
|
||||
/**
|
||||
@@ -12,14 +13,16 @@ use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
*/
|
||||
class Blueprints
|
||||
{
|
||||
use GravTrait;
|
||||
|
||||
protected $search;
|
||||
protected $types;
|
||||
protected $instances = [];
|
||||
protected $instances = array();
|
||||
|
||||
/**
|
||||
* @param string|array $search Search path.
|
||||
*/
|
||||
public function __construct($search = 'blueprints://')
|
||||
public function __construct($search)
|
||||
{
|
||||
$this->search = $search;
|
||||
}
|
||||
@@ -34,7 +37,73 @@ class Blueprints
|
||||
public function get($type)
|
||||
{
|
||||
if (!isset($this->instances[$type])) {
|
||||
$this->instances[$type] = $this->loadFile($type);
|
||||
$parents = [];
|
||||
if (is_string($this->search)) {
|
||||
$filename = $this->search . $type . YAML_EXT;
|
||||
|
||||
// Check if search is a stream and resolve the path.
|
||||
if (strpos($filename, '://')) {
|
||||
$grav = static::getGrav();
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $grav['locator'];
|
||||
$parents = $locator->findResources($filename);
|
||||
$filename = array_shift($parents);
|
||||
}
|
||||
} else {
|
||||
$filename = isset($this->search[$type]) ? $this->search[$type] : '';
|
||||
}
|
||||
|
||||
if ($filename && is_file($filename)) {
|
||||
$file = CompiledYamlFile::instance($filename);
|
||||
$blueprints = $file->content();
|
||||
} else {
|
||||
$blueprints = [];
|
||||
}
|
||||
|
||||
$blueprint = new Blueprint($type, $blueprints, $this);
|
||||
|
||||
if (isset($blueprints['@extends'])) {
|
||||
// Extend blueprint by other blueprints.
|
||||
$extends = (array) $blueprints['@extends'];
|
||||
|
||||
if (is_string(key($extends))) {
|
||||
$extends = [ $extends ];
|
||||
}
|
||||
|
||||
foreach ($extends as $extendConfig) {
|
||||
$extendType = !is_string($extendConfig) ? empty($extendConfig['type']) ? false : $extendConfig['type'] : $extendConfig;
|
||||
|
||||
if (!$extendType) {
|
||||
continue;
|
||||
} elseif ($extendType === '@parent') {
|
||||
$parentFile = array_shift($parents);
|
||||
if (!$parentFile || !is_file($parentFile)) {
|
||||
continue;
|
||||
}
|
||||
$blueprints = CompiledYamlFile::instance($parentFile)->content();
|
||||
$parent = new Blueprint($type.'-parent', $blueprints, $this);
|
||||
$blueprint->extend($parent);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_string($extendConfig) || empty($extendConfig['context'])) {
|
||||
$context = $this;
|
||||
} else {
|
||||
// Load blueprints from external context.
|
||||
$array = explode('://', $extendConfig['context'], 2);
|
||||
$scheme = array_shift($array);
|
||||
$path = array_shift($array);
|
||||
if ($path) {
|
||||
$scheme .= '://';
|
||||
$extendType = $path ? "{$path}/{$extendType}" : $extendType;
|
||||
}
|
||||
$context = new self($scheme);
|
||||
}
|
||||
$blueprint->extend($context->get($extendType));
|
||||
}
|
||||
}
|
||||
|
||||
$this->instances[$type] = $blueprint;
|
||||
}
|
||||
|
||||
return $this->instances[$type];
|
||||
@@ -50,15 +119,15 @@ class Blueprints
|
||||
if ($this->types === null) {
|
||||
$this->types = array();
|
||||
|
||||
$grav = Grav::instance();
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $grav['locator'];
|
||||
|
||||
// Get stream / directory iterator.
|
||||
if ($locator->isStream($this->search)) {
|
||||
$iterator = $locator->getIterator($this->search);
|
||||
// Check if search is a stream.
|
||||
if (strpos($this->search, '://')) {
|
||||
// Stream: use UniformResourceIterator.
|
||||
$grav = static::getGrav();
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = $grav['locator'];
|
||||
$iterator = $locator->getIterator($this->search, null);
|
||||
} else {
|
||||
// Not a stream: use DirectoryIterator.
|
||||
$iterator = new \DirectoryIterator($this->search);
|
||||
}
|
||||
|
||||
@@ -71,29 +140,6 @@ class Blueprints
|
||||
$this->types[$name] = ucfirst(strtr($name, '_', ' '));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->types;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load blueprint file.
|
||||
*
|
||||
* @param string $name Name of the blueprint.
|
||||
* @return Blueprint
|
||||
*/
|
||||
protected function loadFile($name)
|
||||
{
|
||||
$blueprint = new Blueprint($name);
|
||||
|
||||
if (is_array($this->search) || is_object($this->search)) {
|
||||
// Page types.
|
||||
$blueprint->setOverrides($this->search);
|
||||
$blueprint->setContext('blueprints://pages');
|
||||
} else {
|
||||
$blueprint->setContext($this->search);
|
||||
}
|
||||
|
||||
return $blueprint->load()->init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use RocketTheme\Toolbox\ArrayTraits\Countable;
|
||||
use RocketTheme\Toolbox\ArrayTraits\Export;
|
||||
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
|
||||
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
|
||||
use RocketTheme\Toolbox\Blueprints\Blueprints;
|
||||
use RocketTheme\Toolbox\File\File;
|
||||
use RocketTheme\Toolbox\File\FileInterface;
|
||||
|
||||
@@ -216,12 +217,12 @@ class Data implements DataInterface, \ArrayAccess, \Countable, ExportInterface
|
||||
/**
|
||||
* Return blueprints.
|
||||
*
|
||||
* @return Blueprint
|
||||
* @return Blueprints
|
||||
*/
|
||||
public function blueprints()
|
||||
{
|
||||
if (!$this->blueprints){
|
||||
$this->blueprints = new Blueprint;
|
||||
$this->blueprints = new Blueprints;
|
||||
} elseif (is_callable($this->blueprints)) {
|
||||
// Lazy load blueprints.
|
||||
$blueprints = $this->blueprints;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
namespace Grav\Common\Data;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\GravTrait;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Symfony\Component\Yaml\Parser;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* Data validation.
|
||||
@@ -14,70 +13,58 @@ use Symfony\Component\Yaml\Yaml;
|
||||
*/
|
||||
class Validation
|
||||
{
|
||||
use GravTrait;
|
||||
|
||||
/**
|
||||
* Validate value against a blueprint field definition.
|
||||
*
|
||||
* @param $value
|
||||
* @param mixed $value
|
||||
* @param array $field
|
||||
* @return array
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function validate($value, array $field)
|
||||
{
|
||||
$messages = [];
|
||||
|
||||
$validate = isset($field['validate']) ? (array) $field['validate'] : [];
|
||||
$validate = isset($field['validate']) ? (array) $field['validate'] : array();
|
||||
|
||||
// If value isn't required, we will stop validation if empty value is given.
|
||||
if (empty($validate['required']) && ($value === null || $value === '')) {
|
||||
return $messages;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($field['type'])) {
|
||||
$field['type'] = 'text';
|
||||
// special case for files, value is never empty and errors with code 4 instead
|
||||
if (empty($validate['required']) && $field['type'] == 'file' && (isset($value['error']) && ($value['error'] == UPLOAD_ERR_NO_FILE || in_array(UPLOAD_ERR_NO_FILE, $value['error'])))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special case for files, value is never empty and errors with code 4 instead.
|
||||
if (empty($validate['required']) && $field['type'] == 'file' && isset($value['error'])
|
||||
&& ($value['error'] == UPLOAD_ERR_NO_FILE || in_array(UPLOAD_ERR_NO_FILE, $value['error']))) {
|
||||
return $messages;
|
||||
}
|
||||
|
||||
// Get language class.
|
||||
$language = Grav::instance()['language'];
|
||||
// Get language class
|
||||
$language = self::getGrav()['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'])
|
||||
: $language->translate('FORM.INVALID_INPUT', null, true) . ' "' . $language->translate($name) . '"';
|
||||
$message = (string) isset($field['validate']['message']) ? $language->translate($field['validate']['message']) : $language->translate('FORM.INVALID_INPUT', null, true) . ' "' . $language->translate($name) . '"';
|
||||
|
||||
if (method_exists(__CLASS__, $method)) {
|
||||
$success = self::$method($value, $validate, $field);
|
||||
} else {
|
||||
$success = true;
|
||||
$success = self::typeText($value, $validate, $field);
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
$messages[$field['name']][] = $message;
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
|
||||
// Check individual rules.
|
||||
// Check individual rules
|
||||
foreach ($validate as $rule => $params) {
|
||||
$method = 'validate' . ucfirst(strtr($rule, '-', '_'));
|
||||
|
||||
$method = 'validate'.strtr($rule, '-', '_');
|
||||
if (method_exists(__CLASS__, $method)) {
|
||||
$success = self::$method($value, $params);
|
||||
|
||||
if (!$success) {
|
||||
$messages[$field['name']][] = $message;
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,28 +76,22 @@ class Validation
|
||||
*/
|
||||
public static function filter($value, array $field)
|
||||
{
|
||||
$validate = isset($field['validate']) ? (array) $field['validate'] : [];
|
||||
$validate = isset($field['validate']) ? (array) $field['validate'] : array();
|
||||
|
||||
// If value isn't required, we will return null if empty value is given.
|
||||
if (empty($validate['required']) && ($value === null || $value === '')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isset($field['type'])) {
|
||||
$field['type'] = 'text';
|
||||
}
|
||||
|
||||
// Special case for files, value is never empty and errors with code 4 instead.
|
||||
if (empty($validate['required']) && $field['type'] == 'file' && isset($value['error'])
|
||||
&& ($value['error'] == UPLOAD_ERR_NO_FILE || in_array(UPLOAD_ERR_NO_FILE, $value['error']))) {
|
||||
// special case for files, value is never empty and errors with code 4 instead
|
||||
if (empty($validate['required']) && $field['type'] == 'file' && (isset($value['error']) && ($value['error'] == UPLOAD_ERR_NO_FILE || in_array(UPLOAD_ERR_NO_FILE, $value['error'])))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If this is a YAML field, simply parse it and return the value.
|
||||
// if this is a YAML field, simply parse it and return the value
|
||||
if (isset($field['yaml']) && $field['yaml'] === true) {
|
||||
try {
|
||||
$yaml = new Parser();
|
||||
|
||||
return $yaml->parse($value);
|
||||
} catch (ParseException $e) {
|
||||
throw new \RuntimeException($e->getMessage());
|
||||
@@ -119,13 +100,14 @@ class Validation
|
||||
|
||||
// Validate type with fallback type text.
|
||||
$type = (string) isset($field['validate']['type']) ? $field['validate']['type'] : $field['type'];
|
||||
$method = 'filter' . ucfirst(strtr($type, '-', '_'));
|
||||
|
||||
if (!method_exists(__CLASS__, $method)) {
|
||||
$method = 'filterText';
|
||||
$method = 'filter'.strtr($type, '-', '_');
|
||||
if (method_exists(__CLASS__, $method)) {
|
||||
$value = self::$method($value, $validate, $field);
|
||||
} else {
|
||||
$value = self::filterText($value, $validate, $field);
|
||||
}
|
||||
|
||||
return self::$method($value, $validate, $field);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,6 +307,7 @@ class Validation
|
||||
* @param array $field Blueprint for the field.
|
||||
* @return bool True if validation succeeded.
|
||||
*/
|
||||
|
||||
public static function typeNumber($value, array $params, array $field)
|
||||
{
|
||||
if (!is_numeric($value)) {
|
||||
@@ -354,7 +337,7 @@ class Validation
|
||||
|
||||
protected static function filterDateTime($value, array $params, array $field)
|
||||
{
|
||||
$format = Grav::instance()['config']->get('system.pages.dateformat.default');
|
||||
$format = self::getGrav()['config']->get('system.pages.dateformat.default');
|
||||
if ($format) {
|
||||
$converted = new \DateTime($value);
|
||||
return $converted->format($format);
|
||||
@@ -568,10 +551,6 @@ class Validation
|
||||
$options = isset($field['options']) ? array_keys($field['options']) : array();
|
||||
$multi = isset($field['multiple']) ? $field['multiple'] : false;
|
||||
|
||||
if (count($values) == 1 && isset($values[0]) && $values[0] == '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($options) {
|
||||
$useKey = isset($field['use']) && $field['use'] == 'keys';
|
||||
foreach ($values as $key => $value) {
|
||||
@@ -616,25 +595,6 @@ class Validation
|
||||
return (array) $value;
|
||||
}
|
||||
|
||||
public static function typeYaml($value, $params)
|
||||
{
|
||||
try {
|
||||
Yaml::parse($value);
|
||||
return true;
|
||||
} catch (ParseException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function filterYaml($value, $params)
|
||||
{
|
||||
try {
|
||||
return (array) Yaml::parse($value);
|
||||
} catch (ParseException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom input: ignore (will not validate)
|
||||
*
|
||||
@@ -657,11 +617,11 @@ class Validation
|
||||
|
||||
public static function validateRequired($value, $params)
|
||||
{
|
||||
if (is_scalar($value)) {
|
||||
return (bool) $params !== true || $value !== '';
|
||||
} else {
|
||||
return (bool) $params !== true || !empty($value);
|
||||
if (is_string($value)) {
|
||||
$value = trim($value);
|
||||
}
|
||||
|
||||
return (bool) $params !== true || !empty($value);
|
||||
}
|
||||
|
||||
public static function validatePattern($value, $params)
|
||||
@@ -729,14 +689,13 @@ class Validation
|
||||
|
||||
public static function validateArray($value, $params)
|
||||
{
|
||||
return is_array($value)
|
||||
|| ($value instanceof \ArrayAccess
|
||||
return is_array($value) || ($value instanceof \ArrayAccess
|
||||
&& $value instanceof \Traversable
|
||||
&& $value instanceof \Countable);
|
||||
}
|
||||
|
||||
public static function validateJson($value, $params)
|
||||
{
|
||||
return (bool) (@json_decode($value));
|
||||
return (bool) (json_decode($value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
namespace Grav\Common\Data;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
||||
class ValidationException extends \RuntimeException
|
||||
{
|
||||
protected $messages = [];
|
||||
|
||||
public function setMessages(array $messages = []) {
|
||||
$this->messages = $messages;
|
||||
|
||||
$language = Grav::instance()['language'];
|
||||
$this->message = $language->translate('FORM.VALIDATION_FAIL', null, true) . ' ' . $this->message;
|
||||
|
||||
foreach ($messages as $variable => &$list) {
|
||||
$list = array_unique($list);
|
||||
foreach ($list as $message) {
|
||||
$this->message .= "<br/>$message";
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMessages()
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
<?php
|
||||
namespace Grav\Common;
|
||||
|
||||
use DebugBar\DataCollector\ConfigCollector;
|
||||
use DebugBar\JavascriptRenderer;
|
||||
use DebugBar\StandardDebugBar;
|
||||
use Grav\Common\Config\Config;
|
||||
|
||||
/**
|
||||
* Class Debugger
|
||||
@@ -12,79 +10,44 @@ use Grav\Common\Config\Config;
|
||||
*/
|
||||
class Debugger
|
||||
{
|
||||
/** @var Grav $grav */
|
||||
protected $grav;
|
||||
|
||||
/** @var Config $config */
|
||||
protected $config;
|
||||
|
||||
/** @var JavascriptRenderer $renderer */
|
||||
protected $renderer;
|
||||
|
||||
/** @var StandardDebugBar $debugbar */
|
||||
protected $debugbar;
|
||||
|
||||
protected $renderer;
|
||||
protected $enabled;
|
||||
|
||||
protected $timers = [];
|
||||
|
||||
/**
|
||||
* Debugger constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->debugbar = new StandardDebugBar();
|
||||
$this->debugbar['time']->addMeasure('Loading', $this->debugbar['time']->getRequestStartTime(), microtime(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the debugger
|
||||
*
|
||||
* @return $this
|
||||
* @throws \DebugBar\DebugBarException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->grav = Grav::instance();
|
||||
$this->config = $this->grav['config'];
|
||||
|
||||
if ($this->enabled()) {
|
||||
$this->debugbar->addCollector(new ConfigCollector((array)$this->config->get('system'), 'Config'));
|
||||
$this->debugbar->addCollector(new ConfigCollector((array)$this->config->get('plugins'), 'Plugins'));
|
||||
$this->debugbar->addCollector(new \DebugBar\DataCollector\ConfigCollector((array)$this->grav['config']->get('system')));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set/get the enabled state of the debugger
|
||||
*
|
||||
* @param bool $state If null, the method returns the enabled value. If set, the method sets the enabled state
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function enabled($state = null)
|
||||
{
|
||||
if (isset($state)) {
|
||||
$this->enabled = $state;
|
||||
} else {
|
||||
if (!isset($this->enabled)) {
|
||||
$this->enabled = $this->config->get('system.debugger.enabled');
|
||||
$this->enabled = $this->grav['config']->get('system.debugger.enabled');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the debugger assets to the Grav Assets
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addAssets()
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
/** @var Assets $assets */
|
||||
$assets = $this->grav['assets'];
|
||||
|
||||
// Add jquery library
|
||||
@@ -105,113 +68,58 @@ class Debugger
|
||||
$assets->addJs($js);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data collector
|
||||
*
|
||||
* @param $collector
|
||||
*
|
||||
* @return $this
|
||||
* @throws \DebugBar\DebugBarException
|
||||
*/
|
||||
public function addCollector($collector)
|
||||
{
|
||||
$this->debugbar->addCollector($collector);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a data collector
|
||||
*
|
||||
* @param $collector
|
||||
*
|
||||
* @return \DebugBar\DataCollector\DataCollectorInterface
|
||||
* @throws \DebugBar\DebugBarException
|
||||
*/
|
||||
public function getCollector($collector)
|
||||
{
|
||||
return $this->debugbar->getCollector($collector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the debug bar
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
echo $this->renderer->render();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the data through the HTTP headers
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sendDataInHeaders()
|
||||
{
|
||||
$this->debugbar->sendDataInHeaders();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a timer with an associated name and description
|
||||
*
|
||||
* @param $name
|
||||
* @param string|null $description
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function startTimer($name, $description = null)
|
||||
{
|
||||
if ($name[0] == '_' || $this->config->get('system.debugger.enabled')) {
|
||||
if ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled')) {
|
||||
$this->debugbar['time']->startMeasure($name, $description);
|
||||
$this->timers[] = $name;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the named timer
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function stopTimer($name)
|
||||
{
|
||||
if (in_array($name, $this->timers) && ($name[0] == '_' || $this->config->get('system.debugger.enabled'))) {
|
||||
if (in_array($name, $this->timers) && ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled'))) {
|
||||
$this->debugbar['time']->stopMeasure($name);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump variables into the Messages tab of the Debug Bar
|
||||
*
|
||||
* @param $message
|
||||
* @param string $label
|
||||
* @param bool $isString
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
||||
public function addMessage($message, $label = 'info', $isString = true)
|
||||
{
|
||||
if ($this->enabled()) {
|
||||
$this->debugbar['messages']->addMessage($message, $label, $isString);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,59 +2,51 @@
|
||||
namespace Grav\Common\Errors;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Whoops;
|
||||
use Whoops\Handler\CallbackHandler;
|
||||
use Whoops\Handler\HandlerInterface;
|
||||
use Whoops\Run;
|
||||
|
||||
/**
|
||||
* Class Debugger
|
||||
* @package Grav\Common
|
||||
*/
|
||||
class Errors
|
||||
class Errors extends Run
|
||||
{
|
||||
|
||||
public function pushHandler($handler, $key = null)
|
||||
{
|
||||
if (is_callable($handler)) {
|
||||
$handler = new CallbackHandler($handler);
|
||||
}
|
||||
|
||||
if (!$handler instanceof HandlerInterface) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Argument to " . __METHOD__ . " must be a callable, or instance of"
|
||||
. "Whoops\\Handler\\HandlerInterface"
|
||||
);
|
||||
}
|
||||
|
||||
// Store with key if provided
|
||||
if ($key) {
|
||||
$this->handlerStack[$key] = $handler;
|
||||
} else {
|
||||
$this->handlerStack[] = $handler;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function resetHandlers()
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
$config = $grav['config']->get('system.errors');
|
||||
$jsonRequest = $_SERVER && isset($_SERVER['HTTP_ACCEPT']) && $_SERVER['HTTP_ACCEPT'] == 'application/json';
|
||||
|
||||
// Setup Whoops-based error handler
|
||||
$whoops = new \Whoops\Run;
|
||||
|
||||
if (isset($config['display'])) {
|
||||
if ($config['display']) {
|
||||
$error_page = new Whoops\Handler\PrettyPageHandler;
|
||||
$error_page->setPageTitle('Crikey! There was an error...');
|
||||
$error_page->addResourcePath(GRAV_ROOT . '/system/assets');
|
||||
$error_page->addCustomCss('whoops.css');
|
||||
$whoops->pushHandler($error_page);
|
||||
} else {
|
||||
$whoops->pushHandler(new SimplePageHandler);
|
||||
}
|
||||
if (isset($config['display']) && !$config['display']) {
|
||||
unset($this->handlerStack['pretty']);
|
||||
$this->handlerStack = array('simple' => new SimplePageHandler()) + $this->handlerStack;
|
||||
}
|
||||
|
||||
if (method_exists('Whoops\Util\Misc', 'isAjaxRequest')) { //Whoops 2.0
|
||||
if (Whoops\Util\Misc::isAjaxRequest() || $jsonRequest) {
|
||||
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
|
||||
}
|
||||
} elseif (function_exists('Whoops\isAjaxRequest')) { //Whoops 2.0.0-alpha
|
||||
if (Whoops\isAjaxRequest() || $jsonRequest) {
|
||||
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
|
||||
}
|
||||
} else { //Whoops 1.x
|
||||
$json_page = new Whoops\Handler\JsonResponseHandler;
|
||||
$json_page->onlyForAjaxRequests(true);
|
||||
if (isset($config['log']) && !$config['log']) {
|
||||
unset($this->handlerStack['log']);
|
||||
}
|
||||
|
||||
if (isset($config['log']) && $config['log']) {
|
||||
$logger = $grav['log'];
|
||||
$whoops->pushHandler(function($exception, $inspector, $run) use ($logger) {
|
||||
try {
|
||||
$logger->addCritical($exception->getMessage() . ' - Trace: ' . $exception->getTraceAsString());
|
||||
} catch (\Exception $e) {
|
||||
echo $e;
|
||||
}
|
||||
}, 'log');
|
||||
}
|
||||
|
||||
$whoops->register();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,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();
|
||||
|
||||
if (!$modified) {
|
||||
@@ -67,11 +66,6 @@ trait CompiledFile
|
||||
if ($file->locked() !== false) {
|
||||
$file->save($cache);
|
||||
$file->unlock();
|
||||
|
||||
// Compile cached file into bytecode cache
|
||||
if (function_exists('opcache_invalidate')) {
|
||||
opcache_invalidate($file->filename(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
$file->free();
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<?php
|
||||
namespace Grav\Common\Filesystem;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
|
||||
/**
|
||||
* Folder helper class.
|
||||
*
|
||||
@@ -22,14 +19,7 @@ abstract class Folder
|
||||
{
|
||||
$last_modified = 0;
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = Grav::instance()['locator'];
|
||||
$flags = \RecursiveDirectoryIterator::SKIP_DOTS;
|
||||
if ($locator->isStream($path)) {
|
||||
$directory = $locator->getRecursiveIterator($path, $flags);
|
||||
} else {
|
||||
$directory = new \RecursiveDirectoryIterator($path, $flags);
|
||||
}
|
||||
$directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
$filter = new RecursiveFolderFilterIterator($directory);
|
||||
$iterator = new \RecursiveIteratorIterator($filter, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
@@ -56,14 +46,7 @@ abstract class Folder
|
||||
{
|
||||
$last_modified = 0;
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = Grav::instance()['locator'];
|
||||
$flags = \RecursiveDirectoryIterator::SKIP_DOTS;
|
||||
if ($locator->isStream($path)) {
|
||||
$directory = $locator->getRecursiveIterator($path, $flags);
|
||||
} else {
|
||||
$directory = new \RecursiveDirectoryIterator($path, $flags);
|
||||
}
|
||||
$directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
$recursive = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
$iterator = new \RegexIterator($recursive, '/^.+\.'.$extensions.'$/i');
|
||||
|
||||
@@ -81,9 +64,8 @@ abstract class Folder
|
||||
/**
|
||||
* Get relative path between target and base path. If path isn't relative, return full path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param mixed|string $base
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $base
|
||||
* @return string
|
||||
*/
|
||||
public static function getRelativePath($path, $base = GRAV_ROOT)
|
||||
@@ -159,10 +141,10 @@ abstract class Folder
|
||||
* @return array
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public static function all($path, array $params = [])
|
||||
public static function all($path, array $params = array())
|
||||
{
|
||||
if ($path === false) {
|
||||
throw new \RuntimeException("Path doesn't exist.");
|
||||
throw new \RuntimeException("Path to {$path} doesn't exist.");
|
||||
}
|
||||
|
||||
$compare = isset($params['compare']) ? 'get' . $params['compare'] : null;
|
||||
@@ -175,26 +157,16 @@ abstract class Folder
|
||||
$folders = isset($params['folders']) ? $params['folders'] : true;
|
||||
$files = isset($params['files']) ? $params['files'] : true;
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = Grav::instance()['locator'];
|
||||
if ($recursive) {
|
||||
$flags = \RecursiveDirectoryIterator::SKIP_DOTS + \FilesystemIterator::UNIX_PATHS + \FilesystemIterator::CURRENT_AS_SELF;
|
||||
if ($locator->isStream($path)) {
|
||||
$directory = $locator->getRecursiveIterator($path, $flags);
|
||||
} else {
|
||||
$directory = new \RecursiveDirectoryIterator($path, $flags);
|
||||
}
|
||||
$directory = new \RecursiveDirectoryIterator($path,
|
||||
\RecursiveDirectoryIterator::SKIP_DOTS + \FilesystemIterator::UNIX_PATHS + \FilesystemIterator::CURRENT_AS_SELF);
|
||||
$iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
$iterator->setMaxDepth(max($levels, -1));
|
||||
} else {
|
||||
if ($locator->isStream($path)) {
|
||||
$iterator = $locator->getIterator($path);
|
||||
} else {
|
||||
$iterator = new \FilesystemIterator($path);
|
||||
}
|
||||
$iterator = new \FilesystemIterator($path);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
$results = array();
|
||||
|
||||
/** @var \RecursiveDirectoryIterator $file */
|
||||
foreach ($iterator as $file) {
|
||||
|
||||
@@ -1,36 +1,25 @@
|
||||
<?php
|
||||
namespace Grav\Common\Filesystem;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\GravTrait;
|
||||
|
||||
/**
|
||||
* Class RecursiveFolderFilterIterator
|
||||
* @package Grav\Common\Filesystem
|
||||
*/
|
||||
class RecursiveFolderFilterIterator extends \RecursiveFilterIterator
|
||||
{
|
||||
use GravTrait;
|
||||
|
||||
protected static $folder_ignores;
|
||||
|
||||
/**
|
||||
* Create a RecursiveFilterIterator from a RecursiveIterator
|
||||
*
|
||||
* @param RecursiveIterator $iterator
|
||||
*/
|
||||
public function __construct(\RecursiveIterator $iterator)
|
||||
{
|
||||
parent::__construct($iterator);
|
||||
if (empty($this::$folder_ignores)) {
|
||||
$this::$folder_ignores = Grav::instance()['config']->get('system.pages.ignore_folders');
|
||||
$this::$folder_ignores = self::getGrav()['config']->get('system.pages.ignore_folders');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the current element of the iterator is acceptable
|
||||
*
|
||||
* @return bool true if the current element is acceptable, otherwise false.
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
|
||||
/** @var $current \SplFileInfo */
|
||||
$current = $this->current();
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<?php
|
||||
namespace Grav\Common\GPM;
|
||||
|
||||
use Grav\Common\GravTrait;
|
||||
use Grav\Common\Iterator;
|
||||
|
||||
abstract class AbstractCollection extends Iterator
|
||||
{
|
||||
abstract class AbstractCollection extends Iterator {
|
||||
|
||||
use GravTrait;
|
||||
|
||||
public function toJson()
|
||||
{
|
||||
$items = [];
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<?php
|
||||
namespace Grav\Common\GPM\Common;
|
||||
|
||||
use Grav\Common\GravTrait;
|
||||
use Grav\Common\Iterator;
|
||||
|
||||
abstract class AbstractPackageCollection extends Iterator
|
||||
{
|
||||
abstract class AbstractPackageCollection extends Iterator {
|
||||
|
||||
use GravTrait;
|
||||
|
||||
protected $type;
|
||||
|
||||
public function toJson()
|
||||
|
||||
@@ -3,17 +3,6 @@ namespace Grav\Common\GPM\Common;
|
||||
|
||||
use Grav\Common\Data\Data;
|
||||
|
||||
/**
|
||||
* @property string name
|
||||
* @property string version
|
||||
* @property string available
|
||||
* @property string package_type
|
||||
* @property string description_plain
|
||||
* @property string slug
|
||||
* @property array author
|
||||
* @property mixed changelog
|
||||
*/
|
||||
|
||||
class Package {
|
||||
|
||||
protected $data;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
namespace Grav\Common\GPM;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Inflector;
|
||||
use Grav\Common\Iterator;
|
||||
use Grav\Common\Utils;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class GPM extends Iterator
|
||||
{
|
||||
@@ -22,7 +20,7 @@ class GPM extends Iterator
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var Remote\GravCore
|
||||
* @var Remote\Grav
|
||||
*/
|
||||
public $grav;
|
||||
|
||||
@@ -44,7 +42,7 @@ class GPM extends Iterator
|
||||
$this->installed = new Local\Packages();
|
||||
try {
|
||||
$this->repository = new Remote\Packages($refresh, $callback);
|
||||
$this->grav = new Remote\GravCore($refresh, $callback);
|
||||
$this->grav = new Remote\Grav($refresh, $callback);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
@@ -69,23 +67,6 @@ class GPM extends Iterator
|
||||
return count($installed['plugins']) + count($installed['themes']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance of a specific Package
|
||||
*
|
||||
* @param string $slug The slug of the Package
|
||||
* @return Local\Package The instance of the Package
|
||||
*/
|
||||
public function getInstalledPackage($slug)
|
||||
{
|
||||
if (isset($this->installed['plugins'][$slug])) {
|
||||
return $this->installed['plugins'][$slug];
|
||||
}
|
||||
|
||||
if (isset($this->installed['themes'][$slug])) {
|
||||
return $this->installed['themes'][$slug];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance of a specific Plugin
|
||||
* @param string $slug The slug of the Plugin
|
||||
@@ -115,11 +96,6 @@ class GPM extends Iterator
|
||||
return isset($this->installed['plugins'][$slug]);
|
||||
}
|
||||
|
||||
public function isPluginInstalledAsSymlink($slug)
|
||||
{
|
||||
return $this->installed['plugins'][$slug]->symlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance of a specific Theme
|
||||
* @param string $slug The slug of the Theme
|
||||
@@ -199,7 +175,7 @@ class GPM extends Iterator
|
||||
}
|
||||
|
||||
foreach ($this->installed['plugins'] as $slug => $plugin) {
|
||||
if (!isset($repository[$slug]) || $plugin->symlink || !$plugin->version || $plugin->gpm === false) {
|
||||
if (!isset($repository[$slug]) || $plugin->symlink) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -209,8 +185,6 @@ class GPM extends Iterator
|
||||
if (version_compare($local_version, $remote_version) < 0) {
|
||||
$repository[$slug]->available = $remote_version;
|
||||
$repository[$slug]->version = $local_version;
|
||||
$repository[$slug]->name = $repository[$slug]->name;
|
||||
$repository[$slug]->type = $repository[$slug]->release_type;
|
||||
$items[$slug] = $repository[$slug];
|
||||
}
|
||||
}
|
||||
@@ -220,29 +194,6 @@ class GPM extends Iterator
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest release of a package from the GPM
|
||||
*
|
||||
* @param $package_name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getLatestVersionOfPackage($package_name)
|
||||
{
|
||||
$repository = $this->repository['plugins'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->available ?: $repository[$package_name]->version;
|
||||
}
|
||||
|
||||
//Not a plugin, it's a theme?
|
||||
$repository = $this->repository['themes'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->available ?: $repository[$package_name]->version;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Plugin or Theme is updatable
|
||||
* @param string $slug The slug of the package
|
||||
@@ -279,7 +230,7 @@ class GPM extends Iterator
|
||||
}
|
||||
|
||||
foreach ($this->installed['themes'] as $slug => $plugin) {
|
||||
if (!isset($repository[$slug]) || $plugin->symlink || !$plugin->version || $plugin->gpm === false) {
|
||||
if (!isset($repository[$slug]) || $plugin->symlink) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -289,7 +240,6 @@ class GPM extends Iterator
|
||||
if (version_compare($local_version, $remote_version) < 0) {
|
||||
$repository[$slug]->available = $remote_version;
|
||||
$repository[$slug]->version = $local_version;
|
||||
$repository[$slug]->type = $repository[$slug]->release_type;
|
||||
$items[$slug] = $repository[$slug];
|
||||
}
|
||||
}
|
||||
@@ -309,56 +259,6 @@ class GPM extends Iterator
|
||||
return array_key_exists($theme, (array) $this->getUpdatableThemes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the release type of a package (stable / testing)
|
||||
*
|
||||
* @param $package_name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getReleaseType($package_name)
|
||||
{
|
||||
$repository = $this->repository['plugins'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->release_type;
|
||||
}
|
||||
|
||||
//Not a plugin, it's a theme?
|
||||
$repository = $this->repository['themes'];
|
||||
if (isset($repository[$package_name])) {
|
||||
return $repository[$package_name]->release_type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the package latest release is stable
|
||||
*
|
||||
* @param $package_name
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isStableRelease($package_name)
|
||||
{
|
||||
return $this->getReleaseType($package_name) === 'stable';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the package latest release is testing
|
||||
*
|
||||
* @param $package_name
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isTestingRelease($package_name)
|
||||
{
|
||||
$hasTesting = isset($this->getInstalledPackage($package_name)->testing);
|
||||
$testing = $hasTesting ? $this->getInstalledPackage($package_name)->testing : false;
|
||||
|
||||
return $this->getReleaseType($package_name) === 'testing' || $testing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Plugin from the repository
|
||||
* @param string $slug The slug of the Plugin
|
||||
@@ -415,35 +315,21 @@ class GPM extends Iterator
|
||||
public function findPackage($search)
|
||||
{
|
||||
$search = strtolower($search);
|
||||
|
||||
$found = $this->getRepositoryTheme($search);
|
||||
if ($found) {
|
||||
if ($found = $this->getRepositoryTheme($search)) {
|
||||
return $found;
|
||||
}
|
||||
|
||||
$found = $this->getRepositoryPlugin($search);
|
||||
if ($found) {
|
||||
if ($found = $this->getRepositoryPlugin($search)) {
|
||||
return $found;
|
||||
}
|
||||
|
||||
$themes = $this->getRepositoryThemes();
|
||||
$plugins = $this->getRepositoryPlugins();
|
||||
|
||||
if (!$themes && !$plugins) {
|
||||
if (!is_writable(ROOT_DIR . '/cache/gpm')) {
|
||||
throw new \RuntimeException("The cache/gpm folder is not writable. Please check the folder permissions.");
|
||||
}
|
||||
|
||||
throw new \RuntimeException("GPM not reachable. Please check your internet connection or check the Grav site is reachable");
|
||||
}
|
||||
|
||||
if ($themes) foreach ($themes as $slug => $theme) {
|
||||
foreach ($this->getRepositoryThemes() as $slug => $theme) {
|
||||
if ($search == $slug || $search == $theme->name) {
|
||||
return $theme;
|
||||
}
|
||||
}
|
||||
|
||||
if ($plugins) foreach ($plugins as $slug => $plugin) {
|
||||
foreach ($this->getRepositoryPlugins() as $slug => $plugin) {
|
||||
if ($search == $slug || $search == $plugin->name) {
|
||||
return $plugin;
|
||||
}
|
||||
@@ -452,6 +338,11 @@ class GPM extends Iterator
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of Plugins and Themes available in the repository
|
||||
* @return array Array of available Plugins and Themes
|
||||
* Format: ['plugins' => array, 'themes' => array]
|
||||
*/
|
||||
/**
|
||||
* Searches for a list of Packages in the repository
|
||||
* @param array $searches An array of either slugs or names
|
||||
@@ -473,8 +364,7 @@ class GPM extends Iterator
|
||||
$search = $key;
|
||||
}
|
||||
|
||||
$found = $this->findPackage($search);
|
||||
if ($found) {
|
||||
if ($found = $this->findPackage($search)) {
|
||||
// set override repository if provided
|
||||
if ($repository) {
|
||||
$found->override_repository = $repository;
|
||||
@@ -505,415 +395,4 @@ class GPM extends Iterator
|
||||
|
||||
return $packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of packages that have the passed one as dependency
|
||||
*
|
||||
* @param string $slug The slug name of the package
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPackagesThatDependOnPackage($slug)
|
||||
{
|
||||
$plugins = $this->getInstalledPlugins();
|
||||
$themes = $this->getInstalledThemes();
|
||||
$packages = array_merge($plugins->toArray(), $themes->toArray());
|
||||
|
||||
$dependent_packages = [];
|
||||
|
||||
foreach($packages as $package_name => $package) {
|
||||
if (isset($package['dependencies'])) {
|
||||
foreach($package['dependencies'] as $dependency) {
|
||||
if (is_array($dependency)) {
|
||||
$dependency = array_keys($dependency)[0];
|
||||
}
|
||||
|
||||
if ($dependency == $slug) {
|
||||
$dependent_packages[] = $package_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dependent_packages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the required version of a dependency of a package
|
||||
*
|
||||
* @param $package_slug
|
||||
* @param $dependency_slug
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getVersionOfDependencyRequiredByPackage($package_slug, $dependency_slug)
|
||||
{
|
||||
$dependencies = $this->getInstalledPackage($package_slug)->dependencies;
|
||||
foreach($dependencies as $dependency) {
|
||||
if (isset($dependency[$dependency_slug])) {
|
||||
return $dependency[$dependency_slug];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the package identified by $slug can be updated to the version passed as argument.
|
||||
* Thrown an exception if it cannot be updated because another package installed requires it to be at an older version.
|
||||
*
|
||||
* @param string $slug
|
||||
* @param string $version_with_operator
|
||||
* @param array $ignore_packages_list
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function checkNoOtherPackageNeedsThisDependencyInALowerVersion($slug, $version_with_operator, $ignore_packages_list) {
|
||||
|
||||
// check if any of the currently installed package need this in a lower version than the one we need. In case, abort and tell which package
|
||||
$dependent_packages = $this->getPackagesThatDependOnPackage($slug);
|
||||
$version = $this->calculateVersionNumberFromDependencyVersion($version_with_operator);
|
||||
|
||||
if (count($dependent_packages)) {
|
||||
foreach($dependent_packages as $dependent_package) {
|
||||
$other_dependency_version_with_operator = $this->getVersionOfDependencyRequiredByPackage($dependent_package, $slug);
|
||||
$other_dependency_version= $this->calculateVersionNumberFromDependencyVersion($other_dependency_version_with_operator);
|
||||
|
||||
// check version is compatible with the one needed by the current package
|
||||
if ($this->versionFormatIsNextSignificantRelease($other_dependency_version_with_operator)) {
|
||||
$compatible = $this->checkNextSignificantReleasesAreCompatible($version,
|
||||
$other_dependency_version);
|
||||
if (!$compatible) {
|
||||
if (!in_array($dependent_package, $ignore_packages_list)) {
|
||||
throw new \Exception("Package <cyan>$slug</cyan> is required in an older version by package <cyan>$dependent_package</cyan>. This package needs a newer version, and because of this it cannot be installed. The <cyan>$dependent_package</cyan> package must be updated to use a newer release of <cyan>$slug</cyan>.",
|
||||
2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the passed packages list can be updated
|
||||
*
|
||||
* @param $packages_names_list
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function checkPackagesCanBeInstalled($packages_names_list)
|
||||
{
|
||||
foreach ($packages_names_list as $package_name) {
|
||||
$this->checkNoOtherPackageNeedsThisDependencyInALowerVersion($package_name, $this->getLatestVersionOfPackage($package_name), $packages_names_list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the dependencies, check the installed packages and return an array with
|
||||
* the list of packages with associated an information on what to do: install, update or ignore.
|
||||
*
|
||||
* `ignore` means the package is already installed and can be safely left as-is.
|
||||
* `install` means the package is not installed and must be installed.
|
||||
* `update` means the package is already installed and must be updated as a dependency needs a higher version.
|
||||
*
|
||||
* @param array $packages
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getDependencies($packages) {
|
||||
$dependencies = $this->calculateMergedDependenciesOfPackages($packages);
|
||||
foreach ($dependencies as $dependency_slug => $dependencyVersionWithOperator) {
|
||||
if (in_array($dependency_slug, $packages)) {
|
||||
unset($dependencies[$dependency_slug]);
|
||||
continue;
|
||||
}
|
||||
|
||||
//First, check for Grav dependency. If a dependency requires Grav > the current version, abort and tell.
|
||||
if ($dependency_slug == 'grav') {
|
||||
if (version_compare($this->calculateVersionNumberFromDependencyVersion($dependencyVersionWithOperator), GRAV_VERSION) === 1) {
|
||||
//Needs a Grav update first
|
||||
throw new \Exception("<red>One of the packages require Grav " . $dependencies['grav'] . ". Please update Grav to the latest release.");
|
||||
} else {
|
||||
unset($dependencies[$dependency_slug]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isPluginInstalled($dependency_slug)) {
|
||||
if ($this->isPluginInstalledAsSymlink($dependency_slug)) {
|
||||
unset($dependencies[$dependency_slug]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$dependencyVersion = $this->calculateVersionNumberFromDependencyVersion($dependencyVersionWithOperator);
|
||||
|
||||
// get currently installed version
|
||||
$locator = Grav::instance()['locator'];
|
||||
$blueprints_path = $locator->findResource('plugins://' . $dependency_slug . DS . 'blueprints.yaml');
|
||||
$package_yaml = Yaml::parse(file_get_contents($blueprints_path));
|
||||
$currentlyInstalledVersion = $package_yaml['version'];
|
||||
|
||||
// if requirement is next significant release, check is compatible with currently installed version, might not be
|
||||
if ($this->versionFormatIsNextSignificantRelease($dependencyVersionWithOperator)) {
|
||||
if ($this->firstVersionIsLower($dependencyVersion, $currentlyInstalledVersion)) {
|
||||
$compatible = $this->checkNextSignificantReleasesAreCompatible($dependencyVersion,
|
||||
$currentlyInstalledVersion);
|
||||
|
||||
if (!$compatible) {
|
||||
throw new \Exception('Dependency <cyan>' . $dependency_slug . '</cyan> is required in an older version than the one installed. This package must be updated. Please get in touch with its developer.',
|
||||
2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if I already have the latest release, remove the dependency
|
||||
$latestRelease = $this->getLatestVersionOfPackage($dependency_slug);
|
||||
|
||||
if ($this->firstVersionIsLower($latestRelease, $dependencyVersion)) {
|
||||
//throw an exception if a required version cannot be found in the GPM yet
|
||||
throw new \Exception('Dependency <cyan>' . $package_yaml['name'] . '</cyan> is required in version <cyan>' . $dependencyVersion . '</cyan> which is higher than the latest release, <cyan>' . $latestRelease . '</cyan>. Try running `bin/gpm -f index` to force a refresh of the GPM cache', 1);
|
||||
}
|
||||
|
||||
if ($this->firstVersionIsLower($currentlyInstalledVersion, $dependencyVersion)) {
|
||||
$dependencies[$dependency_slug] = 'update';
|
||||
} else {
|
||||
if ($currentlyInstalledVersion == $latestRelease) {
|
||||
unset($dependencies[$dependency_slug]);
|
||||
} else {
|
||||
// an update is not strictly required mark as 'ignore'
|
||||
$dependencies[$dependency_slug] = 'ignore';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$dependencyVersion = $this->calculateVersionNumberFromDependencyVersion($dependencyVersionWithOperator);
|
||||
|
||||
// if requirement is next significant release, check is compatible with latest available version, might not be
|
||||
if ($this->versionFormatIsNextSignificantRelease($dependencyVersionWithOperator)) {
|
||||
$latestVersionOfPackage = $this->getLatestVersionOfPackage($dependency_slug);
|
||||
if ($this->firstVersionIsLower($dependencyVersion, $latestVersionOfPackage)) {
|
||||
$compatible = $this->checkNextSignificantReleasesAreCompatible($dependencyVersion,
|
||||
$latestVersionOfPackage);
|
||||
|
||||
if (!$compatible) {
|
||||
throw new \Exception('Dependency <cyan>' . $dependency_slug . '</cyan> is required in an older version than the latest release available, and it cannot be installed. This package must be updated. Please get in touch with its developer.',
|
||||
2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dependencies[$dependency_slug] = 'install';
|
||||
}
|
||||
}
|
||||
|
||||
$dependencies_slugs = array_keys($dependencies);
|
||||
$this->checkNoOtherPackageNeedsTheseDependenciesInALowerVersion(array_merge($packages, $dependencies_slugs));
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
public function checkNoOtherPackageNeedsTheseDependenciesInALowerVersion($dependencies_slugs)
|
||||
{
|
||||
foreach ($dependencies_slugs as $dependency_slug) {
|
||||
$this->checkNoOtherPackageNeedsThisDependencyInALowerVersion($dependency_slug, $this->getLatestVersionOfPackage($dependency_slug), $dependencies_slugs);
|
||||
}
|
||||
}
|
||||
|
||||
private function firstVersionIsLower($firstVersion, $secondVersion) {
|
||||
return version_compare($firstVersion, $secondVersion) == -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and merges the dependencies of a package
|
||||
*
|
||||
* @param string $packageName The package information
|
||||
*
|
||||
* @param array $dependencies The dependencies array
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function calculateMergedDependenciesOfPackage($packageName, $dependencies)
|
||||
{
|
||||
$packageData = $this->findPackage($packageName);
|
||||
|
||||
//Check for dependencies
|
||||
if (isset($packageData->dependencies)) {
|
||||
foreach ($packageData->dependencies as $dependency) {
|
||||
$current_package_name = $dependency['name'];
|
||||
if (isset($dependency['version'])) {
|
||||
$current_package_version_information = $dependency['version'];
|
||||
}
|
||||
|
||||
if (!isset($dependencies[$current_package_name])) {
|
||||
// Dependency added for the first time
|
||||
|
||||
if (!isset($current_package_version_information)) {
|
||||
$dependencies[$current_package_name] = '*';
|
||||
} else {
|
||||
$dependencies[$current_package_name] = $current_package_version_information;
|
||||
}
|
||||
|
||||
//Factor in the package dependencies too
|
||||
$dependencies = $this->calculateMergedDependenciesOfPackage($current_package_name, $dependencies);
|
||||
}
|
||||
else {
|
||||
// Dependency already added by another package
|
||||
//if this package requires a version higher than the currently stored one, store this requirement instead
|
||||
if (isset($current_package_version_information) && $current_package_version_information !== '*') {
|
||||
|
||||
$currently_stored_version_information = $dependencies[$current_package_name];
|
||||
$currently_stored_version_number = $this->calculateVersionNumberFromDependencyVersion($currently_stored_version_information);
|
||||
|
||||
$currently_stored_version_is_in_next_significant_release_format = false;
|
||||
if ($this->versionFormatIsNextSignificantRelease($currently_stored_version_information)) {
|
||||
$currently_stored_version_is_in_next_significant_release_format = true;
|
||||
}
|
||||
|
||||
if (!$currently_stored_version_number) {
|
||||
$currently_stored_version_number = '*';
|
||||
}
|
||||
|
||||
$current_package_version_number = $this->calculateVersionNumberFromDependencyVersion($current_package_version_information);
|
||||
if (!$current_package_version_number) {
|
||||
throw new \Exception('Bad format for version of dependency ' . $current_package_name . ' for package ' . $packageName, 1);
|
||||
}
|
||||
|
||||
$current_package_version_is_in_next_significant_release_format = false;
|
||||
if ($this->versionFormatIsNextSignificantRelease($current_package_version_information)) {
|
||||
$current_package_version_is_in_next_significant_release_format = true;
|
||||
}
|
||||
|
||||
//If I had stored '*', change right away with the more specific version required
|
||||
if ($currently_stored_version_number === '*') {
|
||||
$dependencies[$current_package_name] = $current_package_version_information;
|
||||
} else {
|
||||
if (!$currently_stored_version_is_in_next_significant_release_format && !$current_package_version_is_in_next_significant_release_format) {
|
||||
//Comparing versions equals or higher, a simple version_compare is enough
|
||||
if (version_compare($currently_stored_version_number, $current_package_version_number) == -1) { //Current package version is higher
|
||||
$dependencies[$current_package_name] = $current_package_version_information;
|
||||
}
|
||||
} else {
|
||||
$compatible = $this->checkNextSignificantReleasesAreCompatible($currently_stored_version_number, $current_package_version_number);
|
||||
if (!$compatible) {
|
||||
throw new \Exception('Dependency ' . $current_package_name . ' is required in two incompatible versions', 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and merges the dependencies of the passed packages
|
||||
*
|
||||
* @param array $packages
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function calculateMergedDependenciesOfPackages($packages)
|
||||
{
|
||||
$dependencies = [];
|
||||
|
||||
foreach ($packages as $package) {
|
||||
$dependencies = $this->calculateMergedDependenciesOfPackage($package, $dependencies);
|
||||
}
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual version from a dependency version string.
|
||||
* Examples:
|
||||
* $versionInformation == '~2.0' => returns '2.0'
|
||||
* $versionInformation == '>=2.0.2' => returns '2.0.2'
|
||||
* $versionInformation == '2.0.2' => returns '2.0.2'
|
||||
* $versionInformation == '*' => returns null
|
||||
* $versionInformation == '' => returns null
|
||||
*
|
||||
* @param string $version
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function calculateVersionNumberFromDependencyVersion($version)
|
||||
{
|
||||
if ($version == '*') {
|
||||
return null;
|
||||
} elseif ($version == '') {
|
||||
return null;
|
||||
} elseif ($this->versionFormatIsNextSignificantRelease($version)) {
|
||||
return substr($version, 1);
|
||||
} elseif ($this->versionFormatIsEqualOrHigher($version)) {
|
||||
return substr($version, 2);
|
||||
} else {
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed version information contains next significant release (tilde) operator
|
||||
*
|
||||
* Example: returns true for $version: '~2.0'
|
||||
*
|
||||
* @param $version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function versionFormatIsNextSignificantRelease($version) {
|
||||
return substr($version, 0, 1) == '~';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed version information contains equal or higher operator
|
||||
*
|
||||
* Example: returns true for $version: '>=2.0'
|
||||
*
|
||||
* @param $version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function versionFormatIsEqualOrHigher($version) {
|
||||
return substr($version, 0, 2) == '>=';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if two releases are compatible by next significant release
|
||||
*
|
||||
* ~1.2 is equivalent to >=1.2 <2.0.0
|
||||
* ~1.2.3 is equivalent to >=1.2.3 <1.3.0
|
||||
*
|
||||
* In short, allows the last digit specified to go up
|
||||
*
|
||||
* @param string $version1 the version string (e.g. '2.0.0' or '1.0')
|
||||
* @param string $version2 the version string (e.g. '2.0.0' or '1.0')
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkNextSignificantReleasesAreCompatible($version1, $version2)
|
||||
{
|
||||
$version1array = explode('.', $version1);
|
||||
$version2array = explode('.', $version2);
|
||||
|
||||
if (count($version1array) > count($version2array)) {
|
||||
list($version1array, $version2array) = [$version2array, $version1array];
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
while ($i < count($version1array) - 1) {
|
||||
if ($version1array[$i] != $version2array[$i]) {
|
||||
return false;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
namespace Grav\Common\GPM;
|
||||
|
||||
use Grav\Common\Filesystem\Folder;
|
||||
use Grav\Common\Grav;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class Installer
|
||||
{
|
||||
@@ -30,15 +30,11 @@ class Installer
|
||||
protected static $target;
|
||||
|
||||
/**
|
||||
* @var integer Error Code
|
||||
* Error Code
|
||||
* @var integer
|
||||
*/
|
||||
protected static $error = 0;
|
||||
|
||||
/**
|
||||
* @var string Post install message
|
||||
*/
|
||||
protected static $message = '';
|
||||
|
||||
/**
|
||||
* Default options for the install
|
||||
* @var array
|
||||
@@ -47,7 +43,7 @@ class Installer
|
||||
'overwrite' => true,
|
||||
'ignore_symlinks' => true,
|
||||
'sophisticated' => false,
|
||||
'theme' => false,
|
||||
'theme' => false,
|
||||
'install_path' => '',
|
||||
'exclude_checks' => [self::EXISTS, self::NOT_FOUND, self::IS_LINK]
|
||||
];
|
||||
@@ -67,22 +63,21 @@ class Installer
|
||||
$options = array_merge(self::$options, $options);
|
||||
$install_path = rtrim($destination . DS . ltrim($options['install_path'], DS), DS);
|
||||
|
||||
if (!self::isGravInstance($destination) || !self::isValidDestination($install_path,
|
||||
$options['exclude_checks'])
|
||||
) {
|
||||
if (!self::isGravInstance($destination) || !self::isValidDestination($install_path, $options['exclude_checks'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self::lastErrorCode() == self::IS_LINK && $options['ignore_symlinks'] ||
|
||||
self::lastErrorCode() == self::EXISTS && !$options['overwrite']
|
||||
) {
|
||||
self::lastErrorCode() == self::EXISTS && !$options['overwrite']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pre install checks
|
||||
static::flightProcessing('pre_install', $install_path);
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
$archive = $zip->open($package);
|
||||
$cache_dir = Grav::instance()['locator']->findResource('cache://', true);
|
||||
$tmp = $cache_dir . DS . 'tmp/Grav-' . uniqid();
|
||||
$tmp = CACHE_DIR . 'tmp/Grav-' . uniqid();
|
||||
|
||||
if ($archive !== true) {
|
||||
self::$error = self::ZIP_OPEN_ERROR;
|
||||
@@ -96,35 +91,13 @@ class Installer
|
||||
|
||||
if (!$unzip) {
|
||||
self::$error = self::ZIP_EXTRACT_ERROR;
|
||||
|
||||
$zip->close();
|
||||
Folder::delete($tmp);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$package_folder_name = $zip->getNameIndex(0);
|
||||
$installer_file_folder = $tmp . '/' . $package_folder_name;
|
||||
|
||||
$is_install = true;
|
||||
$installer = self::loadInstaller($installer_file_folder, $is_install);
|
||||
|
||||
if (isset($options['is_update']) && $options['is_update'] === true) {
|
||||
$method = 'preUpdate';
|
||||
} else {
|
||||
$method = 'preInstall';
|
||||
}
|
||||
|
||||
if ($installer && method_exists($installer, $method)) {
|
||||
$method_result = $installer::$method();
|
||||
if ($method_result !== true) {
|
||||
self::$error = 'An error occurred';
|
||||
if (is_string($method_result)) {
|
||||
self::$error = $method_result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$options['sophisticated']) {
|
||||
if ($options['theme']) {
|
||||
@@ -139,16 +112,8 @@ class Installer
|
||||
Folder::delete($tmp);
|
||||
$zip->close();
|
||||
|
||||
if (isset($options['is_update']) && $options['is_update'] === true) {
|
||||
$method = 'postUpdate';
|
||||
} else {
|
||||
$method = 'postInstall';
|
||||
}
|
||||
|
||||
self::$message = '';
|
||||
if ($installer && method_exists($installer, $method)) {
|
||||
self::$message = $installer::$method();
|
||||
}
|
||||
// Post install checks
|
||||
static::flightProcessing('post_install', $install_path);
|
||||
|
||||
self::$error = self::OK;
|
||||
|
||||
@@ -156,60 +121,25 @@ class Installer
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates and returns the package installer class
|
||||
*
|
||||
* @param string $installer_file_folder The folder path that contains install.php
|
||||
* @param bool $is_install True if install, false if removal
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
private static function loadInstaller($installer_file_folder, $is_install)
|
||||
protected static function flightProcessing($state, $install_path)
|
||||
{
|
||||
$installer = null;
|
||||
$blueprints_path = $install_path . DS . 'blueprints.yaml';
|
||||
|
||||
$installer_file_folder = rtrim($installer_file_folder, DS);
|
||||
|
||||
$install_file = $installer_file_folder . DS . 'install.php';
|
||||
|
||||
if (file_exists($install_file)) {
|
||||
require_once($install_file);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($is_install) {
|
||||
$slug = '';
|
||||
if (($pos = strpos($installer_file_folder, 'grav-plugin-')) !== false) {
|
||||
$slug = substr($installer_file_folder, $pos + strlen('grav-plugin-'));
|
||||
} elseif (($pos = strpos($installer_file_folder, 'grav-theme-')) !== false) {
|
||||
$slug = substr($installer_file_folder, $pos + strlen('grav-theme-'));
|
||||
if (file_exists($blueprints_path)) {
|
||||
$package_yaml = Yaml::parse(file_get_contents($blueprints_path));
|
||||
if (isset($package_yaml['install'][$state]['create'])) {
|
||||
foreach ((array) $package_yaml['install']['pre_install']['create'] as $file) {
|
||||
Folder::mkdir($install_path . '/' . ltrim($file, '/'));
|
||||
}
|
||||
}
|
||||
if (isset($package_yaml['install'][$state]['remove'])) {
|
||||
foreach ((array) $package_yaml['install']['pre_install']['remove'] as $file) {
|
||||
Folder::delete($install_path . '/' . ltrim($file, '/'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$path_elements = explode('/', $installer_file_folder);
|
||||
$slug = end($path_elements);
|
||||
}
|
||||
|
||||
if (!$slug) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class_name = ucfirst($slug) . 'Install';
|
||||
|
||||
if (class_exists($class_name)) {
|
||||
return $class_name;
|
||||
}
|
||||
|
||||
return $installer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ZipArchive $zip
|
||||
* @param $install_path
|
||||
* @param $tmp
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function moveInstall(\ZipArchive $zip, $install_path, $tmp)
|
||||
{
|
||||
$container = $zip->getNameIndex(0);
|
||||
@@ -222,13 +152,6 @@ class Installer
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ZipArchive $zip
|
||||
* @param $install_path
|
||||
* @param $tmp
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function copyInstall(\ZipArchive $zip, $install_path, $tmp)
|
||||
{
|
||||
$firstDir = $zip->getNameIndex(0);
|
||||
@@ -242,13 +165,6 @@ class Installer
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ZipArchive $zip
|
||||
* @param $install_path
|
||||
* @param $tmp
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function sophisticatedInstall(\ZipArchive $zip, $install_path, $tmp)
|
||||
{
|
||||
for ($i = 0, $l = $zip->numFiles; $i < $l; $i++) {
|
||||
@@ -287,8 +203,8 @@ class Installer
|
||||
/**
|
||||
* Uninstalls one or more given package
|
||||
*
|
||||
* @param string $path The slug of the package(s)
|
||||
* @param array $options Options to use for uninstalling
|
||||
* @param string $path The slug of the package(s)
|
||||
* @param array $options Options to use for uninstalling
|
||||
*
|
||||
* @return boolean True if everything went fine, False otherwise.
|
||||
*/
|
||||
@@ -300,30 +216,7 @@ class Installer
|
||||
return false;
|
||||
}
|
||||
|
||||
$installer_file_folder = $path;
|
||||
$is_install = false;
|
||||
$installer = self::loadInstaller($installer_file_folder, $is_install);
|
||||
|
||||
if ($installer && method_exists($installer, 'preUninstall')) {
|
||||
$method_result = $installer::preUninstall();
|
||||
if ($method_result !== true) {
|
||||
self::$error = 'An error occurred';
|
||||
if (is_string($method_result)) {
|
||||
self::$error = $method_result;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = Folder::delete($path);
|
||||
|
||||
self::$message = '';
|
||||
if ($result && $installer && method_exists($installer, 'postUninstall')) {
|
||||
self::$message = $installer::postUninstall();
|
||||
}
|
||||
|
||||
return $result;
|
||||
return Folder::delete($path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,24 +273,13 @@ class Installer
|
||||
return !self::$error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last message added by the installer
|
||||
* @return string The message
|
||||
*/
|
||||
public static function getMessage()
|
||||
{
|
||||
return self::$message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last error occurred in a string message format
|
||||
* @return string The message of the last error
|
||||
*/
|
||||
public static function lastErrorMsg()
|
||||
{
|
||||
if (is_string(self::$error)) {
|
||||
return self::$error;
|
||||
}
|
||||
$msg = 'Unknown Error';
|
||||
|
||||
switch (self::$error) {
|
||||
case 0:
|
||||
@@ -433,7 +315,7 @@ class Installer
|
||||
break;
|
||||
|
||||
default:
|
||||
$msg = 'Unknown Error';
|
||||
return 'Unknown error';
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -451,8 +333,7 @@ class Installer
|
||||
|
||||
/**
|
||||
* Allows to manually set an error
|
||||
*
|
||||
* @param int|string $error the Error code
|
||||
* @param $error the Error code
|
||||
*/
|
||||
|
||||
public static function setError($error)
|
||||
|
||||
@@ -19,7 +19,7 @@ class Package extends BasePackage
|
||||
$this->data->set('slug', $package->slug);
|
||||
$this->data->set('description_html', $html_description);
|
||||
$this->data->set('description_plain', strip_tags($html_description));
|
||||
$this->data->set('symlink', is_link(USER_DIR . $package_type . DS . $this->slug));
|
||||
$this->data->set('symlink', is_link(USER_DIR . $package_type . DS . $this->name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace Grav\Common\GPM\Local;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
||||
/**
|
||||
* Class Plugins
|
||||
* @package Grav\Common\GPM\Local
|
||||
@@ -19,8 +17,6 @@ class Plugins extends AbstractPackageCollection
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/** @var \Grav\Common\Plugins $plugins */
|
||||
$plugins = Grav::instance()['plugins'];
|
||||
parent::__construct($plugins->all());
|
||||
parent::__construct(self::getGrav()['plugins']->all());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace Grav\Common\GPM\Local;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
||||
/**
|
||||
* Class Themes
|
||||
* @package Grav\Common\GPM\Local
|
||||
@@ -19,6 +17,6 @@ class Themes extends AbstractPackageCollection
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(Grav::instance()['themes']->all());
|
||||
parent::__construct(self::getGrav()['themes']->all());
|
||||
}
|
||||
}
|
||||
|
||||