mirror of
https://github.com/getgrav/grav.git
synced 2026-03-05 20:11:50 +01:00
Merge branch 'release/0.9.40'
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
# Composer
|
||||
composer.lock
|
||||
.composer
|
||||
vendor/
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ RewriteRule .* index.php [L]
|
||||
|
||||
## Begin - Security
|
||||
# Block all direct access for these folders
|
||||
RewriteRule ^(cache|bin|logs|backup)/(.*) error [L]
|
||||
RewriteRule ^(.git|cache|bin|logs|backup)/(.*) error [L]
|
||||
# Block access to specific file types for these folders
|
||||
RewriteRule ^(system|user|vendor)/(.*)\.(txt|md|html|yaml|php|twig|sh|bat)$ error [L]
|
||||
## End - Security
|
||||
|
||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,3 +1,19 @@
|
||||
# v0.9.40
|
||||
## 08/31/2015
|
||||
|
||||
1. [](#new)
|
||||
* Added some new Twig filers: `defined`, `rtrim`, `ltrim`
|
||||
* Admin support for customizable page file name + template override
|
||||
1. [](#improved)
|
||||
* Better message for incompatible/unsupported Twig template
|
||||
* Improved User blueprints with better help
|
||||
* Switched to composer **install** rather than **update** by default
|
||||
* Admin autofocus on page title
|
||||
* `.htaccess` hardening (`.htaccess` & `htaccess.txt`)
|
||||
* Cache safety checks for missing folders
|
||||
1. [](#bugfix)
|
||||
* Fixed issue with unescaped `o` character in date formats
|
||||
|
||||
# v0.9.39
|
||||
## 08/25/2015
|
||||
|
||||
|
||||
1012
composer.lock
generated
Normal file
1012
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,7 @@ RewriteRule .* index.php [L]
|
||||
|
||||
## Begin - Security
|
||||
# Block all direct access for these folders
|
||||
RewriteRule ^(cache|bin|logs)/(.*) error [L]
|
||||
RewriteRule ^(.git|cache|bin|logs|backup)/(.*) error [L]
|
||||
# Block access to specific file types for these folders
|
||||
RewriteRule ^(system|user|vendor)/(.*)\.(txt|md|html|yaml|php|twig|sh|bat)$ error [L]
|
||||
## End - Security
|
||||
|
||||
@@ -60,9 +60,9 @@ form:
|
||||
label: PLUGIN_ADMIN.SUMMARY_SIZE
|
||||
help: PLUGIN_ADMIN.SUMMARY_SIZE_HELP
|
||||
validate:
|
||||
type: int
|
||||
min: 0
|
||||
max: 65536
|
||||
type: int
|
||||
min: 0
|
||||
max: 65536
|
||||
|
||||
summary.format:
|
||||
type: toggle
|
||||
|
||||
@@ -58,7 +58,7 @@ form:
|
||||
default: "jS M Y"
|
||||
options:
|
||||
"F jS \\a\\t g:ia": Date1
|
||||
"l jS of F g:i A": Date2
|
||||
"l jS \\of F g:i A": Date2
|
||||
"D, m M Y G:i:s": Date3
|
||||
"d-m-y G:i": Date4
|
||||
"jS M Y": Date5
|
||||
@@ -71,14 +71,14 @@ form:
|
||||
help: PLUGIN_ADMIN.LONG_DATE_FORMAT_HELP
|
||||
options:
|
||||
"F jS \\a\\t g:ia": Date1
|
||||
"l jS of F g:i A": Date2
|
||||
"l jS \\of F g:i A": Date2
|
||||
"D, m M Y G:i:s": Date3
|
||||
"d-m-y G:i": Date4
|
||||
"jS M Y": Date5
|
||||
|
||||
pages.order.by:
|
||||
type: select
|
||||
size: medium
|
||||
size: long
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.DEFAULT_ORDERING
|
||||
help: PLUGIN_ADMIN.DEFAULT_ORDERING_HELP
|
||||
@@ -324,7 +324,7 @@ form:
|
||||
size: small
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.CACHE_CHECK_METHOD
|
||||
help: PLUGIN_ADMIN.CACHE_CHECK_METHOD
|
||||
help: PLUGIN_ADMIN.CACHE_CHECK_METHOD_HELP
|
||||
options:
|
||||
file: File
|
||||
folder: Folder
|
||||
|
||||
@@ -23,6 +23,7 @@ form:
|
||||
fields:
|
||||
header.title:
|
||||
type: text
|
||||
autofocus: true
|
||||
style: vertical
|
||||
label: PLUGIN_ADMIN.TITLE
|
||||
|
||||
@@ -144,10 +145,11 @@ form:
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
|
||||
type:
|
||||
type: templates
|
||||
name:
|
||||
type: select
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
|
||||
label: PLUGIN_ADMIN.PAGE_FILE
|
||||
help: PLUGIN_ADMIN.PAGE_FILE_HELP
|
||||
default: default
|
||||
@data-options: '\Grav\Common\Page\Pages::types'
|
||||
|
||||
@@ -248,6 +250,14 @@ form:
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
header.template:
|
||||
type: select
|
||||
toggleable: true
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
|
||||
default: default
|
||||
@data-options: '\Grav\Common\Page\Pages::types'
|
||||
|
||||
header.order_by:
|
||||
type: hidden
|
||||
|
||||
|
||||
@@ -36,10 +36,11 @@ form:
|
||||
validate:
|
||||
required: true
|
||||
|
||||
type:
|
||||
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:
|
||||
|
||||
@@ -76,7 +76,7 @@ form:
|
||||
validate:
|
||||
required: true
|
||||
|
||||
type:
|
||||
name:
|
||||
type: select
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.MODULAR_TEMPLATE
|
||||
|
||||
@@ -38,11 +38,11 @@ form:
|
||||
validate:
|
||||
required: true
|
||||
|
||||
type:
|
||||
name:
|
||||
type: select
|
||||
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
|
||||
help: PLUGIN_ADMIN.DISPLAY_TEMPLATE_HELP
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.PAGE_FILE
|
||||
help: PLUGIN_ADMIN.PAGE_FILE_HELP
|
||||
default: default
|
||||
@data-options: '\Grav\Common\Page\Pages::types'
|
||||
validate:
|
||||
|
||||
@@ -73,7 +73,7 @@ form:
|
||||
options:
|
||||
'/': PLUGIN_ADMIN.DEFAULT_OPTION_ROOT
|
||||
|
||||
type:
|
||||
name:
|
||||
type: select
|
||||
classes: fancy
|
||||
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
|
||||
|
||||
@@ -11,5 +11,6 @@ form:
|
||||
username:
|
||||
type: text
|
||||
label: PLUGIN_ADMIN.USERNAME
|
||||
help: PLUGIN_ADMIN.USERNAME_HELP
|
||||
validate:
|
||||
required: true
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '0.9.39');
|
||||
define('GRAV_VERSION', '0.9.40');
|
||||
define('DS', '/');
|
||||
|
||||
// Directories and Paths
|
||||
|
||||
@@ -239,19 +239,20 @@ class Cache extends Getters
|
||||
$anything = false;
|
||||
$files = glob(ROOT_DIR . $path . '*');
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
if (@unlink($file)) {
|
||||
$anything = true;
|
||||
}
|
||||
} elseif (is_dir($file)) {
|
||||
if (@Folder::delete($file)) {
|
||||
$anything = true;
|
||||
if (is_array($files)) {
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
if (@unlink($file)) {
|
||||
$anything = true;
|
||||
}
|
||||
} elseif (is_dir($file)) {
|
||||
if (@Folder::delete($file)) {
|
||||
$anything = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($anything) {
|
||||
$output[] = '<red>Cleared: </red>' . $path . '*';
|
||||
}
|
||||
|
||||
@@ -48,4 +48,5 @@ h6 {
|
||||
|
||||
code {
|
||||
font-weight: bold;
|
||||
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
<header>
|
||||
Server Error
|
||||
</header>
|
||||
<p>We're sorry! The server has encountered an internal error and was unable to complete your request.
|
||||
Please contact the system administrator for more information.</p>
|
||||
<h6>For further details please review your <code>logs/</code> folder, or enable displaying of errors in your system configuration.</h6>
|
||||
<h6>Error Code: <b><?php echo $code ?></b></h6>
|
||||
|
||||
|
||||
|
||||
<p>Sorry, something went terribly wrong!</p>
|
||||
|
||||
<h3><?php echo $code ?> - <?php echo $message ?></h3>
|
||||
|
||||
<h5>For further details please review your <code>logs/</code> folder, or enable displaying of errors in your system configuration.</h5>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -28,6 +28,7 @@ class SimplePageHandler extends Handler
|
||||
$cssFile = $this->getResource("error.css");
|
||||
|
||||
$code = $inspector->getException()->getCode();
|
||||
$message = $inspector->getException()->getMessage();
|
||||
|
||||
if ($inspector->getException() instanceof \ErrorException) {
|
||||
$code = Misc::translateErrorCode($code);
|
||||
@@ -36,6 +37,7 @@ class SimplePageHandler extends Handler
|
||||
$vars = array(
|
||||
"stylesheet" => file_get_contents($cssFile),
|
||||
"code" => $code,
|
||||
"message" => $message,
|
||||
);
|
||||
|
||||
$helper->setVariables($vars);
|
||||
|
||||
@@ -623,8 +623,12 @@ class Page
|
||||
$regex = '/^[0-9]+\./u';
|
||||
return preg_replace($regex, '', $this->folder);
|
||||
}
|
||||
if ($name == 'type') {
|
||||
return $this->template();
|
||||
if ($name == 'name') {
|
||||
$name_val = str_replace('.md', '', $this->name());
|
||||
if ($this->modular()) {
|
||||
return 'modular/' . $name_val;
|
||||
}
|
||||
return $name_val;
|
||||
}
|
||||
if ($name == 'media') {
|
||||
return $this->media()->all();
|
||||
@@ -1657,7 +1661,10 @@ class Page
|
||||
public function isFirst()
|
||||
{
|
||||
$collection = $this->parent()->collection('content', false);
|
||||
return $collection->isFirst($this->path());
|
||||
if ($collection instanceof Collection) {
|
||||
return $collection->isFirst($this->path());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1668,7 +1675,10 @@ class Page
|
||||
public function isLast()
|
||||
{
|
||||
$collection = $this->parent()->collection('content', false);
|
||||
return $collection->isLast($this->path());
|
||||
if ($collection instanceof Collection) {
|
||||
return $collection->isLast($this->path());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1700,7 +1710,10 @@ class Page
|
||||
public function adjacentSibling($direction = 1)
|
||||
{
|
||||
$collection = $this->parent()->collection('content', false);
|
||||
return $collection->adjacentSibling($this->path(), $direction);
|
||||
if ($collection instanceof Collection) {
|
||||
return $collection->adjacentSibling($this->path(), $direction);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1737,7 +1750,7 @@ class Page
|
||||
|
||||
if (isset($routes[$uri_path])) {
|
||||
$child_page = $pages->dispatch($uri->route())->parent();
|
||||
while (!$child_page->root()) {
|
||||
if ($child_page) while (!$child_page->root()) {
|
||||
if ($this->path() == $child_page->path()) {
|
||||
return true;
|
||||
}
|
||||
@@ -1830,7 +1843,7 @@ class Page
|
||||
}
|
||||
foreach ($items as $item) {
|
||||
if (empty($page->taxonomy[$taxonomy])
|
||||
|| !in_array($item, $page->taxonomy[$taxonomy])) {
|
||||
|| !in_array(htmlspecialchars_decode($item, ENT_QUOTES), $page->taxonomy[$taxonomy])) {
|
||||
$collection->remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Grav\Common\Twig;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Page\Page;
|
||||
use Grav\Common\Inflector;
|
||||
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
|
||||
/**
|
||||
@@ -303,6 +304,7 @@ class Twig
|
||||
$pages = $this->grav['pages'];
|
||||
$page = $this->grav['page'];
|
||||
$content = $page->content();
|
||||
$config = $this->grav['config'];
|
||||
|
||||
$twig_vars = $this->twig_vars;
|
||||
|
||||
@@ -325,14 +327,16 @@ class Twig
|
||||
$output = $this->twig->render($template, $twig_vars);
|
||||
} catch (\Twig_Error_Loader $e) {
|
||||
// If loader error, and not .html.twig, try it as fallback
|
||||
$inflector = new Inflector();
|
||||
$error_msg = 'The template file for this page: "' . $page->template().'.html'.TWIG_EXT.'" is not provided by the theme: "'. $inflector->titleize($config->get('system.pages.theme')) .'"';
|
||||
if ($ext != '.html'.TWIG_EXT) {
|
||||
try {
|
||||
$output = $this->twig->render($page->template().'.html'.TWIG_EXT, $twig_vars);
|
||||
} catch (\Twig_Error_Loader $e) {
|
||||
throw new \RuntimeException($e->getRawMessage(), 404, $e);
|
||||
throw new \RuntimeException($error_msg, 400, $e);
|
||||
}
|
||||
} else {
|
||||
throw new \RuntimeException($e->getRawMessage(), 404, $e);
|
||||
throw new \RuntimeException($error_msg, 400, $e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,12 @@ class TwigExtension extends \Twig_Extension
|
||||
new \Twig_SimpleFilter('ksort', [$this,'ksortFilter']),
|
||||
new \Twig_SimpleFilter('contains', [$this, 'containsFilter']),
|
||||
new \Twig_SimpleFilter('nicetime', [$this, 'nicetimeFilter']),
|
||||
new \Twig_SimpleFilter('defined', [$this, 'definedDefaultFilter']),
|
||||
new \Twig_SimpleFilter('absolute_url', [$this, 'absoluteUrlFilter']),
|
||||
new \Twig_SimpleFilter('markdown', [$this, 'markdownFilter']),
|
||||
new \Twig_SimpleFilter('starts_with', [$this, 'startsWithFilter']),
|
||||
new \Twig_SimpleFilter('rtrim', [$this, 'rtrimFilter']),
|
||||
new \Twig_SimpleFilter('ltrim', [$this, 'ltrimFilter']),
|
||||
new \Twig_SimpleFilter('ends_with', [$this, 'endsWithFilter']),
|
||||
new \Twig_SimpleFilter('t', [$this, 'translate']),
|
||||
new \Twig_SimpleFilter('ta', [$this, 'translateArray'])
|
||||
@@ -370,6 +373,25 @@ class TwigExtension extends \Twig_Extension
|
||||
return Utils::endsWith($haystack, $needle);
|
||||
}
|
||||
|
||||
public function definedDefaultFilter($value, $default = null)
|
||||
{
|
||||
if (isset($value)) {
|
||||
return $value;
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
public function rtrimFilter($value, $chars = null)
|
||||
{
|
||||
return rtrim($value, $chars);
|
||||
}
|
||||
|
||||
public function ltrimFilter($value, $chars = null)
|
||||
{
|
||||
return ltrim($value, $chars);
|
||||
}
|
||||
|
||||
public function translate()
|
||||
{
|
||||
return $this->grav['language']->translate(func_get_args());
|
||||
@@ -381,6 +403,8 @@ class TwigExtension extends \Twig_Extension
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Repeat given string x times.
|
||||
*
|
||||
|
||||
@@ -54,8 +54,8 @@ class ComposerCommand extends Command
|
||||
InputOption::VALUE_NONE,
|
||||
'update the dependencies'
|
||||
)
|
||||
->setDescription("Updates the composer vendordependencies needed by Grav.")
|
||||
->setHelp('The <info>composer</info> command updates the composer vendordependencies needed by Grav');
|
||||
->setDescription("Updates the composer vendor dependencies needed by Grav.")
|
||||
->setHelp('The <info>composer</info> command updates the composer vendor dependencies needed by Grav');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ class ComposerCommand extends Command
|
||||
{
|
||||
$this->setupConsole($input, $output);
|
||||
|
||||
$action = 'update';
|
||||
$action = $input->getOption('install') ? 'install' : ($input->getOption('update') ? 'update' : 'install');
|
||||
|
||||
if ($input->getOption('install')) {
|
||||
$action = 'install';
|
||||
|
||||
@@ -53,7 +53,7 @@ class NewUserCommand extends Command
|
||||
$question->setValidator(function ($value) {
|
||||
if (!preg_match('/^[a-z0-9_-]{3,16}$/', $value)) {
|
||||
throw new RuntimeException(
|
||||
'Username should be between 3 and 16 comprised of lowercase letters, numbers, underscores and hyphens'
|
||||
'Username should be between 3 and 16 characters, including lowercase letters, numbers, underscores, and hyphens. Uppercase letters, spaces, and special characters are not allowed'
|
||||
);
|
||||
}
|
||||
if (file_exists(self::getGrav()['locator']->findResource('user://accounts/' . $value . YAML_EXT))) {
|
||||
|
||||
Reference in New Issue
Block a user