First commit

This commit is contained in:
Pierre Hubert
2016-11-19 12:08:12 +01:00
commit 990540b2b9
4706 changed files with 931207 additions and 0 deletions

View File

@ -0,0 +1,54 @@
div.phpdebugbar {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.phpdebugbar pre {
padding: 1rem;
}
.phpdebugbar div.phpdebugbar-header > div > * {
padding: 5px 15px;
}
.phpdebugbar div.phpdebugbar-header > div.phpdebugbar-header-right > * {
padding: 5px 8px;
}
.phpdebugbar div.phpdebugbar-header, .phpdebugbar a.phpdebugbar-restore-btn {
background-image: url(grav.png);
}
.phpdebugbar a.phpdebugbar-restore-btn {
width: 13px;
}
.phpdebugbar a.phpdebugbar-tab.phpdebugbar-active {
background: #3DB9EC;
color: #fff;
margin-top: -1px;
padding-top: 6px;
}
.phpdebugbar .phpdebugbar-widgets-toolbar {
padding-left: 5px;
}
.phpdebugbar input[type=text] {
padding: 0;
display: inline;
}
.phpdebugbar dl.phpdebugbar-widgets-varlist, ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
font-family: "DejaVu Sans Mono", Menlo, Monaco, Consolas, Courier, monospace;
font-size: 12px;
}
ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label {
text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff;
top: 0;
}
.phpdebugbar pre, .phpdebugbar code {
margin: 0;
font-size: 14px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

File diff suppressed because one or more lines are too long

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

@ -0,0 +1,19 @@
body header {
background: #8552A2;
}
body .left-panel {
background: inherit;
}
body .exc-title-primary {
color: #fff;
}
body .exc-title {
color: #ddd;
}
body .frame:not(.active):hover {
background: #e6e6e6;
}

View File

@ -0,0 +1,5 @@
title: PLUGIN_ADMIN.MEDIA
form:
validation: loose
fields:

View File

@ -0,0 +1,117 @@
title: PLUGIN_ADMIN.SITE
form:
validation: loose
fields:
content:
type: section
title: PLUGIN_ADMIN.DEFAULTS
underline: true
fields:
title:
type: text
label: PLUGIN_ADMIN.SITE_TITLE
size: large
placeholder: PLUGIN_ADMIN.SITE_TITLE_PLACEHOLDER
help: PLUGIN_ADMIN.SITE_TITLE_HELP
author.name:
type: text
size: large
label: PLUGIN_ADMIN.DEFAULT_AUTHOR
help: PLUGIN_ADMIN.DEFAULT_AUTHOR_HELP
author.email:
type: text
size: large
label: PLUGIN_ADMIN.DEFAULT_EMAIL
help: PLUGIN_ADMIN.DEFAULT_EMAIL_HELP
validate:
type: email
taxonomies:
type: selectize
size: large
label: PLUGIN_ADMIN.TAXONOMY_TYPES
classes: fancy
help: PLUGIN_ADMIN.TAXONOMY_TYPES_HELP
validate:
type: commalist
summary:
type: section
title: PLUGIN_ADMIN.PAGE_SUMMARY
underline: true
fields:
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
append: PLUGIN_ADMIN.CHARACTERS
label: PLUGIN_ADMIN.SUMMARY_SIZE
help: PLUGIN_ADMIN.SUMMARY_SIZE_HELP
validate:
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: 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: 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

@ -0,0 +1,8 @@
title: PLUGIN_ADMIN.FILE_STREAMS
form:
validation: loose
hidden: true
fields:
schemes.xxx:
type: array

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,290 @@
title: PLUGIN_ADMIN.DEFAULT
rules:
slug:
pattern: "[a-zа-я][a-zа-я0-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
validate:
type: textarea
uploads:
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: PLUGIN_ADMIN.OPTIONS
fields:
publishing:
type: section
title: PLUGIN_ADMIN.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::parentsRawRoutes'
data-default@: '\Grav\Plugin\admin::rawRoute'
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.dateformat:
toggleable: true
type: select
size: medium
selectize:
create: true
label: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT
help: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT_HELP
placeholder: PLUGIN_ADMIN.DEFAULT_DATE_FORMAT_PLACEHOLDER
data-options@: '\Grav\Common\Utils::dateFormats'
validate:
type: string
header.menu:
type: text
label: PLUGIN_ADMIN.MENU
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: text
toggleable: true
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
header.append_url_extension:
type: text
label: PLUGIN_ADMIN.APPEND_URL_EXT
toggleable: true
help: PLUGIN_ADMIN.APPEND_URL_EXT_HELP
header.order_by:
type: hidden
header.order_manual:
type: hidden
validate:
type: commalist
blueprint:
type: blueprint

View File

@ -0,0 +1,36 @@
rules:
slug:
pattern: "[a-zа-я][a-zа-я0-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
label: PLUGIN_ADMIN.TITLE
header.external_url:
type: text
label: PLUGIN_ADMIN.EXTERNAL_URL
placeholder: https://getgrav.org
validate:
required: true
options:
type: tab
title: PLUGIN_ADMIN.OPTIONS

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': 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

@ -0,0 +1,54 @@
rules:
slug:
pattern: "[a-z][a-z0-9_\-]+"
min: 2
max: 80
form:
validation: loose
fields:
section:
type: section
title: PLUGIN_ADMIN.ADD_MODULAR_CONTENT
title:
type: text
label: PLUGIN_ADMIN.PAGE_TITLE
validate:
required: true
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
validate:
type: slug
required: true
route:
type: select
label: PLUGIN_ADMIN.PAGE
classes: fancy
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
data-default@: '\Grav\Plugin\admin::rawRoute'
validate:
required: true
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
help: PLUGIN_ADMIN.PAGE_FILE_HELP
default: default
data-options@: '\Grav\Common\Page\Pages::modularTypes'
validate:
required: true
modular:
type: hidden
default: 1
validate:
type: bool
blueprint:
type: blueprint

View File

@ -0,0 +1,106 @@
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:
frontmatter:
classes: frontmatter
type: editor
label: PLUGIN_ADMIN.FRONTMATTER
autofocus: true
codemirror:
mode: 'yaml'
indentUnit: 4
autofocus: true
indentWithTabs: false
lineNumbers: true
styleActiveLine: true
gutters: ['CodeMirror-lint-markers']
lint: true
content:
type: markdown
uploads:
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: PLUGIN_ADMIN.OPTIONS
fields:
columns:
type: columns
fields:
column1:
type: column
fields:
ordering:
type: toggle
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
folder:
type: text
label: PLUGIN_ADMIN.FILENAME
validate:
type: slug
required: true
route:
type: select
label: PLUGIN_ADMIN.PARENT
classes: fancy
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
data-default@: '\Grav\Plugin\admin::rawRoute'
options:
'': PLUGIN_ADMIN.DEFAULT_OPTION_SELECT
validate:
required: true
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
default: default
data-options@: '\Grav\Common\Page\Pages::modularTypes'
validate:
required: true
column2:
type: column
fields:
order:
type: order
label: PLUGIN_ADMIN.ORDERING
blueprint:
type: blueprint

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::parentsRawRoutes'
data-default@: '\Grav\Plugin\admin::rawRoute'
options:
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT

View File

@ -0,0 +1,66 @@
rules:
slug:
pattern: "[a-z][a-z0-9_\-]+"
min: 2
max: 80
form:
validation: loose
fields:
section:
type: section
title: PLUGIN_ADMIN.ADD_PAGE
title:
type: text
label: PLUGIN_ADMIN.PAGE_TITLE
help: PLUGIN_ADMIN.PAGE_TITLE_HELP
validate:
required: true
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
type: slug
required: true
route:
type: select
label: PLUGIN_ADMIN.PARENT_PAGE
classes: fancy
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
data-default@: '\Grav\Plugin\admin::getLastPageRoute'
options:
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
validate:
required: true
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.PAGE_FILE
help: PLUGIN_ADMIN.PAGE_FILE_HELP
data-options@: '\Grav\Common\Page\Pages::types'
data-default@: '\Grav\Plugin\admin::getLastPageName'
validate:
required: true
visible:
type: toggle
label: PLUGIN_ADMIN.VISIBLE
help: PLUGIN_ADMIN.VISIBLE_HELP
highlight: ''
default: ''
options:
'': Auto
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
required: true
blueprint:
type: blueprint

View File

@ -0,0 +1,35 @@
rules:
slug:
pattern: "[a-z][a-z0-9_\-]+"
min: 2
max: 80
form:
validation: loose
fields:
section:
type: section
title: PLUGIN_ADMIN.ADD_FOLDER
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
type: slug
required: true
route:
type: select
label: PLUGIN_ADMIN.PARENT_PAGE
classes: fancy
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
data-default@: '\Grav\Plugin\admin::getLastPageRoute'
options:
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
validate:
required: true
blueprint:
type: blueprint

View File

@ -0,0 +1,105 @@
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:
frontmatter:
classes: frontmatter
type: editor
label: PLUGIN_ADMIN.FRONTMATTER
autofocus: true
codemirror:
mode: 'yaml'
indentUnit: 4
autofocus: true
indentWithTabs: false
lineNumbers: true
styleActiveLine: true
gutters: ['CodeMirror-lint-markers']
lint: true
content:
type: markdown
uploads:
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: PLUGIN_ADMIN.OPTIONS
fields:
columns:
type: columns
fields:
column1:
type: column
fields:
ordering:
type: toggle
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
type: slug
required: true
route:
type: select
label: PLUGIN_ADMIN.PARENT
classes: fancy
data-options@: '\Grav\Common\Page\Pages::parentsRawRoutes'
data-default@: '\Grav\Plugin\admin::rawRoute'
options:
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
help: PLUGIN_ADMIN.DISPLAY_TEMPLATE_HELP
default: default
data-options@: '\Grav\Common\Page\Pages::types'
validate:
required: true
column2:
type: column
fields:
order:
type: order
label: PLUGIN_ADMIN.ORDERING
blueprint:
type: blueprint

View File

@ -0,0 +1,92 @@
title: Site
form:
validation: loose
fields:
info:
type: userinfo
size: large
content:
type: section
title: PLUGIN_ADMIN.ACCOUNT
underline: true
username:
type: text
size: large
label: PLUGIN_ADMIN.USERNAME
disabled: true
readonly: true
email:
type: email
size: large
label: PLUGIN_ADMIN.EMAIL
validate:
type: email
message: PLUGIN_ADMIN.EMAIL_VALIDATION_MESSAGE
required: true
password:
type: password
size: large
label: PLUGIN_ADMIN.PASSWORD
validate:
required: false
message: PLUGIN_ADMIN.PASSWORD_VALIDATION_MESSAGE
pattern: '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}'
fullname:
type: text
size: large
label: PLUGIN_ADMIN.FULL_NAME
validate:
required: true
title:
type: text
size: large
label: PLUGIN_ADMIN.TITLE
language:
type: select
label: PLUGIN_ADMIN.LANGUAGE
size: medium
classes: fancy
data-options@: '\Grav\Plugin\admin::adminLanguages'
default: 'en'
help: PLUGIN_ADMIN.LANGUAGE_HELP
security:
title: PLUGIN_ADMIN.ACCESS_LEVELS
type: section
security: admin.super
underline: true
fields:
groups:
type: selectize
size: large
label: PLUGIN_ADMIN.GROUPS
data-options@: '\Grav\User\Groups::groups'
classes: fancy
help: PLUGIN_ADMIN.GROUPS_HELP
validate:
type: commalist
access.admin:
type: array
label: PLUGIN_ADMIN.ADMIN_ACCESS
multiple: false
validate:
type: array
access.site:
type: array
label: PLUGIN_ADMIN.SITE_ACCESS
multiple: false
validate:
type: array

View File

@ -0,0 +1,16 @@
title: PLUGIN_ADMIN.ADD_ACCOUNT
form:
validation: loose
fields:
content:
type: section
title: PLUGIN_ADMIN.ADD_ACCOUNT
username:
type: text
label: PLUGIN_ADMIN.USERNAME
help: PLUGIN_ADMIN.USERNAME_HELP
validate:
required: true

View File

@ -0,0 +1,44 @@
title: Group
form:
validation: loose
fields:
spacer:
type: spacer
text: '<br>'
groupname:
type: text
size: large
label: PLUGIN_ADMIN.NAME
disabled: true
readonly: true
readableName:
type: text
size: large
label: PLUGIN_ADMIN_PRO.READABLE_NAME
description:
type: text
size: large
label: PLUGIN_ADMIN.DESCRIPTION
icon:
type: text
size: small
label: PLUGIN_ADMIN_PRO.ICON
access.admin:
type: array
label: PLUGIN_ADMIN.ADMIN_ACCESS
multiple: false
validate:
type: array
access.site:
type: array
label: PLUGIN_ADMIN.SITE_ACCESS
multiple: false
validate:
type: array

View File

@ -0,0 +1,16 @@
title: PLUGIN_ADMIN_PRO.ADD_GROUP
form:
validation: loose
fields:
content:
type: section
title: PLUGIN_ADMIN_PRO.ADD_GROUP
groupname:
type: text
label: PLUGIN_ADMIN_PRO.GROUP_NAME
help: PLUGIN_ADMIN_PRO.GROUP_NAME_HELP
validate:
required: true

View File

@ -0,0 +1,203 @@
types:
defaults:
type: file
thumb: media/thumb.png
mime: application/octet-stream
image:
filters:
default:
- enableProgressive
jpg:
type: image
thumb: media/thumb-jpg.png
mime: image/jpeg
jpe:
type: image
thumb: media/thumb-jpg.png
mime: image/jpeg
jpeg:
type: image
thumb: media/thumb-jpeg.png
mime: image/jpeg
png:
type: image
thumb: media/thumb-png.png
mime: image/png
gif:
type: animated
thumb: media/thumb-gif.png
mime: image/gif
svg:
type: vector
thumb: media/thumb.png
mime: image/svg+xml
mp4:
type: video
thumb: media/thumb-mp4.png
mime: video/mp4
mov:
type: video
thumb: media/thumb-mov.png
mime: video/quicktime
m4v:
type: video
thumb: media/thumb-m4v.png
mime: video/x-m4v
swf:
type: video
thumb: media/thumb-swf.png
mime: video/x-flv
flv:
type: video
thumb: media/thumb-flv.png
mime: video/x-flv
webm:
type: video
thumb: media/thumb.png
mime: video/webm
ogv:
type: video
thumb: media/thumb-ogg.png
mime: video/ogg
mp3:
type: audio
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
aiff:
type: audio
mime: audio/aiff
aif:
type: audio
mime: audio/aif
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
mime: application/msword
docx:
type: file
mime: application/msword
xls:
type: file
mime: application/vnd.ms-excel
xlt:
type: file
mime: application/vnd.ms-excel
xlm:
type: file
mime: application/vnd.ms-excel
xld:
type: file
mime: application/vnd.ms-excel
xla:
type: file
mime: application/vnd.ms-excel
xlc:
type: file
mime: application/vnd.ms-excel
xlw:
type: file
mime: application/vnd.ms-excel
xll:
type: file
mime: application/vnd.ms-excel
ppt:
type: file
mime: application/vnd.ms-powerpoint
pps:
type: file
mime: application/vnd.ms-powerpoint
rtf:
type: file
mime: application/rtf
bmp:
type: file
mime: image/bmp
tiff:
type: file
mime: image/tiff
mpeg:
type: file
mime: video/mpeg
mpg:
type: file
mime: video/mpeg
mpe:
type: file
mime: video/mpeg
avi:
type: file
mime: video/msvideo
wmv:
type: file
mime: video/x-ms-wmv
html:
type: file
thumb: media/thumb-html.png
mime: text/html
htm:
type: file
thumb: media/thumb-html.png
mime: text/html
pdf:
type: file
thumb: media/thumb-pdf.png
mime: application/pdf
zip:
type: file
thumb: media/thumb-zip.png
mime: application/zip
7z:
type: file
thumb: media/thumb-7zip.png
mime: application/x-7z-compressed
gz:
type: file
thumb: media/thumb-gz.png
mime: application/gzip
tar:
type: file
mime: application/x-tar
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

@ -0,0 +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
metadata:
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
# '/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

@ -0,0 +1,16 @@
schemes:
image:
type: ReadOnlyStream
paths:
- user://images
- system://images
page:
type: ReadOnlyStream
paths:
- user://pages
account:
type: ReadOnlyStream
paths:
- user://accounts

View File

@ -0,0 +1,131 @@
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
wrapped_site: false # For themes/plugins to know if Grav is wrapped by another platform
reverse_proxy_setup: false # Running in a reverse proxy scenario with different webserver ports than proxy
force_ssl: false # If enabled, Grav forces to be accessed via HTTPS (NOTE: Not an ideal solution)
custom_base_url: '' # Set the base_url manually
languages:
supported: [] # List of languages supported. eg: [en, fr, de]
include_default_lang: true # Include the default lang prefix in all URLs
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
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 /
hide_in_urls: false # Hide the home route in URLs
pages:
theme: antimatter # Default theme (defaults to "antimatter" theme)
order:
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
process:
markdown: true # Process Markdown
twig: false # Process Twig
twig_first: false # Process Twig before markdown when processing both on a page
events:
page: true # Enable page level events
twig: true # Enable Twig level events
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,htm,json,rss,atom] # list of valid page types
append_url_extension: '' # Append page's extension in Page urls (e.g. '.html' results in /path/page.html)
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_default_code: 301 # Default code to use for redirects
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
ignore_hidden: true # Ignore all Hidden files and folders
url_taxonomy_filters: true # Enable auto-magic URL-based taxonomy filters for page collections
frontmatter:
process_twig: false # Should the frontmatter be processed to replace Twig variables?
ignore_fields: ['form','forms'] # Fields that might contain Twig variables and should not be processed
cache:
enabled: true # Set to true to enable caching
check:
method: file # Method to check for updates in pages: file|folder|none
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
debug: true # Enable Twig debug
auto_reload: true # Refresh cache on changes
autoescape: false # Autoescape Twig vars
undefined_functions: true # Allow undefined functions
undefined_filters: true # Allow undefined filters
umask_fix: false # By default Twig creates cached files as 755, fix switches this to 775
assets: # Configuration for Assets Manager (JS, CSS)
css_pipeline: false # The CSS pipeline is the unification of multiple CSS resources into one file
css_pipeline_include_externals: true # Include external URLs in the pipeline by default
css_pipeline_before_excludes: true # Render the pipeline before any excluded files
css_minify: true # Minify the CSS during pipelining
css_minify_windows: false # Minify Override for Windows platforms. False by default due to ThreadStackSize
css_rewrite: true # Rewrite any CSS relative URLs during pipelining
js_pipeline: false # The JS pipeline is the unification of multiple JS resources into one file
js_pipeline_include_externals: true # Include external URLs in the pipeline by default
js_pipeline_before_excludes: true # Render the pipeline before any excluded files
js_minify: true # Minify the JS during pipelining
enable_asset_timestamp: false # Enable asset timestamps
collections:
jquery: system://assets/jquery/jquery-2.x.min.js
errors:
display: false # Display full backtrace-style error page
log: true # Log errors to /logs folder
debugger:
enabled: false # Enable Grav debugger and following settings
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
cache_perms: '0755' # MUST BE IN QUOTES!! Default cache folder perms. Usually '0755' or '0775'
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 supported media types to try to display inline
allowed_fallback_types: [] # Array of allowed media types of files found if accessed via Page route
session:
enabled: true # Enable Session support
timeout: 1800 # Timeout in seconds
name: grav-site # Name prefix of the session cookie. Use alphanumeric, dashes or underscores only. Do not use dots in the session name
secure: false # Set session secure. If true, indicates that communication for this cookie must be over an encrypted transmission. Enable this only on sites that run exclusively on HTTPS
httponly: true # Set session HTTP only. If true, indicates that cookies should be used only over HTTP, and JavaScript modification is not allowed.
path:
gpm:
releases: stable # Set to either 'stable' or 'testing'
proxy_url: # Configure a manual proxy URL for GPM (eg 127.0.0.1:3128)

View File

@ -0,0 +1,50 @@
<?php
/**
* @package Grav.Core
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.1.5');
define('GRAV_TESTING', false);
define('DS', '/');
define('GRAV_PHP_MIN', '5.5.9');
// Directories and Paths
if (!defined('GRAV_ROOT')) {
define('GRAV_ROOT', str_replace(DIRECTORY_SEPARATOR, DS, getcwd()));
}
define('ROOT_DIR', GRAV_ROOT . '/');
define('USER_PATH', 'user/');
define('USER_DIR', ROOT_DIR . USER_PATH);
define('CACHE_DIR', ROOT_DIR . 'cache/');
// DEPRECATED: Do not use!
define('ASSETS_DIR', ROOT_DIR . 'assets/');
define('IMAGES_DIR', ROOT_DIR . 'images/');
define('ACCOUNTS_DIR', USER_DIR .'accounts/');
define('PAGES_DIR', USER_DIR .'pages/');
define('DATA_DIR', USER_DIR .'data/');
define('SYSTEM_DIR', ROOT_DIR .'system/');
define('LIB_DIR', SYSTEM_DIR .'src/');
define('PLUGINS_DIR', USER_DIR .'plugins/');
define('THEMES_DIR', USER_DIR .'themes/');
define('VENDOR_DIR', ROOT_DIR .'vendor/');
define('LOG_DIR', ROOT_DIR .'logs/');
// END DEPRECATED
// Some extensions
define('CONTENT_EXT', '.md');
define('TEMPLATE_EXT', '.html.twig');
define('TWIG_EXT', '.twig');
define('PLUGIN_EXT', '.php');
define('YAML_EXT', '.yaml');
// Content types
define('RAW_CONTENT', 1);
define('TWIG_CONTENT', 2);
define('TWIG_CONTENT_LIST', 3);
define('TWIG_TEMPLATES', 4);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

View File

@ -0,0 +1,75 @@
---
FRONTMATTER_ERROR_PAGE: |
---
العنوان: %1$s
---
# خطأ: مادة أمامية غير صحيحة
مسار: '%2$s'
**%3$s**
, , ,
%4$s
, , ,
NICETIME:
NO_DATE_PROVIDED: لم يتم تقديم التاريخ
BAD_DATE: تاريخ خاطئ
AGO: من قبل
FROM_NOW: من الآن
SECOND: ثانية
MINUTE: دقيقة
HOUR: ساعة
DAY: يوم
WEEK: أسبوع
MONTH: شهر
YEAR: سنة
DECADE: عقد
SEC: ثانية
MIN: دقيقة
HR: ساعة
WK: أسبوع
MO: شهر
YR: سنة
DEC: عقد
SECOND_PLURAL: ثواني
MINUTE_PLURAL: ‮دقائق
HOUR_PLURAL: ساعات
DAY_PLURAL: أيام
WEEK_PLURAL: أسابيع
MONTH_PLURAL: أشهر
YEAR_PLURAL: سنوات
DECADE_PLURAL: عقود
SEC_PLURAL: ثواني
MIN_PLURAL: دقائق
HR_PLURAL: ساعات
WK_PLURAL: أسابيع
MO_PLURAL: أشهر
YR_PLURAL: سنوات
DEC_PLURAL: عقود
FORM:
VALIDATION_FAIL: '<b>فشل التحقق من صحة:</b>'
INVALID_INPUT: إدخال غير صحيح في
MISSING_REQUIRED_FIELD: 'حقل مطلوب مفقود:'
MONTHS_OF_THE_YEAR:
- كانون الثاني
- شباط
- آذار/ مارس
- نيسان
- أيار
- حزيران
- تموز
- آب
- أيلول
- تشرين الأول
- تشرين الثاني
- كانون الأول
DAYS_OF_THE_WEEK:
- الاثنين
- الثلاثاء
- الأربعاء
- الخميس
- الجمعة
- السبت
- الأحد

View File

@ -0,0 +1,75 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# S'ha produït un error: Frontmatter invàlid
Ruta: `%2$s`
**%3$s**
```
%4$s
```
NICETIME:
NO_DATE_PROVIDED: "No s'ha proporcionat data"
BAD_DATE: Data invàlida
AGO: abans
FROM_NOW: "des d'ara"
SECOND: segon
MINUTE: minut
HOUR: hora
DAY: dia
WEEK: setmana
MONTH: mes
YEAR: any
DECADE: dècada
SEC: s
MIN: min
HR: h
WK: setm.
MO: m.
YR: a.
DEC: dèc.
SECOND_PLURAL: segons
MINUTE_PLURAL: minuts
HOUR_PLURAL: hores
DAY_PLURAL: dies
WEEK_PLURAL: setmanes
MONTH_PLURAL: mesos
YEAR_PLURAL: anys
DECADE_PLURAL: dècades
SEC_PLURAL: s
MIN_PLURAL: min
HR_PLURAL: h
WK_PLURAL: setm.
MO_PLURAL: mesos
YR_PLURAL: anys
DEC_PLURAL: dèc.
FORM:
VALIDATION_FAIL: '<b>Ha fallat la validació:</b>'
INVALID_INPUT: Entrada no vàlida a
MISSING_REQUIRED_FIELD: 'Falta camp obligatori:'
MONTHS_OF_THE_YEAR:
- Gener
- Febrer
- Març
- Abril
- Maig
- Juny
- Juliol
- Agost
- Setembre
- Octubre
- Novembre
- Desembre
DAYS_OF_THE_WEEK:
- Dilluns
- Dimarts
- Dimecres
- Dijous
- Divendres
- Dissabte
- Diumenge

View File

@ -0,0 +1,81 @@
---
INFLECTOR_UNCOUNTABLE:
- vybavení
- informace
- rýže
- peníze
- druhy
- série
- ryba
- ovce
INFLECTOR_IRREGULAR:
person: lidé
man: muži
child: děti
sex: pohlaví
move: pohyby
INFLECTOR_ORDINALS:
default: '.'
first: '.'
second: '.'
third: '.'
NICETIME:
NO_DATE_PROVIDED: Datum nebylo vloženo
BAD_DATE: Chybné datum
AGO: zpět
FROM_NOW: od teď
SECOND: sekunda
MINUTE: minuta
HOUR: hodina
DAY: den
WEEK: týden
MONTH: měsíc
YEAR: rok
DECADE: dekáda
SEC: sek
MIN: min
HR: hod
WK: t
MO: m
YR: r
DEC: dek
SECOND_PLURAL: sekundy
MINUTE_PLURAL: minuty
HOUR_PLURAL: hodiny
DAY_PLURAL: dny
WEEK_PLURAL: týdny
MONTH_PLURAL: měsíce
YEAR_PLURAL: roky
DECADE_PLURAL: dekády
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: hod
WK_PLURAL: t
MO_PLURAL: m
YR_PLURAL: r
DEC_PLURAL: dek
FORM:
VALIDATION_FAIL: '<b>Ověření se nezdařilo:</b>'
INVALID_INPUT: Neplatný vstup v
MISSING_REQUIRED_FIELD: 'Chybí požadované pole:'
MONTHS_OF_THE_YEAR:
- ledna
- února
- března
- dubna
- května
- června
- července
- srpna
- září
- října
- listopadu
- prosince
DAYS_OF_THE_WEEK:
- Pondělí
- Úterý
- Středa
- Čtvrtek
- Pátek
- Sobota
- Neděle

View File

@ -0,0 +1,75 @@
---
FRONTMATTER_ERROR_PAGE: |
---
Titel: %1$s
---
# Fejl: Ugyldigt frontmatter
Sti: `%2$s`
**%3$s**
```
%4$s
```
NICETIME:
NO_DATE_PROVIDED: Ingen dato angivet
BAD_DATE: Ugyldig dato
AGO: siden
FROM_NOW: fra nu
SECOND: sekund
MINUTE: minut
HOUR: time
DAY: dag
WEEK: uge
MONTH: måned
YEAR: år
DECADE: årti
SEC: sek
MIN: min
HR: t
WK: u
MO: md
YR: år
DEC: årti
SECOND_PLURAL: sekunder
MINUTE_PLURAL: minutter
HOUR_PLURAL: timer
DAY_PLURAL: dage
WEEK_PLURAL: uger
MONTH_PLURAL: måneder
YEAR_PLURAL: år
DECADE_PLURAL: årtier
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: timer
WK_PLURAL: uger
MO_PLURAL: mdr
YR_PLURAL: år
DEC_PLURAL: årtier
FORM:
VALIDATION_FAIL: '<b>Validering mislykkedes:</b>'
INVALID_INPUT: Ugyldigt input i
MISSING_REQUIRED_FIELD: 'Mangler obligatorisk felt:'
MONTHS_OF_THE_YEAR:
- Januar
- Februar
- Marts
- April
- Maj
- Juni
- Juli
- August
- September
- Oktober
- November
- December
DAYS_OF_THE_WEEK:
- Mandag
- Tirsdag
- Onsdag
- Torsdag
- Fredag
- Lørdag
- Søndag

View File

@ -0,0 +1,89 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Fehler: Frontmatter enthält Fehler
Pfad: `%2$s`
**%3$s **
```
%4$s
```
INFLECTOR_UNCOUNTABLE:
1: Informationen
2: Reis
3: Geld
INFLECTOR_IRREGULAR:
person: Personen
man: Menschen
child: Kinder
sex: Geschlecht
move: Züge
INFLECTOR_ORDINALS:
default: '.'
first: '.'
second: '.'
third: '.'
NICETIME:
NO_DATE_PROVIDED: Kein Datum angegeben
BAD_DATE: Falsches Datum
AGO: her
FROM_NOW: ab jetzt
SECOND: Sekunde
MINUTE: Minute
HOUR: Stunde
DAY: Tag
WEEK: Woche
MONTH: Monat
YEAR: Jahr
DECADE: Jahrzehnt
SEC: Sek.
MIN: Min.
HR: Std.
WK: Wo.
MO: Mo.
YR: J.
DEC: Dek.
SECOND_PLURAL: Sekunden
MINUTE_PLURAL: Minuten
HOUR_PLURAL: Stunden
DAY_PLURAL: Tage
WEEK_PLURAL: Wochen
MONTH_PLURAL: Monate
YEAR_PLURAL: Jahre
DECADE_PLURAL: Jahrzehnte
SEC_PLURAL: Sekunden
MIN_PLURAL: Minuten
HR_PLURAL: Stunden
WK_PLURAL: Wochen
MO_PLURAL: Monate
YR_PLURAL: Jahre
DEC_PLURAL: Jahrzehnten
FORM:
VALIDATION_FAIL: '<b>Überprüfung fehlgeschlagen:</b>'
INVALID_INPUT: Ungültige Eingabe in
MISSING_REQUIRED_FIELD: 'Erforderliches Feld fehlt:'
MONTHS_OF_THE_YEAR:
- Januar
- Februar
- März
- April
- Mai
- Juni
- Juli
- August
- September
- Oktober
- November
- Dezember
DAYS_OF_THE_WEEK:
- Montag
- Dienstag
- Mittwoch
- Donnerstag
- Freitag
- Samstag
- Sonntag

View File

@ -0,0 +1,22 @@
---
MONTHS_OF_THE_YEAR:
- Ιανουάριος
- Φεβρουάριος
- Μάρτιος
- Απρίλιος
- Μάιος
- Ιούνιος
- Ιούλιος
- Αύγουστος
- Σεπτέμβριος
- Οκτώβριος
- Νοέμβριος
- Δεκέμβριος
DAYS_OF_THE_WEEK:
- Δευτέρα
- Τρίτη
- Τετάρτη
- Πέμπτη
- Παρασκευή
- Σάββατο
- Κυριακή

View File

@ -0,0 +1,100 @@
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'
NICETIME:
NO_DATE_PROVIDED: No date provided
BAD_DATE: Bad date
AGO: ago
FROM_NOW: from now
SECOND: second
MINUTE: minute
HOUR: hour
DAY: day
WEEK: week
MONTH: month
YEAR: year
DECADE: decade
SEC: sec
MIN: min
HR: hr
DAY: day
WK: wk
MO: mo
YR: yr
DEC: dec
SECOND_PLURAL: seconds
MINUTE_PLURAL: minutes
HOUR_PLURAL: hours
DAY_PLURAL: days
WEEK_PLURAL: weeks
MONTH_PLURAL: months
YEAR_PLURAL: years
DECADE_PLURAL: decades
SEC_PLURAL: secs
MIN_PLURAL: mins
HR_PLURAL: hrs
DAY_PLURAL: days
WK_PLURAL: wks
MO_PLURAL: mos
YR_PLURAL: yrs
DEC_PLURAL: decs
FORM:
VALIDATION_FAIL: <b>Validation failed:</b>
INVALID_INPUT: Invalid input in
MISSING_REQUIRED_FIELD: Missing required field:
MONTHS_OF_THE_YEAR: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
DAYS_OF_THE_WEEK: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

View File

@ -0,0 +1,90 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Error: Frontmatter Inválido
Ruta: `%2$s`
**%3$s**
```
%4$s
```
INFLECTOR_UNCOUNTABLE:
0: equipo
1: información
3: dinero
5: series
6: pescado
7: oveja
INFLECTOR_IRREGULAR:
man: hombres
child: niños
sex: sexos
INFLECTOR_ORDINALS:
first: ro
second: do
third: ro
NICETIME:
NO_DATE_PROVIDED: No se proporcionó fecha
BAD_DATE: Fecha erronea
AGO: antes
FROM_NOW: desde ahora
SECOND: segundo
MINUTE: minuto
HOUR: hora
DAY: día
WEEK: semana
MONTH: mes
YEAR: año
DECADE: década
SEC: seg
MIN: min
HR: h
WK: sem
MO: mes
YR: año
DEC: dec
SECOND_PLURAL: segundos
MINUTE_PLURAL: minutos
HOUR_PLURAL: horas
DAY_PLURAL: días
WEEK_PLURAL: semanas
MONTH_PLURAL: meses
YEAR_PLURAL: años
DECADE_PLURAL: décadas
SEC_PLURAL: segs
MIN_PLURAL: mins
HR_PLURAL: hs
WK_PLURAL: sem
MO_PLURAL: mes
YR_PLURAL: años
DEC_PLURAL: décadas
FORM:
VALIDATION_FAIL: '<b>Falló la validación. </b>'
INVALID_INPUT: 'Dato inválido en: '
MISSING_REQUIRED_FIELD: 'Falta el campo requerido: '
MONTHS_OF_THE_YEAR:
- Enero
- Febrero
- Marzo
- Abril
- Mayo
- Junio
- Julio
- Agosto
- Septiembre
- Octubre
- Noviembre
- Diciembre
DAYS_OF_THE_WEEK:
- Lunes
- Martes
- Miércoles
- Jueves
- Viernes
- Sábado
- Domingo

View File

@ -0,0 +1,60 @@
---
NICETIME:
NO_DATE_PROVIDED: Päivämäärää ei annettu
BAD_DATE: Virheellinen päivämäärä
AGO: sitten
FROM_NOW: tästä lähtien
SECOND: sekunti
MINUTE: minuutti
HOUR: tunti
DAY: päivä
WEEK: viikko
MONTH: kuukausi
YEAR: vuosi
DECADE: vuosikymmen
SEC: sek
MIN: min
HR: h
WK: vk
MO: kk
YR: v
DEC: vuosikymmen
SECOND_PLURAL: sekuntia
MINUTE_PLURAL: minuuttia
HOUR_PLURAL: tuntia
DAY_PLURAL: päivää
WEEK_PLURAL: viikkoa
MONTH_PLURAL: kuukautta
YEAR_PLURAL: vuotta
DECADE_PLURAL: vuosikymmentä
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: h
WK_PLURAL: v
MO_PLURAL: kk
YR_PLURAL: v
DEC_PLURAL: vuosikymmentä
FORM:
VALIDATION_FAIL: '<b>Vahvistus epäonnistui:</b>'
MISSING_REQUIRED_FIELD: 'Puuttuva pakollinen kenttä:'
MONTHS_OF_THE_YEAR:
- Tammikuu
- Helmikuu
- Maaliskuu
- Huhtikuu
- Toukokuu
- Kesäkuuta
- Heinäkuu
- Elokuu
- Syyskuu
- Lokakuu
- Marraskuu
- Joulukuu
DAYS_OF_THE_WEEK:
- Maanantai
- Tiistai
- Keskiviikko
- Torstai
- Perjantai
- Lauantai
- Sunnuntai

View File

@ -0,0 +1,138 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Erreur : Frontmatter invalide
Path: `%2$s`
**%3$s**
```
%4$s
```
INFLECTOR_PLURALS:
/(quiz)$/i: '\1zes'
/^(ox)$/i: '\1en'
"/([m|l])ouse$/i": '\1ice'
/(matr|vert|ind)ix|ex$/i: '\1ices'
/(x|ch|ss|sh)$/i: '\1es'
"/([^aeiouy]|qu)ies$/i": '\1y'
"/([^aeiouy]|qu)y$/i": '\1ies'
/(hive)$/i: '\1s'
"/(?:([^f])fe|([lr])f)$/i": '\1\2ves'
/sis$/i: ses
"/([ti])um$/i": '\1a'
/(buffal|tomat)o$/i: '\1oes'
/(bu)s$/i: '\1ses'
/(alias|status)/i: '\1es'
/(octop|vir)us$/i: '\1i'
/(ax|test)is$/i: '\1es'
/s$/i: s
/$/: s
INFLECTOR_SINGULAR:
/(quiz)zes$/i: '\1'
/(matr)ices$/i: '\1ix'
/(vert|ind)ices$/i: '\1ex'
/^(ox)en/i: '\1'
/(alias|status)es$/i: '\1'
"/([octop|vir])i$/i": '\1us'
/(cris|ax|test)es$/i: '\1is'
/(shoe)s$/i: '\1'
/(o)es$/i: '\1'
/(bus)es$/i: '\1'
"/([m|l])ice$/i": '\1ouse'
/(x|ch|ss|sh)es$/i: '\1'
/(m)ovies$/i: '\1ovie'
/(s)eries$/i: '\1eries'
"/([^aeiouy]|qu)ies$/i": '\1y'
"/([lr])ves$/i": '\1f'
/(tive)s$/i: '\1'
/(hive)s$/i: '\1'
"/([^f])ves$/i": '\1fe'
/(^analy)ses$/i: '\1sis'
/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i: '\1\2sis'
"/([ti])a$/i": '\1um'
/(n)ews$/i: '\1ews'
INFLECTOR_UNCOUNTABLE:
- équipement
- informations
- riz
- argent
- espèces
- séries
- poisson
- mouton
INFLECTOR_IRREGULAR:
person: personnes
man: hommes
child: enfants
sex: sexes
move: déplacements
INFLECTOR_ORDINALS:
default: ème
first: er
second: ème
third: ème
NICETIME:
NO_DATE_PROVIDED: Aucune date fournie
BAD_DATE: Date erronée
AGO: plus tôt
FROM_NOW: à partir de maintenant
SECOND: seconde
MINUTE: minute
HOUR: heure
DAY: jour
WEEK: semaine
MONTH: mois
YEAR: année
DECADE: décennie
SEC: s
MIN: m
HR: h
WK: sem
MO: m
YR: an
DEC: déc
SECOND_PLURAL: secondes
MINUTE_PLURAL: minutes
HOUR_PLURAL: heures
DAY_PLURAL: jours
WEEK_PLURAL: semaines
MONTH_PLURAL: mois
YEAR_PLURAL: années
DECADE_PLURAL: décennies
SEC_PLURAL: s
MIN_PLURAL: m
HR_PLURAL: h
WK_PLURAL: sem
MO_PLURAL: mois
YR_PLURAL: a
DEC_PLURAL: décs
FORM:
VALIDATION_FAIL: '<b>La validation a échoué :</b>'
INVALID_INPUT: Saisie non valide
MISSING_REQUIRED_FIELD: 'Champ obligatoire manquant :'
MONTHS_OF_THE_YEAR:
- Janvier
- Février
- Mars
- Avril
- Mai
- Juin
- Juillet
- Août
- Septembre
- Octobre
- Novembre
- Décembre
DAYS_OF_THE_WEEK:
- Lundi
- Mardi
- Mercredi
- Jeudi
- Vendredi
- Samedi
- Dimanche

View File

@ -0,0 +1,75 @@
---
INFLECTOR_UNCOUNTABLE:
- oprema
- informacije
- riža
- novac
- vrsta
- serija
- riba
- ovca
INFLECTOR_IRREGULAR:
person: osobe
man: ljudi
child: djeca
sex: spolovi
move: Pomakni
NICETIME:
NO_DATE_PROVIDED: Datum nije upisan
BAD_DATE: Pogrešan datum
AGO: prije
FROM_NOW: od sada
SECOND: sekunda
MINUTE: minuta
HOUR: sat
DAY: dan
WEEK: tjedan
MONTH: mjesec
YEAR: godina
DECADE: desetljeće
SEC: sek
HR: sat
WK: t
MO: m
YR: g
DEC: des
SECOND_PLURAL: sekundi
MINUTE_PLURAL: minuta
HOUR_PLURAL: sati
DAY_PLURAL: dan
WEEK_PLURAL: tjedana
MONTH_PLURAL: mjeseci
YEAR_PLURAL: godina
DECADE_PLURAL: desetljeća
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: sat
WK_PLURAL: t
MO_PLURAL: m
YR_PLURAL: g
DEC_PLURAL: des
FORM:
VALIDATION_FAIL: '<b>Validacija nije uspjela:</b>'
INVALID_INPUT: Pogrešan unos u
MISSING_REQUIRED_FIELD: 'Nedostaje obavezno polje:'
MONTHS_OF_THE_YEAR:
- Siječanj
- Veljača
- Ožujak
- Travanj
- Svibanj
- Lipanj
- Srpanj
- Kolovoz
- Rujan
- Listopad
- Studeni
- Prosinac
DAYS_OF_THE_WEEK:
- Ponedjeljak
- Utorak
- Srijeda
- Četvrtak
- Petak
- Subota
- Nedjelja

View File

@ -0,0 +1,138 @@
---
FRONTMATTER_ERROR_PAGE: |
---
cím: %1$s
---
# Hiba: Érvénytelen Frontmatter
Elérési út: `%2$s`
**%3$s**
```
%4$s
```
INFLECTOR_PLURALS:
/(quiz)$/i: '\1zes'
/^(ox)$/i: '\1en'
"/([m|l])ouse$/i": '\1ice'
/(matr|vert|ind)ix|ex$/i: '\1ices'
/(x|ch|ss|sh)$/i: '\1es'
"/([^aeiouy]|qu)ies$/i": '\1y'
"/([^aeiouy]|qu)y$/i": '\1ies'
/(hive)$/i: '\1s'
"/(?:([^f])fe|([lr])f)$/i": '\1\2ves'
/sis$/i: ses
"/([ti])um$/i": '\1a'
/(buffal|tomat)o$/i: '\1oes'
/(bu)s$/i: '\1ses'
/(alias|status)/i: '\1es'
/(octop|vir)us$/i: '\1i'
/(ax|test)is$/i: '\1es'
/s$/i: s
/$/: s
INFLECTOR_SINGULAR:
/(quiz)zes$/i: '\1'
/(matr)ices$/i: '\1ix'
/(vert|ind)ices$/i: '\1ex'
/^(ox)en/i: '\1'
/(alias|status)es$/i: '\1'
"/([octop|vir])i$/i": '\1us'
/(cris|ax|test)es$/i: '\1is'
/(shoe)s$/i: '\1'
/(o)es$/i: '\1'
/(bus)es$/i: '\1'
"/([m|l])ice$/i": '\1ouse'
/(x|ch|ss|sh)es$/i: '\1'
/(m)ovies$/i: '\1ovie'
/(s)eries$/i: '\1eries'
"/([^aeiouy]|qu)ies$/i": '\1y'
"/([lr])ves$/i": '\1f'
/(tive)s$/i: '\1'
/(hive)s$/i: '\1'
"/([^f])ves$/i": '\1fe'
/(^analy)ses$/i: '\1sis'
/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i: '\1\2sis'
"/([ti])a$/i": '\1um'
/(n)ews$/i: '\1ews'
INFLECTOR_UNCOUNTABLE:
- felszerelés
- információ
- rizs
- pénz
- fajok
- sorozat
- hal
- juh
INFLECTOR_IRREGULAR:
person: személyek
man: férfiak
child: gyerekek
sex: nemek
move: lépések
INFLECTOR_ORDINALS:
default: '.'
first: '.'
second: '.'
third: '.'
NICETIME:
NO_DATE_PROVIDED: Nincs dátum megadva
BAD_DATE: Hibás dátum
AGO: elteltével
FROM_NOW: mostantól
SECOND: másodperc
MINUTE: perc
HOUR: óra
DAY: nap
WEEK: hét
MONTH: hónap
YEAR: év
DECADE: évtized
SEC: mp
MIN: p
HR: ó
WK: hét
MO:
YR: év
DEC: évt
SECOND_PLURAL: másodperc
MINUTE_PLURAL: perc
HOUR_PLURAL: óra
DAY_PLURAL: nap
WEEK_PLURAL: hét
MONTH_PLURAL: hónap
YEAR_PLURAL: év
DECADE_PLURAL: évtized
SEC_PLURAL: mp
MIN_PLURAL: perc
HR_PLURAL: ó
WK_PLURAL: hét
MO_PLURAL:
YR_PLURAL: év
DEC_PLURAL: évt
FORM:
VALIDATION_FAIL: '<b>A validáció hibát talált:</b>'
INVALID_INPUT: 'Az itt megadott érték érvénytelen:'
MISSING_REQUIRED_FIELD: 'Ez a kötelező mező nincs kitöltve:'
MONTHS_OF_THE_YEAR:
- január
- február
- március
- április
- május
- június
- július
- augusztus
- szeptember
- október
- november
- december
DAYS_OF_THE_WEEK:
- hétfő
- kedd
- szerda
- csütörtök
- péntek
- szombat
- vasárnap

View File

@ -0,0 +1,62 @@
---
FRONTMATTER_ERROR_PAGE: "---Titolo: %1$s---# Errore: Frontmatter non valido: '%2$s' * *%3$s * * ' '%4$s ' '"
NICETIME:
NO_DATE_PROVIDED: Nessuna data fornita
BAD_DATE: Data non valida
AGO: fa
FROM_NOW: da adesso
SECOND: secondo
MINUTE: minuto
HOUR: ora
DAY: giorno
WEEK: settimana
MONTH: mese
YEAR: anno
DECADE: decennio
SEC: sec
MIN: min
HR: ora
WK: settimana
MO: mese
YR: anno
DEC: decennio
SECOND_PLURAL: secondi
MINUTE_PLURAL: minuti
HOUR_PLURAL: ore
DAY_PLURAL: giorni
WEEK_PLURAL: settimane
MONTH_PLURAL: mesi
YEAR_PLURAL: anni
DECADE_PLURAL: decadi
SEC_PLURAL: secondi
MIN_PLURAL: minuti
HR_PLURAL: ore
WK_PLURAL: settimane
MO_PLURAL: mesi
YR_PLURAL: anni
DEC_PLURAL: decenni
FORM:
VALIDATION_FAIL: '<b>Validazione fallita:</b>'
INVALID_INPUT: Input non valido in
MISSING_REQUIRED_FIELD: 'Campo richiesto mancante:'
MONTHS_OF_THE_YEAR:
- Gennaio
- Febbraio
- Marzo
- Aprile
- Maggio
- Giugno
- Luglio
- Agosto
- Settembre
- Ottobre
- Novembre
- Dicembre
DAYS_OF_THE_WEEK:
- Lunedì
- Martedì
- Mercoledì
- Giovedì
- Venerdì
- Sabato
- Domenica

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: []
INFLECTOR_SINGULAR: []
INFLECTOR_UNCOUNTABLE: []
INFLECTOR_IRREGULAR:
'person': 'みんな'
'man': '人'
'child': '子供'
'sex': '性別'
'move': '移動'
INFLECTOR_ORDINALS: []
NICETIME:
NO_DATE_PROVIDED: 日付が設定されていません
BAD_DATE: 不正な日付
AGO:
FROM_NOW: from now
SECOND:
MINUTE:
HOUR:
DAY:
WEEK:
MONTH:
YEAR:
DECADE: 10年
SEC:
MIN:
HR:
DAY:
WK:
MO:
YR:
DEC: dec
SECOND_PLURAL:
MINUTE_PLURAL:
HOUR_PLURAL:
DAY_PLURAL:
WEEK_PLURAL:
MONTH_PLURAL:
YEAR_PLURAL:
DECADE_PLURAL: 10年
SEC_PLURAL:
MIN_PLURAL:
HR_PLURAL:
DAY_PLURAL:
WK_PLURAL:
MO_PLURAL:
YR_PLURAL:
DEC_PLURAL: 10年
FORM:
VALIDATION_FAIL: <b>バリデーション失敗 :</b>
INVALID_INPUT: 不正な入力:
MISSING_REQUIRED_FIELD: 必須項目が入力されていません:
MONTHS_OF_THE_YEAR: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
DAYS_OF_THE_WEEK: ['月', '火', '水', '木', '金', '土', '日']

View File

@ -0,0 +1,69 @@
---
INFLECTOR_UNCOUNTABLE:
2: ryžiai
3: pinigai
4: prieskoniai
5: serijos
6: žuvis
7: avis
INFLECTOR_IRREGULAR:
person: žmonės
man: žmogus
child: vaikai
sex: lytys
move: juda
NICETIME:
NO_DATE_PROVIDED: Nenurodyta data
BAD_DATE: Neteisinga data
AGO: prieš
FROM_NOW: nuo dabar
SECOND: sekundė
MINUTE: minutė
HOUR: valanda
DAY: diena
WEEK: savaitė
MONTH: mėnuo
YEAR: metai
DECADE: dešimtmetis
SEC: sek
MIN: min
HR: val
WK: sav
MO: mėn
YR: m
MINUTE_PLURAL: minutės
HOUR_PLURAL: valandos
DAY_PLURAL: dienos
WEEK_PLURAL: savaitės
MONTH_PLURAL: mėnesiai
YEAR_PLURAL: metai
DECADE_PLURAL: dešimtmečiai
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: val
WK_PLURAL: sav
MO_PLURAL: mėn
YR_PLURAL: m
FORM:
MISSING_REQUIRED_FIELD: 'Būtina užpildyti laukelį:'
MONTHS_OF_THE_YEAR:
- Sausis
- Vasaris
- Kovas
- Balandis
- Gegužė
- Birželis
- Liepa
- Rugpjūtis
- Rugsėjis
- Spalis
- Lakpritis
- Gruodis
DAYS_OF_THE_WEEK:
- Pirmadienis
- Antradienis
- Trečiadienis
- Ketvirtadienis
- Penktadienis
- Šeštadienis
- Sekmadienis

View File

@ -0,0 +1,2 @@
MONTHS_OF_THE_YEAR: ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember']
DAYS_OF_THE_WEEK: ['mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag', 'søndag']

View File

@ -0,0 +1,64 @@
---
INFLECTOR_IRREGULAR:
person: personen
man: mensen
child: kinderen
sex: geslacht
move: verplaatsen
NICETIME:
NO_DATE_PROVIDED: geen datum opgegeven
BAD_DATE: Datumformaat onjuist
AGO: geleden
FROM_NOW: vanaf nu
SECOND: seconde
MINUTE: minuut
HOUR: uur
DAY: dag
WEEK: week
MONTH: maand
YEAR: jaar
DECADE: decenium
SEC: s
MIN: min
HR: u
MO: ma
YR: j
SECOND_PLURAL: seconden
MINUTE_PLURAL: minuten
HOUR_PLURAL: uren
DAY_PLURAL: dagen
WEEK_PLURAL: weken
MONTH_PLURAL: maanden
YEAR_PLURAL: jaren
DECADE_PLURAL: decennia
SEC_PLURAL: seconden
MIN_PLURAL: minuten
HR_PLURAL: uren
WK_PLURAL: weken
MO_PLURAL: maanden
YR_PLURAL: jaren
FORM:
VALIDATION_FAIL: '<b>Validatie mislukt:</b>'
INVALID_INPUT: Ongeldige invoer in
MISSING_REQUIRED_FIELD: 'Verplicht veld ontbreekt:'
MONTHS_OF_THE_YEAR:
- Januari
- Februari
- Maart
- april
- Mei
- Juni
- Juli
- Augustus
- september
- Oktober
- november
- december
DAYS_OF_THE_WEEK:
- Maandag
- Dinsdag
- Woensdag
- Donderdag
- Vrijdag
- Zaterdag
- Zondag

View File

@ -0,0 +1,93 @@
---
FRONTMATTER_ERROR_PAGE: |
---
Tittel: %1$s
---
# Feilmelding: Ugyldig Frontmatter
Pane: '%2$s'
**%3$s **
```
%4$s
```
INFLECTOR_PLURALS:
/(quiz)$/i: '\1zes'
/^(ox)$/i: '\1en'
INFLECTOR_UNCOUNTABLE:
- utstyr
- informasjon
- ris
- penger
- arter
- serier
- fisk
- sau
INFLECTOR_IRREGULAR:
person: folk
man: menn
child: barn
sex: kjønn
move: trekk
NICETIME:
NO_DATE_PROVIDED: Ingen dato gitt
BAD_DATE: Dårlig dato
AGO: siden
FROM_NOW: fra nå
SECOND: sekund
MINUTE: minutt
HOUR: time
DAY: dag
WEEK: uke
MONTH: måned
YEAR: år
DECADE: tiår
SEC: sek
MIN: min
HR: t
WK: uke
MO:
YR: år
DEC: des
SECOND_PLURAL: sekunder
MINUTE_PLURAL: minutter
HOUR_PLURAL: timer
DAY_PLURAL: dager
WEEK_PLURAL: uker
MONTH_PLURAL: måneder
YEAR_PLURAL: år
DECADE_PLURAL: tiår
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: timer
WK_PLURAL: uker
MO_PLURAL: mdr
YR_PLURAL: år
DEC_PLURAL: årtier
FORM:
VALIDATION_FAIL: '<b>Validering mislyktes:</b>'
INVALID_INPUT: Ugyldig innhold i
MISSING_REQUIRED_FIELD: 'Mangler påkrevd felt:'
MONTHS_OF_THE_YEAR:
- januar
- februar
- mars
- april
- mai
- juni
- juli
- august
- september
- oktober
- november
- desember
DAYS_OF_THE_WEEK:
- mandag
- tirsdag
- onsdag
- torsdag
- fredag
- lørdag
- søndag

View File

@ -0,0 +1,75 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Error: Nieprawidłowy Frontmatter
Path: `%2$s`
**%3$s**
```
%4$s
```
NICETIME:
NO_DATE_PROVIDED: Nie podano daty
BAD_DATE: Zła data
AGO: temu
FROM_NOW: od teraz
SECOND: sekunda
MINUTE: minuta
HOUR: godzina
DAY: dzień
WEEK: tydzień
MONTH: miesiąc
YEAR: rok
DECADE: dekada
SEC: sek
MIN: min
HR: godz
WK: tydz
MO: m-c
YR: rok
DEC: dekada
SECOND_PLURAL: sekund
MINUTE_PLURAL: minut
HOUR_PLURAL: godzin
DAY_PLURAL: dni
WEEK_PLURAL: tygodnie
MONTH_PLURAL: miesięcy
YEAR_PLURAL: lat
DECADE_PLURAL: dekad
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: godz
WK_PLURAL: tyg
MO_PLURAL: m-ce
YR_PLURAL: lat
DEC_PLURAL: dekad
FORM:
VALIDATION_FAIL: '<b>Weryfikacja nie powiodła się:</b>'
INVALID_INPUT: Nieprawidłowe dane wejściowe
MISSING_REQUIRED_FIELD: 'Opuszczono wymagane pole:'
MONTHS_OF_THE_YEAR:
- Styczeń
- Luty
- Marzec
- Kwiecień
- Maj
- Czerwiec
- Lipiec
- Sierpień
- Wrzesień
- Październik
- Listopad
- Grudzień
DAYS_OF_THE_WEEK:
- Poniedziałek
- Wtorek
- Środa
- Czwartek
- Piątek
- Sobota
- Niedziela

View File

@ -0,0 +1,79 @@
---
FRONTMATTER_ERROR_PAGE: |
---
título: %1$s
---
# Erro: Frontmatter inválida
Caminho: `%2$s`
**%3$s**
```
%4$s
```
INFLECTOR_UNCOUNTABLE:
1: informação
2: arroz
3: dinheiro
INFLECTOR_IRREGULAR:
man: homens
sex: sexos
NICETIME:
NO_DATE_PROVIDED: Não foi fornecida data
BAD_DATE: Data inválida
AGO: atrás
FROM_NOW: a partir de agora
SECOND: segundo
MINUTE: minuto
HOUR: hora
DAY: dia
WEEK: semana
MONTH: mês
YEAR: ano
DECADE: década
SEC: seg
MIN: mín
HR: h
WK: sem
MO: m
YR: a
DEC: dec
SECOND_PLURAL: segundos
MINUTE_PLURAL: minutos
HOUR_PLURAL: horas
DAY_PLURAL: dias
WEEK_PLURAL: semanas
MONTH_PLURAL: meses
YEAR_PLURAL: anos
DECADE_PLURAL: décadas
SEC_PLURAL: seg
MIN_PLURAL: mins
HR_PLURAL: hrs
WK_PLURAL: sems
YR_PLURAL: anos
FORM:
VALIDATION_FAIL: '<b>Validação falhada: </b>'
MISSING_REQUIRED_FIELD: 'Campo obrigatório ausente:'
MONTHS_OF_THE_YEAR:
- Janeiro
- Fevereiro
- Março
- Abril
- Maio
- Junho
- Julho
- Agosto
- Setembro
- Outubro
- Novembro
- Dezembro
DAYS_OF_THE_WEEK:
- Segunda
- Terça
- Quarta
- Quinta
- Sexta
- Sábado
- Domingo

View File

@ -0,0 +1,101 @@
---
FRONTMATTER_ERROR_PAGE: |
---
Titlu: %1$s
---
# Eroare: Frontmatter este invalid
Calea: `%2$s`
**%3$s**
```
%4$s
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'
INFLECTOR_UNCOUNTABLE:
- echipament
- informaţie
- orez
- bani
- specii
- serii
- peşte
- oaie
INFLECTOR_IRREGULAR:
person: persoane
man: bărbați
child: copii
sex: sexe
move: mutări
NICETIME:
NO_DATE_PROVIDED: Nu există o dată prevăzută
BAD_DATE: Dată incorectă
AGO: în urmă
FROM_NOW: de acum
SECOND: secundă
MINUTE: minut
HOUR: oră
DAY: zi
WEEK: săptămână
MONTH: lună
YEAR: an
DECADE: decadă
SEC: sec
MIN: min
HR: oră
WK: săpt
MO: lună
YR: an
DEC: decadă
SECOND_PLURAL: secunde
MINUTE_PLURAL: minute
HOUR_PLURAL: ore
DAY_PLURAL: zile
WEEK_PLURAL: săptămâni
MONTH_PLURAL: luni
YEAR_PLURAL: ani
DECADE_PLURAL: decade
SEC_PLURAL: sec
MIN_PLURAL: min
HR_PLURAL: ore
WK_PLURAL: săpt
MO_PLURAL: luni
YR_PLURAL: ani
DEC_PLURAL: decenii
FORM:
VALIDATION_FAIL: '<b>Validare nereușită</b>'
INVALID_INPUT: Date incorecte în
MISSING_REQUIRED_FIELD: 'Câmp obligatoriu lipsă:'
MONTHS_OF_THE_YEAR:
- Ianuarie
- Februarie
- Martie
- Aprilie
- Mai
- Iunie
- Iulie
- August
- Septembrie
- Octombrie
- Noiembrie
- Decembrie
DAYS_OF_THE_WEEK:
- Luni
- Marți
- Miercuri
- Joi
- Vineri
- Sâmbătă
- Duminică

View File

@ -0,0 +1,81 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Ошибка: Недопустимое содержимое
Path: `%2$s`
**%3$s**
```
%4$s
```
INFLECTOR_IRREGULAR:
person: люди
man: человек
child: ребенок
sex: пол
move: движется
NICETIME:
NO_DATE_PROVIDED: Дата не указана
BAD_DATE: Неверная дата
AGO: назад
FROM_NOW: теперь
SECOND: секунда
MINUTE: минута
HOUR: час
DAY: д
WEEK: неделя
MONTH: месяц
YEAR: год
DECADE: десятилетие
SEC: с
MIN: мин
HR: ч
WK: нед.
MO: мес.
YR: г.
DEC: гг.
SECOND_PLURAL: секунды
MINUTE_PLURAL: минуты
HOUR_PLURAL: часы
DAY_PLURAL: д
WEEK_PLURAL: недели
MONTH_PLURAL: месяцы
YEAR_PLURAL: годы
DECADE_PLURAL: десятилетия
SEC_PLURAL: с
MIN_PLURAL: мин
HR_PLURAL: ч
WK_PLURAL: нед
MO_PLURAL: мес
YR_PLURAL: г.
DEC_PLURAL: гг.
FORM:
VALIDATION_FAIL: '<b>Проверка не удалась:</b>'
INVALID_INPUT: Неверный ввод в
MISSING_REQUIRED_FIELD: 'Отсутствует необходимое поле:'
MONTHS_OF_THE_YEAR:
- Январь
- Февраль
- Март
- Апрель
- Май
- Июнь
- Июль
- Август
- Сентябрь
- Октябрь
- Ноябрь
- Декабрь
DAYS_OF_THE_WEEK:
- Понедельник
- Вторник
- Среда
- Четверг
- Пятница
- Суббота
- Воскресенье

View File

@ -0,0 +1,42 @@
---
NICETIME:
NO_DATE_PROVIDED: Neposkytnutý žiaden dátum
BAD_DATE: Nesprávny dátum
AGO: pred
FROM_NOW: odteraz
SECOND: sekunda
MINUTE: minúta
HOUR: hodina
DAY: deň
WEEK: týždeň
MONTH: mesiac
YEAR: rok
DECADE: desaťročie
SEC: sek
MIN: min
HR: hod
FORM:
VALIDATION_FAIL: '<b>Overenie zlyhalo:</b>'
INVALID_INPUT: Neplatný vstup v
MISSING_REQUIRED_FIELD: 'Chýba vyžadované pole:'
MONTHS_OF_THE_YEAR:
- Január
- Február
- Marec
- Apríl
- Máj
- Jún
- Júl
- August
- September
- Október
- November
- December
DAYS_OF_THE_WEEK:
- Pondelok
- Utorok
- Streda
- Štvrtok
- Piatok
- Sobota
- Nedeľa

View File

@ -0,0 +1,62 @@
---
FRONTMATTER_ERROR_PAGE: '--- titel: %1$s --- # Fel: Ogiltig Frontmatter-sökväg: `%2$s` **%3$s** ``` %4$s ```'
NICETIME:
NO_DATE_PROVIDED: Inget datum har angivits
BAD_DATE: Ogiltigt datum
AGO: sedan
FROM_NOW: från nu
SECOND: sekund
MINUTE: minut
HOUR: timme
DAY: dag
WEEK: vecka
MONTH: månad
YEAR: år
DECADE: årtionde
SEC: sek
MIN: min
HR: t
WK: v
MO: m
YR: år
DEC: dec
SECOND_PLURAL: sekunder
MINUTE_PLURAL: minuter
HOUR_PLURAL: timmar
DAY_PLURAL: dagar
WEEK_PLURAL: veckor
MONTH_PLURAL: månader
YEAR_PLURAL: år
DECADE_PLURAL: årtionden
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: t
WK_PLURAL: v
MO_PLURAL:
YR_PLURAL: år
DEC_PLURAL: dec
FORM:
VALIDATION_FAIL: '<b>Kontrollen misslyckades:</b>'
INVALID_INPUT: Ogiltig indata i
MISSING_REQUIRED_FIELD: 'Obligatoriskt fält måste fyllas i:'
MONTHS_OF_THE_YEAR:
- Januari
- Februrari
- Mars
- April
- Maj
- Juni
- Juli
- Augusti
- September
- Oktober
- November
- December
DAYS_OF_THE_WEEK:
- Måndag
- Tisdag
- Onsdag
- Torsdag
- Fredag
- Lördag
- Söndag

View File

@ -0,0 +1,75 @@
---
FRONTMATTER_ERROR_PAGE: |
---
ชื่อเรื่อง: %1$s
---
# ข้อผิดพลาด: Invalid Frontmatter
Path: `%2$s`
**%3$s**
```
%4$s
```
NICETIME:
NO_DATE_PROVIDED: ไม่มีวันที่ให้
BAD_DATE: รูปแบบวันที่ผิด
AGO: ที่ผ่านมา
FROM_NOW: จากตอนนี้
SECOND: วินาที
MINUTE: นาที
HOUR: ชั่วโมง
DAY: วัน
WEEK: สัปดาห์
MONTH: เดือน
YEAR: ปี
DECADE: ทศวรรษที่ผ่านมา
SEC: วิ
MIN: นาที
HR: ชม.
WK: wk
MO: mo
YR: yr
DEC: dec
SECOND_PLURAL: วินาที
MINUTE_PLURAL: นาที
HOUR_PLURAL: ชั่วโมง
DAY_PLURAL: วัน
WEEK_PLURAL: สัปดาห์
MONTH_PLURAL: เดือน
YEAR_PLURAL: ปี
DECADE_PLURAL: ทศวรรษที่ผ่านมา
SEC_PLURAL: วินาที
MIN_PLURAL: นาที
HR_PLURAL: ชั่วโมง
WK_PLURAL: wks
MO_PLURAL: mos
YR_PLURAL: ปี
DEC_PLURAL: decs
FORM:
VALIDATION_FAIL: '<b>ตรวจสอบล้มเหลว: </b>'
INVALID_INPUT: ป้อนข้อมูลไม่ถูกต้องใน
MISSING_REQUIRED_FIELD: 'ขาดข้อมูลที่จำเป็น:'
MONTHS_OF_THE_YEAR:
- มกราคม
- กุมภาพันธ์
- มีนาคม
- เมษายน
- พฤษภาคม
- มิถุนายน
- กรกฏาคม
- สิงหาคม
- กันยายน
- ตุลาคม
- พฤศจิกายน
- ธันวาคม
DAYS_OF_THE_WEEK:
- จันทร์
- อังคาร
- พุธ
- พฤหัสบดี
- ศุกร์
- เสาร์
- อาทิตย์

View File

@ -0,0 +1,59 @@
---
NICETIME:
NO_DATE_PROVIDED: Tarih yok
BAD_DATE: Yanlış tarih
AGO: önce
FROM_NOW: (şimdiden)
SECOND: saniye
MINUTE: dakika
HOUR: saat
DAY: gün
WEEK: hafta
MONTH: ay
YEAR: yıl
DECADE: onyıl
SEC: sn
MIN: dk
HR: sa
WK: hft
MO: ay
YR: yl
DEC: onyl
SECOND_PLURAL: saniye
MINUTE_PLURAL: dakika
HOUR_PLURAL: saat
DAY_PLURAL: gün
WEEK_PLURAL: hafta
MONTH_PLURAL: ay
YEAR_PLURAL: yıl
DECADE_PLURAL: onyıl
SEC_PLURAL: sn
MIN_PLURAL: dk
HR_PLURAL: sa
WK_PLURAL: hft
MO_PLURAL: ay
YR_PLURAL: yl
DEC_PLURAL: onyl
FORM:
VALIDATION_FAIL: '<b>Doğrulama başarısız:</b>'
MONTHS_OF_THE_YEAR:
- Ocak
- Şubat
- Mart
- Nisan
- Mayıs
- Haziran
- Temmuz
- Ağustos
- Eylül
- Ekim
- Kasım
- Aralık
DAYS_OF_THE_WEEK:
- Pazartesi
- Salı
- Çarşamba
- Perşembe
- Cuma
- Cumartesi
- Pazar

View File

@ -0,0 +1,75 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Помилка: Недопустимий вміст
Path: `%2$s`
**%3$s**
```
%4$s
```
NICETIME:
NO_DATE_PROVIDED: Не вказана дата
BAD_DATE: Невірна дата
AGO: назад
FROM_NOW: відтепер
SECOND: секунда
MINUTE: хвилина
HOUR: година
DAY: день
WEEK: тиждень
MONTH: місяць
YEAR: рік
DECADE: десятиріччя
SEC: с
MIN: хв
HR: год
WK: тиж.
MO: міс.
YR: р.
DEC: рр.
SECOND_PLURAL: секунди
MINUTE_PLURAL: хвилини
HOUR_PLURAL: години
DAY_PLURAL: дні
WEEK_PLURAL: тижні
MONTH_PLURAL: місяці
YEAR_PLURAL: роки
DECADE_PLURAL: десятиріччя
SEC_PLURAL: с
MIN_PLURAL: хв
HR_PLURAL: год
WK_PLURAL: тиж.
MO_PLURAL: міс.
YR_PLURAL: рр.
DEC_PLURAL: рр.
FORM:
VALIDATION_FAIL: '<b>Перевірка не вдалася:</b>'
INVALID_INPUT: Невірне введення в
MISSING_REQUIRED_FIELD: 'Відсутнє необхідне поле:'
MONTHS_OF_THE_YEAR:
- Січень
- Лютий
- Березень
- Квітень
- Травень
- Червень
- Липень
- Серпень
- Вересень
- Жовтень
- Листопад
- Грудень
DAYS_OF_THE_WEEK:
- Понеділок
- Вівторок
- Середа
- Четвер
- "П'ятниця"
- Субота
- Неділя

View File

@ -0,0 +1,75 @@
---
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Error: Invalid Frontmatter
Path: `%2$s`
**%3$s**
```
%4$s
```
NICETIME:
NO_DATE_PROVIDED: Không có ngày được cung cấp
BAD_DATE: Ngày không hợp lệ
AGO: cách đây
FROM_NOW: từ bây giờ
SECOND: giây
MINUTE: phút
HOUR: giờ
DAY: ngày
WEEK: tuần
MONTH: tháng
YEAR: năm
DECADE: thập kỷ
SEC: giây
MIN: phút
HR: giờ
WK: tuần
MO: tháng
YR: năm
DEC: thập kỷ
SECOND_PLURAL: giây
MINUTE_PLURAL: phút
HOUR_PLURAL: giờ
DAY_PLURAL: ngày
WEEK_PLURAL: tuần
MONTH_PLURAL: tháng
YEAR_PLURAL: năm
DECADE_PLURAL: thập kỷ
SEC_PLURAL: giây
MIN_PLURAL: phút
HR_PLURAL: giờ
WK_PLURAL: tuần
MO_PLURAL: tháng
YR_PLURAL: năm
DEC_PLURAL: thập kỷ
FORM:
VALIDATION_FAIL: '<b>Xác nhận thất bại:</b>'
INVALID_INPUT: Dữ liệu nhập không hợp lệ cho
MISSING_REQUIRED_FIELD: 'Thiếu trường bắt buộc:'
MONTHS_OF_THE_YEAR:
- Tháng 1
- Tháng 2
- Tháng 3
- Tháng 4
- Tháng 5
- Tháng 6
- Tháng 7
- Tháng 8
- Tháng 9
- Tháng 10
- Tháng Mười 11
- Tháng 12
DAYS_OF_THE_WEEK:
- Thứ 2
- Thứ 3
- Thứ 4
- Thứ 5
- Thứ 6
- Thứ 7
- Chủ Nhật

View File

@ -0,0 +1,5 @@
---
title: Not Found
routable: false
notfound: true
---

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,143 @@
<?php
/**
* @package Grav.Common.Backup
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Backup;
use Grav\Common\Grav;
use Grav\Common\Inflector;
class ZipBackup
{
protected static $ignorePaths = [
'backup',
'cache',
'images',
'logs',
'tmp'
];
protected static $ignoreFolders = [
'.git',
'.svn',
'.hg',
'.idea',
'node_modules'
];
/**
* Backup
*
* @param null $destination
* @param callable|null $messager
*
* @return null|string
*/
public static function backup($destination = null, callable $messager = null)
{
if (!$destination) {
$destination = Grav::instance()['locator']->findResource('backup://', true);
if (!$destination) {
throw new \RuntimeException('The backup folder is missing.');
}
}
$name = substr(strip_tags(Grav::instance()['config']->get('site.title', basename(GRAV_ROOT))), 0, 20);
$inflector = new Inflector();
if (is_dir($destination)) {
$date = date('YmdHis', time());
$filename = trim($inflector->hyphenize($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);
$max_execution_time = ini_set('max_execution_time', 600);
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();
if ($max_execution_time !== false) {
ini_set('max_execution_time', $max_execution_time);
}
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

@ -0,0 +1,137 @@
<?php
/**
* @package Grav.Common
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common;
/**
* Internally uses the PhpUserAgent package https://github.com/donatj/PhpUserAgent
*/
class Browser
{
protected $useragent = [];
/**
* Browser constructor.
*/
public function __construct()
{
try {
$this->useragent = parse_user_agent();
} catch (\InvalidArgumentException $e) {
$this->useragent = parse_user_agent("Mozilla/5.0 (compatible; Unknown;)");
}
}
/**
* Get the current browser identifier
*
* Currently detected browsers:
*
* Android Browser
* BlackBerry Browser
* Camino
* Kindle / Silk
* Firefox / Iceweasel
* Safari
* Internet Explorer
* IEMobile
* Chrome
* Opera
* Midori
* Vivaldi
* TizenBrowser
* Lynx
* Wget
* Curl
*
* @return string the lowercase browser name
*/
public function getBrowser()
{
return strtolower($this->useragent['browser']);
}
/**
* Get the current platform identifier
*
* Currently detected platforms:
*
* Desktop
* -> Windows
* -> Linux
* -> Macintosh
* -> Chrome OS
* Mobile
* -> Android
* -> iPhone
* -> iPad / iPod Touch
* -> Windows Phone OS
* -> Kindle
* -> Kindle Fire
* -> BlackBerry
* -> Playbook
* -> Tizen
* Console
* -> Nintendo 3DS
* -> New Nintendo 3DS
* -> Nintendo Wii
* -> Nintendo WiiU
* -> PlayStation 3
* -> PlayStation 4
* -> PlayStation Vita
* -> Xbox 360
* -> Xbox One
*
* @return string the lowercase platform name
*/
public function getPlatform()
{
return strtolower($this->useragent['platform']);
}
/**
* Get the current full version identifier
*
* @return string the browser full version identifier
*/
public function getLongVersion()
{
return $this->useragent['version'];
}
/**
* Get the current major version identifier
*
* @return string the browser major version identifier
*/
public function getVersion()
{
$version = explode('.', $this->getLongVersion());
return intval($version[0]);
}
/**
* Determine if the request comes from a human, or from a bot/crawler
*
* @return bool
*/
public function isHuman()
{
$browser = $this->getBrowser();
if (empty($browser)) {
return false;
}
if (preg_match('~(bot|crawl)~i', $browser)) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,401 @@
<?php
/**
* @package Grav.Common
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common;
use \Doctrine\Common\Cache as DoctrineCache;
use Grav\Common\Config\Config;
use Grav\Common\Filesystem\Folder;
use Grav\Common\Grav;
/**
* The GravCache object is used throughout Grav to store and retrieve cached data.
* It uses DoctrineCache library and supports a variety of caching mechanisms. Those include:
*
* APC
* XCache
* RedisCache
* MemCache
* MemCacheD
* FileSystem
*/
class Cache extends Getters
{
/**
* @var string Cache key.
*/
protected $key;
protected $lifetime;
protected $now;
/** @var Config $config */
protected $config;
/**
* @var DoctrineCache\CacheProvider
*/
protected $driver;
protected $driver_name;
protected $driver_setting;
/**
* @var bool
*/
protected $enabled;
protected $cache_dir;
protected static $standard_remove = [
'cache://twig/',
'cache://doctrine/',
'cache://compiled/',
'cache://validated-',
'cache://images',
'asset://',
];
protected static $all_remove = [
'cache://',
'cache://images',
'asset://',
'tmp://'
];
protected static $assets_remove = [
'asset://'
];
protected static $images_remove = [
'cache://images'
];
protected static $cache_remove = [
'cache://'
];
protected static $tmp_remove = [
'tmp://'
];
/**
* Constructor
*
* @param Grav $grav
*/
public function __construct(Grav $grav)
{
$this->init($grav);
}
/**
* Initialization that sets a base key and the driver based on configuration settings
*
* @param Grav $grav
*
* @return void
*/
public function init(Grav $grav)
{
/** @var Config $config */
$this->config = $grav['config'];
$this->now = time();
$this->cache_dir = $grav['locator']->findResource('cache://doctrine', true, true);
/** @var Uri $uri */
$uri = $grav['uri'];
$prefix = $this->config->get('system.cache.prefix');
$this->enabled = (bool)$this->config->get('system.cache.enabled');
// Cache key allows us to invalidate all cache on configuration changes.
$this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION),
2, 8);
$this->driver_setting = $this->config->get('system.cache.driver');
$this->driver = $this->getCacheDriver();
// Set the cache namespace to our unique key
$this->driver->setNamespace($this->key);
// Dump Cache state
$grav['debugger']->addMessage('Cache: [' . ($this->enabled ? 'true' : 'false') . '] Setting: [' . $this->driver_setting . '] Driver: [' . $this->driver_name . ']');
}
/**
* Automatically picks the cache mechanism to use. If you pick one manually it will use that
* If there is no config option for $driver in the config, or it's set to 'auto', it will
* pick the best option based on which cache extensions are installed.
*
* @return DoctrineCache\CacheProvider The cache driver to use
*/
public function getCacheDriver()
{
$setting = $this->driver_setting;
$driver_name = 'file';
if (!$setting || $setting == 'auto') {
if (extension_loaded('apcu')) {
$driver_name = 'apcu';
} elseif (extension_loaded('apc')) {
$driver_name = 'apc';
} elseif (extension_loaded('wincache')) {
$driver_name = 'wincache';
} elseif (extension_loaded('xcache')) {
$driver_name = 'xcache';
}
} else {
$driver_name = $setting;
}
$this->driver_name = $driver_name;
switch ($driver_name) {
case 'apc':
$driver = new DoctrineCache\ApcCache();
break;
case 'apcu':
$driver = new DoctrineCache\ApcuCache();
break;
case 'wincache':
$driver = new DoctrineCache\WinCacheCache();
break;
case 'xcache':
$driver = new DoctrineCache\XcacheCache();
break;
case 'memcache':
$memcache = new \Memcache();
$memcache->connect($this->config->get('system.cache.memcache.server', 'localhost'),
$this->config->get('system.cache.memcache.port', 11211));
$driver = new DoctrineCache\MemcacheCache();
$driver->setMemcache($memcache);
break;
case 'memcached':
$memcached = new \Memcached();
$memcached->addServer($this->config->get('system.cache.memcached.server', 'localhost'),
$this->config->get('system.cache.memcached.port', 11211));
$driver = new DoctrineCache\MemcachedCache();
$driver->setMemcached($memcached);
break;
case 'redis':
$redis = new \Redis();
$redis->connect($this->config->get('system.cache.redis.server', 'localhost'),
$this->config->get('system.cache.redis.port', 6379));
$driver = new DoctrineCache\RedisCache();
$driver->setRedis($redis);
break;
default:
$driver = new DoctrineCache\FilesystemCache($this->cache_dir);
break;
}
return $driver;
}
/**
* Gets a cached entry if it exists based on an id. If it does not exist, it returns false
*
* @param string $id the id of the cached entry
*
* @return object returns the cached entry, can be any type, or false if doesn't exist
*/
public function fetch($id)
{
if ($this->enabled) {
return $this->driver->fetch($id);
} else {
return false;
}
}
/**
* Stores a new cached entry.
*
* @param string $id the id of the cached entry
* @param array|object $data the data for the cached entry to store
* @param int $lifetime the lifetime to store the entry in seconds
*/
public function save($id, $data, $lifetime = null)
{
if ($this->enabled) {
if ($lifetime === null) {
$lifetime = $this->getLifetime();
}
$this->driver->save($id, $data, $lifetime);
}
}
/**
* Deletes an item in the cache based on the id
*
* @param string $id the id of the cached data entry
* @return bool true if the item was deleted successfully
*/
public function delete($id)
{
if ($this->enabled) {
return $this->driver->delete($id);
}
return false;
}
/**
* Returns a boolean state of whether or not the item exists in the cache based on id key
*
* @param string $id the id of the cached data entry
* @return bool true if the cached items exists
*/
public function contains($id)
{
if ($this->enabled) {
return $this->driver->contains(($id));
}
return false;
}
/**
* Getter method to get the cache key
*/
public function getKey()
{
return $this->key;
}
/**
* Setter method to set key (Advanced)
*/
public function setKey($key)
{
$this->key = $key;
$this->driver->setNamespace($this->key);
}
/**
* Helper method to clear all Grav caches
*
* @param string $remove standard|all|assets-only|images-only|cache-only
*
* @return array
*/
public static function clearCache($remove = 'standard')
{
$locator = Grav::instance()['locator'];
$output = [];
$user_config = USER_DIR . 'config/system.yaml';
switch ($remove) {
case 'all':
$remove_paths = self::$all_remove;
break;
case 'assets-only':
$remove_paths = self::$assets_remove;
break;
case 'images-only':
$remove_paths = self::$images_remove;
break;
case 'cache-only':
$remove_paths = self::$cache_remove;
break;
case 'tmp-only':
$remove_paths = self::$tmp_remove;
break;
default:
$remove_paths = self::$standard_remove;
}
foreach ($remove_paths as $stream) {
// Convert stream to a real path
try {
$path = $locator->findResource($stream, true, true);
} catch (\Exception $e) {
// stream not found..
continue;
}
$anything = false;
$files = glob($path . '/*');
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 . '/*';
}
}
$output[] = '';
if (($remove == 'all' || $remove == 'standard') && file_exists($user_config)) {
touch($user_config);
$output[] = '<red>Touched: </red>' . $user_config;
$output[] = '';
}
return $output;
}
/**
* Set the cache lifetime programmatically
*
* @param int $future timestamp
*/
public function setLifetime($future)
{
if (!$future) {
return;
}
$interval = $future - $this->now;
if ($interval > 0 && $interval < $this->getLifetime()) {
$this->lifetime = $interval;
}
}
/**
* Retrieve the cache lifetime (in seconds)
*
* @return mixed
*/
public function getLifetime()
{
if ($this->lifetime === null) {
$this->lifetime = $this->config->get('system.cache.lifetime') ?: 604800; // 1 week default
}
return $this->lifetime;
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* @package Grav.Common
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common;
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;
}
/**
* Return the composer executable file path
*
* @return string
*/
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

@ -0,0 +1,247 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use RocketTheme\Toolbox\File\PhpFile;
abstract class CompiledBase
{
/**
* @var int Version number for the compiled file.
*/
public $version = 1;
/**
* @var string Filename (base name) of the compiled configuration.
*/
public $name;
/**
* @var string|bool Configuration checksum.
*/
public $checksum;
/**
* @var string Cache folder to be used.
*/
protected $cacheFolder;
/**
* @var array List of files to load.
*/
protected $files;
/**
* @var string
*/
protected $path;
/**
* @var mixed Configuration object.
*/
protected $object;
/**
* @param string $cacheFolder Cache folder to be used.
* @param array $files List of files as returned from ConfigFileFinder class.
* @param string $path Base path for the file list.
* @throws \BadMethodCallException
*/
public function __construct($cacheFolder, array $files, $path)
{
if (!$cacheFolder) {
throw new \BadMethodCallException('Cache folder not defined.');
}
$this->cacheFolder = $cacheFolder;
$this->files = $files;
$this->path = $path ? rtrim($path, '\\/') . '/' : '';
}
/**
* Get filename for the compiled PHP file.
*
* @param string $name
* @return $this
*/
public function name($name = null)
{
if (!$this->name) {
$this->name = $name ?: md5(json_encode(array_keys($this->files)));
}
return $this;
}
/**
* Function gets called when cached configuration is saved.
*/
public function modified() {}
/**
* Load the configuration.
*
* @return mixed
*/
public function load()
{
if ($this->object) {
return $this->object;
}
$filename = $this->createFilename();
if (!$this->loadCompiledFile($filename) && $this->loadFiles()) {
$this->saveCompiledFile($filename);
}
return $this->object;
}
/**
* Returns checksum from the configuration files.
*
* You can set $this->checksum = false to disable this check.
*
* @return bool|string
*/
public function checksum()
{
if (!isset($this->checksum)) {
$this->checksum = md5(json_encode($this->files) . $this->version);
}
return $this->checksum;
}
protected function createFilename()
{
return "{$this->cacheFolder}/{$this->name()->name}.php";
}
/**
* Create configuration object.
*
* @param array $data
*/
abstract protected function createObject(array $data = []);
/**
* Finalize configuration object.
*/
abstract protected function finalizeObject();
/**
* Load single configuration file and append it to the correct position.
*
* @param string $name Name of the position.
* @param string $filename File to be loaded.
*/
abstract protected function loadFile($name, $filename);
/**
* Load and join all configuration files.
*
* @return bool
* @internal
*/
protected function loadFiles()
{
$this->createObject();
$list = array_reverse($this->files);
foreach ($list as $files) {
foreach ($files as $name => $item) {
$this->loadFile($name, $this->path . $item['file']);
}
}
$this->finalizeObject();
return true;
}
/**
* Load compiled file.
*
* @param string $filename
* @return bool
* @internal
*/
protected function loadCompiledFile($filename)
{
if (!file_exists($filename)) {
return false;
}
$cache = include $filename;
if (
!is_array($cache)
|| !isset($cache['checksum'])
|| !isset($cache['data'])
|| !isset($cache['@class'])
|| $cache['@class'] != get_class($this)
) {
return false;
}
// Load real file if cache isn't up to date (or is invalid).
if ($cache['checksum'] !== $this->checksum()) {
return false;
}
$this->createObject($cache['data']);
$this->finalizeObject();
return true;
}
/**
* Save compiled file.
*
* @param string $filename
* @throws \RuntimeException
* @internal
*/
protected function saveCompiledFile($filename)
{
$file = PhpFile::instance($filename);
// Attempt to lock the file for writing.
try {
$file->lock(false);
} catch (\Exception $e) {
// Another process has locked the file; we will check this in a bit.
}
if ($file->locked() === false) {
// File was already locked by another process.
return;
}
$cache = [
'@class' => get_class($this),
'timestamp' => time(),
'checksum' => $this->checksum(),
'files' => $this->files,
'data' => $this->getState()
];
$file->save($cache);
$file->unlock();
$file->free();
$this->modified();
}
protected function getState()
{
return $this->object->toArray();
}
}

View File

@ -0,0 +1,115 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use Grav\Common\Data\Blueprint;
use Grav\Common\Data\BlueprintSchema;
use Grav\Common\Grav;
class CompiledBlueprints extends CompiledBase
{
/**
* @var int Version number for the compiled file.
*/
public $version = 2;
/**
* @var BlueprintSchema Blueprints object.
*/
protected $object;
/**
* Returns checksum from the configuration files.
*
* You can set $this->checksum = false to disable this check.
*
* @return bool|string
*/
public function checksum()
{
if (!isset($this->checksum)) {
$this->checksum = md5(json_encode($this->files) . json_encode($this->getTypes()) . $this->version);
}
return $this->checksum;
}
/**
* Create configuration object.
*
* @param array $data
*/
protected function createObject(array $data = [])
{
$this->object = (new BlueprintSchema($data))->setTypes($this->getTypes());
}
/**
* Get list of form field types.
*
* @return array
*/
protected function getTypes()
{
return Grav::instance()['plugins']->formFieldTypes ?: [];
}
/**
* Finalize configuration object.
*/
protected function finalizeObject()
{
}
/**
* Load single configuration file and append it to the correct position.
*
* @param string $name Name of the position.
* @param array $files Files to be loaded.
*/
protected function loadFile($name, $files)
{
// Load blueprint file.
$blueprint = new Blueprint($files);
$this->object->embed($name, $blueprint->load()->toArray(), '/', true);
}
/**
* Load and join all configuration files.
*
* @return bool
* @internal
*/
protected function loadFiles()
{
$this->createObject();
// Convert file list into parent list.
$list = [];
foreach ($this->files as $files) {
foreach ($files as $name => $item) {
$list[$name][] = $this->path . $item['file'];
}
}
// Load files.
foreach ($list as $name => $files) {
$this->loadFile($name, $files);
}
$this->finalizeObject();
return true;
}
protected function getState()
{
return $this->object->getState();
}
}

View File

@ -0,0 +1,102 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use Grav\Common\File\CompiledYamlFile;
class CompiledConfig extends CompiledBase
{
/**
* @var int Version number for the compiled file.
*/
public $version = 1;
/**
* @var Config Configuration object.
*/
protected $object;
/**
* @var callable Blueprints loader.
*/
protected $callable;
/**
* @var bool
*/
protected $withDefaults;
/**
* Set blueprints for the configuration.
*
* @param callable $blueprints
* @return $this
*/
public function setBlueprints(callable $blueprints)
{
$this->callable = $blueprints;
return $this;
}
/**
* @param bool $withDefaults
* @return mixed
*/
public function load($withDefaults = false)
{
$this->withDefaults = $withDefaults;
return parent::load();
}
/**
* Create configuration object.
*
* @param array $data
*/
protected function createObject(array $data = [])
{
if ($this->withDefaults && empty($data) && is_callable($this->callable)) {
$blueprints = $this->callable;
$data = $blueprints()->getDefaults();
}
$this->object = new Config($data, $this->callable);
}
/**
* Finalize configuration object.
*/
protected function finalizeObject()
{
$this->object->checksum($this->checksum());
}
/**
* Function gets called when cached configuration is saved.
*/
public function modified()
{
$this->object->modified(true);
}
/**
* Load single configuration file and append it to the correct position.
*
* @param string $name Name of the position.
* @param string $filename File to be loaded.
*/
protected function loadFile($name, $filename)
{
$file = CompiledYamlFile::instance($filename);
$this->object->join($name, $file->content(), '/');
$file->free();
}
}

View File

@ -0,0 +1,68 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use Grav\Common\File\CompiledYamlFile;
class CompiledLanguages extends CompiledBase
{
/**
* @var int Version number for the compiled file.
*/
public $version = 1;
/**
* @var Languages Configuration object.
*/
protected $object;
/**
* Create configuration object.
*
* @param array $data
*/
protected function createObject(array $data = [])
{
$this->object = new Languages($data);
}
/**
* Finalize configuration object.
*/
protected function finalizeObject()
{
$this->object->checksum($this->checksum());
}
/**
* Function gets called when cached configuration is saved.
*/
public function modified()
{
$this->object->modified(true);
}
/**
* Load single configuration file and append it to the correct position.
*
* @param string $name Name of the position.
* @param string $filename File to be loaded.
*/
protected function loadFile($name, $filename)
{
$file = CompiledYamlFile::instance($filename);
if (preg_match('|languages\.yaml$|', $filename)) {
$this->object->mergeRecursive($file->content());
} else {
$this->object->join($name, $file->content(), '/');
}
$file->free();
}
}

View File

@ -0,0 +1,98 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use Grav\Common\Debugger;
use Grav\Common\Grav;
use Grav\Common\Data\Data;
use Grav\Common\Service\ConfigServiceProvider;
class Config extends Data
{
protected $checksum;
protected $modified = false;
public function key()
{
return $this->checksum();
}
public function checksum($checksum = null)
{
if ($checksum !== null) {
$this->checksum = $checksum;
}
return $this->checksum;
}
public function modified($modified = null)
{
if ($modified !== null) {
$this->modified = $modified;
}
return $this->modified;
}
public function reload()
{
$grav = Grav::instance();
// Load new configuration.
$config = ConfigServiceProvider::load($grav);
/** @var Debugger $debugger */
$debugger = $grav['debugger'];
if ($config->modified()) {
// Update current configuration.
$this->items = $config->toArray();
$this->checksum($config->checksum());
$this->modified(true);
$debugger->addMessage('Configuration was changed and saved.');
}
return $this;
}
public function debug()
{
/** @var Debugger $debugger */
$debugger = Grav::instance()['debugger'];
$debugger->addMessage('Environment Name: ' . $this->environment);
if ($this->modified()) {
$debugger->addMessage('Configuration reloaded and cached.');
}
}
public function init()
{
$setup = Grav::instance()['setup']->toArray();
foreach ($setup as $key => $value) {
if ($key === 'streams' || !is_array($value)) {
// Optimized as streams and simple values are fully defined in setup.
$this->items[$key] = $value;
} else {
$this->joinDefaults($key, $value);
}
}
}
/**
* @return mixed
* @deprecated
*/
public function getLanguages()
{
return Grav::instance()['languages'];
}
}

View File

@ -0,0 +1,262 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use Grav\Common\Filesystem\Folder;
class ConfigFileFinder
{
protected $base = '';
/**
* @param string $base
* @return $this
*/
public function setBase($base)
{
$this->base = $base ? "{$base}/" : '';
return $this;
}
/**
* Return all locations for all the files with a timestamp.
*
* @param array $paths List of folders to look from.
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
*/
public function locateFiles(array $paths, $pattern = '|\.yaml$|', $levels = -1)
{
$list = [];
foreach ($paths as $folder) {
$list += $this->detectRecursive($folder, $pattern, $levels);
}
return $list;
}
/**
* Return all locations for all the files with a timestamp.
*
* @param array $paths List of folders to look from.
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
*/
public function getFiles(array $paths, $pattern = '|\.yaml$|', $levels = -1)
{
$list = [];
foreach ($paths as $folder) {
$path = trim(Folder::getRelativePath($folder), '/');
$files = $this->detectRecursive($folder, $pattern, $levels);
$list += $files[trim($path, '/')];
}
return $list;
}
/**
* Return all paths for all the files with a timestamp.
*
* @param array $paths List of folders to look from.
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
*/
public function listFiles(array $paths, $pattern = '|\.yaml$|', $levels = -1)
{
$list = [];
foreach ($paths as $folder) {
$list = array_merge_recursive($list, $this->detectAll($folder, $pattern, $levels));
}
return $list;
}
/**
* Find filename from a list of folders.
*
* Note: Only finds the last override.
*
* @param string $filename
* @param array $folders
* @return array
*/
public function locateFileInFolder($filename, array $folders)
{
$list = [];
foreach ($folders as $folder) {
$list += $this->detectInFolder($folder, $filename);
}
return $list;
}
/**
* Find filename from a list of folders.
*
* @param array $folders
* @param string $filename
* @return array
*/
public function locateInFolders(array $folders, $filename = null)
{
$list = [];
foreach ($folders as $folder) {
$path = trim(Folder::getRelativePath($folder), '/');
$list[$path] = $this->detectInFolder($folder, $filename);
}
return $list;
}
/**
* Return all existing locations for a single file with a timestamp.
*
* @param array $paths Filesystem paths to look up from.
* @param string $name Configuration file to be located.
* @param string $ext File extension (optional, defaults to .yaml).
* @return array
*/
public function locateFile(array $paths, $name, $ext = '.yaml')
{
$filename = preg_replace('|[.\/]+|', '/', $name) . $ext;
$list = [];
foreach ($paths as $folder) {
$path = trim(Folder::getRelativePath($folder), '/');
if (is_file("{$folder}/{$filename}")) {
$modified = filemtime("{$folder}/{$filename}");
} else {
$modified = 0;
}
$basename = $this->base . $name;
$list[$path] = [$basename => ['file' => "{$path}/{$filename}", 'modified' => $modified]];
}
return $list;
}
/**
* Detects all directories with a configuration file and returns them with last modification time.
*
* @param string $folder Location to look up from.
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
* @internal
*/
protected function detectRecursive($folder, $pattern, $levels)
{
$path = trim(Folder::getRelativePath($folder), '/');
if (is_dir($folder)) {
// Find all system and user configuration files.
$options = [
'levels' => $levels,
'compare' => 'Filename',
'pattern' => $pattern,
'filters' => [
'pre-key' => $this->base,
'key' => $pattern,
'value' => function (\RecursiveDirectoryIterator $file) use ($path) {
return ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()];
}
],
'key' => 'SubPathname'
];
$list = Folder::all($folder, $options);
ksort($list);
} else {
$list = [];
}
return [$path => $list];
}
/**
* Detects all directories with the lookup file and returns them with last modification time.
*
* @param string $folder Location to look up from.
* @param string $lookup Filename to be located (defaults to directory name).
* @return array
* @internal
*/
protected function detectInFolder($folder, $lookup = null)
{
$folder = rtrim($folder, '/');
$path = trim(Folder::getRelativePath($folder), '/');
$base = $path === $folder ? '' : ($path ? substr($folder, 0, -strlen($path)) : $folder . '/');
$list = [];
if (is_dir($folder)) {
$iterator = new \DirectoryIterator($folder);
/** @var \DirectoryIterator $directory */
foreach ($iterator as $directory) {
if (!$directory->isDir() || $directory->isDot()) {
continue;
}
$name = $directory->getBasename();
$find = ($lookup ?: $name) . '.yaml';
$filename = "{$path}/{$name}/{$find}";
if (file_exists($base . $filename)) {
$basename = $this->base . $name;
$list[$basename] = ['file' => $filename, 'modified' => filemtime($base . $filename)];
}
}
}
return $list;
}
/**
* Detects all plugins with a configuration file and returns them with last modification time.
*
* @param string $folder Location to look up from.
* @param string $pattern Pattern to match the file. Pattern will also be removed from the key.
* @param int $levels Maximum number of recursive directories.
* @return array
* @internal
*/
protected function detectAll($folder, $pattern, $levels)
{
$path = trim(Folder::getRelativePath($folder), '/');
if (is_dir($folder)) {
// Find all system and user configuration files.
$options = [
'levels' => $levels,
'compare' => 'Filename',
'pattern' => $pattern,
'filters' => [
'pre-key' => $this->base,
'key' => $pattern,
'value' => function (\RecursiveDirectoryIterator $file) use ($path) {
return ["{$path}/{$file->getSubPathname()}" => $file->getMTime()];
}
],
'key' => 'SubPathname'
];
$list = Folder::all($folder, $options);
ksort($list);
} else {
$list = [];
}
return $list;
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use Grav\Common\Data\Data;
class Languages extends Data
{
public function checksum($checksum = null)
{
if ($checksum !== null) {
$this->checksum = $checksum;
}
return $this->checksum;
}
public function modified($modified = null)
{
if ($modified !== null) {
$this->modified = $modified;
}
return $this->modified;
}
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

@ -0,0 +1,273 @@
<?php
/**
* @package Grav.Common.Config
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Config;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Data\Data;
use Grav\Common\Utils;
use Pimple\Container;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Setup extends Data
{
public static $environment;
protected $streams = [
'system' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['system'],
]
],
'user' => [
'type' => 'ReadOnlyStream',
'force' => true,
'prefixes' => [
'' => ['user'],
]
],
'environment' => [
'type' => 'ReadOnlyStream'
// If not defined, environment will be set up in the constructor.
],
'asset' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['assets'],
]
],
'blueprints' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['environment://blueprints', 'user://blueprints', 'system/blueprints'],
]
],
'config' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['environment://config', 'user://config', 'system/config'],
]
],
'plugins' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://plugins'],
]
],
'plugin' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://plugins'],
]
],
'themes' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://themes'],
]
],
'languages' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['environment://languages', 'user://languages', 'system/languages'],
]
],
'cache' => [
'type' => 'Stream',
'force' => true,
'prefixes' => [
'' => ['cache'],
'images' => ['images']
]
],
'log' => [
'type' => 'Stream',
'force' => true,
'prefixes' => [
'' => ['logs']
]
],
'backup' => [
'type' => 'Stream',
'force' => true,
'prefixes' => [
'' => ['backup']
]
],
'tmp' => [
'type' => 'Stream',
'force' => true,
'prefixes' => [
'' => ['tmp']
]
],
'image' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://images', 'system://images']
]
],
'page' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://pages']
]
],
'account' => [
'type' => 'ReadOnlyStream',
'prefixes' => [
'' => ['user://accounts']
]
],
];
/**
* @param Container|array $container
*/
public function __construct($container)
{
$environment = static::$environment ?: ($container['uri']->environment() ?: 'localhost');
// Pre-load setup.php which contains our initial configuration.
// Configuration may contain dynamic parts, which is why we need to always load it.
$file = GRAV_ROOT . '/setup.php';
$setup = is_file($file) ? (array) include $file : [];
// Add default streams defined in beginning of the class.
if (!isset($setup['streams']['schemes'])) {
$setup['streams']['schemes'] = [];
}
$setup['streams']['schemes'] += $this->streams;
// Initialize class.
parent::__construct($setup);
// Set up environment.
$this->def('environment', $environment);
$this->def('streams.schemes.environment.prefixes', ['' => ["user://{$this->environment}"]]);
}
/**
* @return $this
*/
public function init()
{
$locator = new UniformResourceLocator(GRAV_ROOT);
$files = [];
$guard = 5;
do {
$check = $files;
$this->initializeLocator($locator);
$files = $locator->findResources('config://streams.yaml');
if ($check === $files) {
break;
}
// Update streams.
foreach (array_reverse($files) as $path) {
$file = CompiledYamlFile::instance($path);
$content = $file->content();
if (!empty($content['schemes'])) {
$this->items['streams']['schemes'] = $content['schemes'] + $this->items['streams']['schemes'];
}
}
} while (--$guard);
if (!$guard) {
throw new \RuntimeException('Setup: Configuration reload loop detected!');
}
// Make sure we have valid setup.
$this->check($locator);
return $this;
}
/**
* 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']);
}
$override = isset($config['override']) ? $config['override'] : false;
$force = isset($config['force']) ? $config['force'] : false;
if (isset($config['prefixes'])) {
foreach ($config['prefixes'] as $prefix => $paths) {
$locator->addPath($scheme, $prefix, $paths, $override, $force);
}
}
}
}
/**
* 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;
}
/**
* @param UniformResourceLocator $locator
* @throws \InvalidArgumentException
*/
protected function check(UniformResourceLocator $locator)
{
$streams = isset($this->items['streams']['schemes']) ? $this->items['streams']['schemes'] : null;
if (!is_array($streams)) {
throw new \InvalidArgumentException('Configuration is missing streams.schemes!');
}
$diff = array_keys(array_diff_key($this->streams, $streams));
if ($diff) {
throw new \InvalidArgumentException(
sprintf('Configuration is missing keys %s from streams.schemes!', implode(', ', $diff))
);
}
if (!$locator->findResource('environment://config', true)) {
// If environment does not have its own directory, remove it from the lookup.
$this->set('streams.schemes.environment.prefixes', ['config' => []]);
$this->initializeLocator($locator);
}
// Create security.yaml if it doesn't exist.
$filename = $locator->findResource('config://security.yaml', true, true);
$file = YamlFile::instance($filename);
if (!$file->exists()) {
$file->save(['salt' => Utils::generateRandomString(14)]);
$file->free();
}
}
}

View File

@ -0,0 +1,254 @@
<?php
/**
* @package Grav.Common.Data
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Data;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Grav;
use RocketTheme\Toolbox\Blueprints\BlueprintForm;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Blueprint extends BlueprintForm
{
/**
* @var string
*/
protected $context = 'blueprints://';
/**
* @var BlueprintSchema
*/
protected $blueprintSchema;
/**
* Set default values for field types.
*
* @param array $types
* @return $this
*/
public function setTypes(array $types)
{
$this->initInternals();
$this->blueprintSchema->setTypes($types);
return $this;
}
/**
* Get nested structure containing default values defined in the blueprints.
*
* Fields without default value are ignored in the list.
*
* @return array
*/
public function getDefaults()
{
$this->initInternals();
return $this->blueprintSchema->getDefaults();
}
/**
* Merge two arrays by using blueprints.
*
* @param array $data1
* @param array $data2
* @param string $name Optional
* @param string $separator Optional
* @return array
*/
public function mergeData(array $data1, array $data2, $name = null, $separator = '.')
{
$this->initInternals();
return $this->blueprintSchema->mergeData($data1, $data2, $name, $separator);
}
/**
* Return data fields that do not exist in blueprints.
*
* @param array $data
* @param string $prefix
* @return array
*/
public function extra(array $data, $prefix = '')
{
$this->initInternals();
return $this->blueprintSchema->extra($data, $prefix);
}
/**
* Validate data against blueprints.
*
* @param array $data
* @throws \RuntimeException
*/
public function validate(array $data)
{
$this->initInternals();
$this->blueprintSchema->validate($data);
}
/**
* Filter data by using blueprints.
*
* @param array $data
* @return array
*/
public function filter(array $data)
{
$this->initInternals();
return $this->blueprintSchema->filter($data);
}
/**
* Return blueprint data schema.
*
* @return BlueprintSchema
*/
public function schema()
{
$this->initInternals();
return $this->blueprintSchema;
}
/**
* Initialize validator.
*/
protected function initInternals()
{
if (!isset($this->blueprintSchema)) {
$types = Grav::instance()['plugins']->formFieldTypes;
$this->blueprintSchema = new BlueprintSchema;
if ($types) {
$this->blueprintSchema->setTypes($types);
}
$this->blueprintSchema->embed('', $this->items);
$this->blueprintSchema->init();
}
}
/**
* @param string $filename
* @return string
*/
protected function loadFile($filename)
{
$file = CompiledYamlFile::instance($filename);
$content = $file->content();
$file->free();
return $content;
}
/**
* @param string|array $path
* @param string $context
* @return array
*/
protected function getFiles($path, $context = null)
{
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if (is_string($path) && !$locator->isStream($path)) {
// Find path overrides.
$paths = isset($this->overrides[$path]) ? (array) $this->overrides[$path] : [];
// Add path pointing to default context.
if ($context === null) {
$context = $this->context;
}
if ($context && $context[strlen($context)-1] !== '/') {
$context .= '/';
}
$path = $context . $path;
if (!preg_match('/\.yaml$/', $path)) {
$path .= '.yaml';
}
$paths[] = $path;
} else {
$paths = (array) $path;
}
$files = [];
foreach ($paths as $lookup) {
if (is_string($lookup) && strpos($lookup, '://')) {
$files = array_merge($files, $locator->findResources($lookup));
} else {
$files[] = $lookup;
}
}
return array_values(array_unique($files));
}
/**
* @param array $field
* @param string $property
* @param array $call
*/
protected function dynamicData(array &$field, $property, array &$call)
{
$params = $call['params'];
if (is_array($params)) {
$function = array_shift($params);
} else {
$function = $params;
$params = [];
}
list($o, $f) = preg_split('/::/', $function, 2);
if (!$f) {
if (function_exists($o)) {
$data = call_user_func_array($o, $params);
}
} else {
if (method_exists($o, $f)) {
$data = call_user_func_array(array($o, $f), $params);
}
}
// If function returns a value,
if (isset($data)) {
if (isset($field[$property]) && is_array($field[$property]) && is_array($data)) {
// Combine field and @data-field together.
$field[$property] += $data;
} else {
// Or create/replace field with @data-field.
$field[$property] = $data;
}
}
}
/**
* @param array $field
* @param string $property
* @param array $call
*/
protected function dynamicConfig(array &$field, $property, array &$call)
{
$value = $call['params'];
$default = isset($field[$property]) ? $field[$property] : null;
$config = Grav::instance()['config']->get($value, $default);
if (!is_null($config)) {
$field[$property] = $config;
}
}
}

View File

@ -0,0 +1,171 @@
<?php
/**
* @package Grav.Common.Data
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Data;
use Grav\Common\Grav;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
use RocketTheme\Toolbox\Blueprints\BlueprintSchema as BlueprintSchemaBase;
class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
{
use Export;
protected $ignoreFormKeys = [
'title' => true,
'help' => true,
'placeholder' => true,
'placeholder_key' => true,
'placeholder_value' => true,
'fields' => true
];
/**
* Validate data against blueprints.
*
* @param array $data
* @throws \RuntimeException
*/
public function validate(array $data)
{
try {
$messages = $this->validateArray($data, $this->nested);
} catch (\RuntimeException $e) {
throw (new ValidationException($e->getMessage(), $e->getCode(), $e))->setMessages();
}
if (!empty($messages)) {
throw (new ValidationException())->setMessages($messages);
}
}
/**
* Filter data by using blueprints.
*
* @param array $data
* @return array
*/
public function filter(array $data)
{
return $this->filterArray($data, $this->nested);
}
/**
* @param array $data
* @param array $rules
* @returns array
* @throws \RuntimeException
* @internal
*/
protected function validateArray(array $data, array $rules)
{
$messages = $this->checkRequired($data, $rules);
foreach ($data as $key => $field) {
$val = isset($rules[$key]) ? $rules[$key] : (isset($rules['*']) ? $rules['*'] : null);
$rule = is_string($val) ? $this->items[$val] : null;
if ($rule) {
// Item has been defined in blueprints.
$messages += Validation::validate($field, $rule);
} elseif (is_array($field) && is_array($val)) {
// Array has been defined in blueprints.
$messages += $this->validateArray($field, $val);
} elseif (isset($rules['validation']) && $rules['validation'] == 'strict') {
// Undefined/extra item.
throw new \RuntimeException(sprintf('%s is not defined in blueprints', $key));
}
}
return $messages;
}
/**
* @param array $data
* @param array $rules
* @return array
* @internal
*/
protected function filterArray(array $data, array $rules)
{
$results = array();
foreach ($data as $key => $field) {
$val = isset($rules[$key]) ? $rules[$key] : (isset($rules['*']) ? $rules['*'] : null);
$rule = is_string($val) ? $this->items[$val] : null;
if ($rule) {
// Item has been defined in blueprints.
$field = Validation::filter($field, $rule);
} elseif (is_array($field) && is_array($val)) {
// Array has been defined in blueprints.
$field = $this->filterArray($field, $val);
} elseif (isset($rules['validation']) && $rules['validation'] == 'strict') {
$field = null;
}
if (isset($field) && (!is_array($field) || !empty($field))) {
$results[$key] = $field;
}
}
return $results;
}
/**
* @param array $data
* @param array $fields
* @return array
*/
protected function checkRequired(array $data, array $fields)
{
$messages = [];
foreach ($fields as $name => $field) {
if (!is_string($field)) {
continue;
}
$field = $this->items[$field];
if (isset($field['validate']['required'])
&& $field['validate']['required'] === true) {
if (isset($data[$name])) {
continue;
}
if ($field['type'] == 'file' && isset($data['data']['name'][$name])) { //handle case of file input fields required
continue;
}
$value = isset($field['label']) ? $field['label'] : $field['name'];
$language = Grav::instance()['language'];
$message = sprintf($language->translate('FORM.MISSING_REQUIRED_FIELD', null, true) . ' %s', $language->translate($value));
$messages[$field['name']][] = $message;
}
}
return $messages;
}
/**
* @param array $field
* @param string $property
* @param array $call
*/
protected function dynamicConfig(array &$field, $property, array &$call)
{
$value = $call['params'];
$default = isset($field[$property]) ? $field[$property] : null;
$config = Grav::instance()['config']->get($value, $default);
if (!is_null($config)) {
$field[$property] = $config;
}
}
}

View File

@ -0,0 +1,100 @@
<?php
/**
* @package Grav.Common.Data
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Data;
use Grav\Common\Grav;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
class Blueprints
{
protected $search;
protected $types;
protected $instances = [];
/**
* @param string|array $search Search path.
*/
public function __construct($search = 'blueprints://')
{
$this->search = $search;
}
/**
* Get blueprint.
*
* @param string $type Blueprint type.
* @return Blueprint
* @throws \RuntimeException
*/
public function get($type)
{
if (!isset($this->instances[$type])) {
$this->instances[$type] = $this->loadFile($type);
}
return $this->instances[$type];
}
/**
* Get all available blueprint types.
*
* @return array List of type=>name
*/
public function types()
{
if ($this->types === null) {
$this->types = array();
$grav = Grav::instance();
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
// Get stream / directory iterator.
if ($locator->isStream($this->search)) {
$iterator = $locator->getIterator($this->search);
} else {
$iterator = new \DirectoryIterator($this->search);
}
/** @var \DirectoryIterator $file */
foreach ($iterator as $file) {
if (!$file->isFile() || '.' . $file->getExtension() != YAML_EXT) {
continue;
}
$name = $file->getBasename(YAML_EXT);
$this->types[$name] = ucfirst(strtr($name, '_', ' '));
}
}
return $this->types;
}
/**
* Load blueprint file.
*
* @param string $name Name of the blueprint.
* @return Blueprint
*/
protected function loadFile($name)
{
$blueprint = new Blueprint($name);
if (is_array($this->search) || is_object($this->search)) {
// Page types.
$blueprint->setOverrides($this->search);
$blueprint->setContext('blueprints://pages');
} else {
$blueprint->setContext($this->search);
}
return $blueprint->load()->init();
}
}

View File

@ -0,0 +1,282 @@
<?php
/**
* @package Grav.Common.Data
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Data;
use RocketTheme\Toolbox\ArrayTraits\Countable;
use RocketTheme\Toolbox\ArrayTraits\Export;
use RocketTheme\Toolbox\ArrayTraits\ExportInterface;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccessWithGetters;
use RocketTheme\Toolbox\File\File;
use RocketTheme\Toolbox\File\FileInterface;
class Data implements DataInterface, \ArrayAccess, \Countable, ExportInterface
{
use NestedArrayAccessWithGetters, Countable, Export;
protected $gettersVariable = 'items';
protected $items;
/**
* @var Blueprints
*/
protected $blueprints;
/**
* @var File
*/
protected $storage;
/**
* @param array $items
* @param Blueprint|callable $blueprints
*/
public function __construct(array $items = array(), $blueprints = null)
{
$this->items = $items;
$this->blueprints = $blueprints;
}
/**
* Get value by using dot notation for nested arrays/objects.
*
* @example $value = $data->value('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 value($name, $default = null, $separator = '.')
{
return $this->get($name, $default, $separator);
}
/**
* Join nested values together by using blueprints.
*
* @param string $name Dot separated path to the requested value.
* @param mixed $value Value to be joined.
* @param string $separator Separator, defaults to '.'
* @return $this
* @throws \RuntimeException
*/
public function join($name, $value, $separator = '.')
{
$old = $this->get($name, null, $separator);
if ($old !== null) {
if (!is_array($old)) {
throw new \RuntimeException('Value ' . $old);
}
if (is_object($value)) {
$value = (array) $value;
} elseif (!is_array($value)) {
throw new \RuntimeException('Value ' . $value);
}
$value = $this->blueprints()->mergeData($old, $value, $name, $separator);
}
$this->set($name, $value, $separator);
return $this;
}
/**
* Get nested structure containing default values defined in the blueprints.
*
* Fields without default value are ignored in the list.
* @return array
*/
public function getDefaults()
{
return $this->blueprints()->getDefaults();
}
/**
* Set default values by using blueprints.
*
* @param string $name Dot separated path to the requested value.
* @param mixed $value Value to be joined.
* @param string $separator Separator, defaults to '.'
* @return $this
*/
public function joinDefaults($name, $value, $separator = '.')
{
if (is_object($value)) {
$value = (array) $value;
}
$old = $this->get($name, null, $separator);
if ($old !== null) {
$value = $this->blueprints()->mergeData($value, $old, $name, $separator);
}
$this->set($name, $value, $separator);
return $this;
}
/**
* Get value from the configuration and join it with given data.
*
* @param string $name Dot separated path to the requested value.
* @param array $value Value to be joined.
* @param string $separator Separator, defaults to '.'
* @return array
* @throws \RuntimeException
*/
public function getJoined($name, $value, $separator = '.')
{
if (is_object($value)) {
$value = (array) $value;
} elseif (!is_array($value)) {
throw new \RuntimeException('Value ' . $value);
}
$old = $this->get($name, null, $separator);
if ($old === null) {
// No value set; no need to join data.
return $value;
}
if (!is_array($old)) {
throw new \RuntimeException('Value ' . $old);
}
// Return joined data.
return $this->blueprints()->mergeData($old, $value, $name, $separator);
}
/**
* Merge two configurations together.
*
* @param array $data
* @return $this
*/
public function merge(array $data)
{
$this->items = $this->blueprints()->mergeData($this->items, $data);
return $this;
}
/**
* Set default values to the configuration if variables were not set.
*
* @param array $data
* @return $this
*/
public function setDefaults(array $data)
{
$this->items = $this->blueprints()->mergeData($data, $this->items);
return $this;
}
/**
* Validate by blueprints.
*
* @return $this
* @throws \Exception
*/
public function validate()
{
$this->blueprints()->validate($this->items);
return $this;
}
/**
* @return $this
* Filter all items by using blueprints.
*/
public function filter()
{
$this->items = $this->blueprints()->filter($this->items);
return $this;
}
/**
* Get extra items which haven't been defined in blueprints.
*
* @return array
*/
public function extra()
{
return $this->blueprints()->extra($this->items);
}
/**
* Return blueprints.
*
* @return Blueprint
*/
public function blueprints()
{
if (!$this->blueprints){
$this->blueprints = new Blueprint;
} elseif (is_callable($this->blueprints)) {
// Lazy load blueprints.
$blueprints = $this->blueprints;
$this->blueprints = $blueprints();
}
return $this->blueprints;
}
/**
* Save data if storage has been defined.
*/
public function save()
{
$file = $this->file();
if ($file) {
$file->save($this->items);
}
}
/**
* Returns whether the data already exists in the storage.
*
* NOTE: This method does not check if the data is current.
*
* @return bool
*/
public function exists()
{
return $this->file()->exists();
}
/**
* Return unmodified data as raw string.
*
* NOTE: This function only returns data which has been saved to the storage.
*
* @return string
*/
public function raw()
{
return $this->file()->raw();
}
/**
* Set or get the data storage.
*
* @param FileInterface $storage Optionally enter a new storage.
* @return FileInterface
*/
public function file(FileInterface $storage = null)
{
if ($storage) {
$this->storage = $storage;
}
return $this->storage;
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* @package Grav.Common.Data
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Data;
use RocketTheme\Toolbox\File\FileInterface;
interface DataInterface
{
/**
* Get value by using dot notation for nested arrays/objects.
*
* @example $value = $data->value('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 value($name, $default = null, $separator = '.');
/**
* Merge external data.
*
* @param array $data
* @return mixed
*/
public function merge(array $data);
/**
* Return blueprints.
*/
public function blueprints();
/**
* Validate by blueprints.
*
* @throws \Exception
*/
public function validate();
/**
* Filter all items by using blueprints.
*/
public function filter();
/**
* Get extra items which haven't been defined in blueprints.
*/
public function extra();
/**
* Save data into the file.
*/
public function save();
/**
* Set or get the data storage.
*
* @param FileInterface $storage Optionally enter a new storage.
* @return FileInterface
*/
public function file(FileInterface $storage = null);
}

View File

@ -0,0 +1,739 @@
<?php
/**
* @package Grav.Common.Data
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Data;
use Grav\Common\Grav;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Yaml;
class Validation
{
/**
* Validate value against a blueprint field definition.
*
* @param $value
* @param array $field
* @return array
*/
public static function validate($value, array $field)
{
$messages = [];
$validate = isset($field['validate']) ? (array) $field['validate'] : [];
// If value isn't required, we will stop validation if empty value is given.
if (empty($validate['required']) && ($value === null || $value === '')) {
return $messages;
}
if (!isset($field['type'])) {
$field['type'] = 'text';
}
// Get language class.
$language = Grav::instance()['language'];
// Validate type with fallback type text.
$type = (string) isset($field['validate']['type']) ? $field['validate']['type'] : $field['type'];
$method = 'type'.strtr($type, '-', '_');
$name = ucfirst(isset($field['label']) ? $field['label'] : $field['name']);
$message = (string) isset($field['validate']['message'])
? $language->translate($field['validate']['message'])
: $language->translate('FORM.INVALID_INPUT', null, true) . ' "' . $language->translate($name) . '"';
if (method_exists(__CLASS__, $method)) {
$success = self::$method($value, $validate, $field);
} else {
$success = true;
}
if (!$success) {
$messages[$field['name']][] = $message;
}
// Check individual rules.
foreach ($validate as $rule => $params) {
$method = 'validate' . ucfirst(strtr($rule, '-', '_'));
if (method_exists(__CLASS__, $method)) {
$success = self::$method($value, $params);
if (!$success) {
$messages[$field['name']][] = $message;
}
}
}
return $messages;
}
/**
* Filter value against a blueprint field definition.
*
* @param mixed $value
* @param array $field
* @return mixed Filtered value.
*/
public static function filter($value, array $field)
{
$validate = isset($field['validate']) ? (array) $field['validate'] : [];
// If value isn't required, we will return null if empty value is given.
if (empty($validate['required']) && ($value === null || $value === '')) {
return null;
}
if (!isset($field['type'])) {
$field['type'] = 'text';
}
// 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' . ucfirst(strtr($type, '-', '_'));
if (!method_exists(__CLASS__, $method)) {
$method = 'filterText';
}
return self::$method($value, $validate, $field);
}
/**
* HTML5 input: text
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeText($value, array $params, array $field)
{
if (!is_string($value)) {
return false;
}
if (isset($params['min']) && strlen($value) < $params['min']) {
return false;
}
if (isset($params['max']) && strlen($value) > $params['max']) {
return false;
}
$min = isset($params['min']) ? $params['min'] : 0;
if (isset($params['step']) && (strlen($value) - $min) % $params['step'] == 0) {
return false;
}
if ((!isset($params['multiline']) || !$params['multiline']) && preg_match('/\R/um', $value)) {
return false;
}
return true;
}
protected static function filterText($value, array $params, array $field)
{
return (string) $value;
}
protected static function filterCommaList($value, array $params, array $field)
{
return is_array($value) ? $value : preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY);
}
protected static function typeCommaList($value, array $params, array $field)
{
return is_array($value) ? true : self::typeText($value, $params, $field);
}
/**
* HTML5 input: textarea
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeTextarea($value, array $params, array $field)
{
if (!isset($params['multiline'])) {
$params['multiline'] = true;
}
return self::typeText($value, $params, $field);
}
/**
* HTML5 input: password
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typePassword($value, array $params, array $field)
{
return self::typeText($value, $params, $field);
}
/**
* HTML5 input: hidden
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeHidden($value, array $params, array $field)
{
return self::typeText($value, $params, $field);
}
/**
* Custom input: checkbox list
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeCheckboxes($value, array $params, array $field)
{
return self::typeArray((array) $value, $params, $field);
}
protected static function filterCheckboxes($value, array $params, array $field)
{
return self::filterArray($value, $params, $field);
}
/**
* HTML5 input: checkbox
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeCheckbox($value, array $params, array $field)
{
$value = (string) $value;
if (!isset($field['value'])) {
$field['value'] = 1;
}
if ($value && $value != $field['value']) {
return false;
}
return true;
}
/**
* HTML5 input: radio
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeRadio($value, array $params, array $field)
{
return self::typeArray((array) $value, $params, $field);
}
/**
* Custom input: toggle
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeToggle($value, array $params, array $field)
{
return self::typeArray((array) $value, $params, $field);
}
/**
* Custom input: file
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeFile($value, array $params, array $field)
{
return self::typeArray((array) $value, $params, $field);
}
protected static function filterFile($value, array $params, array $field)
{
return (array) $value;
}
/**
* HTML5 input: select
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeSelect($value, array $params, array $field)
{
return self::typeArray((array) $value, $params, $field);
}
/**
* HTML5 input: number
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeNumber($value, array $params, array $field)
{
if (!is_numeric($value)) {
return false;
}
if (isset($params['min']) && $value < $params['min']) {
return false;
}
if (isset($params['max']) && $value > $params['max']) {
return false;
}
$min = isset($params['min']) ? $params['min'] : 0;
if (isset($params['step']) && fmod($value - $min, $params['step']) == 0) {
return false;
}
return true;
}
protected static function filterNumber($value, array $params, array $field)
{
return (int) $value;
}
protected static function filterDateTime($value, array $params, array $field)
{
$format = Grav::instance()['config']->get('system.pages.dateformat.default');
if ($format) {
$converted = new \DateTime($value);
return $converted->format($format);
}
return $value;
}
/**
* HTML5 input: range
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeRange($value, array $params, array $field)
{
return self::typeNumber($value, $params, $field);
}
protected static function filterRange($value, array $params, array $field)
{
return self::filterNumber($value, $params, $field);
}
/**
* HTML5 input: color
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeColor($value, array $params, array $field)
{
return preg_match('/^\#[0-9a-fA-F]{3}[0-9a-fA-F]{3}?$/u', $value);
}
/**
* HTML5 input: email
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeEmail($value, array $params, array $field)
{
$values = !is_array($value) ? explode(',', preg_replace('/\s+/', '', $value)) : $value;
foreach ($values as $value) {
if (!(self::typeText($value, $params, $field) && filter_var($value, FILTER_VALIDATE_EMAIL))) {
return false;
}
}
return true;
}
/**
* HTML5 input: url
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeUrl($value, array $params, array $field)
{
return self::typeText($value, $params, $field) && filter_var($value, FILTER_VALIDATE_URL);
}
/**
* HTML5 input: datetime
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeDatetime($value, array $params, array $field)
{
if ($value instanceof \DateTime) {
return true;
} elseif (!is_string($value)) {
return false;
} elseif (!isset($params['format'])) {
return false !== strtotime($value);
}
$dateFromFormat = \DateTime::createFromFormat($params['format'], $value);
return $dateFromFormat && $value === date($params['format'], $dateFromFormat->getTimestamp());
}
/**
* HTML5 input: datetime-local
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeDatetimeLocal($value, array $params, array $field)
{
return self::typeDatetime($value, $params, $field);
}
/**
* HTML5 input: date
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeDate($value, array $params, array $field)
{
$params = array($params);
if (!isset($params['format'])) {
$params['format'] = 'Y-m-d';
}
return self::typeDatetime($value, $params, $field);
}
/**
* HTML5 input: time
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeTime($value, array $params, array $field)
{
$params = array($params);
if (!isset($params['format'])) {
$params['format'] = 'H:i';
}
return self::typeDatetime($value, $params, $field);
}
/**
* HTML5 input: month
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeMonth($value, array $params, array $field)
{
$params = array($params);
if (!isset($params['format'])) {
$params['format'] = 'Y-m';
}
return self::typeDatetime($value, $params, $field);
}
/**
* HTML5 input: week
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeWeek($value, array $params, array $field)
{
if (!isset($params['format']) && !preg_match('/^\d{4}-W\d{2}$/u', $value)) {
return false;
}
return self::typeDatetime($value, $params, $field);
}
/**
* Custom input: array
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeArray($value, array $params, array $field)
{
if (!is_array($value)) {
return false;
}
if (isset($field['multiple'])) {
if (isset($params['min']) && count($value) < $params['min']) {
return false;
}
if (isset($params['max']) && count($value) > $params['max']) {
return false;
}
$min = isset($params['min']) ? $params['min'] : 0;
if (isset($params['step']) && (count($value) - $min) % $params['step'] == 0) {
return false;
}
}
$options = isset($field['options']) ? array_keys($field['options']) : array();
$values = isset($field['use']) && $field['use'] == 'keys' ? array_keys($value) : $value;
if ($options && array_diff($values, $options)) {
return false;
}
return true;
}
protected static function filterArray($value, $params, $field)
{
$values = (array) $value;
$options = isset($field['options']) ? array_keys($field['options']) : array();
$multi = isset($field['multiple']) ? $field['multiple'] : false;
if (count($values) == 1 && isset($values[0]) && $values[0] == '') {
return null;
}
if ($options) {
$useKey = isset($field['use']) && $field['use'] == 'keys';
foreach ($values as $key => $value) {
$values[$key] = $useKey ? (bool) $value : $value;
}
}
if ($multi) {
foreach ($values as $key => $value) {
if (is_array($value)) {
$value = implode(',', $value);
}
$values[$key] = array_map('trim', explode(',', $value));
}
}
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;
}
public static function typeYaml($value, $params)
{
try {
Yaml::parse($value);
return true;
} catch (ParseException $e) {
return false;
}
}
public static function filterYaml($value, $params)
{
try {
return (array) Yaml::parse($value);
} catch (ParseException $e) {
return null;
}
}
/**
* Custom input: ignore (will not validate)
*
* @param mixed $value Value to be validated.
* @param array $params Validation parameters.
* @param array $field Blueprint for the field.
* @return bool True if validation succeeded.
*/
public static function typeIgnore($value, array $params, array $field)
{
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)
{
if (is_scalar($value)) {
return (bool) $params !== true || $value !== '';
} else {
return (bool) $params !== true || !empty($value);
}
}
public static function validatePattern($value, $params)
{
return (bool) preg_match("`^{$params}$`u", $value);
}
// Internal types
public static function validateAlpha($value, $params)
{
return ctype_alpha($value);
}
public static function validateAlnum($value, $params)
{
return ctype_alnum($value);
}
public static function typeBool($value, $params)
{
return is_bool($value) || $value == 1 || $value == 0;
}
public static function validateBool($value, $params)
{
return is_bool($value) || $value == 1 || $value == 0;
}
protected static function filterBool($value, $params)
{
return (bool) $value;
}
public static function validateDigit($value, $params)
{
return ctype_digit($value);
}
public static function validateFloat($value, $params)
{
return is_float(filter_var($value, FILTER_VALIDATE_FLOAT));
}
protected static function filterFloat($value, $params)
{
return (float) $value;
}
public static function validateHex($value, $params)
{
return ctype_xdigit($value);
}
public static function validateInt($value, $params)
{
return is_numeric($value) && (int) $value == $value;
}
protected static function filterInt($value, $params)
{
return (int) $value;
}
public static function validateArray($value, $params)
{
return is_array($value)
|| ($value instanceof \ArrayAccess
&& $value instanceof \Traversable
&& $value instanceof \Countable);
}
public static function validateJson($value, $params)
{
return (bool) (@json_decode($value));
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* @package Grav.Common.Data
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Data;
use Grav\Common\Grav;
class ValidationException extends \RuntimeException
{
protected $messages = [];
public function setMessages(array $messages = []) {
$this->messages = $messages;
$language = Grav::instance()['language'];
$this->message = $language->translate('FORM.VALIDATION_FAIL', null, true) . ' ' . $this->message;
foreach ($messages as $variable => &$list) {
$list = array_unique($list);
foreach ($list as $message) {
$this->message .= "<br/>$message";
}
}
return $this;
}
public function getMessages()
{
return $this->messages;
}
}

View File

@ -0,0 +1,235 @@
<?php
/**
* @package Grav.Common
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common;
use DebugBar\DataCollector\ConfigCollector;
use DebugBar\JavascriptRenderer;
use DebugBar\StandardDebugBar;
use Grav\Common\Config\Config;
class Debugger
{
/** @var Grav $grav */
protected $grav;
/** @var Config $config */
protected $config;
/** @var JavascriptRenderer $renderer */
protected $renderer;
/** @var StandardDebugBar $debugbar */
protected $debugbar;
protected $enabled;
protected $timers = [];
/**
* Debugger constructor.
*/
public function __construct()
{
$this->debugbar = new StandardDebugBar();
$this->debugbar['time']->addMeasure('Loading', $this->debugbar['time']->getRequestStartTime(), microtime(true));
}
/**
* Initialize the debugger
*
* @return $this
* @throws \DebugBar\DebugBarException
*/
public function init()
{
$this->grav = Grav::instance();
$this->config = $this->grav['config'];
if ($this->enabled()) {
$this->debugbar->addCollector(new ConfigCollector((array)$this->config->get('system'), 'Config'));
$this->debugbar->addCollector(new ConfigCollector((array)$this->config->get('plugins'), 'Plugins'));
}
return $this;
}
/**
* Set/get the enabled state of the debugger
*
* @param bool $state If null, the method returns the enabled value. If set, the method sets the enabled state
*
* @return null
*/
public function enabled($state = null)
{
if (isset($state)) {
$this->enabled = $state;
} else {
if (!isset($this->enabled)) {
$this->enabled = $this->config->get('system.debugger.enabled');
}
}
return $this->enabled;
}
/**
* Add the debugger assets to the Grav Assets
*
* @return $this
*/
public function addAssets()
{
if ($this->enabled()) {
/** @var Assets $assets */
$assets = $this->grav['assets'];
// Add jquery library
$assets->add('jquery', 101);
$this->renderer = $this->debugbar->getJavascriptRenderer();
$this->renderer->setIncludeVendors(false);
// Get the required CSS files
list($css_files, $js_files) = $this->renderer->getAssets(null, JavascriptRenderer::RELATIVE_URL);
foreach ($css_files as $css) {
$assets->addCss($css);
}
$assets->addCss('/system/assets/debugger.css');
foreach ($js_files as $js) {
$assets->addJs($js);
}
}
return $this;
}
/**
* Adds a data collector
*
* @param $collector
*
* @return $this
* @throws \DebugBar\DebugBarException
*/
public function addCollector($collector)
{
$this->debugbar->addCollector($collector);
return $this;
}
/**
* Returns a data collector
*
* @param $collector
*
* @return \DebugBar\DataCollector\DataCollectorInterface
* @throws \DebugBar\DebugBarException
*/
public function getCollector($collector)
{
return $this->debugbar->getCollector($collector);
}
/**
* Displays the debug bar
*
* @return $this
*/
public function render()
{
if ($this->enabled()) {
echo $this->renderer->render();
}
return $this;
}
/**
* Sends the data through the HTTP headers
*
* @return $this
*/
public function sendDataInHeaders()
{
$this->debugbar->sendDataInHeaders();
return $this;
}
/**
* Start a timer with an associated name and description
*
* @param $name
* @param string|null $description
*
* @return $this
*/
public function startTimer($name, $description = null)
{
if ($name[0] == '_' || $this->config->get('system.debugger.enabled')) {
$this->debugbar['time']->startMeasure($name, $description);
$this->timers[] = $name;
}
return $this;
}
/**
* Stop the named timer
*
* @param string $name
*
* @return $this
*/
public function stopTimer($name)
{
if (in_array($name, $this->timers) && ($name[0] == '_' || $this->config->get('system.debugger.enabled'))) {
$this->debugbar['time']->stopMeasure($name);
}
return $this;
}
/**
* Dump variables into the Messages tab of the Debug Bar
*
* @param $message
* @param string $label
* @param bool $isString
*
* @return $this
*/
public function addMessage($message, $label = 'info', $isString = true)
{
if ($this->enabled()) {
$this->debugbar['messages']->addMessage($message, $label, $isString);
}
return $this;
}
/**
* Dump exception into the Messages tab of the Debug Bar
*
* @param \Exception $e
* @return Debugger
*/
public function addException(\Exception $e)
{
if ($this->enabled()) {
$this->debugbar['exceptions']->addException($e);
}
return $this;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* @package Grav.Common.Errors
*
* @copyright Copyright (C) 2014 - 2016 RocketTheme, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Errors;
use Grav\Common\Grav;
use Whoops;
class Errors
{
public function resetHandlers()
{
$grav = Grav::instance();
$config = $grav['config']->get('system.errors');
$jsonRequest = $_SERVER && isset($_SERVER['HTTP_ACCEPT']) && $_SERVER['HTTP_ACCEPT'] == 'application/json';
// Setup Whoops-based error handler
$whoops = new \Whoops\Run;
if (isset($config['display'])) {
if ($config['display']) {
$error_page = new Whoops\Handler\PrettyPageHandler;
$error_page->setPageTitle('Crikey! There was an error...');
$error_page->addResourcePath(GRAV_ROOT . '/system/assets');
$error_page->addCustomCss('whoops.css');
$whoops->pushHandler($error_page);
} else {
$whoops->pushHandler(new SimplePageHandler);
}
}
if (method_exists('Whoops\Util\Misc', 'isAjaxRequest')) { //Whoops 2.0
if (Whoops\Util\Misc::isAjaxRequest() || $jsonRequest) {
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
}
} elseif (function_exists('Whoops\isAjaxRequest')) { //Whoops 2.0.0-alpha
if (Whoops\isAjaxRequest() || $jsonRequest) {
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
}
} else { //Whoops 1.x
$json_page = new Whoops\Handler\JsonResponseHandler;
$json_page->onlyForAjaxRequests(true);
}
if (isset($config['log']) && $config['log']) {
$logger = $grav['log'];
$whoops->pushHandler(function($exception, $inspector, $run) use ($logger) {
try {
$logger->addCritical($exception->getMessage() . ' - Trace: ' . $exception->getTraceAsString());
} catch (\Exception $e) {
echo $e;
}
}, 'log');
}
$whoops->register();
}
}

View File

@ -0,0 +1,52 @@
html, body {
height: 100%
}
body {
margin:0 3rem;
padding:0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 1.5rem;
line-height: 1.4;
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
}
.container {
margin: 0rem;
max-width: 600px;
padding-bottom:5rem;
}
header {
color: #000;
font-size: 4rem;
letter-spacing: 2px;
line-height: 1.1;
margin-bottom: 2rem;
}
p {
font-family: Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif;
color: #666;
}
h5 {
font-weight: normal;
color: #999;
font-size: 1rem;
}
h6 {
font-weight: normal;
color: #999;
}
code {
font-weight: bold;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}

View File

@ -0,0 +1,30 @@
<?php
/**
* Layout template file for Whoops's pretty error output.
*/
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Whoops there was an error!</title>
<style><?php echo $stylesheet ?></style>
</head>
<body>
<div class="container">
<div class="details">
<header>
Server Error
</header>
<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>
</html>

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