diff --git a/.travis.yml b/.travis.yml
index 2a2b5d695..578da9f7f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -52,7 +52,11 @@ script:
FILES="$RT_DEVTOOLS/grav-dist/*.zip";
for file in ${FILES[@]}; do
NAME=${file##*/};
- REPO="$(echo ${NAME} | rev | cut -f 2- -d "-" | rev)";
+ if [[ "$NAME" == *"-rc"* ]]; then
+ REPO="$(echo ${NAME} | rev | cut -f 3- -d "-" | rev)";
+ else
+ REPO="$(echo ${NAME} | rev | cut -f 2- -d "-" | rev)";
+ fi;
if [[ $REPO == 'grav' || $REPO == 'grav-admin' || $REPO == 'grav-update' ]]; then
REPO="grav";
fi;
@@ -60,7 +64,7 @@ script:
ASSETS="$(echo "${API}" | node gh-assets.js)";
TAG="$(echo "${API}" | grep tag_name | head -n 1 | cut -d '"' -f 4)";
if [ $REPO == "grav" ]; then
- TAG=$TRAVIS_TAG;
+ TAG="$TRAVIS_TAG";
fi;
if [ ! -z "$ASSETS" ]; then
for asset in ${ASSETS[@]}; do
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8cb97d31d..fa91a22cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+# v1.0.0-rc.2
+## 10/27/2015
+
+1. [](#new)
+ * Added support for CSS Asset groups
+ * Added a `wrapped_site` system option for themes/plugins to use
+ * Pass `Page` object as event to `onTwigPageVariables()` event hook
+ * New `Data.items()` method to get all items
+1. [](#improved)
+ * Missing pipelined remote asset will now fail quietly
+ * More reliably handle inline JS and CSS to remove only surrounding HTML tags
+ * `Medium.meta` returns new Data object so null checks are possible
+ * Improved Medium metadata merging to allow for automatic title/alt/class attributes
+ * Moved Grav object to global variable rather than template variable (useful for macros)
+ * German language improvements
+ * Updated bundled composer
+1. [](#bugfix)
+ * Accept variety of `true` values in `User.authorize()` method
+ * Fix for `Validation` throwing an error if no label set
+
# v1.0.0-rc.1
## 10/23/2015
@@ -18,7 +38,7 @@
1. [](#improved)
* Moved hardcoded mimetypes to `media.yaml` to be treated as Page media files
* Set `errors: display: false` by default in `system.yaml`
- * Strip out extra slashes in the URI
+ * Strip out extra slashes in the URI
* Validate hostname to ensure it is valid
* Ignore more SCM folders in Backups
* Removed `home_redirect` settings from `system.yaml`
@@ -29,7 +49,7 @@
* Debugbar vendor library update
* Always fallback to english if other translations are not available
1. [](#bugfix)
- * Fix for redirecting external URL with multi-language
+ * Fix for redirecting external URL with multi-language
* Fix for Asset pipeline not respecting asset groups
* Fix language files with child/parent theme relationships
* Fixed a regression issue resulting in incorrect default language
diff --git a/bin/composer.phar b/bin/composer.phar
index deead1618..72b1546b2 100755
Binary files a/bin/composer.phar and b/bin/composer.phar differ
diff --git a/system/blueprints/config/system.yaml b/system/blueprints/config/system.yaml
index fca66cd30..b17fc3605 100644
--- a/system/blueprints/config/system.yaml
+++ b/system/blueprints/config/system.yaml
@@ -750,6 +750,17 @@ form:
underline: true
fields:
+ wrapped_site:
+ type: toggle
+ label: PLUGIN_ADMIN.WRAPPED_SITE
+ highlight: 0
+ help: PLUGIN_ADMIN.WRAPPED_SITE_HELP
+ options:
+ 1: PLUGIN_ADMIN.YES
+ 0: PLUGIN_ADMIN.NO
+ validate:
+ type: bool
+
absolute_urls:
type: toggle
label: PLUGIN_ADMIN.ABSOLUTE_URLS
diff --git a/system/config/system.yaml b/system/config/system.yaml
index 366d1e549..443788d67 100644
--- a/system/config/system.yaml
+++ b/system/config/system.yaml
@@ -2,6 +2,7 @@ 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
languages:
supported: [] # List of languages supported. eg: [en, fr, de]
diff --git a/system/defines.php b/system/defines.php
index 2adc2b99e..b3d9c06e4 100644
--- a/system/defines.php
+++ b/system/defines.php
@@ -2,7 +2,7 @@
// Some standard defines
define('GRAV', true);
-define('GRAV_VERSION', '1.0.0-rc.1');
+define('GRAV_VERSION', '1.0.0-rc.2');
define('DS', '/');
// Directories and Paths
diff --git a/system/languages/de.yaml b/system/languages/de.yaml
index 7cdc5d8e8..798e14d10 100644
--- a/system/languages/de.yaml
+++ b/system/languages/de.yaml
@@ -1,43 +1,43 @@
INFLECTOR_IRREGULAR:
- 'person': 'personen'
- 'man': 'menschen'
- 'child': 'kinder'
- 'sex': 'geschlecht'
- 'move': 'züge'
+ 'person': 'Personen'
+ 'man': 'Menschen'
+ 'child': 'Kinder'
+ 'sex': 'Geschlecht'
+ 'move': 'Züge'
NICETIME:
NO_DATE_PROVIDED: Keine Daten vorhanden
BAD_DATE: Falsches Datum
AGO: her
FROM_NOW: ab jetzt
- SECOND: sekunde
- MINUTE: minute
- HOUR: stunde
- DAY: tag
- WEEK: woche
- MONTH: monat
- YEAR: jahr
- DECADE: dekade
+ SECOND: Sekunde
+ MINUTE: Minute
+ HOUR: Stunde
+ DAY: Tag
+ WEEK: Woche
+ MONTH: Monat
+ YEAR: Jahr
+ DECADE: Dekade
SEC: sek
MIN: min
HR: std
- DAY: tag
+ DAY: Tag
WK: wo
MO: mo
YR: yh
DEC: dec
- SECOND_PLURAL: sekunden
- MINUTE_PLURAL: minuten
- HOUR_PLURAL: stunden
- DAY_PLURAL: tage
- WEEK_PLURAL: wochen
- MONTH_PLURAL: monate
- YEAR_PLURAL: jahre
- DECADE_PLURAL: dekaden
- SEC_PLURAL: sekunden
- MIN_PLURAL: minuten
- HR_PLURAL: stunden
- DAY_PLURAL: tage
- WK_PLURAL: wochen
- MO_PLURAL: monate
- YR_PLURAL: jahre
- DEC_PLURAL: dekaden
+ SECOND_PLURAL: Sekunden
+ MINUTE_PLURAL: Minuten
+ HOUR_PLURAL: Stunden
+ DAY_PLURAL: Tage
+ WEEK_PLURAL: Wochen
+ MONTH_PLURAL: Monate
+ YEAR_PLURAL: Jahre
+ DECADE_PLURAL: Dekaden
+ SEC_PLURAL: Sekunden
+ MIN_PLURAL: Minuten
+ HR_PLURAL: Stunden
+ DAY_PLURAL: Tage
+ WK_PLURAL: Wochen
+ MO_PLURAL: Monate
+ YR_PLURAL: Jahre
+ DEC_PLURAL: Dekaden
diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php
index 14a9161ef..f1a61b349 100644
--- a/system/src/Grav/Common/Assets.php
+++ b/system/src/Grav/Common/Assets.php
@@ -42,6 +42,8 @@ class Assets
/** @const Regex to match CSS import content */
const CSS_IMPORT_REGEX = '{@import(.*);}';
+ const HTML_TAG_REGEX = '#(<([A-Z][A-Z0-9]*)>)+(.*)(<\/\2>)#is';
+
/**
* Closure used by the pipeline to fetch assets.
@@ -227,21 +229,22 @@ class Assets
* It checks for duplicates.
* You may add more than one asset passing an array as argument.
*
- * @param mixed $asset
- * @param int $priority the priority, bigger comes first
- * @param bool $pipeline false if this should not be pipelined
+ * @param mixed $asset
+ * @param int $priority the priority, bigger comes first
+ * @param bool $pipeline false if this should not be pipelined
+ * @param null $group
*
* @return $this
*/
- public function addCss($asset, $priority = null, $pipeline = null)
+ public function addCss($asset, $priority = null, $pipeline = null, $group = null)
{
if (is_array($asset)) {
foreach ($asset as $a) {
- $this->addCss($a, $priority, $pipeline);
+ $this->addCss($a, $priority, $pipeline, $group);
}
return $this;
} elseif (isset($this->collections[$asset])) {
- $this->add($this->collections[$asset], $priority, $pipeline);
+ $this->add($this->collections[$asset], $priority, $pipeline, $group);
return $this;
}
@@ -253,7 +256,8 @@ class Assets
'asset' => $asset,
'priority' => intval($priority ?: 10),
'order' => count($this->css),
- 'pipeline' => $pipeline ?: true
+ 'pipeline' => $pipeline ?: true,
+ 'group' => $group ?: 'head'
];
// check for dynamic array and merge with defaults
@@ -369,20 +373,27 @@ class Assets
* For adding chunks of string-based inline CSS
*
* @param mixed $asset
- * @param int $priority the priority, bigger comes first
+ * @param int $priority the priority, bigger comes first
+ * @param null $group
*
* @return $this
*/
- public function addInlineCss($asset, $priority = null)
+ public function addInlineCss($asset, $priority = null, $group = null)
{
+ $asset = trim($asset);
+
if (is_a($asset, 'Twig_Markup')) {
- $asset = strip_tags((string)$asset);
+ preg_match(self::HTML_TAG_REGEX, $asset, $matches );
+ if (isset($matches[3])) {
+ $asset = $matches[3];
+ }
}
$data = [
'priority' => intval($priority ?: 10),
'order' => count($this->inline_css),
- 'asset' => $asset
+ 'asset' => $asset,
+ 'group' => $group ?: 'head'
];
// check for dynamic array and merge with defaults
@@ -416,8 +427,13 @@ class Assets
*/
public function addInlineJs($asset, $priority = null, $group = null)
{
+ $asset = trim($asset);
+
if (is_a($asset, 'Twig_Markup')) {
- $asset = strip_tags((string)$asset);
+ preg_match(self::HTML_TAG_REGEX, $asset, $matches );
+ if (isset($matches[3])) {
+ $asset = $matches[3];
+ }
}
$data = [
@@ -447,11 +463,12 @@ class Assets
/**
* Build the CSS link tags.
*
+ * @param string $group name of the group
* @param array $attributes
*
* @return string
*/
- public function css($attributes = [])
+ public function css($group = 'head', $attributes = [])
{
if (!$this->css) {
return null;
@@ -479,29 +496,37 @@ class Assets
$attributes = $this->attributes(array_merge(['type' => 'text/css', 'rel' => 'stylesheet'], $attributes));
$output = '';
+ $inline_css = '';
+
if ($this->css_pipeline) {
- $pipeline_result = $this->pipelineCss();
+ $pipeline_result = $this->pipelineCss($group);
if ($pipeline_result) {
$output .= '' . "\n";
}
foreach ($this->css_no_pipeline as $file) {
- $media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
- $output .= '' . "\n";
+ if ($group && $file['group'] == $group) {
+ $media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
+ $output .= '' . "\n";
+ }
}
} else {
foreach ($this->css as $file) {
- $media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
- $output .= '' . "\n";
+ if ($group && $file['group'] == $group) {
+ $media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
+ $output .= '' . "\n";
+ }
}
}
// Render Inline CSS
- if (count($this->inline_css) > 0) {
- $output .= "\n";
+ }
+
+ if ($inline_css) {
+ $output .= "\n\n";
}
@@ -582,7 +607,7 @@ class Assets
*
* @return string
*/
- protected function pipelineCss()
+ protected function pipelineCss($group = 'head')
{
/** @var Cache $cache */
$cache = self::getGrav()['cache'];
@@ -594,7 +619,7 @@ class Assets
// clear no-pipeline assets lists
$this->css_no_pipeline = [];
- $file = md5(json_encode($this->css) . $this->css_minify . $this->css_rewrite) . '.css';
+ $file = md5(json_encode($this->css) . $this->css_minify . $this->css_rewrite . $group) . '.css';
$relative_path = "{$this->base_url}" . basename(ASSETS_DIR) . "/{$file}";
$absolute_path = ASSETS_DIR . $file;
@@ -606,10 +631,12 @@ class Assets
// Remove any non-pipeline files
foreach ($this->css as $id => $asset) {
- if (!$asset['pipeline']) {
- $this->css_no_pipeline[$id] = $asset;
- } else {
- $temp_css[$id] = $asset;
+ if ($asset['group'] == $group) {
+ if (!$asset['pipeline']) {
+ $this->css_no_pipeline[$id] = $asset;
+ } else {
+ $temp_css[$id] = $asset;
+ }
}
}
@@ -930,6 +957,7 @@ class Assets
* Download and concatenate the content of several links.
*
* @param array $links
+ * @param bool $css
*
* @return string
*/
@@ -960,7 +988,12 @@ class Assets
$link = ROOT_DIR . $relative_path;
}
- $file = ($this->fetch_command instanceof Closure) ? $this->fetch_command->__invoke($link) : file_get_contents($link);
+ $file = ($this->fetch_command instanceof Closure) ? @$this->fetch_command->__invoke($link) : @file_get_contents($link);
+
+ // No file found, skip it...
+ if ($file === false) {
+ continue;
+ }
// Double check last character being
if (!$css) {
diff --git a/system/src/Grav/Common/Data/Data.php b/system/src/Grav/Common/Data/Data.php
index 6a35fbc9e..2a12eb22d 100644
--- a/system/src/Grav/Common/Data/Data.php
+++ b/system/src/Grav/Common/Data/Data.php
@@ -224,6 +224,16 @@ class Data implements DataInterface
return $this->file()->raw();
}
+ /**
+ * Return the data items.
+ *
+ * @return array
+ */
+ public function items()
+ {
+ return $this->items;
+ }
+
/**
* Set or get the data storage.
*
diff --git a/system/src/Grav/Common/Data/Validation.php b/system/src/Grav/Common/Data/Validation.php
index 1ad2f22a4..8bdc064af 100644
--- a/system/src/Grav/Common/Data/Validation.php
+++ b/system/src/Grav/Common/Data/Validation.php
@@ -36,7 +36,7 @@ class Validation
// Validate type with fallback type text.
$type = (string) isset($field['validate']['type']) ? $field['validate']['type'] : $field['type'];
$method = 'type'.strtr($type, '-', '_');
- $name = ucfirst($field['label'] ? $field['label'] : $field['name']);
+ $name = ucfirst(isset($field['label']) ? $field['label'] : $field['name']);
$message = (string) isset($field['validate']['message']) ? $field['validate']['message'] : 'Invalid input in "' . $language->translate($name) . '""';
if (method_exists(__CLASS__, $method)) {
diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php
index cf15863cf..d3d3e6298 100644
--- a/system/src/Grav/Common/Page/Medium/Medium.php
+++ b/system/src/Grav/Common/Page/Medium/Medium.php
@@ -68,6 +68,16 @@ class Medium extends Data implements RenderableInterface
$this->reset();
}
+ /**
+ * Return just metadata from the Medium object
+ *
+ * @return $this
+ */
+ public function meta()
+ {
+ return new Data($this->items);
+ }
+
/**
* Add meta file for the medium.
*
@@ -203,9 +213,29 @@ class Medium extends Data implements RenderableInterface
}
$attributes['style'] = $style;
- !empty($title) && empty($attributes['title']) && $attributes['title'] = $title;
- !empty($alt) && empty($attributes['alt']) && $attributes['alt'] = $alt;
- !empty($class) && empty($attributes['class']) && $attributes['class'] = $class;
+ if (empty($attributes['title'])) {
+ if (!empty($title)) {
+ $attributes['title'] = $title;
+ } elseif (!empty($this->items['title'])) {
+ $attributes['title'] = $this->items['title'];
+ }
+ }
+
+ if (empty($attributes['alt'])) {
+ if (!empty($alt)) {
+ $attributes['alt'] = $alt;
+ } elseif (!empty($this->items['alt'])) {
+ $attributes['alt'] = $this->items['alt'];
+ }
+ }
+
+ if (empty($attributes['class'])) {
+ if (!empty($class)) {
+ $attributes['class'] = $class;
+ } elseif (!empty($this->items['class'])) {
+ $attributes['class'] = $this->items['class'];
+ }
+ }
switch ($this->mode) {
case 'text':
@@ -376,8 +406,6 @@ class Medium extends Data implements RenderableInterface
$this->querystring($this->querystring(null, false) . '&' . $qs);
}
- self::$grav['debugger']->addMessage($this->querystring());
-
return $this;
}
diff --git a/system/src/Grav/Common/Twig/Twig.php b/system/src/Grav/Common/Twig/Twig.php
index 5b2319561..381efe56f 100644
--- a/system/src/Grav/Common/Twig/Twig.php
+++ b/system/src/Grav/Common/Twig/Twig.php
@@ -7,6 +7,7 @@ use Grav\Common\Page\Page;
use Grav\Common\Inflector;
use Grav\Common\Utils;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
+use RocketTheme\Toolbox\Event\Event;
/**
* The Twig object handles all the Twig template rendering for Grav. It's a singleton object
@@ -142,7 +143,6 @@ class Twig
// Set some standard variables for twig
$this->twig_vars = array(
- 'grav' => $this->grav,
'config' => $config,
'uri' => $this->grav['uri'],
'base_dir' => rtrim(ROOT_DIR, '/'),
@@ -202,7 +202,7 @@ class Twig
$content = $content !== null ? $content : $item->content();
// override the twig header vars for local resolution
- $this->grav->fireEvent('onTwigPageVariables');
+ $this->grav->fireEvent('onTwigPageVariables', new Event(['page' => $item]));
$twig_vars = $this->twig_vars;
$twig_vars['page'] = $item;
diff --git a/system/src/Grav/Common/Twig/TwigExtension.php b/system/src/Grav/Common/Twig/TwigExtension.php
index 9424e8f87..2da411210 100644
--- a/system/src/Grav/Common/Twig/TwigExtension.php
+++ b/system/src/Grav/Common/Twig/TwigExtension.php
@@ -36,6 +36,18 @@ class TwigExtension extends \Twig_Extension
return 'GravTwigExtension';
}
+ /**
+ * Register some standard globals
+ *
+ * @return array
+ */
+ public function getGlobals()
+ {
+ return array(
+ 'grav' => $this->grav,
+ );
+ }
+
/**
* Return a list of all filters.
*
diff --git a/system/src/Grav/Common/User/User.php b/system/src/Grav/Common/User/User.php
index 21cd61c38..e11be723a 100644
--- a/system/src/Grav/Common/User/User.php
+++ b/system/src/Grav/Common/User/User.php
@@ -5,6 +5,7 @@ use Grav\Common\Data\Blueprints;
use Grav\Common\Data\Data;
use Grav\Common\File\CompiledYamlFile;
use Grav\Common\GravTrait;
+use Grav\Common\Utils;
/**
* User object
@@ -138,7 +139,7 @@ class User extends Data
return false;
}
- return $this->get("access.{$action}") === true;
+ return Utils::isPositive($this->get("access.{$action}"));
}
/**
diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php
index c0b15af44..8c55669a2 100644
--- a/system/src/Grav/Common/Utils.php
+++ b/system/src/Grav/Common/Utils.php
@@ -377,4 +377,14 @@ abstract class Utils
}
}
+ /**
+ * Checks if a value is positive
+ *
+ * @param string $value
+ *
+ * @return boolean
+ */
+ public static function isPositive($value) {
+ return in_array($value, [true, 1, '1', 'yes', 'on', 'true'], true);
+ }
}