diff --git a/CHANGELOG.md b/CHANGELOG.md
index 972507d9c5..6d81ab63e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,26 @@
+# v0.9.5 beta
+## 11/09/2014
+
+1. [](#new)
+ * Added quality setting to medium for compression configuration of images
+ * Added new onPageContentProcessed() event that is post-content processing but pre-caching
+2. [](#improved)
+ * Added support for AND and OR taxonomy filtering. AND by default (was OR)
+ * Added specific clearing options for CLI clear-cache command
+ * Moved environment method to URI so it can be accessible in plugins and themes
+ * Set Grav's output variable to public so it can be manipulated in onOutputGenerated event
+ * Updated vendor libraries to latest versions
+ * Better handing of 'home' in active menu state detection
+ * Various PSR code tidying
+ * Improved some error messages and notices
+3. [](#bugfix)
+ * Force route rebuild when configuration changes
+ * Fix for 'installed undefined' error in CLI versions command
+ * Do not remove the JSON/Text error handlers
+ * Fix for supporting inline JS and CSS when Asset pipeline enabled
+ * Fix for Data URLs in CSS being badly formed
+ * Fix Markdown links with fragment and query elements
+
# v0.9.4 beta
## 10/29/2014
diff --git a/composer.json b/composer.json
index 70ad4cbc66..236f322578 100644
--- a/composer.json
+++ b/composer.json
@@ -27,10 +27,6 @@
{
"type": "vcs",
"url": "https://github.com/rockettheme/toolbox"
- },
- {
- "type": "vcs",
- "url": "https://github.com/rhukster/minify"
}
],
"autoload": {
diff --git a/system/defines.php b/system/defines.php
index 51b2203f2a..8e7b035ef3 100644
--- a/system/defines.php
+++ b/system/defines.php
@@ -2,7 +2,7 @@
// Some standard defines
define('GRAV', true);
-define('GRAV_VERSION', '0.9.4');
+define('GRAV_VERSION', '0.9.5');
define('DS', '/');
// Directories and Paths
diff --git a/system/src/Grav/Common/Assets.php b/system/src/Grav/Common/Assets.php
index c89a6282fb..4f332ab361 100644
--- a/system/src/Grav/Common/Assets.php
+++ b/system/src/Grav/Common/Assets.php
@@ -338,12 +338,10 @@ public function css($attributes = [])
foreach ($this->css_no_pipeline as $file) {
$output .= ''."\n";
}
- return $output;
- }
-
-
- foreach($this->css as $file) {
- $output .= '' . "\n";
+ } else {
+ foreach($this->css as $file) {
+ $output .= '' . "\n";
+ }
}
// Render Inline CSS
@@ -387,12 +385,10 @@ public function js($attributes = [])
foreach ($this->js_no_pipeline as $file) {
$output .= ''."\n";
}
- return $output;
- }
-
-
- foreach($this->js as $file) {
- $output .= '' . "\n";
+ } else {
+ foreach($this->js as $file) {
+ $output .= '' . "\n";
+ }
}
// Render Inline JS
@@ -632,6 +628,10 @@ protected function cssRewrite($file, $relative_path)
function($matches) use ($relative_path) {
$old_url = $matches[1];
+
+ // ensure this is not a data url
+ if (strpos($old_url, 'data:') === 0) return $matches[0];
+
$newpath = array();
$paths = explode('/', $old_url);
diff --git a/system/src/Grav/Common/Errors/Errors.php b/system/src/Grav/Common/Errors/Errors.php
index 591eba2b2d..57dfbd85a4 100644
--- a/system/src/Grav/Common/Errors/Errors.php
+++ b/system/src/Grav/Common/Errors/Errors.php
@@ -45,8 +45,6 @@ public function resetHandlers()
$config = $grav['config']->get('system.errors');
if (isset($config['display']) && !$config['display']) {
unset($this->handlerStack['pretty']);
- unset($this->handlerStack['text']);
- unset($this->handlerStack['json']);
$this->handlerStack = array('simple' => new SimplePageHandler()) + $this->handlerStack;
}
if (isset($config['log']) && !$config['log']) {
diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php
index 35c8f6b1fc..8ed8c499dd 100644
--- a/system/src/Grav/Common/Grav.php
+++ b/system/src/Grav/Common/Grav.php
@@ -25,7 +25,7 @@ class Grav extends Container
/**
* @var string
*/
- protected $output;
+ public $output;
/**
* @var static
@@ -112,7 +112,7 @@ protected static function load(array $values)
$medium = $media[$media_file];
// loop through actions for the image and call them
- foreach ($c['uri']->query(null,true) as $action => $params) {
+ foreach ($c['uri']->query(null, true) as $action => $params) {
if (in_array($action, Medium::$valid_actions)) {
call_user_func_array(array(&$medium, $action), explode(',', $params));
}
@@ -294,7 +294,7 @@ public function fireEvent($eventName, Event $event = null)
*/
public function shutdown()
{
- if($this['config']->get('system.debugger.shutdown.close_connection')) {
+ if ($this['config']->get('system.debugger.shutdown.close_connection')) {
set_time_limit(0);
ignore_user_abort(true);
diff --git a/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php b/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php
index 7ac0b20002..1357c686bf 100644
--- a/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php
+++ b/system/src/Grav/Common/Markdown/MarkdownGravLinkTrait.php
@@ -33,7 +33,7 @@ protected function identifyLink($Excerpt)
if (!isset($url['host']) && isset($url['path'])) {
// convert the URl is required
- $Excerpt['element']['attributes']['href'] = $this->convertUrl($url['path']);
+ $Excerpt['element']['attributes']['href'] = $this->convertUrl(Uri::build_url($url));
}
}
diff --git a/system/src/Grav/Common/Page/Medium.php b/system/src/Grav/Common/Page/Medium.php
index bbee389c7c..f98c0d2c33 100644
--- a/system/src/Grav/Common/Page/Medium.php
+++ b/system/src/Grav/Common/Page/Medium.php
@@ -114,6 +114,16 @@ public function path()
return $output;
}
+ /**
+ * Sets the quality of the image
+ * @param Int $quality 0-100 quality
+ * @return Medium
+ */
+ public function quality($quality) {
+ $this->quality = $quality;
+ return $this;
+ }
+
/**
* Return URL to file.
*
@@ -149,6 +159,7 @@ public function format($type = null, $quality = 80)
$this->type = $type;
$this->quality = $quality;
+ return $this;
}
/**
diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php
index c99e51f845..6a49b0a563 100644
--- a/system/src/Grav/Common/Page/Page.php
+++ b/system/src/Grav/Common/Page/Page.php
@@ -358,11 +358,34 @@ public function content($var = null)
$this->content = $content;
+ // Process any post-processing but pre-caching functionality
+ self::$grav->fireEvent('onPageContentProcessed', new Event(['page' => $this]));
+
}
return $this->content;
}
+ /**
+ * Needed by the onPageContentProcessed event to get the raw page content
+ *
+ * @return string the current page content
+ */
+ public function getRawContent()
+ {
+ return $this->content;
+ }
+
+ /**
+ * Needed by the onPageContentProcessed event to set the raw page content
+ *
+ * @param $content
+ */
+ public function setRawContent($content)
+ {
+ $this->content = $content;
+ }
+
/**
* Get value from a page variable (used mostly for creating edit forms).
*
@@ -1326,10 +1349,21 @@ public function activeChild()
{
/** @var Uri $uri */
$uri = self::$grav['uri'];
+ $config = self::$grav['config'];
- if (!$this->home() && (strpos($uri->url(), $this->url()) === 0)) {
- return true;
+ // Special check when item is home
+ if ($this->home()) {
+ $paths = $uri->paths();
+ $home = ltrim($config->get('system.home.alias'), '/');
+ if ($paths[0] == $home) {
+ return true;
+ }
+ } else {
+ if (strpos($uri->url(), $this->url()) === 0) {
+ return true;
+ }
}
+
return false;
}
@@ -1418,8 +1452,6 @@ public function collection($params = 'content')
}
}
}
-
- $config->set('system.cache.enabled', false); // TODO: Do we still need this?
}
}
// TODO: END OF MOVE
diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php
index 23e30792f8..9b58304e6a 100644
--- a/system/src/Grav/Common/Page/Pages.php
+++ b/system/src/Grav/Common/Page/Pages.php
@@ -206,7 +206,9 @@ public function sortCollection(Collection $collection, $orderBy, $orderDir = 'as
*/
public function get($path)
{
- if (!is_null($path) && !is_string($path)) throw new \Exception();
+ if (!is_null($path) && !is_string($path)) {
+ throw new \Exception();
+ }
return isset($this->instances[(string) $path]) ? $this->instances[(string) $path] : null;
}
@@ -319,7 +321,7 @@ public function getList(Page $current = null, $level = 0)
*
* @return Types
*/
- static public function getTypes()
+ public static function getTypes()
{
if (!self::$types) {
self::$types = new Types();
@@ -339,7 +341,7 @@ static public function getTypes()
*
* @return array
*/
- static public function types()
+ public static function types()
{
$types = self::getTypes();
@@ -351,7 +353,7 @@ static public function types()
*
* @return array
*/
- static public function modularTypes()
+ public static function modularTypes()
{
$types = self::getTypes();
@@ -363,7 +365,7 @@ static public function modularTypes()
*
* @return array
*/
- static public function parents()
+ public static function parents()
{
$grav = Grav::instance();
@@ -404,10 +406,11 @@ protected function buildPages()
$last_modified = Folder::lastModifiedFile(PAGES_DIR);
}
- $page_cache_id = md5(USER_DIR.$last_modified);
+ $page_cache_id = md5(USER_DIR.$last_modified.$config->checksum());
list($this->instances, $this->routes, $this->children, $taxonomy_map, $this->sort) = $cache->fetch($page_cache_id);
if (!$this->instances) {
+ $this->grav['debugger']->addMessage('Page cache missed, rebuilding pages..');
$this->recurse();
$this->buildRoutes();
@@ -418,6 +421,7 @@ protected function buildPages()
);
} else {
// If pages was found in cache, set the taxonomy
+ $this->grav['debugger']->addMessage('Page cache hit.');
$taxonomy->taxonomy($taxonomy_map);
}
} else {
@@ -445,7 +449,9 @@ protected function recurse($directory = PAGES_DIR, Page &$parent = null)
$config = $this->grav['config'];
$page->path($directory);
- if ($parent) $page->parent($parent);
+ if ($parent) {
+ $page->parent($parent);
+ }
$page->orderDir($config->get('system.pages.order.dir'));
$page->orderBy($config->get('system.pages.order.by'));
@@ -608,7 +614,7 @@ protected function buildSort($path, array $pages, $order_by = 'default', $manual
// handle special case when order_by is random
if ($order_by == 'random') {
- $list = $this->array_shuffle($list);
+ $list = $this->arrayShuffle($list);
} else {
// else just sort the list according to specified key
asort($list);
@@ -643,12 +649,13 @@ protected function buildSort($path, array $pages, $order_by = 'default', $manual
}
// Shuffles and associative array
- protected function array_shuffle($list) {
+ protected function arrayShuffle($list)
+ {
$keys = array_keys($list);
shuffle($keys);
$new = array();
- foreach($keys as $key) {
+ foreach ($keys as $key) {
$new[$key] = $list[$key];
}
diff --git a/system/src/Grav/Common/Service/ConfigServiceProvider.php b/system/src/Grav/Common/Service/ConfigServiceProvider.php
index a2885876f0..0945ce038c 100644
--- a/system/src/Grav/Common/Service/ConfigServiceProvider.php
+++ b/system/src/Grav/Common/Service/ConfigServiceProvider.php
@@ -3,6 +3,7 @@
use Grav\Common\Config\Config;
use Grav\Common\Grav;
+use Grav\Common\Uri;
use Grav\Common\Filesystem\Folder;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
@@ -33,7 +34,7 @@ public function register(Container $container)
public function loadMasterConfig(Container $container)
{
- $environment = $this->getEnvironment();
+ $environment = $this->getEnvironment($container);
$file = CACHE_DIR . 'compiled/config/master-'.$environment.'.php';
$data = is_file($file) ? (array) include $file : [];
if ($data) {
@@ -54,25 +55,17 @@ public function loadMasterConfig(Container $container)
public function loadMasterBlueprints(Container $container)
{
- $environment = $this->getEnvironment();
+ $environment = $this->getEnvironment($container);
$file = CACHE_DIR . 'compiled/blueprints/master-'.$environment.'.php';
$data = is_file($file) ? (array) include $file : [];
return new Blueprints($data, $container);
}
- public function getEnvironment()
+ public function getEnvironment(Container $container)
{
- if (!$this->environment) {
- $address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '::1';
-
- // check for localhost variations
- if ($address == '::1' || $address == '127.0.0.1') {
- $hostname = 'localhost';
- } else {
- $hostname = gethostname();
- }
- $this->environment = $hostname;
+ if (!isset($this->environment)) {
+ $this->environment = $container['uri']->environment();
}
return $this->environment;
diff --git a/system/src/Grav/Common/Taxonomy.php b/system/src/Grav/Common/Taxonomy.php
index 1224cbee2d..6ea5a35912 100644
--- a/system/src/Grav/Common/Taxonomy.php
+++ b/system/src/Grav/Common/Taxonomy.php
@@ -71,20 +71,33 @@ public function addTaxonomy(Page $page, $page_taxonomy = null)
* particular taxonomy.
*
* @param array $taxonomies taxonomies to search, eg ['tag'=>['animal','cat']]
- * @return Page page object with sub-pages set to contain matches found in the taxonomy map
+ * @param string $operator can be 'or' or 'and' (defaults to 'or')
+ * @return Colleciton Collection object set to contain matches found in the taxonomy map
*/
- public function findTaxonomy($taxonomies)
+ public function findTaxonomy($taxonomies, $operator = 'and')
{
- $results = array();
+ $matches = [];
+ $results = [];
foreach ((array)$taxonomies as $taxonomy => $items) {
foreach ((array) $items as $item) {
if (isset($this->taxonomy_map[$taxonomy][$item])) {
- $results = array_merge($results, $this->taxonomy_map[$taxonomy][$item]);
+ $matches[] = $this->taxonomy_map[$taxonomy][$item];
}
}
}
+ if (strtolower($operator) == 'or') {
+ foreach ($matches as $match) {
+ $results = array_merge($results, $match);
+ }
+ } else {
+ $results = $matches ? array_pop($matches) : [];
+ foreach ($matches as $match) {
+ $results = array_intersect_key($results, $match);
+ }
+ }
+
return new Collection($results, ['taxonomies' => $taxonomies]);
}
diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php
index eb580889c4..f5648391c5 100644
--- a/system/src/Grav/Common/Themes.php
+++ b/system/src/Grav/Common/Themes.php
@@ -37,7 +37,12 @@ public function init()
/** @var Themes $themes */
$themes = $this->grav['themes'];
$themes->configure();
- $instance = $themes->load();
+
+ try {
+ $instance = $themes->load();
+ } catch (\InvalidArgumentException $e) {
+ throw new \RuntimeException($this->current(). ' theme could not be found');
+ }
if ($instance instanceof EventSubscriberInterface) {
$events->addSubscriber($instance);
diff --git a/system/src/Grav/Common/Twig.php b/system/src/Grav/Common/Twig.php
index d10636f8e6..acdf04bd02 100644
--- a/system/src/Grav/Common/Twig.php
+++ b/system/src/Grav/Common/Twig.php
@@ -240,7 +240,7 @@ public function processSite($format = null)
try {
$output = $this->twig->render($template, $twig_vars);
} catch (\Twig_Error_Loader $e) {
- throw new \RuntimeException('Twig template not found: '.$template, 404, $e);
+ throw new \RuntimeException($e->getRawMessage(), 404, $e);
}
return $output;
diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php
index 3e914334d9..4dbdb14d0e 100644
--- a/system/src/Grav/Common/Uri.php
+++ b/system/src/Grav/Common/Uri.php
@@ -9,6 +9,8 @@
*/
class Uri
{
+ public $url;
+
protected $base;
protected $root;
protected $bits;
@@ -17,7 +19,6 @@ class Uri
protected $content_path;
protected $path;
protected $paths;
- protected $url;
protected $query;
protected $params;
@@ -50,6 +51,16 @@ public function __construct()
$root_path = substr($uri, 0, strpos($uri, '/', 1)) . $root_path;
}
+ // set hostname
+ $address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '::1';
+
+ // check for localhost variations
+ if ($address == '::1' || $address == '127.0.0.1') {
+ $this->host = 'localhost';
+ } else {
+ $this->host = gethostname();
+ }
+
$this->base = $base;
$this->root = $base . $root_path;
$this->url = $base . $uri;
@@ -120,7 +131,7 @@ public function paths($id = null)
if (isset($id)) {
return $this->paths[$id];
} else {
- return implode('/', $this->paths);
+ return $this->paths;
}
}
@@ -213,7 +224,8 @@ public function url($include_host = false)
*
* @return String The path of the URI
*/
- public function path() {
+ public function path()
+ {
return $this->path;
}
@@ -222,7 +234,8 @@ public function path() {
*
* @return String The extension of the URI
*/
- public function extension($default = null) {
+ public function extension($default = null)
+ {
if (!$this->extension) {
$this->extension = $default;
}
@@ -234,16 +247,28 @@ public function extension($default = null) {
*
* @return String The host of the URI
*/
- public function host() {
+ public function host()
+ {
return $this->host;
}
+ /**
+ * Gets the environment name
+ *
+ * @return String
+ */
+ public function environment()
+ {
+ return $this->host();
+ }
+
/**
* Return the base of the URI
*
* @return String The base of the URI
*/
- public function base() {
+ public function base()
+ {
return $this->base;
}
@@ -340,7 +365,8 @@ public function ip()
* @param $parsed_url
* @return string
*/
- public static function build_url($parsed_url) {
+ public static function build_url($parsed_url)
+ {
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
$host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
$port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
diff --git a/system/src/Grav/Console/Cli/ClearCacheCommand.php b/system/src/Grav/Console/Cli/ClearCacheCommand.php
index aaad55c9a2..148d24634d 100644
--- a/system/src/Grav/Console/Cli/ClearCacheCommand.php
+++ b/system/src/Grav/Console/Cli/ClearCacheCommand.php
@@ -17,9 +17,6 @@
class ClearCacheCommand extends Command
{
- /**
- * @var array
- */
protected $standard_remove = [
'cache/twig/',
'cache/doctrine/',
@@ -29,15 +26,24 @@ class ClearCacheCommand extends Command
'assets/',
];
- /**
- * @var array
- */
protected $all_remove = [
'cache/',
'images/',
'assets/'
];
+ protected $assets_remove = [
+ 'assets/'
+ ];
+
+ protected $images_remove = [
+ 'images/'
+ ];
+
+ protected $cache_remove = [
+ 'cache/'
+ ];
+
/**
*
*/
@@ -46,7 +52,10 @@ protected function configure()
$this
->setName("clear-cache")
->setDescription("Clears Grav cache")
- ->addOption('all', null, InputOption::VALUE_NONE, 'If set will remove all')
+ ->addOption('all', null, InputOption::VALUE_NONE, 'If set will remove all including compiled, twig, doctrine caches')
+ ->addOption('assets-only', null, InputOption::VALUE_NONE, 'If set will remove only assets/*')
+ ->addOption('images-only', null, InputOption::VALUE_NONE, 'If set will remove only images/*')
+ ->addOption('cache-only', null, InputOption::VALUE_NONE, 'If set will remove only cache/*')
->setHelp('The clear-cache deletes all cache files');
}
@@ -84,6 +93,12 @@ private function cleanPaths(InputInterface $input, OutputInterface $output)
if ($input->getOption('all')) {
$remove_paths = $this->all_remove;
+ } elseif ($input->getOption('assets-only')) {
+ $remove_paths = $this->assets_remove;
+ } elseif ($input->getOption('images-only')) {
+ $remove_paths = $this->images_remove;
+ } elseif ($input->getOption('cache-only')) {
+ $remove_paths = $this->cache_remove;
} else {
$remove_paths = $this->standard_remove;
}
diff --git a/system/src/Grav/Console/Gpm/VersionCommand.php b/system/src/Grav/Console/Gpm/VersionCommand.php
index 8840423d24..c1068d8ab2 100644
--- a/system/src/Grav/Console/Gpm/VersionCommand.php
+++ b/system/src/Grav/Console/Gpm/VersionCommand.php
@@ -58,6 +58,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->gpm = new GPM($this->input->getOption('force'));
$packages = $this->input->getArgument('package');
+ $installed = false;
+
if (!count($packages)) {
$packages = ['grav'];
}