Merge branch 'release/1.6.6'

This commit is contained in:
Andy Miller
2019-04-17 16:02:05 -06:00
12 changed files with 219 additions and 60 deletions

View File

@@ -1,3 +1,19 @@
# v1.6.6
## 04/17/2019
1. [](#new)
* `FormInterface` now implements `RenderInterface`
* Added new `FormInterface::getTask()` method which reads the task from `form.task` in the blueprint
1. [](#improved)
* Updated vendor libraries to latest
1. [](#bugfix)
* Rollback `redirect_default_route` logic as it has issues with multi-lang [#2459](https://github.com/getgrav/grav/issues/2459)
* Fix potential issue with `|contains` Twig filter on PHP 7.3
* Fixed bug in text field filtering: return empty string if value isn't a string or number [#2460](https://github.com/getgrav/grav/issues/2460)
* Force Asset `priority` to be an integer and not throw error if invalid string passed [#2461](https://github.com/getgrav/grav/issues/2461)
* Fixed bug in text field filtering: return empty string if value isn't a string or number
* Fixed `FlexForm` missing getter methods for defining form variables
# v1.6.5
## 04/15/2019

107
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "dce6e4d72c9b5ac769cd3d93fecdf1c2",
"content-hash": "a65d66d9ce6844a3743c992e74c1c55d",
"packages": [
{
"name": "antoligy/dom-string-iterators",
@@ -541,17 +541,17 @@
},
{
"name": "gregwar/image",
"version": "v2.0.24",
"version": "v2.0.25",
"target-dir": "Gregwar/Image",
"source": {
"type": "git",
"url": "https://github.com/Gregwar/Image.git",
"reference": "52145816255dd20cb4bb115d0f9e1030c6287994"
"reference": "03534d5760cbea5c96e6292041ff81a3bb205c36"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Gregwar/Image/zipball/52145816255dd20cb4bb115d0f9e1030c6287994",
"reference": "52145816255dd20cb4bb115d0f9e1030c6287994",
"url": "https://api.github.com/repos/Gregwar/Image/zipball/03534d5760cbea5c96e6292041ff81a3bb205c36",
"reference": "03534d5760cbea5c96e6292041ff81a3bb205c36",
"shasum": ""
},
"require": {
@@ -589,7 +589,7 @@
"gd",
"image"
],
"time": "2019-01-27T15:10:06+00:00"
"time": "2019-03-01T15:55:29+00:00"
},
{
"name": "guzzlehttp/psr7",
@@ -1774,16 +1774,16 @@
},
{
"name": "symfony/console",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "24206aff3efe6962593297e57ef697ebb220e384"
"reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/24206aff3efe6962593297e57ef697ebb220e384",
"reference": "24206aff3efe6962593297e57ef697ebb220e384",
"url": "https://api.github.com/repos/symfony/console/zipball/e2840bb38bddad7a0feaf85931e38fdcffdb2f81",
"reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81",
"shasum": ""
},
"require": {
@@ -1842,7 +1842,7 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2019-04-01T07:32:59+00:00"
"time": "2019-04-08T14:23:48+00:00"
},
{
"name": "symfony/contracts",
@@ -1914,16 +1914,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "ca5af306fbc37f3cf597e91bc9cfa0c7d3f33544"
"reference": "fbce53cd74ac509cbe74b6f227622650ab759b02"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ca5af306fbc37f3cf597e91bc9cfa0c7d3f33544",
"reference": "ca5af306fbc37f3cf597e91bc9cfa0c7d3f33544",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fbce53cd74ac509cbe74b6f227622650ab759b02",
"reference": "fbce53cd74ac509cbe74b6f227622650ab759b02",
"shasum": ""
},
"require": {
@@ -1974,7 +1974,7 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"time": "2019-03-30T15:58:42+00:00"
"time": "2019-04-06T13:51:08+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -2267,16 +2267,16 @@
},
{
"name": "symfony/process",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "1e6cbb41dadcaf29e0db034d6ad0d039a9df06e6"
"reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/1e6cbb41dadcaf29e0db034d6ad0d039a9df06e6",
"reference": "1e6cbb41dadcaf29e0db034d6ad0d039a9df06e6",
"url": "https://api.github.com/repos/symfony/process/zipball/8cf39fb4ccff793340c258ee7760fd40bfe745fe",
"reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe",
"shasum": ""
},
"require": {
@@ -2312,20 +2312,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2019-03-10T20:07:02+00:00"
"time": "2019-04-10T16:20:36+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "9f87189ac10b42edf7fb8edc846f1937c6d157cf"
"reference": "e760a38e12b15032325e64be63f7ffc1817af617"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/9f87189ac10b42edf7fb8edc846f1937c6d157cf",
"reference": "9f87189ac10b42edf7fb8edc846f1937c6d157cf",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/e760a38e12b15032325e64be63f7ffc1817af617",
"reference": "e760a38e12b15032325e64be63f7ffc1817af617",
"shasum": ""
},
"require": {
@@ -2388,11 +2388,11 @@
"debug",
"dump"
],
"time": "2019-02-23T15:17:42+00:00"
"time": "2019-04-17T14:57:01+00:00"
},
{
"name": "symfony/yaml",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
@@ -2451,16 +2451,16 @@
},
{
"name": "twig/twig",
"version": "v1.38.4",
"version": "v1.39.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "7732e9e7017d751313811bd118de61302e9c8b35"
"reference": "23e7b6f0cfa1d7ba3de69f30d8e05cf957412fec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/7732e9e7017d751313811bd118de61302e9c8b35",
"reference": "7732e9e7017d751313811bd118de61302e9c8b35",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/23e7b6f0cfa1d7ba3de69f30d8e05cf957412fec",
"reference": "23e7b6f0cfa1d7ba3de69f30d8e05cf957412fec",
"shasum": ""
},
"require": {
@@ -2475,7 +2475,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.38-dev"
"dev-master": "1.39-dev"
}
},
"autoload": {
@@ -2513,7 +2513,7 @@
"keywords": [
"templating"
],
"time": "2019-03-23T14:27:19+00:00"
"time": "2019-04-16T17:12:57+00:00"
},
{
"name": "willdurand/negotiation",
@@ -3172,16 +3172,16 @@
},
{
"name": "myclabs/deep-copy",
"version": "1.8.1",
"version": "1.9.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8"
"reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
"reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
"reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72",
"shasum": ""
},
"require": {
@@ -3216,7 +3216,7 @@
"object",
"object graph"
],
"time": "2018-06-11T23:09:50+00:00"
"time": "2019-04-07T13:18:21+00:00"
},
{
"name": "nette/bootstrap",
@@ -3416,7 +3416,7 @@
"homepage": "https://nette.org/contributors"
}
],
"description": "? Nette Finder: find files and directories with an intuitive API.",
"description": "🔍 Nette Finder: find files and directories with an intuitive API.",
"homepage": "https://nette.org",
"keywords": [
"filesystem",
@@ -3476,7 +3476,7 @@
"homepage": "https://nette.org/contributors"
}
],
"description": "? Nette NEON: encodes and decodes NEON file format.",
"description": "🍸 Nette NEON: encodes and decodes NEON file format.",
"homepage": "http://ne-on.org",
"keywords": [
"export",
@@ -5228,16 +5228,16 @@
},
{
"name": "symfony/browser-kit",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
"reference": "61d85c5af2fc058014c7c89504c3944e73a086f0"
"reference": "c09c18cca96d7067152f78956faf55346c338283"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/61d85c5af2fc058014c7c89504c3944e73a086f0",
"reference": "61d85c5af2fc058014c7c89504c3944e73a086f0",
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/c09c18cca96d7067152f78956faf55346c338283",
"reference": "c09c18cca96d7067152f78956faf55346c338283",
"shasum": ""
},
"require": {
@@ -5281,11 +5281,11 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
"time": "2019-02-23T15:17:42+00:00"
"time": "2019-04-07T09:56:43+00:00"
},
{
"name": "symfony/css-selector",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@@ -5338,7 +5338,7 @@
},
{
"name": "symfony/dom-crawler",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
@@ -5395,16 +5395,16 @@
},
{
"name": "symfony/finder",
"version": "v4.2.5",
"version": "v4.2.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a"
"reference": "e45135658bd6c14b61850bf131c4f09a55133f69"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/267b7002c1b70ea80db0833c3afe05f0fbde580a",
"reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a",
"url": "https://api.github.com/repos/symfony/finder/zipball/e45135658bd6c14b61850bf131c4f09a55133f69",
"reference": "e45135658bd6c14b61850bf131c4f09a55133f69",
"shasum": ""
},
"require": {
@@ -5440,7 +5440,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2019-02-23T15:42:05+00:00"
"time": "2019-04-06T13:51:08+00:00"
},
{
"name": "theseer/tokenizer",
@@ -5593,7 +5593,8 @@
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-curl": "*",
"ext-zip": "*"
"ext-zip": "*",
"ext-dom": "*"
},
"platform-dev": [],
"platform-overrides": {

View File

@@ -8,7 +8,7 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.6.5');
define('GRAV_VERSION', '1.6.6');
define('GRAV_TESTING', false);
define('DS', '/');

View File

@@ -78,6 +78,9 @@ abstract class BaseAsset extends PropertyObject
}
}
// Force priority to be an int
$this->priority = (int) $this->priority;
// Do some special stuff for CSS/JS (not inline)
if (!Utils::startsWith($this->getType(), 'inline')) {
$this->base_url = rtrim($uri->rootUrl($config->get('system.absolute_urls')), '/') . '/';

View File

@@ -154,6 +154,10 @@ class Validation
protected static function filterText($value, array $params, array $field)
{
if (!\is_string($value) && !is_numeric($value)) {
return '';
}
if (!empty($params['trim'])) {
$value = trim($value);
}

View File

@@ -80,8 +80,6 @@ class PagesServiceProvider implements ServiceProviderInterface
}
// Default route test and redirect
if ($config->get('system.pages.redirect_default_route') && $page->route() !== $path) {
$uri->setUriProperties(['path' => $page->route()]);
$url = $uri->toOriginalString();
$c->redirect($url);
}
}

View File

@@ -447,7 +447,11 @@ class TwigExtension extends \Twig_Extension implements \Twig_Extension_GlobalsIn
*/
public function containsFilter($haystack, $needle)
{
return (strpos($haystack, $needle) !== false);
if (empty($needle)) {
return $haystack;
}
return (strpos($haystack, (string) $needle) !== false);
}
/**

View File

@@ -168,6 +168,11 @@ class Flex implements \Countable
$keyFieldFind = 'storage_key';
foreach ($keys as $flexKey) {
if (!$flexKey) {
continue;
}
$flexKey = (string)$flexKey;
// Normalize key and type using fallback to default type if it was set.
[$key, $type, $guess] = $this->resolveKeyAndType($flexKey, $defaultType);

View File

@@ -12,11 +12,15 @@ namespace Grav\Framework\Flex;
use Grav\Common\Data\Blueprint;
use Grav\Common\Data\Data;
use Grav\Common\Grav;
use Grav\Common\Twig\Twig;
use Grav\Common\Utils;
use Grav\Framework\Flex\Interfaces\FlexFormInterface;
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
use Grav\Framework\Form\Traits\FormTrait;
use Grav\Framework\Route\Route;
use Twig\Error\LoaderError;
use Twig\Error\SyntaxError;
use Twig\TemplateWrapper;
/**
* Class FlexForm
@@ -45,6 +49,7 @@ class FlexForm implements FlexFormInterface
{
$this->name = $name;
$this->form = $form;
$uniqueId = $object->exists() ? $object->getStorageKey() : "{$object->getFlexType()}:new";
$this->setObject($object);
$this->setId($this->getName());
@@ -221,6 +226,42 @@ class FlexForm implements FlexFormInterface
$this->doUnserialize($data);
}
public function __get($name)
{
$method = "get{$name}";
if (method_exists($this, $method)) {
return $this->{$method}();
}
$form = $this->getBlueprint()->form();
return $form[$name] ?? null;
}
public function __set($name, $value)
{
$method = "set{$name}";
if (method_exists($this, $method)) {
$this->{$method}($value);
}
}
public function __isset($name)
{
$method = "get{$name}";
if (method_exists($this, $method)) {
return true;
}
$form = $this->getBlueprint()->form();
return isset($form[$name]);
}
public function __unset($name)
{
}
/**
* Note: this method clones the object.
*
@@ -234,6 +275,29 @@ class FlexForm implements FlexFormInterface
return $this;
}
/**
* @param string $layout
* @return TemplateWrapper
* @throws LoaderError
* @throws SyntaxError
*/
protected function getTemplate($layout)
{
$grav = Grav::instance();
/** @var Twig $twig */
$twig = $grav['twig'];
return $twig->twig()->resolveTemplate(
[
"flex-objects/layouts/{$this->getFlexType()}/form/{$layout}.html.twig",
"flex-objects/layouts/_default/form/{$layout}.html.twig",
"forms/{$layout}/form.html.twig",
'forms/default/form.html.twig'
]
);
}
/**
* @param array $data
* @param array $files
@@ -243,6 +307,7 @@ class FlexForm implements FlexFormInterface
{
/** @var FlexObject $object */
$object = clone $this->getObject();
$object->update($data, $files);
$object->save();

View File

@@ -11,6 +11,7 @@ namespace Grav\Framework\Form\Interfaces;
use Grav\Common\Data\Blueprint;
use Grav\Common\Data\Data;
use Grav\Framework\Interfaces\RenderInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UploadedFileInterface;
@@ -18,7 +19,7 @@ use Psr\Http\Message\UploadedFileInterface;
* Interface FormInterface
* @package Grav\Framework\Form
*/
interface FormInterface extends \Serializable
interface FormInterface extends RenderInterface, \Serializable
{
/**
* Get HTML id="..." attribute.
@@ -83,6 +84,13 @@ interface FormInterface extends \Serializable
*/
public function getNonce(): string;
/**
* Get task for the form if set in blueprints.
*
* @return string
*/
public function getTask(): string;
/**
* Get form action (URL). If action is empty, it points to the current page.
*

View File

@@ -14,10 +14,15 @@ use Grav\Common\Data\Data;
use Grav\Common\Data\ValidationException;
use Grav\Common\Form\FormFlash;
use Grav\Common\Grav;
use Grav\Common\Twig\Twig;
use Grav\Common\Utils;
use Grav\Framework\ContentBlock\HtmlBlock;
use Grav\Framework\Form\Interfaces\FormInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UploadedFileInterface;
use Twig\Error\LoaderError;
use Twig\Error\SyntaxError;
use Twig\TemplateWrapper;
/**
* Trait FormTrait
@@ -94,6 +99,11 @@ trait FormTrait
return '';
}
public function getTask(): string
{
return $this->getBlueprint()->get('form/task') ?? '';
}
public function getData(string $name = null)
{
return null !== $name ? $this->data[$name] : $this->data;
@@ -337,6 +347,30 @@ trait FormTrait
return $this->flash;
}
/**
* {@inheritdoc}
* @see FormInterface::render()
*/
public function render(string $layout = null, array $context = [])
{
if (null === $layout) {
$layout = 'default';
}
$grav = Grav::instance();
$block = HtmlBlock::create();
$block->disableCache();
$output = $this->getTemplate($layout)->render(
['grav' => $grav, 'block' => $block, 'form' => $this, 'layout' => $layout] + $context
);
$block->setContent($output);
return $block;
}
protected function unsetFlash(): void
{
$this->flash = null;
@@ -362,6 +396,27 @@ trait FormTrait
$this->errors[] = $error;
}
/**
* @param string $layout
* @return TemplateWrapper
* @throws LoaderError
* @throws SyntaxError
*/
protected function getTemplate($layout)
{
$grav = Grav::instance();
/** @var Twig $twig */
$twig = $grav['twig'];
return $twig->twig()->resolveTemplate(
[
"forms/{$layout}/form.html.twig",
'forms/default/form.html.twig'
]
);
}
/**
* Parse PSR-7 ServerRequest into data and files.
*

View File

@@ -103,7 +103,7 @@ trait NestedPropertyTrait
$current[$offset] = [];
}
} else {
throw new \RuntimeException('Cannot set nested property on non-array value');
throw new \RuntimeException("Cannot set nested property {$property} on non-array value");
}
$current = &$current[$offset];
@@ -147,7 +147,7 @@ trait NestedPropertyTrait
return $this;
}
} else {
throw new \RuntimeException('Cannot set nested property on non-array value');
throw new \RuntimeException("Cannot unset nested property {$property} on non-array value");
}
$current = &$current[$offset];