mirror of
https://github.com/getgrav/grav.git
synced 2026-07-20 09:32:14 +02:00
Merge branch '1.6' of github.com:getgrav/grav into 1.6
# Conflicts: # CHANGELOG.md
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
# v1.6.0-rc.5
|
||||
## mm/dd/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added `FlexObjectInterface::getDefaultValue()` and `FormInterface::getDefaultValue()`
|
||||
1. [](#improved)
|
||||
* Added `Content-Type: application/json` body support for PSR-7 `ServerRequest`
|
||||
* Remove PHP time limit in `ZipArchive`
|
||||
* DebugBar: Resolve twig templates in deprecated backtraces in order to help locating Twig issues
|
||||
1. [](#bugfix)
|
||||
* Fixed `Undefined method closure::fields()` when getting avatar for user, thanks @Romarain [#2422](https://github.com/getgrav/grav/issues/2422)
|
||||
* Grav 1.6: Added `Flex[Class]::getFlexType()` to all flex classes to have the interface for all Flex classes
|
||||
* FlexObjects: Remove null values during save
|
||||
|
||||
# v1.6.0-rc.4
|
||||
## 03/20/2019
|
||||
|
||||
@@ -25,6 +25,9 @@ class Blueprint extends BlueprintForm
|
||||
/** @var BlueprintSchema */
|
||||
protected $blueprintSchema;
|
||||
|
||||
/** @var array */
|
||||
protected $defaults;
|
||||
|
||||
public function setScope($scope)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
@@ -56,7 +59,11 @@ class Blueprint extends BlueprintForm
|
||||
{
|
||||
$this->initInternals();
|
||||
|
||||
return $this->blueprintSchema->getDefaults();
|
||||
if (null === $this->defaults) {
|
||||
$this->defaults = $this->blueprintSchema->getDefaults();
|
||||
}
|
||||
|
||||
return $this->defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,6 +181,7 @@ class Blueprint extends BlueprintForm
|
||||
|
||||
$this->blueprintSchema->embed('', $this->items);
|
||||
$this->blueprintSchema->init();
|
||||
$this->defaults = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ use DebugBar\DebugBar;
|
||||
use DebugBar\JavascriptRenderer;
|
||||
use DebugBar\StandardDebugBar;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Processors\ProcessorInterface;
|
||||
use Twig\Template;
|
||||
use Twig\TemplateWrapper;
|
||||
|
||||
class Debugger
|
||||
{
|
||||
@@ -44,7 +47,7 @@ class Debugger
|
||||
/** @var array */
|
||||
protected $timers = [];
|
||||
|
||||
/** @var string[] $deprecations */
|
||||
/** @var array $deprecations */
|
||||
protected $deprecations = [];
|
||||
|
||||
/** @var callable */
|
||||
@@ -356,57 +359,183 @@ class Debugger
|
||||
return true;
|
||||
}
|
||||
|
||||
$backtrace = debug_backtrace(false);
|
||||
// Figure out error scope from the error.
|
||||
$scope = 'unknown';
|
||||
if (stripos($errstr, 'grav') !== false) {
|
||||
$scope = 'grav';
|
||||
} elseif (strpos($errfile, '/twig/') !== false) {
|
||||
$scope = 'twig';
|
||||
} elseif (stripos($errfile, '/yaml/') !== false) {
|
||||
$scope = 'yaml';
|
||||
} elseif (strpos($errfile, '/vendor/') !== false) {
|
||||
$scope = 'vendor';
|
||||
}
|
||||
|
||||
// Clean up backtrace to make it more useful.
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
|
||||
|
||||
// Skip current call.
|
||||
array_shift($backtrace);
|
||||
|
||||
// Find yaml file where the error happened.
|
||||
if ($scope === 'yaml') {
|
||||
foreach ($backtrace as $current) {
|
||||
if (isset($current['args'])) {
|
||||
foreach ($current['args'] as $arg) {
|
||||
if ($arg instanceof \SplFileInfo) {
|
||||
$arg = $arg->getPathname();
|
||||
}
|
||||
if (\is_string($arg) && preg_match('/.+\.(yaml|md)$/i', $arg)) {
|
||||
$errfile = $arg;
|
||||
$errline = 0;
|
||||
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter arguments.
|
||||
$cut = 0;
|
||||
$previous = null;
|
||||
foreach ($backtrace as $i => &$current) {
|
||||
if (isset($current['args'])) {
|
||||
$args = [];
|
||||
foreach ($current['args'] as $arg) {
|
||||
if (\is_string($arg)) {
|
||||
$arg = "'" . $arg . "'";
|
||||
if (mb_strlen($arg) > 100) {
|
||||
$arg = 'string';
|
||||
}
|
||||
} elseif (\is_bool($arg)) {
|
||||
$arg = $arg ? 'true' : 'false';
|
||||
} elseif (\is_scalar($arg)) {
|
||||
$arg = $arg;
|
||||
} elseif (\is_object($arg)) {
|
||||
$arg = get_class($arg) . ' $object';
|
||||
} elseif (\is_array($arg)) {
|
||||
$arg = '$array';
|
||||
} else {
|
||||
$arg = '$object';
|
||||
}
|
||||
|
||||
$args[] = $arg;
|
||||
}
|
||||
$current['args'] = $args;
|
||||
}
|
||||
|
||||
$object = $current['object'] ?? null;
|
||||
unset($current['object']);
|
||||
|
||||
$reflection = null;
|
||||
if ($object instanceof TemplateWrapper) {
|
||||
$reflection = new \ReflectionObject($object);
|
||||
$property = $reflection->getProperty('template');
|
||||
$property->setAccessible(true);
|
||||
$object = $property->getValue($object);
|
||||
}
|
||||
|
||||
if ($object instanceof Template) {
|
||||
$file = $current['file'] ?? null;
|
||||
|
||||
if (preg_match('`(Template.php|TemplateWrapper.php)$`', $file)) {
|
||||
$current = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
$debugInfo = $object->getDebugInfo();
|
||||
|
||||
$line = 1;
|
||||
if (!$reflection) {
|
||||
foreach ($debugInfo as $codeLine => $templateLine) {
|
||||
if ($codeLine <= $current['line']) {
|
||||
$line = $templateLine;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$src = $object->getSourceContext();
|
||||
//$code = preg_split('/\r\n|\r|\n/', $src->getCode());
|
||||
//$current['twig']['twig'] = trim($code[$line - 1]);
|
||||
$current['twig']['file'] = $src->getPath();
|
||||
$current['twig']['line'] = $line;
|
||||
|
||||
$prevFile = $previous['file'] ?? null;
|
||||
if ($prevFile && $file === $prevFile) {
|
||||
$prevLine = $previous['line'];
|
||||
|
||||
$line = 1;
|
||||
foreach ($debugInfo as $codeLine => $templateLine) {
|
||||
if ($codeLine <= $prevLine) {
|
||||
$line = $templateLine;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//$previous['twig']['twig'] = trim($code[$line - 1]);
|
||||
$previous['twig']['file'] = $src->getPath();
|
||||
$previous['twig']['line'] = $line;
|
||||
}
|
||||
|
||||
$cut = $i;
|
||||
} elseif ($object instanceof ProcessorInterface) {
|
||||
$cut = $cut ?: $i;
|
||||
break;
|
||||
}
|
||||
|
||||
$previous = &$backtrace[$i];
|
||||
}
|
||||
unset($current);
|
||||
|
||||
if ($cut) {
|
||||
$backtrace = array_slice($backtrace, 0, $cut + 1);
|
||||
}
|
||||
$backtrace = array_values(array_filter($backtrace));
|
||||
|
||||
// Skip vendor libraries and the method where error was triggered.
|
||||
while ($current = array_shift($backtrace)) {
|
||||
if (isset($current['file']) && strpos($current['file'], 'vendor') !== false) {
|
||||
foreach ($backtrace as $i => $current) {
|
||||
if (!isset($current['file'])) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($current['file'], '/vendor/') !== false) {
|
||||
$cut = $i + 1;
|
||||
continue;
|
||||
}
|
||||
if (isset($current['function']) && ($current['function'] === 'user_error' || $current['function'] === 'trigger_error')) {
|
||||
$current = array_shift($backtrace);
|
||||
$cut = $i + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Add back last call.
|
||||
array_unshift($backtrace, $current);
|
||||
|
||||
// Filter arguments.
|
||||
foreach ($backtrace as &$current) {
|
||||
if (isset($current['args'])) {
|
||||
$args = [];
|
||||
foreach ($current['args'] as $arg) {
|
||||
if (\is_string($arg)) {
|
||||
$args[] = "'" . $arg . "'";
|
||||
} elseif (\is_bool($arg)) {
|
||||
$args[] = $arg ? 'true' : 'false';
|
||||
} elseif (\is_scalar($arg)) {
|
||||
$args[] = $arg;
|
||||
} elseif (\is_object($arg)) {
|
||||
$args[] = get_class($arg) . ' $object';
|
||||
} elseif (\is_array($arg)) {
|
||||
$args[] = '$array';
|
||||
} else {
|
||||
$args[] = '$object';
|
||||
}
|
||||
}
|
||||
$current['args'] = $args;
|
||||
}
|
||||
if ($cut) {
|
||||
$backtrace = array_slice($backtrace, $cut);
|
||||
}
|
||||
unset($current);
|
||||
$backtrace = array_values(array_filter($backtrace));
|
||||
|
||||
$this->deprecations[] = [
|
||||
$current = reset($backtrace);
|
||||
|
||||
// If the issue happened inside twig file, change the file and line to match that file.
|
||||
$file = $current['twig']['file'] ?? '';
|
||||
if ($file) {
|
||||
$errfile = $file;
|
||||
$errline = $current['twig']['line'] ?? 0;
|
||||
}
|
||||
|
||||
$deprecation = [
|
||||
'scope' => $scope,
|
||||
'message' => $errstr,
|
||||
'file' => $errfile,
|
||||
'line' => $errline,
|
||||
'trace' => $backtrace,
|
||||
'count' => 1
|
||||
];
|
||||
|
||||
$this->deprecations[] = $deprecation;
|
||||
|
||||
// Do not pass forward.
|
||||
return true;
|
||||
}
|
||||
@@ -431,38 +560,37 @@ class Debugger
|
||||
|
||||
protected function getDepracatedMessage($deprecated)
|
||||
{
|
||||
$scope = 'unknown';
|
||||
if (stripos($deprecated['message'], 'grav') !== false) {
|
||||
$scope = 'grav';
|
||||
} elseif (!isset($deprecated['file'])) {
|
||||
$scope = 'unknown';
|
||||
} elseif (stripos($deprecated['file'], 'twig') !== false) {
|
||||
$scope = 'twig';
|
||||
} elseif (stripos($deprecated['file'], 'yaml') !== false) {
|
||||
$scope = 'yaml';
|
||||
} elseif (stripos($deprecated['file'], 'vendor') !== false) {
|
||||
$scope = 'vendor';
|
||||
}
|
||||
$scope = $deprecated['scope'];
|
||||
|
||||
$trace = [];
|
||||
foreach ($deprecated['trace'] as $current) {
|
||||
$class = $current['class'] ?? '';
|
||||
$type = $current['type'] ?? '';
|
||||
$function = $this->getFunction($current);
|
||||
if (isset($current['file'])) {
|
||||
$current['file'] = str_replace(GRAV_ROOT . '/', '', $current['file']);
|
||||
if (isset($deprecated['trace'])) {
|
||||
foreach ($deprecated['trace'] as $current) {
|
||||
$class = $current['class'] ?? '';
|
||||
$type = $current['type'] ?? '';
|
||||
$function = $this->getFunction($current);
|
||||
if (isset($current['file'])) {
|
||||
$current['file'] = str_replace(GRAV_ROOT . '/', '', $current['file']);
|
||||
}
|
||||
|
||||
unset($current['class'], $current['type'], $current['function'], $current['args']);
|
||||
|
||||
if (isset($current['twig'])) {
|
||||
$trace[] = $current['twig'];
|
||||
} else {
|
||||
$trace[] = ['call' => $class . $type . $function] + $current;
|
||||
}
|
||||
}
|
||||
|
||||
unset($current['class'], $current['type'], $current['function'], $current['args']);
|
||||
|
||||
$trace[] = ['call' => $class . $type . $function] + $current;
|
||||
}
|
||||
|
||||
$array = [
|
||||
'message' => $deprecated['message'],
|
||||
'file' => $deprecated['file'],
|
||||
'line' => $deprecated['line'],
|
||||
'trace' => $trace
|
||||
];
|
||||
|
||||
return [
|
||||
[
|
||||
'message' => $deprecated['message'],
|
||||
'trace' => $trace
|
||||
],
|
||||
array_filter($array),
|
||||
$scope
|
||||
];
|
||||
}
|
||||
@@ -473,6 +601,6 @@ class Debugger
|
||||
return '';
|
||||
}
|
||||
|
||||
return $trace['function'] . '(' . implode(', ', $trace['args']) . ')';
|
||||
return $trace['function'] . '(' . implode(', ', $trace['args'] ?? []) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,9 +161,9 @@ class User extends FlexObject implements UserInterface, MediaManipulationInterfa
|
||||
* @param string|null $separator
|
||||
* @return mixed
|
||||
*/
|
||||
public function value($name, $default = null, $separator = null)
|
||||
public function getFormValue(string $name, $default = null, string $separator = null)
|
||||
{
|
||||
$value = parent::value($name, null, $separator);
|
||||
$value = parent::getFormValue($name, null, $separator);
|
||||
|
||||
if ($name === 'avatar') {
|
||||
return $this->parseFileProperty($value);
|
||||
|
||||
@@ -63,7 +63,7 @@ class Flex implements \Countable
|
||||
*/
|
||||
public function addDirectory(FlexDirectory $directory)
|
||||
{
|
||||
$this->types[$directory->getType()] = $directory;
|
||||
$this->types[$directory->getFlexType()] = $directory;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
|
||||
parent::__construct($entries);
|
||||
|
||||
if ($directory) {
|
||||
$this->setFlexDirectory($directory)->setKey($directory->getType());
|
||||
$this->setFlexDirectory($directory)->setKey($directory->getFlexType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
|
||||
*/
|
||||
public function getFlexType(): string
|
||||
{
|
||||
return $this->_flexDirectory->getType();
|
||||
return $this->_flexDirectory->getFlexType();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,7 +245,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
|
||||
* {@inheritdoc}
|
||||
* @see FlexCollectionInterface::render()
|
||||
*/
|
||||
public function render($layout = null, array $context = [])
|
||||
public function render(string $layout = null, array $context = [])
|
||||
{
|
||||
if (null === $layout) {
|
||||
$layout = 'default';
|
||||
|
||||
@@ -91,8 +91,19 @@ class FlexDirectory implements FlexAuthorizeInterface
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @deprecated 1.6 Use ->getFlexType() method instead.
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
user_error(__CLASS__ . '::' . __FUNCTION__ . '() is deprecated since Grav 1.6, use ->getFlexType() method instead', E_USER_DEPRECATED);
|
||||
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFlexType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
@@ -102,7 +113,7 @@ class FlexDirectory implements FlexAuthorizeInterface
|
||||
*/
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->getBlueprintInternal()->get('title', ucfirst($this->getType()));
|
||||
return $this->getBlueprintInternal()->get('title', ucfirst($this->getFlexType()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,13 +323,13 @@ class FlexDirectory implements FlexAuthorizeInterface
|
||||
if (Utils::isAdminPlugin()) {
|
||||
$key = substr($key, 0, -1);
|
||||
}
|
||||
$cache = new DoctrineCache($gravCache->getCacheDriver(), 'flex-objects-' . $this->getType() . $key, $timeout);
|
||||
$cache = new DoctrineCache($gravCache->getCacheDriver(), 'flex-objects-' . $this->getFlexType() . $key, $timeout);
|
||||
} catch (\Exception $e) {
|
||||
/** @var Debugger $debugger */
|
||||
$debugger = Grav::instance()['debugger'];
|
||||
$debugger->addException($e);
|
||||
|
||||
$cache = new MemoryCache('flex-objects-' . $this->getType());
|
||||
$cache = new MemoryCache('flex-objects-' . $this->getFlexType());
|
||||
}
|
||||
|
||||
// Disable cache key validation.
|
||||
|
||||
@@ -45,7 +45,7 @@ class FlexForm implements FlexFormInterface
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->form = $form;
|
||||
$uniqueId = $object->exists() ? $object->getStorageKey() : "{$object->getType()}:new";
|
||||
$uniqueId = $object->exists() ? $object->getStorageKey() : "{$object->getFlexType()}:new";
|
||||
$this->setObject($object);
|
||||
$this->setId($this->getName());
|
||||
$this->setUniqueId(md5($uniqueId));
|
||||
@@ -73,7 +73,7 @@ class FlexForm implements FlexFormInterface
|
||||
$object = $this->getObject();
|
||||
$name = $this->name ?: 'object';
|
||||
|
||||
return "flex-{$object->getType()}-{$name}";
|
||||
return "flex-{$object->getFlexType()}-{$name}";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,6 +101,26 @@ class FlexForm implements FlexFormInterface
|
||||
return $value ?? $this->getObject()->value($name);
|
||||
}
|
||||
|
||||
public function getDefaultValue(string $name)
|
||||
{
|
||||
return $this->object->getDefaultValue($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultValues(): array
|
||||
{
|
||||
return $this->object->getDefaultValues();
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFlexType(): string
|
||||
{
|
||||
return $this->object->getFlexType();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FlexObjectInterface
|
||||
*/
|
||||
|
||||
@@ -104,7 +104,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
|
||||
*/
|
||||
public function getFlexType(): string
|
||||
{
|
||||
return $this->_flexDirectory->getType();
|
||||
return $this->_flexDirectory->getFlexType();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +171,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
|
||||
{
|
||||
// Get storage keys for the objects.
|
||||
$keys = [];
|
||||
$type = $this->_flexDirectory->getType() . '.obj:';
|
||||
$type = $this->_flexDirectory->getFlexType() . '.obj:';
|
||||
|
||||
foreach ($this->getEntries() as $key => $value) {
|
||||
$keys[$key] = $value['flex_key'] ?? $type . $value['storage_key'];
|
||||
@@ -191,7 +191,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
|
||||
return $this;
|
||||
}
|
||||
|
||||
$type = $keyField === 'flex_key' ? $this->_flexDirectory->getType() . '.obj:' : '';
|
||||
$type = $keyField === 'flex_key' ? $this->_flexDirectory->getFlexType() . '.obj:' : '';
|
||||
$entries = [];
|
||||
foreach ($this->getEntries() as $key => $value) {
|
||||
if (!isset($value['key'])) {
|
||||
@@ -221,7 +221,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
|
||||
* {@inheritdoc}
|
||||
* @see FlexCollectionInterface::render()
|
||||
*/
|
||||
public function render($layout = null, array $context = [])
|
||||
public function render(string $layout = null, array $context = [])
|
||||
{
|
||||
return $this->__call('render', [$layout, $context]);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
|
||||
*/
|
||||
public function getFlexType(): string
|
||||
{
|
||||
return $this->_flexDirectory->getType();
|
||||
return $this->_flexDirectory->getFlexType();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +186,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
|
||||
*/
|
||||
public function getFlexKey(): string
|
||||
{
|
||||
return $this->_storage['flex_key'] ?? $this->_flexDirectory->getType() . '.obj:' . $this->getStorageKey();
|
||||
return $this->_storage['flex_key'] ?? $this->_flexDirectory->getFlexType() . '.obj:' . $this->getStorageKey();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,7 +357,7 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
|
||||
* {@inheritdoc}
|
||||
* @see FlexObjectInterface::render()
|
||||
*/
|
||||
public function render($layout = null, array $context = [])
|
||||
public function render(string $layout = null, array $context = [])
|
||||
{
|
||||
if (null === $layout) {
|
||||
$layout = 'default';
|
||||
@@ -616,9 +616,50 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @see FlexObjectInterface::value()
|
||||
* @see FlexObjectInterface::getDefaultValue()
|
||||
*/
|
||||
public function value($name, $default = null, $separator = null)
|
||||
public function getDefaultValue(string $name, string $separator = null)
|
||||
{
|
||||
$separator = $separator ?: '.';
|
||||
$path = explode($separator, $name) ?: [];
|
||||
$offset = array_shift($path) ?? '';
|
||||
|
||||
$current = $this->getDefaultValues();
|
||||
|
||||
if (!isset($current[$offset])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$current = $current[$offset];
|
||||
|
||||
while ($path) {
|
||||
$offset = array_shift($path);
|
||||
|
||||
if ((\is_array($current) || $current instanceof \ArrayAccess) && isset($current[$offset])) {
|
||||
$current = $current[$offset];
|
||||
} elseif (\is_object($current) && isset($current->{$offset})) {
|
||||
$current = $current->{$offset};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultValues(): array
|
||||
{
|
||||
return $this->getBlueprint()->getDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @see FlexObjectInterface::getFormValue()
|
||||
*/
|
||||
public function getFormValue(string $name, $default = null, string $separator = null)
|
||||
{
|
||||
if ($name === 'storage_key') {
|
||||
return $this->getStorageKey();
|
||||
@@ -630,6 +671,19 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
|
||||
return $this->getNestedProperty($name, $default, $separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed|null $default
|
||||
* @param string|null $separator
|
||||
* @return mixed
|
||||
*
|
||||
* @deprecated 1.6 Use ->getFormValue() method instead.
|
||||
*/
|
||||
public function value($name, $default = null, $separator = null)
|
||||
{
|
||||
return $this->getFormValue($name, $default, $separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this object.
|
||||
*
|
||||
|
||||
@@ -11,11 +11,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Grav\Framework\Flex\Interfaces;
|
||||
|
||||
use Grav\Framework\ContentBlock\ContentBlockInterface;
|
||||
use Grav\Framework\ContentBlock\HtmlBlock;
|
||||
use Grav\Framework\Flex\FlexDirectory;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Grav\Framework\Interfaces\RenderInterface;
|
||||
|
||||
/**
|
||||
* Defines common interface shared with both Flex Objects and Collections.
|
||||
@@ -23,7 +20,7 @@ use Twig\Error\SyntaxError;
|
||||
* @used-by \Grav\Framework\Flex\FlexObject
|
||||
* @since 1.6
|
||||
*/
|
||||
interface FlexCommonInterface
|
||||
interface FlexCommonInterface extends RenderInterface
|
||||
{
|
||||
/**
|
||||
* Get Flex Type of the object / collection.
|
||||
@@ -64,22 +61,4 @@ interface FlexCommonInterface
|
||||
* @return string Returns cache checksum.
|
||||
*/
|
||||
public function getCacheChecksum(): string;
|
||||
|
||||
/**
|
||||
* Renders the object / collection.
|
||||
*
|
||||
* @example {% render object layout 'edit' with { limited: true } %}
|
||||
* @example {% render collection layout 'list' %}
|
||||
*
|
||||
* @param string $layout Layout name.
|
||||
* @param array $context Context given to the renderer.
|
||||
*
|
||||
* @return ContentBlockInterface|HtmlBlock Returns `HtmlBlock` containing the rendered output.
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
* @throws LoaderError
|
||||
* @throws SyntaxError
|
||||
* @api
|
||||
*/
|
||||
public function render($layout = null, array $context = []);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ interface FlexObjectInterface extends FlexCommonInterface, NestedObjectInterface
|
||||
* @throws \RuntimeException if object already exists.
|
||||
* @api
|
||||
*/
|
||||
public function create($key = null);
|
||||
public function create(string $key = null);
|
||||
|
||||
/**
|
||||
* Save object into the storage.
|
||||
@@ -173,12 +173,36 @@ interface FlexObjectInterface extends FlexCommonInterface, NestedObjectInterface
|
||||
public function getForm(string $name = '', array $form = null);
|
||||
|
||||
/**
|
||||
* Form field compatibility.
|
||||
* Returns default value suitable to be used in a form for the given property.
|
||||
*
|
||||
* @param string $name Property name.
|
||||
* @param mixed $default Default value.
|
||||
* @param string $separator Optional nested property separator.
|
||||
* @return mixed Returns value of the field.
|
||||
* @see FlexObjectInterface::getForm()
|
||||
*
|
||||
* @param string $name Property name.
|
||||
* @param string $separator Optional nested property separator.
|
||||
*
|
||||
* @return mixed|null Returns default value of the field, null if there is no default value.
|
||||
*/
|
||||
public function value($name, $default = null, $separator = null);
|
||||
public function getDefaultValue(string $name, string $separator = null);
|
||||
|
||||
/**
|
||||
* Returns default values suitable to be used in a form for the given property.
|
||||
*
|
||||
* @see FlexObjectInterface::getForm()
|
||||
*
|
||||
* @return array Returns default values.
|
||||
*/
|
||||
public function getDefaultValues(): array;
|
||||
|
||||
/**
|
||||
* Returns raw value suitable to be used in a form for the given property.
|
||||
*
|
||||
* @see FlexObjectInterface::getForm()
|
||||
*
|
||||
* @param string $name Property name.
|
||||
* @param mixed $default Default value.
|
||||
* @param string $separator Optional nested property separator.
|
||||
*
|
||||
* @return mixed Returns value of the field.
|
||||
*/
|
||||
public function getFormValue(string $name, $default = null, string $separator = null);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,42 @@ trait FormTrait
|
||||
return $this->data[$name] ?? null;
|
||||
}
|
||||
|
||||
public function getDefaultValue(string $name)
|
||||
{
|
||||
$path = explode('.', $name) ?: [];
|
||||
$offset = array_shift($path) ?? '';
|
||||
|
||||
$current = $this->getDefaultValues();
|
||||
|
||||
if (!isset($current[$offset])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$current = $current[$offset];
|
||||
|
||||
while ($path) {
|
||||
$offset = array_shift($path);
|
||||
|
||||
if ((\is_array($current) || $current instanceof \ArrayAccess) && isset($current[$offset])) {
|
||||
$current = $current[$offset];
|
||||
} elseif (\is_object($current) && isset($current->{$offset})) {
|
||||
$current = $current->{$offset};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultValues(): array
|
||||
{
|
||||
return $this->getBlueprint()->getDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return FormInterface|$this
|
||||
|
||||
38
system/src/Grav/Framework/Interfaces/RenderInterface.php
Normal file
38
system/src/Grav/Framework/Interfaces/RenderInterface.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @package Grav\Framework\Interfaces
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Framework\Interfaces;
|
||||
|
||||
use Grav\Framework\ContentBlock\ContentBlockInterface;
|
||||
use Grav\Framework\ContentBlock\HtmlBlock;
|
||||
|
||||
/**
|
||||
* Defines common interface to render any object.
|
||||
*
|
||||
* @used-by \Grav\Framework\Flex\FlexObject
|
||||
* @since 1.6
|
||||
*/
|
||||
interface RenderInterface
|
||||
{
|
||||
/**
|
||||
* Renders the object.
|
||||
*
|
||||
* @example $block = $object->render('custom', ['variable' => 'value']);
|
||||
* @example {% render object layout 'custom' with { variable: 'value' } %}
|
||||
*
|
||||
* @param string|null $layout Layout to be used.
|
||||
* @param array|null $context Extra context given to the renderer.
|
||||
*
|
||||
* @return ContentBlockInterface|HtmlBlock Returns `HtmlBlock` containing the rendered output.
|
||||
* @api
|
||||
*/
|
||||
public function render(string $layout = null, array $context = []);
|
||||
}
|
||||
@@ -95,7 +95,7 @@ trait ArrayPropertyTrait
|
||||
*/
|
||||
protected function getElements()
|
||||
{
|
||||
return $this->_elements;
|
||||
return array_filter($this->_elements, function ($val) { return $val !== null; });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -183,7 +183,10 @@ trait ObjectPropertyTrait
|
||||
|
||||
$elements = [];
|
||||
foreach ($properties as $offset => $value) {
|
||||
$elements[$offset] = $this->offsetSerialize($offset, $value);
|
||||
$serialized = $this->offsetSerialize($offset, $value);
|
||||
if ($serialized !== null) {
|
||||
$elements[$offset] = $this->offsetSerialize($offset, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $elements;
|
||||
|
||||
Reference in New Issue
Block a user