test appel img twig

This commit is contained in:
2021-03-19 16:07:04 +01:00
parent bc84eb05d5
commit 80be13743f
63 changed files with 999 additions and 1167 deletions
@@ -10,6 +10,7 @@
namespace Grav\Common\Assets;
use Grav\Common\Assets\Traits\AssetUtilsTrait;
use Grav\Common\Config\Config;
use Grav\Common\Grav;
use Grav\Common\Uri;
use Grav\Common\Utils;
@@ -171,6 +172,31 @@ abstract class BaseAsset extends PropertyObject
return $this;
}
/**
* Receive asset location and return the SRI integrity hash
*
* @param $input
*
* @return string
*/
public static function integrityHash( $input )
{
$grav = Grav::instance();
$assetsConfig = $grav['config']->get('system.assets');
if ( !empty($assetsConfig['enable_asset_sri']) && $assetsConfig['enable_asset_sri'] )
{
$dataToHash = file_get_contents( GRAV_ROOT . $input);
$hash = hash('sha256', $dataToHash, true);
$hash_base64 = base64_encode($hash);
return ' integrity="sha256-' . $hash_base64 . '"';
}
return '';
}
/**
+1 -1
View File
@@ -47,6 +47,6 @@ class Css extends BaseAsset
return "<style>\n" . trim($buffer) . "\n</style>\n";
}
return '<link href="' . trim($this->asset) . $this->renderQueryString() . '"' . $this->renderAttributes() . ">\n";
return '<link href="' . trim($this->asset) . $this->renderQueryString() . '"' . $this->renderAttributes() . $this->integrityHash($this->asset) . ">\n";
}
}
+1 -1
View File
@@ -43,6 +43,6 @@ class Js extends BaseAsset
return '<script' . $this->renderAttributes() . ">\n" . trim($buffer) . "\n</script>\n";
}
return '<script src="' . trim($this->asset) . $this->renderQueryString() . '"' . $this->renderAttributes() . "></script>\n";
return '<script src="' . trim($this->asset) . $this->renderQueryString() . '"' . $this->renderAttributes() . $this->integrityHash($this->asset) . "></script>\n";
}
}
+3 -2
View File
@@ -9,6 +9,7 @@
namespace Grav\Common\Assets;
use Grav\Common\Assets\BaseAsset;
use Grav\Common\Assets\Traits\AssetUtilsTrait;
use Grav\Common\Config\Config;
use Grav\Common\Grav;
@@ -148,7 +149,7 @@ class Pipeline extends PropertyObject
$output = "<style>\n" . $buffer . "\n</style>\n";
} else {
$this->asset = $relative_path;
$output = '<link href="' . $relative_path . $this->renderQueryString() . '"' . $this->renderAttributes() . ">\n";
$output = '<link href="' . $relative_path . $this->renderQueryString() . '"' . $this->renderAttributes() . BaseAsset::integrityHash($this->asset) . ">\n";
}
return $output;
@@ -211,7 +212,7 @@ class Pipeline extends PropertyObject
$output = '<script' . $this->renderAttributes(). ">\n" . $buffer . "\n</script>\n";
} else {
$this->asset = $relative_path;
$output = '<script src="' . $relative_path . $this->renderQueryString() . '"' . $this->renderAttributes() . "></script>\n";
$output = '<script src="' . $relative_path . $this->renderQueryString() . '"' . $this->renderAttributes() . BaseAsset::integrityHash($this->asset) . "></script>\n";
}
return $output;
+4 -2
View File
@@ -71,6 +71,7 @@ class Cache extends Getters
'cache://twig/',
'cache://doctrine/',
'cache://compiled/',
'cache://clockwork/',
'cache://validated-',
'cache://images',
'asset://',
@@ -80,6 +81,7 @@ class Cache extends Getters
'cache://twig/',
'cache://doctrine/',
'cache://compiled/',
'cache://clockwork/',
'cache://validated-',
'asset://',
];
@@ -311,7 +313,7 @@ class Cache extends Getters
if ($password && !$redis->auth($password)) {
throw new \RedisException('Redis authentication failed');
}
// Select alternate ( !=0 ) database ID if set
if ($databaseId && !$redis->select($databaseId)) {
throw new \RedisException('Could not select alternate Redis database ID');
@@ -498,7 +500,7 @@ class Cache extends Getters
$anything = true;
}
} elseif (is_dir($file)) {
if (Folder::delete($file)) {
if (Folder::delete($file, false)) {
$anything = true;
}
}
@@ -21,13 +21,16 @@ use Grav\Common\Grav;
use Grav\Common\Page\Header;
use Grav\Common\Page\Interfaces\PageCollectionInterface;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\User\Interfaces\UserInterface;
use Grav\Common\Utils;
use Grav\Framework\Flex\FlexDirectory;
use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
use Grav\Framework\Flex\Interfaces\FlexStorageInterface;
use Grav\Framework\Flex\Pages\FlexPageIndex;
use InvalidArgumentException;
use RuntimeException;
use function array_slice;
use function count;
use function in_array;
use function is_array;
use function is_string;
@@ -299,7 +302,33 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
'type' => ['root', 'dir'],
];
return $this->getLevelListingRecurse($options);
$key = 'page.idx.lev.' . sha1(json_encode($options, JSON_THROW_ON_ERROR) . $this->getCacheKey());
$checksum = $this->getCacheChecksum();
$cache = $this->getCache('object');
/** @var Debugger $debugger */
$debugger = Grav::instance()['debugger'];
$result = null;
try {
$cached = $cache->get($key);
$test = $cached[0] ?? null;
$result = $test === $checksum ? ($cached[1] ?? null) : null;
} catch (\Psr\SimpleCache\InvalidArgumentException $e) {
$debugger->addException($e);
}
try {
if (null === $result) {
$result = $this->getLevelListingRecurse($options);
$cache->set($key, [$checksum, $result]);
}
} catch (\Psr\SimpleCache\InvalidArgumentException $e) {
$debugger->addException($e);
}
return $result;
}
/**
@@ -429,6 +458,9 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
$selectedChildren = $selectedChildren->order($sortby, $order, $custom ?? null);
}
/** @var UserInterface|null $user */
$user = Grav::instance()['user'] ?? null;
/** @var PageObject $child */
foreach ($selectedChildren as $child) {
$selected = $child->path() === $extra;
@@ -482,7 +514,7 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
'visible' => $child->visible(),
'routable' => $child->routable(),
'tags' => $tags,
'actions' => $this->getListingActions($child),
'actions' => $this->getListingActions($child, $user),
];
$extras = array_filter($extras, static function ($v) {
return $v !== null;
@@ -535,20 +567,21 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
/**
* @param PageObject $object
* @param UserInterface $user
* @return array
*/
protected function getListingActions(PageObject $object): array
protected function getListingActions(PageObject $object, UserInterface $user): array
{
$actions = [];
if ($object->isAuthorized('read')) {
if ($object->isAuthorized('read', null, $user)) {
$actions[] = 'preview';
$actions[] = 'edit';
}
if ($object->isAuthorized('update')) {
if ($object->isAuthorized('update', null, $user)) {
$actions[] = 'copy';
$actions[] = 'move';
}
if ($object->isAuthorized('delete')) {
if ($object->isAuthorized('delete', null, $user)) {
$actions[] = 'delete';
}
@@ -62,7 +62,6 @@ class PageObject extends FlexPageObject
/** @var string Language code, eg: 'en' */
protected $language;
/** @var string File format, eg. 'md' */
protected $format;
@@ -78,6 +77,7 @@ class PageObject extends FlexPageObject
'path' => true,
'full_order' => true,
'filterBy' => true,
'translated' => false,
] + parent::getCachedMethods();
}
@@ -92,6 +92,11 @@ class PageObject extends FlexPageObject
}
}
public function translated(): bool
{
return $this->translatedLanguages(true) ? true : false;
}
/**
* @param string|array $query
* @return Route|null
@@ -223,7 +228,7 @@ class PageObject extends FlexPageObject
}
// Reorder siblings.
$siblings = is_array($reorder) ? $this->reorderSiblings($reorder) : [];
$siblings = is_array($reorder) ? ($this->reorderSiblings($reorder) ?? []) : [];
$data = $this->prepareStorage();
unset($data['header']);
@@ -289,6 +294,9 @@ class PageObject extends FlexPageObject
$grav->fireEvent('onAdminAfterSave', new Event(['type' => 'flex', 'directory' => $this->getFlexDirectory(), 'object' => $this]));
}
// Reset original after save events have all been called.
$this->_original = null;
return $instance;
}
@@ -308,13 +316,14 @@ class PageObject extends FlexPageObject
$this->_reorder = [];
$this->setProperty('parent_key', $parent->getStorageKey());
$this->storeOriginal();
return $this;
}
/**
* @param array $ordering
* @return PageCollection
* @return PageCollection|null
*/
protected function reorderSiblings(array $ordering)
{
@@ -324,17 +333,35 @@ class PageObject extends FlexPageObject
$newParentKey = $this->getProperty('parent_key');
$isMoved = $oldParentKey !== $newParentKey;
$order = !$isMoved ? $this->order() : false;
if ($order !== false) {
$order = (int)$order;
}
$parent = $this->parent();
if (!$parent) {
throw new RuntimeException('Cannot reorder a page which has no parent');
}
/** @var PageCollection|null $siblings */
/** @var PageCollection $siblings */
$siblings = $parent->children();
$siblings = $siblings->getCollection()->withOrdered();
/** @var PageCollection|null $siblings */
$siblings = $siblings->getCollection()->withOrdered()->orderBy(['order' => 'ASC']);
// Handle special case where ordering isn't given.
if ($ordering === []) {
if ($order >= 999999) {
// Set ordering to point to be the last item.
$order = 0;
foreach ($siblings as $sibling) {
$order = max($order, (int)$sibling->order());
}
$this->order($order + 1);
}
// Do not change sibling ordering.
return null;
}
$siblings = $siblings->orderBy(['order' => 'ASC']);
if ($storageKey !== null) {
if ($order !== false) {
@@ -378,7 +405,9 @@ class PageObject extends FlexPageObject
throw new RuntimeException("New parent page '{$parentKey}' not found.");
}
}
$newSiblings = $newParent->children()->getCollection()->withOrdered();
/** @var PageCollection $newSiblings */
$newSiblings = $newParent->children();
$newSiblings = $newSiblings->getCollection()->withOrdered();
$order = 0;
foreach ($newSiblings as $sibling) {
$order = max($order, (int)$sibling->order());
@@ -584,14 +613,17 @@ class PageObject extends FlexPageObject
unset($elements['ordering'], $elements['order']);
} elseif (array_key_exists('ordering', $elements) && array_key_exists('order', $elements)) {
// Store ordering.
$this->_reorder = !empty($elements['order']) ? explode(',', $elements['order']) : [];
$ordering = $elements['order'] ?? null;
$this->_reorder = !empty($ordering) ? explode(',', $ordering) : [];
$order = false;
if ((bool)($elements['ordering'] ?? false)) {
$order = 999999;
$order = $this->order();
if ($order === false) {
$order = 999999;
}
}
$this->order();
$elements['order'] = $order;
}
@@ -110,6 +110,9 @@ class PageStorage extends FolderStorage
}
} catch (RuntimeException $e) {
$frontmatter = 'ERROR: ' . $e->getMessage();
} finally {
$file->free();
unset($file);
}
return $frontmatter;
@@ -127,6 +130,9 @@ class PageStorage extends FolderStorage
$raw = $file->raw();
} catch (RuntimeException $e) {
$raw = 'ERROR: ' . $e->getMessage();
} finally {
$file->free();
unset($file);
}
return $raw;
@@ -407,7 +413,7 @@ class PageStorage extends FolderStorage
if (!$isClone && $file->exists()) {
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
$toPath = $locator->isStream($newFilepath) ? $locator->findResource($newFilepath, true, true) : $newFilepath;
$toPath = $locator->isStream($newFilepath) ? $locator->findResource($newFilepath, true, true) : GRAV_ROOT . "/{$newFilepath}";
$success = $file->rename($toPath);
if (!$success) {
throw new RuntimeException("Changing page template failed: {$oldFilepath} => {$newFilepath}");
@@ -439,16 +445,19 @@ class PageStorage extends FolderStorage
} else {
$debugger->addMessage('Page content has not been changed, do not update the file', 'debug');
}
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($newFolder)) {
$locator->clearCache();
}
} catch (RuntimeException $e) {
$name = isset($file) ? $file->filename() : $newKey;
throw new RuntimeException(sprintf('Flex saveRow(%s): %s', $name, $e->getMessage()));
} finally {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$locator->clearCache();
if (isset($file)) {
$file->free();
unset($file);
}
}
$row['__META'] = $this->getObjectMeta($newKey, true);
@@ -512,7 +521,11 @@ class PageStorage extends FolderStorage
$locator = Grav::instance()['locator'];
if (mb_strpos($key, '@@') === false) {
$path = $this->getStoragePath($key);
$path = $path ? $locator->findResource($path) : null;
if (is_string($path)) {
$path = $locator->isStream($path) ? $locator->findResource($path) : GRAV_ROOT . "/{$path}";
} else {
$path = null;
}
} else {
$path = null;
}
@@ -67,7 +67,7 @@ trait PageTranslateTrait
if (!$folder) {
return [];
}
$folder = $locator($folder);
$folder = $locator->isStream($folder) ? $locator->getResource($folder) : GRAV_ROOT . "/{$folder}";
$list = array_fill_keys($languages, null);
foreach ($translated as $languageCode => $languageFile) {
+12 -6
View File
@@ -426,12 +426,18 @@ class Grav extends Container
// Clean route for redirect
$route = preg_replace("#^\/[\\\/]+\/#", '/', $route);
// Check for code in route
$regex = '/.*(\[(30[1-7])\])$/';
preg_match($regex, $route, $matches);
if ($matches) {
$route = str_replace($matches[1], '', $matches[0]);
$code = $matches[2];
if (null !== $code || $code < 300 || $code > 399) {
$code = null;
}
if (null === $code) {
// Check for redirect code in the route: e.g. /new/[301], /new[301]/route or /new[301].html
$regex = '/.*(\[(30[1-7])\])(.\w+|\/.*?)?$/';
preg_match($regex, $route, $matches);
if ($matches) {
$route = str_replace($matches[1], '', $matches[0]);
$code = $matches[2];
}
}
if ($code === null) {
+4 -4
View File
@@ -34,7 +34,7 @@ class LogViewer
public function objectTail($filepath, $lines = 1, $desc = true)
{
$data = $this->tail($filepath, $lines);
$tailed_log = explode(PHP_EOL, $data);
$tailed_log = $data ? explode(PHP_EOL, $data) : [];
$line_objects = [];
foreach ($tailed_log as $line) {
@@ -54,13 +54,13 @@ class LogViewer
public function tail($filepath, $lines = 1)
{
$f = @fopen($filepath, "rb");
$f = $filepath ? @fopen($filepath, 'rb') : false;
if ($f === false) {
return false;
} else {
$buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));
}
$buffer = ($lines < 2 ? 64 : ($lines < 10 ? 512 : 4096));
fseek($f, -1, SEEK_END);
if (fread($f, 1) != "\n") {
$lines -= 1;
@@ -63,7 +63,7 @@ interface PageRoutableInterface
* the parents route and the current Page's slug.
*
* @param string|null $var Set new default route.
* @return string The route for the Page.
* @return string|null The route for the Page.
*/
public function route($var = null);
@@ -278,10 +278,10 @@ class Excerpts
);
}
$defaults = $config['images']['defaults'] ?? [];
$defaults = $this->config['images']['defaults'] ?? [];
if (count($defaults)) {
foreach ($defaults as $method => $params) {
if (!array_search($method, array_column($actions, 'method'))) {
if (array_search($method, array_column($actions, 'method')) === false) {
$actions[] = [
'method' => $method,
'params' => $params,
+1 -1
View File
@@ -1875,7 +1875,7 @@ class Page implements PageInterface
* the parents route and the current Page's slug.
*
* @param string|null $var Set new default route.
* @return string The route for the Page.
* @return string|null The route for the Page.
*/
public function route($var = null)
{
+30 -8
View File
@@ -769,6 +769,9 @@ class Pages
public function get($path)
{
$path = (string)$path;
if ($path === '') {
return null;
}
// Check for local instances first.
if (array_key_exists($path, $this->instances)) {
@@ -777,14 +780,26 @@ class Pages
$instance = $this->index[$path] ?? null;
if (is_string($instance)) {
/** @var Language $language */
$language = $this->grav['language'];
$lang = $language->getActive();
if ($lang) {
$instance .= ':' . $lang;
if ($this->directory) {
/** @var Language $language */
$language = $this->grav['language'];
$lang = $language->getActive();
if ($lang) {
$languages = $language->getFallbackLanguages($lang, true);
$key = $instance;
$instance = null;
foreach ($languages as $code) {
$test = $code ? $key . ':' . $code : $key;
if (($instance = $this->directory->getObject($test, 'flex_key')) !== null) {
break;
}
}
} else {
$instance = $this->directory->getObject($instance, 'flex_key');
}
}
$instance = $this->directory ? $this->directory->getObject($instance, 'flex_key') : null;
if ($instance) {
if ($instance instanceof PageInterface) {
if ($this->fire_events && method_exists($instance, 'initialize')) {
$instance->initialize();
}
@@ -1159,7 +1174,14 @@ class Pages
$event->types = $types;
$grav->fireEvent('onGetPageBlueprints', $event);
$types->scanBlueprints('theme://blueprints/');
$types->init();
// Try new location first.
$lookup = 'theme://blueprints/pages/';
if (!is_dir($lookup)) {
$lookup = 'theme://blueprints/';
}
$types->scanBlueprints($lookup);
// Scan templates
$event = new Event();
+21 -13
View File
@@ -32,22 +32,23 @@ class Types implements \ArrayAccess, \Iterator, \Countable
/** @var array */
protected $items;
/** @var array */
protected $systemBlueprints;
protected $systemBlueprints = [];
/**
* @param string $type
* @param Blueprint|null $blueprint
* @return void
*/
public function register($type, $blueprint = null)
{
if (!isset($this->items[$type])) {
$this->items[$type] = [];
} elseif (!$blueprint) {
} elseif (null === $blueprint) {
return;
}
if (!$blueprint && $this->systemBlueprints) {
$blueprint = $this->systemBlueprints[$type] ?? $this->systemBlueprints['default'];
if (null === $blueprint) {
$blueprint = $this->systemBlueprints[$type] ?? $this->systemBlueprints['default'] ?? null;
}
if ($blueprint) {
@@ -55,8 +56,23 @@ class Types implements \ArrayAccess, \Iterator, \Countable
}
}
/**
* @return void
*/
public function init()
{
if (null === $this->systemBlueprints) {
// Register all blueprints from the blueprints stream.
$this->systemBlueprints = $this->findBlueprints('blueprints://pages');
foreach ($this->systemBlueprints as $type => $blueprint) {
$this->register($type);
}
}
}
/**
* @param string $uri
* @return void
*/
public function scanBlueprints($uri)
{
@@ -64,15 +80,6 @@ class Types implements \ArrayAccess, \Iterator, \Countable
throw new InvalidArgumentException('First parameter must be URI');
}
if (null === $this->systemBlueprints) {
$this->systemBlueprints = $this->findBlueprints('blueprints://pages');
// Register default by default.
$this->register('default');
$this->register('external');
}
foreach ($this->findBlueprints($uri) as $type => $blueprint) {
$this->register($type, $blueprint);
}
@@ -80,6 +87,7 @@ class Types implements \ArrayAccess, \Iterator, \Countable
/**
* @param string $uri
* @return void
*/
public function scanTemplates($uri)
{
+53 -34
View File
@@ -16,6 +16,7 @@ use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Config\Config;
use LogicException;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use function defined;
@@ -35,11 +36,11 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
/** @var Grav */
protected $grav;
/** @var Config */
/** @var Config|null */
protected $config;
/** @var bool */
protected $active = true;
/** @var Blueprint */
/** @var Blueprint|null */
protected $blueprint;
/**
@@ -127,21 +128,25 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
protected function isPluginActiveAdmin($plugin_route)
{
$should_run = false;
$active = false;
/** @var Uri $uri */
$uri = $this->grav['uri'];
/** @var Config $config */
$config = $this->config ?? $this->grav['config'];
if (strpos($uri->path(), $this->config->get('plugins.admin.route') . '/' . $plugin_route) === false) {
$should_run = false;
if (strpos($uri->path(), $config->get('plugins.admin.route') . '/' . $plugin_route) === false) {
$active = false;
} elseif (isset($uri->paths()[1]) && $uri->paths()[1] === $plugin_route) {
$should_run = true;
$active = true;
}
return $should_run;
return $active;
}
/**
* @param array $events
* @return void
*/
protected function enable(array $events)
{
@@ -164,22 +169,18 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
/**
* @param array $params
* @param string $eventName
* @return int
*/
private function getPriority($params, $eventName)
{
$grav = Grav::instance();
$override = implode('.', ['priorities', $this->name, $eventName, $params[0]]);
if ($grav['config']->get($override) !== null) {
return $grav['config']->get($override);
}
if (isset($params[1])) {
return $params[1];
}
return 0;
return $this->grav['config']->get($override) ?? $params[1] ?? 0;
}
/**
* @param array $events
* @return void
*/
protected function disable(array $events)
{
@@ -207,12 +208,13 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
public function offsetExists($offset)
{
$this->loadBlueprint();
if ($offset === 'title') {
$offset = 'name';
}
return isset($this->blueprint[$offset]);
$blueprint = $this->getBlueprint();
return isset($blueprint[$offset]);
}
/**
@@ -223,12 +225,13 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
public function offsetGet($offset)
{
$this->loadBlueprint();
if ($offset === 'title') {
$offset = 'name';
}
return $this->blueprint[$offset] ?? null;
$blueprint = $this->getBlueprint();
return $blueprint[$offset] ?? null;
}
/**
@@ -281,9 +284,12 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
protected function parseLinks($content, $function, $internal_regex = '(.*)')
{
$regex = '/\[plugin:(?:' . $this->name . ')\]\(' . $internal_regex . '\)/i';
$regex = '/\[plugin:(?:' . preg_quote($this->name, '/') . ')\]\(' . $internal_regex . '\)/i';
return preg_replace_callback($regex, $function, $content);
$result = preg_replace_callback($regex, $function, $content);
\assert($result !== null);
return $result;
}
/**
@@ -301,9 +307,12 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
protected function mergeConfig(PageInterface $page, $deep = false, $params = [], $type = 'plugins')
{
/** @var Config $config */
$config = $this->config ?? $this->grav['config'];
$class_name = $this->name;
$class_name_merged = $class_name . '.merged';
$defaults = $this->config->get($type . '.' . $class_name, []);
$defaults = $config->get($type . '.' . $class_name, []);
$page_header = $page->header();
$header = [];
@@ -356,23 +365,26 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
/**
* Persists to disk the plugin parameters currently stored in the Grav Config object
*
* @param string $plugin_name The name of the plugin whose config it should store.
*
* @param string $name The name of the plugin whose config it should store.
* @return bool
*/
public static function saveConfig($plugin_name)
public static function saveConfig($name)
{
if (!$plugin_name) {
if (!$name) {
return false;
}
$grav = Grav::instance();
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
$filename = 'config://plugins/' . $plugin_name . '.yaml';
$file = YamlFile::instance($locator->findResource($filename, true, true));
$content = $grav['config']->get('plugins.' . $plugin_name);
$filename = 'config://plugins/' . $name . '.yaml';
$file = YamlFile::instance((string)$locator->findResource($filename, true, true));
$content = $grav['config']->get('plugins.' . $name);
$file->save($content);
$file->free();
unset($file);
return true;
}
@@ -384,21 +396,28 @@ class Plugin implements EventSubscriberInterface, ArrayAccess
*/
public function getBlueprint()
{
if (!$this->blueprint) {
if (null === $this->blueprint) {
$this->loadBlueprint();
\assert($this->blueprint instanceof Blueprint);
}
return $this->blueprint;
}
/**
* Load blueprints.
*
* @return void
*/
protected function loadBlueprint()
{
if (!$this->blueprint) {
if (null === $this->blueprint) {
$grav = Grav::instance();
/** @var Plugins $plugins */
$plugins = $grav['plugins'];
$this->blueprint = $plugins->get($this->name)->blueprints();
$data = $plugins->get($this->name);
\assert($data !== null);
$this->blueprint = $data->blueprints();
}
}
}
+27 -11
View File
@@ -17,6 +17,7 @@ use Grav\Common\File\CompiledYamlFile;
use Grav\Events\PluginsLoadedEvent;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RuntimeException;
use SplFileInfo;
use Symfony\Component\EventDispatcher\EventDispatcher;
use function get_class;
use function is_object;
@@ -27,7 +28,7 @@ use function is_object;
*/
class Plugins extends Iterator
{
/** @var array */
/** @var array|null */
public $formFieldTypes;
/** @var bool */
@@ -46,6 +47,7 @@ class Plugins extends Iterator
$iterator = $locator->getIterator('plugins://');
$plugins = [];
/** @var SplFileInfo $directory */
foreach ($iterator as $directory) {
if (!$directory->isDir()) {
continue;
@@ -56,7 +58,10 @@ class Plugins extends Iterator
sort($plugins, SORT_NATURAL | SORT_FLAG_CASE);
foreach ($plugins as $plugin) {
$this->add($this->loadPlugin($plugin));
$object = $this->loadPlugin($plugin);
if ($object) {
$this->add($object);
}
}
}
@@ -68,13 +73,21 @@ class Plugins extends Iterator
$blueprints = [];
$formFields = [];
$grav = Grav::instance();
/** @var Config $config */
$config = $grav['config'];
/** @var Plugin $plugin */
foreach ($this->items as $plugin) {
if (isset($plugin->features['blueprints'])) {
$blueprints["plugin://{$plugin->name}/blueprints"] = $plugin->features['blueprints'];
}
if (method_exists($plugin, 'getFormFieldTypes')) {
$formFields[get_class($plugin)] = isset($plugin->features['formfields']) ? $plugin->features['formfields'] : 0;
// Setup only enabled plugins.
if ($config["plugins.{$plugin->name}.enabled"] && $plugin instanceof Plugin) {
if (isset($plugin->features['blueprints'])) {
$blueprints["plugin://{$plugin->name}/blueprints"] = $plugin->features['blueprints'];
}
if (method_exists($plugin, 'getFormFieldTypes')) {
$formFields[get_class($plugin)] = $plugin->features['formfields'] ?? 0;
}
}
}
@@ -83,7 +96,7 @@ class Plugins extends Iterator
arsort($blueprints, SORT_NUMERIC);
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$locator = $grav['locator'];
$locator->addPath('blueprints', '', array_keys($blueprints), ['system', 'blueprints']);
}
@@ -150,6 +163,7 @@ class Plugins extends Iterator
* Add a plugin
*
* @param Plugin $plugin
* @return void
*/
public function add($plugin)
{
@@ -175,8 +189,8 @@ class Plugins extends Iterator
*/
public static function getPlugins(): array
{
$grav = Grav::instance();
$plugins = $grav['plugins'];
/** @var Plugins $plugins */
$plugins = Grav::instance()['plugins'];
$list = [];
foreach ($plugins as $instance) {
@@ -200,11 +214,13 @@ class Plugins extends Iterator
/**
* Return list of all plugin data with their blueprints.
*
* @return array<string,Data>
* @return Data[]
*/
public static function all()
{
$grav = Grav::instance();
/** @var Plugins $plugins */
$plugins = $grav['plugins'];
$list = [];
@@ -105,8 +105,9 @@ class InitializeProcessor extends ProcessorBase
$this->initializeUri($config);
// Grav may return redirect response right away.
if ($config->get('system.pages.redirect_trailing_slash', false)) {
$response = $this->handleRedirectRequest($request);
$redirectCode = (int)$config->get('system.pages.redirect_trailing_slash', 1);
if ($redirectCode) {
$response = $this->handleRedirectRequest($request, $redirectCode > 300 ? $redirectCode : null);
if ($response) {
$this->stopTimer('_init');
@@ -413,7 +414,7 @@ class InitializeProcessor extends ProcessorBase
$this->stopTimer('_init_uri');
}
protected function handleRedirectRequest(RequestInterface $request): ?ResponseInterface
protected function handleRedirectRequest(RequestInterface $request, int $code = null): ?ResponseInterface
{
if (!in_array($request->getMethod(), ['GET', 'HEAD'])) {
return null;
@@ -426,7 +427,7 @@ class InitializeProcessor extends ProcessorBase
if ($path !== $root && $path !== $root . '/' && Utils::endsWith($path, '/')) {
// Use permanent redirect for SEO reasons.
return $this->container->getRedirectResponse((string)$uri->withPath(rtrim($path, '/')), 301);
return $this->container->getRedirectResponse((string)$uri->withPath(rtrim($path, '/')), $code);
}
return null;
@@ -77,32 +77,46 @@ class PagesServiceProvider implements ServiceProviderInterface
}
}
$url = $pages->route($page->route());
$route = $page->route();
if ($route && \in_array($uri->method(), ['GET', 'HEAD'], true)) {
$pageExtension = $page->urlExtension();
$url = $pages->route($route) . $pageExtension;
if ($uri->params()) {
if ($url === '/') { //Avoid double slash
$url = $uri->params();
} else {
$url .= $uri->params();
if ($uri->params()) {
if ($url === '/') { //Avoid double slash
$url = $uri->params();
} else {
$url .= $uri->params();
}
}
if ($uri->query()) {
$url .= '?' . $uri->query();
}
if ($uri->fragment()) {
$url .= '#' . $uri->fragment();
}
}
if ($uri->query()) {
$url .= '?' . $uri->query();
}
if ($uri->fragment()) {
$url .= '#' . $uri->fragment();
}
/** @var Language $language */
$language = $grav['language'];
/** @var Language $language */
$language = $grav['language'];
// Language-specific redirection scenarios
if ($language->enabled() && ($language->isLanguageInUrl() xor $language->isIncludeDefaultLanguage())) {
$grav->redirect($url);
}
// Default route test and redirect
if ($config->get('system.pages.redirect_default_route') && $page->route() !== $path) {
$grav->redirect($url);
$redirectCode = (int)$config->get('system.pages.redirect_default_route', 0);
// Language-specific redirection scenarios
if ($language->enabled() && ($language->isLanguageInUrl() xor $language->isIncludeDefaultLanguage())) {
$grav->redirect($url, $redirectCode);
}
// Default route test and redirect
if ($redirectCode) {
$uriExtension = $uri->extension();
$uriExtension = null !== $uriExtension ? '.' . $uriExtension : '';
if ($route !== $path || ($pageExtension !== $uriExtension
&& \in_array($pageExtension, ['', '.htm', '.html'], true)
&& \in_array($uriExtension, ['', '.htm', '.html'], true))) {
$grav->redirect($url, $redirectCode);
}
}
}
}
+15 -35
View File
@@ -9,9 +9,9 @@
namespace Grav\Common;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Config\Config;
use RocketTheme\Toolbox\File\YamlFile;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* Class Theme
@@ -44,53 +44,30 @@ class Theme extends Plugin
/**
* Persists to disk the theme parameters currently stored in the Grav Config object
*
* @param string $theme_name The name of the theme whose config it should store.
* @param string $name The name of the theme whose config it should store.
* @return bool
*/
public static function saveConfig($theme_name)
public static function saveConfig($name)
{
if (!$theme_name) {
if (!$name) {
return false;
}
$grav = Grav::instance();
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
$filename = 'config://themes/' . $theme_name . '.yaml';
$file = YamlFile::instance($locator->findResource($filename, true, true));
$content = $grav['config']->get('themes.' . $theme_name);
$filename = 'config://themes/' . $name . '.yaml';
$file = YamlFile::instance((string)$locator->findResource($filename, true, true));
$content = $grav['config']->get('themes.' . $name);
$file->save($content);
$file->free();
unset($file);
return true;
}
/**
* Override the mergeConfig method to work for themes
*
* @param PageInterface $page
* @param string $deep
* @param array $params
* @param string $type
* @return Data\Data
*/
protected function mergeConfig(PageInterface $page, $deep = 'merge', $params = [], $type = 'themes')
{
return parent::mergeConfig($page, $deep, $params, $type);
}
/**
* Simpler getter for the theme blueprint
*
* @return mixed
*/
public function getBlueprint()
{
if (!$this->blueprint) {
$this->loadBlueprint();
}
return $this->blueprint;
}
/**
* Load blueprints.
*
@@ -100,8 +77,11 @@ class Theme extends Plugin
{
if (!$this->blueprint) {
$grav = Grav::instance();
/** @var Themes $themes */
$themes = $grav['themes'];
$this->blueprint = $themes->get($this->name)->blueprints();
$data = $themes->get($this->name);
\assert($data !== null);
$this->blueprint = $data->blueprints();
}
}
}
+18 -3
View File
@@ -33,10 +33,8 @@ class Themes extends Iterator
{
/** @var Grav */
protected $grav;
/** @var Config */
protected $config;
/** @var bool */
protected $inited = false;
@@ -95,6 +93,20 @@ class Themes extends Iterator
$events->addSubscriber($instance);
}
// Register blueprints.
if (is_dir('theme://blueprints/pages')) {
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$locator->addPath('blueprints', '', ['theme://blueprints'], ['user', 'blueprints']);
}
// Register form fields.
if (method_exists($instance, 'getFormFieldTypes')) {
/** @var Plugins $plugins */
$plugins = $this->grav['plugins'];
$plugins->formFieldTypes = $instance->getFormFieldTypes() + $plugins->formFieldTypes;
}
$this->grav['theme'] = $instance;
$this->grav->fireEvent('onThemeInitialized');
@@ -382,7 +394,10 @@ class Themes extends Iterator
}
// Try Old style theme classes
$path = strtolower(preg_replace('#\\\|_(?!.+\\\)#', '/', $class));
$path = preg_replace('#\\\|_(?!.+\\\)#', '/', $class);
\assert(null !== $path);
$path = strtolower($path);
$file = $locator("themes://{$path}/theme.php") ?: $locator("themes://{$path}/{$path}.php");
// Load class
+6 -9
View File
@@ -21,6 +21,7 @@ use RocketTheme\Toolbox\Event\Event;
use RuntimeException;
use function array_key_exists;
use function count;
use function in_array;
use function is_array;
use function is_string;
use function strlen;
@@ -394,7 +395,7 @@ class Uri
* Return the Extension of the URI
*
* @param string|null $default
* @return string The extension of the URI
* @return string|null The extension of the URI
*/
public function extension($default = null)
{
@@ -1408,18 +1409,14 @@ class Uri
/**
* Check if this is a valid Grav extension
*
* @param string $extension
* @param string|null $extension
* @return bool
*/
public function isValidExtension($extension)
public function isValidExtension($extension): bool
{
$valid_page_types = implode('|', Utils::getSupportPageTypes());
$extension = (string)$extension;
// Strip the file extension for valid page types
if (preg_match('/(' . $valid_page_types . ')/', $extension)) {
return true;
}
return false;
return $extension !== '' && in_array($extension, Utils::getSupportPageTypes(), true);
}
/**
+3 -2
View File
@@ -154,8 +154,6 @@ class CleanCommand extends Command
'vendor/itsgoingd/clockwork/.gitattributes',
'vendor/itsgoingd/clockwork/CHANGELOG.md',
'vendor/itsgoingd/clockwork/composer.json',
'vendor/kodus/psr7-server/composer.json',
'vendor/kodus/psr7-server/CHANGELOG.md',
'vendor/league/climate/composer.json',
'vendor/league/climate/CHANGELOG.md',
'vendor/league/climate/CONTRIBUTING.md',
@@ -197,6 +195,9 @@ class CleanCommand extends Command
'vendor/nyholm/psr7/phpstan.neon.dist',
'vendor/nyholm/psr7/CHANGELOG.md',
'vendor/nyholm/psr7/psalm.xml',
'vendor/nyholm/psr7-server/.github',
'vendor/nyholm/psr7-server/composer.json',
'vendor/nyholm/psr7-server/CHANGELOG.md',
'vendor/phive/twig-extensions-deferred/.gitignore',
'vendor/phive/twig-extensions-deferred/.travis.yml',
'vendor/phive/twig-extensions-deferred/composer.json',
@@ -14,11 +14,13 @@ namespace Grav\Framework\Controller\Traits;
use Grav\Common\Config\Config;
use Grav\Common\Debugger;
use Grav\Common\Grav;
use Grav\Common\Utils;
use Grav\Framework\Psr7\Response;
use Grav\Framework\RequestHandler\Exception\RequestException;
use Grav\Framework\Route\Route;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;
use Throwable;
use function get_class;
use function in_array;
@@ -76,6 +78,55 @@ trait ControllerResponseTrait
return new Response($code, $headers, json_encode($content));
}
/**
* @param string $filename
* @param string|resource|StreamInterface $resource
* @param array|null $headers
* @param array|null $options
* @return ResponseInterface
*/
protected function createDownloadResponse(string $filename, $resource, array $headers = null, array $options = null): ResponseInterface
{
// Required for IE, otherwise Content-Disposition may be ignored
if (ini_get('zlib.output_compression')) {
@ini_set('zlib.output_compression', 'Off');
}
$headers = $headers ?? [];
$options = $options ?? ['force_download' => true];
$file_parts = pathinfo($filename);
if (!isset($headers['Content-Type'])) {
$mimetype = Utils::getMimeByExtension($file_parts['extension']);
$headers['Content-Type'] = $mimetype;
}
// TODO: add multipart download support.
//$headers['Accept-Ranges'] = 'bytes';
if (!empty($options['force_download'])) {
$headers['Content-Disposition'] = 'attachment; filename="' . $file_parts['basename'] . '"';
}
if (!isset($headers['Content-Length'])) {
$realpath = realpath($filename);
if ($realpath) {
$headers['Content-Length'] = filesize($realpath);
}
}
$headers += [
'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
'Cache-Control' => 'no-store, no-cache, must-revalidate',
'Pragma' => 'no-cache'
];
return new Response(200, $headers, $resource);
}
/**
* @param string $url
* @param int|null $code
+1 -1
View File
@@ -380,7 +380,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
// Handle primary key alias.
$keyField = $this->getFlexDirectory()->getStorage()->getKeyField();
if (isset($orderings[$keyField])) {
if ($keyField !== 'key' && $keyField !== 'storage_key' && isset($orderings[$keyField])) {
$orderings['key'] = $orderings[$keyField];
unset($orderings[$keyField]);
}
@@ -885,6 +885,14 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
];
}
/**
* Clone object.
*/
public function __clone()
{
// Allows future compatibility as parent::__clone() works.
}
protected function markAsCopy(): void
{
$meta = $this->getMetaData();
@@ -16,7 +16,6 @@ use Grav\Common\Grav;
use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Page\Traits\PageFormTrait;
use Grav\Common\User\Interfaces\UserCollectionInterface;
use Grav\Framework\File\Formatter\YamlFormatter;
use Grav\Framework\Flex\FlexObject;
use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
use Grav\Framework\Flex\Interfaces\FlexTranslateInterface;
@@ -50,6 +49,20 @@ class FlexPageObject extends FlexObject implements PageInterface, FlexTranslateI
/** @var array|null */
protected $_reorder;
/** @var FlexPageObject|null */
protected $_original;
/**
* Clone page.
*/
public function __clone()
{
parent::__clone();
if (isset($this->header)) {
$this->header = clone($this->header);
}
}
/**
* @return array
@@ -242,6 +255,32 @@ class FlexPageObject extends FlexObject implements PageInterface, FlexTranslateI
return parent::save();
}
/**
* Gets the Page Unmodified (original) version of the page.
*
* Assumes that object has been cloned before modifying it.
*
* @return FlexPageObject|null The original version of the page.
*/
public function getOriginal()
{
return $this->_original;
}
/**
* Store the Page Unmodified (original) version of the page.
*
* Can be called multiple times, only the first call matters.
*
* @return void
*/
public function storeOriginal(): void
{
if (null === $this->_original) {
$this->_original = clone $this;
}
}
/**
* Get display order for the associated media.
*
@@ -398,23 +437,6 @@ class FlexPageObject extends FlexObject implements PageInterface, FlexTranslateI
unset($elements['content']);
}
// TODO: Remove: RAW frontmatter support has been moved to Flex-Objects v1.0.2 controller.
if (isset($elements['frontmatter'])) {
$formatter = new YamlFormatter();
try {
// Replace the whole header except for media order, which is used in admin.
$media_order = $elements['media_order'] ?? null;
$elements['header'] = $formatter->decode($elements['frontmatter']);
if ($media_order) {
$elements['header']['media_order'] = $media_order;
}
} catch (RuntimeException $e) {
throw new RuntimeException('Badly formatted markdown');
}
unset($elements['frontmatter']);
}
if (!$extended) {
$folder = !empty($elements['folder']) ? trim($elements['folder']) : '';
@@ -27,6 +27,8 @@ trait PageAuthorsTrait
{
/** @var array<int,UserInterface> */
private $_authors;
/** @var array|null */
private $_permissionsCache;
/**
* Returns true if object has the named author.
@@ -70,15 +72,19 @@ trait PageAuthorsTrait
*/
public function getPermissions(bool $inherit = false)
{
$permissions = [];
if ($inherit && $this->getNestedProperty('header.permissions.inherit', true)) {
$parent = $this->parent();
if ($parent && method_exists($parent, 'getPermissions')) {
$permissions = $parent->getPermissions($inherit);
if (null === $this->_permissionsCache) {
$permissions = [];
if ($inherit && $this->getNestedProperty('header.permissions.inherit', true)) {
$parent = $this->parent();
if ($parent && method_exists($parent, 'getPermissions')) {
$permissions = $parent->getPermissions($inherit);
}
}
$this->_permissionsCache = $this->loadPermissions($permissions);
}
return $this->loadPermissions($permissions);
return $this->_permissionsCache;
}
/**
@@ -277,6 +277,8 @@ trait PageLegacyTrait
throw new RuntimeException('Failed: Cannot set page parent to a child of current page');
}
$this->storeOriginal();
// TODO:
throw new RuntimeException(__METHOD__ . '(): Not Implemented');
}
@@ -292,6 +294,8 @@ trait PageLegacyTrait
*/
public function copy(PageInterface $parent = null)
{
$this->storeOriginal();
$filesystem = Filesystem::getInstance(false);
$parentStorageKey = ltrim($filesystem->dirname("/{$this->getMasterKey()}"), '/');
@@ -715,8 +719,9 @@ trait PageLegacyTrait
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$folder = $locator->isStream($folder) ? $locator->getResource($folder) : GRAV_ROOT . "/{$folder}";
return $locator->findResource($folder, true, true) . '/' . ($this->isPage() ? $this->name() : 'default.md');
return $folder . '/' . ($this->isPage() ? $this->name() : 'default.md');
}
/**
@@ -733,8 +738,9 @@ trait PageLegacyTrait
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$folder = $locator->isStream($folder) ? $locator->getResource($folder, false) : $folder;
return $locator->findResource($folder, false, true) . '/' . ($this->isPage() ? $this->name() : 'default.md');
return $folder . '/' . ($this->isPage() ? $this->name() : 'default.md');
}
/**
@@ -1085,18 +1091,6 @@ trait PageLegacyTrait
return $this->exists() || is_dir($this->getStorageFolder() ?? '');
}
/**
* Gets the Page Unmodified (original) version of the page.
*
* Assumes that object has been cloned before modifying it.
*
* @return PageInterface|null The original version of the page.
*/
public function getOriginal()
{
return $this->getFlexDirectory()->getObject($this->getKey());
}
/**
* Gets the action.
*
@@ -18,6 +18,7 @@ use Grav\Common\Uri;
use Grav\Framework\Filesystem\Filesystem;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RuntimeException;
use function dirname;
use function is_string;
/**
@@ -32,6 +33,8 @@ trait PageRoutableTrait
private $_route;
/** @var string|null */
private $_path;
/** @var PageInterface|null */
private $_parentCache;
/**
* Returns the page extension, got from the page `url_extension` config and falls back to the
@@ -317,7 +320,7 @@ trait PageRoutableTrait
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$path = $locator->findResource($folder, false);
$path = $locator->isStream($folder) ? $locator->findResource($folder, false) : $folder;
return is_string($path) ? $path : null;
}
@@ -350,7 +353,7 @@ trait PageRoutableTrait
if ($folder) {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$folder = $locator($folder);
$folder = $locator->isStream($folder) ? $locator->getResource($folder) : GRAV_ROOT . "/{$folder}";
}
return $this->_path = is_string($folder) ? $folder : null;
@@ -413,13 +416,12 @@ trait PageRoutableTrait
throw new RuntimeException(__METHOD__ . '(PageInterface): Not Implemented');
}
if ($this->root()) {
return null;
if ($this->_parentCache || $this->root()) {
return $this->_parentCache;
}
$filesystem = Filesystem::getInstance(false);
$directory = $this->getFlexDirectory();
$parentKey = ltrim($filesystem->dirname("/{$this->getKey()}"), '/');
$parentKey = ltrim(dirname("/{$this->getKey()}"), '/');
if ($parentKey) {
$parent = $directory->getObject($parentKey);
$language = $this->getLanguage();
@@ -427,12 +429,14 @@ trait PageRoutableTrait
$parent = $parent->getTranslation($language) ?? $parent;
}
return $parent;
$this->_parentCache = $parent;
} else {
$index = $directory->getIndex();
$this->_parentCache = method_exists($index, 'getRoot') ? $index->getRoot() : null;
}
$index = $directory->getIndex();
return method_exists($index, 'getRoot') ? $index->getRoot() : null;
return $this->_parentCache;
}
/**
@@ -186,10 +186,10 @@ abstract class AbstractFilesystemStorage implements FlexStorageInterface
$locator = Grav::instance()['locator'];
if (!$locator->isStream($path)) {
return $path;
return GRAV_ROOT . "/{$path}";
}
return (string)($locator->findResource($path) ?: $locator->findResource($path, true, true));
return $locator->getResource($path);
}
/**
@@ -83,6 +83,8 @@ class FileStorage extends FolderStorage
$path = $this->getPathFromKey($src);
$file = $this->getFile($path);
$file->delete();
$file->free();
unset($file);
return true;
}
@@ -377,12 +377,14 @@ class FolderStorage extends AbstractFilesystemStorage
$file = $this->getFile($path);
try {
$data = (array)$file->content();
$file->free();
if (isset($data[0])) {
throw new RuntimeException('Broken object file');
}
} catch (RuntimeException $e) {
$data = ['__ERROR' => $e->getMessage()];
} finally {
$file->free();
unset($file);
}
$data['__META'] = $this->getObjectMeta($key);
@@ -426,13 +428,17 @@ class FolderStorage extends AbstractFilesystemStorage
$file->save($row);
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($path)) {
$locator->clearCache();
}
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('Flex saveFile(%s): %s', $path ?? $key, $e->getMessage()));
} finally {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$locator->clearCache();
if (isset($file)) {
$file->free();
unset($file);
}
}
$row['__META'] = $this->getObjectMeta($key, true);
@@ -452,14 +458,14 @@ class FolderStorage extends AbstractFilesystemStorage
if ($file->exists()) {
$file->delete();
}
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($filename)) {
$locator->clearCache($filename);
}
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('Flex deleteFile(%s): %s', $filename, $e->getMessage()));
} finally {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$locator->clearCache();
$file->free();
}
return $data;
@@ -474,14 +480,12 @@ class FolderStorage extends AbstractFilesystemStorage
{
try {
Folder::copy($this->resolvePath($src), $this->resolvePath($dst));
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($src) || $locator->isStream($dst)) {
$locator->clearCache();
}
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('Flex copyFolder(%s, %s): %s', $src, $dst, $e->getMessage()));
} finally {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$locator->clearCache();
}
return true;
@@ -496,14 +500,12 @@ class FolderStorage extends AbstractFilesystemStorage
{
try {
Folder::move($this->resolvePath($src), $this->resolvePath($dst));
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($src) || $locator->isStream($dst)) {
$locator->clearCache();
}
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('Flex moveFolder(%s, %s): %s', $src, $dst, $e->getMessage()));
} finally {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$locator->clearCache();
}
return true;
@@ -517,17 +519,13 @@ class FolderStorage extends AbstractFilesystemStorage
protected function deleteFolder(string $path, bool $include_target = false): bool
{
try {
$success = Folder::delete($this->resolvePath($path), $include_target);
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($path)) {
$locator->clearCache();
}
return $success;
return Folder::delete($this->resolvePath($path), $include_target);
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('Flex deleteFolder(%s): %s', $path, $e->getMessage()));
} finally {
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$locator->clearCache();
}
}
@@ -669,7 +667,14 @@ class FolderStorage extends AbstractFilesystemStorage
/** @var string $pattern */
$pattern = !empty($options['pattern']) ? $options['pattern'] : $this->dataPattern;
$this->dataFolder = $options['folder'];
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
$folder = $options['folder'];
if ($locator->isStream($folder)) {
$folder = $locator->getResource($folder, false);
}
$this->dataFolder = $folder;
$this->dataFile = $options['file'] ?? 'item';
$this->dataExt = $extension;
if (mb_strpos($pattern, '{FILE}') === false && mb_strpos($pattern, '{EXT}') === false) {
@@ -414,9 +414,13 @@ class SimpleStorage extends AbstractFilesystemStorage
}
$file->save($content);
$this->modified = (int)$file->modified(); // cast false to 0
$file->free();
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('Flex save(): %s', $e->getMessage()));
} finally {
if (isset($file)) {
$file->free();
unset($file);
}
}
}
@@ -453,6 +457,10 @@ class SimpleStorage extends AbstractFilesystemStorage
$data = new Data($content);
$content = $data->get($this->prefix);
}
$file->free();
unset($file);
$this->data = $content;
$list = [];