Compare commits

...

873 Commits

Author SHA1 Message Date
Andy Miller
e366cdfb05 Merge branch 'hotfix/0.9.42' 2015-09-11 16:29:33 -06:00
Andy Miller
67d17080e6 version update 2015-09-11 16:29:19 -06:00
Andy Miller
345ed1178c missing return statement 2015-09-11 16:27:53 -06:00
Andy Miller
f8c02d065e Merge branch 'release/0.9.41' 2015-09-11 13:26:59 -06:00
Andy Miller
07fe7f4f89 typos 2015-09-11 13:26:38 -06:00
Andy Miller
546bb9bb13 version update 2015-09-11 13:25:13 -06:00
Andy Miller
5208304ef6 Fix for modular template types not getting found 2015-09-11 12:21:36 -06:00
Andy Miller
9ce5cc8f77 Added logic for configuring redirect in admin 2015-09-11 10:47:26 -06:00
Andy Miller
bef9e3c5ce Add simple redirect: header option for Page 2015-09-11 10:21:25 -06:00
Andy Miller
572bb429ce Fix for #317 markdown_extra: overriding markdown:extra: 2015-09-11 09:38:32 -06:00
Andy Miller
955e985f4d Merge pull request #316 from getgrav/feature/conform-to-authorize
Conform to authorize
2015-09-11 09:21:24 -06:00
Flavio Copes
fab8667dd4 Fix typo 2015-09-11 15:14:23 +02:00
Flavio Copes
03a8baf51c Order twig filters and functions by name 2015-09-11 15:13:01 +02:00
Flavio Copes
1f2f259554 Conform to authorize 2015-09-11 14:59:29 +02:00
Flavio Copes
989f5f5b61 Check to prevent error when Grav cannot reach the remote 2015-09-10 22:33:57 +02:00
Flavio Copes
063b31e7e6 Added authorize twig extension 2015-09-10 21:29:18 +02:00
Andy Miller
9abbb85b4a update composer.lock file with new versions 2015-09-10 12:49:56 -06:00
Andy Miller
2ecebd14b0 added check for mbstring support 2015-09-10 12:49:38 -06:00
Andy Miller
2f38277993 Refactored the truncate and truncateHTML methods. new 'word-safe' versions and UTF8 compatible. #313 #315 2015-09-10 12:49:19 -06:00
Andy Miller
faf690b833 Fixed all() not actually returning all pages... 2015-09-09 19:37:48 -06:00
Andy Miller
506517901d Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-09-09 15:01:55 -06:00
Andy Miller
2a1f5500bd translate message 2015-09-09 15:01:47 -06:00
Flavio Copes
38fad35119 Add ofOneOfTheseTypes() to Collection 2015-09-09 21:18:14 +02:00
Andy Miller
502eab85bf add support for yaml toggle to save in yam format 2015-09-09 13:07:01 -06:00
Flavio Copes
567169c4cb Add ofType() method to Collection, to filter collections by type 2015-09-09 09:27:17 +02:00
Andy Miller
cdc3f45257 Just filter published 2015-09-08 17:49:15 -06:00
Andy Miller
f7ff0f8ad5 fix typos in publish/unpublish date fields 2015-09-08 17:43:50 -06:00
Andy Miller
f9ac87db3a new editable select drop down for default date format 2015-09-08 17:43:23 -06:00
Andy Miller
b712174136 Merge pull request #310 from mufac/patch-3
Fix bug in newuser command
2015-09-08 11:12:24 -06:00
Andy Miller
81ca34ea1d Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-09-08 11:07:45 -06:00
Andy Miller
27a2f462a0 fix for page name and multilang 2015-09-08 11:07:38 -06:00
mufac
986664a766 Fix bug in newuser command
grav newuser was setting password to null irrespective of what was entered at the console
2015-09-07 21:34:55 -05:00
Andy Miller
3a4bea928a Merge pull request #309 from vitorgalvao/patch-1
nginx.conf: cosmetic fixes
2015-09-07 18:02:06 -06:00
Vítor Galvão
0ad8c43c7b nginx.conf: cosmetic fixes 2015-09-08 00:58:55 +01:00
Andy Miller
87ddd619de Added the ability to set the default PHP locale and override via multilang config #299 2015-09-07 16:54:48 -06:00
Andy Miller
5827fe4a22 minor refactor 2015-09-07 15:28:05 -06:00
Andy Miller
bd06842375 Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-09-07 15:15:28 -06:00
Andy Miller
71c8dcb595 fix for multisite routing 2015-09-07 15:15:18 -06:00
Andy Miller
1b76486bff Added configurable ignore files/folders 2015-09-07 15:14:57 -06:00
Andy Miller
7b1d5efe0d Merge pull request #308 from nunull/develop
[bin/grav newuser] Hide input when prompting for password (Fixes #307)
2015-09-07 15:00:15 -06:00
Timm Albers
9d7a46fe94 [bin/grav newuser] Prompt twice for password since input is hidden (Fixes #307) 2015-09-07 19:18:26 +02:00
Timm Albers
e494c87e28 [bin/grav newuser] Hide input when prompting for password (Fixes #307) 2015-09-07 18:10:51 +02:00
Andy Miller
6215f148b5 underlines back in site.yam config 2015-09-07 09:23:26 -06:00
Andy Miller
7f35c69b12 Merge pull request #305 from getgrav/feature/work-on-form-plugin
Work related to the Form plugin
2015-09-07 09:19:15 -06:00
Andy Miller
0688909fb7 simple implementation of multiple content collections for a page 2015-09-06 12:59:34 -06:00
Andy Miller
a5e2f76cb8 @taxonomy collection should only get non-modular and published pages 2015-09-06 10:58:14 -06:00
Andy Miller
119e52fa15 Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-09-05 19:20:50 -06:00
Andy Miller
083ef6d474 Added routable logic so modular pages are not routable by default (as intended!) 2015-09-05 19:20:43 -06:00
Andy Miller
d7bbbb2d76 Merge pull request #301 from getgrav/allow-validate-pages-from-outside-admin
Allow validating a page from outside the admin plugin
2015-09-05 12:45:13 -06:00
Flavio Copes
2fa9f79962 Allow validating a page from outside the admin plugin
This change allows a plugin to call validate() (which in turn calls blueprints()) on a page from the front, without needing the admin plugin to be active and set in the Grav object.
2015-09-05 11:55:22 +02:00
Andy Miller
8fdac33219 fix for themes with multiple stream prefixes 2015-09-04 09:42:44 -06:00
Flavio Copes
d3e4adb3c4 Renamed uploads form field to pagemedia 2015-09-04 16:59:29 +02:00
Flavio Copes
469ab56b64 Add a string Twig function that renders arrays as json_encoded strings, and just outputs other values (used by the form plugin) 2015-09-04 14:59:41 +02:00
Andy Miller
89c694443d Better twig error msg (part 2) 2015-09-03 16:45:07 -06:00
Andy Miller
6fd95154bb Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-09-03 12:01:53 -06:00
Andy Miller
4de2665192 Truncator improvements 2015-09-03 12:01:43 -06:00
Flavio Copes
23d38083f6 Merge pull request #297 from getgrav/work-on-images
Correctly generate 2x image too and make it available to srcset, fixes #133
2015-09-03 15:13:07 +02:00
Flavio Copes
0ae486737f Correctly generate 2x image too and make it available to srcset, fixes #133 2015-09-03 15:12:02 +02:00
Flavio Copes
cd3aa54a12 Focus on frontmatter in expert mode 2015-09-03 13:20:52 +02:00
Andy Miller
ec55020f77 Filter to save dates based on default format if it has been set 2015-09-02 17:17:21 -06:00
Andy Miller
d4461f075b Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-09-02 15:29:50 -06:00
Andy Miller
f67bb675a1 Added support for custom page date format: https://github.com/getgrav/grav-plugin-admin/issues/135 2015-09-02 15:29:41 -06:00
Andy Miller
a084f804f2 Merge pull request #295 from mufac/patch-2
Set default when config option is empty
2015-09-01 18:59:11 -06:00
mufac
a898f97d21 Set default when config option is empty
The default config option is an empty array, which causes get() to return null, which can lead to an error with the type of the second argument to in_array().
2015-09-01 19:50:00 -05:00
Andy Miller
9c3b062cff changed order to address redirect loop 2015-08-31 21:47:58 -06:00
Andy Miller
dd00f34cb8 Default to performing a 301 redirect for URIs with trailing slashes 2015-08-31 21:28:00 -06:00
Andy Miller
b9e24712a8 added missing accounts/ folder 2015-08-31 18:07:04 -06:00
Andy Miller
1ebbef257e Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-08-31 17:57:23 -06:00
Andy Miller
e7aca138d3 Log all from debug onward 2015-08-31 17:57:09 -06:00
Djamil Legato
f0ed155814 Added support for automatic package release of grav-admin 2015-08-31 16:54:38 -07:00
Andy Miller
838ddabd3c slight modification to not include ellipsis on sentence break 2015-08-31 16:26:29 -06:00
Andy Miller
5f3c20b71b updated truncate filter with a new optional toggle to enable/disable going up to a break character 2015-08-31 16:20:02 -06:00
Andy Miller
76bff5a1a9 moved dependencies to master 2015-08-31 15:41:02 -06:00
Andy Miller
e7270f17fd Merge branch 'release/0.9.40' 2015-08-31 10:22:34 -06:00
Andy Miller
aa709c4089 Merge branch 'release/0.9.40' into develop 2015-08-31 10:22:34 -06:00
Andy Miller
807032b0f0 version update 2015-08-31 10:21:24 -06:00
Andy Miller
b2597d1058 safety check when clearing cache paths 2015-08-31 09:02:07 -06:00
Andy Miller
56bb8c0304 explicit null value 2015-08-31 08:09:30 -06:00
Andy Miller
c4a51c2c9f Merge pull request #294 from fantasticme/develop
.htaccess hardening
2015-08-30 10:21:16 -06:00
Ionut Morariu
c3cdf0238a .htaccess hardening 2015-08-30 18:16:20 +02:00
Andy Miller
f28fc339df Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-08-29 10:40:49 -06:00
Andy Miller
45be24192e Support for page file name + template override 2015-08-29 10:40:43 -06:00
Flavio Copes
bb2929dfe9 Fix space between words 2015-08-29 17:05:40 +02:00
Flavio Copes
5b2cf24840 Merge pull request #289 from getgrav/autofocus-page-title
Put autofocus on page title
2015-08-29 15:42:33 +02:00
Andy Miller
19688ffcb5 Merge pull request #288 from getgrav/fix-123
Solve an issue with apostrophes in the taxonomy name
2015-08-29 07:28:35 -06:00
Flavio Copes
0baab3ae9f Put autofocus on page title
Refs https://github.com/getgrav/grav-plugin-admin/issues/122
2015-08-29 13:23:19 +02:00
Flavio Copes
9364c07c81 Solve an issue with apostrophes in the taxonomy name
Fixes #123
2015-08-29 11:58:24 +02:00
Flavio Copes
b46ab8aa5b Fix order by select size 2015-08-29 10:47:29 +02:00
Andy Miller
9d70a93619 Added a few filters 2015-08-28 13:39:57 -06:00
Andy Miller
688ec17cba some fixes for no siblings 2015-08-28 11:38:52 -06:00
Andy Miller
8bdef0dc57 Merge branch 'develop' of https://github.com/getgrav/grav into develop 2015-08-28 10:59:59 -06:00
Andy Miller
826fa8e225 switch to 'install' by default and use composer.lock 2015-08-28 10:59:54 -06:00
Flavio Copes
c41e58b1d7 Fix translation label 2015-08-28 16:52:18 +02:00
Flavio Copes
198c181ed7 Add help to the username blueprint 2015-08-28 16:01:42 +02:00
Flavio Copes
665974a21e Prevent error, check if $child_page is not null 2015-08-28 15:55:21 +02:00
Flavio Copes
be4af2403b Better explanation for bin/grav newuser username format 2015-08-28 15:55:21 +02:00
Andy Miller
19a4480b96 Merge pull request #284 from mufac/patch-1
Fix issue with date format for PHP 5.1.0+
2015-08-26 15:20:34 -06:00
mufac
f58df3c48f Fix issue with date format for PHP 5.1.0+
As of PHP 5.1.0 the character 'o' represents the ISO-8601 year number in a date format. Therefore the 'o' needs to be escaped to avoid being converted to a year in the admin > configuration > system > long/short date format pulldown menu.

I should note that this fixes the issue for English, but you might want to consider moving the date format into a language string in order to provide better multi-language support.
2015-08-26 15:50:55 -05:00
Andy Miller
a19e20e347 Better error message on incompatible template file 2015-08-26 11:20:14 -06:00
Andy Miller
cb074afd85 Merge branch 'release/0.9.39' 2015-08-25 10:45:28 -06:00
Andy Miller
03613481a3 Merge branch 'release/0.9.39' into develop 2015-08-25 10:45:28 -06:00
Andy Miller
7e3226e596 version update 2015-08-25 10:45:04 -06:00
Flavio Copes
c7c81e5380 Solve issue in page.active for the homepage. Fixes #279 2015-08-25 17:37:16 +02:00
Flavio Copes
b3c1584630 Fix issue with session name containing invalid characters
The underscore '_' is not a valid char for session name. Not sure why I
was only getting this error in Opera
https://stackoverflow.com/questions/3185779/the-session-id-is-too-long-o
r-contains-illegal-characters-valid-characters-are
2015-08-25 11:06:38 +02:00
Andy Miller
889a1a147c Merge branch 'release/0.9.38' into develop 2015-08-24 15:06:40 -06:00
Andy Miller
795268a98b Merge branch 'release/0.9.38' 2015-08-24 15:06:39 -06:00
Andy Miller
70a36602e8 version update 2015-08-24 14:46:14 -06:00
Andy Miller
46736becc7 updated 2015-08-24 14:45:05 -06:00
Andy Miller
af160168f1 Revamped metadata to use same customizable array system as the site.yaml 2015-08-24 13:41:28 -06:00
Flavio Copes
6e21a3f56a Drop @deprecated line 2015-08-24 09:07:30 +02:00
Andy Miller
86f29ebe57 Fix for trailing / not matching active and activeChild paths #277 2015-08-21 13:19:24 -06:00
Andy Miller
cf867d29a0 Added symfony dump() method for debugging 2015-08-21 13:13:33 -06:00
Andy Miller
93a3d800ef remove required to sync with normal 2015-08-21 11:39:20 -06:00
Matias Griese
056ad33f50 Fix blueprint @extends with external context (regression from #38) 2015-08-21 19:04:44 +03:00
Andy Miller
e750e1b183 Merge pull request #276 from Sommerregen/patch-1
Fix error from grav-plugin-admin issue # 80
2015-08-21 09:04:10 -06:00
Andy Miller
257949505c Merge pull request #275 from akoebbe/feature/arbitrary-date-collection-filter
Feature/Allow the use of custom datetime fields for collection filtering
2015-08-21 09:01:51 -06:00
Andrew Koebbe
b688660ff3 Move the $field param to the end of the method for backward compatibility. 2015-08-21 09:54:14 -05:00
Benny
ddc98f99da Fix error from gav-plugin-admin issue # 80
This change fixes an issue connected with https://github.com/getgrav/grav-plugin-admin/issues/80 that occurred when installing plugins removing the duplicate slash in the beginning due to https://github.com/getgrav/grav/blob/develop/system/defines.php#L17 .
2015-08-21 14:15:31 +02:00
Andrew Koebbe
8e41b51cb7 Allow the use of any custom page date field for dateRange collection filtering. 2015-08-20 23:37:29 -05:00
Andy Miller
0675ce718c better/safer parent route logic 2015-08-20 17:38:07 -06:00
Andy Miller
25ac6a0600 Merge branch 'feature/work-on-languages-workflow' into develop 2015-08-20 15:38:40 -06:00
Andy Miller
e8ca646070 updated toolbox 2015-08-20 15:38:21 -06:00
Flavio Copes
ce8fd4d3ef Add pathPrefixedByLangCode to Utils, fix generating pages routes for translated languages 2015-08-20 19:55:00 +02:00
Matias Griese
26d1973110 Fix blueprints loading (regression from #38) 2015-08-20 20:45:39 +03:00
Matias Griese
c4cd355f5b Add support for extending blueprints with its parent (single level only) 2015-08-20 12:23:41 +03:00
Matias Griese
4a59b8ae43 Fix logic to list and load blueprints by using streams (#38) 2015-08-20 11:35:01 +03:00
Andy Miller
c3f2ddf3e4 fixed a typo 2015-08-19 18:11:02 -06:00
Andy Miller
8cbb86045e Added a simple base_url with no language (useful for admin) 2015-08-19 14:58:42 -06:00
Flavio Copes
e54b202de3 Add translatedLanguages and untranslatedLanguages methods to Page class 2015-08-19 14:30:09 +02:00
Andy Miller
6466241cbb unset plaintext pw and hash on user save 2015-08-18 19:07:34 -06:00
Flavio Copes
dbccdbd51f Merge branch 'feature/translate-blueprints' into develop 2015-08-18 20:33:21 +02:00
Flavio Copes
3141336c9b Translate system config 2015-08-18 16:59:17 +02:00
Flavio Copes
07bf588aa4 All pages blueprints translated 2015-08-18 16:18:01 +02:00
Flavio Copes
ce84648689 Translate page default blueprint 2015-08-18 15:51:53 +02:00
Flavio Copes
cdef7d62c8 Translate user blueprints, config/media, config/site 2015-08-18 15:16:06 +02:00
Flavio Copes
440c27d27b blueprints/user/account.yaml 2015-08-18 14:45:10 +02:00
Andy Miller
e82b90b117 better lang chooser 2015-08-17 18:21:04 -06:00
Flavio Copes
1ecf147764 Merge pull request #270 from getgrav/feature/translate-admin
Feature/translate admin
2015-08-17 16:33:36 +02:00
Andy Miller
58b9ecf030 Added ordering to raw blueprints 2015-08-16 14:06:25 -06:00
Andy Miller
0e28dc835e Added translation for frontmatter error 2015-08-16 13:51:04 -06:00
Flavio Copes
8800f48312 Add requirements to the readme, fixes #264 2015-08-16 09:10:53 +02:00
Andy Miller
6315004a24 change title to slug 2015-08-14 22:16:40 -06:00
Andy Miller
ee63192512 catch header parse exception and create a simple page so site doesn't break 2015-08-14 16:30:18 -06:00
Andy Miller
1c9dec6ea4 unset route and slug 2015-08-14 15:01:13 -06:00
Andy Miller
6fd85c8dbd Stuff needed for page vibility/ordering setting 2015-08-14 14:30:11 -06:00
Andy Miller
80e4ed1746 Tweak the default layout 2015-08-14 14:29:04 -06:00
Flavio Copes
06b5a93fe9 Add language to user blueprint 2015-08-13 18:30:17 +02:00
Flavio Copes
7ca2e9b5f0 Merge branch 'develop' into feature/translate-admin 2015-08-13 18:30:02 +02:00
Djamil Legato
274ff3d8c0 Additional slug fixes with GPM (#44). Increased spaces in GPM CLI 2015-08-12 10:41:47 -07:00
Flavio Copes
42e6d587d8 Fix slug to be lowercase 2015-08-12 15:35:45 +02:00
Andy Miller
c13daf7780 Merge branch 'release/0.9.37' 2015-08-12 06:31:53 -06:00
Andy Miller
e47b3e73d3 Merge branch 'release/0.9.37' into develop 2015-08-12 06:31:53 -06:00
Andy Miller
38a7b0d7ab version update 2015-08-12 06:31:07 -06:00
Andy Miller
e13c5c214a reverted !empty to isset and put in some casting logic to handle empty/invalid values 2015-08-12 06:22:49 -06:00
Andy Miller
a975786b7b fix for empty string header values throwing errors 2015-08-12 05:57:14 -06:00
Andy Miller
0bccaf5458 Merge branch 'release/0.9.36' 2015-08-11 19:38:18 -06:00
Andy Miller
9b760da29b Merge branch 'release/0.9.36' into develop 2015-08-11 19:38:18 -06:00
Andy Miller
5a7ad45a7e version update 2015-08-11 19:38:07 -06:00
Andy Miller
3cf5c6e4ab Use GRAV_ROOT for session identifier #53 2015-08-11 15:46:48 -06:00
Flavio Copes
659517001b Revert "Force english in admin"
This reverts commit 8962d2b1e4.
2015-08-11 10:14:08 +02:00
Flavio Copes
4c94776ace Minor code improvements and typos 2015-08-11 10:08:45 +02:00
Andy Miller
76c4da7945 support user and system languages 2015-08-08 14:44:30 -06:00
Andy Miller
aacd9732f2 Added a newuser command to make creating users simpler 2015-08-08 11:24:18 -06:00
Andy Miller
16b2cccea4 Use sessions for admin even when sessions are disabled 2015-08-07 15:15:28 -06:00
Djamil Legato
8922f6a486 Added isSymlink logic to determine if Grav is symbolically linked or not. 2015-08-07 13:33:25 -07:00
Flavio Copes
d28656ce4b Update system blueprint to use the current date in the date format select, refs getgrav/grav-plugin-admin#26 2015-08-07 21:59:50 +02:00
Flavio Copes
8c4f6d68e8 Better example for date format, fixes getgrav/grav-plugin-admin#26 2015-08-07 21:16:17 +02:00
Andy Miller
972987c515 updated composer.phar 2015-08-07 13:10:23 -06:00
Andy Miller
09fc5b768e Merge branch 'feature/update-pages-blueprint' into develop 2015-08-07 11:57:14 -06:00
Andy Miller
77caad9944 refactor recurse with public method to reset pages cache 2015-08-07 08:13:29 -06:00
Flavio Copes
5c367ac598 Update pages blueprint to add toggleable and remove the global options 2015-08-07 12:11:01 +02:00
Andy Miller
867445cbd8 refactor the blueprints fallback a little 2015-08-06 22:26:51 -06:00
Andy Miller
65df265e30 Added a default type as a default type :) 2015-08-06 22:26:19 -06:00
Andy Miller
11869ad4ec Merge branch 'release/0.9.35' 2015-08-06 18:38:48 -06:00
Andy Miller
62b8486431 Merge branch 'release/0.9.35' into develop 2015-08-06 18:38:48 -06:00
Andy Miller
11fc34cfed version update 2015-08-06 18:38:35 -06:00
Andy Miller
b5717c2cbb Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Djamil Legato (1) and Sommerregen (1)
# Via Andy Miller (1) and Djamil Legato (1)
* 'develop' of https://github.com/getgrav/grav:
  Fixed GPM issue when using cURL throwing an `Undefined offset: 1` exception
  Fix #248 (Plugin language interference) and fixed summary
2015-08-06 18:31:21 -06:00
Andy Miller
0c085a5aab Override save to not store the username field 2015-08-06 18:31:08 -06:00
Andy Miller
5cee23cbfa Added new unsetRoute() to allow route() to rebuild 2015-08-06 18:30:50 -06:00
Andy Miller
1e168b3100 made username disabled 2015-08-06 18:30:24 -06:00
Djamil Legato
018f7a6dec Fixed GPM issue when using cURL throwing an Undefined offset: 1 exception 2015-08-06 11:31:37 -07:00
Andy Miller
a62e88f22b Merge pull request #249 from Sommerregen/bugfix/plugin-language-interference
Fix #248 (Plugin language interference) and fixed summary
2015-08-06 12:20:52 -06:00
Sommerregen
dc5ba9eff4 Fix #248 (Plugin language interference) and fixed summary 2015-08-06 19:59:20 +02:00
Andy Miller
4bebdfe0c7 fixed metadata merging (hopefully!) 2015-08-05 22:27:26 -06:00
Andy Miller
f8fd065192 removed unused body_classes in modular type 2015-08-05 22:26:57 -06:00
Andy Miller
9d38d0818b fix robots field 2015-08-05 22:26:41 -06:00
Andy Miller
a1ad9b7f4d list of pages should show all except root 2015-08-05 18:06:50 -06:00
Andy Miller
29cb55e91c visible toggle and help commands on new page 2015-08-05 18:06:07 -06:00
Andy Miller
0687d2ff78 added body_classes to modular type 2015-08-05 18:05:34 -06:00
Andy Miller
cd04572b78 using new templates field type 2015-08-05 18:04:57 -06:00
Andy Miller
6bb47124a9 added body classes 2015-08-05 18:03:34 -06:00
Andy Miller
1a21186ba1 removed duplicate hidden type field 2015-08-05 18:03:16 -06:00
Andy Miller
82d1193090 removed required from title 2015-08-05 18:02:48 -06:00
Andy Miller
ea76ac024a Merge pull request #244 from notklaatu/develop
added conf settings for running grav in sud dir, on nginx
2015-08-05 09:39:21 -06:00
Klaatu
ff52d61322 added conf settings for running grav in sud dir, on nginx 2015-08-05 11:44:38 +12:00
Andy Miller
83e970731e Merge branch 'release/0.9.34' into develop 2015-08-04 16:53:33 -06:00
Andy Miller
c6ea5eb5e9 Merge branch 'release/0.9.34' 2015-08-04 16:53:32 -06:00
Andy Miller
aa7a4111e6 version update 2015-08-04 16:53:16 -06:00
Andy Miller
2b01f832bd Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Sommerregen
# Via Andy Miller (1) and Sommerregen (1)
* 'develop' of https://github.com/getgrav/grav:
  Add language property to page
2015-08-04 09:41:21 -06:00
Andy Miller
1401102396 more extensive extension() method 2015-08-04 09:40:59 -06:00
Andy Miller
8963d024a6 more dynamic extension() method 2015-08-04 09:40:28 -06:00
Andy Miller
bb5e7b508f Merge pull request #243 from Sommerregen/feature/add-language-property-to-page
Add language property to page
2015-08-03 16:46:13 -06:00
Andy Miller
bfc9efea92 added new arrayFilterRecursive 2015-08-03 16:11:02 -06:00
Andy Miller
75feea3e75 back to Symfony 2.7.3 2015-08-03 16:10:16 -06:00
Sommerregen
e142f5ee61 Add language property to page 2015-08-03 22:08:07 +02:00
Djamil Legato
9746c2db5d Move yaml missing 2015-08-03 12:43:24 -07:00
Andy Miller
311598e3a6 Merge pull request #242 from flaviocopes/patch-1
Fix moving the page to the root
2015-08-03 08:15:26 -06:00
Andy Miller
109d19f02e changed order 2015-08-03 08:01:27 -06:00
Flavio Copes
bc5ea13821 Fix moving the page to the root
$parent->route() returned null when moving to the root
2015-08-03 10:19:56 +02:00
Andy Miller
e9cc34f481 Merge pull request #241 from aptly-io/fix_twig_vars_sideeffect
Fix #240 I'm ok with this.
2015-08-02 20:07:31 -06:00
franchan
9f254b6c84 Fix #240
$page->content() fires the onPageContentRaw event.
A plugin handler for this event might want to update the twig variable
with additional information during twig rendering.

However, $twig_vars takes a copy of $Twig->twig_vars and
therefore never sees any later changes in $Twig->twig_vars.

By moving the method call $page->content() earlier,
potential twig variable changes from a plugin get now inside this
local variable copy.
2015-08-02 23:52:48 +02:00
Andy Miller
4f442d1edc support admin overrides of blueprints 2015-08-02 12:13:08 -06:00
Andy Miller
a1a10ab23d more tweaks for blueprints 2015-08-01 17:40:58 -06:00
Andy Miller
21beefd387 added array() function to cast as an array 2015-08-01 13:37:32 -06:00
Andy Miller
a7e03c9d5c Stopped storing metadata in page header 2015-08-01 13:37:12 -06:00
Andy Miller
49781f9717 made metadata optional 2015-08-01 13:36:52 -06:00
Andy Miller
ca12c69741 fix for system lang files 2015-08-01 10:20:15 -06:00
Djamil Legato
333814eab0 Reenabled toggleables for Published 2015-07-31 13:10:51 -07:00
Djamil Legato
c18311eeb2 Moved blog and blog item blueprints out of Grav and into Antimatter theme 2015-07-31 13:10:24 -07:00
Andy Miller
3caa0d1ef5 Merge pull request #237 from flaviocopes/feature/separate-sessions-for-site-and-admin
Feature/separate sessions for site and admin
2015-07-31 11:05:56 -06:00
Flavio Copes
dc56f85881 Separate sessions for site and admin 2015-07-31 18:21:43 +02:00
Flavio Copes
532e035724 Load uri before session 2015-07-31 18:21:06 +02:00
Andy Miller
c3431e1ead Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Flavio Copes
# Via Andy Miller (3) and Flavio Copes (1)
* 'develop' of https://github.com/getgrav/grav:
  Move $session_timeout & $session_path inside the if statement
  Correctly instantiate the Inflector
  Force english in admin
  Refresh session timeout
2015-07-31 08:35:46 -06:00
Andy Miller
3016e77897 loose validation so un-formed values are not lost 2015-07-31 08:35:35 -06:00
Andy Miller
cf69ba0d66 Merge pull request #236 from flaviocopes/patch-4
Correctly instantiate the Inflector
2015-07-31 08:34:27 -06:00
Andy Miller
4e82891779 Merge pull request #232 from flaviocopes/patch-2
Refresh session timeout
2015-07-31 08:33:25 -06:00
Flavio Copes
7fa3e7bf28 Move $session_timeout & $session_path inside the if statement 2015-07-31 16:06:02 +02:00
Flavio Copes
656c23a891 Correctly instantiate the Inflector
$this->grav is not what we expect here. Got a fatal error on `$ bin/gpm` execution
2015-07-31 16:01:52 +02:00
Andy Miller
00f758dd98 Merge pull request #235 from flaviocopes/patch-3
Force english in admin
2015-07-31 07:52:52 -06:00
Flavio Copes
8962d2b1e4 Force english in admin 2015-07-31 15:48:47 +02:00
Flavio Copes
eefb761e98 Refresh session timeout 2015-07-30 19:17:04 +02:00
Andy Miller
9363da137f Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Djamil Legato
# Via Djamil Legato
* 'develop' of https://github.com/getgrav/grav:
  Added support for select multiple attribute in array filter
2015-07-29 22:00:30 -06:00
Andy Miller
c4daae2f95 added new blueprintName() method that takes into account blueprint value passed via a form 2015-07-29 22:00:03 -06:00
Andy Miller
b201b21e46 added blueprint hidden field to standard blueprints 2015-07-29 21:59:24 -06:00
Andy Miller
c959fd9c48 rolled back to composer 2.7.1 due to broken CLI choice method 2015-07-29 21:58:53 -06:00
Djamil Legato
0845b5e28a Added support for select multiple attribute in array filter 2015-07-29 20:43:13 -07:00
Andy Miller
b9f9570033 minor reformatting 2015-07-29 12:19:56 -06:00
Andy Miller
baa0e73703 updated default yaml 2015-07-29 11:31:50 -06:00
Andy Miller
e97aaccfee added a cache_all option for media images 2015-07-28 20:57:16 -06:00
Andy Miller
f58cfd8571 Merge branch 'feature/blueprint-extend' into develop
Conflicts:
	system/blueprints/config/site.yaml
	system/blueprints/config/system.yaml
2015-07-28 18:36:02 -06:00
Andy Miller
1a43d31c50 whitespace removal 2015-07-28 16:23:49 -06:00
Andy Miller
d244442e70 fixed translations with multiple plugins 2015-07-28 12:11:07 -06:00
Djamil Legato
a009c56271 Supported Language and Taxonomies are now using Selectize tags in admin 2015-07-28 11:08:37 -07:00
Andy Miller
f30af37faf php tidy 2015-07-28 11:10:38 -06:00
Andy Miller
bb4eea7999 missing use statement - issue #230 2015-07-28 04:54:16 -06:00
Andy Miller
e26b80d873 removed some extraneous messages 2015-07-27 08:32:29 -06:00
Andy Miller
b23aa1bc4c tweaks to system blueprint 2015-07-24 17:29:37 -06:00
Andy Miller
e22655b440 updated site.yaml blueprint 2015-07-24 15:16:36 -06:00
Andy Miller
8e57839271 missing some init() checks 2015-07-24 10:55:57 -06:00
Andy Miller
16f779c8f5 changed Inflector from static to class + added multilang support 2015-07-24 10:26:54 -06:00
Andy Miller
bd08d787f2 typo 2015-07-24 08:20:46 -06:00
Andy Miller
df99fe0073 blueprint updates 2015-07-24 08:20:36 -06:00
Andy Miller
7a2fceaee9 renamed translations.fallback property 2015-07-24 08:08:50 -06:00
Andy Miller
bb69656bd7 added base languages config 2015-07-24 08:08:23 -06:00
Andy Miller
5be0618b4d more blueprints progress 2015-07-24 07:50:47 -06:00
Andy Miller
ad00252a4e base translations settings 2015-07-24 07:50:35 -06:00
Andy Miller
84eee30d1f fix for string/array conversion error 2015-07-24 07:50:18 -06:00
Andy Miller
8975c2936c remove unused use that is causing an error 2015-07-23 11:36:43 -06:00
Andy Miller
b64bfc9ab0 more progress on system blueprint 2015-07-23 11:36:26 -06:00
Andy Miller
cc9f5ed096 More validation updates 2015-07-22 15:31:32 -06:00
Andy Miller
2161daa398 Prettier validation messages 2015-07-22 15:31:05 -06:00
Andy Miller
f1a41394ab updates for account validation 2015-07-22 15:30:27 -06:00
Andy Miller
6d5bb6f887 Merge branch 'release/0.9.33' 2015-07-21 13:48:10 -06:00
Andy Miller
9bcf9a7dcd Merge branch 'release/0.9.33' into develop 2015-07-21 13:48:10 -06:00
Andy Miller
6d69f03111 version update 2015-07-21 13:48:00 -06:00
Andy Miller
0b709ddb1a cleanup 2015-07-21 11:50:18 -06:00
Andy Miller
6ba780ba3b support translate taking string or array for key 2015-07-21 11:50:08 -06:00
Andy Miller
f0f24142b2 fix for broken auto-file-extension setting 2015-07-20 18:28:58 -06:00
Andy Miller
a716da14f7 Allow extension to be set manually, else set it from the file 2015-07-20 16:35:33 -06:00
Andy Miller
d8a80479c2 more explicit check for page extension 2015-07-20 16:35:21 -06:00
Andy Miller
8d4a55a3a4 added Vary: Accept-Encoding option. Off by default 2015-07-19 13:22:15 -06:00
Andy Miller
0c0aa94ded routable() now takes published() into account. Re issue #227 2015-07-17 17:31:36 -06:00
Andy Miller
0fd4991dd4 Fix for issue #225 - zip skipping required empty folders 2015-07-17 17:06:20 -06:00
Andy Miller
5f32ea64eb Extended ImageFile to provide event on creation function 2015-07-17 16:06:23 -06:00
Andy Miller
dc6705c74a added a new onImageMediumSaved event - useful for compression services 2015-07-17 14:04:19 -06:00
Andy Miller
4479f251a6 removed pageinit timing - was not doing much 2015-07-17 14:03:30 -06:00
Andy Miller
ac076fb892 fix for twig cache permissions 2015-07-15 10:18:23 -06:00
Andy Miller
503b38c17f fix for #224 - summary delimiter not getting proper position in certain conditions 2015-07-14 22:58:06 -06:00
Andy Miller
7b6680cde2 Merge branch 'release/0.9.32' into develop 2015-07-14 15:03:03 -06:00
Andy Miller
7029edfd58 Merge branch 'release/0.9.32' 2015-07-14 15:03:02 -06:00
Andy Miller
3b3ac68f47 version update 2015-07-14 15:02:49 -06:00
Andy Miller
5e28d04aa6 fixed a typo 2015-07-14 09:06:32 -06:00
Andy Miller
102140b917 Support 'en' translations independent from language support 2015-07-13 21:02:24 -06:00
Andy Miller
17d7e19e84 Added support for http_accept_language #219 2015-07-13 13:01:32 -06:00
Andy Miller
d7b810e87e fix for session active lang and homepage redirects 2015-07-13 12:14:52 -06:00
Andy Miller
3cf44b4c62 added translateArray() functionality 2015-07-13 11:57:20 -06:00
Andy Miller
96a9962895 minor language tweaks 2015-07-13 11:56:47 -06:00
Andy Miller
b2cd4db395 Default generator updated 2015-07-13 11:55:12 -06:00
Andy Miller
015ef2c6ce Fix for #218 - ignore root level page 2015-07-13 11:48:56 -06:00
Andy Miller
0ba1af244d Merge branch 'release/0.9.31' 2015-07-09 17:31:21 -06:00
Andy Miller
547a049140 Merge branch 'release/0.9.31' into develop 2015-07-09 17:31:21 -06:00
Andy Miller
05e0013990 version update 2015-07-09 17:30:26 -06:00
Andy Miller
b9d6f75923 Updated all bin/grav CLI commands to use ConsoleTrait 2015-07-09 17:23:56 -06:00
Andy Miller
07f4cb0892 updated to latest composer.par 2015-07-09 17:23:33 -06:00
Andy Miller
e48be33c6c unified backup command to mimic admin functionality 2015-07-09 17:08:29 -06:00
Andy Miller
b3ba54894e removed useless call 2015-07-09 17:07:52 -06:00
Andy Miller
14753d499d Fix for markdown filter error: Issue #115 2015-07-09 14:47:24 -06:00
Andy Miller
bb348fff94 fix for translations 2015-07-09 11:56:46 -06:00
Andy Miller
c097907098 safety check 2015-07-09 09:44:10 -06:00
Andy Miller
3719bac746 use an array for clarity 2015-07-08 20:05:26 -06:00
Andy Miller
85add10bef better handling of unsupported media types download 2015-07-08 20:04:15 -06:00
Andy Miller
8a7a9d4a45 added a configurable array for unsupported file types to inline rather than download 2015-07-08 20:03:43 -06:00
Andy Miller
875885f647 changed pages.types to be an array 2015-07-08 20:03:04 -06:00
Andy Miller
3af85ed14f added xml, json, css, and js to supported media "file" types 2015-07-08 20:01:55 -06:00
Andy Miller
34f6020e7f Merge branch 'release/0.9.30' 2015-07-08 13:26:01 -06:00
Andy Miller
2a6b96937c Merge branch 'release/0.9.30' into develop 2015-07-08 13:26:01 -06:00
Andy Miller
8861918827 version update 2015-07-08 13:25:50 -06:00
Andy Miller
6212aef8b1 added changelog 2015-07-08 12:59:28 -06:00
Andy Miller
f13c4e916a added option to store active lang in session 2015-07-08 11:39:08 -06:00
Andy Miller
60e183a8c0 Added a language-safe redirect option that appends lang if set 2015-07-08 11:23:51 -06:00
Andy Miller
939449c1b0 Added an option to always redirect to the default route if the route doesn't match default 2015-07-08 11:23:21 -06:00
Andy Miller
5970e5bf5c added ability to specify language to translate 2015-07-07 21:40:07 -06:00
Andy Miller
aee5a38313 don't hard-fail on missing language home alias 2015-07-07 21:27:17 -06:00
Andy Miller
19b2de7040 Use new location for Language file 2015-07-07 18:57:13 -06:00
Andy Miller
20d7ed5421 New Language files 2015-07-07 18:56:59 -06:00
Andy Miller
0dd53aea02 more robust active() and activeChild() methods to support multiple routes 2015-07-07 18:56:40 -06:00
Andy Miller
801d5d361a Add session support into Grav core (was in login plugin) 2015-07-07 14:21:30 -06:00
Andy Miller
dc7362c70b various sensiolab fixes 2015-07-06 21:50:05 -06:00
Andy Miller
fc3c0e7fa5 Merge branch 'feature/better_language_yaml_support' into develop 2015-07-06 21:30:51 -06:00
Andy Miller
e172f5c82d add toggle for translations.fallback 2015-07-06 21:20:15 -06:00
Andy Miller
3a7426ed04 more robust logic 2015-07-06 21:08:45 -06:00
Andy Miller
3ab1feb7b1 handle array for values 2015-07-06 20:53:04 -06:00
Andy Miller
1c90ee6db3 more support for translations in plugins/themes 2015-07-06 20:47:04 -06:00
Andy Miller
046136bc37 improved with plugin merge 2015-07-06 17:19:22 -06:00
Andy Miller
1d0234550e first whack at providing language yaml support 2015-07-05 21:48:13 -06:00
Andy Miller
cca3a039ad set some config defaults 2015-07-05 18:43:48 -06:00
Andy Miller
e73d101c97 fixed page expires again 2015-07-05 14:55:22 -06:00
Andy Miller
389e53207e Merge branch 'feature/lang_test' into develop 2015-07-05 14:53:46 -06:00
Andy Miller
5bdce4fb28 And the actual jQuery file! 2015-07-05 14:52:48 -06:00
Andy Miller
b06e3b3281 updated jQuery reference to v2.1.4 2015-07-05 14:50:54 -06:00
Andy Miller
a4d39ce424 Added translation Twig function and filter 2015-07-05 13:58:33 -06:00
Andy Miller
79f5aaa032 added a default route alias - particularly useful for multilane switching 2015-07-04 10:11:40 -06:00
Andy Miller
740ea2e86d removed unused method for now 2015-07-04 09:40:41 -06:00
Andy Miller
364f95ec45 add active lang to the base_url stuff 2015-07-03 16:16:36 -06:00
Andy Miller
6668a7b8ab save standard routing in aliases if default overrides 2015-07-03 15:41:39 -06:00
Andy Miller
571f27d518 minor modifications 2015-07-03 14:05:15 -06:00
Andy Miller
0fa70b5b35 better fallback approach 2015-07-03 08:20:21 -06:00
Andy Miller
be8d424404 added some fallback logic - still needs work! 2015-07-02 22:06:07 -06:00
Andy Miller
08e239fcf4 Added lang template paths for theme by default 2015-07-02 15:53:05 -06:00
Andy Miller
947cb79558 optimized enabled test 2015-07-02 15:50:05 -06:00
Andy Miller
1f1df9afc7 support lang specific homepage 2015-07-02 11:19:44 -06:00
Andy Miller
ef40bb25fd added a timer around pageInitialized event 2015-07-02 09:46:57 -06:00
Andy Miller
e2db025aa0 minor updates 2015-07-01 20:50:36 -06:00
Andy Miller
63369247ab fix for regex and last language 2015-07-01 15:56:56 -06:00
Andy Miller
8c695df9da fixed template name based on current lang 2015-07-01 11:07:09 -06:00
Andy Miller
1c9d41ad58 some more multilane progress 2015-07-01 10:59:08 -06:00
Andy Miller
e7721d21a2 Merge branch 'develop' into feature/lang_test
* develop:
  broke-out fallback into a protected method
  fix for content mismatch error
  add canonical routes like an alias
  add canonical route support
2015-06-30 16:56:04 -06:00
Andy Miller
547f72919f broke-out fallback into a protected method 2015-06-30 16:22:43 -06:00
Andy Miller
2b6740dc7b fix for content mismatch error 2015-06-30 16:14:06 -06:00
Andy Miller
1a91cf7033 add canonical routes like an alias 2015-06-30 14:59:48 -06:00
Andy Miller
1e9418b87b add canonical route support 2015-06-30 14:59:24 -06:00
Andy Miller
bedf1555af invalid method name 2015-06-29 22:04:21 -06:00
Andy Miller
5d070f4d9e Merge branch 'develop' into feature/lang_test
* develop:
  Fix for #212 - media timestamp typo
  get route() dynamically and add any route aliases
  added accessor for routeAliases
  small optimization
  initial default override support
  Potential fix for Insight (sensio labs)
  lost default page timeout in last release.. resetting

Conflicts:
	system/config/system.yaml
2015-06-29 22:01:40 -06:00
Andy Miller
7eff48bd4f Merge branch 'feature/custom_page_routes' into develop 2015-06-29 21:56:50 -06:00
Andy Miller
dfccfb3cf3 Fix for #212 - media timestamp typo 2015-06-29 15:38:53 -06:00
Andy Miller
aeebc13d83 get route() dynamically and add any route aliases 2015-06-29 15:30:53 -06:00
Andy Miller
0a42ace4ba added accessor for routeAliases 2015-06-29 15:30:32 -06:00
Andy Miller
7b4f0a29ac small optimization 2015-06-29 15:30:18 -06:00
Andy Miller
b529456745 initial default override support 2015-06-29 12:51:05 -06:00
Djamil Legato
f1a929624f Potential fix for Insight (sensio labs) 2015-06-28 12:12:44 -07:00
Andy Miller
65285ad11e lost default page timeout in last release.. resetting 2015-06-28 09:24:20 -06:00
Andy Miller
eb421bc95e more progress on matching lang keys 2015-06-28 09:23:48 -06:00
Andy Miller
917a5c3082 some initial lang work 2015-06-26 12:25:22 -06:00
Andy Miller
ea491fbde5 Merge pull request #211 from barryanders/develop
Spelling corrections.
2015-06-26 09:41:02 -06:00
Barry Anders
a98d01ba65 Spelling corrections. 2015-06-26 10:20:49 -05:00
Andy Miller
7e2fa8295a fixed ordering on a couple of filters 2015-06-25 16:25:45 -06:00
Andy Miller
adf758a569 updated some config files 2015-06-25 16:25:31 -06:00
Andy Miller
49941105dc Fix issue where page-based css and js were being downloaded rather than processed 2015-06-23 18:58:24 -06:00
Andy Miller
c07afab981 support arrays in startsWith() and endsWith() 2015-06-23 18:57:54 -06:00
Andy Miller
c2b07fec1f Merge branch 'release/0.9.29' 2015-06-22 17:10:37 -06:00
Andy Miller
7f8baf326e Merge branch 'release/0.9.29' into develop 2015-06-22 17:10:37 -06:00
Andy Miller
9601061f25 version update 2015-06-22 17:10:24 -06:00
Andy Miller
b1317e56ec Disabled last_modified and etag page header by default 2015-06-22 15:30:01 -06:00
Andy Miller
353832c386 Fix for directory relative 'down' links 2015-06-22 12:56:11 -06:00
Andy Miller
8bf04d4593 Merge pull request #207 from Sommerregen/feature/enable-custom-summaries
Modified `$page->summary()` to allow custom summary assignments
2015-06-21 13:27:56 -06:00
Sommerregen
c9f0500c6f Refactored code. Added $page->setSummary(<string>) method. 2015-06-21 11:03:30 +02:00
Andy Miller
0dc465bb41 PR #145 - Set all but debugger to specific versions 2015-06-20 12:11:00 -06:00
Andy Miller
34e50aab21 remove replicated code... 2015-06-20 11:54:46 -06:00
Andy Miller
5a2411a0e6 Merge pull request #206 from Sommerregen/feature/add-build-pages-event
Add `onBuildPagesInitialized` event for memory & time consuming plugins
2015-06-20 11:51:12 -06:00
Andy Miller
178f66c940 Merge pull request #189 from Sommerregen/feature/params-option-merge-config
Added params option for mergeConfig method
2015-06-20 11:45:32 -06:00
Sommerregen
6d3a7a3989 Fixed variable name 2015-06-20 18:24:19 +02:00
Sommerregen
2400eaf04e Resolving conflicts after rebase 2015-06-20 14:42:28 +02:00
Sommerregen
752a3ca5bd Incorporated Gertt's modifications into PR 2015-06-20 14:39:24 +02:00
Sommerregen
6dbb6eb432 Changed "mergeConfig" head to match previous method signature 2015-06-20 14:38:57 +02:00
Sommerregen
e580bb9998 Added params option for mergeConfig method 2015-06-20 14:38:33 +02:00
Sommerregen
d309491f06 Modified $page->summary() to allow custom summary assignments 2015-06-20 13:54:57 +02:00
Sommerregen
0e35048143 Add onBuildPagesInitialized event for memory and time consuming plugins 2015-06-20 13:53:07 +02:00
Andy Miller
c919ed36b4 Error handling around bad regex .. just to be safer 2015-06-17 17:53:32 -06:00
Andy Miller
6d2a7c53dc very simple, yet surprisingly powerful Regex style redirect and route support 2015-06-17 17:39:44 -06:00
Djamil Legato
a8582fc131 Hello Travis! 2015-06-17 12:58:23 -07:00
Djamil Legato
76b7bd855d initial travis setup to trigger detection 2015-06-16 23:06:57 -07:00
Andy Miller
5656bb3caf Pre-load ArrayInput to avoid Exception if it gets moved/replaced during upgrade 2015-06-16 20:51:38 -06:00
Andy Miller
57bd4d8f22 Merge branch 'release/0.9.28' 2015-06-16 16:15:42 -06:00
Andy Miller
e71cd5a7ad Merge branch 'release/0.9.28' into develop 2015-06-16 16:15:42 -06:00
Andy Miller
4132388dda version update 2015-06-16 16:15:25 -06:00
Andy Miller
1edabe3b00 added page level overrides of etag and last_modified header flags 2015-06-16 10:25:27 -06:00
Andy Miller
019fdd65e9 added toggles to enable/disable last_modified and etag headers 2015-06-16 09:58:56 -06:00
Andy Miller
fa432cd32f Another incorrect slug name 2015-06-15 16:03:22 -06:00
Andy Miller
4935679659 fix #202 - incorrect slug name causing issues 2015-06-15 15:00:49 -06:00
Andy Miller
835c64c173 comment fix 2015-06-15 14:59:44 -06:00
Andy Miller
4d6ecbe618 Moved convertUrl() from ParsedownGravTrait into Uri as a static method 2015-06-14 17:54:22 -06:00
Andy Miller
63456aad85 reset how symfony libs versions are set in composer 2015-06-13 06:45:49 -06:00
Andy Miller
bec2ee91b5 updated symphony versions 2015-06-13 06:44:17 -06:00
Andy Miller
027c9cdd04 updated to latest cache library - should be a little faster! 2015-06-12 22:32:23 -06:00
Andy Miller
8ecea3a8c1 some more fixes for image handling in certain scenarios 2015-06-12 15:54:20 -06:00
Andy Miller
69e6d57346 Merge pull request #200 from Seebz/issue-199
Fix for issue #199 - Looks good! Thanks
2015-06-08 14:47:06 +01:00
Seebz
8127d9cf31 Fix for issue #199 2015-06-04 16:46:18 +02:00
Gert
bc1a9b31fa add @config directive to get config values from blueprints 2015-06-03 16:21:49 +02:00
Gert
ff5658e803 update blueprints 2015-06-01 21:23:53 +02:00
Gert
3d986cdd91 Merge branch 'develop' of github.com:getgrav/grav into feature/blueprint-extend
* 'develop' of github.com:getgrav/grav:
  optimization to image handling supporting url encoded filenames and removed a regex
  Fix for #196 - `+` in an image filename
2015-06-01 11:43:39 +02:00
Andy Miller
32810efcd9 optimization to image handling supporting url encoded filenames and removed a regex 2015-05-27 14:55:50 +02:00
Andy Miller
76b463792e Fix for #196 - + in an image filename 2015-05-26 16:18:59 +03:00
Gert
b4a0a31539 fix pages.process defaults 2015-05-25 17:33:57 +02:00
Gert
acbc7efdc8 remove theme selection from general settings 2015-05-25 17:23:24 +02:00
Gert
8475e0803a Merge branch 'develop' of github.com:getgrav/grav into feature/blueprint-extend
* 'develop' of github.com:getgrav/grav:
  removed unneeded flags from reggae
  fix for dot files
  fix for path detection on windows [fix #194]
  Fix for issue #194 - query string handling
2015-05-25 17:18:41 +02:00
Andy Miller
f779fc57df removed unneeded flags from reggae 2015-05-22 11:43:23 +03:00
Andy Miller
7afef9073c fix for dot files 2015-05-21 22:44:11 +02:00
Gert
370b5db34e remove unexisting option 2015-05-20 22:09:43 +02:00
Gert
6adabb5f71 add ignore field for removing fields on extended blueprints 2015-05-20 21:55:04 +02:00
Gert
df9a0eeab2 set context for default blueprint extends 2015-05-20 21:30:35 +02:00
Gert
e6d58b780e load system blueprints as a fallback for pages 2015-05-20 20:33:40 +02:00
Gert
e4b65d5d7f add check for themes without blueprints/templates folders 2015-05-20 18:18:32 +02:00
Gert
bf61a123cc implement blueprints for the list type 2015-05-20 17:13:22 +02:00
Gert
71f0757015 remove debug line 2015-05-20 16:52:41 +02:00
Gert
f1e57e0e9c modular type needs to have modular/ prefix 2015-05-20 16:45:54 +02:00
Gert
1147516dcc fix for path detection on windows [fix #194] 2015-05-20 16:07:39 +02:00
Andy Miller
3f1661965b Fix for issue #194 - query string handling 2015-05-18 18:54:08 +02:00
Gert
adb0b3ab18 Merge branch 'develop' of github.com:getgrav/grav into feature/blueprint-extend
* 'develop' of github.com:getgrav/grav:
  use PHP_BINARY constant
  fix composer execution for various scenarios
  Remove unnecessary white space
  Move default location to class constant
  Improve composer location identification
  Fix line break in command
  Propagate composer check to all occurences
  Use global composer install when available
2015-05-15 22:59:31 +02:00
Gert
8afad07146 Merge branch 'fix/composer-execution' into develop
* fix/composer-execution:
  use PHP_BINARY constant
  fix composer execution for various scenarios
2015-05-15 21:05:33 +02:00
Gert
81bce07a6e use PHP_BINARY constant 2015-05-15 20:16:42 +02:00
Gert
e883b57ac6 fix composer execution for various scenarios 2015-05-15 19:54:33 +02:00
Gert
921685ff88 fix blueprint type changing when extends 2015-05-15 17:32:21 +02:00
Andy Miller
ae2f95b1ae Merge pull request #192 from eschmar/feature/composer-global
Fix composer location method
2015-05-15 16:44:44 +02:00
Gert
4f77ef26b5 fix default values for process header 2015-05-15 11:40:38 +02:00
Marcel Eschmann
d8df9ffb53 Remove unnecessary white space 2015-05-15 00:20:08 +02:00
Marcel Eschmann
3c51c0acd4 Move default location to class constant 2015-05-15 00:03:48 +02:00
Marcel Eschmann
c085540143 Improve composer location identification 2015-05-14 23:56:55 +02:00
Marcel Eschmann
d239dd56d5 Fix line break in command 2015-05-14 23:32:16 +02:00
Andy Miller
8f9eb3b48b Merge pull request #191 from eschmar/feature/composer-global
Use global composer install when available
2015-05-14 23:15:25 +02:00
Marcel Eschmann
1f906e6a50 Propagate composer check to all occurences 2015-05-14 21:37:47 +02:00
Marcel Eschmann
e0a4efe181 Use global composer install when available 2015-05-14 21:10:05 +02:00
Gert
78e9c8fa1a Merge branch 'develop' of github.com:getgrav/grav into feature/blueprint-extend
* 'develop' of github.com:getgrav/grav:
  add method to set raw markdown on page
  fix modularTypes key properties
2015-05-13 19:41:18 +02:00
Gert
9382dc9c10 add method to set raw markdown on page 2015-05-13 18:52:13 +02:00
Gert
aa85f20aa9 fix modularTypes key properties 2015-05-13 18:50:13 +02:00
Gert
4ae01d48ae fix prefix split on empty prefix 2015-05-13 18:48:52 +02:00
Gert
fe3082c6c9 update taxonomy blueprint 2015-05-13 15:39:37 +02:00
Gert
ab6c257ba6 use new taxonomy field + for all pages 2015-05-12 00:49:31 +02:00
Gert
628ae561d5 more sensible approach to blueprint::extra prefix handling 2015-05-11 12:33:03 +02:00
Gert
56b5a65b24 Merge branch 'develop' of github.com:getgrav/grav into feature/blueprint-extend
* 'develop' of github.com:getgrav/grav:
  fix for alternative media resolutions
  version update
  updated changelog
  composer.par updated to latest
  make sure lookup path does not become empty (root sites)
  ignore .DS_Store in media lookup
  check if medium was created before setting size
  re-add size property to media
2015-05-11 12:29:52 +02:00
Gert
73654a99f9 fix for alternative media resolutions 2015-05-11 11:43:23 +02:00
Andy Miller
ea8add59b1 Merge branch 'release/0.9.27' 2015-05-09 13:14:33 -06:00
Andy Miller
5078ae62c0 Merge branch 'release/0.9.27' into develop 2015-05-09 13:14:33 -06:00
Andy Miller
e026ba32f4 version update 2015-05-09 13:14:23 -06:00
Andy Miller
e9ebe3b533 updated changelog 2015-05-09 12:53:29 -06:00
Andy Miller
cea130700d composer.par updated to latest 2015-05-09 12:36:22 -06:00
Andy Miller
0ae7ebac68 Merge branch 'feature/media-sizes' into develop 2015-05-09 12:25:55 -06:00
Gert
326f1bc890 update item blueprint 2015-05-09 16:47:16 +02:00
Gert
cabec818e2 make sure lookup path does not become empty (root sites) 2015-05-09 16:08:33 +02:00
Gert
ff04b33efd provide default blueprints for common page types 2015-05-09 15:58:17 +02:00
Gert
4f1a71b145 fix extra prefix implementation for extra data of blueprints 2015-05-09 15:58:07 +02:00
Gert
f7f8aa108a allow custom context for extending blueprints 2015-05-09 15:57:55 +02:00
Gert
718d443d52 trim trailing slashes from path during page lookup [fixes #190] 2015-05-09 15:07:15 +02:00
Andy Miller
57c5885216 don't cache twig template when you pass params 2015-05-07 16:01:11 -06:00
Andy Miller
14767a3e11 added twig filters for starts_with and ends_with 2015-05-07 14:13:05 -06:00
Sommerregen
fb31caefef Changed "mergeConfig" head to match previous method signature 2015-05-06 23:01:35 +02:00
Sommerregen
7ceb0dd065 Added params option for mergeConfig method 2015-05-05 21:23:54 +02:00
Andy Miller
b2a78d587c added check to see if on same page 2015-05-05 12:48:15 -06:00
Gert
16c3a3690b ignore .DS_Store in media lookup 2015-05-05 20:33:47 +02:00
Gert
7f8e8f67a5 check if medium was created before setting size 2015-05-05 19:49:14 +02:00
Gert
9792c9a84e re-add size property to media 2015-05-04 17:42:53 +02:00
Gert
13e9e6f5e1 modular page cannot be added to root 2015-05-04 17:12:24 +02:00
Gert
e62133233c remove permission management from user settings 2015-05-04 15:59:06 +02:00
Gert
3ec855e28f fix typo in type 2015-05-04 15:58:39 +02:00
Gert
4b56a05f57 media blueprints 2015-05-04 15:44:25 +02:00
Gert
845da953e1 timestamp blueprints under caching header 2015-05-04 15:39:33 +02:00
Gert
565a76c317 error handler blueprints 2015-05-04 15:37:07 +02:00
Gert
e01a116173 asset timestamps blueprint 2015-05-04 15:36:17 +02:00
Gert
4e07c294c5 gzip compression blueprint 2015-05-04 15:29:46 +02:00
Gert
58bb5a6993 publish_dates blueprint 2015-05-04 15:23:08 +02:00
Gert
2c51dd5fe1 default ordering fix 2015-05-04 15:18:55 +02:00
Gert
ce8513d3ff timezon and param_sep blueprints 2015-05-04 15:18:31 +02:00
Gert
08c4fd02d2 fix markdown extra blueprint 2015-05-04 15:13:29 +02:00
Gert
2e680cd35a email validate 2015-05-04 14:56:34 +02:00
Andy Miller
f12ef84a98 Added a function to parseLinks - used by YouTube plugin as testbed 2015-05-02 14:21:13 -06:00
Andy Miller
0563b2b6e5 fixed missing method name 2015-05-02 11:31:10 -06:00
Andy Miller
c68c39df27 fix for .. page references 2015-05-01 06:23:49 -06:00
Andy Miller
41c00d7fbe fix for absolute url's below this page 2015-05-01 06:23:31 -06:00
Andy Miller
750dfb60dc Fix to properly normalize the font rewrite path 2015-04-30 22:51:39 -06:00
Andy Miller
4305bbabd5 fix for theme name same as base_url and asset pipeline 2015-04-30 18:05:30 -06:00
Andy Miller
ecc12be531 restored gpm install functions 2015-04-30 16:54:23 -06:00
Andy Miller
b65280f3c9 added other close bits back for gzip close connection 2015-04-28 17:34:59 -06:00
Andy Miller
e077b3d04c Merge branch 'feature/gert_gzip' into develop 2015-04-28 17:21:43 -06:00
Andy Miller
91a963f580 tweaks 2015-04-28 17:21:30 -06:00
Gert
8404ba7a09 gzip 2015-04-29 01:07:24 +02:00
Gertt
86b907c86c Merge pull request #186 from getgrav/feature/config-fixes
Feature/config fixes
2015-04-28 23:58:44 +02:00
Gertt
ca899072d4 Merge pull request #185 from getgrav/feature/common_backup
Feature/common backup
2015-04-28 23:49:51 +02:00
Gert
bbfc63e943 ignore all .git folders 2015-04-28 23:35:58 +02:00
Andy Miller
9bce9ce026 removed unused 'use' statements 2015-04-28 11:31:28 -06:00
Andy Miller
3a25f028df Commented these out for now 2015-04-28 11:30:03 -06:00
Andy Miller
491c6d6a1f fixed missing classes 2015-04-28 11:28:08 -06:00
Andy Miller
64bb6ea2ad remove another unused var 2015-04-28 11:26:30 -06:00
Andy Miller
084e59dc90 remove unused var 2015-04-28 11:26:18 -06:00
Andy Miller
f7ea2e95e4 strict comparison 2015-04-28 11:24:46 -06:00
Andy Miller
7acdf231a4 removed php config overrides 2015-04-28 11:21:47 -06:00
Andy Miller
5d38e0fa14 add a menu sample in site.yaml 2015-04-27 21:41:52 -06:00
Gert
e364616730 add server directives to block access to backup folder 2015-04-27 21:53:08 +02:00
Gert
5ccefee288 backup to backup folder 2015-04-27 21:45:42 +02:00
Gert
93f4ad6e5a upload limit setting 2015-04-27 19:29:32 +02:00
Gert
c481acbb71 implement ignore for backups 2015-04-27 16:24:17 +02:00
Gert
bbdb0189f1 use site name for backup archive name 2015-04-27 16:13:48 +02:00
Gert
e1d655a3ac move backup code into Grav\Common 2015-04-27 12:40:30 +02:00
Andy Miller
d849f8a03e Added page level summary header overrides 2015-04-26 18:45:47 -06:00
Andy Miller
67c3d64275 optimize composer 2015-04-26 18:13:53 -06:00
Andy Miller
1546783371 upgrade already has vendor libs 2015-04-26 18:10:56 -06:00
Andy Miller
21cc9f86f3 added new composer update command 2015-04-26 18:00:34 -06:00
Andy Miller
2936d26f8d added --prefer-dist to these commands 2015-04-26 17:37:34 -06:00
Andy Miller
ae453dbc71 restore deprecated for whoops - causing composer issue 2015-04-26 17:21:38 -06:00
Andy Miller
d25699397f add composer update to gpm selfupgrade 2015-04-26 17:21:12 -06:00
Andy Miller
d461fac089 optimize install of vendor libs 2015-04-26 17:20:52 -06:00
Andy Miller
4bda629a6a handle condition of errors resulting in blank page. 2015-04-26 16:58:45 -06:00
Andy Miller
8a2817a305 Added check for curl in GPM 2015-04-26 16:39:58 -06:00
Andy Miller
8887f8862d Improved and cleaned up a couple of folder methods 2015-04-26 15:30:10 -06:00
Andy Miller
4883a408c7 updated composer.phar 2015-04-25 18:41:45 -06:00
Andy Miller
7b75171f79 Merge branch 'release/0.9.26' 2015-04-24 17:27:51 -06:00
Andy Miller
dc42288fa0 Merge branch 'release/0.9.26' into develop 2015-04-24 17:27:51 -06:00
Andy Miller
f576f914ae version update 2015-04-24 17:27:31 -06:00
Andy Miller
88faa5040c fix infinite loop bug in path() 2015-04-24 17:19:28 -06:00
Andy Miller
1e5365ba51 fix for home path not dispatching correctly 2015-04-24 17:13:14 -06:00
Andy Miller
eb93dacba0 Merge branch 'release/0.9.25' 2015-04-24 14:07:01 -06:00
Andy Miller
1e79cbc945 Merge branch 'release/0.9.25' into develop 2015-04-24 14:07:01 -06:00
Andy Miller
d350bd31cb version update 2015-04-24 14:06:44 -06:00
Andy Miller
89b9b4e9b7 Some optimizations and fixes 2015-04-22 14:12:45 -06:00
Andy Miller
9549e5aa4c moved to stable version of toolbox (now in packagist) 2015-04-22 12:31:16 -06:00
Andy Miller
1517d0e40b fix for relative images at root 2015-04-21 19:21:49 -06:00
Andy Miller
f13593aac7 Added E-Tag, Last-Modified, Cache-Control and Page-based Expires 2015-04-21 15:57:17 -06:00
Andy Miller
b8023b2444 Reset default expires time to 0 seconds 2015-04-21 15:39:55 -06:00
Andy Miller
bb49098a05 Merge branch 'feature/modified_timestamp_tweak' into develop 2015-04-21 14:11:32 -06:00
Andy Miller
c368fbcda9 tweaks 2015-04-21 14:08:00 -06:00
Andy Miller
1c1bf86e9a more optimizations.. using regexiterator now 2015-04-21 13:55:53 -06:00
Andy Miller
5f1b190ba9 rework to only check .md files 2015-04-21 13:25:42 -06:00
Andy Miller
0860f53d68 doc tag fix 2015-04-21 12:29:45 -06:00
Andy Miller
1ffd1cb6e7 Fixes for absolute images 2015-04-20 21:40:06 -06:00
Andy Miller
030d230312 Support page defaults merged with system config - #174 2015-04-20 21:38:26 -06:00
Andy Miller
974f9d52a4 Refactored link handling to better absolute handles pages and url elements. Fixes issue #173 2015-04-20 19:05:53 -06:00
Andy Miller
1a238ea1b1 fix for spaces in relative dir 2015-04-20 13:33:54 -06:00
Gert
a049441048 Merge branch 'develop' of github.com:getgrav/grav into develop
* 'develop' of github.com:getgrav/grav:
  Should fix: spaces in webroot for `bin/grav install` #164
2015-04-20 20:54:07 +02:00
Gert
20e771f121 add metod to get all pages 2015-04-20 20:53:39 +02:00
Gert
cff4e225e6 fix bug in collection filtering 2015-04-20 20:53:26 +02:00
Andy Miller
2c69f539ae Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Gert (3) and Kyle Shockey (1)
# Via Gert (1) and others
* 'develop' of https://github.com/getgrav/grav:
  Update README.md
  Merge branch develop into feature/password_improvement
  protect against timing attacks
  fix flaws in authentication
2015-04-20 12:41:37 -06:00
Andy Miller
548081471c Should fix: spaces in webroot for bin/grav install #164 2015-04-20 12:41:26 -06:00
Ryan Matthew Pierson
3688cfa397 Merge pull request #171 from kyleshockey/patch-1
README.md grammar changes
2015-04-17 14:02:20 -05:00
Kyle Shockey
20b2856dee Update README.md
grammar changes
2015-04-17 10:59:03 -07:00
Gert
7e94e46459 use gravtrait in plugins 2015-04-16 17:54:48 +02:00
Gert
f3b4efb661 Make plugins and themes load the merged config from all files 2015-04-16 17:43:03 +02:00
Gert
7947ba2442 fix config reload to actually reload from files 2015-04-16 17:42:29 +02:00
Gert
ef63e993d2 Merge branch 'feature/password_improvements' into develop
* feature/password_improvements:
  Merge branch develop into feature/password_improvement
  protect against timing attacks
  fix flaws in authentication
2015-04-16 12:49:19 +02:00
Gert
29ae5b7aae Merge branch develop into feature/password_improvement 2015-04-16 12:48:37 +02:00
Andy Miller
6baf7e0b35 Merge branch 'release/0.9.24' 2015-04-15 15:55:48 -06:00
Andy Miller
2e7ece17d7 Merge branch 'release/0.9.24' into develop 2015-04-15 15:55:48 -06:00
Andy Miller
2a56f21d13 version update 2015-04-15 15:55:28 -06:00
Andy Miller
d253c3c6c5 updated changelog 2015-04-15 15:54:36 -06:00
Andy Miller
289a838ba1 disable timestamps by default 2015-04-15 11:14:04 -06:00
Andy Miller
f6f3e96106 Merge branch 'develop' of https://github.com/getgrav/grav into develop
* 'develop' of https://github.com/getgrav/grav:
  hide notice about ob_flush()
2015-04-15 09:34:37 -06:00
Andy Miller
7d22305678 hide notice about ob_flush() 2015-04-15 06:44:34 -06:00
Andy Miller
7571d1d562 Merge branch 'feature/media_querystring' into develop 2015-04-14 22:51:44 -06:00
Andy Miller
b4c06f537d added page expires 2015-04-14 22:50:45 -06:00
Andy Miller
830c723bae Revert "added page expires"
This reverts commit f02f3d507dc0959866e6bdef67cc1cf29c0f173e.
2015-04-14 22:50:26 -06:00
Andy Miller
b83ab07374 added page expires 2015-04-14 21:59:31 -06:00
Gert
8200cb9336 querystring and cache timestamp support in media 2015-04-15 03:10:08 +02:00
Andy Miller
b1a38306af Added asset timestamps 2015-04-14 15:46:11 -06:00
Andy Miller
6ec0f4782f Merge pull request #169 from TomasVotruba/patch-1
cs
2015-04-13 11:44:06 -06:00
Tomáš Votruba
d25f9bcf1b cs 2015-04-13 19:41:52 +02:00
Gert
cd3fd5a7b7 protect against timing attacks 2015-04-13 14:44:56 +02:00
Gert
1ab1378259 fix flaws in authentication 2015-04-13 13:10:56 +02:00
Andy Miller
21f87ade2d Merge branch 'feature/improved_download_support' into develop 2015-04-11 18:27:09 -06:00
Andy Miller
8f54e5739f fix for any file with parameters 2015-04-10 14:28:37 -06:00
Andy Miller
21a6594573 Added a onBeforeDownload() event to provide logging/access check, etc. 2015-04-10 14:14:51 -06:00
Andy Miller
01ce80fb1a fixed direct operations on media objects 2015-04-10 13:30:36 -06:00
Andy Miller
174672c411 Support chunked downloads and non-media filetypes 2015-04-10 13:22:10 -06:00
Andy Miller
4785103081 Added download() and getMimeType() static methods 2015-04-10 13:21:53 -06:00
Andy Miller
7030422b11 New baseman option in Uri class 2015-04-10 13:21:23 -06:00
Andy Miller
2a06dc9bea customizable page types 2015-04-10 13:21:03 -06:00
Andy Miller
66927043de Merge branch 'release/0.9.23' 2015-04-09 13:01:01 -06:00
Andy Miller
7d16bafd52 Merge branch 'release/0.9.23' into develop 2015-04-09 13:01:01 -06:00
Andy Miller
ee340e2d6f version update 2015-04-09 13:00:50 -06:00
Andy Miller
66d9fd1a5e Merge branch 'feature/gpm_array_object_fixes' into develop 2015-04-09 12:51:55 -06:00
Andy Miller
7c28de6ae5 fixes for download 2015-04-09 12:41:03 -06:00
Andy Miller
c95f602ea2 fixes for changelog 2015-04-09 12:37:46 -06:00
Gert
6361280d99 remove supressed warnings 2015-04-09 20:13:10 +02:00
Andy Miller
b3a9d7cd41 fixes for broken gpm selfupgrade 2015-04-08 22:29:50 -06:00
Gert
071989c554 Merge branch 'develop' of github.com:getgrav/grav into develop
* 'develop' of github.com:getgrav/grav:
  Fix Folder::getRelativePath() so that it works with backslashes
  version update
2015-04-08 22:56:12 +02:00
Gert
f956d7113f use FilesystemIterator to solve windows path issue more elegantly 2015-04-08 22:55:27 +02:00
Matias Griese
f0472fdd76 Fix Folder::getRelativePath() so that it works with backslashes 2015-04-08 21:37:19 +03:00
Andy Miller
01899676a4 Merge branch 'release/0.9.22' into develop 2015-04-08 12:22:35 -06:00
Andy Miller
b13d572ca8 Merge branch 'release/0.9.22' 2015-04-08 12:22:34 -06:00
Andy Miller
a588e08405 version update 2015-04-08 12:22:23 -06:00
Andy Miller
6c93483220 updated changelog 2015-04-08 11:53:00 -06:00
Gert
733c13102b remove double ; 2015-04-08 11:43:40 -06:00
Gert
688d6fe17a normalize grav path 2015-04-08 11:43:28 -06:00
Gert
25ff1f230f fix mixed slashes in paths 2015-04-08 11:43:20 -06:00
Andy Miller
094b58130a Fix for issue #167 - latest version check out of order 2015-04-08 11:42:23 -06:00
Andy Miller
a18ec00962 Merge branch 'release/0.9.21' 2015-04-07 13:53:44 -06:00
Andy Miller
d9188e76ed Merge branch 'release/0.9.21' into develop 2015-04-07 13:53:44 -06:00
Andy Miller
a04a79af3e version update 2015-04-07 13:53:32 -06:00
Andy Miller
0c84392d0f sizes reference in changelog 2015-04-07 13:18:59 -06:00
Andy Miller
be12f350cb changelog updated 2015-04-07 13:05:21 -06:00
Andy Miller
01c7eadc92 Added new default_image_quality system configuration option 2015-04-07 12:55:29 -06:00
Andy Miller
4b3abc282a PSR Fixes 2015-04-07 12:42:48 -06:00
Andy Miller
81358e9984 Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Gert
# Via Gert
* 'develop' of https://github.com/getgrav/grav:
  fix alternative type not detected anymore
2015-04-07 09:11:09 -06:00
Andy Miller
8179d8eac1 updated composer packages 2015-04-07 09:10:42 -06:00
Gert
c22a2579a9 Merge branch 'develop' of github.com:getgrav/grav into develop
* 'develop' of github.com:getgrav/grav:
  update Console/GPM for refactored Common/GPM
  refactor Common/GPM namespace for more unified approach to installed vs remote packages
  add filter function to iterator
2015-04-06 23:27:19 +02:00
Gert
0a26772e35 fix alternative type not detected anymore 2015-04-06 23:26:53 +02:00
Andy Miller
364fc7afa8 Merge branch 'feature/GPM-unify' into develop 2015-04-06 10:27:16 -06:00
Gert
82bd54eb0b update Console/GPM for refactored Common/GPM 2015-04-04 14:02:28 +02:00
Gert
d92d9bafc6 refactor Common/GPM namespace for more unified approach to installed vs remote packages 2015-04-04 14:01:46 +02:00
Gert
9c541ee20b add filter function to iterator 2015-04-04 14:00:52 +02:00
Gert
105dc34b2a don't scale @1x images, use them as base 2015-04-03 11:30:35 +02:00
Andy Miller
0d8b46a157 fixed image element name 2015-04-01 17:27:51 -06:00
Gert
6142a12f48 Merge branch 'feature-multimedia' into develop
* feature-multimedia:
  reset on construct
  thumbnail selection fixes
  remove debugger line
2015-04-01 23:33:24 +02:00
Gert
1bda3eb1e3 Merge branch 'develop' of github.com:getgrav/grav into feature-multimedia
* 'develop' of github.com:getgrav/grav:
2015-04-01 23:32:40 +02:00
Gert
96b2b327b2 reset on construct 2015-04-01 16:51:24 +02:00
Gert
e014b12626 thumbnail selection fixes 2015-04-01 16:17:10 +02:00
Gert
d473f72edd remove debugger line 2015-04-01 16:14:18 +02:00
Andy Miller
7139425812 Merge pull request #161 from Gertt/feature-multimedia
Media overhaul
2015-03-31 15:00:49 -06:00
Gert
f5722d7baa Merge branch 'develop' of github.com:getgrav/grav into feature-multimedia
* 'develop' of github.com:getgrav/grav:
  switched to && operator
  Moved default image quality to defines.php
  Missing 'quality' in valid image functions
  updated version
  updated version
  updated changelog
  Fix for issue #158 - load order with debugger on
  Added support for external URL in directs
  more description for separator
  Serve images as static files
  Corrected HTML output of links with empty HTML anchors
  Changed Twig Link Regex which fixes #149 [Markdown Doesn't Handle [words](#)]

Conflicts:
	system/src/Grav/Common/Page/Medium.php
2015-03-31 22:58:24 +02:00
Gert
467eb00f0f rename factory to mediumfactory 2015-03-31 22:52:41 +02:00
Gert
0ce3646977 use style for static resize 2015-03-31 22:50:55 +02:00
Gert
53dd6c0860 multimedia refactor finishing touches 2015-03-31 21:23:14 +02:00
Andy Miller
e4a130c919 switched to && operator 2015-03-28 14:52:35 -06:00
Andy Miller
0d9ddb92d5 Moved default image quality to defines.php 2015-03-26 11:32:17 -06:00
Andy Miller
68a561d4fb Missing 'quality' in valid image functions 2015-03-26 11:24:22 -06:00
Andy Miller
5e651dd0e5 Merge branch 'release/0.9.20' 2015-03-24 17:31:39 -06:00
Andy Miller
1bb2965916 Merge tag '0.9.20' into develop
Release v0.9.20
2015-03-24 17:31:39 -06:00
Andy Miller
4ea650fc6d updated version 2015-03-24 17:31:24 -06:00
Andy Miller
501b38c4ba updated version 2015-03-24 17:30:30 -06:00
Andy Miller
ede958bd61 updated changelog 2015-03-24 17:29:44 -06:00
Andy Miller
f3d099e655 Fix for issue #158 - load order with debugger on 2015-03-19 23:29:45 -06:00
Andy Miller
db5c3ea400 Added support for external URL in directs 2015-03-16 21:10:31 -06:00
Andy Miller
504f57930a Merge pull request #151 from rzimin/patch-1
Serve images as static files
2015-03-16 18:59:27 -06:00
Andy Miller
02b1b2cf9d Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Sommerregen
# Via Andy Miller (1) and Sommerregen (1)
* 'develop' of https://github.com/getgrav/grav:
  Corrected HTML output of links with empty HTML anchors
  Changed Twig Link Regex which fixes #149 [Markdown Doesn't Handle [words](#)]
2015-03-12 17:09:15 -06:00
Andy Miller
99dbb3225b more description for separator 2015-03-12 17:08:33 -06:00
rzimin
08a8d69be2 Serve images as static files
Ensure images are served as static files when using Nginx
2015-03-12 13:34:46 +03:00
Andy Miller
a029f89ad2 Merge pull request #150 from Sommerregen/bugfix/parsedown-handle-empty-html-anchors
Changed Twig Link Regex which fixes #149 [Markdown Doesn't Handle [words](#)
2015-03-08 19:17:16 -06:00
Sommerregen
ed02fed866 Corrected HTML output of links with empty HTML anchors 2015-03-08 20:01:30 +01:00
Sommerregen
06de6c8e17 Changed Twig Link Regex which fixes #149 [Markdown Doesn't Handle [words](#)] 2015-03-08 19:24:48 +01:00
Gert
9ddfcd2154 Merge branch 'develop' of github.com:getgrav/grav into feature-multimedia
* 'develop' of github.com:getgrav/grav:
  updated changelog
  Added async and defer loading of JavaScript files
  Updated web.config  - Assets accesible
  fixed date
  version update
  removed some unused vars
  Removed some duplicate code via a trait
  Broke out iterators into their own class files
  only use files for last modified, so children don't affect the modified time of their parent page
  prevent a page from taken it's parent into account when detecting modified time
  Fixed `nth()` and added `first()` `last()` and `reverse()` methods
  Revert "Replace constant with streams. (need for multisite)."
  Replace constant with streams. (need for multisite).
2015-03-02 22:52:18 +01:00
Andy Miller
217e5e5a2c Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Vivalldi
# Via Andy Miller (1) and Vivalldi (1)
* 'develop' of https://github.com/getgrav/grav:
  Updated web.config  - Assets accesible
2015-03-02 11:09:54 -07:00
Andy Miller
272bf357d4 updated changelog 2015-03-02 11:06:14 -07:00
Andy Miller
9a5d14aa13 Added async and defer loading of JavaScript files 2015-03-02 11:03:21 -07:00
Andy Miller
2b70b2ad4f Merge pull request #148 from Vivalldi/patch-1
Updated web.config  - Assets accesible
2015-03-02 10:33:10 -07:00
Vivalldi
9323385b25 Updated web.config - Assets accesible
The system/assets folder is accessible except for .txt .md .html .yaml .php .twig .sh .bat files.
2015-03-02 12:30:46 -05:00
Andy Miller
fe90204772 Merge branch 'release/0.9.19' 2015-03-01 15:30:15 -07:00
Andy Miller
1b66e3d2a1 fixed date 2015-03-01 14:48:13 -07:00
Andy Miller
a2e1b9e100 Merge branch 'release/0.9.19' 2015-02-28 17:53:09 -07:00
Andy Miller
74ab81b524 Merge branch 'release/0.9.19' into develop 2015-02-28 17:53:09 -07:00
Andy Miller
01be2df935 version update 2015-02-28 17:52:55 -07:00
Andy Miller
62e5ea3bbd removed some unused vars 2015-02-28 14:14:20 -07:00
Andy Miller
b8c274b7b8 Removed some duplicate code via a trait 2015-02-28 14:13:59 -07:00
Andy Miller
e154b13b6e Broke out iterators into their own class files 2015-02-28 13:56:53 -07:00
Andy Miller
0f312a3c43 Merge pull request #146 from Gertt/develop
fix for last modified time detection of page
2015-02-27 16:17:48 -07:00
Gert
d8823a6b3a only use files for last modified, so children don't affect the modified time of their parent page 2015-02-27 23:29:23 +01:00
Gert
73d5f9da90 prevent a page from taken it's parent into account when detecting modified time 2015-02-27 22:16:59 +01:00
Andy Miller
7707b042e5 Fixed nth() and added first() last() and reverse() methods 2015-02-26 19:28:34 -07:00
Gert
ff95a116c2 Merge branch 'develop' of github.com:getgrav/grav into feature-multimedia
* 'develop' of github.com:getgrav/grav: (21 commits)
  Added initial named-assets implementation
  version update
  Update README.md
  Added optional deep option. defaults to false
  Added more flexible param separator option
  PSR camelCase fix
  missed a logical operator
  Fix camelCase method
  removed function in loop
  removed some commented out code
  removed unused vars
  Removed unused `use` statements
  rename fixme to todo
  remove fixme
  Object type hints
  strict boolean compare
  PSR fixes
  Strict boolean compares
  Some insight fixes
  Added new random string static and twig function
  ...
2015-02-24 21:40:59 +01:00
Andy Miller
2fe6dda365 Added initial named-assets implementation 2015-02-23 16:30:52 -07:00
Gert
f30a3c137e define new types 2015-02-22 00:01:55 +01:00
Gert
a5d31e7187 allow duplicated actions and follow medium on action 2015-02-22 00:01:44 +01:00
Gert
73c42313fa media overhaul 2015-02-22 00:00:52 +01:00
Andy Miller
686ba8a3f6 Merge branch 'release/0.9.18' into develop 2015-02-19 16:59:41 -07:00
Andy Miller
3397d5d2b7 Merge branch 'release/0.9.18' 2015-02-19 16:59:40 -07:00
Andy Miller
9ab3524fc5 version update 2015-02-19 16:59:20 -07:00
Andy Miller
3f10fa1b4c Update README.md 2015-02-18 22:21:38 -07:00
Andy Miller
6811fbea3d Added optional deep option. defaults to false 2015-02-18 22:04:02 -07:00
Andy Miller
3e245ef686 Merge pull request #144 from Sommerregen/bugfix/get-nested-default-plugin-configurations
Fix to merge nested page options with default plugin configurations
2015-02-18 21:59:49 -07:00
Andy Miller
28cff4e1da Added more flexible param separator option 2015-02-18 15:51:27 -07:00
Andy Miller
2bf67e482d PSR camelCase fix 2015-02-18 13:17:16 -07:00
Andy Miller
3976e4ce23 missed a logical operator 2015-02-18 13:12:57 -07:00
Andy Miller
a1ab94ffdd Fix camelCase method 2015-02-18 12:54:01 -07:00
Andy Miller
d6bed5441d removed function in loop 2015-02-18 12:51:58 -07:00
Andy Miller
e505c409ac removed some commented out code 2015-02-18 12:50:33 -07:00
Andy Miller
409742c078 removed unused vars 2015-02-18 12:48:01 -07:00
Andy Miller
6bd76028ce Removed unused use statements 2015-02-18 12:47:45 -07:00
Andy Miller
87dc53912b rename fixme to todo 2015-02-18 12:37:53 -07:00
Andy Miller
83d606c34a remove fixme 2015-02-18 12:37:39 -07:00
Andy Miller
1f906326e7 Object type hints 2015-02-18 12:37:19 -07:00
Andy Miller
ec67bf4c5b strict boolean compare 2015-02-18 12:37:00 -07:00
Andy Miller
127fe7fa2a PSR fixes 2015-02-18 12:36:30 -07:00
Andy Miller
e0de6f8b5f Strict boolean compares 2015-02-18 12:36:19 -07:00
Andy Miller
e81e35b7c2 Some insight fixes 2015-02-18 12:24:35 -07:00
Andy Miller
9bc365fe9e Added new random string static and twig function 2015-02-17 15:44:34 -07:00
Gert
21772c5481 Merge branch 'develop' of github.com:getgrav/grav into feature-multimedia
* 'develop' of github.com:getgrav/grav: (31 commits)
  Some performance optimizations for folder/file checking routines
  now checks for symlink availability before giving that option
  updated bundled composer package
  Backup pages folder if it exits in demo copy
  Fix rcopy reference
  Fix for issue #140 - plugin/theme install status not working on windows
  added a space after prompt
  Look for `_demo` content in packages and prompt to install it
  Use rcopy from Utils class
  Set package_type for unknown packages based on best guess
  Added recursive folder copy
  Don't critically fail, only log when plugin has config but is missing
  added repo URL to output
  text addition
  some corner case fixes
  Added symlink + git clone installation methods
  beginning of dependency work
  move timezone setting to after Config's `init()` method
  added timezone override support
  added a twig processTemplate() method
  ...

Conflicts:
	system/src/Grav/Common/Markdown/ParsedownGravTrait.php
	system/src/Grav/Common/Page/Media.php
	system/src/Grav/Common/Page/Medium.php
2015-02-17 20:41:49 +01:00
Andy Miller
7b32cbe2e1 Some performance optimizations for folder/file checking routines 2015-02-17 11:22:35 -07:00
Andy Miller
04a2f618bd now checks for symlink availability before giving that option 2015-02-16 18:48:52 -07:00
Andy Miller
73a104000a updated bundled composer package 2015-02-16 18:28:52 -07:00
Andy Miller
b8cb788324 Backup pages folder if it exits in demo copy 2015-02-16 14:46:05 -07:00
Andy Miller
690bb8a8be Fix rcopy reference 2015-02-16 14:45:21 -07:00
Andy Miller
26b0b02de2 Fix for issue #140 - plugin/theme install status not working on windows 2015-02-16 10:14:14 -07:00
Andy Miller
e5348ec8f1 added a space after prompt 2015-02-15 16:16:27 -07:00
Andy Miller
5e22eee1a8 Look for _demo content in packages and prompt to install it 2015-02-15 16:10:00 -07:00
Andy Miller
534bb57d3f Use rcopy from Utils class 2015-02-15 16:09:16 -07:00
Andy Miller
f8c203c033 Set package_type for unknown packages based on best guess 2015-02-15 16:08:53 -07:00
Andy Miller
300155e82e Added recursive folder copy 2015-02-15 16:08:24 -07:00
Andy Miller
3117a214d4 Merge branch 'feature/gpm_dependency' into develop 2015-02-15 15:30:25 -07:00
Andy Miller
9959868022 Don't critically fail, only log when plugin has config but is missing 2015-02-15 15:24:07 -07:00
Andy Miller
9248c5b709 added repo URL to output 2015-02-15 14:21:17 -07:00
Andy Miller
85fb5bccf3 text addition 2015-02-15 14:07:40 -07:00
Andy Miller
bd595ca9f6 some corner case fixes 2015-02-15 14:04:50 -07:00
Andy Miller
ace8823bd6 Added symlink + git clone installation methods 2015-02-15 13:37:51 -07:00
Sommerregen
5051b15145 Fix to merge nested page options with default plugin configurations 2015-02-15 21:20:20 +01:00
Andy Miller
1c1f2c268a beginning of dependency work 2015-02-14 22:33:50 -07:00
Andy Miller
545c76088c move timezone setting to after Config's init() method 2015-02-14 13:07:45 -07:00
Andy Miller
b418a7fd1e added timezone override support 2015-02-14 10:38:01 -07:00
Andy Miller
2938848df1 added a twig processTemplate() method 2015-02-13 11:35:21 -07:00
Andy Miller
17172f8920 added a contains() static method 2015-02-13 11:35:04 -07:00
Andy Miller
aeb237633e Merge pull request #139 from Zifius/patch-1
Update formatting to have blocks nesting less confusing
2015-02-10 17:01:31 -07:00
Andy Miller
d8a29dd639 Moved parsedown config into trait 2015-02-09 18:56:33 -07:00
Andy Miller
5c139e4b3c added a new markdown twig filter 2015-02-09 18:56:12 -07:00
Andy Miller
d69a0a9b06 minor naming updates 2015-02-09 16:35:02 -07:00
Andy Miller
07ce9c83ac changed getGrav() to static 2015-02-08 11:42:08 -07:00
Andy Miller
1d3559f0db Added a new filter to convert relative to absolute URLs 2015-02-07 12:21:40 -07:00
Andy Miller
be92a1da97 Merge pull request #141 from Gertt/patch-1
fix page ids not picking up folder-only pages
2015-02-07 09:56:54 -07:00
Gertt
97b430a888 Update Page.php 2015-02-07 17:55:46 +01:00
Gertt
b696e0d790 fix page ids not picking up folder-only pages 2015-02-07 17:47:58 +01:00
Gert
5b08a8605e various bugfixes, thumbnail support for files 2015-02-07 00:05:40 +01:00
Andy Miller
ab358dd820 Merge branch 'release/0.9.17' 2015-02-05 20:59:46 -07:00
Andy Miller
573b3227c7 Merge branch 'release/0.9.17' into develop 2015-02-05 20:59:46 -07:00
Andy Miller
50785c2434 version update 2015-02-05 20:59:23 -07:00
Andy Miller
fb9705809d HHVM fixes due to issues with traits and static variables #138 2015-02-05 15:07:31 -07:00
Alexander Turiak
1aeac01284 Update formatting to have blocks nesting less confusing 2015-02-05 12:43:49 +02:00
Gert
0cc35b56e5 Merge branch 'develop' of github.com:getgrav/grav into feature-multimedia
* 'develop' of github.com:getgrav/grav:
  Utilize new summary.delimiter setting rather than constant
  PSR fixes
  fix for markdown adding HTML tags into inline JS/CSS
  moved summary delimiter into site config
  fix for twig set capturing
  Moved to camels for plugins+themes as optional class naming type
  Added summary option
2015-02-04 22:39:47 +01:00
Gert
1423375312 enable markdown for any medium object and further cleanup 2015-02-04 22:39:34 +01:00
Gert
640ba16f8b fix alternatives detect 2015-02-04 22:38:24 +01:00
Andy Miller
d4e17442b2 Merge branch 'develop' of https://github.com/getgrav/grav into develop
# By Sommerregen
# Via Andy Miller (1) and Sommerregen (1)
* 'develop' of https://github.com/getgrav/grav:
  Added summary option
2015-02-02 17:27:04 -07:00
Andy Miller
eb4eafd915 Utilize new summary.delimiter setting rather than constant 2015-02-02 17:25:51 -07:00
Andy Miller
dc65475723 PSR fixes 2015-02-02 17:25:24 -07:00
Andy Miller
3f33e97f0c fix for markdown adding HTML tags into inline JS/CSS 2015-02-02 17:25:14 -07:00
Andy Miller
02508933d7 moved summary delimiter into site config 2015-02-02 17:24:41 -07:00
Andy Miller
89ebf2b011 Merge pull request #136 from Sommerregen/feature/added-summary-option
Added summary option
2015-02-02 17:23:00 -07:00
Andy Miller
c747c4baf7 fix for twig set capturing 2015-02-02 16:27:36 -07:00
Andy Miller
a3c848e4e2 Moved to camels for plugins+themes as optional class naming type 2015-02-02 13:08:56 -07:00
Gert
345d61f04f Merge branch 'develop' of github.com:getgrav/grav into feature-multimedia
* 'develop' of github.com:getgrav/grav:
  per-page debug setting not working as intended. Changing approaches...
  fix for using just defaults
  version update
  Added a page override support to media debug
  Some performance optimizations
  some cleanup refactoring
  PSR fixes
  Added 'enabled' option for summary and fixed query support in assets
  Added merge config and disable function in "Plugin.php"
2015-02-02 20:58:29 +01:00
Andy Miller
f0585ddb4e per-page debug setting not working as intended. Changing approaches... 2015-02-02 09:59:54 -07:00
Sommerregen
a6790cace3 Added summary option 2015-02-01 18:15:24 +01:00
Andy Miller
f244fc93c8 fix for using just defaults 2015-01-30 19:19:49 -07:00
Andy Miller
846a0baed8 Merge branch 'release/0.9.16' 2015-01-30 18:13:37 -07:00
Andy Miller
26ebb8fa6d Merge branch 'release/0.9.16' into develop 2015-01-30 18:13:37 -07:00
Andy Miller
cb8ea7780f version update 2015-01-30 18:13:25 -07:00
Andy Miller
5400bd3951 Added a page override support to media debug 2015-01-30 17:38:43 -07:00
Andy Miller
03521cd3f6 Some performance optimizations 2015-01-29 17:22:55 -07:00
Andy Miller
1eb0e37214 Merge pull request #133 from Sommerregen/feature/merge-config-and-disable-function-in-plugin.php
Added merge config and disable function in "Plugin.php"
2015-01-29 13:02:23 -07:00
Andy Miller
3e769618ec some cleanup refactoring 2015-01-29 10:40:30 -07:00
Andy Miller
9319d5c0aa PSR fixes 2015-01-29 10:27:10 -07:00
Andy Miller
eb94940df6 Merge pull request #132 from Sommerregen/feature/summary-options-and-query-support-in-assets
Added 'enabled' option for summary and fixed query support in assets
2015-01-29 10:23:59 -07:00
Sommerregen
a4c8c53939 Added 'enabled' option for summary and fixed query support in assets 2015-01-29 16:57:46 +01:00
Sommerregen
567dd0d2c6 Added merge config and disable function in "Plugin.php" 2015-01-29 16:51:17 +01:00
Gert
6f06e0c424 fix var name 2015-01-29 05:04:38 +01:00
Gert
8dfb9d08c4 refactor medium and basic implementation of video 2015-01-29 05:01:31 +01:00
Andy Miller
25c44816c0 moved cached images from image:// to cache://images 2015-01-28 10:01:20 -07:00
Andy Miller
1a692b348e some minor cleanup 2015-01-27 21:27:42 -07:00
Andy Miller
17ed48e677 PSR Fixes 2015-01-27 17:37:58 -07:00
Andy Miller
685033bb02 Went back to using regular image:// stream 2015-01-27 17:31:41 -07:00
Andy Miller
b86c982ba1 Updated to use new image cache stream and add width/height back to link 2015-01-27 17:24:21 -07:00
Andy Miller
a0148f36fd added image cache stream 2015-01-27 17:22:06 -07:00
Andy Miller
b88de0cd3b Merge pull request #131 from namaless/bugfix/medium_fix_locator_unused_vars_phpdoc
Bug fixes phpdoc/missed vars/locator.
2015-01-27 17:00:11 -07:00
Pereira Ricardo
3207efd383 Add again the width and height params for lightbox method. 2015-01-28 00:55:12 +01:00
Pereira Ricardo
31dd235b50 Add missed streams for images and system folders. Fixed problem with images link when you use user/images folder instead /images folder. 2015-01-28 00:39:24 +01:00
Pereira Ricardo
bb1cdb17f5 Typo fix. 2015-01-27 23:40:41 +01:00
Pereira Ricardo
f35287cb7a - Removed unused variables.
- Add missed phpdoc params.
- Update constants with locator.
2015-01-27 23:36:43 +01:00
Andy Miller
391f7d3be4 Merge pull request #130 from Gertt/feature-responsive-images
Feature responsive images
2015-01-27 13:35:32 -07:00
Gert
76d0583b00 prevent double overlays on scaled media generation 2015-01-27 21:29:14 +01:00
Gert
7857568c92 update images 2015-01-27 21:28:59 +01:00
Gert
bfe94bc5d0 add option to show debug overlay on images 2015-01-27 21:18:16 +01:00
Gert
cf3bcf6d7f fix double base url 2015-01-26 23:21:47 +01:00
Gert
d2aa775ee8 make cache names of generated images more informative by adding correct @#x suffix 2015-01-26 21:45:10 +01:00
Gert
ce800ccd92 fix lightbox issue 2015-01-26 21:31:47 +01:00
Gert
2c57453608 don't output srcset when only one image 2015-01-26 21:30:17 +01:00
Gert
03f729602b refactor the way parsedown gets image data, this also fixes lightbox operations for markdown 2015-01-26 18:57:54 +01:00
Andy Miller
21f064b1d0 updated parsedown extra lib 2015-01-25 22:12:46 -07:00
Gert
b7f6b827e4 fix lightbox for responsive images 2015-01-26 03:18:17 +01:00
Gert
a33e2ed226 fix empty alternatives bug 2015-01-26 02:45:14 +01:00
Gert
ef7806b509 forgot to save after fixing merge conflict 2015-01-26 02:43:52 +01:00
Gert
e268cda1b5 Merge branch 'develop' of github.com:getgrav/grav into feature-responsive-images
* 'develop' of github.com:getgrav/grav:
  fix for #129 markdown images not found when base_url == '/' on homepage

Conflicts:
	system/src/Grav/Common/Markdown/ParsedownGravTrait.php
2015-01-26 02:42:48 +01:00
Gert
3ae5e3c569 refactor and create missing versions of medium 2015-01-26 02:40:34 +01:00
Andy Miller
304c7519d1 fix for #129 markdown images not found when base_url == '/' on homepage 2015-01-25 18:33:24 -07:00
Gert
a4a8a422a5 fix for base url error 2015-01-25 23:48:58 +01:00
Gert
6700003dd2 generate @1x image when user provides only @2x 2015-01-25 23:11:23 +01:00
Gert
93f99fcff1 refactor image parsedown and correct use of reset 2015-01-25 23:07:24 +01:00
Gert
a03f54902a make sure param is int 2015-01-25 23:06:47 +01:00
Gert
4112d363dd get filters working on srcset 2015-01-25 20:40:29 +01:00
Gert
3f1c6dd662 implement srcset on all output functions and add data-attribute for lightbox plugins to use 2015-01-25 19:25:47 +01:00
Gert
89b2da636f Merge branch 'develop' of github.com:getgrav/grav into feature-responsive-images
* 'develop' of github.com:getgrav/grav:
  Added logic so markdown link will work with other non-self pages
  fixed bug with image dispatch for traditionally _non-routable_ pages, such as `image/foo.jpg`
2015-01-25 15:47:29 +01:00
Gert
c010ae3a97 switch to new srcset spec 2015-01-25 15:47:23 +01:00
Andy Miller
f619c8f49f Added logic so markdown link will work with other non-self pages 2015-01-24 17:28:20 -07:00
Andy Miller
a27a1a3fd1 fixed bug with image dispatch for traditionally _non-routable_ pages, such as image/foo.jpg 2015-01-24 16:59:20 -07:00
Gert
f7470ace97 basic srcset implementation 2015-01-24 17:36:49 +01:00
Andy Miller
cb6b362e20 Merge branch 'release/0.9.15' 2015-01-23 17:22:57 -07:00
Andy Miller
c6200f386a Merge branch 'release/0.9.15' into develop 2015-01-23 17:22:57 -07:00
Andy Miller
60423e4a28 version update 2015-01-23 17:22:41 -07:00
Andy Miller
f40410816e updated changelog 2015-01-23 17:21:58 -07:00
Andy Miller
63a2ffc0b1 fix for markdown images/links in pages with slug override 2015-01-23 17:09:37 -07:00
Andy Miller
fad428b94b Fix for broken image last-ditch-effort mechanism 2015-01-23 16:44:39 -07:00
Andy Miller
8b251ca350 Part 2 of greedy fix 2015-01-23 16:37:20 -07:00
Andy Miller
05bd5cb964 Fix for aggressive and greedy regex stripping numbers after / when should only strip order 2015-01-23 16:17:02 -07:00
Andy Miller
76a6b77065 fixed typo in mime types 2015-01-23 15:57:54 -07:00
Andy Miller
5049086062 Fix to pickup deprecated markdown_extra system setting. 2015-01-23 14:46:34 -07:00
Andy Miller
f04dece44c Merge branch 'release/0.9.14' 2015-01-23 13:08:47 -07:00
Andy Miller
621f38d856 Merge branch 'release/0.9.14' into develop 2015-01-23 13:08:47 -07:00
Andy Miller
ccc65aa420 version update 2015-01-23 13:08:35 -07:00
Andy Miller
7ddf35d3fa updated changelog 2015-01-23 12:34:18 -07:00
Andy Miller
689c65c5e4 bumped parsedown extra lib version 2015-01-22 17:47:05 -07:00
Andy Miller
e571f3bcfd Added some missing clean statements 2015-01-22 17:44:32 -07:00
Andy Miller
adf80c3f87 fix for change in slash trimming in Resource Locator 2015-01-22 16:50:35 -07:00
Andy Miller
fed9862e44 set auto_link_breaks to false by default 2015-01-21 22:07:37 -07:00
Andy Miller
7bc924b6d6 Added ability to configure markdown options in configuration and in page 2015-01-21 21:58:51 -07:00
Andy Miller
c881624801 Added ability to configure the special characters that are automatically converted in Parsedown 2015-01-21 21:57:55 -07:00
Andy Miller
3c63993db8 Some pretty serious page refactoring to clean up a rather unreadable chunk of code in content() method 2015-01-21 18:21:39 -07:00
Andy Miller
ac26c3ab4e added ability to set metadata 2015-01-21 15:36:05 -07:00
Andy Miller
2dedd9d1a0 Refactored Parsedown override class names 2015-01-21 13:23:53 -07:00
Andy Miller
c1ef8b6399 ENT_QUOTES works better than ENT_HTML5, so changing 2015-01-21 13:23:15 -07:00
Andy Miller
c2f2f7b009 fix for quotes in metadata 2015-01-21 12:22:29 -07:00
Andy Miller
c2c5afbb05 Added new onPageContentRaw() event that processes before markdown 2015-01-21 11:14:52 -07:00
Andy Miller
19eae2300f Merge branch 'feature/process_ordering' into develop 2015-01-20 18:08:41 -07:00
Andy Miller
0ddd2941e9 Add event when caching markdown content too 2015-01-20 18:08:14 -07:00
Andy Miller
6863d70f0b Merge pull request #126 from namaless/develop
Update User.php
2015-01-20 16:27:23 -07:00
Pereira Ricardo
9f782a4aed Update User.php 2015-01-20 21:11:13 +01:00
Matias Griese
bc844ba0d3 Merge pull request #125 from getgrav/revert-124-hotfix/user_class_streams
Revert "Replace constant with streams. (need for multisite)."
2015-01-20 19:43:09 +02:00
Andy Miller
af97876794 some initial refactoring 2015-01-20 10:42:13 -07:00
Matias Griese
92f319c188 Revert "Replace constant with streams. (need for multisite)." 2015-01-20 19:36:38 +02:00
Matias Griese
010872fc1e Merge pull request #124 from namaless/hotfix/user_class_streams
Replace constant with streams. (need for multisite).
2015-01-20 19:35:40 +02:00
Matias Griese
259d8356b0 Update url() method in twig 2015-01-20 19:23:05 +02:00
Andy Miller
4cd4bb4202 fix for non-url valid twig code in Markdown Link/Image 2015-01-20 09:35:30 -07:00
Pereira Ricardo
fdb19b1a90 Replace constant with streams. (need for multisite). 2015-01-20 11:07:37 +01:00
Andy Miller
c9385632a9 cleanup 2015-01-19 15:32:57 -07:00
Andy Miller
0c90b5c7b2 assets typo 2015-01-19 15:32:45 -07:00
Andy Miller
ac4650632e Merge branch 'rindeal-feature/introduce_phpunit' into develop 2015-01-19 15:21:55 -07:00
Andy Miller
aae644ca33 Merge branch 'feature/introduce_phpunit' of https://github.com/rindeal/grav into rindeal-feature/introduce_phpunit
Conflicts:
	composer.json
2015-01-19 15:21:10 -07:00
Andy Miller
6aabb83204 minor perf optimizations 2015-01-19 15:16:36 -07:00
Andy Miller
593f7bfe27 Merge pull request #115 from namaless/feature/inline_assets_priority
Add inline assets priority
2015-01-19 15:12:05 -07:00
Andy Miller
77d1bf5ca8 Merge pull request #118 from namaless/fix/typo
Fix small spellchecker
2015-01-19 15:06:39 -07:00
Andy Miller
bc8f742565 broke out resource into a variable 2015-01-19 15:02:33 -07:00
Andy Miller
632c48e1e6 Updated parsedown extra lib 2015-01-19 14:36:05 -07:00
Andy Miller
42b2f99c6d RE PR: #119 - Refactored a bit to be better optimized and also take into account $pages->base() 2015-01-19 14:35:52 -07:00
Pereira Ricardo
e518e3ca92 Fix small spellchecker 2015-01-18 03:22:51 +01:00
Pereira Ricardo
e013cf70db Add inline assets priority
Use md5 from content for discard multiple iterance.
2015-01-18 03:14:09 +01:00
Djamil Legato
bdf80fd920 Cherry-pick of #112 2015-01-16 14:44:25 -08:00
Andy Miller
ce282c47cf updated changelog 2015-01-16 13:39:06 -07:00
Andy Miller
23a25b8df2 Added a gzip param - default to off 2015-01-16 13:38:56 -07:00
Andy Miller
8363da35c6 updated parsedown-extra 2015-01-16 13:38:43 -07:00
Andy Miller
ff973a0634 Added Gzip support and fix for php-fpm connections 2015-01-16 13:38:30 -07:00
Andy Miller
2b504149f8 updates for changelog 2015-01-16 11:14:34 -07:00
Andy Miller
031df8de2c Added optional all param to pages.find() 2015-01-16 11:14:18 -07:00
Andy Miller
229d3acc99 moved rewrite base before exploits in .htaccess 2015-01-16 11:13:47 -07:00
Andy Miller
195bdd71a2 Updated Parsedown + ParsedownExtra to latest stable version 2015-01-12 17:29:44 -07:00
Andy Miller
f6da7c9344 Fixes for most recent Parsedown + ParsedownExtra 2015-01-12 17:29:15 -07:00
Andy Miller
50ebdeddad Revert "forgot to change this one back"
This reverts commit 4f4974aae4.
2015-01-11 16:00:14 -07:00
Andy Miller
4f4974aae4 forgot to change this one back 2015-01-11 15:57:55 -07:00
Andy Miller
977b7d2936 Force modular pages to be non-visible in menus 2015-01-11 15:23:22 -07:00
Andy Miller
c4797a2d6f Rolled back previous MarkdownTrait until next Parsedown release 2015-01-11 12:14:43 -07:00
Andy Miller
e293050ea1 Rolled back Parsedown to 1.1.4 and ParsedownExtra to 0.2.6 until next Parsedown Release 2015-01-11 12:14:22 -07:00
Andy Miller
4c2ed0ee3d Updated included composer package 2015-01-11 11:54:55 -07:00
Andy Miller
c550faa843 fix for published setting having precedents over publish_date and unpublish_date 2015-01-11 11:54:40 -07:00
Andy Miller
e433150a5a Use page:// stream rather than PAGES_DIR constant 2015-01-10 16:07:33 -07:00
Andy Miller
ceb3626c94 More fixes for markdown images 2015-01-10 15:58:44 -07:00
Andy Miller
2d33f745ba fix for bug cause by commit: 6e39107d45 2015-01-10 15:58:24 -07:00
Andy Miller
4cf0a71a45 fixes for Parsedown update 2015-01-10 14:31:03 -07:00
Matias Griese
7f526cea76 Fix fixed path in theme_url Twig variable 2015-01-10 17:55:28 +02:00
Matias Griese
6e39107d45 Add support for path prefixes like /en for multisite/multilanguage support 2015-01-10 17:54:09 +02:00
Matias Griese
9ddfced969 Fix a bug with missing streams when configuration was not loaded from cache 2015-01-10 14:23:16 +02:00
Matias Griese
dde6b2cd8b Add support for multiple configurations by setup.php 2015-01-10 11:55:57 +02:00
Matias Griese
a9894902be Fix RewriteBase getting run only after exploit checks in .htaccess 2015-01-10 11:55:01 +02:00
Andy Miller
f48c8fb50a Merge branch 'release/0.9.13' into develop 2015-01-09 15:44:07 -07:00
Jan Chren
260f200d6f fixed problems with multiloading of includes
https://github.com/sebastianbergmann/phpunit/issues/314
2014-09-14 23:08:56 +02:00
Jan Chren
2d95b3bb09 PHPUnit testing introduced 2014-09-14 22:44:59 +02:00
153 changed files with 10927 additions and 2855 deletions

View File

@@ -2,15 +2,15 @@ git:
problems:
url: https://github.com/getgrav/grav-plugin-problems
path: user/plugins/problems
branch: develop
branch: master
error:
url: https://github.com/getgrav/grav-plugin-error
path: user/plugins/error
branch: develop
branch: master
antimatter:
url: https://github.com/getgrav/grav-theme-antimatter
path: user/themes/antimatter
branch: develop
branch: master
links:
problems:
src: grav-plugin-problems

3
.gitignore vendored
View File

@@ -1,5 +1,4 @@
# Composer
composer.lock
.composer
vendor/
@@ -7,6 +6,8 @@ vendor/
.sass-cache
# Grav Specific
backup/*
!backup/.*
cache/*
!cache/.*
assets/*

View File

@@ -2,6 +2,17 @@
RewriteEngine On
## Begin RewriteBase
# 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>
##
# RewriteBase /
## End - RewriteBase
## Begin - Exploits
# If you experience problems on your site block out the operations listed below
# This attempts to block the most common type of exploit `attempts` to Grav
@@ -19,17 +30,6 @@ RewriteRule .* index.php [F]
#
## End - Exploits
## Begin RewriteBase
# 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>
##
# RewriteBase /
## End - RewriteBase
## Begin - Index
# If the requested path and file is not /index.php and the request
# has not already been internally rewritten to the index.php script
@@ -44,7 +44,7 @@ RewriteRule .* index.php [L]
## Begin - Security
# Block all direct access for these folders
RewriteRule ^(cache|bin|logs)/(.*) error [L]
RewriteRule ^(.git|cache|bin|logs|backup)/(.*) error [L]
# Block access to specific file types for these folders
RewriteRule ^(system|user|vendor)/(.*)\.(txt|md|html|yaml|php|twig|sh|bat)$ error [L]
## End - Security

78
.travis.yml Normal file
View File

@@ -0,0 +1,78 @@
language: php
php: 5.6
branches:
only:
- master
- build_test
notifications:
email:
on_success: never
on_failure: always
hipchat:
# hipchat_api@grav
rooms:
- secure: "bqO0wM1B7bJnQw2fuhquSXEqI9gw6WmFytIh9sEWXzbYTzTUP5t0PcKOd3FT2BNMRaDxPJLVl+vG/oqmqDUBkEmOGcG504IQjeNzZqnMz0tXQMIcCc22Las9tFfc4Jf6RVi/qGomFtHGE9Wgii+TAN4zqZaufbNjwd8SyjO0+W8="
template:
- '%{repository}#%{build_number} (%{branch}): Grav Core and Skeletons packages have been uploaded. (<a href="%{build_url}">Details</a>)'
format: html
env:
global:
# Colors!
- TEXTRESET=$(tput sgr0) # reset the foreground colour
- RED=$(tput setaf 1)
- GREEN=$(tput setaf 2)
- YELLOW=$(tput setaf 3)
- BLUE=$(tput setaf 4)
- BOLD=$(tput bold)
# User
- GH_USER="getgrav"
# Paths
- RT_DEVTOOLS=$HOME/devtools
- GOPATH="$HOME/go"
- PATH="$GOPATH/bin:$PATH"
# GH_TOKEN [API Key]
- secure: "jS+c+g2v33vypG4VtqiSDW2qQ4dGJZlrUKBRCztoy1yrOrYRPvc5Vzi/AS3fDmZ4yizukEwmUNNzyZQcgFvLPpmCCml46Dovp8R9OXhbNe8OnULmaSn2Zkr71oblMYu6ZP+RpYvNq0BIdSB3u2TiFriHMiTIkX9UwZNaUCOX1ig="
# BB_TOKEN value => "user:pass@"
- secure: "einUtSEkUWy2IrqLXyVjwUU+mwaaoiOXRRVdLBpA3Zye6bZx8cm5h/5AplkPWhM/NmCJoW/MwNZHHkFhlr3mDRov5iOxVmTTYfnXB+I5lxYTSgduOLLErS7mU8hfADpVDU8bHNU44fNGD3UEiG1PD4qQBX4DMlqIFmR20mjs81k="
# GH_API_USER [for curl]
- secure: "Xbk/V9aIys0NxccJGR3Zrm2GRxDnA0RuazBs1puIboTYDhbi0Z7JTL+mOx3xp5Kfoniad/xAuijQESTM9MMrKqq/qCzhAMaC1+vcL4pCHZH4NSG6DBxB9BPkKVFq+1llu5FTEf8bkxHzwGR0l1ARW6TVRcgTHr5B58bCEIwEOrI="
# Latest Release version
- 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:
- composer self-update
- 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
script:
- if [ ! -z "$TRAVIS_TAG" ]; then
FILES="$RT_DEVTOOLS/grav-dist/*.zip";
for file in ${FILES[@]}; do
NAME=${file##*/};
REPO="$(echo ${NAME} | rev | cut -f 2- -d "-" | rev)";
if [[ $REPO == 'grav' || $REPO == 'grav-admin' || $REPO == 'grav-update' ]]; then
REPO="grav";
fi;
API="$(curl --fail --user "${GH_API_USER}" -s https://api.github.com/repos/${GH_USER}/${REPO}/releases/latest)";
ASSETS="$(echo "${API}" | node gh-assets.js)";
TAG="$(echo "${API}" | grep tag_name | head -n 1 | cut -d '"' -f 4)";
if [ $REPO == "grav" ]; then
TAG=$TRAVIS_TAG;
fi;
if [ ! -z "$ASSETS" ]; then
for asset in ${ASSETS[@]}; do
asset_id=$(echo ${asset} | cut -d ':' -f 1);
asset_name=$(echo ${asset} | cut -d ':' -f 2);
if [ "${NAME}" == "${asset_name}" ]; then
echo -e "\nAsset ${BOLD}${BLUE}${NAME}${TEXTRESET} already exists in ${YELLOW}${REPO}${TEXTRESET}@${BOLD}${YELLOW}${TAG}${TEXTRESET}... deleting id ${BOLD}${RED}${asset_id}${TEXTRESET}...";
curl -X DELETE --fail --user "${GH_API_USER}" "https://api.github.com/repos/${GH_USER}/${REPO}/releases/assets/${asset_id}";
fi;
done;
fi;
echo "Uploading package ${BOLD}${BLUE}${NAME}${TEXTRESET} to ${YELLOW}${REPO}${TEXTRESET}@${YELLOW}${TAG}${TEXTRESET}";
github-release upload --security-token $GH_TOKEN --user ${GH_USER} --repo $REPO --tag $TAG --name "$NAME" --file "$file";
done;
fi

View File

@@ -1,3 +1,475 @@
# v0.9.42
## 09/11/2015
1. [](#bugfix)
* Fixed `User.authorise()` to be backwards compabile
# v0.9.41
## 09/11/2015
1. [](#new)
* New and improved multibyte-safe TruncateHTML function and filter
* Added support for custom page date format
* Added a `string` Twig filter to render as json_encoded string
* Added `authorize` Twig filter
* Added support for theme inheritance in the admin
* Support for multiple content collections on a page
* Added configurable files/folders ignores for pages
* Added the ability to set the default PHP locale and override via multi-lang configuration
* Added ability to save as YAML via admin
* Added check for `mbstring` support
* Added new `redirect` header for pages
1. [](#improved)
* Changed dependencies from `develop` to `master`
* Updated logging to log everything from `debug` level on (was `warning`)
* Added missing `accounts/` folder
* Default to performing a 301 redirect for URIs with trailing slashes
* Improved Twig error messages
* Allow validating of forms from anywhere such as plugins
* Added logic so modular pages are by default non-routable
* Hide password input in `bin/grav newuser` command
1. [](#bugfix)
* Fixed `Pages.all()` not returning modular pages
* Fix for modular template types not getting found
* Fix for `markdown_extra:` overriding `markdown:extra:` setting
* Fix for multi-site routing
* Fix for multi-lang page name error
* Fixed a redirect loop in `URI` class
* Fixed a potential error when `unsupported_inline_types` is empty
* Correctly generate 2x retina image
* Typo fixes in page publish/unpublish blueprint
# v0.9.40
## 08/31/2015
1. [](#new)
* Added some new Twig filters: `defined`, `rtrim`, `ltrim`
* Admin support for customizable page file name + template override
1. [](#improved)
* Better message for incompatible/unsupported Twig template
* Improved User blueprints with better help
* Switched to composer **install** rather than **update** by default
* Admin autofocus on page title
* `.htaccess` hardening (`.htaccess` & `htaccess.txt`)
* Cache safety checks for missing folders
1. [](#bugfix)
* Fixed issue with unescaped `o` character in date formats
# v0.9.39
## 08/25/2015
1. [](#bugfix)
* `Page.active()` not triggering on **homepage**
* Fix for invalid session name in Opera browser
# v0.9.38
## 08/24/2015
1. [](#new)
* Added `language` to **user** blueprint
* Added translations to blueprints
* New extending logic for blueprints
* Blueprints are now loaded with Streams to allow for better overrides
* Added new Symfony `dump()` method
1. [](#improved)
* Catch YAML header parse exception so site doesn't die
* Better `Page.parent()` logic
* Improved GPM display layout
* Tweaked default page layout
* Unset route and slug for improved reliability of route changes
* Added requirements to README.md
* Updated various libraries
* Allow use of custom page date field for dateRange collections
1. [](#bugfix)
* Slug fixes with GPM
* Unset plaintext password on save
* Fix for trailing `/` not matching active children
# v0.9.37
## 08/12/2015
3. [](#bugfix)
* Fixed issue when saving `header.process` in page forms via the **admin plugin**
* Fixed error due to use of `set_time_limit` that might be disabled on some hosts
# v0.9.36
## 08/11/2015
1. [](#new)
* Added a new `newuser` CLI command to create user accounts
* Added `default` blueprint for all templates
* Support `user` and `system` language translation merging
1. [](#improved)
* Added isSymlink method in GPM to determine if Grav is symbolically linked or not
* Refactored page recursing
* Updated blueprints to use new toggles
* Updated blueprints to use current date for date format fields
* Updated composer.phar
* Use sessions for admin even when disabled for site
* Use `GRAV_ROOT` in session identifier
# v0.9.35
## 08/06/2015
1. [](#new)
* Added `body_classes` field
* Added `visiblity` toggle and help tooltips on new page form
* Added new `Page.unsetRoute()` method to allow admin to regenerate the route
2. [](#improved)
* User save no longer stores username each time
* Page list form field now shows all pages except root
* Removed required option from page title
* Added configuration settings for running Nginx in sub directory
3. [](#bugfix)
* Fixed deep translation merging
* Fixed broken **metadata** merging with site defaults
* Fixed broken **summary** field
* Fixed broken robots field
* Fixed GPM issue when using cURL, throwing an `Undefined offset: 1` exception
* Removed duplicate hidden page `type` field
# v0.9.34
## 08/04/2015
1. [](#new)
* Added new `cache_all` system setting + media `cache()` method
* Added base languages configuration
* Added property language to page to help plugins identify page language
* New `Utils::arrayFilterRecursive()` method
2. [](#improved)
* Improved Session handling to support site and admin independently
* Allow Twig variables to be modified in other events
* Blueprint updates in preparation for Admin plugin
* Changed `Inflector` from static to object and added multi-language support
* Support for admin override of a page's blueprints
3. [](#bugfix)
* Removed unused `use` in `VideoMedium` that was causing error
* Array fix in `User.authorise()` method
* Fix for typo in `translations_fallback`
* Fixed moving page to the root
# v0.9.33
## 07/21/2015
1. [](#new)
* Added new `onImageMediumSaved()` event (useful for post-image processing)
* Added `Vary: Accept-Encoding` option
2. [](#improved)
* Multilang-safe delimeter position
* Refactored Twig classes and added optional umask setting
* Removed `pageinit()` timing
* `Page->routable()` now takes `published()` state into account
* Improved how page extension is set
* Support `Language->translate()` method taking string and array
3. [](#bugfix)
* Fixed `backup` command to include empty folders
# v0.9.32
## 07/14/2015
1. [](#new)
* Detect users preferred language via `http_accept_language` setting
* Added new `translateArray()` language method
2. [](#improved)
* Support `en` translations by default for plugins & themes
* Improved default generator tag
* Minor language tweaks and fixes
3. [](#bugfix)
* Fix for session active language and homepage redirects
* Ignore root-level page rather than throwing error
# v0.9.31
## 07/09/2015
1. [](#new)
* Added xml, json, css and js to valid media file types
2. [](#improved)
* Better handling of unsupported media type downloads
* Improved `bin/grav backup` command to mimic admin plugin location/name
3. [](#bugfix)
* Critical fix for broken language translations
* Fix for Twig markdown filter error
* Safety check for download extension
# v0.9.30
## 07/08/2015
1. [](#new)
* BIG NEWS! Extensive Multi-Language support is all new in 0.9.30!
* Translation support via Twig filter/function and PHP method
* Page specific default route
* Page specific route aliases
* Canonical URL route support
* Added built-in session support
* New `Page.rawRoute()` to get a consistent folder-based route to a page
* Added option to always redirect to default page on alias URL
* Added language safe redirect function for use in core and plugins
2. [](#improved)
* Improved `Page.active()` and `Page.activeChild()` methods to support route aliases
* Various spelling corrections in `.php` comments, `.md` and `.yaml` files
* `Utils::startsWith()` and `Utils::endsWith()` now support needle arrays
* Added a new timer around `pageInitialized` event
* Updated jQuery library to v2.1.4
3. [](#bugfix)
* In-page CSS and JS files are now handled properly
* Fix for `enable_media_timestamp` not working properly
# v0.9.29
## 06/22/2015
1. [](#new)
* New and improved Regex-powered redirect and route alias logic
* Added new `onBuildPagesInitialized` event for memory critical or time-consuming plugins
* Added a `setSummary()` method for pages
2. [](#improved)
* Improved `MergeConfig()` logic for more control
* Travis skeleton build trigger implemented
* Set composer.json versions to stable versions where possible
* Disabled `last_modified` and `etag` page headers by default (causing too much page caching)
3. [](#bugfix)
* Preload classes during `bin/gpm selfupgrade` to avoid issues with updated classes
* Fix for directory relative _down_ links
# v0.9.28
## 06/16/2015
1. [](#new)
* Added method to set raw markdown on a page
* Added ability to enabled system and page level `etag` and `last_modified` headers
2. [](#improved)
* Improved image path processing
* Improved query string handling
* Optimization to image handling supporting URL encoded filenames
* Use global `composer` when available rather than Grv provided one
* Use `PHP_BINARY` contant rather than `php` executable
* Updated Doctrine Cache library
* Updated Symfony libraries
* Moved `convertUrl()` method to Uri object
3. [](#bugfix)
* Fix incorrect slug causing problems with CLI `uninstall`
* Fix Twig runtime error with assets pipeline in sufolder installations
* Fix for `+` in image filenames
* Fix for dot files causing issues with page processing
* Fix for Uri path detection on Windows platform
* Fix for alternative media resolutions
* Fix for modularTypes key properties
# v0.9.27
## 05/09/2015
1. [](#new)
* Added new composer CLI command
* Added page-level summary header overrides
* Added `size` back for Media objects
* Refactored Backup command in preparation for admin plugin
* Added a new `parseLinks` method to Plugins class
* Added `starts_with` and `ends_with` Twig filters
2. [](#improved)
* Optimized install of vendor libraries for speed improvement
* Improved configuration handling in preparation for admin plugin
* Cache optimization: Don't cache Twig templates when you pass dynamic params
* Moved `Utils::rcopy` to `Folder::rcopy`
* Improved `Folder::doDelete`
* Added check for required Curl in GPM
* Updated included composer.phar to latest version
* Various blueprint fixes for admin plugin
* Various PSR and code cleanup tasks
3. [](#bugfix)
* Fix issue with Gzip not working with `onShutDown()` event
* Fix for URLs with trailing slashes
* Handle condition where certain errors resulted in blank page
* Fix for issue with theme name equal to base_url and asset pipeline
* Fix to properly normalize font rewrite path
* Fix for absolute URLs below the current page
* Fix for `..` page references
# v0.9.26
## 04/24/2015
3. [](#bugfix)
* Fixed issue with homepage routes failing with 'dirname' error
# v0.9.25
## 04/24/2015
1. [](#new)
* Added support for E-Tag, Last-Modified, Cache-Control and Page-based expires headers
2. [](#improved)
* Refactored media image handling to make it more flexible and support absolute paths
* Refactored page modification check process to make it faster
* User account improvements in preparation for admin plugin
* Protect against timing attacks
* Reset default system expires time to 0 seconds (can override if you need to)
3. [](#bugfix)
* Fix issues with spaces in webroot when using `bin/grav install`
* Fix for spaces in relative directory
* Bug fix in collection filtering
# v0.9.24
## 04/15/2015
1. [](#new)
* Added support for chunked downloads of Assets
* Added new `onBeforeDownload()` event
* Added new `download()` and `getMimeType()` methods to Utils class
* Added configuration option for supported page types
* Added assets and media timestamp options (off by default)
* Added page expires configuration option
2. [](#bugfix)
* Fixed issue with Nginx/Gzip and `ob_flush()` throwing error
* Fixed assets actions on 'direct media' URLs
* Fix for 'direct assets` with any parameters
# v0.9.23
## 04/09/2015
1. [](#bugfix)
* Fix for broken GPM `selfupgrade` (Grav 0.9.21 and 0.9.22 will need to manually upgrade to this version)
# v0.9.22
## 04/08/2015
1. [](#bugfix)
* Fix to normalize GRAV_ROOT path for Windows
* Fix to normalize Media image paths for Windows
* Fix for GPM `selfupgrade` when you are on latest version
# v0.9.21
## 04/07/2015
1. [](#new)
* Major Media functionality enhancements: SVG, Animated GIF, Video support!
* Added ability to configure default image quality in system configuration
* Added `sizes` attributes for custom retina image breakpoints
2. [](#improved)
* Don't scale @1x retina images
* Add filter to Iterator class
* Updated various composer packages
* Various PSR fixes
# v0.9.20
## 03/24/2015
1. [](#new)
* Added `addAsyncJs()` and `addDeferJs()` to Assets manager
* Added support for extranal URL redirects
2. [](#improved)
* Fix unpredictable asset ordering when set from plugin/system
* Updated `nginx.conf` to ensure system assets are accessible
* Ensure images are served as static files in Nginx
* Updated vendor libraries to latest versions
* Updated included composer.phar to latest version
3. [](#bugfix)
* Fixed issue with markdown links to `#` breaking HTML
# v0.9.19
## 02/28/2015
1. [](#new)
* Added named assets capability and bundled jQuery into Grav core
* Added `first()` and `last()` to `Iterator` class
2. [](#improved)
* Improved page modification routine to skip _dot files_
* Only use files to calculate page modification dates
* Broke out Folder iterators into their own classes
* Various Sensiolabs Insight fixes
3. [](#bugfix)
* Fixed `Iterator.nth()` method
# v0.9.18
## 02/19/2015
1. [](#new)
* Added ability for GPM `install` to automatically install `_demo` content if found (w/backup)
* Added ability for themes and plugins to have dependencies required to install via GPM
* Added ability to override the system timezone rather than relying on server setting only
* Added new Twig filter `random_string` for generating random id values
* Added new Twig filter `markdown` for on-the-fly markdown processing
* Added new Twig filter `absoluteUrl` to convert relative to absolute URLs
* Added new `processTemplate()` method to Twig object for on-the-fly processing of twig template
* Added `rcopy()` and `contains()` helper methods in Utils
2. [](#improved)
* Provided new `param_sep` variable to better support Apache on Windows
* Moved parsedown configuration into the trait
* Added optional **deep-copy** option to `mergeConfig()` for plugins
* Updated bundled `composer.phar` package
* Various Sensiolabs Insight fixes - Silver level now!
* Various PSR Fixes
3. [](#bugfix)
* Fix for windows platforms not displaying installed themes/plugins via GPM
* Fix page IDs not picking up folder-only pages
# v0.9.17
## 02/05/2015
1. [](#new)
* Added **full HHVM support!** Get your speed on with Facebook's crazy fast PHP JIT compiler
2. [](#improved)
* More flexible page summary control
* Support **CamelCase** plugin and theme class names. Replaces dashes and underscores
* Moved summary delimiter into `site.yaml` so it can be configurable
* Various PSR fixes
3. [](#bugfix)
* Fix for `mergeConfig()` not falling back to defaults
* Fix for `addInlineCss()` and `addInlineJs()` Assets not working between Twig tags
* Fix for Markdown adding HTML tags into inline CSS and JS
# v0.9.16
## 01/30/2015
1. [](#new)
* Added **Retina** and **Responsive** image support via Grav media and `srcset` image attribute
* Added image debug option that overlays responsive resolution
* Added a new image cache stream
2. [](#improved)
* Improved the markdown Lightbox functionality to better mimic Twig version
* Fullsize Lightbox can now have filters applied
* Added a new `mergeConfig()` method to Plugin class to merge system + page header configuration
* Added a new `disable()` method to Plugin class to programmatically disable a plugin
* Updated Parsedown and Parsedown Extra to address bugs
* Various PSR fixes
3. [](#bugfix)
* Fix bug with image dispatch in traditionally _non-routable_ pages
* Fix for markdown link not working on non-current pages
* Fix for markdown images not being found on homepage
# v0.9.15
## 01/23/2015
3. [](#bugfix)
* Typo in video mime types
* Fix for old `markdown_extra` system setting not getting picked up
* Fix in regex for Markdown links with numeric values in path
* Fix for broken image routing mechanism that got broken at some point
* Fix for markdown images/links in pages with page slug override
# v0.9.14
## 01/23/2015
1. [](#new)
* Added **GZip** support
* Added multiple configurations via `setup.php`
* Added base structure for unit tests
* New `onPageContentRaw()` plugin event that processes before any page processing
* Added ability to dynamically set Metadata on page
* Added ability to dynamically configure Markdown processing via Parsedown options
2. [](#improved)
* Refactored `page.content()` method to be more flexible and reliable
* Various updates and fixes for streams resulting in better multi-site support
* Updated Twig, Parsedown, ParsedownExtra, DoctrineCache libraries
* Refactored Parsedown trait
* Force modular pages to be non-visible in menus
* Moved RewriteBase before Exploits in `.htaccess`
* Added standard video formats to Media support
* Added priority for inline assets
* Check for uniqueness when adding multiple inline assets
* Improved support for Twig-based URLs inside Markdown links and images
* Improved Twig `url()` function
3. [](#bugfix)
* Fix for HTML entities quotes in Metadata values
* Fix for `published` setting to have precedent of `publish_date` and `unpublish_date`
* Fix for `onShutdown()` events not closing connections properly in **php-fpm** environments
# v0.9.13
## 01/09/2015
@@ -6,7 +478,7 @@
* Added `publish_date` in page headers to automatically publish page
* Added `unpublish_date` in page headers to automatically unpublish page
* Added `dateRange()` capability for collections
* Added ability to dynamically control Cache lifetime programatically
* Added ability to dynamically control Cache lifetime programmatically
* Added ability to sort by anything in the page header. E.g. `sort: header.taxonomy.year`
* Added various helper methods to collections: `copy, nonVisible, modular, nonModular, published, nonPublished, nonRoutable`
2. [](#improved)
@@ -15,7 +487,7 @@
* House-cleaning of some unused methods in Pages object
3. [](#bugfix)
* Fix `uninstall` GPM command that was broken in last release
* Fix for intermitten `undefined index` error when working with Collections
* Fix for intermittent `undefined index` error when working with Collections
* Fix for date of some pages being set to incorrect future timestamps
# v0.9.12
@@ -27,8 +499,8 @@
* Added support for **in-page** Twig processing in **modular** pages
* Added configurable support for `undefined` Twig functions and filters
2. [](#improved)
* Fallback to default `.html` template if error occurs on non-html pages
* Added ability to have PSR-1 friendly plugin names (camelcase, no-dashes)
* Fall back to default `.html` template if error occurs on non-html pages
* Added ability to have PSR-1 friendly plugin names (CamelCase, no-dashes)
* Fix to `composer.json` to deter API rate-limit errors
* Added **non-exception-throwing** handler for undefined methods on `Medium` objects
3. [](#bugfix)
@@ -181,7 +653,7 @@
* Broke cache types out into multiple directories in the cache folder
* Removed vendor libs from github repository
* Various PSR cleanup of code
* Various Blueprint updates to support upcoming Admin plugin
* Various Blueprint updates to support upcoming admin plugin
* Added ability to filter page children for normal/modular/all
* Added `sort_by_key` twig filter
* Added `visible()` and `routable()` filters to page collections
@@ -254,7 +726,7 @@
* Addition of Dependency Injection Container
* Refactored plugins to use Symfony Event Dispatcher
* New Asset Manager to provide unified management of JavaScript and CSS
* Asset Pipelining to provide unification, minify, and optimazation of JavaScript and CSS
* Asset Pipelining to provide unification, minify, and optimization of JavaScript and CSS
* Grav Media support directly in Markdown syntax
* Additional Grav Generator meta tag in default themes
* Added support for PHP Stream Wrapper for resource location

View File

@@ -1,9 +1,10 @@
# ![](https://avatars1.githubusercontent.com/u/8237355?v=2&s=50) Grav
[![Gitter](https://badges.gitter.im/Join Chat.svg)](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 principals 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.
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad/mini.png)](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/getgrav/grav?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
The underlying architecture of Grav has been designed to use well-established and _best-in-class_ technologies, where applicable, to ensure that Grav is simple to use and easy to extend. Some of these key technologies include:
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.
The underlying architecture of Grav is designed to use well-established and _best-in-class_ technologies, to ensure that Grav is simple to use and easy to extend. Some of these key technologies include:
* [Twig Templating](http://twig.sensiolabs.org/): for powerful control of the user interface
* [Markdown](http://en.wikipedia.org/wiki/Markdown): for easy content creation
@@ -15,6 +16,11 @@ The underlying architecture of Grav has been designed to use well-established an
* [Symfony Console](http://symfony.com/doc/current/components/console/introduction.html): for CLI interface
* [Gregwar Image Library](https://github.com/Gregwar/Image): for dynamic image manipulation
# 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
You have two options to get Grav:

0
backup/.gitkeep Normal file
View File

Binary file not shown.

13
bin/gpm
View File

@@ -6,10 +6,17 @@ 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';
}
use Grav\Common\Composer;
if (!file_exists(__DIR__ . '/../vendor')){
// Before we can even start, we need to run composer first
$composer = Composer::getComposerExecutor();
echo "Preparing to install vendor dependencies...\n\n";
echo system('php bin/composer.phar --working-dir="'.__DIR__.'/../" --no-interaction install');
echo system($composer.' --working-dir="'.__DIR__.'/../" --no-interaction --no-dev --prefer-dist -o install');
echo "\n\n";
}
@@ -26,6 +33,10 @@ if (!file_exists(ROOT_DIR . 'index.php')) {
exit('FATAL: Must be run from ROOT directory of Grav!');
}
if (!function_exists('curl_version')) {
exit('FATAL: GPM requires PHP Curl module to be installed');
}
$grav = Grav::instance(array('loader' => $autoload));
$grav['config']->init();
$grav['streams'];

View File

@@ -6,10 +6,17 @@ 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';
}
use Grav\Common\Composer;
if (!file_exists(__DIR__ . '/../vendor')){
// Before we can even start, we need to run composer first
$composer = Composer::getComposerExecutor();
echo "Preparing to install vendor dependencies...\n\n";
echo system('php bin/composer.phar --working-dir="'.__DIR__.'/../" --no-interaction install');
echo system($composer.' --working-dir="'.__DIR__.'/../" --no-interaction --no-dev --prefer-dist -o install');
echo "\n\n";
}
@@ -28,10 +35,12 @@ if (!file_exists(ROOT_DIR . 'index.php')) {
$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\NewUserCommand(),
));
$app->run();

View File

@@ -8,28 +8,22 @@
"require": {
"php": ">=5.4.0",
"twig/twig": "~1.16",
"erusev/parsedown-extra": "dev-master",
"symfony/yaml": "~2.6",
"symfony/console": "~2.6",
"symfony/event-dispatcher": "~2.6",
"doctrine/cache": "~1.3",
"erusev/parsedown-extra": "~0.7",
"symfony/yaml": "~2.7",
"symfony/console": "~2.7",
"symfony/event-dispatcher": "~2.7",
"symfony/var-dumper": "~2.7",
"doctrine/cache": "~1.4",
"maximebf/debugbar": "dev-master",
"filp/whoops": "1.2.*@dev",
"monolog/monolog": "~1.1",
"gregwar/image": "~2.0",
"monolog/monolog": "~1.0",
"gregwar/image": "~2.0",
"ircmaxell/password-compat": "1.0.*",
"mrclay/minify": "dev-master",
"donatj/phpuseragentparser": "dev-master",
"mrclay/minify": "~2.2",
"donatj/phpuseragentparser": "~0.3",
"pimple/pimple": "~3.0",
"rockettheme/toolbox": "dev-develop"
"rockettheme/toolbox": "1.1.*"
},
"repositories": [
{
"type": "vcs",
"no-api": true,
"url": "https://github.com/rockettheme/toolbox"
}
],
"autoload": {
"psr-4": {
"Grav\\": "system/src/Grav"

1012
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,17 @@
RewriteEngine On
## Begin RewriteBase
# 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>
##
# RewriteBase /
## End - RewriteBase
## Begin - Exploits
# If you experience problems on your site block out the operations listed below
# This attempts to block the most common type of exploit `attempts` to Grav
@@ -19,17 +30,6 @@ RewriteRule .* index.php [F]
#
## End - Exploits
## Begin RewriteBase
# 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>
##
# RewriteBase /
## End - RewriteBase
## Begin - Index
# If the requested path and file is not /index.php and the request
# has not already been internally rewritten to the index.php script
@@ -44,7 +44,7 @@ RewriteRule .* index.php [L]
## Begin - Security
# Block all direct access for these folders
RewriteRule ^(cache|bin|logs)/(.*) error [L]
RewriteRule ^(.git|cache|bin|logs|backup)/(.*) error [L]
# Block access to specific file types for these folders
RewriteRule ^(system|user|vendor)/(.*)\.(txt|md|html|yaml|php|twig|sh|bat)$ error [L]
## End - Security

View File

@@ -2,12 +2,13 @@
namespace Grav;
if (version_compare($ver = PHP_VERSION, $req = '5.4.0', '<')) {
exit(sprintf('You are running PHP %s, but Grav needs at least <strong>PHP %s</strong> to run.', $ver, $req));
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)) {
exit('Please run: <i>bin/grav install</i>');
throw new \RuntimeException("Please run: <i>bin/grav install</i>");
}
use Grav\Common\Grav;
@@ -15,19 +16,25 @@ use Grav\Common\Grav;
// Register the auto-loader.
$loader = require_once $autoload;
if (!ini_get('date.timezone')) {
date_default_timezone_set('UTC');
}
// 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')) {
throw new \RuntimeException("'mbstring' extension is not loaded. This is required for Grav to run correctly");
}
mb_internal_encoding('UTF-8');
// Get the Grav instance
$grav = Grav::instance(
array(
'loader' => $loader
)
);
// Process the page
try {
$grav->process();
} catch (\Exception $e) {
$grav->fireEvent('onFatalException');
throw $e;

View File

@@ -1,66 +1,87 @@
worker_processes 1;
worker_processes 1;
events {
worker_connections 1024;
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
listen 80;
server_name localhost;
error_page 500 502 503 504 /50x.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
root html;
}
location / {
root html;
index index.php;
if (!-e $request_filename){ rewrite ^(.*)$ /index.php last; }
}
location / {
root html;
index index.php;
if (!-e $request_filename){ rewrite ^(.*)$ /index.php last; }
}
location /user {
rewrite ^/user/accounts/(.*)$ /error redirect;
rewrite ^/user/config/(.*)$ /error redirect;
rewrite ^/user/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
}
# if you want grav in a sub-directory of your main site
# (for example, example.com/mygrav) then you need this rewrite:
location /mygrav {
index index.php;
if (!-e $request_filename){ rewrite ^(.*)$ /mygrav/$2 last; }
try_files $uri $uri/ /index.php?$args;
}
location /cache {
rewrite ^/cache/(.*) /error redirect;
}
# if using grav in a sub-directory of your site,
# prepend the actual path to each location
# for example: /mygrav/images
# and: /mygrav/user
# and: /mygrav/cache
# and so on
location /bin {
rewrite ^/bin/(.*)$ /error redirect;
}
location /images/ {
# Serve images as static
}
location /system {
rewrite ^/system/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
}
location /user {
rewrite ^/user/accounts/(.*)$ /error redirect;
rewrite ^/user/config/(.*)$ /error redirect;
rewrite ^/user/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
}
location /vendor {
rewrite ^/vendor/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
}
location /cache {
rewrite ^/cache/(.*) /error redirect;
}
# Remember to change 127.0.0.1:9000 to the Ip/port
# you configured php-cgi.exe to run from
location /bin {
rewrite ^/bin/(.*)$ /error redirect;
}
location /backup {
rewrite ^/backup/(.*) /error redirect;
}
location /system {
rewrite ^/system/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
}
location /vendor {
rewrite ^/vendor/(.*)\.(txt|md|html|php|yaml|json|twig|sh|bat)$ /error redirect;
}
# Remember to change 127.0.0.1:9000 to the Ip/port
# you configured php-cgi.exe to run from
location ~ \.php$ {
try_files $uri =404;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -1,4 +1,4 @@
title: Media
title: PLUGIN_ADMIN.MEDIA
form:
validation: loose

View File

@@ -1,70 +1,116 @@
title: Site
title: PLUGIN_ADMIN.SITE
form:
validation: loose
fields:
content:
type: section
title: Defaults
title: PLUGIN_ADMIN.DEFAULTS
underline: true
fields:
title:
type: text
label: Site Title
label: PLUGIN_ADMIN.SITE_TITLE
size: large
placeholder: "Site wide title"
help: Default title for your site
placeholder: PLUGIN_ADMIN.SITE_TITLE_PLACEHOLDER
help: PLUGIN_ADMIN.SITE_TITLE_HELP
author.name:
type: text
size: large
label: Default Author
label: PLUGIN_ADMIN.DEFAULT_AUTHOR
help: PLUGIN_ADMIN.DEFAULT_AUTHOR_HELP
author.email:
type: text
size: large
label: Default Email
label: PLUGIN_ADMIN.DEFAULT_EMAIL
help: PLUGIN_ADMIN.DEFAULT_EMAIL_HELP
validate:
type: email
taxonomies:
type: text
type: selectize
size: large
label: Taxonomy Types
label: PLUGIN_ADMIN.TAXONOMY_TYPES
classes: fancy
help: PLUGIN_ADMIN.TAXONOMY_TYPES_HELP
validate:
type: commalist
metadata:
type: array
label: Metadata
placeholder_key: Name
placeholder_value: Content
blog:
summary:
type: section
title: Blog
title: PLUGIN_ADMIN.PAGE_SUMMARY
underline: true
fields:
blog.route:
type: text
size: large
label: Blog URL
summary.enabled:
type: toggle
label: PLUGIN_ADMIN.ENABLED
highlight: 1
help: PLUGIN_ADMIN.ENABLED_HELP
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
summary.size:
type: text
size: x-small
label: Summary Size
label: PLUGIN_ADMIN.SUMMARY_SIZE
help: PLUGIN_ADMIN.SUMMARY_SIZE_HELP
validate:
type: int
min: 0
max: 65536
type: int
min: 0
max: 65536
summary.format:
type: toggle
label: PLUGIN_ADMIN.FORMAT
classes: fancy
help: PLUGIN_ADMIN.FORMAT_HELP
highlight: short
options:
'short': PLUGIN_ADMIN.SHORT
'long': PLUGIN_ADMIN.LONG
summary.delimiter:
type: text
size: x-small
label: PLUGIN_ADMIN.DELIMITER
help: PLUGIN_ADMIN.DELIMITER_HELP
metadata:
type: section
title: PLUGIN_ADMIN.METADATA
underline: true
fields:
metadata:
type: array
label: PLUGIN_ADMIN.METADATA
help: PLUGIN_ADMIN.METADATA_HELP
placeholder_key: PLUGIN_ADMIN.METADATA_KEY
placeholder_value: PLUGIN_ADMIN.METADATA_VALUE
routes:
type: section
title: Routes
title: PLUGIN_ADMIN.REDIRECTS_AND_ROUTES
underline: true
fields:
redirects:
type: array
label: PLUGIN_ADMIN.CUSTOM_REDIRECTS
help: PLUGIN_ADMIN.CUSTOM_REDIRECTS_HELP
placeholder_key: PLUGIN_ADMIN.CUSTOM_REDIRECTS_PLACEHOLDER_KEY
placeholder_value: PLUGIN_ADMIN.CUSTOM_REDIRECTS_PLACEHOLDER_VALUE
routes:
type: array
label: Custom
placeholder_key: /your/alias
placeholder_value: /your/route
label: PLUGIN_ADMIN.CUSTOM_ROUTES
help: PLUGIN_ADMIN.CUSTOM_ROUTES_HELP
placeholder_key: PLUGIN_ADMIN.CUSTOM_ROUTES_PLACEHOLDER_KEY
placeholder_value: PLUGIN_ADMIN.CUSTOM_ROUTES_PLACEHOLDER_VALUE

View File

@@ -1,4 +1,4 @@
title: File Streams
title: PLUGIN_ADMIN.FILE_STREAMS
form:
validation: loose

View File

@@ -1,4 +1,4 @@
title: System
title: PLUGIN_ADMIN.SYSTEM
form:
validation: loose
@@ -6,7 +6,7 @@ form:
content:
type: section
title: Content
title: PLUGIN_ADMIN.CONTENT
underline: true
fields:
@@ -14,105 +14,117 @@ form:
type: pages
size: medium
classes: fancy
label: Home Page
label: PLUGIN_ADMIN.HOME_PAGE
show_all: false
show_modular: false
show_root: false
help: "The page that Grav will use as the default landing page"
help: PLUGIN_ADMIN.HOME_PAGE_HELP
pages.theme:
type: themeselect
classes: fancy
selectize: true
size: medium
label: Default Theme
help: "Set the theme (defaults to 'default')"
pages.markdown_extra:
type: toggle
label: Markdown Extra
highlight: 1
options:
1: Yes
0: No
validate:
type: bool
label: PLUGIN_ADMIN.DEFAULT_THEME
help: PLUGIN_ADMIN.DEFAULT_THEME_HELP
pages.process:
type: checkboxes
label: Process
label: PLUGIN_ADMIN.PROCESS
help: PLUGIN_ADMIN.PROCESS_HELP
default: [markdown: true, twig: true]
options:
markdown: Markdown
twig: Twig
use: keys
pages.dateformat.short:
timezone:
type: select
label: PLUGIN_ADMIN.TIMEZONE
size: medium
classes: fancy
label: Short Date Format
help: "Set the short date format"
default: 'jS M Y'
help: PLUGIN_ADMIN.TIMEZONE_HELP
@data-options: '\Grav\Common\Utils::timezones'
default: ''
options:
'F jS \\a\\t g:ia': "January 1st at 11:59pm"
'l jS of F g:i A': "Monday 1st of January at 11:59 PM"
'D, m M Y G:i:s': "Mon, 01 Jan 2014 23:59:00"
'd-m-y G:i': "01-01-14 23:59"
'jS M Y': "10th Feb 2014"
'': 'Default (Server Timezone)'
pages.dateformat.default:
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'
options:
"": Auto Guess or Enter Custom
validate:
type: string
pages.dateformat.short:
type: dateformat
size: medium
classes: fancy
label: PLUGIN_ADMIN.SHORT_DATE_FORMAT
help: PLUGIN_ADMIN.SHORT_DATE_FORMAT_HELP
default: "jS M Y"
options:
"F jS \\a\\t g:ia": Date1
"l jS \\of F g:i A": Date2
"D, m M Y G:i:s": Date3
"d-m-y G:i": Date4
"jS M Y": Date5
pages.dateformat.long:
type: select
type: dateformat
size: medium
classes: fancy
label: Long Date Format
help: "Set the long date format"
label: PLUGIN_ADMIN.LONG_DATE_FORMAT
help: PLUGIN_ADMIN.LONG_DATE_FORMAT_HELP
options:
'F jS \a\t g:ia': "January 1st at 11:59pm"
'l jS of F g:i A': "Monday 1st of January at 11:59 PM"
'D, m M Y G:i:s': "Mon, 01 Jan 2014 23:59:00"
'd-m-y G:i': "01-01-14 23:59"
'jS M Y': "10th Feb 2014"
"F jS \\a\\t g:ia": Date1
"l jS \\of F g:i A": Date2
"D, m M Y G:i:s": Date3
"d-m-y G:i": Date4
"jS M Y": Date5
pages.order.by:
type: select
size: medium
size: long
classes: fancy
label: Default Ordering
label: PLUGIN_ADMIN.DEFAULT_ORDERING
help: PLUGIN_ADMIN.DEFAULT_ORDERING_HELP
options:
default: Default - based on folder name
folder: Folder - based on prefix-less folder name
title: Title - based on title field in header
date: Date - based on date field in header
default: PLUGIN_ADMIN.DEFAULT_ORDERING_DEFAULT
folder: PLUGIN_ADMIN.DEFAULT_ORDERING_FOLDER
title: PLUGIN_ADMIN.DEFAULT_ORDERING_TITLE
date: PLUGIN_ADMIN.DEFAULT_ORDERING_DATE
pages.order.dir:
type: toggle
label: Default Order Direction
label: PLUGIN_ADMIN.DEFAULT_ORDER_DIRECTION
highlight: asc
default: desc
help: PLUGIN_ADMIN.DEFAULT_ORDER_DIRECTION_HELP
options:
asc: Ascending
desc: Descending
asc: PLUGIN_ADMIN.ASCENDING
desc: PLUGIN_ADMIN.DESCENDING
pages.list.count:
type: text
size: x-small
label: Default Item Count
help: "Default max pages count"
label: PLUGIN_ADMIN.DEFAULT_PAGE_COUNT
help: PLUGIN_ADMIN.DEFAULT_PAGE_COUNT_HELP
validate:
type: number
min: 1
events:
type: section
title: Events
underline: true
fields:
pages.events.page:
pages.publish_dates:
type: toggle
label: Page events
label: PLUGIN_ADMIN.DATE_BASED_PUBLISHING
help: PLUGIN_ADMIN.DATE_BASED_PUBLISHING_HELP
highlight: 1
options:
1: Yes
@@ -120,29 +132,255 @@ form:
validate:
type: bool
pages.events.twig:
pages.events:
type: checkboxes
label: PLUGIN_ADMIN.EVENTS
help: PLUGIN_ADMIN.EVENTS_HELP
default: [page: true, twig: true]
options:
page: Page Events
twig: Twig Events
use: keys
pages.redirect_default_route:
type: toggle
label: Twig events
label: PLUGIN_ADMIN.REDIRECT_DEFAULT_ROUTE
help: PLUGIN_ADMIN.REDIRECT_DEFAULT_ROUTE_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
pages.redirect_trailing_slash:
type: toggle
label: PLUGIN_ADMIN.REDIRECT_TRAILING_SLASH
help: PLUGIN_ADMIN.REDIRECT_TRAILING_SLASH_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
pages.ignore_files:
type: selectize
size: large
label: PLUGIN_ADMIN.IGNORE_FILES
help: PLUGIN_ADMIN.IGNORE_FILES_HELP
classes: fancy
validate:
type: commalist
pages.ignore_folders:
type: selectize
size: large
label: PLUGIN_ADMIN.IGNORE_FOLDERS
help: PLUGIN_ADMIN.IGNORE_FOLDERS_HELP
classes: fancy
validate:
type: commalist
languages:
type: section
title: PLUGIN_ADMIN.LANGUAGES
underline: true
fields:
languages.supported:
type: selectize
size: large
label: PLUGIN_ADMIN.SUPPORTED
help: PLUGIN_ADMIN.SUPPORTED_HELP
classes: fancy
validate:
type: commalist
languages.translations:
type: toggle
label: PLUGIN_ADMIN.TRANSLATIONS_ENABLED
help: PLUGIN_ADMIN.TRANSLATIONS_ENABLED_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
languages.translations_fallback:
type: toggle
label: PLUGIN_ADMIN.TRANSLATIONS_FALLBACK
help: PLUGIN_ADMIN.TRANSLATIONS_FALLBACK_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
languages.session_store_active:
type: toggle
label: PLUGIN_ADMIN.ACTIVE_LANGUAGE_IN_SESSION
help: PLUGIN_ADMIN.ACTIVE_LANGUAGE_IN_SESSION_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
languages.home_redirect.include_lang:
type: toggle
label: PLUGIN_ADMIN.HOME_REDIRECT_INCLUDE_LANGUAGE
help: PLUGIN_ADMIN.HOME_REDIRECT_INCLUDE_LANGUAGE_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
languages.home_redirect.include_route:
type: toggle
label: PLUGIN_ADMIN.HOME_REDIRECT_INCLUDE_ROUTE
help: PLUGIN_ADMIN.HOME_REDIRECT_INCLUDE_ROUTE_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
languages.http_accept_language:
type: toggle
label: PLUGIN_ADMIN.HTTP_ACCEPT_LANGUAGE
help: PLUGIN_ADMIN.HTTP_ACCEPT_LANGUAGE_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
languages.override_locale:
type: toggle
label: PLUGIN_ADMIN.OVERRIDE_LOCALE
help: PLUGIN_ADMIN.OVERRIDE_LOCALE_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
http_headers:
type: section
title: PLUGIN_ADMIN.HTTP_HEADERS
underline: true
fields:
pages.expires:
type: text
size: small
label: PLUGIN_ADMIN.EXPIRES
help: PLUGIN_ADMIN.EXPIRES_HELP
validate:
type: number
min: 1
pages.last_modified:
type: toggle
label: PLUGIN_ADMIN.LAST_MODIFIED
help: PLUGIN_ADMIN.LAST_MODIFIED_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
pages.etag:
type: toggle
label: PLUGIN_ADMIN.ETAG
help: PLUGIN_ADMIN.ETAG_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
pages.vary_accept_encoding:
type: toggle
label: PLUGIN_ADMIN.VARY_ACCEPT_ENCODING
help: PLUGIN_ADMIN.VARY_ACCEPT_ENCODING_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
markdown:
type: section
title: Markdown
underline: true
fields:
pages.markdown.extra:
type: toggle
label: Markdown extra
help: PLUGIN_ADMIN.MARKDOWN_EXTRA_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
pages.markdown.auto_line_breaks:
type: toggle
label: PLUGIN_ADMIN.AUTO_LINE_BREAKS
help: PLUGIN_ADMIN.AUTO_LINE_BREAKS_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
pages.markdown.auto_url_links:
type: toggle
label: PLUGIN_ADMIN.AUTO_URL_LINKS
help: PLUGIN_ADMIN.AUTO_URL_LINKS_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
pages.markdown.escape_markup:
type: toggle
label: PLUGIN_ADMIN.ESCAPE_MARKUP
help: PLUGIN_ADMIN.ESCAPE_MARKUP_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
caching:
type: section
title: Caching
title: PLUGIN_ADMIN.CACHING
underline: true
fields:
cache.enabled:
type: toggle
label: Caching
label: PLUGIN_ADMIN.CACHING
help: PLUGIN_ADMIN.CACHING_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
@@ -150,7 +388,8 @@ form:
type: select
size: small
classes: fancy
label: Cache Check Method
label: PLUGIN_ADMIN.CACHE_CHECK_METHOD
help: PLUGIN_ADMIN.CACHE_CHECK_METHOD_HELP
options:
file: File
folder: Folder
@@ -160,7 +399,8 @@ form:
type: select
size: small
classes: fancy
label: Cache driver
label: PLUGIN_ADMIN.CACHE_DRIVER
help: PLUGIN_ADMIN.CACHE_DRIVER_HELP
options:
auto: Auto detect
file: File
@@ -172,193 +412,349 @@ form:
cache.prefix:
type: text
size: x-small
label: Cache Prefix
placeholder: "Derived from base URL (override by entering random string)"
label: PLUGIN_ADMIN.CACHE_PREFIX
help: PLUGIN_ADMIN.CACHE_PREFIX_HELP
placeholder: PLUGIN_ADMIN.CACHE_PREFIX_PLACEHOLDER
cache.lifetime:
type: text
size: small
label: PLUGIN_ADMIN.LIFETIME
help: PLUGIN_ADMIN.LIFETIME_HELP
validate:
type: number
cache.gzip:
type: toggle
label: PLUGIN_ADMIN.GZIP_COMPRESSION
help: PLUGIN_ADMIN.GZIP_COMPRESSION_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
twig:
type: section
title: Twig Templating
title: PLUGIN_ADMIN.TWIG_TEMPLATING
underline: true
fields:
twig.cache:
type: toggle
label: Twig caching
label: PLUGIN_ADMIN.TWIG_CACHING
help: PLUGIN_ADMIN.TWIG_CACHING_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
twig.debug:
type: toggle
label: Twig debug
highlight: 1
label: PLUGIN_ADMIN.TWIG_DEBUG
help: PLUGIN_ADMIN.TWIG_DEBUG_HELP
highlight: 0
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
twig.auto_reload:
type: toggle
label: Detect changes
label: PLUGIN_ADMIN.DETECT_CHANGES
help: PLUGIN_ADMIN.DETECT_CHANGES_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
twig.autoescape:
type: toggle
label: Autoescape variables
highlight: 1
label: PLUGIN_ADMIN.AUTOESCAPE_VARIABLES
help: PLUGIN_ADMIN.AUTOESCAPE_VARIABLES_HELP
highlight: 0
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets:
type: section
title: Assets
title: PLUGIN_ADMIN.ASSETS
underline: true
fields:
assets.css_pipeline:
type: toggle
label: CSS Pipeline
highlight: 1
label: PLUGIN_ADMIN.CSS_PIPELINE
help: PLUGIN_ADMIN.CSS_PIPELINE_HELP
highlight: 0
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.css_minify:
type: toggle
label: CSS Minify
label: PLUGIN_ADMIN.CSS_MINIFY
help: PLUGIN_ADMIN.CSS_MINIFY_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.css_minify_windows:
type: toggle
label: CSS Minify Windows Override
highlight: 1
label: PLUGIN_ADMIN.CSS_MINIFY_WINDOWS_OVERRIDE
help: PLUGIN_ADMIN.CSS_MINIFY_WINDOWS_OVERRIDE_HELP
highlight: 0
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.css_rewrite:
type: toggle
label: CSS Rewrite
label: PLUGIN_ADMIN.CSS_REWRITE
help: PLUGIN_ADMIN.CSS_REWRITE_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.js_pipeline:
type: toggle
label: JavaScript Pipeline
highlight: 01
label: PLUGIN_ADMIN.JAVASCRIPT_PIPELINE
help: PLUGIN_ADMIN.JAVASCRIPT_PIPELINE_HELP
highlight: 0
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.js_minify:
type: toggle
label: JavaScript Minify
label: PLUGIN_ADMIN.JAVASCRIPT_MINIFY
help: PLUGIN_ADMIN.JAVASCRIPT_MINIFY_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.enable_asset_timestamp:
type: toggle
label: PLUGIN_ADMIN.ENABLED_TIMESTAMPS_ON_ASSETS
help: PLUGIN_ADMIN.ENABLED_TIMESTAMPS_ON_ASSETS_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
assets.collections:
type: array
label: PLUGIN_ADMIN.COLLECTIONS
placeholder_key: collection_name
placeholder_value: collection_path
errors:
type: section
title: PLUGIN_ADMIN.ERROR_HANDLER
underline: true
fields:
errors.display:
type: toggle
label: PLUGIN_ADMIN.DISPLAY_ERRORS
help: PLUGIN_ADMIN.DISPLAY_ERRORS_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
errors.log:
type: toggle
label: PLUGIN_ADMIN.LOG_ERRORS
help: PLUGIN_ADMIN.LOG_ERRORS_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
debugger:
type: section
title: Debugger
title: PLUGIN_ADMIN.DEBUGGER
underline: true
fields:
debugger.enabled:
type: toggle
label: Debugger
highlight: 1
label: PLUGIN_ADMIN.DEBUGGER
help: PLUGIN_ADMIN.DEBUGGER_HELP
highlight: 0
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
debugger.mode:
type: select
size: small
classes: fancy
label: Mode
options:
detect: Auto-Detect
development: Development
production: Production
debugger.strict:
debugger.twig:
type: toggle
label: Strict
label: PLUGIN_ADMIN.DEBUG_TWIG
help: PLUGIN_ADMIN.DEBUG_TWIG_HELP
highlight: 1
options:
1: Yes
0: No
validate:
type: bool
debugger.max_depth:
type: select
size: small
classes: fancy
label: Detail Level
placeholder: "How many nested levels to display for objects or arrays"
options:
1: 1 level
2: 2 levels
3: 3 levels
4: 4 levels
5: 5 levels
6: 6 levels
7: 7 levels
8: 8 levels
9: 9 levels
10: 10 levels
validate:
type: number
debugger.log.enabled:
type: toggle
label: Logging
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
debugger.shutdown.close_connection:
type: toggle
label: Shutdown Close Connection
label: PLUGIN_ADMIN.SHUTDOWN_CLOSE_CONNECTION
help: PLUGIN_ADMIN.SHUTDOWN_CLOSE_CONNECTION_HELP
highlight: 1
options:
1: Yes
0: No
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
media:
type: section
title: PLUGIN_ADMIN.MEDIA
underline: true
fields:
images.default_image_quality:
type: text
label: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY
help: PLUGIN_ADMIN.DEFAULT_IMAGE_QUALITY_HELP
classes: x-small
validate:
type: number
min: 1
max: 100
images.cache_all:
type: toggle
label: PLUGIN_ADMIN.CACHE_ALL
help: PLUGIN_ADMIN.CACHE_ALL_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
images.debug:
type: toggle
label: PLUGIN_ADMIN.IMAGES_DEBUG
help: PLUGIN_ADMIN.IMAGES_DEBUG_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
media.upload_limit:
type: text
label: PLUGIN_ADMIN.UPLOAD_LIMIT
help: PLUGIN_ADMIN.UPLOAD_LIMIT_HELP
classes: small
validate:
type: number
media.enable_media_timestamp:
type: toggle
label: PLUGIN_ADMIN.ENABLE_MEDIA_TIMESTAMP
help: PLUGIN_ADMIN.ENABLE_MEDIA_TIMESTAMP_HELP
highlight: 0
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
session:
type: section
title: PLUGIN_ADMIN.SESSION
underline: true
fields:
session.enabled:
type: toggle
label: PLUGIN_ADMIN.ENABLED
help: PLUGIN_ADMIN.SESSION_ENABLED_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
session.timeout:
type: text
size: small
label: PLUGIN_ADMIN.TIMEOUT
help: PLUGIN_ADMIN.TIMEOUT_HELP
validate:
type: number
min: 1
session.name:
type: text
size: small
label: PLUGIN_ADMIN.NAME
help: PLUGIN_ADMIN.SESSION_NAME_HELP
advanced:
type: section
title: PLUGIN_ADMIN.ADVANCED
underline: true
fields:
absolute_urls:
type: toggle
label: PLUGIN_ADMIN.ABSOLUTE_URLS
highlight: 0
help: PLUGIN_ADMIN.ABSOLUTE_URLS_HELP
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
param_sep:
type: select
label: PLUGIN_ADMIN.PARAMETER_SEPARATOR
classes: fancy
help: PLUGIN_ADMIN.PARAMETER_SEPARATOR_HELP
default: ''
options:
':': ': (default)'
';': '; (for Apache running on Windows)'

View File

@@ -0,0 +1,276 @@
title: PLUGIN_ADMIN.DEFAULT
rules:
slug:
pattern: "[a-z][a-z0-9_\-]+"
min: 2
max: 80
form:
validation: loose
fields:
tabs:
type: tabs
active: 1
fields:
content:
type: tab
title: PLUGIN_ADMIN.CONTENT
fields:
header.title:
type: text
autofocus: true
style: vertical
label: PLUGIN_ADMIN.TITLE
content:
type: markdown
label: PLUGIN_ADMIN.CONTENT
validate:
type: textarea
uploads:
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: PLUGIN_ADMIN.OPTIONS
fields:
publishing:
type: section
title: Publishing
underline: true
fields:
header.published:
type: toggle
toggleable: true
label: PLUGIN_ADMIN.PUBLISHED
help: PLUGIN_ADMIN.PUBLISHED_HELP
highlight: 1
size: medium
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
header.date:
type: datetime
label: PLUGIN_ADMIN.DATE
toggleable: true
help: PLUGIN_ADMIN.DATE_HELP
header.publish_date:
type: datetime
label: PLUGIN_ADMIN.PUBLISHED_DATE
toggleable: true
help: PLUGIN_ADMIN.PUBLISHED_DATE_HELP
header.unpublish_date:
type: datetime
label: PLUGIN_ADMIN.UNPUBLISHED_DATE
toggleable: true
help: PLUGIN_ADMIN.UNPUBLISHED_DATE_HELP
header.metadata:
toggleable: true
type: array
label: PLUGIN_ADMIN.METADATA
help: PLUGIN_ADMIN.METADATA_HELP
placeholder_key: PLUGIN_ADMIN.METADATA_KEY
placeholder_value: PLUGIN_ADMIN.METADATA_VALUE
taxonomies:
type: section
title: PLUGIN_ADMIN.TAXONOMIES
underline: true
fields:
header.taxonomy:
type: taxonomy
label: PLUGIN_ADMIN.TAXONOMY
multiple: true
validate:
type: array
advanced:
type: tab
title: PLUGIN_ADMIN.ADVANCED
fields:
columns:
type: columns
fields:
column1:
type: column
fields:
settings:
type: section
title: PLUGIN_ADMIN.SETTINGS
underline: true
ordering:
type: toggle
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
validate:
type: slug
route:
type: select
label: PLUGIN_ADMIN.PARENT
classes: fancy
@data-options: '\Grav\Common\Page\Pages::parents'
@data-default: '\Grav\Plugin\admin::route'
options:
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.PAGE_FILE
help: PLUGIN_ADMIN.PAGE_FILE_HELP
default: default
@data-options: '\Grav\Common\Page\Pages::pageTypes'
header.body_classes:
type: text
label: PLUGIN_ADMIN.BODY_CLASSES
column2:
type: column
fields:
order_title:
type: section
title: PLUGIN_ADMIN.ORDERING
underline: true
order:
type: order
label: PLUGIN_ADMIN.PAGE_ORDER
sitemap:
overrides:
type: section
title: PLUGIN_ADMIN.OVERRIDES
underline: true
fields:
header.menu:
type: text
label: PLUGIN_ADMIN.MENU
toggleable: true
help: PLUGIN_ADMIN.MENU_HELP
header.slug:
type: text
label: PLUGIN_ADMIN.SLUG
toggleable: true
help: PLUGIN_ADMIN.SLUG_HELP
validate:
message: PLUGIN_ADMIN.SLUG_VALIDATE_MESSAGE
rule: slug
header.redirect:
type: text
label: PLUGIN_ADMIN.REDIRECT
toggleable: true
help: PLUGIN_ADMIN.REDIRECT_HELP
header.process:
type: checkboxes
label: PLUGIN_ADMIN.PROCESS
toggleable: true
@config-default: system.pages.process
default:
markdown: true
twig: false
options:
markdown: Markdown
twig: Twig
use: keys
header.child_type:
type: select
toggleable: true
label: PLUGIN_ADMIN.DEFAULT_CHILD_TYPE
default: default
placeholder: PLUGIN_ADMIN.USE_GLOBAL
@data-options: '\Grav\Common\Page\Pages::types'
header.routable:
type: toggle
toggleable: true
label: PLUGIN_ADMIN.ROUTABLE
help: PLUGIN_ADMIN.ROUTABLE_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
header.cache_enable:
type: toggle
toggleable: true
label: PLUGIN_ADMIN.CACHING
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
header.visible:
type: toggle
toggleable: true
label: PLUGIN_ADMIN.VISIBLE
help: PLUGIN_ADMIN.VISIBLE_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
header.template:
type: select
toggleable: true
classes: fancy
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
default: default
@data-options: '\Grav\Common\Page\Pages::types'
header.order_by:
type: hidden
header.order_manual:
type: hidden
validate:
type: commalist
blueprint:
type: blueprint

View File

@@ -0,0 +1,47 @@
title: PLUGIN_ADMIN.MODULAR
@extends:
type: default
context: blueprints://pages
form:
fields:
tabs:
type: tabs
active: 1
fields:
content:
fields:
header.content.items:
type: select
label: PLUGIN_ADMIN.ITEMS
default: @self.modular
options:
@self.modular: Children
header.content.order.by:
type: select
label: PLUGIN_ADMIN.ORDER_BY
default: date
options:
folder: PLUGIN_ADMIN.FOLDER
title: PLUGIN_ADMIN.TITLE
date: PLUGIN_ADMIN.DATE
default: PLUGIN_ADMIN.DEFAULT
header.content.order.dir:
type: select
label: PLUGIN_ADMIN.ORDER
default: desc
options:
asc: PLUGIN_ADMIN.ASCENDING
desc: PLUGIN_ADMIN.DESCENDING
header.process:
type: ignore
content:
type: ignore
uploads:
type: ignore

View File

@@ -10,38 +10,37 @@ form:
section:
type: section
title: Add Modular Content
title: PLUGIN_ADMIN.ADD_MODULAR_CONTENT
title:
type: text
label: Page Title
label: PLUGIN_ADMIN.PAGE_TITLE
validate:
required: true
folder:
type: text
label: Folder Name
label: PLUGIN_ADMIN.FOLDER_NAME
validate:
type: slug
required: true
route:
type: select
label: Page
label: PLUGIN_ADMIN.PAGE
classes: fancy
@data-options: '\Grav\Common\Page\Pages::parents'
@data-default: '\Grav\Plugin\admin::route'
options:
'': '- Select -'
'': PLUGIN_ADMIN.DEFAULT_OPTION_SELECT
validate:
required: true
type:
name:
type: select
classes: fancy
label: Modular Template
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
help: PLUGIN_ADMIN.PAGE_FILE_HELP
default: default
@data-options: '\Grav\Common\Page\Pages::modularTypes'
validate:
@@ -52,3 +51,6 @@ form:
default: 1
validate:
type: bool
blueprint:
type: blueprint

View File

@@ -15,26 +15,26 @@ form:
fields:
content:
type: tab
title: Content
title: PLUGIN_ADMIN.CONTENT
fields:
frontmatter:
type: frontmatter
label: Frontmatter
label: PLUGIN_ADMIN.FRONTMATTER
content:
type: markdown
label: Content
label: PLUGIN_ADMIN.CONTENT
uploads:
type: uploads
label: Page Media
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: Options
title: PLUGIN_ADMIN.OPTIONS
fields:
@@ -47,28 +47,39 @@ form:
fields:
ordering:
type: toggle
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
folder:
type: text
label: Filename
label: PLUGIN_ADMIN.FILENAME
validate:
type: slug
required: true
route:
type: select
label: Parent
label: PLUGIN_ADMIN.PARENT
classes: fancy
@data-options: '\Grav\Common\Page\Pages::parents'
@data-default: '\Grav\Plugin\admin::route'
options:
'/': '- Root -'
'': PLUGIN_ADMIN.DEFAULT_OPTION_SELECT
validate:
required: true
type:
name:
type: select
classes: fancy
label: Modular Template
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
default: default
@data-options: '\Grav\Common\Page\Pages::modularTypes'
validate:
@@ -80,5 +91,7 @@ form:
fields:
order:
type: order
label: Ordering
label: PLUGIN_ADMIN.ORDERING
blueprint:
type: blueprint

View File

@@ -0,0 +1,17 @@
rules:
slug:
pattern: "[a-z][a-z0-9_\-]+"
min: 2
max: 80
form:
validation: loose
fields:
route:
type: select
label: PLUGIN_ADMIN.PARENT
classes: fancy
@data-options: '\Grav\Common\Page\Pages::parents'
@data-default: '\Grav\Plugin\admin::route'
options:
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT

View File

@@ -10,39 +10,57 @@ form:
section:
type: section
title: Add Page
title: PLUGIN_ADMIN.ADD_PAGE
title:
type: text
label: Page Title
label: PLUGIN_ADMIN.PAGE_TITLE
help: PLUGIN_ADMIN.PAGE_TITLE_HELP
validate:
required: true
folder:
type: text
label: Folder Name
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
type: slug
required: true
route:
type: select
label: Parent Page
label: PLUGIN_ADMIN.PARENT_PAGE
classes: fancy
@data-options: '\Grav\Common\Page\Pages::parents'
@data-default: '\Grav\Plugin\admin::route'
options:
'/': '- Root -'
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
validate:
required: true
type:
name:
type: select
classes: fancy
label: Display Template
label: PLUGIN_ADMIN.PAGE_FILE
help: PLUGIN_ADMIN.PAGE_FILE_HELP
default: default
@data-options: '\Grav\Common\Page\Pages::types'
validate:
required: true
visible:
type: toggle
label: PLUGIN_ADMIN.VISIBLE
help: PLUGIN_ADMIN.VISIBLE_HELP
highlight: ''
default: ''
options:
'': Auto
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
required: true
blueprint:
type: blueprint

View File

@@ -1,42 +0,0 @@
rules:
slug:
pattern: "[a-z][a-z0-9_\-]+"
min: 2
max: 80
form:
validation: loose
fields:
title:
type: text
label: Title
validate:
required: true
folder:
type: text
label: Folder
validate:
type: slug
required: true
route:
type: select
label: Parent
classes: fancy
@data-options: '\Grav\Common\Page\Pages::parents'
@data-default: '\Grav\Plugin\admin::route'
options:
'/': '- Root -'
validate:
required: true
type:
type: select
classes: fancy
label: Display Template
default: default
@data-options: '\Grav\Common\Page\Pages::types'
validate:
required: true

View File

@@ -15,26 +15,25 @@ form:
fields:
content:
type: tab
title: Content
title: PLUGIN_ADMIN.CONTENT
fields:
frontmatter:
type: frontmatter
label: Frontmatter
label: PLUGIN_ADMIN.FRONTMATTER
autofocus: true
content:
type: markdown
label: Content
label: PLUGIN_ADMIN.CONTENT
uploads:
type: uploads
label: Page Media
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: Options
title: PLUGIN_ADMIN.OPTIONS
fields:
@@ -47,28 +46,39 @@ form:
fields:
ordering:
type: toggle
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
folder:
type: text
label: Folder Name
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
type: slug
required: true
route:
type: select
label: Parent
label: PLUGIN_ADMIN.PARENT
classes: fancy
@data-options: '\Grav\Common\Page\Pages::parents'
@data-default: '\Grav\Plugin\admin::route'
options:
'/': '- Root -'
validate:
required: true
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
type:
name:
type: select
classes: fancy
label: Display Template
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
help: PLUGIN_ADMIN.DISPLAY_TEMPLATE_HELP
default: default
@data-options: '\Grav\Common\Page\Pages::types'
validate:
@@ -80,5 +90,7 @@ form:
fields:
order:
type: order
label: Ordering
label: PLUGIN_ADMIN.ORDERING
blueprint:
type: blueprint

View File

@@ -5,82 +5,52 @@ form:
content:
type: section
title: Account
title: PLUGIN_ADMIN.ACCOUNT
fields:
username:
type: text
size: large
label: Username
label: PLUGIN_ADMIN.USERNAME
disabled: true
readonly: true
email:
type: text
type: email
size: large
label: Email
label: PLUGIN_ADMIN.EMAIL
validate:
type: email
message: PLUGIN_ADMIN.EMAIL_VALIDATION_MESSAGE
required: true
password:
type: password
size: large
label: Password
label: PLUGIN_ADMIN.PASSWORD
validate:
required: true
message: PLUGIN_ADMIN.PASSWORD_VALIDATION_MESSAGE
pattern: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}'
fullname:
type: text
size: large
label: Full name
label: PLUGIN_ADMIN.FULL_NAME
validate:
required: true
title:
type: text
size: large
label: Title
label: PLUGIN_ADMIN.TITLE
admin:
type: section
title: Admin Access
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:
access.admin.super:
type: toggle
label: Super user
default: 0
highlight: 1
options:
1: Yes
0: No
validate:
type: bool
access.admin.login:
type: toggle
label: Admin login
default: 0
highlight: 1
options:
1: Yes
0: No
validate:
type: bool
site:
type: section
title: Site Access
fields:
access.site.login:
type: toggle
label: Site login
default: 1
highlight: 1
options:
1: Yes
0: No
validate:
type: bool

View File

@@ -1,4 +1,4 @@
title: Add Account
title: PLUGIN_ADMIN.ADD_ACCOUNT
form:
validation: loose
@@ -6,10 +6,11 @@ form:
content:
type: section
title: Add Account
title: PLUGIN_ADMIN.ADD_ACCOUNT
username:
type: text
label: Username
label: PLUGIN_ADMIN.USERNAME
help: PLUGIN_ADMIN.USERNAME_HELP
validate:
required: true

View File

@@ -20,10 +20,15 @@ png:
thumb: media/thumb-png.png
mime: image/png
gif:
type: image
type: animated
thumb: media/thumb-gif.png
mime: image/gif
svg:
type: vector
thumb: media/thumb-gif.png
mime: image/svg+xml
mp4:
type: video
thumb: media/thumb-mp4.png
@@ -40,11 +45,40 @@ swf:
type: video
thumb: media/thumb-swf.png
mime: video/x-flv
flv:
type: video
thumb: media/thumb-flv.png
mime: video/x-flv
mp3:
type: audio
thumb: media/thumb-mp3.png
mime: audio/mp3
ogg:
type: audio
thumb: media/thumb-ogg.png
mime: audio/ogg
wma:
type: audio
thumb: media/thumb-wma.png
mime: audio/wma
m4a:
type: audio
thumb: media/thumb-m4a.png
mime: audio/m4a
wav:
type: audio
thumb: media/thumb-wav.png
mime: audio/wav
txt:
type: file
thumb: media/thumb-txt.png
mime: text/plain
xml:
type: file
thumb: media/thumb-xml.png
mime: application/xml
doc:
type: file
thumb: media/thumb-doc.png
@@ -65,3 +99,16 @@ gz:
type: file
thumb: media/thumb-gz.png
mime: application/gzip
css:
type: file
thumb: media/thumb-css.png
mime: text/css
js:
type: file
thumb: media/thumb-js.png
mime: application/javascript
json:
type: file
thumb: media/thumb-json.png
mime: application/json

View File

@@ -1,15 +1,34 @@
title: Grav # Name of the site
author:
name: John Appleseed # Default author name
email: 'john@email.com' # Default author email
taxonomies: [category,tag] # Arbitrary list of taxonomy types
blog:
route: '/blog' # Route to blog
metadata:
description: 'My Grav Site' # Site description
description: 'My Grav Site' # Site description
summary:
enabled: true # enable or disable summary of page
format: short # long = summary delimiter will be ignored; short = use the first occurrence of delimiter or size
size: 300 # Maximum length of summary (characters)
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
routes:
/something/else: '/blog/sample-3' # Alias for /blog/sample-3
/another/one/here: '/blog/sample-3' # Another alias for /blog/sample-3
/new/*: '/blog/*' # Wildcard any /new/my-page URL to /blog/my-page Route
/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)
#menu: # Sample Menu Example
# - text: Source
# icon: github
# url: https://github.com/getgrav/grav
# - icon: twitter
# url: http://twitter.com/getgrav

View File

@@ -8,6 +8,7 @@ schemes:
type: ReadOnlyStream
paths:
- user://images
- system://images
page:
type: ReadOnlyStream

View File

@@ -1,17 +1,31 @@
absolute_urls: false # Absolute or relative URLs for `base_url`
timezone: '' # Valid values: http://php.net/manual/en/timezones.php
default_locale: # Default locale (defaults to system)
param_sep: ':' # Parameter separator, use ';' for Apache on windows
languages:
supported: [] # List of languages supported. eg: [en, fr, de]
translations: true # Enable translations by default
translations_fallback: true # Fallback through supported translations if active lang doesn't exist
session_store_active: false # Store active language in session
home_redirect:
include_lang: true # Include language in home redirect (/en)
include_route: false # Include route in home redirect (/blog)
http_accept_language: false # Attempt to set the language based on http_accept_language header in the browser
override_locale: false # Override the default or system locale with language specific one
home:
alias: '/home' # Default path for home, ie /
pages:
theme: antimatter # Default theme (defaults to "antimatter" theme)
markdown_extra: false # Enable support for Markdown Extra support (GFM by default)
order:
by: defaults # Order pages by "default", "alpha" or "date"
by: default # Order pages by "default", "alpha" or "date"
dir: asc # Default ordering direction, "asc" or "desc"
list:
count: 20 # Default item count per page
dateformat:
default: # The default date format Grav expects in the `date: ` field
short: 'jS M Y' # Short date format
long: 'F jS \a\t g:ia' # Long date format
publish_dates: true # automatically publish/unpublish based on dates
@@ -21,6 +35,23 @@ pages:
events:
page: true # Enable page level events
twig: true # Enable twig level events
markdown:
extra: false # Enable support for Markdown Extra support (GFM by default)
auto_line_breaks: false # Enable automatic line breaks
auto_url_links: false # Enable automatic HTML links
escape_markup: false # Escape markup tags into entities
special_chars: # List of special characters to automatically convert to entities
'>': 'gt'
'<': 'lt'
types: [txt,xml,html,json,rss,atom] # list of valid page types
expires: 604800 # Page expires time in seconds (604800 seconds = 7 days)
last_modified: false # Set the last modified date header based on file modifcation timestamp
etag: false # Set the etag header tag
vary_accept_encoding: false # Add `Vary: Accept-Encoding` header
redirect_default_route: false # Automatically redirect to a page's default route
redirect_trailing_slash: true # Handle automatically or 301 redirect a trailing / URL
ignore_files: [.DS_Store] # Files to ignore in Pages
ignore_folders: [.git, .idea] # Folders to ignore in Pages
cache:
enabled: true # Set to true to enable caching
@@ -29,6 +60,7 @@ cache:
driver: auto # One of: auto|file|apc|xcache|memcache|wincache
prefix: 'g' # Cache prefix string (prevents cache conflicts)
lifetime: 604800 # Lifetime of cached data in seconds (0 = infinite)
gzip: false # GZip compress the page output
twig:
cache: true # Set to true to enable twig caching
@@ -45,6 +77,9 @@ assets: # Configuration for Assets Manager (JS, C
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_minify: true # Minify the JS during pipelining
enable_asset_timestamp: false # Enable asset timestamps
collections:
jquery: system://assets/jquery/jquery-2.1.4.min.js
errors:
display: true # Display full backtrace-style error page
@@ -55,3 +90,21 @@ debugger:
twig: true # Enable debugging of Twig templates
shutdown:
close_connection: true # Close the connection before calling onShutdown(). false for debugging
images:
default_image_quality: 85 # Default image quality to use when resampling images (85%)
cache_all: false # Cache all image by default
debug: false # Show an overlay over images indicating the pixel depth of the image when working with retina for example
media:
enable_media_timestamp: false # Enable media timetsamps
upload_limit: 0 # Set maximum upload size in bytes (0 is unlimited)
unsupported_inline_types: [] # Array of unsupported media file types to try to display inline
session:
enabled: true # Enable Session support
timeout: 1800 # Timeout in seconds
name: grav-site # Name prefix of the session cookie
security:
default_hash: $2y$10$kwsyMVwM8/7j0K/6LHT.g.Fs49xOCTp2b8hh/S5.dPJuJcJB6T.UK

View File

@@ -2,12 +2,12 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '0.9.13');
define('GRAV_VERSION', '0.9.42');
define('DS', '/');
// Directories and Paths
if (!defined('GRAV_ROOT')) {
define('GRAV_ROOT', getcwd());
define('GRAV_ROOT', str_replace(DIRECTORY_SEPARATOR, DS, getcwd()));
}
define('ROOT_DIR', GRAV_ROOT . '/');
define('USER_PATH', 'user/');
@@ -17,14 +17,16 @@ define('ASSETS_DIR', ROOT_DIR . 'assets/');
define('CACHE_DIR', ROOT_DIR . 'cache/');
define('IMAGES_DIR', ROOT_DIR . 'images/');
define('LOG_DIR', ROOT_DIR .'logs/');
define('VENDOR_DIR', ROOT_DIR .'vendor/');
define('LIB_DIR', SYSTEM_DIR .'src/');
define('ACCOUNTS_DIR', USER_DIR .'accounts/');
define('DATA_DIR', USER_DIR .'data/');
define('PAGES_DIR', USER_DIR .'pages/');
// DEPRECATED: Do not use!
define('DATA_DIR', USER_DIR .'data/');
define('LIB_DIR', SYSTEM_DIR .'src/');
define('PLUGINS_DIR', USER_DIR .'plugins/');
define('THEMES_DIR', USER_DIR .'themes/');
define('VENDOR_DIR', ROOT_DIR .'vendor/');
// END DEPRECATED
// Some extensions
define('CONTENT_EXT', '.md');
@@ -38,6 +40,3 @@ define('RAW_CONTENT', 1);
define('TWIG_CONTENT', 2);
define('TWIG_CONTENT_LIST', 3);
define('TWIG_TEMPLATES', 4);
// Misc Defines
define('SUMMARY_DELIMITER', '===');

59
system/languages/en.yaml Normal file
View File

@@ -0,0 +1,59 @@
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:
'/(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'
'/s$/i': ''
INFLECTOR_UNCOUNTABLE: ['equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep']
INFLECTOR_IRREGULAR:
'person': 'people'
'man': 'men'
'child': 'children'
'sex': 'sexes'
'move': 'moves'
INFLECTOR_ORDINALS:
'default': 'th'
'first': 'st'
'second': 'nd'
'third': 'rd'

View File

@@ -47,7 +47,7 @@ class Assets
* Closure used by the pipeline to fetch assets.
*
* Useful when file_get_contents() function is not available in your PHP
* instalation or when you want to apply any kind of preprocessing to
* installation or when you want to apply any kind of preprocessing to
* your assets before they get pipelined.
*
* The closure will receive as the only parameter a string with the path/URL of the asset and
@@ -71,6 +71,7 @@ class Assets
// Some configuration variables
protected $config;
protected $base_url;
protected $timestamp = '';
// Default values for pipeline settings
protected $css_minify = true;
@@ -82,7 +83,6 @@ class Assets
protected $css_no_pipeline = array();
protected $js_no_pipeline = array();
public function __construct(array $options = array())
{
// Forward config options
@@ -120,7 +120,7 @@ class Assets
}
// Set custom pipeline fetch command
if (isset($config['fetch_command']) and ($config['fetch_command'] instanceof Closure)) {
if (isset($config['fetch_command']) && ($config['fetch_command'] instanceof Closure)) {
$this->fetch_command = $config['fetch_command'];
}
@@ -143,17 +143,23 @@ class Assets
}
// Set collections
if (isset($config['collections']) and is_array($config['collections'])) {
if (isset($config['collections']) && is_array($config['collections'])) {
$this->collections = $config['collections'];
}
// Autoload assets
if (isset($config['autoload']) and is_array($config['autoload'])) {
if (isset($config['autoload']) && is_array($config['autoload'])) {
foreach ($config['autoload'] as $asset) {
$this->add($asset);
}
}
// Set timestamp
if (isset($config['enable_asset_timestamp']) && $config['enable_asset_timestamp'] === true) {
$this->timestamp = '?' . self::getGrav()['cache']->getKey();
}
return $this;
}
@@ -163,12 +169,17 @@ class Assets
public function init()
{
/** @var Config $config */
$config = self::$grav['config'];
$base_url = self::$grav['base_url'];
$config = self::getGrav()['config'];
$base_url = self::getGrav()['base_url'];
$asset_config = (array)$config->get('system.assets');
$this->config($asset_config);
$this->base_url = $base_url . '/';
// Register any preconfigured collections
foreach ($config->get('system.assets.collections') as $name => $collection) {
$this->registerCollection($name, (array)$collection);
}
}
/**
@@ -193,13 +204,15 @@ class Assets
} elseif (isset($this->collections[$asset])) {
$this->add($this->collections[$asset], $priority, $pipeline);
} else {
// Get extension
$extension = pathinfo(parse_url($asset, PHP_URL_PATH), PATHINFO_EXTENSION);
// JavaScript or CSS
$info = pathinfo($asset);
if (isset($info['extension'])) {
$ext = strtolower($info['extension']);
if ($ext === 'css') {
if (strlen($extension) > 0) {
$extension = strtolower($extension);
if ($extension === 'css') {
$this->addCss($asset, $priority, $pipeline);
} elseif ($ext === 'js') {
} elseif ($extension === 'js') {
$this->addJs($asset, $priority, $pipeline);
}
}
@@ -226,7 +239,9 @@ class Assets
foreach ($asset as $a) {
$this->addCss($a, $priority, $pipeline);
}
return $this;
} elseif (isset($this->collections[$asset])) {
$this->add($this->collections[$asset], $priority, $pipeline);
return $this;
}
@@ -234,8 +249,9 @@ class Assets
$asset = $this->buildLocalLink($asset);
}
if ($asset && !array_key_exists($asset, $this->css)) {
$this->css[$asset] = [
$key = md5($asset);
if ($asset) {
$this->css[$key] = [
'asset' => $asset,
'priority' => $priority,
'order' => count($this->css),
@@ -255,16 +271,19 @@ class Assets
* @param mixed $asset
* @param int $priority the priority, bigger comes first
* @param bool $pipeline false if this should not be pipelined
* @param string $loading how the asset is loaded (async/defer)
*
* @return $this
*/
public function addJs($asset, $priority = 10, $pipeline = true)
public function addJs($asset, $priority = 10, $pipeline = true, $loading = '')
{
if (is_array($asset)) {
foreach ($asset as $a) {
$this->addJs($a, $priority, $pipeline);
}
return $this;
} elseif (isset($this->collections[$asset])) {
$this->add($this->collections[$asset], $priority, $pipeline);
return $this;
}
@@ -272,18 +291,48 @@ class Assets
$asset = $this->buildLocalLink($asset);
}
if ($asset && !array_key_exists($asset, $this->js)) {
$this->js[$asset] = [
$key = md5($asset);
if ($asset) {
$this->js[$key] = [
'asset' => $asset,
'priority' => $priority,
'order' => count($this->js),
'pipeline' => $pipeline
'pipeline' => $pipeline,
'loading' => $loading
];
}
return $this;
}
/**
* Convenience wrapper for async loading of JavaScript
*
* @param $asset
* @param int $priority
* @param bool $pipeline
*
* @return \Grav\Common\Assets
*/
public function addAsyncJs($asset, $priority = 10, $pipeline = true)
{
return $this->addJs($asset, $priority, $pipeline, 'async');
}
/**
* Convenience wrapper for deferred loading of JavaScript
*
* @param $asset
* @param int $priority
* @param bool $pipeline
*
* @return \Grav\Common\Assets
*/
public function addDeferJs($asset, $priority = 10, $pipeline = true)
{
return $this->addJs($asset, $priority, $pipeline, 'defer');
}
/**
* Add an inline CSS asset.
*
@@ -297,9 +346,16 @@ class Assets
*/
public function addInlineCss($asset, $priority = 10)
{
if (is_string($asset) && !in_array($asset, $this->inline_css)) {
$this->inline_css[] = $asset;
if (is_a($asset, 'Twig_Markup')) {
$asset = strip_tags((string)$asset);
}
$key = md5($asset);
if (is_string($asset) && !array_key_exists($key, $this->inline_css)) {
$this->inline_css[$key] = [
'priority' => $priority,
'order' => count($this->inline_css),
'asset' => $asset
];
}
return $this;
@@ -312,14 +368,22 @@ class Assets
* For adding chunks of string-based inline JS
*
* @param mixed $asset
* @param int $priority the priority, bigger comes first
*
* @return $this
*/
public function addInlineJs($asset)
public function addInlineJs($asset, $priority = 10)
{
if (is_string($asset) && !in_array($asset, $this->inline_js)) {
$this->inline_js[] = $asset;
if (is_a($asset, 'Twig_Markup')) {
$asset = strip_tags((string)$asset);
}
$key = md5($asset);
if (is_string($asset) && !array_key_exists($key, $this->inline_js)) {
$this->inline_js[$key] = [
'priority' => $priority,
'order' => count($this->inline_js),
'asset' => $asset
];
}
return $this;
@@ -339,15 +403,23 @@ class Assets
}
// Sort array by priorities (larger priority first)
if (self::$grav) {
if (self::getGrav()) {
usort($this->css, function ($a, $b) {
if ($a['priority'] == $b['priority']) {
return $b['order'] - $a['order'];
}
return $a['priority'] - $b['priority'];
});
usort($this->inline_css, function ($a, $b) {
if ($a['priority'] == $b['priority']) {
return $b['order'] - $a['order'];
}
return $a['priority'] - $b['priority'];
});
}
$this->css = array_reverse($this->css);
$this->inline_css = array_reverse($this->inline_css);
$attributes = $this->attributes(array_merge(['type' => 'text/css', 'rel' => 'stylesheet'], $attributes));
@@ -356,11 +428,11 @@ class Assets
$output .= '<link href="' . $this->pipeline(CSS_ASSET) . '"' . $attributes . ' />' . "\n";
foreach ($this->css_no_pipeline as $file) {
$output .= '<link href="' . $file['asset'] . '"' . $attributes . ' />' . "\n";
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' />' . "\n";
}
} else {
foreach ($this->css as $file) {
$output .= '<link href="' . $file['asset'] . '"' . $attributes . ' />' . "\n";
$output .= '<link href="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' />' . "\n";
}
}
@@ -368,7 +440,7 @@ class Assets
if (count($this->inline_css) > 0) {
$output .= "<style>\n";
foreach ($this->inline_css as $inline) {
$output .= $inline . "\n";
$output .= $inline['asset'] . "\n";
}
$output .= "</style>\n";
}
@@ -397,7 +469,16 @@ class Assets
}
return $a['priority'] - $b['priority'];
});
usort($this->inline_js, function ($a, $b) {
if ($a['priority'] == $b['priority']) {
return $b['order'] - $a['order'];
}
return $a['priority'] - $b['priority'];
});
$this->js = array_reverse($this->js);
$this->inline_js = array_reverse($this->inline_js);
$attributes = $this->attributes(array_merge(['type' => 'text/javascript'], $attributes));
@@ -405,11 +486,11 @@ class Assets
if ($this->js_pipeline) {
$output .= '<script src="' . $this->pipeline(JS_ASSET) . '"' . $attributes . ' ></script>' . "\n";
foreach ($this->js_no_pipeline as $file) {
$output .= '<script src="' . $file['asset'] . '"' . $attributes . ' ></script>' . "\n";
$output .= '<script src="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' ' . $file['loading']. '></script>' . "\n";
}
} else {
foreach ($this->js as $file) {
$output .= '<script src="' . $file['asset'] . '"' . $attributes . ' ></script>' . "\n";
$output .= '<script src="' . $file['asset'] . $this->timestamp . '"' . $attributes . ' ' . $file['loading'].'></script>' . "\n";
}
}
@@ -417,7 +498,7 @@ class Assets
if (count($this->inline_js) > 0) {
$output .= "<script>\n";
foreach ($this->inline_js as $inline) {
$output .= $inline . "\n";
$output .= $inline['asset'] . "\n";
}
$output .= "</script>\n";
}
@@ -428,14 +509,14 @@ class Assets
/**
* Minifiy and concatenate CSS / JS files.
* Minify and concatenate CSS / JS files.
*
* @return string
*/
protected function pipeline($css = true)
{
/** @var Cache $cache */
$cache = self::$grav['cache'];
$cache = self::getGrav()['cache'];
$key = '?' . $cache->getKey();
if ($css) {
@@ -493,17 +574,68 @@ class Assets
return $relative_path . $key;
}
/**
* Return the array of all the registered CSS assets
*
* @return array
*/
public function getCss()
{
return $this->css;
}
/**
* Return the array of all the registered JS assets
*
* @return array
*/
public function getJs()
{
return $this->js;
}
/**
* Return the array of all the registered collections
*
* @return array
*/
public function getCollections()
{
return $this->collections;
}
/**
* Determines if an asset exists as a collection, CSS or JS reference
*
* @param $asset
*
* @return bool
*/
public function exists($asset)
{
if (isset($this->collections[$asset]) ||
isset($this->css[$asset]) ||
isset($this->js[$asset])) {
return true;
} else {
return false;
}
}
/**
* Add/replace collection.
*
* @param string $collectionName
* @param array $assets
* @param bool $overwrite
*
* @return $this
*/
public function registerCollection($collectionName, Array $assets)
public function registerCollection($collectionName, Array $assets, $overwrite = false)
{
$this->collections[$collectionName] = $assets;
if ($overwrite || !isset($this->collections[$collectionName])) {
$this->collections[$collectionName] = $assets;
}
return $this;
}
@@ -542,26 +674,6 @@ class Assets
return $this;
}
/**
* Get all CSS assets already added.
*
* @return array
*/
public function getCss()
{
return $this->css;
}
/**
* Get all JavaScript assets already added.
*
* @return array
*/
public function getJs()
{
return $this->js;
}
/**
* Add all CSS assets within $directory (relative to public dir).
*
@@ -615,9 +727,9 @@ class Assets
$info = pathinfo($asset);
if (isset($info['extension'])) {
$ext = strtolower($info['extension']);
if ($ext === 'css' and !in_array($asset, $this->css)) {
if ($ext === 'css' && !in_array($asset, $this->css)) {
$this->css[] = $asset;
} elseif ($ext === 'js' and !in_array($asset, $this->js)) {
} elseif ($ext === 'js' && !in_array($asset, $this->js)) {
$this->js[] = $asset;
}
}
@@ -629,7 +741,7 @@ class Assets
/**
* Determine whether a link is local or remote.
*
* Undestands both "http://" and "https://" as well as protocol agnostic links "//"
* Understands both "http://" and "https://" as well as protocol agnostic links "//"
*
* @param string $link
*
@@ -637,8 +749,8 @@ class Assets
*/
protected function isRemoteLink($link)
{
return ('http://' === substr($link, 0, 7) or 'https://' === substr($link, 0, 8)
or '//' === substr($link, 0, 2));
return ('http://' === substr($link, 0, 7) || 'https://' === substr($link, 0, 8)
|| '//' === substr($link, 0, 2));
}
/**
@@ -651,7 +763,7 @@ class Assets
protected function buildLocalLink($asset)
{
try {
$asset = self::$grav['locator']->findResource($asset, false);
$asset = self::getGrav()['locator']->findResource($asset, false);
} catch (\Exception $e) {
}
@@ -713,7 +825,8 @@ class Assets
} else {
// Fix to remove relative dir if grav is in one
if (($this->base_url != '/') && (strpos($this->base_url, $link) == 0)) {
$relative_path = str_replace($this->base_url, '/', $link);
$base_url = '#' . preg_quote($this->base_url, '#') . '#';
$relative_path = ltrim(preg_replace($base_url, '/', $link, 1), '/');
}
$relative_dir = dirname($relative_path);
@@ -769,18 +882,7 @@ class Assets
return $matches[0];
}
$newpath = array();
$paths = explode('/', $old_url);
foreach ($paths as $path) {
if ($path == '..') {
$relative_path = dirname($relative_path);
} else {
$newpath[] = $path;
}
}
$new_url = rtrim($this->base_url, '/') . $relative_path . '/' . implode('/', $newpath);
$new_url = $this->base_url . ltrim(Utils::normalizePath($relative_path . '/' . $old_url), '/');
return str_replace($old_url, $new_url, $matches[0]);
},
@@ -818,7 +920,7 @@ class Assets
*
* @param string $directory
* @param string $pattern (regex)
* @param string $ltrim Will be trimed from the left of the file path
* @param string $ltrim Will be trimmed from the left of the file path
*
* @return array
*/

View File

@@ -0,0 +1,125 @@
<?php
namespace Grav\Common\Backup;
use Grav\Common\GravTrait;
use Grav\Common\Filesystem\Folder;
/**
* The ZipBackup class lets you create simple zip-backups of a grav site
*
* @author RocketTheme
* @license MIT
*/
class ZipBackup
{
use GravTrait;
protected static $ignorePaths = [
'backup',
'cache',
'images',
'logs'
];
protected static $ignoreFolders = [
'.git',
'.idea'
];
public static function backup($destination = null, callable $messager = null)
{
if (!$destination) {
$destination = self::getGrav()['locator']->findResource('backup://', true);
if (!$destination)
throw new \RuntimeException('The backup folder is missing.');
Folder::mkdir($destination);
}
$name = self::getGrav()['config']->get('site.title', basename(GRAV_ROOT));
if (is_dir($destination)) {
$date = date('YmdHis', time());
$filename = $name . '-' . $date . '.zip';
$destination = rtrim($destination, DS) . DS . $filename;
}
$messager && $messager([
'type' => 'message',
'level' => 'info',
'message' => 'Creating new Backup "' . $destination . '"'
]);
$messager && $messager([
'type' => 'message',
'level' => 'info',
'message' => ''
]);
$zip = new \ZipArchive();
$zip->open($destination, \ZipArchive::CREATE);
static::folderToZip(GRAV_ROOT, $zip, strlen(rtrim(GRAV_ROOT, DS) . DS), $messager);
$messager && $messager([
'type' => 'progress',
'percentage' => false,
'complete' => true
]);
$messager && $messager([
'type' => 'message',
'level' => 'info',
'message' => ''
]);
$messager && $messager([
'type' => 'message',
'level' => 'info',
'message' => 'Saving and compressing archive...'
]);
$zip->close();
return $destination;
}
/**
* @param $folder
* @param $zipFile
* @param $exclusiveLength
* @param $messager
*/
private static function folderToZip($folder, \ZipArchive &$zipFile, $exclusiveLength, callable $messager = null)
{
$handle = opendir($folder);
while (false !== $f = readdir($handle)) {
if ($f != '.' && $f != '..') {
$filePath = "$folder/$f";
// Remove prefix from file path before add to zip.
$localPath = substr($filePath, $exclusiveLength);
if (in_array($f, static::$ignoreFolders)) {
continue;
} elseif (in_array($localPath, static::$ignorePaths)) {
$zipFile->addEmptyDir($f);
continue;
}
if (is_file($filePath)) {
$zipFile->addFile($filePath, $localPath);
$messager && $messager([
'type' => 'progress',
'percentage' => false,
'complete' => false
]);
} elseif (is_dir($filePath)) {
// Add sub-directory.
$zipFile->addEmptyDir($localPath);
static::folderToZip($filePath, $zipFile, $exclusiveLength, $messager);
}
}
}
closedir($handle);
}
}

View File

@@ -188,8 +188,7 @@ class Cache extends Getters
public function save($id, $data, $lifetime = null)
{
if ($this->enabled) {
if ($lifetime == null) {
if ($lifetime === null) {
$lifetime = $this->getLifetime();
}
$this->driver->save($id, $data, $lifetime);
@@ -240,19 +239,20 @@ class Cache extends Getters
$anything = false;
$files = glob(ROOT_DIR . $path . '*');
foreach ($files as $file) {
if (is_file($file)) {
if (@unlink($file)) {
$anything = true;
}
} elseif (is_dir($file)) {
if (@Folder::delete($file)) {
$anything = true;
if (is_array($files)) {
foreach ($files as $file) {
if (is_file($file)) {
if (@unlink($file)) {
$anything = true;
}
} elseif (is_dir($file)) {
if (@Folder::delete($file)) {
$anything = true;
}
}
}
}
if ($anything) {
$output[] = '<red>Cleared: </red>' . $path . '*';
}
@@ -272,7 +272,7 @@ class Cache extends Getters
/**
* Set the cache lifetime programatically
* Set the cache lifetime programmatically
*
* @param int $future timestamp
*/

View File

@@ -0,0 +1,55 @@
<?php
namespace Grav\Common;
/**
* Offers composer helper methods.
*
* @author eschmar
* @license MIT
*/
class Composer
{
/** @const Default composer location */
const DEFAULT_PATH = "bin/composer.phar";
/**
* Returns the location of composer.
*
* @return string
*/
public static function getComposerLocation()
{
if (!function_exists('shell_exec') || strtolower(substr(PHP_OS, 0, 3)) === 'win') {
return self::DEFAULT_PATH;
}
// check for global composer install
$path = trim(shell_exec("command -v composer"));
// fall back to grav bundled composer
if (!$path || !preg_match('/(composer|composer\.phar)$/', $path)) {
$path = self::DEFAULT_PATH;
}
return $path;
}
public static function getComposerExecutor()
{
$executor = PHP_BINARY . ' ';
$composer = static::getComposerLocation();
if ($composer !== static::DEFAULT_PATH && is_executable($composer)) {
$file = fopen($composer, 'r');
$firstLine = fgets($file);
fclose($file);
if (!preg_match('/^#!.+php/i', $firstLine)) {
$executor = '';
}
}
return $executor . $composer;
}
}

View File

@@ -3,7 +3,6 @@ namespace Grav\Common\Config;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Grav;
use Grav\Common\GravTrait;
use Grav\Common\Filesystem\Folder;
use RocketTheme\Toolbox\Blueprints\Blueprints as BaseBlueprints;
use RocketTheme\Toolbox\File\PhpFile;

View File

@@ -3,10 +3,7 @@ namespace Grav\Common\Config;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Grav;
use Grav\Common\GravTrait;
use Grav\Common\Uri;
use Grav\Common\Data\Data;
use Grav\Common\Filesystem\Folder;
use RocketTheme\Toolbox\Blueprints\Blueprints;
use RocketTheme\Toolbox\File\PhpFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
@@ -21,6 +18,12 @@ class Config extends Data
{
protected $grav;
protected $streams = [
'system' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['system'],
]
],
'user' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
@@ -57,10 +60,17 @@ class Config extends Data
'' => ['user://themes'],
]
],
'languages' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://languages', 'system/languages'],
]
],
'cache' => [
'type' => 'Stream',
'prefixes' => [
'' => ['cache']
'' => ['cache'],
'images' => ['images']
]
],
'log' => [
@@ -68,49 +78,52 @@ class Config extends Data
'prefixes' => [
'' => ['logs']
]
],
'backup' => [
'type' => 'Stream',
'prefixes' => [
'' => ['backup']
]
]
];
protected $setup = [];
protected $blueprintFiles = [];
protected $configFiles = [];
protected $languageFiles = [];
protected $checksum;
protected $timestamp;
protected $configLookup;
protected $blueprintLookup;
protected $pluginLookup;
protected $languagesLookup;
protected $finder;
protected $environment;
protected $messages = [];
public function __construct(array $items = array(), Grav $grav = null, $environment = null)
protected $languages;
public function __construct(array $setup = array(), Grav $grav = null, $environment = null)
{
$this->grav = $grav ?: Grav::instance();
$this->finder = new ConfigFinder;
$this->environment = $environment ?: 'localhost';
$this->messages[] = 'Environment Name: ' . $this->environment;
if (isset($items['@class'])) {
if ($items['@class'] != get_class($this)) {
throw new \InvalidArgumentException('Unrecognized config cache file!');
}
// Loading pre-compiled configuration.
$this->timestamp = (int) $items['timestamp'];
$this->checksum = $items['checksum'];
$this->items = (array) $items['data'];
} else {
// Make sure that
if (!isset($items['streams']['schemes'])) {
$items['streams']['schemes'] = [];
}
$items['streams']['schemes'] += $this->streams;
$items = $this->autoDetectEnvironmentConfig($items);
$this->messages[] = $items['streams']['schemes']['config']['prefixes'][''];
parent::__construct($items);
// Make sure that
if (!isset($setup['streams']['schemes'])) {
$setup['streams']['schemes'] = [];
}
$setup['streams']['schemes'] += $this->streams;
$setup = $this->autoDetectEnvironmentConfig($setup);
$this->setup = $setup;
parent::__construct($setup);
$this->check();
}
@@ -121,8 +134,10 @@ class Config extends Data
public function reload()
{
$this->items = $this->setup;
$this->check();
$this->init();
$this->debug();
return $this;
}
@@ -146,6 +161,7 @@ class Config extends Data
foreach ($this->messages as $message) {
$this->grav['debugger']->addMessage($message);
}
$this->messages = [];
}
public function init()
@@ -157,49 +173,57 @@ class Config extends Data
$this->blueprintLookup = $locator->findResources('blueprints://config');
$this->pluginLookup = $locator->findResources('plugins://');
if (!isset($this->checksum)) {
$this->messages[] = 'No cached configuration, compiling new configuration..';
} elseif ($this->checksum() != $this->checksum) {
$this->messages[] = 'Configuration checksum mismatch, reloading configuration..';
} else {
$this->messages[] = 'Configuration checksum matches, using cached version.';
return;
}
$this->loadCompiledBlueprints($this->blueprintLookup, $this->pluginLookup, 'master');
$this->loadCompiledConfig($this->configLookup, $this->pluginLookup, 'master');
// process languages if supported
if ($this->get('system.languages.translations', true)) {
$this->languagesLookup = $locator->findResources('languages://');
$this->loadCompiledLanguages($this->languagesLookup, $this->pluginLookup, 'master');
}
$this->initializeLocator($locator);
}
public function checksum()
{
$checkBlueprints = $this->get('system.cache.check.blueprints', false);
$checkConfig = $this->get('system.cache.check.config', true);
$checkSystem = $this->get('system.cache.check.system', true);
if (empty($this->checksum)) {
$checkBlueprints = $this->get('system.cache.check.blueprints', false);
$checkLanguages = $this->get('system.cache.check.languages', false);
$checkConfig = $this->get('system.cache.check.config', true);
$checkSystem = $this->get('system.cache.check.system', true);
if (!$checkBlueprints && !$checkConfig && !$checkSystem) {
$this->messages[] = 'Skip configuration timestamp check.';
return false;
if (!$checkBlueprints && !!$checkLanguages && $checkConfig && !$checkSystem) {
$this->messages[] = 'Skip configuration timestamp check.';
return false;
}
// Generate checksum according to the configuration settings.
if (!$checkConfig) {
// Just check changes in system.yaml files and ignore all the other files.
$cc = $checkSystem ? $this->finder->locateConfigFile($this->configLookup, 'system') : [];
} else {
// Check changes in all configuration files.
$cc = $this->finder->locateConfigFiles($this->configLookup, $this->pluginLookup);
}
if ($checkBlueprints) {
$cb = $this->finder->locateBlueprintFiles($this->blueprintLookup, $this->pluginLookup);
} else {
$cb = [];
}
if ($checkLanguages) {
$cl = $this->finder->locateLanguageFiles($this->languagesLookup, $this->pluginLookup);
} else {
$cl = [];
}
$this->checksum = md5(json_encode([$cc, $cb, $cl]));
}
// Generate checksum according to the configuration settings.
if (!$checkConfig) {
$this->messages[] = 'Check configuration timestamps from system.yaml files.';
// Just check changes in system.yaml files and ignore all the other files.
$cc = $checkSystem ? $this->finder->locateConfigFile($this->configLookup, 'system') : [];
} else {
$this->messages[] = 'Check configuration timestamps from all configuration files.';
// Check changes in all configuration files.
$cc = $this->finder->locateConfigFiles($this->configLookup, $this->pluginLookup);
}
if ($checkBlueprints) {
$this->messages[] = 'Check blueprint timestamps from all blueprint files.';
$cb = $this->finder->locateBlueprintFiles($this->blueprintLookup, $this->pluginLookup);
} else {
$cb = [];
}
return md5(json_encode([$cc, $cb]));
return $this->checksum;
}
protected function autoDetectEnvironmentConfig($items)
@@ -249,7 +273,6 @@ class Config extends Data
'files' => $blueprintFiles,
'data' => $this->blueprints->toArray()
];
// If compiled file wasn't already locked by another process, save it.
if ($file->locked() !== false) {
$this->messages[] = 'Saving compiled blueprints.';
@@ -263,14 +286,71 @@ class Config extends Data
protected function loadCompiledConfig($configs, $plugins, $filename = null)
{
$checksum = md5(json_encode($configs));
$filename = $filename
? CACHE_DIR . 'compiled/config/' . $filename . '-' . $this->environment . '.php'
: CACHE_DIR . 'compiled/config/' . $checksum . '-' . $this->environment . '.php';
$file = PhpFile::instance($filename);
$cache = $file->exists() ? $file->content() : null;
$class = get_class($this);
$checksum = $this->checksum();
if (
!is_array($cache)
|| !isset($cache['checksum'])
|| !isset($cache['@class'])
|| $cache['@class'] != $class
) {
$this->messages[] = 'No cached configuration, compiling new configuration..';
} else if ($cache['checksum'] !== $checksum) {
$this->messages[] = 'Configuration checksum mismatch, reloading configuration..';
} else {
$this->messages[] = 'Configuration checksum matches, using cached version.';
$this->items = $cache['data'];
return;
}
$configFiles = $this->finder->locateConfigFiles($configs, $plugins);
$checksum .= ':'.md5(json_encode($configFiles));
// Attempt to lock the file for writing.
$file->lock(false);
// Load configuration.
foreach ($configFiles as $files) {
$this->loadConfigFiles($files);
}
$cache = [
'@class' => $class,
'timestamp' => time(),
'checksum' => $checksum,
'data' => $this->toArray()
];
// If compiled file wasn't already locked by another process, save it.
if ($file->locked() !== false) {
$this->messages[] = 'Saving compiled configuration.';
$file->save($cache);
$file->unlock();
}
$this->items = $cache['data'];
}
/**
* @param $languages
* @param $plugins
* @param null $filename
*/
protected function loadCompiledLanguages($languages, $plugins, $filename = null)
{
$checksum = md5(json_encode($languages));
$filename = $filename
? CACHE_DIR . 'compiled/languages/' . $filename . '-' . $this->environment . '.php'
: CACHE_DIR . 'compiled/languages/' . $checksum . '-' . $this->environment . '.php';
$file = PhpFile::instance($filename);
$cache = $file->exists() ? $file->content() : null;
$languageFiles = $this->finder->locateLanguageFiles($languages, $plugins);
$checksum .= ':' . md5(json_encode($languageFiles));
$class = get_class($this);
// Load real file if cache isn't up to date (or is invalid).
@@ -284,26 +364,41 @@ class Config extends Data
// Attempt to lock the file for writing.
$file->lock(false);
// Load configuration.
foreach ($configFiles as $files) {
$this->loadConfigFiles($files);
}
$cache = [
'@class' => $class,
'timestamp' => time(),
'checksum' => $this->checksum(),
'data' => $this->toArray()
];
// Load languages.
$this->languages = new Languages;
if (isset($languageFiles['user/plugins'])) {
foreach ((array) $languageFiles['user/plugins'] as $plugin => $item) {
$lang_file = CompiledYamlFile::instance($item['file']);
$content = $lang_file->content();
$this->languages->mergeRecursive($content);
}
unset($languageFiles['user/plugins']);
}
foreach ($languageFiles as $location) {
foreach ($location as $lang => $item) {
$lang_file = CompiledYamlFile::instance($item['file']);
$content = $lang_file->content();
$this->languages->join($lang, $content, '/');
}
}
$cache = [
'@class' => $class,
'checksum' => $checksum,
'files' => $languageFiles,
'data' => $this->languages->toArray()
];
// If compiled file wasn't already locked by another process, save it.
if ($file->locked() !== false) {
$this->messages[] = 'Saving compiled configuration.';
$this->messages[] = 'Saving compiled languages.';
$file->save($cache);
$file->unlock();
}
} else {
$this->languages = new Languages($cache['data']);
}
$this->items = $cache['data'];
}
/**
@@ -331,4 +426,52 @@ class Config extends Data
$this->join($name, $file->content(), '/');
}
}
/**
* Initialize resource locator by using the configuration.
*
* @param UniformResourceLocator $locator
*/
public function initializeLocator(UniformResourceLocator $locator)
{
$locator->reset();
$schemes = (array) $this->get('streams.schemes', []);
foreach ($schemes as $scheme => $config) {
if (isset($config['paths'])) {
$locator->addPath($scheme, '', $config['paths']);
}
if (isset($config['prefixes'])) {
foreach ($config['prefixes'] as $prefix => $paths) {
$locator->addPath($scheme, $prefix, $paths);
}
}
}
}
/**
* Get available streams and their types from the configuration.
*
* @return array
*/
public function getStreams()
{
$schemes = [];
foreach ((array) $this->get('streams.schemes') as $scheme => $config) {
$type = !empty($config['type']) ? $config['type'] : 'ReadOnlyStream';
if ($type[0] != '\\') {
$type = '\\RocketTheme\\Toolbox\\StreamWrapper\\' . $type;
}
$schemes[$scheme] = $type;
}
return $schemes;
}
public function getLanguages()
{
return $this->languages;
}
}

View File

@@ -49,6 +49,18 @@ class ConfigFinder
return $list;
}
public function locateLanguageFiles(array $languages, array $plugins)
{
$list = [];
foreach (array_reverse($plugins) as $folder) {
$list += $this->detectLanguagesInFolder($folder, 'languages');
}
foreach (array_reverse($languages) as $folder) {
$list += $this->detectRecursive($folder);
}
return $list;
}
/**
* Get all locations for a single configuration file.
*
@@ -90,11 +102,11 @@ class ConfigFinder
$list = [];
if (is_dir($folder)) {
$iterator = new \DirectoryIterator($folder);
$iterator = new \FilesystemIterator($folder);
/** @var \DirectoryIterator $directory */
foreach ($iterator as $directory) {
if (!$directory->isDir() || $directory->isDot()) {
if (!$directory->isDir()) {
continue;
}
@@ -111,6 +123,34 @@ class ConfigFinder
return [$path => $list];
}
protected function detectLanguagesInFolder($folder, $lookup = null)
{
$path = trim(Folder::getRelativePath($folder), '/');
$list = [];
if (is_dir($folder)) {
$iterator = new \FilesystemIterator($folder);
/** @var \DirectoryIterator $directory */
foreach ($iterator as $directory) {
if (!$directory->isDir()) {
continue;
}
$name = $directory->getBasename();
$find = ($lookup ?: $name) . '.yaml';
$filename = "{$path}/{$name}/$find";
if (file_exists($filename)) {
$list[$name] = ['file' => $filename, 'modified' => filemtime($filename)];
}
}
}
return [$path => $list];
}
/**
* Detects all plugins with a configuration file and returns them with last modification time.
*

View File

@@ -0,0 +1,27 @@
<?php
namespace Grav\Common\Config;
use Grav\Common\Data\Data;
/**
* The Languages class contains configuration rules.
*
* @author RocketTheme
* @license MIT
*/
class Languages extends Data
{
public function reformat()
{
if (isset($this->items['plugins'])) {
$this->items = array_merge_recursive($this->items, $this->items['plugins']);
unset($this->items['plugins']);
}
}
public function mergeRecursive(array $data)
{
$this->items = array_merge_recursive($this->items, $data);
}
}

View File

@@ -1,6 +1,7 @@
<?php
namespace Grav\Common\Data;
use Grav\Common\GravTrait;
use RocketTheme\Toolbox\ArrayTraits\Export;
/**
@@ -11,7 +12,7 @@ use RocketTheme\Toolbox\ArrayTraits\Export;
*/
class Blueprint
{
use Export;
use Export, DataMutatorTrait, GravTrait;
public $name;
@@ -46,68 +47,6 @@ class Blueprint
$this->filter = array_flip($filter);
}
/**
* Get value by using dot notation for nested arrays/objects.
*
* @example $value = $data->get('this.is.my.nested.variable');
*
* @param string $name Dot separated path to the requested value.
* @param mixed $default Default value (or null).
* @param string $separator Separator, defaults to '.'
*
* @return mixed Value.
*/
public function get($name, $default = null, $separator = '.')
{
$path = explode($separator, $name);
$current = $this->items;
foreach ($path as $field) {
if (is_object($current) && isset($current->{$field})) {
$current = $current->{$field};
} elseif (is_array($current) && isset($current[$field])) {
$current = $current[$field];
} else {
return $default;
}
}
return $current;
}
/**
* Sey value by using dot notation for nested arrays/objects.
*
* @example $value = $data->set('this.is.my.nested.variable', true);
*
* @param string $name Dot separated path to the requested value.
* @param mixed $value New value.
* @param string $separator Separator, defaults to '.'
*/
public function set($name, $value, $separator = '.')
{
$path = explode($separator, $name);
$current = &$this->items;
foreach ($path as $field) {
if (is_object($current)) {
// Handle objects.
if (!isset($current->{$field})) {
$current->{$field} = array();
}
$current = &$current->{$field};
} else {
// Handle arrays and scalars.
if (!is_array($current)) {
$current = array($field => array());
} elseif (!isset($current[$field])) {
$current[$field] = array();
}
$current = &$current[$field];
}
}
$current = $value;
}
/**
* Return all form fields.
*
@@ -137,7 +76,7 @@ class Blueprint
try {
$this->validateArray($data, $this->nested);
} catch (\RuntimeException $e) {
throw new \RuntimeException(sprintf('Page validation failed: %s', $e->getMessage()));
throw new \RuntimeException(sprintf('<b>Validation failed:</b> %s', $e->getMessage()));
}
}
@@ -146,10 +85,9 @@ class Blueprint
*
* @param array $data1
* @param array $data2
* @param string $name
* @return array
*/
public function mergeData(array $data1, array $data2, $name = null)
public function mergeData(array $data1, array $data2)
{
// Initialize data
$this->fields();
@@ -180,7 +118,17 @@ class Blueprint
{
// Initialize data
$this->fields();
return $this->extraArray($data, $this->nested, $prefix);
$rules = $this->nested;
// 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);
}
/**
@@ -213,7 +161,7 @@ class Blueprint
$bref = array_merge($bref, array($key => $head[$key]));
}
}
} while(count($head_stack));
} while (count($head_stack));
$this->items = $blueprints;
}
@@ -349,7 +297,7 @@ class Blueprint
// 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);
$array += $this->ExtraArray($field, $val, $prefix . $key . '.');
} else {
// Undefined/extra item.
$array[$prefix.$key] = $field;
@@ -376,11 +324,11 @@ class Blueprint
$field['name'] = $prefix . $key;
$field += $params;
if (isset($field['fields'])) {
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 {
} else if ($field['type'] !== 'ignore') {
// Add rule.
$this->rules[$prefix . $key] = &$field;
$this->addProperty($prefix . $key);
@@ -425,10 +373,20 @@ class Blueprint
}
}
}
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;
}
}
}
// Initialize predefined validation rule.
if (isset($field['validate']['rule'])) {
if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') {
$field['validate'] += $this->getRule($field['validate']['rule']);
}
}
@@ -478,14 +436,15 @@ class Blueprint
* @throws \RuntimeException
* @internal
*/
protected function checkRequired(array $data, array $fields) {
protected function checkRequired(array $data, array $fields)
{
foreach ($fields as $name => $field) {
if (!is_string($field)) {
continue;
}
$field = $this->rules[$field];
if (isset($field['validate']['required'])
&& $field['validate']['required'] == true
&& $field['validate']['required'] === true
&& empty($data[$name])) {
throw new \RuntimeException("Missing required field: {$field['name']}");
}

View File

@@ -2,6 +2,8 @@
namespace Grav\Common\Data;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\GravTrait;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Blueprints class keeps track on blueprint instances.
@@ -11,6 +13,8 @@ use Grav\Common\File\CompiledYamlFile;
*/
class Blueprints
{
use GravTrait;
protected $search;
protected $types;
protected $instances = array();
@@ -20,11 +24,7 @@ class Blueprints
*/
public function __construct($search)
{
if (!is_string($search)) {
$this->search = $search;
} else {
$this->search = rtrim($search, '\\/') . '/';
}
$this->search = $search;
}
/**
@@ -37,8 +37,18 @@ class Blueprints
public function get($type)
{
if (!isset($this->instances[$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] : '';
}
@@ -47,7 +57,6 @@ class Blueprints
$file = CompiledYamlFile::instance($filename);
$blueprints = $file->content();
} else {
// throw new \RuntimeException("Blueprints for '{$type}' cannot be found! {$this->search}{$type}");
$blueprints = [];
}
@@ -56,8 +65,41 @@ class Blueprints
if (isset($blueprints['@extends'])) {
// Extend blueprint by other blueprints.
$extends = (array) $blueprints['@extends'];
foreach ($extends as $extendType) {
$blueprint->extend($this->get($extendType));
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));
}
}
@@ -77,7 +119,18 @@ class Blueprints
if ($this->types === null) {
$this->types = array();
$iterator = new \DirectoryIterator($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);
}
/** @var \DirectoryIterator $file */
foreach ($iterator as $file) {
if (!$file->isFile() || '.' . $file->getExtension() != YAML_EXT) {

View File

@@ -15,7 +15,7 @@ use RocketTheme\Toolbox\File\FileInterface;
*/
class Data implements DataInterface
{
use ArrayAccessWithGetters, Countable, Export;
use ArrayAccessWithGetters, Countable, Export, DataMutatorTrait;
protected $gettersVariable = 'items';
protected $items;
@@ -56,67 +56,6 @@ class Data implements DataInterface
return $this->get($name, $default, $separator);
}
/**
* Get value by using dot notation for nested arrays/objects.
*
* @example $value = $data->get('this.is.my.nested.variable');
*
* @param string $name Dot separated path to the requested value.
* @param mixed $default Default value (or null).
* @param string $separator Separator, defaults to '.'
* @return mixed Value.
*/
public function get($name, $default = null, $separator = '.')
{
$path = explode($separator, $name);
$current = $this->items;
foreach ($path as $field) {
if (is_object($current) && isset($current->{$field})) {
$current = $current->{$field};
} elseif (is_array($current) && isset($current[$field])) {
$current = $current[$field];
} else {
return $default;
}
}
return $current;
}
/**
* Sey value by using dot notation for nested arrays/objects.
*
* @example $value = $data->set('this.is.my.nested.variable', true);
*
* @param string $name Dot separated path to the requested value.
* @param mixed $value New value.
* @param string $separator Separator, defaults to '.'
*/
public function set($name, $value, $separator = '.')
{
$path = explode($separator, $name);
$current = &$this->items;
foreach ($path as $field) {
if (is_object($current)) {
// Handle objects.
if (!isset($current->{$field})) {
$current->{$field} = array();
}
$current = &$current->{$field};
} else {
// Handle arrays and scalars.
if (!is_array($current)) {
$current = array($field => array());
} elseif (!isset($current[$field])) {
$current[$field] = array();
}
$current = &$current[$field];
}
}
$current = $value;
}
/**
* Set default value by using dot notation for nested arrays/objects.
*

View File

@@ -0,0 +1,68 @@
<?php
namespace Grav\Common\Data;
trait DataMutatorTrait
{
/**
* Get value by using dot notation for nested arrays/objects.
*
* @example $value = $data->get('this.is.my.nested.variable');
*
* @param string $name Dot separated path to the requested value.
* @param mixed $default Default value (or null).
* @param string $separator Separator, defaults to '.'
* @return mixed Value.
*/
public function get($name, $default = null, $separator = '.')
{
$path = explode($separator, $name);
$current = $this->items;
foreach ($path as $field) {
if (is_object($current) && isset($current->{$field})) {
$current = $current->{$field};
} elseif (is_array($current) && isset($current[$field])) {
$current = $current[$field];
} else {
return $default;
}
}
return $current;
}
/**
* Set value by using dot notation for nested arrays/objects.
*
* @example $value = $data->set('this.is.my.nested.variable', true);
*
* @param string $name Dot separated path to the requested value.
* @param mixed $value New value.
* @param string $separator Separator, defaults to '.'
*/
public function set($name, $value, $separator = '.')
{
$path = explode($separator, $name);
$current = &$this->items;
foreach ($path as $field) {
if (is_object($current)) {
// Handle objects.
if (!isset($current->{$field})) {
$current->{$field} = array();
}
$current = &$current->{$field};
} else {
// Handle arrays and scalars.
if (!is_array($current)) {
$current = array($field => array());
} elseif (!isset($current[$field])) {
$current[$field] = array();
}
$current = &$current[$field];
}
}
$current = $value;
}
}

View File

@@ -1,5 +1,8 @@
<?php
namespace Grav\Common\Data;
use Grav\Common\GravTrait;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser;
/**
* Data validation.
@@ -9,6 +12,8 @@ namespace Grav\Common\Data;
*/
class Validation
{
use GravTrait;
/**
* Validate value against a blueprint field definition.
*
@@ -25,17 +30,22 @@ class Validation
return;
}
// 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($field['label'] ? $field['label'] : $field['name']);
$message = (string) isset($field['validate']['message']) ? $field['validate']['message'] : 'Invalid input in "' . $language->translate($name) . '""';
if (method_exists(__CLASS__, $method)) {
$success = self::$method($value, $validate, $field);
} else {
$success = self::typeText($value, $validate, $field);
}
if (!$success) {
$name = $field['label'] ? $field['label'] : $field['name'];
throw new \RuntimeException("invalid input in {$name}");
throw new \RuntimeException($message);
}
// Check individual rules
@@ -43,8 +53,9 @@ class Validation
$method = 'validate'.strtr($rule, '-', '_');
if (method_exists(__CLASS__, $method)) {
$success = self::$method($value, $params);
if (!$success) {
throw new \RuntimeException('Failed');
throw new \RuntimeException($message);
}
}
}
@@ -66,6 +77,16 @@ class Validation
return null;
}
// 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());
}
}
// Validate type with fallback type text.
$type = (string) isset($field['validate']['type']) ? $field['validate']['type'] : $field['type'];
$method = 'filter'.strtr($type, '-', '_');
@@ -285,6 +306,17 @@ class Validation
return (int) $value;
}
protected static function filterDateTime($value, array $params, array $field)
{
$format = self::getGrav()['config']->get('system.pages.dateformat.default');
if ($format) {
$converted = new \DateTime($value);
return $converted->format($format);
}
return $value;
}
/**
* HTML5 input: range
*
@@ -375,7 +407,7 @@ class Validation
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeDatetime_local($value, array $params, array $field)
public static function typeDatetimeLocal($value, array $params, array $field)
{
return self::typeDatetime($value, $params, $field);
}
@@ -489,6 +521,7 @@ class Validation
{
$values = (array) $value;
$options = isset($field['options']) ? array_keys($field['options']) : array();
$multi = isset($field['multiple']) ? $field['multiple'] : false;
if ($options) {
$useKey = isset($field['use']) && $field['use'] == 'keys';
@@ -497,9 +530,39 @@ class Validation
}
}
if ($multi) {
foreach ($values as $key => $value) {
$values[$key] = explode(',', $value[0]);
}
}
return $values;
}
public static function typeList($value, array $params, array $field)
{
if (!is_array($value)) {
return false;
}
if (isset($field['fields'])) {
foreach ($value as $key => $item) {
foreach ($field['fields'] as $subKey => $subField) {
$subKey = trim($subKey, '.');
$subValue = isset($item[$subKey]) ? $item[$subKey] : null;
self::validate($subValue, $subField);
}
}
}
return true;
}
protected static function filterList($value, array $params, array $field)
{
return (array) $value;
}
/**
* Custom input: ignore (will not validate)
*
@@ -513,11 +576,16 @@ class Validation
return true;
}
public static function filterIgnore($value, array $params, array $field)
{
return $value;
}
// HTML5 attributes (min, max and range are handled inside the types)
public static function validateRequired($value, $params)
{
return (bool) $params != true || !empty($value);
return (bool) $params !== true || !empty($value);
}
public static function validatePattern($value, $params)

View File

@@ -1,10 +1,8 @@
<?php
namespace Grav\Common;
use DebugBar\Bridge\Twig\TraceableTwigEnvironment;
use DebugBar\JavascriptRenderer;
use DebugBar\StandardDebugBar;
//use \Tracy\Debugger as TracyDebugger;
/**
* Class Debugger
@@ -48,9 +46,11 @@ class Debugger
public function addAssets()
{
if ($this->enabled()) {
$assets = $this->grav['assets'];
// Add jquery library
$assets->add('jquery', 101);
$this->renderer = $this->debugbar->getJavascriptRenderer();
$this->renderer->setIncludeVendors(false);

View File

@@ -4,9 +4,6 @@ namespace Grav\Common\Errors;
use Grav\Common\Grav;
use Whoops\Handler\CallbackHandler;
use Whoops\Handler\HandlerInterface;
use Whoops\Handler\JsonResponseHandler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Handler\PlainTextHandler;
use Whoops\Run;
/**
@@ -23,7 +20,7 @@ class Errors extends \Whoops\Run
}
if (!$handler instanceof HandlerInterface) {
throw new InvalidArgumentException(
throw new \InvalidArgumentException(
"Argument to " . __METHOD__ . " must be a callable, or instance of"
. "Whoops\\Handler\\HandlerInterface"
);

View File

@@ -48,4 +48,5 @@ h6 {
code {
font-weight: bold;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}

View File

@@ -16,10 +16,14 @@
<header>
Server Error
</header>
<p>We're sorry! The server has encountered an internal error and was unable to complete your request.
Please contact the system administrator for more information.</p>
<h6>For further details please review your <code>logs/</code> folder, or enable displaying of errors in your system configuration.</h6>
<h6>Error Code: <b><?php echo $code ?></b></h6>
<p>Sorry, something went terribly wrong!</p>
<h3><?php echo $code ?> - <?php echo $message ?></h3>
<h5>For further details please review your <code>logs/</code> folder, or enable displaying of errors in your system configuration.</h5>
</div>
</div>
</body>

View File

@@ -21,15 +21,14 @@ class SimplePageHandler extends Handler
*/
public function handle()
{
$exception = $this->getException();
$inspector = $this->getInspector();
$run = $this->getRun();
$helper = new TemplateHelper();
$templateFile = $this->getResource("layout.html.php");
$cssFile = $this->getResource("error.css");
$code = $inspector->getException()->getCode();
$message = $inspector->getException()->getMessage();
if ($inspector->getException() instanceof \ErrorException) {
$code = Misc::translateErrorCode($code);
@@ -38,6 +37,7 @@ class SimplePageHandler extends Handler
$vars = array(
"stylesheet" => file_get_contents($cssFile),
"code" => $code,
"message" => $message,
);
$helper->setVariables($vars);
@@ -46,6 +46,11 @@ class SimplePageHandler extends Handler
return Handler::QUIT;
}
/**
* @param $resource
*
* @return string
*/
protected function getResource($resource)
{
// If the resource was found before, we can speed things up
@@ -67,7 +72,7 @@ class SimplePageHandler extends Handler
}
// If we got this far, nothing was found.
throw new RuntimeException(
throw new \RuntimeException(
"Could not find resource '$resource' in any resource paths."
. "(searched: " . join(", ", $this->searchPaths). ")"
);
@@ -76,7 +81,7 @@ class SimplePageHandler extends Handler
public function addResourcePath($path)
{
if (!is_dir($path)) {
throw new InvalidArgumentException(
throw new \InvalidArgumentException(
"'$path' is not a valid directory"
);
}

View File

@@ -25,7 +25,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 . "/compiled/files/{$key}{$this->extension}.php");
$file = PhpFile::instance(CACHE_DIR . "compiled/files/{$key}{$this->extension}.php");
$modified = $this->modified();
if (!$modified) {

View File

@@ -19,12 +19,13 @@ abstract class Folder
{
$last_modified = 0;
$directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($directory, \RecursiveIteratorIterator::SELF_FIRST);
$dirItr = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
$filterItr = new RecursiveFolderFilterIterator($dirItr);
$itr = new \RecursiveIteratorIterator($filterItr, \RecursiveIteratorIterator::SELF_FIRST);
/** @var \RecursiveDirectoryIterator $file */
foreach ($iterator as $file) {
$dir_modified = $file->getMTime();
foreach ($itr as $dir) {
$dir_modified = $dir->getMTime();
if ($dir_modified > $last_modified) {
$last_modified = $dir_modified;
}
@@ -33,33 +34,24 @@ abstract class Folder
return $last_modified;
}
public static function getRelativePath($to, $from = ROOT_DIR)
{
$from = preg_replace('![\\|/]+!', '/', $from);
$to = preg_replace('![\\|/]+!', '/', $to);
if (strpos($to, $from) === 0) {
$to = substr($to, strlen($from));
}
return $to;
}
/**
* Recursively find the last modified time under given path by file.
*
* @param string $path
* @param string $extensions which files to search for specifically
*
* @return int
*/
public static function lastModifiedFile($path)
public static function lastModifiedFile($path, $extensions = 'md|yaml')
{
$last_modified = 0;
$dirItr = new \RecursiveDirectoryIterator($path);
$filterItr = new GravRecursiveFilterIterator($dirItr);
$itr = new \RecursiveIteratorIterator($filterItr, \RecursiveIteratorIterator::SELF_FIRST);
$dirItr = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
$itrItr = new \RecursiveIteratorIterator($dirItr, \RecursiveIteratorIterator::SELF_FIRST);
$itr = new \RegexIterator($itrItr, '/^.+\.'.$extensions.'$/i');
/** @var \RecursiveDirectoryIterator $file */
foreach ($itr as $file) {
foreach ($itr as $filepath => $file) {
$file_modified = $file->getMTime();
if ($file_modified > $last_modified) {
$last_modified = $file_modified;
@@ -69,6 +61,43 @@ abstract class Folder
return $last_modified;
}
/**
* Get relative path between target and base path. If path isn't relative, return full path.
*
* @param string $path
* @param string $base
* @return string
*/
public static function getRelativePath($path, $base = GRAV_ROOT)
{
if ($base) {
$base = preg_replace('![\\\/]+!', '/', $base);
$path = preg_replace('![\\\/]+!', '/', $path);
if (strpos($path, $base) === 0) {
$path = ltrim(substr($path, strlen($base)), '/');
}
}
return $path;
}
/**
* Shift first directory out of the path.
*
* @param string $path
* @return string
*/
public static function shift(&$path)
{
$parts = explode('/', trim($path, '/'), 2);
$result = array_shift($parts);
$path = array_shift($parts);
return $result ?: null;
}
/**
* Return recursive list of all files and directories under given path.
*
@@ -208,8 +237,9 @@ abstract class Folder
/**
* Recursively delete directory from filesystem.
*
* @param string $target
* @param string $target
* @throws \RuntimeException
* @return bool
*/
public static function delete($target)
{
@@ -248,6 +278,46 @@ abstract class Folder
}
}
/**
* Recursive copy of one directory to another
*
* @param $src
* @param $dest
*
* @return bool
*/
public static function rcopy($src, $dest)
{
// If the src is not a directory do a simple file copy
if (!is_dir($src)) {
copy($src, $dest);
return true;
}
// If the destination directory does not exist create it
if (!is_dir($dest)) {
if (!mkdir($dest)) {
// If the destination directory could not be created stop processing
return false;
}
}
// Open the source directory to read in files
$i = new \DirectoryIterator($src);
/** @var \DirectoryIterator $f */
foreach ($i as $f) {
if ($f->isFile()) {
copy($f->getRealPath(), "$dest/" . $f->getFilename());
} else {
if (!$f->isDot() && $f->isDir()) {
static::rcopy($f->getRealPath(), "$dest/$f");
}
}
}
return true;
}
/**
* @param string $folder
* @return bool
@@ -260,30 +330,24 @@ abstract class Folder
return @unlink($folder);
}
// Go through all items in filesystem and recursively remove everything.
$files = array_diff(scandir($folder), array('.', '..'));
foreach ($files as $file) {
$path = "{$folder}/{$file}";
(is_dir($path)) ? self::doDelete($path) : @unlink($path);
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($folder, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
);
/** @var \DirectoryIterator $fileinfo */
foreach ($files as $fileinfo) {
if ($fileinfo->isDir()) {
if (false === rmdir($fileinfo->getRealPath())) {
return false;
}
} else {
if (false === unlink($fileinfo->getRealPath())) {
return false;
}
}
}
return @rmdir($folder);
return rmdir($folder);
}
}
class GravRecursiveFilterIterator extends \RecursiveFilterIterator
{
public static $FILTERS = array(
'..', '.DS_Store'
);
public function accept()
{
return !in_array(
$this->current()->getFilename(),
self::$FILTERS,
true
);
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Grav\Common\Filesystem;
use Grav\Common\GravTrait;
class RecursiveFolderFilterIterator extends \RecursiveFilterIterator
{
use GravTrait;
protected static $folder_ignores;
public function __construct(\RecursiveIterator $iterator)
{
parent::__construct($iterator);
if (empty($this::$folder_ignores)) {
$this::$folder_ignores = self::getGrav()['config']->get('system.pages.ignore_folders');
}
}
public function accept()
{
/** @var $current \SplFileInfo */
$current = $this->current();
if ($current->isDir() && !in_array($current->getFilename(), $this::$folder_ignores)) {
return true;
}
return false;
}
}

View File

@@ -1,19 +1,19 @@
<?php
namespace Grav\Common\GPM\Local;
namespace Grav\Common\GPM;
use Grav\Common\GravTrait;
use Grav\Common\Iterator;
class Collection extends Iterator
{
abstract class AbstractCollection extends Iterator {
use GravTrait;
public function toJson()
{
$items = [];
foreach ($this->items as $name => $theme) {
$items[$name] = $theme->toArray();
foreach ($this->items as $name => $package) {
$items[$name] = $package->toArray();
}
return json_encode($items);
@@ -23,8 +23,8 @@ class Collection extends Iterator
{
$items = [];
foreach ($this->items as $name => $theme) {
$items[$name] = $theme->toArray();
foreach ($this->items as $name => $package) {
$items[$name] = $package->toArray();
}
return $items;

View File

@@ -0,0 +1,34 @@
<?php
namespace Grav\Common\GPM\Common;
use Grav\Common\GravTrait;
use Grav\Common\Iterator;
abstract class AbstractPackageCollection extends Iterator {
use GravTrait;
protected $type;
public function toJson()
{
$items = [];
foreach ($this->items as $name => $package) {
$items[$name] = $package->toArray();
}
return json_encode($items);
}
public function toArray()
{
$items = [];
foreach ($this->items as $name => $package) {
$items[$name] = $package->toArray();
}
return $items;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Grav\Common\GPM\Common;
use Grav\Common\Iterator;
class CachedCollection extends Iterator {
protected static $cache;
public function __construct($items)
{
// local cache to speed things up
if (!isset(self::$cache[get_called_class().__METHOD__])) {
self::$cache[get_called_class().__METHOD__] = $items;
}
foreach (self::$cache[get_called_class().__METHOD__] as $name => $item) {
$this->append([$name => $item]);
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Grav\Common\GPM\Common;
use Grav\Common\Data\Data;
class Package {
protected $data;
public function __construct(Data $package, $type = null) {
$this->data = $package;
if ($type) {
$this->data->set('package_type', $type);
}
}
public function getData() {
return $this->data;
}
public function __get($key) {
return $this->data->get($key);
}
public function __isset($key) {
return isset($this->data->$key);
}
public function __toString() {
return $this->toJson();
}
public function toJson() {
return $this->data->toJson();
}
public function toArray() {
return $this->data->toArray();
}
}

View File

@@ -1,7 +1,9 @@
<?php
namespace Grav\Common\GPM;
use Grav\Common\Inflector;
use Grav\Common\Iterator;
use Grav\Common\Utils;
class GPM extends Iterator
{
@@ -28,6 +30,8 @@ class GPM extends Iterator
*/
protected $cache;
protected $install_paths = ['plugins' => 'user/plugins/%name%', 'themes' => 'user/themes/%name%', 'skeletons' => 'user/'];
/**
* Creates a new GPM instance with Local and Remote packages available
* @param boolean $refresh Applies to Remote Packages only and forces a refetch of data
@@ -345,9 +349,23 @@ class GPM extends Iterator
public function findPackages($searches = [])
{
$packages = ['total' => 0, 'not_found' => []];
$inflector = new Inflector();
foreach ($searches as $search) {
$repository = '';
// if this is an object, get the search data from the key
if (is_object($search)) {
$search = (array) $search;
$key = key($search);
$repository = $search[$key];
$search = $key;
}
if ($found = $this->findPackage($search)) {
// set override repository if provided
if ($repository) {
$found->override_repository = $repository;
}
if (!isset($packages[$found->package_type])) {
$packages[$found->package_type] = [];
}
@@ -355,7 +373,20 @@ class GPM extends Iterator
$packages[$found->package_type][$found->slug] = $found;
$packages['total']++;
} else {
$packages['not_found'][] = $search;
// make a best guess at the type based on the repo URL
if (Utils::contains($repository, '-theme')) {
$type = 'themes';
} else {
$type = 'plugins';
}
$not_found = new \stdClass();
$not_found->name = $inflector->camelize($search);
$not_found->slug = $search;
$not_found->package_type = $type;
$not_found->install_path = str_replace('%name%', $search, $this->install_paths[$type]);
$not_found->override_repository = $repository;
$packages['not_found'][$search] = $not_found;
}
}

View File

@@ -61,21 +61,18 @@ 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']
) {
if (self::lastErrorCode() == self::IS_LINK && $options['ignore_symlinks'] ||
self::lastErrorCode() == self::EXISTS && !$options['overwrite']) {
return false;
}
$zip = new \ZipArchive();
$archive = $zip->open($package);
$tmp = CACHE_DIR . DS . 'tmp/Grav-' . uniqid();
$tmp = CACHE_DIR . 'tmp/Grav-' . uniqid();
if ($archive !== true) {
self::$error = self::ZIP_OPEN_ERROR;
@@ -112,7 +109,7 @@ class Installer
}
public static function nonSophisticatedInstall($zip, $install_path, $tmp)
public static function nonSophisticatedInstall(\ZipArchive $zip, $install_path, $tmp)
{
$container = $zip->getNameIndex(0); // TODO: better way of determining if zip has container folder
if (file_exists($install_path)) {
@@ -124,7 +121,7 @@ class Installer
return true;
}
public static function sophisticatedInstall($zip, $install_path, $tmp)
public static function sophisticatedInstall(\ZipArchive $zip, $install_path, $tmp)
{
for ($i = 0, $l = $zip->numFiles; $i < $l; $i++) {
$filename = $zip->getNameIndex($i);
@@ -161,9 +158,9 @@ class Installer
/**
* Unnstalls one or more given package
* Uninstalls one or more given package
*
* @param string $package The slug of the package(s)
* @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.
@@ -290,4 +287,14 @@ class Installer
{
return self::$error;
}
/**
* Allows to manually set an error
* @param $error the Error code
*/
public static function setError($error)
{
self::$error = $error;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Grav\Common\GPM\Local;
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
use Grav\Common\GPM\Local\Package;
abstract class AbstractPackageCollection extends BaseCollection {
public function __construct($items)
{
foreach ($items as $name => $data) {
$data->set('slug', $name);
$this->items[$name] = new Package($data, $this->type);
}
}
}

View File

@@ -2,39 +2,24 @@
namespace Grav\Common\GPM\Local;
use Grav\Common\Data\Data;
use Grav\Common\GPM\Common\Package as BasePackage;
/**
* Class Package
* @package Grav\Common\GPM\Local
*/
class Package
class Package extends BasePackage
{
/**
* @var Data
*/
protected $data;
/**
* @var \Grav\Common\Data\Blueprint
*/
protected $blueprints;
protected $settings;
/**
* @param Data $package
* @param bool $package_type
*/
public function __construct(Data $package, $package_type = false)
public function __construct(Data $package, $package_type = null)
{
$this->data = $package;
$this->blueprints = $this->data->blueprints();
$data = new Data($package->blueprints()->toArray());
parent::__construct($data, $package_type);
if ($package_type) {
$html_description = \Parsedown::instance()->line($this->blueprints->get('description'));
$this->blueprints->set('package_type', $package_type);
$this->blueprints->set('slug', $this->blueprints->name);
$this->blueprints->set('description_html', $html_description);
$this->blueprints->set('description_plain', strip_tags($html_description));
$this->blueprints->set('symlink', is_link(USER_DIR . $package_type . DS . $this->blueprints->name));
}
$this->settings = $package->toArray();
$html_description = \Parsedown::instance()->line($this->description);
$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->name));
}
/**
@@ -42,47 +27,6 @@ class Package
*/
public function isEnabled()
{
return $this->data['enabled'];
}
/**
* @return Data
*/
public function getData()
{
return $this->data;
}
/**
* @param $key
* @return mixed
*/
public function __get($key)
{
return $this->blueprints->get($key);
}
/**
* @return string
*/
public function __toString()
{
return $this->toJson();
}
/**
* @return string
*/
public function toJson()
{
return $this->blueprints->toJson();
}
/**
* @return array
*/
public function toArray()
{
return $this->blueprints->toArray();
return $this->settings['enabled'];
}
}

View File

@@ -1,28 +1,17 @@
<?php
namespace Grav\Common\GPM\Local;
use Grav\Common\Iterator;
use Grav\Common\GPM\Common\CachedCollection;
class Packages extends Iterator
class Packages extends CachedCollection
{
private $plugins;
private $themes;
protected static $cache;
public function __construct()
{
// local cache to speed things up
if (!isset(self::$cache[__METHOD__])) {
self::$cache[__METHOD__] = [
'plugins' => new Plugins(),
'themes' => new Themes()
];
}
$items = [
'plugins' => new Plugins(),
'themes' => new Themes()
];
$this->plugins = self::$cache[__METHOD__]['plugins'];
$this->themes = self::$cache[__METHOD__]['themes'];
$this->append(['plugins' => $this->plugins]);
$this->append(['themes' => $this->themes]);
parent::__construct($items);
}
}

View File

@@ -5,22 +5,18 @@ namespace Grav\Common\GPM\Local;
* Class Plugins
* @package Grav\Common\GPM\Local
*/
class Plugins extends Collection
class Plugins extends AbstractPackageCollection
{
/**
* @var string
*/
private $type = 'plugins';
protected $type = 'plugins';
/**
* Local Plugins Constructor
*/
public function __construct()
{
$grav = self::$grav;
foreach ($grav['plugins']->all() as $name => $data) {
$this->items[$name] = new Package($data, $this->type);
}
parent::__construct(self::getGrav()['plugins']->all());
}
}

View File

@@ -1,15 +1,22 @@
<?php
namespace Grav\Common\GPM\Local;
class Themes extends Collection
/**
* Class Themes
* @package Grav\Common\GPM\Local
*/
class Themes extends AbstractPackageCollection
{
private $type = 'themes';
/**
* @var string
*/
protected $type = 'themes';
/**
* Local Themes Constructor
*/
public function __construct()
{
$grav = self::$grav;
foreach ($grav['themes']->all() as $name => $data) {
$this->items[$name] = new Package($data, $this->type);
}
parent::__construct(self::getGrav()['themes']->all());
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Grav\Common\GPM;
use Grav\Common\Data\Data;
/**
* Interface Package
* @package Grav\Common\GPM
*/
class Package
{
/**
* @var Data
*/
protected $data;
/**
* @var \Grav\Common\Data\Blueprint
*/
protected $blueprints;
/**
* @param Data $package
* @param bool $package_type
*/
public function __construct(Data $package, $package_type = false);
/**
* @return mixed
*/
public function isEnabled();
/**
* @return Data
*/
public function getData();
/**
* @param $key
* @return mixed
*/
public function __get($key);
/**
* @return string
*/
public function __toString();
/**
* @return string
*/
public function toJson();
/**
* @return array
*/
public function toArray();
}

View File

@@ -0,0 +1,55 @@
<?php
namespace Grav\Common\GPM\Remote;
use Grav\Common\GPM\Common\AbstractPackageCollection as BaseCollection;
use Grav\Common\GPM\Response;
use \Doctrine\Common\Cache\FilesystemCache;
class AbstractPackageCollection extends BaseCollection
{
/**
* The cached data previously fetched
* @var string
*/
protected $raw;
/**
* The lifetime to store the entry in seconds
* @var integer
*/
private $lifetime = 86400;
protected $repository;
protected $cache;
public function __construct($repository = null, $refresh = false, $callback = null)
{
if ($repository === null) {
throw new \RuntimeException("A repository is required to indicate the origin of the remote collection");
}
$cache_dir = self::getGrav()['locator']->findResource('cache://gpm', true, true);
$this->cache = new FilesystemCache($cache_dir);
$this->repository = $repository;
$this->raw = $this->cache->fetch(md5($this->repository));
$this->fetch($refresh, $callback);
foreach (json_decode($this->raw, true) as $slug => $data) {
$this->items[$slug] = new Package($data, $this->type);
}
}
public function fetch($refresh = false, $callback = null)
{
if (!$this->raw || $refresh) {
$response = Response::get($this->repository, [], $callback);
$this->raw = $response;
$this->cache->save(md5($this->repository), $this->raw, $this->lifetime);
}
return $this->raw;
}
}

View File

@@ -1,70 +0,0 @@
<?php
namespace Grav\Common\GPM\Remote;
use Grav\Common\GPM\Response;
use Grav\Common\GravTrait;
use Grav\Common\Iterator;
use \Doctrine\Common\Cache\Cache as DoctrineCache;
use \Doctrine\Common\Cache\FilesystemCache;
class Collection extends Iterator {
use GravTrait;
/**
* The cached data previously fetched
* @var string
*/
protected $raw;
/**
* The lifetime to store the entry in seconds
* @var integer
*/
private $lifetime = 86400;
private $repository;
private $cache;
private $plugins, $themes;
public function __construct($repository = null) {
if ($repository == null) {
throw new \RuntimeException("A repository is required for storing the cache");
}
$cache_dir = self::$grav['locator']->findResource('cache://gpm', true, true);
$this->cache = new FilesystemCache($cache_dir);
$this->repository = $repository;
$this->raw = $this->cache->fetch(md5($this->repository));
}
public function toJson() {
$items = [];
foreach ($this->items as $name => $theme) {
$items[$name] = $theme->toArray();
}
return json_encode($items);
}
public function toArray() {
$items = [];
foreach ($this->items as $name => $theme) {
$items[$name] = $theme->toArray();
}
return $items;
}
public function fetch($refresh = false, $callback = null) {
if (!$this->raw || $refresh) {
$response = Response::get($this->repository, [], $callback);
$this->raw = $response;
$this->cache->save(md5($this->repository), $this->raw, $this->lifetime);
}
return $this->raw;
}
}

View File

@@ -1,9 +1,11 @@
<?php
namespace Grav\Common\GPM\Remote;
class Grav extends Collection
use \Doctrine\Common\Cache\FilesystemCache;
class Grav extends AbstractPackageCollection
{
private $repository = 'http://getgrav.org/downloads/grav.json';
protected $repository = 'http://getgrav.org/downloads/grav.json';
private $data;
private $version;
@@ -15,15 +17,17 @@ class Grav extends Collection
*/
public function __construct($refresh = false, $callback = null)
{
parent::__construct($this->repository);
$cache_dir = self::getGrav()['locator']->findResource('cache://gpm', true, true);
$this->cache = new FilesystemCache($cache_dir);
$this->raw = $this->cache->fetch(md5($this->repository));
$this->fetch($refresh, $callback);
$this->data = json_decode($this->raw);
$this->version = @$this->data->version ?: '-';
$this->date = @$this->data->date ?: '-';
$this->data = json_decode($this->raw, true);
$this->version = isset($this->data['version']) ? $this->data['version'] : '-';
$this->date = isset($this->data['date']) ? $this->data['date'] : '-';
foreach ($this->data->assets as $slug => $data) {
if (isset($this->data['assets'])) foreach ($this->data['assets'] as $slug => $data) {
$this->items[$slug] = new Package($data);
}
}
@@ -34,7 +38,7 @@ class Grav extends Collection
*/
public function getAssets()
{
return $this->data->assets;
return $this->data['assets'];
}
/**
@@ -46,11 +50,11 @@ class Grav extends Collection
public function getChangelog($diff = null)
{
if (!$diff) {
return $this->data->changelog;
return $this->data['changelog'];
}
$diffLog = [];
foreach ($this->data->changelog as $version => $changelog) {
foreach ($this->data['changelog'] as $version => $changelog) {
preg_match("/[\d\.]+/", $version, $cleanVersion);
if (!$cleanVersion || version_compare($diff, $cleanVersion[0], ">=")) { continue; }
@@ -83,4 +87,9 @@ class Grav extends Collection
{
return version_compare(GRAV_VERSION, $this->getVersion(), '<');
}
public function isSymlink()
{
return is_link(GRAV_ROOT . DS . 'index.php');
}
}

View File

@@ -1,32 +1,12 @@
<?php
namespace Grav\Common\GPM\Remote;
class Package {
public function __construct($package, $package_type = false) {
$this->data = $package;
if ($package_type) {
$this->data->package_type = $package_type;
}
}
use Grav\Common\Data\Data;
use Grav\Common\GPM\Common\Package as BasePackage;
public function getData() {
return $this->data;
class Package extends BasePackage {
public function __construct($package, $package_type = null) {
$data = new Data($package);
parent::__construct($data, $package_type);
}
public function __get($key) {
return $this->data->$key;
}
public function __toString() {
return $this->toJson();
}
public function toJson() {
return json_encode($this->data);
}
public function toArray() {
return $this->data;
}
}

View File

@@ -1,28 +1,17 @@
<?php
namespace Grav\Common\GPM\Remote;
use Grav\Common\Iterator;
use Grav\Common\GPM\Common\CachedCollection;
class Packages extends Iterator
class Packages extends CachedCollection
{
private $plugins;
private $themes;
protected static $cache;
public function __construct($refresh = false, $callback = null)
{
// local cache to speed things up
if (!isset(self::$cache[__METHOD__])) {
self::$cache[__METHOD__] = [
'plugins' => new Plugins($refresh, $callback),
'themes' => new Themes($refresh, $callback)
];
}
$items = [
'plugins' => new Plugins($refresh, $callback),
'themes' => new Themes($refresh, $callback)
];
$this->plugins = self::$cache[__METHOD__]['plugins']->toArray();
$this->themes = self::$cache[__METHOD__]['themes']->toArray();
$this->append(['plugins' => $this->plugins]);
$this->append(['themes' => $this->themes]);
parent::__construct($items);
}
}

View File

@@ -1,21 +1,24 @@
<?php
namespace Grav\Common\GPM\Remote;
class Plugins extends Collection
/**
* Class Plugins
* @package Grav\Common\GPM\Remote
*/
class Plugins extends AbstractPackageCollection
{
private $repository = 'http://getgrav.org/downloads/plugins.json';
private $type = 'plugins';
private $data;
/**
* @var string
*/
protected $type = 'plugins';
protected $repository = 'http://getgrav.org/downloads/plugins.json';
/**
* Local Plugins Constructor
*/
public function __construct($refresh = false, $callback = null)
{
parent::__construct($this->repository);
$this->fetch($refresh, $callback);
$this->data = json_decode($this->raw);
foreach ($this->data as $slug => $data) {
$this->items[$slug] = new Package($data, $this->type);
}
parent::__construct($this->repository, $refresh, $callback);
}
}

View File

@@ -1,21 +1,24 @@
<?php
namespace Grav\Common\GPM\Remote;
class Themes extends Collection
/**
* Class Themes
* @package Grav\Common\GPM\Remote
*/
class Themes extends AbstractPackageCollection
{
private $repository = 'http://getgrav.org/downloads/themes.json';
private $type = 'themes';
private $data;
/**
* @var string
*/
protected $type = 'themes';
protected $repository = 'http://getgrav.org/downloads/themes.json';
/**
* Local Themes Constructor
*/
public function __construct($refresh = false, $callback = null)
{
parent::__construct($this->repository);
$this->fetch($refresh, $callback);
$this->data = json_decode($this->raw);
foreach ($this->data as $slug => $data) {
$this->items[$slug] = new Package($data, $this->type);
}
parent::__construct($this->repository, $refresh, $callback);
}
}

View File

@@ -78,7 +78,6 @@ class Response
$method = 'get' . ucfirst(strtolower(self::$method));
self::$callback = $callback;
return static::$method($uri, $options, $callback);
}
@@ -161,6 +160,8 @@ class Response
private static function getCurl()
{
$args = func_get_args();
$args = count($args) > 1 ? $args : array_shift($args);
$uri = $args[0];
$options = $args[1];
$callback = $args[2];

View File

@@ -1,9 +1,6 @@
<?php
namespace Grav\Common\GPM;
use Grav\Common\Filesystem\Folder;
use Grav\Common\GPM\Installer;
class Upgrader
{
/**
@@ -68,7 +65,7 @@ class Upgrader
* Returns the changelog list for each version of Grav
* @param string $diff the version number to start the diff from
*
* @return array return the chagenlog list for each version
* @return array return the changelog list for each version
*/
public function getChangelog($diff = null)
{
@@ -83,4 +80,14 @@ class Upgrader
{
return version_compare($this->getLocalVersion(), $this->getRemoteVersion(), "<");
}
/**
* Checks if Grav is currently symbolically linked
* @return boolean True if Grav is symlinked, False otherwise.
*/
public function isSymlink()
{
return $this->remote->isSymlink();
}
}

View File

@@ -1,15 +1,17 @@
<?php
namespace Grav\Common;
use Grav\Common\Language\Language;
use Grav\Common\Page\Medium\ImageMedium;
use Grav\Common\Page\Pages;
use Grav\Common\Service\ConfigServiceProvider;
use Grav\Common\Service\ErrorServiceProvider;
use Grav\Common\Service\LoggerServiceProvider;
use Grav\Common\Service\StreamsServiceProvider;
use Grav\Common\Twig\Twig;
use RocketTheme\Toolbox\DI\Container;
use RocketTheme\Toolbox\Event\Event;
use RocketTheme\Toolbox\Event\EventDispatcher;
use Grav\Common\Page\Medium;
/**
* Grav
@@ -55,6 +57,8 @@ class Grav extends Container
$container['grav'] = $container;
$container['debugger'] = new Debugger();
$container['debugger']->startTimer('_init', 'Initialize');
@@ -76,8 +80,11 @@ class Grav extends Container
$container['cache'] = function ($c) {
return new Cache($c);
};
$container['session'] = function ($c) {
return new Session($c);
};
$container['plugins'] = function ($c) {
return new Plugins($c);
return new Plugins();
};
$container['themes'] = function ($c) {
return new Themes($c);
@@ -88,41 +95,38 @@ class Grav extends Container
$container['taxonomy'] = function ($c) {
return new Taxonomy($c);
};
$container['language'] = function ($c) {
return new Language($c);
};
$container['pages'] = function ($c) {
return new Page\Pages($c);
};
$container['assets'] = function ($c) {
return new Assets();
};
$container['assets'] = new Assets();
$container['page'] = function ($c) {
/** @var Pages $pages */
$pages = $c['pages'];
$page = $pages->dispatch($c['uri']->route());
/** @var Uri $uri */
$uri = $c['uri'];
$path = rtrim($uri->path(), '/');
$path = $path ?: '/';
$page = $pages->dispatch($path);
// handle redirect if not 'default route' configuration
if ($page && $c['config']->get('system.pages.redirect_default_route') && $page->route() != $path) {
$c->redirectLangSafe($page->route());
}
// if page is not found, try some fallback stuff
if (!$page || !$page->routable()) {
// special case where a media file is requested
if (!$page) {
$path_parts = pathinfo($c['uri']->route());
$page = $c['pages']->dispatch($path_parts['dirname']);
if ($page) {
$media = $page->media()->all();
$media_file = urldecode($path_parts['basename']);
if (isset($media[$media_file])) {
$medium = $media[$media_file];
// loop through actions for the image and call them
foreach ($c['uri']->query(null, true) as $action => $params) {
if (in_array($action, Medium::$valid_actions)) {
call_user_func_array(array(&$medium, $action), explode(',', $params));
}
}
header('Content-type: '. $mime = $medium->get('mime'));
echo file_get_contents($medium->path());
die;
}
}
}
// Try fallback URL stuff...
$c->fallbackUrl($page, $path);
// If no page found, fire event
$event = $c->fireEvent('onPageNotFound');
@@ -155,6 +159,8 @@ class Grav extends Container
$container->register(new StreamsServiceProvider);
$container->register(new ConfigServiceProvider);
$container['inflector'] = new Inflector();
$container['debugger']->stopTimer('_init');
return $container;
@@ -162,20 +168,37 @@ class Grav extends Container
public function process()
{
// Use output buffering to prevent headers from being sent too early.
ob_start();
/** @var Debugger $debugger */
$debugger = $this['debugger'];
// Initialize configuration.
$debugger->startTimer('_config', 'Configuration');
$this['config']->init();
$this['uri']->init();
$this['session']->init();
$this['errors']->resetHandlers();
$debugger->init();
$this['config']->debug();
$debugger->stopTimer('_config');
// Use output buffering to prevent headers from being sent too early.
ob_start();
if ($this['config']->get('system.cache.gzip')) {
ob_start('ob_gzhandler');
}
// Initialize the timezone
if ($this['config']->get('system.timezone')) {
date_default_timezone_set($this['config']->get('system.timezone'));
}
// Initialize Locale if set and configured
if ($this['language']->enabled() && $this['config']->get('system.languages.override_locale')) {
setlocale(LC_ALL, $this['language']->getLanguage());
} elseif ($this['config']->get('system.default_locale')) {
setlocale(LC_ALL, $this['config']->get('system.default_locale'));
}
$debugger->startTimer('streams', 'Streams');
$this['streams'];
$debugger->stopTimer('streams');
@@ -206,7 +229,6 @@ class Grav extends Container
$this['pages']->init();
$this->fireEvent('onPagesInitialized');
$debugger->stopTimer('pages');
$this->fireEvent('onPageInitialized');
$debugger->addAssets();
@@ -242,10 +264,34 @@ class Grav extends Container
$this['session']->close();
}
header("Location: " . rtrim($uri->rootUrl(), '/') .'/'. trim($route, '/'), true, $code);
if ($uri->isExternal($route)) {
$url = $route;
} else {
$url = rtrim($uri->rootUrl(), '/') .'/'. trim($route, '/');
}
header("Location: {$url}", true, $code);
exit();
}
/**
* Redirect browser to another location taking language into account (preferred)
*
* @param string $route Internal route.
* @param int $code Redirection code (30x)
*/
public function redirectLangSafe($route, $code = 303)
{
/** @var Language $language */
$language = $this['language'];
if ($language->enabled()) {
return $this->redirect($language->getLanguage() . $route, $code);
} else {
return $this->redirect($route);
}
}
/**
* Returns mime type for the file format.
*
@@ -275,18 +321,46 @@ class Grav extends Container
public function header()
{
$extension = $this['uri']->extension();
/** @var Page $page */
$page = $this['page'];
header('Content-type: ' . $this->mime($extension));
// Calculate Expires Headers if set to > 0
$expires = $page->expires();
if ($expires > 0) {
$expires_date = gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT';
header('Cache-Control: max-age=' . $expires_date);
header('Expires: '. $expires_date);
}
// Set the last modified time
if ($page->lastModified()) {
$last_modified_date = gmdate('D, d M Y H:i:s', $page->modified()) . ' GMT';
header('Last-Modified: ' . $last_modified_date);
}
// Calculate a Hash based on the raw file
if ($page->eTag()) {
header('ETag: ' . md5($page->raw() . $page->modified()));
}
// Set debugger data in headers
if (!($extension == null || $extension == 'html')) {
if (!($extension === null || $extension == 'html')) {
$this['debugger']->enabled(false);
// $this['debugger']->sendDataInHeaders();
}
// Set HTTP response code
if (isset($this['page']->header()->http_response_code)) {
http_response_code($this['page']->header()->http_response_code);
}
// Vary: Accept-Encoding
if ($this['config']->get('system.pages.vary_accept_encoding', false)) {
header('Vary: Accept-Encoding');
}
}
/**
@@ -310,23 +384,89 @@ class Grav extends Container
public function shutdown()
{
if ($this['config']->get('system.debugger.shutdown.close_connection')) {
//stop user abort
if (function_exists('ignore_user_abort')) {
@ignore_user_abort(true);
}
// close the session
if (isset($this['session'])) {
$this['session']->close();
}
header('Content-length: ' . ob_get_length());
header("Connection: close\r\n");
// flush buffer if gzip buffer was started
if ($this['config']->get('system.cache.gzip')) {
ob_end_flush(); // gzhandler buffer
}
// get lengh and close the connection
header('Content-Length: ' . ob_get_length());
header("Connection: close");
// flush the regular buffer
ob_end_flush();
ob_flush();
@ob_flush();
flush();
// fix for fastcgi close connection issue
if (function_exists('fastcgi_finish_request')) {
@fastcgi_finish_request();
}
}
$this->fireEvent('onShutdown');
}
/**
* This attempts to find media, other files, and download them
* @param $page
* @param $path
*/
protected function fallbackUrl($page, $path)
{
/** @var Uri $uri */
$uri = $this['uri'];
$path_parts = pathinfo($path);
$page = $this['pages']->dispatch($path_parts['dirname'], true);
if ($page) {
$media = $page->media()->all();
$parsed_url = parse_url(urldecode($uri->basename()));
$media_file = $parsed_url['path'];
// if this is a media object, try actions first
if (isset($media[$media_file])) {
$medium = $media[$media_file];
foreach ($uri->query(null, true) as $action => $params) {
if (in_array($action, ImageMedium::$magic_actions)) {
call_user_func_array(array(&$medium, $action), explode(',', $params));
}
}
Utils::download($medium->path(), false);
}
// unsupported media type, try to download it...
$uri_extension = $uri->extension();
if ($uri_extension) {
$extension = $uri_extension;
} else {
if (isset($path_parts['extension'])) {
$extension = $path_parts['extension'];
} else {
$extension = null;
}
}
if ($extension) {
$download = true;
if (in_array(ltrim($extension, '.'), $this['config']->get('system.media.unsupported_inline_types', []))) {
$download = false;
}
Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download);
}
}
}
}

View File

@@ -11,8 +11,11 @@ trait GravTrait
/**
* @return Grav
*/
public function getGrav()
public static function getGrav()
{
if (!self::$grav) {
self::$grav = Grav::instance();
}
return self::$grav;
}

View File

@@ -0,0 +1,164 @@
<?php
namespace Grav\Common\Helpers;
use DOMDocument;
/**
* This file is part of urodoz/truncateHTML.
*
* (c) Albert Lacarta <urodoz@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class InvalidHtmlException extends \Exception {
}
class Truncator {
public static $default_options = array(
'ellipsis' => '…',
'break' => ' ',
'length_in_chars' => false,
'word_safe' => false,
);
// These tags are allowed to have an ellipsis inside
public static $ellipsable_tags = array(
'p', 'ol', 'ul', 'li',
'div', 'header', 'article', 'nav',
'section', 'footer', 'aside',
'dd', 'dt', 'dl',
);
public static $self_closing_tags = array(
'br', 'hr', 'img',
);
/**
* Truncate given HTML string to specified length.
* If length_in_chars is false it's trimmed by number
* of words, otherwise by number of characters.
*
* @param string $html
* @param integer $length
* @param string|array $opts
* @return string
*/
public static function truncate($html, $length, $opts=array()) {
if (is_string($opts)) $opts = array('ellipsis' => $opts);
$opts = array_merge(static::$default_options, $opts);
// wrap the html in case it consists of adjacent nodes like <p>foo</p><p>bar</p>
$html = mb_convert_encoding("<div>".$html."</div>", 'HTML-ENTITIES', 'UTF-8');
$root_node = null;
// Parse using HTML5Lib if it's available.
if (class_exists('HTML5Lib\\Parser')) {
try {
$doc = \HTML5Lib\Parser::parse($html);
$root_node = $doc->documentElement->lastChild->lastChild;
}
catch (\Exception $e) {
;
}
}
if ($root_node === null) {
// HTML5Lib not available so we'll have to use DOMDocument
// We'll only be able to parse HTML5 if it's valid XML
$doc = new DOMDocument('4.01', 'utf-8');
$doc->formatOutput = false;
$doc->preserveWhitespace = true;
// loadHTML will fail with HTML5 tags (article, nav, etc)
// so we need to suppress errors and if it fails to parse we
// retry with the XML parser instead
$prev_use_errors = libxml_use_internal_errors(true);
if ($doc->loadHTML($html)) {
$root_node = $doc->documentElement->lastChild->lastChild;
}
else if ($doc->loadXML($html)) {
$root_node = $doc->documentElement;
}
else {
libxml_use_internal_errors($prev_use_errors);
throw new InvalidHtmlException;
}
libxml_use_internal_errors($prev_use_errors);
}
list($text, $_, $opts) = static::_truncate_node($doc, $root_node, $length, $opts);
$text = mb_substr(mb_substr($text, 0, -6), 5);
return $text;
}
protected static function _truncate_node($doc, $node, $length, $opts) {
if ($length === 0 && !static::ellipsable($node)) {
return array('', 1, $opts);
}
list($inner, $remaining, $opts) = static::_inner_truncate($doc, $node, $length, $opts);
if (0 === mb_strlen($inner)) {
return array(in_array(mb_strtolower($node->nodeName), static::$self_closing_tags) ? $doc->saveXML($node) : "", $length - $remaining, $opts);
}
while($node->firstChild) {
$node->removeChild($node->firstChild);
}
$newNode = $doc->createDocumentFragment();
$newNode->appendXml($inner);
$node->appendChild($newNode);
return array($doc->saveXML($node), $length - $remaining, $opts);
}
protected static function _inner_truncate($doc, $node, $length, $opts) {
$inner = '';
$remaining = $length;
foreach($node->childNodes as $childNode) {
if ($childNode->nodeType === XML_ELEMENT_NODE) {
list($txt, $nb, $opts) = static::_truncate_node($doc, $childNode, $remaining, $opts);
}
else if ($childNode->nodeType === XML_TEXT_NODE) {
list($txt, $nb, $opts) = static::_truncate_text($doc, $childNode, $remaining, $opts);
} else {
$txt = '';
$nb = 0;
}
$remaining -= $nb;
$inner .= $txt;
if ($remaining < 0) {
if (static::ellipsable($node)) {
$inner = preg_replace('/(?:[\s\pP]+|(?:&(?:[a-z]+|#[0-9]+);?))*$/', '', $inner).$opts['ellipsis'];
$opts['ellipsis'] = '';
$opts['was_truncated'] = true;
}
break;
}
}
return array($inner, $remaining, $opts);
}
protected static function _truncate_text($doc, $node, $length, $opts) {
$string = $node->textContent;
if ($opts['length_in_chars']) {
$count = mb_strlen($string);
if ($count <= $length && $length > 0) {
return array($string, $count, $opts);
}
if ($opts['word_safe']) {
if (false !== ($breakpoint = mb_strpos($string, $opts['break'], $length))) {
if ($breakpoint < mb_strlen($string) - 1) {
$string = mb_substr($string, 0, $breakpoint) . $opts['break'];
}
}
return array($string, $count, $opts);
}
return array(mb_substr($node->textContent, 0, $length), $count, $opts);
}
else {
preg_match_all('/\s*\S+/', $string, $words);
$words = $words[0];
$count = count($words);
if ($count <= $length && $length > 0) {
return array($xhtml, $count, $opts);
}
return array(implode('', array_slice($words, 0, $length)), $count, $opts);
}
}
protected static function ellipsable($node) {
return ($node instanceof DOMDocument)
|| in_array(mb_strtolower($node->nodeName), static::$ellipsable_tags)
;
}
}

View File

@@ -4,6 +4,7 @@ namespace Grav\Common;
/**
* This file was originally part of the Akelos Framework
*/
use Grav\Common\Language\Language;
/**
* Inflector for pluralize and singularize English nouns.
@@ -20,65 +21,55 @@ namespace Grav\Common;
class Inflector
{
use GravTrait;
protected $plural;
protected $singular;
protected $uncountable;
protected $irregular;
protected $ordinals;
public function init()
{
if (empty($this->plural)) {
$language = self::getGrav()['language'];
$this->plural = $language->translate('INFLECTOR_PLURALS', null, true);
$this->singular = $language->translate('INFLECTOR_SINGULAR', null, true);
$this->uncountable = $language->translate('INFLECTOR_UNCOUNTABLE', null, true);
$this->irregular = $language->translate('INFLECTOR_IRREGULAR', null, true);
$this->ordinals = $language->translate('INFLECTOR_ORDINALS', null, true);
}
}
/**
* Pluralizes English nouns.
*
* @access static public
* @static
* @param string $word English noun to pluralize
* @return string Plural noun
*/
public static function pluralize($word, $count = 2)
public function pluralize($word, $count = 2)
{
$this->init();
if ($count == 1) {
return $word;
}
$plural = array(
'/(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');
$uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
$irregular = array(
'person' => 'people',
'man' => 'men',
'child' => 'children',
'sex' => 'sexes',
'move' => 'moves');
$lowercased_word = strtolower($word);
foreach ($uncountable as $_uncountable) {
foreach ($this->uncountable as $_uncountable) {
if (substr($lowercased_word, (-1*strlen($_uncountable))) == $_uncountable) {
return $word;
}
}
foreach ($irregular as $_plural => $_singular) {
foreach ($this->irregular as $_plural => $_singular) {
if (preg_match('/('.$_plural.')$/i', $word, $arr)) {
return preg_replace('/('.$_plural.')$/i', substr($arr[0], 0, 1).substr($_singular, 1), $word);
}
}
foreach ($plural as $rule => $replacement) {
foreach ($this->plural as $rule => $replacement) {
if (preg_match($rule, $word)) {
return preg_replace($rule, $replacement, $word);
}
@@ -94,62 +85,28 @@ class Inflector
* @param int $count
* @return string Singular noun.
*/
public static function singularize($word, $count = 1)
public function singularize($word, $count = 1)
{
$this->init();
if ($count != 1) {
return $word;
}
$singular = array (
'/(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' => '',
);
$uncountable = array('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep');
$irregular = array(
'person' => 'people',
'man' => 'men',
'child' => 'children',
'sex' => 'sexes',
'move' => 'moves');
$lowercased_word = strtolower($word);
foreach ($uncountable as $_uncountable) {
foreach ($this->uncountable as $_uncountable) {
if (substr($lowercased_word, (-1*strlen($_uncountable))) == $_uncountable) {
return $word;
}
}
foreach ($irregular as $_plural => $_singular) {
foreach ($this->irregular as $_plural => $_singular) {
if (preg_match('/('.$_singular.')$/i', $word, $arr)) {
return preg_replace('/('.$_singular.')$/i', substr($arr[0], 0, 1).substr($_plural, 1), $word);
}
}
foreach ($singular as $rule => $replacement) {
foreach ($this->singular as $rule => $replacement) {
if (preg_match($rule, $word)) {
return preg_replace($rule, $replacement, $word);
}
@@ -162,24 +119,22 @@ class Inflector
* Converts an underscored or CamelCase word into a English
* sentence.
*
* The titleize static public function converts text like "WelcomePage",
* The titleize public function converts text like "WelcomePage",
* "welcome_page" or "welcome page" to this "Welcome
* Page".
* If second parameter is set to 'first' it will only
* capitalize the first character of the title.
*
* @access static public
* @static
* @param string $word Word to format as tile
* @param string $uppercase If set to 'first' it will only uppercase the
* first character. Otherwise it will uppercase all
* the words in the title.
* @return string Text formatted as title
*/
public static function titleize($word, $uppercase = '')
public function titleize($word, $uppercase = '')
{
$uppercase = $uppercase == 'first' ? 'ucfirst' : 'ucwords';
return $uppercase(static::humanize(static::underscorize($word)));
return $uppercase($this->humanize($this->underscorize($word)));
}
/**
@@ -189,13 +144,11 @@ class Inflector
* will remove non alphanumeric character from the word, so
* "who's online" will be converted to "WhoSOnline"
*
* @access static public
* @static
* @see variablize
* @param string $word Word to convert to camel case
* @return string UpperCamelCasedWord
*/
public static function camelize($word)
public function camelize($word)
{
return str_replace(' ', '', ucwords(preg_replace('/[^A-Z^a-z^0-9]+/', ' ', $word)));
}
@@ -208,12 +161,10 @@ class Inflector
*
* This can be really useful for creating friendly URLs.
*
* @access static public
* @static
* @param string $word Word to underscore
* @return string Underscored word
*/
public static function underscorize($word)
public function underscorize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1_\2', $regex1);
@@ -229,12 +180,10 @@ class Inflector
*
* This can be really useful for creating friendly URLs.
*
* @access static public
* @static
* @param string $word Word to hyphenate
* @return string hyphenized word
*/
public static function hyphenize($word)
public function hyphenize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1-\2', $word);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1-\2', $regex1);
@@ -252,14 +201,12 @@ class Inflector
* If you need to uppercase all the words you just have to
* pass 'all' as a second parameter.
*
* @access static public
* @static
* @param string $word String to "humanize"
* @param string $uppercase If set to 'all' it will uppercase all the words
* instead of just the first one.
* @return string Human-readable word
*/
public static function humanize($word, $uppercase = '')
public function humanize($word, $uppercase = '')
{
$uppercase = $uppercase == 'all' ? 'ucwords' : 'ucfirst';
return $uppercase(str_replace('_', ' ', preg_replace('/_id$/', '', $word)));
@@ -272,15 +219,13 @@ class Inflector
* will remove non alphanumeric character from the word, so
* "who's online" will be converted to "whoSOnline"
*
* @access static public
* @static
* @see camelize
* @param string $word Word to lowerCamelCase
* @return string Returns a lowerCamelCasedWord
*/
public static function variablize($word)
public function variablize($word)
{
$word = static::camelize($word);
$word = $this->camelize($word);
return strtolower($word[0]).substr($word, 1);
}
@@ -290,15 +235,13 @@ class Inflector
*
* Converts "Person" to "people"
*
* @access static public
* @static
* @see classify
* @param string $class_name Class name for getting related table_name.
* @return string plural_table_name
*/
public static function tableize($class_name)
public function tableize($class_name)
{
return static::pluralize(static::underscore($class_name));
return $this->pluralize($this->underscore($class_name));
}
/**
@@ -307,15 +250,13 @@ class Inflector
*
* Converts "people" to "Person"
*
* @access static public
* @static
* @see tableize
* @param string $table_name Table name for getting related ClassName.
* @return string SingularClassName
*/
public static function classify($table_name)
public function classify($table_name)
{
return static::camelize(static::singularize($table_name));
return $this->camelize($this->singularize($table_name));
}
/**
@@ -323,34 +264,34 @@ class Inflector
*
* This method converts 13 to 13th, 2 to 2nd ...
*
* @access static public
* @static
* @param integer $number Number to get its ordinal value
* @return string Ordinal representation of given string.
*/
public static function ordinalize($number)
public function ordinalize($number)
{
$this->init();
if (in_array(($number % 100), range(11, 13))) {
return $number.'th';
return $number.$this->ordinals['default'];
} else {
switch (($number % 10)) {
case 1:
return $number.'st';
return $number.$this->ordinals['first'];
break;
case 2:
return $number.'nd';
return $number.$this->ordinals['second'];
break;
case 3:
return $number.'rd';
return $number.$this->ordinals['third'];
break;
default:
return $number.'th';
return $number.$this->ordinals['default'];
break;
}
}
}
public static function monthize($days)
public function monthize($days)
{
$now = new \DateTime();
$end = new \DateTime();

View File

@@ -84,10 +84,43 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
*/
public function nth($key)
{
$items = array_values($this->items);
$items = array_keys($this->items);
return (isset($items[$key])) ? $this->offsetGet($items[$key]) : false;
}
/**
* Get the first item
*
* @return mixed
*/
public function first()
{
$items = array_keys($this->items);
return $this->offsetGet(array_shift($items));
}
/**
* Get the last item
*
* @return mixed
*/
public function last()
{
$items = array_keys($this->items);
return $this->offsetGet(array_pop($items));
}
/**
* Reverse the Iterator
*
* @return $this
*/
public function reverse()
{
$this->items = array_reverse($this->items);
return $this;
}
/**
* @param mixed $needle Searched value.
* @return string|bool Key if found, otherwise false.
@@ -164,4 +197,23 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
return $this;
}
/**
* Filter elements from the list
* @param callable|null $callback A function the receives ($value, $key) and must return a boolean to indicate filter status
* @return $this
*/
public function filter(callable $callback = null)
{
foreach ($this->items as $key => $value) {
if (
($callback && !call_user_func($callback, $value, $key)) ||
(!$callback && !(bool) $value)
) {
unset($this->items[$key]);
}
}
return $this;
}
}

View File

@@ -0,0 +1,415 @@
<?php
namespace Grav\Common\Language;
use Grav\Common\Grav;
/**
* Language and translation functionality for Grav
*/
class Language
{
protected $grav;
protected $enabled = true;
protected $languages = [];
protected $page_extensions = [];
protected $fallback_languages = [];
protected $default;
protected $active = null;
protected $config;
protected $http_accept_language;
/**
* Constructor
*
* @param \Grav\Common\Grav $grav
*/
public function __construct(Grav $grav)
{
$this->grav = $grav;
$this->config = $grav['config'];
$this->languages = $this->config->get('system.languages.supported', []);
$this->init();
}
/**
* Initialize the default and enabled languages
*/
public function init()
{
$this->default = reset($this->languages);
if (empty($this->languages)) {
$this->enabled = false;
}
}
/**
* Ensure that languages are enabled
*
* @return bool
*/
public function enabled()
{
return $this->enabled;
}
/**
* Gets the array of supported languages
*
* @return array
*/
public function getLanguages()
{
return $this->languages;
}
/**
* Sets the current supported languages manually
*
* @param $langs
*/
public function setLanguages($langs)
{
$this->languages = $langs;
$this->init();
}
/**
* Gets a pipe-separated string of available languages
*
* @return string
*/
public function getAvailable()
{
return implode('|', $this->languages);
}
/**
* Gets language, active if set, else default
*
* @return mixed
*/
public function getLanguage()
{
return $this->active ? $this->active : $this->default;
}
/**
* Gets current default language
*
* @return mixed
*/
public function getDefault()
{
return $this->default;
}
/**
* Sets default language manually
*
* @param $lang
*
* @return bool
*/
public function setDefault($lang)
{
if ($this->validate($lang)) {
$this->default = $lang;
return $lang;
}
return false;
}
/**
* Gets current active language
*
* @return mixed
*/
public function getActive()
{
return $this->active;
}
/**
* Sets active language manually
*
* @param $lang
*
* @return bool
*/
public function setActive($lang)
{
if ($this->validate($lang)) {
$this->active = $lang;
return $lang;
}
return false;
}
/**
* Sets the active language based on the first part of the URL
*
* @param $uri
*
* @return mixed
*/
public function setActiveFromUri($uri)
{
$regex = '/(\/(' . $this->getAvailable() . ')).*/';
// if languages set
if ($this->enabled()) {
// try setting from prefix of URL (/en/blah/blah)
if (preg_match($regex, $uri, $matches)) {
$this->active = $matches[2];
$uri = preg_replace("/\\" . $matches[1] . "/", '', $matches[0], 1);
// store in session if different
if ($this->config->get('system.session.enabled', false)
&& $this->config->get('system.languages.session_store_active', true)
&& $this->grav['session']->active_language != $this->active
) {
$this->grav['session']->active_language = $this->active;
}
} else {
// try getting from session, else no active
if ($this->config->get('system.session.enabled', false) &&
$this->config->get('system.languages.session_store_active', true)) {
$this->active = $this->grav['session']->active_language ?: null;
}
// if still null, try from http_accept_language header
if ($this->active === null && $this->config->get('system.languages.http_accept_language')) {
$preferred = $this->getBrowserLanguages();
foreach ($preferred as $lang) {
if ($this->validate($lang)) {
$this->active = $lang;
break;
}
}
}
}
}
return $uri;
}
/**
* Gets an array of valid extensions with active first, then fallback extensions
*
* @return array
*/
public function getFallbackPageExtensions($file_ext = null)
{
if (empty($this->page_extensions)) {
if (empty($file_ext)) {
$file_ext = CONTENT_EXT;
}
if ($this->enabled()) {
$valid_lang_extensions = [];
foreach ($this->languages as $lang) {
$valid_lang_extensions[] = '.' . $lang . $file_ext;
}
if ($this->active) {
$active_extension = '.' . $this->active . $file_ext;
$key = array_search($active_extension, $valid_lang_extensions);
unset($valid_lang_extensions[$key]);
array_unshift($valid_lang_extensions, $active_extension);
}
$this->page_extensions = array_merge($valid_lang_extensions, (array)$file_ext);
} else {
$this->page_extensions = (array)$file_ext;
}
}
return $this->page_extensions;
}
/**
* Gets an array of languages with active first, then fallback languages
*
* @return array
*/
public function getFallbackLanguages()
{
if (empty($this->fallback_languages)) {
if ($this->enabled()) {
$fallback_languages = $this->languages;
if ($this->active) {
$active_extension = $this->active;
$key = array_search($active_extension, $fallback_languages);
unset($fallback_languages[$key]);
array_unshift($fallback_languages, $active_extension);
}
$this->fallback_languages = $fallback_languages;
}
}
return $this->fallback_languages;
}
/**
* Ensures the language is valid and supported
*
* @param $lang
*
* @return bool
*/
public function validate($lang)
{
if (in_array($lang, $this->languages)) {
return true;
}
return false;
}
/**
* Translate a key and possibly arguments into a string using current lang and fallbacks
*
* @param $args first argument is the lookup key value
* other arguments can be passed and replaced in the translation with sprintf syntax
* @param Array $languages
* @param bool $array_support
* @param bool $html_out
*
* @return string
*/
public function translate($args, Array $languages = null, $array_support = false, $html_out = false)
{
if (is_array($args)) {
$lookup = array_shift($args);
} else {
$lookup = $args;
$args = [];
}
if ($this->config->get('system.languages.translations', true)) {
if ($this->enabled() && $lookup) {
if (empty($languages)) {
if ($this->config->get('system.languages.translations_fallback', true)) {
$languages = $this->getFallbackLanguages();
} else {
$languages = (array)$this->getDefault();
}
}
} else {
$languages = ['en'];
}
foreach ((array)$languages as $lang) {
$translation = $this->getTranslation($lang, $lookup, $array_support);
if ($translation) {
if (count($args) >= 1) {
return vsprintf($translation, $args);
} else {
return $translation;
}
}
}
}
if ($html_out) {
return '<span class="untranslated">' . $lookup . '</span>';
} else {
return $lookup;
}
}
/**
* Translate Array
*
* @param $key
* @param $index
* @param null $languages
* @param bool $html_out
*
* @return string
*/
public function translateArray($key, $index, $languages = null, $html_out = false)
{
if ($this->config->get('system.languages.translations', true)) {
if ($this->enabled() && $key) {
if (empty($languages)) {
if ($this->config->get('system.languages.translations_fallback', true)) {
$languages = $this->getFallbackLanguages();
} else {
$languages = (array)$this->getDefault();
}
}
} else {
$languages = ['en'];
}
foreach ((array)$languages as $lang) {
$translation_array = (array)$this->config->getLanguages()->get($lang . '.' . $key, null);
if ($translation_array && array_key_exists($index, $translation_array)) {
return $translation_array[$index];
}
}
}
if ($html_out) {
return '<span class="untranslated">' . $key . '[' . $index . ']</span>';
} else {
return $key . '[' . $index . ']';
}
}
/**
* Lookup the translation text for a given lang and key
*
* @param $lang lang code
* @param $key key to lookup with
* @param bool $array_support
*
* @return string
*/
public function getTranslation($lang, $key, $array_support = false)
{
$translation = $this->config->getLanguages()->get($lang . '.' . $key, null);
if (!$array_support && is_array($translation)) {
return (string)array_shift($translation);
}
return $translation;
}
public function getBrowserLanguages($accept_langs = [])
{
if (empty($this->http_accept_language)) {
if (empty($accept_langs) && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$accept_langs = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
} else {
return $accept_langs;
}
foreach (explode(',', $accept_langs) as $k => $pref) {
// split $pref again by ';q='
// and decorate the language entries by inverted position
if (false !== ($i = strpos($pref, ';q='))) {
$langs[substr($pref, 0, $i)] = array((float)substr($pref, $i + 3), -$k);
} else {
$langs[$pref] = array(1, -$k);
}
}
arsort($langs);
// no need to undecorate, because we're only interested in the keys
$this->http_accept_language = array_keys($langs);
}
return $this->http_accept_language;
}
}

View File

@@ -0,0 +1,770 @@
<?php
namespace Grav\Common\Language;
/**
* Language and translation functionality for Grav
*/
class LanguageCodes
{
protected static $codes = [
"ab" => [
"name" => "Abkhaz",
"nativeName" => "аҧсуа"
],
"aa" => [
"name" => "Afar",
"nativeName" => "Afaraf"
],
"af" => [
"name" => "Afrikaans",
"nativeName" => "Afrikaans"
],
"ak" => [
"name" => "Akan",
"nativeName" => "Akan"
],
"sq" => [
"name" => "Albanian",
"nativeName" => "Shqip"
],
"am" => [
"name" => "Amharic",
"nativeName" => "አማርኛ"
],
"ar" => [
"name" => "Arabic",
"nativeName" => "العربية"
],
"an" => [
"name" => "Aragonese",
"nativeName" => "Aragonés"
],
"hy" => [
"name" => "Armenian",
"nativeName" => "Հայերեն"
],
"as" => [
"name" => "Assamese",
"nativeName" => "অসমীয়া"
],
"av" => [
"name" => "Avaric",
"nativeName" => "авар мацӀ"
],
"ae" => [
"name" => "Avestan",
"nativeName" => "avesta"
],
"ay" => [
"name" => "Aymara",
"nativeName" => "aymar aru"
],
"az" => [
"name" => "Azerbaijani",
"nativeName" => "azərbaycan dili"
],
"bm" => [
"name" => "Bambara",
"nativeName" => "bamanankan"
],
"ba" => [
"name" => "Bashkir",
"nativeName" => "башҡорт теле"
],
"eu" => [
"name" => "Basque",
"nativeName" => "euskara"
],
"be" => [
"name" => "Belarusian",
"nativeName" => "Беларуская"
],
"bn" => [
"name" => "Bengali",
"nativeName" => "বাংলা"
],
"bh" => [
"name" => "Bihari",
"nativeName" => "भोजपुरी"
],
"bi" => [
"name" => "Bislama",
"nativeName" => "Bislama"
],
"bs" => [
"name" => "Bosnian",
"nativeName" => "bosanski jezik"
],
"br" => [
"name" => "Breton",
"nativeName" => "brezhoneg"
],
"bg" => [
"name" => "Bulgarian",
"nativeName" => "български език"
],
"my" => [
"name" => "Burmese",
"nativeName" => "ဗမာစာ"
],
"ca" => [
"name" => "Catalan",
"nativeName" => "Català"
],
"ch" => [
"name" => "Chamorro",
"nativeName" => "Chamoru"
],
"ce" => [
"name" => "Chechen",
"nativeName" => "нохчийн мотт"
],
"ny" => [
"name" => "Chichewa",
"nativeName" => "chiCheŵa"
],
"zh" => [
"name" => "Chinese",
"nativeName" => "中文"
],
"cv" => [
"name" => "Chuvash",
"nativeName" => "чӑваш чӗлхи"
],
"kw" => [
"name" => "Cornish",
"nativeName" => "Kernewek"
],
"co" => [
"name" => "Corsican",
"nativeName" => "corsu"
],
"cr" => [
"name" => "Cree",
"nativeName" => "ᓀᐦᐃᔭᐍᐏᐣ"
],
"hr" => [
"name" => "Croatian",
"nativeName" => "hrvatski"
],
"cs" => [
"name" => "Czech",
"nativeName" => "česky"
],
"da" => [
"name" => "Danish",
"nativeName" => "dansk"
],
"dv" => [
"name" => "Divehi",
"nativeName" => "ދިވެހި"
],
"nl" => [
"name" => "Dutch",
"nativeName" => "Nederlands"
],
"en" => [
"name" => "English",
"nativeName" => "English"
],
"eo" => [
"name" => "Esperanto",
"nativeName" => "Esperanto"
],
"et" => [
"name" => "Estonian",
"nativeName" => "eesti"
],
"ee" => [
"name" => "Ewe",
"nativeName" => "Eʋegbe"
],
"fo" => [
"name" => "Faroese",
"nativeName" => "føroyskt"
],
"fj" => [
"name" => "Fijian",
"nativeName" => "vosa Vakaviti"
],
"fi" => [
"name" => "Finnish",
"nativeName" => "suomi"
],
"fr" => [
"name" => "French",
"nativeName" => "français"
],
"ff" => [
"name" => "Fula",
"nativeName" => "Fulfulde"
],
"gl" => [
"name" => "Galician",
"nativeName" => "Galego"
],
"ka" => [
"name" => "Georgian",
"nativeName" => "ქართული"
],
"de" => [
"name" => "German",
"nativeName" => "Deutsch"
],
"el" => [
"name" => "Greek",
"nativeName" => "Ελληνικά"
],
"gn" => [
"name" => "Guaraní",
"nativeName" => "Avañeẽ"
],
"gu" => [
"name" => "Gujarati",
"nativeName" => "ગુજરાતી"
],
"ht" => [
"name" => "Haitian",
"nativeName" => "Kreyòl ayisyen"
],
"ha" => [
"name" => "Hausa",
"nativeName" => "هَوُسَ"
],
"he" => [
"name" => "Hebrew",
"nativeName" => "עברית"
],
"hz" => [
"name" => "Herero",
"nativeName" => "Otjiherero"
],
"hi" => [
"name" => "Hindi",
"nativeName" => "हिन्दी"
],
"ho" => [
"name" => "Hiri Motu",
"nativeName" => "Hiri Motu"
],
"hu" => [
"name" => "Hungarian",
"nativeName" => "Magyar"
],
"ia" => [
"name" => "Interlingua",
"nativeName" => "Interlingua"
],
"id" => [
"name" => "Indonesian",
"nativeName" => "Bahasa Indonesia"
],
"ie" => [
"name" => "Interlingue",
"nativeName" => "Interlingue"
],
"ga" => [
"name" => "Irish",
"nativeName" => "Gaeilge"
],
"ig" => [
"name" => "Igbo",
"nativeName" => "Asụsụ Igbo"
],
"ik" => [
"name" => "Inupiaq",
"nativeName" => "Iñupiaq"
],
"io" => [
"name" => "Ido",
"nativeName" => "Ido"
],
"is" => [
"name" => "Icelandic",
"nativeName" => "Íslenska"
],
"it" => [
"name" => "Italian",
"nativeName" => "Italiano"
],
"iu" => [
"name" => "Inuktitut",
"nativeName" => "ᐃᓄᒃᑎᑐᑦ"
],
"ja" => [
"name" => "Japanese",
"nativeName" => "日本語"
],
"jv" => [
"name" => "Javanese",
"nativeName" => "basa Jawa"
],
"kl" => [
"name" => "Kalaallisut",
"nativeName" => "kalaallisut"
],
"kn" => [
"name" => "Kannada",
"nativeName" => "ಕನ್ನಡ"
],
"kr" => [
"name" => "Kanuri",
"nativeName" => "Kanuri"
],
"ks" => [
"name" => "Kashmiri",
"nativeName" => "कश्मीरी"
],
"kk" => [
"name" => "Kazakh",
"nativeName" => "Қазақ тілі"
],
"km" => [
"name" => "Khmer",
"nativeName" => "ភាសាខ្មែរ"
],
"ki" => [
"name" => "Kikuyu",
"nativeName" => "Gĩkũyũ"
],
"rw" => [
"name" => "Kinyarwanda",
"nativeName" => "Ikinyarwanda"
],
"ky" => [
"name" => "Kirghiz",
"nativeName" => "кыргыз тили"
],
"kv" => [
"name" => "Komi",
"nativeName" => "коми кыв"
],
"kg" => [
"name" => "Kongo",
"nativeName" => "KiKongo"
],
"ko" => [
"name" => "Korean",
"nativeName" => "한국어"
],
"ku" => [
"name" => "Kurdish",
"nativeName" => "كوردی‎"
],
"kj" => [
"name" => "Kwanyama",
"nativeName" => "Kuanyama"
],
"la" => [
"name" => "Latin",
"nativeName" => "latine"
],
"lb" => [
"name" => "Luxembourgish",
"nativeName" => "Lëtzebuergesch"
],
"lg" => [
"name" => "Luganda",
"nativeName" => "Luganda"
],
"li" => [
"name" => "Limburgish",
"nativeName" => "Limburgs"
],
"ln" => [
"name" => "Lingala",
"nativeName" => "Lingála"
],
"lo" => [
"name" => "Lao",
"nativeName" => "ພາສາລາວ"
],
"lt" => [
"name" => "Lithuanian",
"nativeName" => "lietuvių kalba"
],
"lu" => [
"name" => "Luba-Katanga",
"nativeName" => "Luba-Katanga"
],
"lv" => [
"name" => "Latvian",
"nativeName" => "latviešu valoda"
],
"gv" => [
"name" => "Manx",
"nativeName" => "Gaelg"
],
"mk" => [
"name" => "Macedonian",
"nativeName" => "македонски јазик"
],
"mg" => [
"name" => "Malagasy",
"nativeName" => "Malagasy fiteny"
],
"ms" => [
"name" => "Malay",
"nativeName" => "بهاس ملايو‎"
],
"ml" => [
"name" => "Malayalam",
"nativeName" => "മലയാളം"
],
"mt" => [
"name" => "Maltese",
"nativeName" => "Malti"
],
"mi" => [
"name" => "Māori",
"nativeName" => "te reo Māori"
],
"mr" => [
"name" => "Marathi",
"nativeName" => "मराठी"
],
"mh" => [
"name" => "Marshallese",
"nativeName" => "Kajin M̧ajeļ"
],
"mn" => [
"name" => "Mongolian",
"nativeName" => "монгол"
],
"na" => [
"name" => "Nauru",
"nativeName" => "Ekakairũ Naoero"
],
"nv" => [
"name" => "Navajo",
"nativeName" => "Diné bizaad"
],
"nb" => [
"name" => "Norwegian Bokmål",
"nativeName" => "Norsk bokmål"
],
"nd" => [
"name" => "North Ndebele",
"nativeName" => "isiNdebele"
],
"ne" => [
"name" => "Nepali",
"nativeName" => "नेपाली"
],
"ng" => [
"name" => "Ndonga",
"nativeName" => "Owambo"
],
"nn" => [
"name" => "Norwegian Nynorsk",
"nativeName" => "Norsk nynorsk"
],
"no" => [
"name" => "Norwegian",
"nativeName" => "Norsk"
],
"ii" => [
"name" => "Nuosu",
"nativeName" => "ꆈꌠ꒿ Nuosuhxop"
],
"nr" => [
"name" => "South Ndebele",
"nativeName" => "isiNdebele"
],
"oc" => [
"name" => "Occitan",
"nativeName" => "Occitan"
],
"oj" => [
"name" => "Ojibwe, Ojibwa",
"nativeName" => "ᐊᓂᔑᓈᐯᒧᐎᓐ"
],
"cu" => [
"name" => "Church Slavic",
"nativeName" => "ѩзыкъ словѣньскъ"
],
"om" => [
"name" => "Oromo",
"nativeName" => "Afaan Oromoo"
],
"or" => [
"name" => "Oriya",
"nativeName" => "ଓଡ଼ିଆ"
],
"os" => [
"name" => "Ossetian",
"nativeName" => "ирон æвзаг"
],
"pa" => [
"name" => "Panjabi",
"nativeName" => "ਪੰਜਾਬੀ"
],
"pi" => [
"name" => "Pāli",
"nativeName" => "पाऴि"
],
"fa" => [
"name" => "Persian",
"nativeName" => "فارسی"
],
"pl" => [
"name" => "Polish",
"nativeName" => "polski"
],
"ps" => [
"name" => "Pashto",
"nativeName" => "پښتو"
],
"pt" => [
"name" => "Portuguese",
"nativeName" => "Português"
],
"qu" => [
"name" => "Quechua",
"nativeName" => "Runa Simi"
],
"rm" => [
"name" => "Romansh",
"nativeName" => "rumantsch grischun"
],
"rn" => [
"name" => "Kirundi",
"nativeName" => "kiRundi"
],
"ro" => [
"name" => "Romanian",
"nativeName" => "română"
],
"ru" => [
"name" => "Russian",
"nativeName" => "русский язык"
],
"sa" => [
"name" => "Sanskrit",
"nativeName" => "संस्कृतम्"
],
"sc" => [
"name" => "Sardinian",
"nativeName" => "sardu"
],
"sd" => [
"name" => "Sindhi",
"nativeName" => "सिन्धी"
],
"se" => [
"name" => "Northern Sami",
"nativeName" => "Davvisámegiella"
],
"sm" => [
"name" => "Samoan",
"nativeName" => "gagana faa Samoa"
],
"sg" => [
"name" => "Sango",
"nativeName" => "yângâ tî sängö"
],
"sr" => [
"name" => "Serbian",
"nativeName" => "српски језик"
],
"gd" => [
"name" => "Scottish Gaelic",
"nativeName" => "Gàidhlig"
],
"sn" => [
"name" => "Shona",
"nativeName" => "chiShona"
],
"si" => [
"name" => "Sinhala",
"nativeName" => "සිංහල"
],
"sk" => [
"name" => "Slovak",
"nativeName" => "slovenčina"
],
"sl" => [
"name" => "Slovene",
"nativeName" => "slovenščina"
],
"so" => [
"name" => "Somali",
"nativeName" => "Soomaaliga"
],
"st" => [
"name" => "Southern Sotho",
"nativeName" => "Sesotho"
],
"es" => [
"name" => "Spanish",
"nativeName" => "Español"
],
"su" => [
"name" => "Sundanese",
"nativeName" => "Basa Sunda"
],
"sw" => [
"name" => "Swahili",
"nativeName" => "Kiswahili"
],
"ss" => [
"name" => "Swati",
"nativeName" => "SiSwati"
],
"sv" => [
"name" => "Swedish",
"nativeName" => "svenska"
],
"ta" => [
"name" => "Tamil",
"nativeName" => "தமிழ்"
],
"te" => [
"name" => "Telugu",
"nativeName" => "తెలుగు"
],
"tg" => [
"name" => "Tajik",
"nativeName" => "тоҷикӣ"
],
"th" => [
"name" => "Thai",
"nativeName" => "ไทย"
],
"ti" => [
"name" => "Tigrinya",
"nativeName" => "ትግርኛ"
],
"bo" => [
"name" => "Tibetan",
"nativeName" => "བོད་ཡིག"
],
"tk" => [
"name" => "Turkmen",
"nativeName" => "Türkmen"
],
"tl" => [
"name" => "Tagalog",
"nativeName" => "Wikang Tagalog"
],
"tn" => [
"name" => "Tswana",
"nativeName" => "Setswana"
],
"to" => [
"name" => "Tonga",
"nativeName" => "faka Tonga"
],
"tr" => [
"name" => "Turkish",
"nativeName" => "Türkçe"
],
"ts" => [
"name" => "Tsonga",
"nativeName" => "Xitsonga"
],
"tt" => [
"name" => "Tatar",
"nativeName" => "татарча"
],
"tw" => [
"name" => "Twi",
"nativeName" => "Twi"
],
"ty" => [
"name" => "Tahitian",
"nativeName" => "Reo Tahiti"
],
"ug" => [
"name" => "Uighur",
"nativeName" => "Uyƣurqə"
],
"uk" => [
"name" => "Ukrainian",
"nativeName" => "українська"
],
"ur" => [
"name" => "Urdu",
"nativeName" => "اردو"
],
"uz" => [
"name" => "Uzbek",
"nativeName" => "zbek"
],
"ve" => [
"name" => "Venda",
"nativeName" => "Tshivenḓa"
],
"vi" => [
"name" => "Vietnamese",
"nativeName" => "Tiếng Việt"
],
"vo" => [
"name" => "Volapük",
"nativeName" => "Volapük"
],
"wa" => [
"name" => "Walloon",
"nativeName" => "Walon"
],
"cy" => [
"name" => "Welsh",
"nativeName" => "Cymraeg"
],
"wo" => [
"name" => "Wolof",
"nativeName" => "Wollof"
],
"fy" => [
"name" => "Western Frisian",
"nativeName" => "Frysk"
],
"xh" => [
"name" => "Xhosa",
"nativeName" => "isiXhosa"
],
"yi" => [
"name" => "Yiddish",
"nativeName" => "ייִדיש"
],
"yo" => [
"name" => "Yoruba",
"nativeName" => "Yorùbá"
],
"za" => [
"name" => "Zhuang",
"nativeName" => "Saɯ cueŋƅ"
]
];
public static function getName($code)
{
return static::get($code, 'name');
}
public static function getNativeName($code)
{
return static::get($code, 'nativeName');
}
public static function getNames(array $keys)
{
$results = [];
foreach ($keys as $key) {
if (isset(static::$codes[$key])) {
$results[$key] = static::$codes[$key];
}
}
return $results;
}
protected static function get($code, $type)
{
if (isset(static::$codes[$code][$type])) {
return static::$codes[$code][$type];
} else {
return false;
}
}
}

View File

@@ -1,14 +0,0 @@
<?php
namespace Grav\Common\Markdown;
class Markdown extends \Parsedown
{
use MarkdownGravLinkTrait;
public function __construct($page)
{
$this->page = $page;
$this->BlockTypes['{'] [] = "TwigTag";
}
}

View File

@@ -1,14 +0,0 @@
<?php
namespace Grav\Common\Markdown;
class MarkdownExtra extends \ParsedownExtra
{
use MarkdownGravLinkTrait;
public function __construct($page)
{
parent::__construct();
$this->page = $page;
$this->BlockTypes['{'] [] = "TwigTag";
}
}

View File

@@ -1,166 +0,0 @@
<?php
namespace Grav\Common\Markdown;
use Grav\Common\Config\Config;
use Grav\Common\Debugger;
use Grav\Common\GravTrait;
use Grav\Common\Page\Medium;
use Grav\Common\Uri;
/**
* A trait to add some custom processing to the identifyLink() method in Parsedown and ParsedownExtra
*/
trait MarkdownGravLinkTrait
{
use GravTrait;
/**
* Ensure Twig tags are treated as block level items with no <p></p> tags
*/
protected function identifyTwigTag($Line)
{
if (preg_match('/[{%|{{|{#].*[#}|}}|%}]/', $Line['body'], $matches)) {
$Block = array(
'element' => $Line['body'],
);
return $Block;
}
}
protected function identifyLink($Excerpt)
{
/** @var Config $config */
$config = self::$grav['config'];
// Run the parent method to get the actual results
$Excerpt = parent::identifyLink($Excerpt);
$actions = array();
$this->base_url = self::$grav['base_url'];
// if this is a link
if (isset($Excerpt['element']['attributes']['href'])) {
$url = parse_url(htmlspecialchars_decode($Excerpt['element']['attributes']['href']));
// if there is no scheme, the file is local
if (!isset($url['scheme'])) {
// convert the URl is required
$Excerpt['element']['attributes']['href'] = $this->convertUrl(Uri::build_url($url));
}
}
// if this is an image
if (isset($Excerpt['element']['attributes']['src'])) {
$alt = isset($Excerpt['element']['attributes']['alt']) ? $Excerpt['element']['attributes']['alt'] : '';
$title = isset($Excerpt['element']['attributes']['title']) ? $Excerpt['element']['attributes']['title'] : '';
//get the url and parse it
$url = parse_url(htmlspecialchars_decode($Excerpt['element']['attributes']['src']));
// if there is no host set but there is a path, the file is local
if (!isset($url['host']) && isset($url['path'])) {
// get the media objects for this page
$media = $this->page->media();
// if there is a media file that matches the path referenced..
if (isset($media->images()[$url['path']])) {
// get the medium object
$medium = $media->images()[$url['path']];
// if there is a query, then parse it and build action calls
if (isset($url['query'])) {
parse_str($url['query'], $actions);
}
// loop through actions for the image and call them
foreach ($actions as $action => $params) {
// as long as it's a valid action
if (in_array($action, Medium::$valid_actions)) {
call_user_func_array(array(&$medium, $action), explode(',', $params));
}
}
// Get the URL for regular images, or an array of bits needed to put together
// the lightbox HTML
if (!isset($actions['lightbox'])) {
$src = $medium->url();
} else {
$src = $medium->lightboxRaw();
}
// set the src element with the new generated url
if (!isset($actions['lightbox']) && !is_array($src)) {
$Excerpt['element']['attributes']['src'] = $src;
} else {
// Create the custom lightbox element
$Element = array(
'name' => 'a',
'attributes' => array('rel' => $src['a_rel'], 'href' => $src['a_url']),
'handler' => 'element',
'text' => array(
'name' => 'img',
'attributes' => array('src' => $src['img_url'], 'alt' => $alt, 'title' => $title)
),
);
// Set any custom classes on the lightbox element
if (isset($Excerpt['element']['attributes']['class'])) {
$Element['attributes']['class'] = $Excerpt['element']['attributes']['class'];
}
// Set the lightbox element on the Excerpt
$Excerpt['element'] = $Element;
}
} else {
// not a current page media file, see if it needs converting to relative
$Excerpt['element']['attributes']['src'] = $this->convertUrl(Uri::build_url($url));
}
}
}
return $Excerpt;
}
/**
* Converts links from absolute '/' or relative (../..) to a grav friendly format
* @param string $markdown_url the URL as it was written in the markdown
* @return string the more friendly formatted url
*/
protected function convertUrl($markdown_url)
{
// if absolue and starts with a base_url move on
if ($this->base_url != '' && strpos($markdown_url, $this->base_url) === 0) {
$new_url = $markdown_url;
// if its absolute with /
} elseif (strpos($markdown_url, '/') === 0) {
$new_url = rtrim($this->base_url, '/') . $markdown_url;
} else {
$relative_path = rtrim($this->base_url, '/') . $this->page->route();
// If this is a 'real' filepath clean it up
if (file_exists($this->page->path().'/'.parse_url($markdown_url, PHP_URL_PATH))) {
$relative_path = rtrim($this->base_url, '/') . preg_replace('/\/([\d]+.)/', '/', str_replace(PAGES_DIR, '/', $this->page->path()));
$markdown_url = preg_replace('/^([\d]+.)/', '', preg_replace('/\/([\d]+.)/', '/', trim(preg_replace('/[^\/]+(\.md$)/', '', $markdown_url), '/')));
}
// else its a relative path already
$newpath = array();
$paths = explode('/', $markdown_url);
// remove the updirectory references (..)
foreach ($paths as $path) {
if ($path == '..') {
$relative_path = dirname($relative_path);
} else {
$newpath[] = $path;
}
}
// build the new url
$new_url = rtrim($relative_path, '/') . '/' . implode('/', $newpath);
}
return $new_url;
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Grav\Common\Markdown;
class Parsedown extends \Parsedown
{
use ParsedownGravTrait;
public function __construct($page, $defaults)
{
$this->init($page, $defaults);
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Grav\Common\Markdown;
class ParsedownExtra extends \ParsedownExtra
{
use ParsedownGravTrait;
public function __construct($page, $defaults)
{
parent::__construct();
$this->init($page, $defaults);
}
}

View File

@@ -0,0 +1,213 @@
<?php
namespace Grav\Common\Markdown;
use Grav\Common\Config\Config;
use Grav\Common\Debugger;
use Grav\Common\GravTrait;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Uri;
use Grav\Common\Utils;
/**
* A trait to add some custom processing to the identifyLink() method in Parsedown and ParsedownExtra
*/
trait ParsedownGravTrait
{
use GravTrait;
protected $page;
protected $pages;
protected $base_url;
protected $pages_dir;
protected $special_chars;
protected $twig_link_regex = '/\!*\[(?:.*)\]\((\{([\{%#])\s*(.*?)\s*(?:\2|\})\})\)/';
/**
* Initialization function to setup key variables needed by the MarkdownGravLinkTrait
*
* @param $page
* @param $defaults
*/
protected function init($page, $defaults)
{
$this->page = $page;
$this->pages = self::getGrav()['pages'];
$this->BlockTypes['{'] [] = "TwigTag";
$this->base_url = rtrim(self::getGrav()['base_url'] . self::getGrav()['pages']->base(), '/');
$this->pages_dir = self::getGrav()['locator']->findResource('page://');
$this->special_chars = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
if ($defaults === null) {
$defaults = self::getGrav()['config']->get('system.pages.markdown');
}
$this->setBreaksEnabled($defaults['auto_line_breaks']);
$this->setUrlsLinked($defaults['auto_url_links']);
$this->setMarkupEscaped($defaults['escape_markup']);
$this->setSpecialChars($defaults['special_chars']);
}
/**
* Make the element function publicly accessible, Medium uses this to render from Twig
*
* @param array $Element
* @return string markup
*/
public function elementToHtml(array $Element)
{
return $this->element($Element);
}
/**
* Setter for special chars
*
* @param $special_chars
*
* @return $this
*/
function setSpecialChars($special_chars)
{
$this->special_chars = $special_chars;
return $this;
}
/**
* Ensure Twig tags are treated as block level items with no <p></p> tags
*/
protected function blockTwigTag($Line)
{
if (preg_match('/[{%|{{|{#].*[#}|}}|%}]/', $Line['body'], $matches)) {
$Block = array(
'markup' => $Line['body'],
);
return $Block;
}
}
protected function inlineSpecialCharacter($Excerpt)
{
if ($Excerpt['text'][0] === '&' && ! preg_match('/^&#?\w+;/', $Excerpt['text'])) {
return array(
'markup' => '&amp;',
'extent' => 1,
);
}
if (isset($this->special_chars[$Excerpt['text'][0]])) {
return array(
'markup' => '&'.$this->special_chars[$Excerpt['text'][0]].';',
'extent' => 1,
);
}
}
protected function inlineImage($excerpt)
{
if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) {
$excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']);
$excerpt = parent::inlineImage($excerpt);
$excerpt['element']['attributes']['src'] = $matches[1];
$excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1;
return $excerpt;
} else {
$excerpt = parent::inlineImage($excerpt);
}
// Some stuff we will need
$actions = array();
$media = null;
// if this is an image
if (isset($excerpt['element']['attributes']['src'])) {
$alt = $excerpt['element']['attributes']['alt'] ?: '';
$title = $excerpt['element']['attributes']['title'] ?: '';
$class = isset($excerpt['element']['attributes']['class']) ? $excerpt['element']['attributes']['class'] : '';
//get the url and parse it
$url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['src']));
// if there is no host set but there is a path, the file is local
if (!isset($url['host']) && isset($url['path'])) {
$path_parts = pathinfo($url['path']);
// get the local path to page media if possible
if ($path_parts['dirname'] == $this->page->url()) {
$url['path'] = $path_parts['basename'];
// get the media objects for this page
$media = $this->page->media();
} else {
// see if this is an external page to this one
$page_route = str_replace($this->base_url, '', $path_parts['dirname']);
$ext_page = $this->pages->dispatch($page_route, true);
if ($ext_page) {
$media = $ext_page->media();
$url['path'] = $path_parts['basename'];
}
}
// if there is a media file that matches the path referenced..
if ($media && isset($media->all()[$url['path']])) {
// get the medium object
$medium = $media->all()[$url['path']];
// if there is a query, then parse it and build action calls
if (isset($url['query'])) {
$actions = array_reduce(explode('&', $url['query']), function ($carry, $item) {
$parts = explode('=', $item, 2);
$value = isset($parts[1]) ? $parts[1] : null;
$carry[] = [ 'method' => $parts[0], 'params' => $value ];
return $carry;
}, []);
}
// loop through actions for the image and call them
foreach ($actions as $action) {
$medium = call_user_func_array(array($medium, $action['method']), explode(',', $action['params']));
}
if (isset($url['fragment'])) {
$medium->urlHash($url['fragment']);
}
$excerpt['element'] = $medium->parseDownElement($title, $alt, $class);
} else {
// not a current page media file, see if it needs converting to relative
$excerpt['element']['attributes']['src'] = Uri::buildUrl($url);
}
}
}
return $excerpt;
}
protected function inlineLink($excerpt)
{
// do some trickery to get around Parsedown requirement for valid URL if its Twig in there
if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) {
$excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']);
$excerpt = parent::inlineLink($excerpt);
$excerpt['element']['attributes']['href'] = $matches[1];
$excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1;
return $excerpt;
} else {
$excerpt = parent::inlineLink($excerpt);
}
// if this is a link
if (isset($excerpt['element']['attributes']['href'])) {
$url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href']));
// if there is no scheme, the file is local
if (!isset($url['scheme']) && (count($url) > 0)) {
// convert the URl is required
$excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url));
}
}
return $excerpt;
}
}

View File

@@ -3,6 +3,7 @@ namespace Grav\Common\Page;
use Grav\Common\Grav;
use Grav\Common\Iterator;
use Grav\Common\Utils;
/**
* Collection of Pages.
@@ -211,30 +212,35 @@ class Collection extends Iterator
}
/**
* Returns the items between a set of date ranges where second value is optional
* Returns the items between a set of date ranges of either the page date field (default) or
* an arbitrary datetime page field where end date is optional
* Dates can be passed in as text that strtotime() can process
* http://php.net/manual/en/function.strtotime.php
*
* @param $startDate
* @param bool $endDate
* @param $field
*
* @return $this
* @throws \Exception
*/
public function dateRange($startDate, $endDate = false)
public function dateRange($startDate, $endDate = false, $field = false)
{
$start = strtotime($startDate);
$end = $endDate ? strtotime($endDate) : strtotime("now +1000 years");
$start = Utils::date2timestamp($startDate);
$end = $endDate ? Utils::date2timestamp($endDate) : strtotime("now +1000 years");
$daterange = [];
$date_range = [];
foreach ($this->items as $path => $slug) {
$page = $this->pages->get($path);
if ($page->date() > $start && $page->date() < $end) {
$daterange[$path] = $slug;
$date = $field ? strtotime($page->value($field)) : $page->date();
if ($date > $start && $date < $end) {
$date_range[$path] = $slug;
}
}
$this->items = $daterange;
$this->items = $date_range;
return $this;
}
@@ -361,12 +367,13 @@ class Collection extends Iterator
{
$routable = [];
foreach (array_keys($this->items) as $path => $slug) {
foreach ($this->items as $path => $slug) {
$page = $this->pages->get($path);
if ($page->routable()) {
$routable[$path] = $slug;
}
}
$this->items = $routable;
return $this;
}
@@ -389,4 +396,47 @@ class Collection extends Iterator
$this->items = $routable;
return $this;
}
/**
* Creates new collection with only pages of the specified type
*
* @return Collection The collection
*/
public function ofType($type)
{
$items = [];
foreach ($this->items as $path => $slug) {
$page = $this->pages->get($path);
if ($page->template() == $type) {
$items[$path] = $slug;
}
}
$this->items = $items;
return $this;
}
/**
* Creates new collection with only pages of one of the specified types
*
* @return Collection The collection
*/
public function ofOneOfTheseTypes($types)
{
$items = [];
foreach ($this->items as $path => $slug) {
$page = $this->pages->get($path);
if (in_array($page->template(), $types)) {
$items[$path] = $slug;
}
}
$this->items = $items;
return $this;
}
}

View File

@@ -5,6 +5,8 @@ use Grav\Common\Getters;
use Grav\Common\Grav;
use Grav\Common\Config\Config;
use Grav\Common\GravTrait;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Page\Medium\MediumFactory;
/**
* Media is a holder object that contains references to the media of page. This object is created and
@@ -23,6 +25,7 @@ class Media extends Getters
protected $instances = array();
protected $images = array();
protected $videos = array();
protected $audios = array();
protected $files = array();
/**
@@ -37,88 +40,102 @@ class Media extends Getters
$this->path = $path;
$iterator = new \DirectoryIterator($path);
$iterator = new \FilesystemIterator($path, \FilesystemIterator::UNIX_PATHS | \FilesystemIterator::SKIP_DOTS);
$media = [];
/** @var \DirectoryIterator $info */
foreach ($iterator as $info) {
foreach ($iterator as $path => $info) {
// Ignore folders and Markdown files.
if ($info->isDot() || !$info->isFile() || $info->getExtension() == 'md') {
if (!$info->isFile() || $info->getExtension() == 'md' || $info->getBasename() === '.DS_Store') {
continue;
}
// Find out the real filename, in case of we are at the metadata.
$filename = $info->getFilename();
list($basename, $ext, $meta) = $this->getFileParts($filename);
// Find out what type we're dealing with
list($basename, $ext, $type, $extra) = $this->getFileParts($info->getFilename());
$media["{$basename}.{$ext}"] = isset($media["{$basename}.{$ext}"]) ? $media["{$basename}.{$ext}"] : [];
if ($type === 'alternative') {
$media["{$basename}.{$ext}"][$type] = isset($media["{$basename}.{$ext}"][$type]) ? $media["{$basename}.{$ext}"][$type] : [];
$media["{$basename}.{$ext}"][$type][$extra] = [ 'file' => $path, 'size' => $info->getSize() ];
} else {
$media["{$basename}.{$ext}"][$type] = [ 'file' => $path, 'size' => $info->getSize() ];
}
}
foreach ($media as $name => $types) {
// First prepare the alternatives in case there is no base medium
if (!empty($types['alternative'])) {
foreach ($types['alternative'] as $ratio => &$alt) {
$alt['file'] = MediumFactory::fromFile($alt['file']);
if (!$alt['file']) {
unset($types['alternative'][$ratio]);
} else {
$alt['file']->set('size', $alt['size']);
}
}
}
// Create the base medium
if (!empty($types['base'])) {
$medium = MediumFactory::fromFile($types['base']['file']);
$medium && $medium->set('size', $types['base']['size']);
} else if (!empty($types['alternative'])) {
$altMedium = reset($types['alternative']);
$ratio = key($types['alternative']);
$altMedium = $altMedium['file'];
$medium = MediumFactory::scaledFromMedium($altMedium, $ratio, 1)['file'];
}
// Get medium instance creating it if it didn't exist.
$medium = $this->get("{$basename}.{$ext}", true);
if (!$medium) {
continue;
}
//set file size
$medium->set('size', $info->getSize());
// Assign meta files to the medium.
if ($meta) {
$medium->addMetaFile($meta);
if (!empty($types['meta'])) {
$medium->addMetaFile($types['meta']['file']);
}
if (!empty($types['thumb'])) {
// We will not turn it into medium yet because user might never request the thumbnail
// not wasting any resources on that, maybe we should do this for medium in general?
$medium->set('thumbnails.page', $types['thumb']['file']);
}
// Build missing alternatives
if (!empty($types['alternative'])) {
$alternatives = $types['alternative'];
$max = max(array_keys($alternatives));
for ($i=2; $i < $max; $i++) {
if (isset($alternatives[$i])) {
continue;
}
$types['alternative'][$i] = MediumFactory::scaledFromMedium($alternatives[$max]['file'], $max, $i);
}
foreach ($types['alternative'] as $ratio => $altMedium) {
$medium->addAlternative($ratio, $altMedium['file']);
}
}
$this->add($name, $medium);
}
}
/**
* Get medium by basename and extension.
* Get medium by filename.
*
* @param string $filename
* @param bool $create
* @return Medium|null
*/
public function get($filename, $create = false)
public function get($filename)
{
if ($create && !isset($this->instances[$filename])) {
$parts = explode('.', $filename);
$ext = array_pop($parts);
$basename = implode('.', $parts);
/** @var Config $config */
$config = self::$grav['config'];
// Check if medium type has been configured.
$params = $config->get("media.".strtolower($ext));
if (!$params) {
return null;
}
$filePath = $this->path . '/' . $filename;
// Add default settings for undefined variables.
$params += $config->get('media.defaults');
$params += array(
'type' => 'file',
'thumb' => 'media/thumb.png',
'mime' => 'application/octet-stream',
'name' => $filename,
'filename' => $filename,
'basename' => $basename,
'extension' => $ext,
'path' => $this->path,
'modified' => filemtime($filePath),
);
$lookup = array(
USER_DIR . 'images/',
SYSTEM_DIR . 'images/',
);
foreach ($lookup as $path) {
if (is_file($path . $params['thumb'])) {
$params['thumb'] = $path . $params['thumb'];
break;
}
}
$this->add(new Medium($params));
}
return isset($this->instances[$filename]) ? $this->instances[$filename] : null;
}
@@ -155,6 +172,17 @@ class Media extends Getters
return $this->videos;
}
/**
* Get a list of all audio media.
*
* @return array|Medium[]
*/
public function audios()
{
ksort($this->audios, SORT_NATURAL | SORT_FLAG_CASE);
return $this->audios;
}
/**
* Get a list of all file media.
*
@@ -169,18 +197,21 @@ class Media extends Getters
/**
* @internal
*/
protected function add($file)
protected function add($name, $file)
{
$this->instances[$file->filename] = $file;
$this->instances[$name] = $file;
switch ($file->type) {
case 'image':
$this->images[$file->filename] = $file;
$this->images[$name] = $file;
break;
case 'video':
$this->videos[$file->filename] = $file;
$this->videos[$name] = $file;
break;
case 'audio':
$this->audios[$name] = $file;
break;
default:
$this->files[$file->filename] = $file;
$this->files[$name] = $file;
}
}
@@ -195,19 +226,35 @@ class Media extends Getters
$fileParts = explode('.', $filename);
$name = array_shift($fileParts);
$extension = null;
while (($part = array_shift($fileParts)) !== null) {
if ($part != 'meta') {
if (isset($extension)) {
$name .= '.' . $extension;
$type = 'base';
$extra = null;
if (preg_match('/(.*)@(\d+)x\.(.*)$/', $filename, $matches)) {
$name = $matches[1];
$extension = $matches[3];
$extra = (int) $matches[2];
$type = 'alternative';
if ($extra === 1) {
$type = 'base';
$extra = null;
}
} else {
$extension = null;
while (($part = array_shift($fileParts)) !== null) {
if ($part != 'meta' && $part != 'thumb') {
if (isset($extension)) {
$name .= '.' . $extension;
}
$extension = $part;
} else {
$type = $part;
$extra = '.' . $part . '.' . implode('.', $fileParts);
break;
}
$extension = $part;
} else {
break;
}
}
$meta = implode('.', $fileParts);
return array($name, $extension, $meta);
return array($name, $extension, $type, $extra);
}
}

View File

@@ -1,382 +0,0 @@
<?php
namespace Grav\Common\Page;
use Grav\Common\Config\Config;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Grav;
use Grav\Common\GravTrait;
use Grav\Common\Data\Blueprint;
use Grav\Common\Data\Data;
use Gregwar\Image\Image as ImageFile;
/**
* The Image medium holds information related to an individual image. These are then stored in the Media object.
*
* @author RocketTheme
* @license MIT
*
* @property string $file_name
* @property string $type
* @property string $name Alias of file_name
* @property string $description
* @property string $url
* @property string $path
* @property string $thumb
* @property int $width
* @property int $height
* @property string $mime
* @property int $modified
*
* Medium can have up to 3 files:
* - video.mov Medium file itself.
* - video.mov.meta.yaml Metadata for the medium.
* - video.mov.thumb.jpg Thumbnail image for the medium.
*
*/
class Medium extends Data
{
use GravTrait;
/**
* @var string
*/
protected $path;
/**
* @var ImageFile
*/
protected $image;
protected $type = 'guess';
protected $quality = 85;
public static $valid_actions = ['resize', 'forceResize', 'cropResize', 'crop', 'cropZoom',
'negate', 'brightness', 'contrast', 'grayscale', 'emboss', 'smooth', 'sharp', 'edge', 'colorize', 'sepia' ];
/**
* @var array
*/
protected $meta = array();
/**
* @var string
*/
protected $linkTarget;
/**
* @var string
*/
protected $linkAttributes;
public function __construct($items = array(), Blueprint $blueprint = null)
{
parent::__construct($items, $blueprint);
$file_path = $this->get('path') . '/' . $this->get('filename');
$file_parts = pathinfo($file_path);
$this->set('thumb', $file_path);
$this->set('extension', $file_parts['extension']);
$this->set('filename', $this->get('filename'));
if ($this->get('type') == 'image') {
$image_info = getimagesize($file_path);
$this->def('width', $image_info[0]);
$this->def('height', $image_info[1]);
$this->def('mime', $image_info['mime']);
$this->reset();
} else {
$this->def('mime', 'application/octet-stream');
}
}
/**
* Return string representation of the object (html or url).
*
* @return string
*/
public function __toString()
{
return $this->linkImage ? $this->html() : $this->url();
}
/**
* Return PATH to file.
*
* @return string path to file
*/
public function path()
{
/** @var Config $config */
$config = self::$grav['config'];
if ($this->image) {
$output = $this->image->cacheFile($this->type, $this->quality);
$this->reset();
$output = ROOT_DIR . $output;
} else {
$output = $this->get('path') . '/' . $this->get('filename');
}
return $output;
}
/**
* Sets the quality of the image
* @param Int $quality 0-100 quality
* @return Medium
*/
public function quality($quality)
{
$this->quality = $quality;
return $this;
}
/**
* Return URL to file.
*
* @return string
*/
public function url()
{
if ($this->image) {
$output = $this->image->cacheFile($this->type, $this->quality);
$this->reset();
} else {
$relPath = preg_replace('|^' . ROOT_DIR . '|', '', $this->get('path'));
$output = $relPath . '/' . $this->get('filename');
}
return self::$grav['base_url'] . '/'. $output;
}
/**
* Sets image output format.
*
* @param string $type
* @param int $quality
* @return $this
*/
public function format($type = null, $quality = 80)
{
if (!$this->image) {
$this->image();
}
$this->type = $type;
$this->quality = $quality;
return $this;
}
/**
* Returns <img> tag from the medium.
*
* @param string $title
* @param string $class
* @param string $type
* @param int $quality
* @return string
*/
public function img($title = null, $class = null, $type = null, $quality = 80)
{
if (!$this->image) {
$this->image();
}
$output = $this->html($title, $class, $type, $quality);
return $output;
}
/**
* Return HTML markup from the medium.
*
* @param string $title
* @param string $class
* @param string $type
* @param int $quality
* @return string
*/
public function html($title = null, $class = null, $type = null, $quality = 80)
{
$title = $title ? $title : $this->get('title');
$class = $class ? $class : '';
if ($this->image) {
$type = $type ? $type : $this->type;
$quality = $quality ? $quality : $this->quality;
$url = $this->url($type, $quality);
$this->reset();
$output = '<img src="' . $url . '" class="'. $class . '" alt="' . $title . '" />';
} else {
$output = $title;
}
if ($this->linkTarget) {
/** @var Config $config */
$config = self::$grav['config'];
$output = '<a href="' . self::$grav['base_url'] . '/'. $this->linkTarget
. '"' . $this->linkAttributes. ' class="'. $class . '">' . $output . '</a>';
$this->linkTarget = $this->linkAttributes = null;
}
return $output;
}
/**
* Return lightbox HTML for the medium.
*
* @param int $width
* @param int $height
* @return $this
*/
public function lightbox($width = null, $height = null)
{
$this->linkAttributes = ' rel="lightbox"';
return $this->link($width, $height);
}
public function lightboxRaw($width = null, $height = null)
{
/** @var Config $config */
$config = self::$grav['config'];
$url = $this->url();
$this->link($width, $height);
$lightbox_url = self::$grav['base_url'] . '/'. $this->linkTarget;
return array('a_url' => $lightbox_url, 'a_rel' => 'lightbox', 'img_url' => $url);
}
/**
* Return link HTML for the medium.
*
* @param int $width
* @param int $height
* @return $this
*/
public function link($width = null, $height = null)
{
if ($this->image) {
$image = clone $this->image;
if ($width && $height) {
$image->cropResize($width, $height);
}
$this->linkTarget = $image->cacheFile($this->type, $this->quality);
} else {
// TODO: we need to find out URI in a bit better way.
$relPath = preg_replace('|^' . ROOT_DIR . '|', '', $this->get('path'));
$this->linkTarget = $relPath. '/' . $this->get('filename');
}
return $this;
}
/**
* Reset image.
*
* @return $this
*/
public function reset()
{
$this->image = null;
if ($this->get('type') == 'image') {
$this->image();
$this->filter();
}
$this->type = 'guess';
$this->quality = 80;
return $this;
}
/**
* Forward the call to the image processing method.
*
* @param string $method
* @param mixed $args
* @return $this|mixed
*/
public function __call($method, $args)
{
if ($method == 'cropZoom') {
$method = 'zoomCrop';
}
// Always initialize image.
if (!$this->image) {
$this->image();
}
try {
$result = call_user_func_array(array($this->image, $method), $args);
} catch (\BadFunctionCallException $e) {
$result = null;
}
// Returns either current object or result of the action.
return $result instanceof ImageFile ? $this : $result;
}
/**
* Gets medium image, resets image manipulation operations.
*
* @param string $variable
* @return $this
*/
public function image($variable = 'thumb')
{
// TODO: add default file
$file = $this->get($variable);
$this->image = ImageFile::open($file)
->setCacheDir(basename(IMAGES_DIR))
->setActualCacheDir(IMAGES_DIR)
->setPrettyName(basename($this->get('basename')));
$this->filter();
return $this;
}
/**
* Add meta file for the medium.
*
* @param $type
* @return $this
*/
public function addMetaFile($type)
{
$this->meta[$type] = $type;
$path = $this->get('path') . '/' . $this->get('filename') . '.meta.' . $type;
if ($type == 'yaml') {
$this->merge(CompiledYamlFile::instance($path)->content());
} elseif (in_array($type, array('jpg', 'jpeg', 'png', 'gif'))) {
$this->set('thumb', $path);
}
$this->reset();
return $this;
}
/**
* Filter image by using user defined filter parameters.
*
* @param string $filter Filter to be used.
*/
public function filter($filter = 'image.filters.default')
{
$filters = (array) $this->get($filter, array());
foreach ($filters as $params) {
$params = (array) $params;
$method = array_shift($params);
$this->__call($method, $params);
}
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace Grav\Common\Page\Medium;
use Grav\Common\GravTrait;
use Gregwar\Image\Exceptions\GenerationError;
use RocketTheme\Toolbox\Event\Event;
class ImageFile extends \Gregwar\Image\Image
{
use GravTrait;
/**
* This is the same as the Gregwar Image class except this one fires a Grav Event on creation of new cached file
*
* @param string $type the image type
* @param int $quality the quality (for JPEG)
* @param bool $actual
*
* @return mixed|string
*/
public function cacheFile($type = 'jpg', $quality = 80, $actual = false)
{
if ($type == 'guess') {
$type = $this->guessType();
}
if (!count($this->operations) && $type == $this->guessType() && !$this->forceCache) {
return $this->getFilename($this->getFilePath());
}
// Computes the hash
$this->hash = $this->getHash($type, $quality);
// Generates the cache file
$cacheFile = '';
if (!$this->prettyName || $this->prettyPrefix) {
$cacheFile .= $this->hash;
}
if ($this->prettyPrefix) {
$cacheFile .= '-';
}
if ($this->prettyName) {
$cacheFile .= $this->prettyName;
}
$cacheFile .= '.'.$type;
// If the files does not exists, save it
$image = $this;
// Target file should be younger than all the current image
// dependencies
$conditions = array(
'younger-than' => $this->getDependencies()
);
// The generating function
$generate = function ($target) use ($image, $type, $quality) {
$result = $image->save($target, $type, $quality);
if ($result != $target) {
throw new GenerationError($result);
}
self::getGrav()->fireEvent('onImageMediumSaved', new Event(['image' => $target]));
};
// Asking the cache for the cacheFile
try {
$file = $this->cache->getOrCreateFile($cacheFile, $conditions, $generate, $actual);
} catch (GenerationError $e) {
$file = $e->getNewFile();
}
if ($actual) {
return $file;
} else {
return $this->getFilename($file);
}
}
}

Some files were not shown because too many files have changed in this diff Show More