Upgrade to 3.1.3
This commit is contained in:
@@ -538,7 +538,7 @@ class Api
|
||||
'file' => ltrim($e->getFile(), $_SERVER['DOCUMENT_ROOT'] ?? null),
|
||||
'line' => $e->getLine(),
|
||||
'code' => empty($e->getCode()) === false ? $e->getCode() : 500,
|
||||
'route' => $this->route->pattern()
|
||||
'route' => $this->route ? $this->route->pattern() : null
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Kirby\Cache;
|
||||
|
||||
use APCUIterator;
|
||||
|
||||
/**
|
||||
* APCu Cache Driver
|
||||
*
|
||||
@@ -14,6 +16,53 @@ namespace Kirby\Cache;
|
||||
class ApcuCache extends Cache
|
||||
{
|
||||
|
||||
/**
|
||||
* Checks if the current key exists in cache
|
||||
*
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists(string $key): bool
|
||||
{
|
||||
return apcu_exists($this->key($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the entire cache directory
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function flush(): bool
|
||||
{
|
||||
if (empty($this->options['prefix']) === false) {
|
||||
return apcu_delete(new APCUIterator('!^' . preg_quote($this->options['prefix']) . '!'));
|
||||
} else {
|
||||
return apcu_clear_cache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the cache
|
||||
*
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function remove(string $key): bool
|
||||
{
|
||||
return apcu_delete($this->key($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an item from the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function retrieve(string $key)
|
||||
{
|
||||
return Value::fromJson(apcu_fetch($this->key($key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an item to the cache for a given number of minutes.
|
||||
*
|
||||
@@ -29,49 +78,6 @@ class ApcuCache extends Cache
|
||||
*/
|
||||
public function set(string $key, $value, int $minutes = 0)
|
||||
{
|
||||
return apcu_store($key, $this->value($value, $minutes)->toJson(), $this->expiration($minutes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an item from the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function retrieve(string $key)
|
||||
{
|
||||
return Value::fromJson(apcu_fetch($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current key exists in cache
|
||||
*
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists(string $key): bool
|
||||
{
|
||||
return apcu_exists($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from the cache
|
||||
*
|
||||
* @param string $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function remove(string $key): bool
|
||||
{
|
||||
return apcu_delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the entire cache directory
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function flush(): bool
|
||||
{
|
||||
return apcu_clear_cache();
|
||||
return apcu_store($this->key($key), $this->value($value, $minutes)->toJson(), $this->expiration($minutes));
|
||||
}
|
||||
}
|
||||
|
@@ -52,6 +52,21 @@ class Cache
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the prefix to the key if given
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function key(string $key): string
|
||||
{
|
||||
if (empty($this->options['prefix']) === false) {
|
||||
$key = $this->options['prefix'] . '/' . $key;
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private method to retrieve the cache value
|
||||
* This needs to be defined by the driver
|
||||
|
@@ -35,11 +35,6 @@ class FileCache extends Cache
|
||||
|
||||
// try to create the directory
|
||||
Dir::make($this->options['root'], true);
|
||||
|
||||
// check for a valid cache directory
|
||||
if (is_dir($this->options['root']) === false) {
|
||||
throw new Exception('The cache directory does not exist');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +46,8 @@ class FileCache extends Cache
|
||||
protected function file(string $key): string
|
||||
{
|
||||
$extension = isset($this->options['extension']) ? '.' . $this->options['extension'] : '';
|
||||
return $this->options['root'] . '/' . $key . $extension;
|
||||
|
||||
return $this->options['root'] . '/' . $this->key($key) . $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +113,13 @@ class FileCache extends Cache
|
||||
*/
|
||||
public function flush(): bool
|
||||
{
|
||||
if (Dir::remove($this->options['root']) === true && Dir::make($this->options['root']) === true) {
|
||||
$root = $this->options['root'];
|
||||
|
||||
if (empty($this->options['prefix']) === false) {
|
||||
$root = $root . '/' . $this->options['prefix'];
|
||||
}
|
||||
|
||||
if (Dir::remove($root) === true && Dir::make($root) === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -232,6 +232,33 @@ class App
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all available blueprints for this installation
|
||||
*
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
public function blueprints(string $type = 'pages')
|
||||
{
|
||||
$blueprints = [];
|
||||
|
||||
foreach ($this->extensions('blueprints') as $name => $blueprint) {
|
||||
if (dirname($name) === $type) {
|
||||
$name = basename($name);
|
||||
$blueprints[$name] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (glob($this->root('blueprints') . '/' . $type . '/*.yml') as $blueprint) {
|
||||
$name = F::name($blueprint);
|
||||
$blueprints[$name] = $name;
|
||||
}
|
||||
|
||||
ksort($blueprints);
|
||||
|
||||
return array_values($blueprints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls any Kirby route
|
||||
*
|
||||
@@ -406,7 +433,7 @@ class App
|
||||
$visitor = $this->visitor();
|
||||
|
||||
foreach ($visitor->acceptedLanguages() as $lang) {
|
||||
if ($language = $languages->findBy('locale', $lang->locale())) {
|
||||
if ($language = $languages->findBy('locale', $lang->locale(LC_ALL))) {
|
||||
return $language;
|
||||
}
|
||||
}
|
||||
@@ -1156,9 +1183,11 @@ class App
|
||||
public function trigger(string $name, ...$arguments)
|
||||
{
|
||||
if ($functions = $this->extension('hooks', $name)) {
|
||||
static $level = 0;
|
||||
static $triggered = [];
|
||||
$level++;
|
||||
|
||||
foreach ($functions as $function) {
|
||||
foreach ($functions as $index => $function) {
|
||||
if (in_array($function, $triggered[$name] ?? []) === true) {
|
||||
continue;
|
||||
}
|
||||
@@ -1169,6 +1198,12 @@ class App
|
||||
// bind the App object to the hook
|
||||
$function->call($this, ...$arguments);
|
||||
}
|
||||
|
||||
$level--;
|
||||
|
||||
if ($level === 0) {
|
||||
$triggered = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1204,6 +1239,16 @@ class App
|
||||
return static::$version = static::$version ?? Data::read(static::$root . '/composer.json')['version'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hash of the version number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function versionHash(): string
|
||||
{
|
||||
return md5(static::version());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the visitor object
|
||||
*
|
||||
|
@@ -82,8 +82,13 @@ class ContentTranslation
|
||||
*/
|
||||
public function content(): array
|
||||
{
|
||||
$parent = $this->parent();
|
||||
$content = $this->content ?? $parent->readContent($this->code());
|
||||
$parent = $this->parent();
|
||||
|
||||
if ($this->content === null) {
|
||||
$this->content = $parent->readContent($this->code());
|
||||
}
|
||||
|
||||
$content = $this->content;
|
||||
|
||||
// merge with the default content
|
||||
if ($this->isDefault() === false && $defaultLanguage = $parent->kirby()->defaultLanguage()) {
|
||||
|
@@ -21,7 +21,8 @@ class Form extends BaseForm
|
||||
|
||||
if ($kirby->multilang() === true) {
|
||||
$fields = $props['fields'] ?? [];
|
||||
$isDefaultLanguage = $kirby->language()->isDefault();
|
||||
$languageCode = $props['language'] ?? $kirby->language()->code();
|
||||
$isDefaultLanguage = $languageCode === $kirby->defaultLanguage()->code();
|
||||
|
||||
foreach ($fields as $fieldName => $fieldProps) {
|
||||
// switch untranslatable fields to readonly
|
||||
@@ -40,7 +41,7 @@ class Form extends BaseForm
|
||||
public static function for(Model $model, array $props = [])
|
||||
{
|
||||
// get the original model data
|
||||
$original = $model->content()->toArray();
|
||||
$original = $model->content($props['language'] ?? null)->toArray();
|
||||
$values = $props['values'] ?? [];
|
||||
|
||||
// convert closures to values
|
||||
|
@@ -46,7 +46,7 @@ class Language extends Model
|
||||
protected $direction;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var array
|
||||
*/
|
||||
protected $locale;
|
||||
|
||||
@@ -293,13 +293,18 @@ class Language extends Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PHP locale setting string
|
||||
* Returns the PHP locale setting array
|
||||
*
|
||||
* @return string
|
||||
* @param int $category If passed, returns the locale for the specified category (e.g. LC_ALL) as string
|
||||
* @return array|string
|
||||
*/
|
||||
public function locale(): string
|
||||
public function locale(int $category = null)
|
||||
{
|
||||
return $this->locale;
|
||||
if ($category !== null) {
|
||||
return $this->locale[$category] ?? $this->locale[LC_ALL] ?? null;
|
||||
} else {
|
||||
return $this->locale;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,12 +406,21 @@ class Language extends Model
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @param string|array $locale
|
||||
* @return self
|
||||
*/
|
||||
protected function setLocale(string $locale = null): self
|
||||
protected function setLocale($locale = null): self
|
||||
{
|
||||
$this->locale = $locale ?? $this->code;
|
||||
if (is_array($locale)) {
|
||||
$this->locale = $locale;
|
||||
} elseif (is_string($locale)) {
|
||||
$this->locale = [LC_ALL => $locale];
|
||||
} elseif ($locale === null) {
|
||||
$this->locale = [LC_ALL => $this->code];
|
||||
} else {
|
||||
throw new InvalidArgumentException('Locale must be string or array');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@@ -67,7 +67,7 @@ class Languages extends Collection
|
||||
$files = glob(App::instance()->root('languages') . '/*.php');
|
||||
|
||||
foreach ($files as $file) {
|
||||
$props = include_once $file;
|
||||
$props = include $file;
|
||||
|
||||
if (is_array($props) === true) {
|
||||
|
||||
|
@@ -405,15 +405,16 @@ abstract class ModelWithContent extends Model
|
||||
* Updates the model data
|
||||
*
|
||||
* @param array $input
|
||||
* @param string $language
|
||||
* @param string $languageCode
|
||||
* @param boolean $validate
|
||||
* @return self
|
||||
*/
|
||||
public function update(array $input = null, string $languageCode = null, bool $validate = false)
|
||||
{
|
||||
$form = Form::for($this, [
|
||||
'input' => $input,
|
||||
'ignoreDisabled' => $validate === false,
|
||||
'input' => $input,
|
||||
'language' => $languageCode,
|
||||
]);
|
||||
|
||||
// validate the input
|
||||
|
@@ -30,7 +30,7 @@ class Panel
|
||||
{
|
||||
$mediaRoot = $kirby->root('media') . '/panel';
|
||||
$panelRoot = $kirby->root('panel') . '/dist';
|
||||
$versionHash = md5($kirby->version());
|
||||
$versionHash = $kirby->versionHash();
|
||||
$versionRoot = $mediaRoot . '/' . $versionHash;
|
||||
|
||||
// check if the version already exists
|
||||
@@ -72,12 +72,15 @@ class Panel
|
||||
// get the uri object for the panel url
|
||||
$uri = new Uri($url = $kirby->url('panel'));
|
||||
|
||||
$pluginCss = new PanelPlugins('css');
|
||||
$pluginJs = new PanelPlugins('js');
|
||||
|
||||
$view = new View($kirby->root('kirby') . '/views/panel.php', [
|
||||
'kirby' => $kirby,
|
||||
'config' => $kirby->option('panel'),
|
||||
'assetUrl' => $kirby->url('media') . '/panel/' . md5($kirby->version()),
|
||||
'pluginCss' => $kirby->url('media') . '/plugins/index.css',
|
||||
'pluginJs' => $kirby->url('media') . '/plugins/index.js',
|
||||
'assetUrl' => $kirby->url('media') . '/panel/' . $kirby->versionHash(),
|
||||
'pluginCss' => $pluginCss->url(),
|
||||
'pluginJs' => $pluginJs->url(),
|
||||
'icons' => F::read($kirby->root('panel') . '/dist/img/icons.svg'),
|
||||
'panelUrl' => $uri->path()->toString(true) . '/',
|
||||
'options' => [
|
||||
|
232
kirby/src/Cms/PanelPlugins.php
Executable file
232
kirby/src/Cms/PanelPlugins.php
Executable file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace Kirby\Cms;
|
||||
|
||||
use Kirby\Toolkit\Dir;
|
||||
use Kirby\Toolkit\F;
|
||||
|
||||
/**
|
||||
* The PanelPlugins class takes care of collecting
|
||||
* js and css plugin files for the panel and caches
|
||||
* them in the media folder
|
||||
*/
|
||||
class PanelPlugins
|
||||
{
|
||||
|
||||
/**
|
||||
* Cache of all collected plugin files
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $files;
|
||||
|
||||
/**
|
||||
* Cache of the unique plugin hash for the url and root
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $hash;
|
||||
|
||||
/**
|
||||
* css or js
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* Creates a new panel plugin instance by type (css or js)
|
||||
*
|
||||
* @param string $type
|
||||
*/
|
||||
public function __construct(string $type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects and returns the plugin files for all plugins
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function files(): array
|
||||
{
|
||||
if ($this->files !== null) {
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
$this->files = [];
|
||||
|
||||
foreach (App::instance()->plugins() as $plugin) {
|
||||
$file = $plugin->root() . '/index.' . $this->type;
|
||||
|
||||
if (file_exists($file) === true) {
|
||||
$this->files[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the cache exists
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function exist(): bool
|
||||
{
|
||||
return file_exists($this->root());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the cache folder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function folder(): string
|
||||
{
|
||||
return 'panel/' . App::versionHash() . '/plugins/' . $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects and removes garbage from old plugin versions
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function gc(): bool
|
||||
{
|
||||
$folder = App::instance()->root('media') . '/' . $this->folder();
|
||||
|
||||
foreach (glob($folder . '/*') as $dir) {
|
||||
$name = basename($dir);
|
||||
|
||||
if ($name !== $this->hash()) {
|
||||
Dir::remove($dir);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique hash for the cache file
|
||||
* The hash is generated from all plugin filenames
|
||||
* and the max modification date to make sure changes
|
||||
* will always be cached properly
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hash(): string
|
||||
{
|
||||
if ($this->hash !== null) {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
return $this->hash = $this->id() . '-' . $this->modified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique id based on all
|
||||
* plugin file roots
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function id(): string
|
||||
{
|
||||
return crc32(implode(array_values($this->files())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification
|
||||
* of the collected plugin files
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function modified(): int
|
||||
{
|
||||
$files = $this->files();
|
||||
$modified = [0];
|
||||
|
||||
foreach ($files as $file) {
|
||||
$modified[] = F::modified($file);
|
||||
}
|
||||
|
||||
return max($modified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path to the cache file
|
||||
* This is used for the root and url methods
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function path(): string
|
||||
{
|
||||
return $this->folder() . '/' . $this->hash() . '/index.' . $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the files from all plugins and concatenate them
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function read(): string
|
||||
{
|
||||
$dist = [];
|
||||
|
||||
foreach ($this->files() as $file) {
|
||||
$dist[] = file_get_contents($file);
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, $dist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the cache exists and
|
||||
* otherwise (re)creates it
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function publish(): bool
|
||||
{
|
||||
if ($this->exist() === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->write();
|
||||
$this->gc();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute path to the cache file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function root(): string
|
||||
{
|
||||
return App::instance()->root('media') . '/' . $this->path();
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute url to the cache file
|
||||
* This is used by the panel to link the plugins
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url(): string
|
||||
{
|
||||
return App::instance()->url('media') . '/' . $this->path();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the cache file
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function write(): bool
|
||||
{
|
||||
return F::write($this->root(), $this->read());
|
||||
}
|
||||
}
|
@@ -13,9 +13,10 @@ class Permissions
|
||||
{
|
||||
protected $actions = [
|
||||
'access' => [
|
||||
'panel' => true,
|
||||
'users' => true,
|
||||
'site' => true
|
||||
'panel' => true,
|
||||
'settings' => true,
|
||||
'site' => true,
|
||||
'users' => true,
|
||||
],
|
||||
'files' => [
|
||||
'changeName' => true,
|
||||
|
@@ -13,49 +13,6 @@ use Kirby\Toolkit\F;
|
||||
*/
|
||||
class PluginAssets
|
||||
{
|
||||
|
||||
/**
|
||||
* Concatenate all plugin js and css files into
|
||||
* a single file and copy them to /media/plugins/index.css or /media/plugins/index.js
|
||||
*
|
||||
* @param string $extension
|
||||
* @return string
|
||||
*/
|
||||
public static function index(string $extension): string
|
||||
{
|
||||
$kirby = App::instance();
|
||||
$cache = $kirby->root('media') . '/plugins/.index.' . $extension;
|
||||
$build = false;
|
||||
$modified = [0];
|
||||
$assets = [];
|
||||
|
||||
foreach ($kirby->plugins() as $plugin) {
|
||||
$file = $plugin->root() . '/index.' . $extension;
|
||||
|
||||
if (file_exists($file) === true) {
|
||||
$assets[] = $file;
|
||||
$modified[] = F::modified($file);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($assets)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file_exists($cache) === false || filemtime($cache) < max($modified)) {
|
||||
$dist = [];
|
||||
foreach ($assets as $asset) {
|
||||
$dist[] = file_get_contents($asset);
|
||||
}
|
||||
$dist = implode(PHP_EOL, $dist);
|
||||
F::write($cache, $dist);
|
||||
} else {
|
||||
$dist = file_get_contents($cache);
|
||||
}
|
||||
|
||||
return $dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean old/deprecated assets on every resolve
|
||||
*
|
||||
@@ -105,6 +62,9 @@ class PluginAssets
|
||||
$target = $plugin->mediaRoot() . '/' . $filename;
|
||||
$url = $plugin->mediaUrl() . '/' . $filename;
|
||||
|
||||
// create the plugin directory first
|
||||
Dir::make($plugin->mediaRoot(), true);
|
||||
|
||||
if (F::link($source, $target, 'symlink') === true) {
|
||||
return Response::redirect($url);
|
||||
}
|
||||
|
@@ -284,9 +284,7 @@ trait UserActions
|
||||
*/
|
||||
protected function writeCredentials(array $credentials): bool
|
||||
{
|
||||
$export = '<?php' . PHP_EOL . PHP_EOL . 'return ' . var_export($credentials, true) . ';';
|
||||
|
||||
return F::write($this->root() . '/index.php', $export);
|
||||
return Data::write($this->root() . '/index.php', $credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -82,6 +82,11 @@ class PHP extends Handler
|
||||
$php = static::encode($data);
|
||||
$php = "<?php\n\nreturn $php;";
|
||||
|
||||
return F::write($file, $php);
|
||||
if (F::write($file, $php) === true) {
|
||||
F::invalidateOpcodeCache($file);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -56,6 +56,8 @@ class Yaml extends Handler
|
||||
return $yaml;
|
||||
}
|
||||
|
||||
// remove bom
|
||||
$yaml = str_replace("\xEF\xBB\xBF", '', $yaml);
|
||||
$result = Spyc::YAMLLoadString($yaml);
|
||||
|
||||
if (is_array($result)) {
|
||||
|
@@ -352,7 +352,7 @@ class FileSessionStore extends SessionStore
|
||||
foreach ($iterator as $file) {
|
||||
// make sure that the file is a session file
|
||||
// prevents deleting files like .gitignore or other unrelated files
|
||||
if (preg_match('/[0-9]+\.[a-z0-9]+\.sess/', $file->getFilename()) !== 1) {
|
||||
if (preg_match('/^[0-9]+\.[a-z0-9]+\.sess$/', $file->getFilename()) !== 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -364,9 +364,6 @@ class FileSessionStore extends SessionStore
|
||||
if ($expiryTime < $currentTime) {
|
||||
// the session has expired, delete it
|
||||
$this->destroy($expiryTime, $id);
|
||||
} else {
|
||||
// the following files are all going to be still valid
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -57,8 +57,12 @@ class A
|
||||
* returned if no element has been found
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get(array $array, $key, $default = null)
|
||||
public static function get($array, $key, $default = null)
|
||||
{
|
||||
if (is_array($array) === false) {
|
||||
return $array;
|
||||
}
|
||||
|
||||
// return the entire array if the key is null
|
||||
if ($key === null) {
|
||||
return $array;
|
||||
@@ -79,17 +83,28 @@ class A
|
||||
|
||||
// support dot notation
|
||||
if (strpos($key, '.') !== false) {
|
||||
$keys = explode('.', $key);
|
||||
$keys = explode('.', $key);
|
||||
$firstKey = array_shift($keys);
|
||||
|
||||
foreach ($keys as $innerKey) {
|
||||
if (isset($array[$innerKey]) === false) {
|
||||
return $default;
|
||||
if (isset($array[$firstKey]) === false) {
|
||||
$currentKey = $firstKey;
|
||||
|
||||
while ($innerKey = array_shift($keys)) {
|
||||
$currentKey = $currentKey . '.' . $innerKey;
|
||||
|
||||
if (isset($array[$currentKey]) === true) {
|
||||
return static::get($array[$currentKey], implode('.', $keys), $default);
|
||||
}
|
||||
}
|
||||
|
||||
$array = $array[$innerKey];
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $array;
|
||||
if (is_array($array[$firstKey]) === true) {
|
||||
return static::get($array[$firstKey], implode('.', $keys), $default);
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $default;
|
||||
|
@@ -27,12 +27,7 @@ class Controller
|
||||
|
||||
foreach ($info->getParameters() as $parameter) {
|
||||
$name = $parameter->getName();
|
||||
|
||||
if (isset($data[$name]) === false) {
|
||||
throw new Exception(sprintf('The "%s" parameter is missing', $name));
|
||||
}
|
||||
|
||||
$args[] = $data[$name];
|
||||
$args[] = $data[$name] ?? null;
|
||||
}
|
||||
|
||||
return $args;
|
||||
|
@@ -264,6 +264,21 @@ class F
|
||||
return pathinfo($name, PATHINFO_BASENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate opcode cache for file.
|
||||
*
|
||||
* @param string $file The path of the file
|
||||
* @return boolean
|
||||
*/
|
||||
public static function invalidateOpcodeCache(string $file): bool
|
||||
{
|
||||
if (function_exists('opcache_invalidate') && strlen(ini_get('opcache.restrict_api')) === 0) {
|
||||
return opcache_invalidate($file, true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a file is of a certain type
|
||||
*
|
||||
|
Reference in New Issue
Block a user