mirror of
https://github.com/getgrav/grav.git
synced 2026-03-04 11:31:43 +01:00
Merge branch 'release/0.9.5'
This commit is contained in:
23
CHANGELOG.md
23
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
|
||||
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/rockettheme/toolbox"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/rhukster/minify"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -338,12 +338,10 @@ class Assets
|
||||
foreach ($this->css_no_pipeline as $file) {
|
||||
$output .= '<link href="'.$file['asset'].'"'.$attributes.' />'."\n";
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
foreach($this->css as $file) {
|
||||
$output .= '<link href="' . $file['asset'] . '"' . $attributes . ' />' . "\n";
|
||||
} else {
|
||||
foreach($this->css as $file) {
|
||||
$output .= '<link href="' . $file['asset'] . '"' . $attributes . ' />' . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Render Inline CSS
|
||||
@@ -387,12 +385,10 @@ class Assets
|
||||
foreach ($this->js_no_pipeline as $file) {
|
||||
$output .= '<script src="'.$file['asset'].'"'.$attributes.' ></script>'."\n";
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
foreach($this->js as $file) {
|
||||
$output .= '<script src="' . $file['asset'] . '"' . $attributes . ' ></script>' . "\n";
|
||||
} else {
|
||||
foreach($this->js as $file) {
|
||||
$output .= '<script src="' . $file['asset'] . '"' . $attributes . ' ></script>' . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Render Inline JS
|
||||
@@ -632,6 +628,10 @@ class Assets
|
||||
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);
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@ class Errors extends \Whoops\Run
|
||||
$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']) {
|
||||
|
||||
@@ -25,7 +25,7 @@ class Grav extends Container
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $output;
|
||||
public $output;
|
||||
|
||||
/**
|
||||
* @var static
|
||||
@@ -112,7 +112,7 @@ class Grav extends Container
|
||||
$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 @@ class Grav extends Container
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ trait MarkdownGravLinkTrait
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,16 @@ class Medium extends Data
|
||||
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 @@ class Medium extends Data
|
||||
|
||||
$this->type = $type;
|
||||
$this->quality = $quality;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -358,11 +358,34 @@ class Page
|
||||
|
||||
$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 @@ class Page
|
||||
{
|
||||
/** @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 @@ class Page
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$config->set('system.cache.enabled', false); // TODO: Do we still need this?
|
||||
}
|
||||
}
|
||||
// TODO: END OF MOVE
|
||||
|
||||
@@ -206,7 +206,9 @@ class Pages
|
||||
*/
|
||||
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 @@ class Pages
|
||||
*
|
||||
* @return Types
|
||||
*/
|
||||
static public function getTypes()
|
||||
public static function getTypes()
|
||||
{
|
||||
if (!self::$types) {
|
||||
self::$types = new Types();
|
||||
@@ -339,7 +341,7 @@ class Pages
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function types()
|
||||
public static function types()
|
||||
{
|
||||
$types = self::getTypes();
|
||||
|
||||
@@ -351,7 +353,7 @@ class Pages
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function modularTypes()
|
||||
public static function modularTypes()
|
||||
{
|
||||
$types = self::getTypes();
|
||||
|
||||
@@ -363,7 +365,7 @@ class Pages
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function parents()
|
||||
public static function parents()
|
||||
{
|
||||
$grav = Grav::instance();
|
||||
|
||||
@@ -404,10 +406,11 @@ class Pages
|
||||
$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 @@ class Pages
|
||||
);
|
||||
} 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 @@ class Pages
|
||||
$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 @@ class Pages
|
||||
|
||||
// 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 @@ class Pages
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace Grav\Common\Service;
|
||||
|
||||
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 @@ class ConfigServiceProvider implements ServiceProviderInterface
|
||||
|
||||
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 @@ class ConfigServiceProvider implements ServiceProviderInterface
|
||||
|
||||
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;
|
||||
|
||||
@@ -71,20 +71,33 @@ class Taxonomy
|
||||
* 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]);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,12 @@ class Themes extends Iterator
|
||||
/** @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);
|
||||
|
||||
@@ -240,7 +240,7 @@ class Twig
|
||||
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;
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace Grav\Common;
|
||||
*/
|
||||
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 @@ class Uri
|
||||
$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 @@ class Uri
|
||||
if (isset($id)) {
|
||||
return $this->paths[$id];
|
||||
} else {
|
||||
return implode('/', $this->paths);
|
||||
return $this->paths;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +224,8 @@ class Uri
|
||||
*
|
||||
* @return String The path of the URI
|
||||
*/
|
||||
public function path() {
|
||||
public function path()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
@@ -222,7 +234,8 @@ class Uri
|
||||
*
|
||||
* @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 @@ class Uri
|
||||
*
|
||||
* @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 @@ class Uri
|
||||
* @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'] : '';
|
||||
|
||||
@@ -17,9 +17,6 @@ use Symfony\Component\Yaml\Yaml;
|
||||
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 @@ class ClearCacheCommand extends Command
|
||||
$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 <info>clear-cache</info> deletes all cache files');
|
||||
}
|
||||
|
||||
@@ -84,6 +93,12 @@ class ClearCacheCommand extends Command
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ class VersionCommand extends Command
|
||||
$this->gpm = new GPM($this->input->getOption('force'));
|
||||
$packages = $this->input->getArgument('package');
|
||||
|
||||
$installed = false;
|
||||
|
||||
if (!count($packages)) {
|
||||
$packages = ['grav'];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user