Compare commits

...

23 Commits
1.6.1 ... 1.6.4

Author SHA1 Message Date
Andy Miller
2bc6848464 Merge branch 'release/1.6.4' 2019-04-15 14:48:10 -06:00
Andy Miller
abefbfc776 prepare for release 2019-04-15 14:48:01 -06:00
Andy Miller
ad173ca129 Improved redirect_default_route logic as well as Uri::toArray() to take into account root_path and extension 2019-04-15 12:44:48 -06:00
Andy Miller
d69ef0e39c Refactored rounded logic in Utils::parseSize() #2394 2019-04-15 11:00:11 -06:00
Matias Griese
436be17881 Fixed Flex simple storage not being properly initialized if used with caching 2019-04-15 14:26:55 +03:00
Andy Miller
9a5fa7e699 Extra forcing of first level arrays in taxonomy 2019-04-14 13:08:57 -06:00
Andy Miller
d502ff08c1 Attempt to resolve issue in form#332 2019-04-13 17:20:45 -06:00
Andy Miller
14eb1281f9 Fix to force all Page::taxonomy to be treated as strings #2446 2019-04-13 13:53:46 -06:00
Andy Miller
8fd7a5aebe Fixes #2445 pipeline excluded assets with cache on 2019-04-13 13:18:13 -06:00
Andy Miller
08423df547 code tidy 2019-04-13 12:27:19 -06:00
Andy Miller
40563ed2f8 Better Utils::normalizePath() logic #2216 2019-04-13 12:21:54 -06:00
Andy Miller
b639f09ca7 Merge branch 'release/1.6.3' 2019-04-12 19:48:13 -06:00
Andy Miller
dd134ad551 Merge tag '1.6.3' into develop
Release v1.6.3
2019-04-12 19:48:13 -06:00
Andy Miller
3d93d50cf0 prepare for release 2019-04-12 19:48:03 -06:00
Andy Miller
f1da7b6063 Fix for vUndefined errors when upgrading 2019-04-12 09:49:20 -06:00
Andy Miller
ef7b33f9b6 Fixed issue with Utils::normalizePath messing with external URLs #2216 2019-04-12 07:55:51 -06:00
Andy Miller
0f0e6ab1c8 Missed this one! #2442 2019-04-12 07:26:44 -06:00
Matias Griese
5362b312d1 Added Blueprint::addDynamicHandler() method to allow custom dynamic handlers, for example custom-options@: getCustomOptions 2019-04-12 12:23:31 +03:00
Andy Miller
ca4d6a398f Merge branch 'release/1.6.2' 2019-04-11 18:25:47 -06:00
Andy Miller
ed00d480f2 Merge tag '1.6.2' into develop
Release v1.6.2
2019-04-11 18:25:47 -06:00
Andy Miller
057bdd546b prepare for release 2019-04-11 18:25:38 -06:00
Andy Miller
7762f0c85e * Revert renaming of ClearCacheCommand to ensure CLI GPM upgrades go smoothly 2019-04-11 18:22:38 -06:00
Andy Miller
4b777f508b Merge tag '1.6.1' into develop
Release v1.6.1
2019-04-11 16:46:51 -06:00
20 changed files with 309 additions and 99 deletions

View File

@@ -1,3 +1,31 @@
# v1.6.4
## 04/15/2019
1. [](#bugfix)
* Improved `redirect_default_route` logic as well as `Uri::toArray()` to take into account `root_path` and `extension`
* Rework logic to pull out excluded files from pipeline more reliably [#2445](https://github.com/getgrav/grav/issues/2445)
* Better logic in `Utils::normalizePath` to handle externals properly [#2216](https://github.com/getgrav/grav/issues/2216)
* Fixed to force all `Page::taxonomy` to be treated as strings [#2446](https://github.com/getgrav/grav/issues/2446)
* Fixed issue with `Grav['user']` not being available [form#332](https://github.com/getgrav/grav-plugin-form/issues/332)
* Updated rounding logic for `Utils::parseSize()` [#2394](https://github.com/getgrav/grav/issues/2394)
* Fixed Flex simple storage not being properly initialized if used with caching
# v1.6.3
## 04/12/2019
1. [](#new)
* Added `Blueprint::addDynamicHandler()` method to allow custom dynamic handlers, for example `custom-options@: getCustomOptions`
1. [](#bugfix)
* Missed a `CacheCommand` reference in `bin/grav` [#2442](https://github.com/getgrav/grav/issues/2442)
* Fixed issue with `Utils::normalizePath` messing with external URLs [#2216](https://github.com/getgrav/grav/issues/2216)
* Fix for `vUndefined` versions when upgrading
# v1.6.2
## 04/11/2019
1. [](#bugfix)
* Revert renaming of `ClearCacheCommand` to ensure CLI GPM upgrades go smoothly
# v1.6.1
## 04/11/2019

View File

@@ -40,7 +40,7 @@ $app->addCommands(array(
new \Grav\Console\Cli\ComposerCommand(),
new \Grav\Console\Cli\SandboxCommand(),
new \Grav\Console\Cli\CleanCommand(),
new \Grav\Console\Cli\CacheCommand(),
new \Grav\Console\Cli\ClearCacheCommand(),
new \Grav\Console\Cli\BackupCommand(),
new \Grav\Console\Cli\NewProjectCommand(),
new \Grav\Console\Cli\SchedulerCommand(),

View File

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

View File

@@ -45,8 +45,10 @@ class Assets extends PropertyObject
// Config Options
protected $css_pipeline;
protected $css_pipeline_include_externals;
protected $css_pipeline_before_excludes;
protected $js_pipeline;
protected $js_pipeline_include_externals;
protected $js_pipeline_before_excludes;
protected $pipeline_options = [];
@@ -264,6 +266,21 @@ class Assets extends PropertyObject
protected function filterAssets($assets, $key, $value, $sort = false)
{
$results = array_filter($assets, function($asset) use ($key, $value) {
if ($key === 'position' && $value === 'pipeline') {
$type = $asset->getType();
if ($asset->getRemote() && $this->{$type . '_pipeline_include_externals'} === false) {
if ($this->{$type . '_pipeline_before_excludes'}) {
$asset->setPosition('after');
} else {
$asset->setPosition('before');
}
return false;
}
}
if ($asset[$key] === $value) return true;
return false;
});
@@ -292,11 +309,9 @@ class Assets extends PropertyObject
$before_output = '';
$pipeline_output = '';
$after_output = '';
$no_pipeline = [];
$assets = 'assets_' . $type;
$pipeline_enabled = $type . '_pipeline';
$before_excludes = $type . '_pipeline_before_excludes';
$render_pipeline = 'render' . ucfirst($type);
$group_assets = $this->filterAssets($this->$assets, 'group', $group);
@@ -309,22 +324,13 @@ class Assets extends PropertyObject
$options = array_merge($this->pipeline_options, ['timestamp' => $this->timestamp]);
$pipeline = new Pipeline($options);
$pipeline_output = $pipeline->$render_pipeline($pipeline_assets, $group, $attributes, $no_pipeline);
$pipeline_output = $pipeline->$render_pipeline($pipeline_assets, $group, $attributes);
} else {
foreach ($pipeline_assets as $asset) {
$pipeline_output .= $asset->render();
}
}
// Handle stuff that couldn't be pipelined
if (!empty($no_pipeline)) {
if ($this->{$before_excludes}) {
$after_assets = array_merge($after_assets, $no_pipeline);
} else {
$before_assets = array_merge($before_assets, $no_pipeline);
}
}
// Before Pipeline
foreach ($before_assets as $asset) {
$before_output .= $asset->render();

View File

@@ -129,6 +129,12 @@ abstract class BaseAsset extends PropertyObject
return $this->remote;
}
public function setPosition($position)
{
$this->position = $position;
return $this;
}
/**
*

View File

@@ -50,9 +50,6 @@ class Pipeline extends PropertyObject
protected $query;
protected $asset;
protected $css_pipeline_include_externals;
protected $js_pipeline_include_externals;
/**
* Closure used by the pipeline to fetch assets.
*
@@ -91,11 +88,10 @@ class Pipeline extends PropertyObject
* @param array $assets
* @param string $group
* @param array $attributes
* @param array $no_pipeline
*
* @return bool|string URL or generated content if available, else false
*/
public function renderCss($assets, $group, $attributes = [], &$no_pipeline = [])
public function renderCss($assets, $group, $attributes = [])
{
// temporary list of assets to pipeline
$inline_group = false;
@@ -119,21 +115,13 @@ class Pipeline extends PropertyObject
if (file_exists($this->assets_dir . $file)) {
$buffer = file_get_contents($this->assets_dir . $file) . "\n";
} else {
foreach ($assets as $id => $asset) {
if ($this->css_pipeline_include_externals === false && $asset->getRemote()) {
$no_pipeline[$id] = $asset;
unset($assets[$id]);
}
}
//if nothing found get out of here!
if (empty($assets) && empty($no_pipeline)) {
if (empty($assets)) {
return false;
}
// Concatenate files
$buffer = $this->gatherLinks($assets, self::CSS_ASSET, $no_pipeline);
$buffer = $this->gatherLinks($assets, self::CSS_ASSET);
// Minify if required
if ($this->shouldMinify('css')) {
@@ -164,11 +152,10 @@ class Pipeline extends PropertyObject
* @param array $assets
* @param string $group
* @param array $attributes
* @param array $no_pipeline
*
* @return bool|string URL or generated content if available, else false
*/
public function renderJs($assets, $group, $attributes = [], &$no_pipeline = [])
public function renderJs($assets, $group, $attributes = [])
{
// temporary list of assets to pipeline
$inline_group = false;
@@ -192,21 +179,13 @@ class Pipeline extends PropertyObject
if (file_exists($this->assets_dir . $file)) {
$buffer = file_get_contents($this->assets_dir . $file) . "\n";
} else {
foreach ($assets as $id => $asset) {
if ($this->js_pipeline_include_externals === false && $asset->getRemote()) {
$no_pipeline[$id] = $asset;
unset($assets[$id]);
}
}
//if nothing found get out of here!
if (empty($assets) && empty($no_pipeline)) {
if (empty($assets)) {
return false;
}
// Concatenate files
$buffer = $this->gatherLinks($assets, self::JS_ASSET, $no_pipeline);
$buffer = $this->gatherLinks($assets, self::JS_ASSET);
// Minify if required
if ($this->shouldMinify('js')) {

View File

@@ -38,11 +38,10 @@ trait AssetUtilsTrait
*
* @param array $assets
* @param bool $css
* @param array $no_pipeline
*
* @return string
*/
protected function gatherLinks(array $assets, $css = true, &$no_pipeline = [])
protected function gatherLinks(array $assets, $css = true)
{
$buffer = '';
@@ -74,9 +73,6 @@ trait AssetUtilsTrait
// No file found, skip it...
if ($file === false) {
if (!$local) { // Assume we couldn't download this file for some reason assume it's not pipeline compatible
$no_pipeline[$id] = $asset;
}
continue;
}

View File

@@ -28,6 +28,15 @@ class Blueprint extends BlueprintForm
/** @var array */
protected $defaults;
protected $handlers = [];
public function __clone()
{
if ($this->blueprintSchema) {
$this->blueprintSchema = clone $this->blueprintSchema;
}
}
public function setScope($scope)
{
$this->scope = $scope;
@@ -66,6 +75,55 @@ class Blueprint extends BlueprintForm
return $this->defaults;
}
/**
* Initialize blueprints with its dynamic fields.
*
* @return $this
*/
public function init()
{
foreach ($this->dynamic as $key => $data) {
// Locate field.
$path = explode('/', $key);
$current = &$this->items;
foreach ($path as $field) {
if (\is_object($current)) {
// Handle objects.
if (!isset($current->{$field})) {
$current->{$field} = [];
}
$current = &$current->{$field};
} else {
// Handle arrays and scalars.
if (!\is_array($current)) {
$current = [$field => []];
} elseif (!isset($current[$field])) {
$current[$field] = [];
}
$current = &$current[$field];
}
}
// Set dynamic property.
foreach ($data as $property => $call) {
$action = $call['action'];
$method = 'dynamic' . ucfirst($action);
if (isset($this->handlers[$action])) {
$callable = $this->handlers[$action];
$callable($current, $property, $call);
} elseif (method_exists($this, $method)) {
$this->{$method}($current, $property, $call);
}
}
}
return $this;
}
/**
* Merge two arrays by using blueprints.
*
@@ -165,6 +223,11 @@ class Blueprint extends BlueprintForm
return $this->blueprintSchema;
}
public function addDynamicHandler(string $name, callable $callable): void
{
$this->handlers[$name] = $callable;
}
/**
* Initialize validator.
*/

View File

@@ -12,11 +12,16 @@ namespace Grav\Common\GPM\Remote;
use Grav\Common\Data\Data;
use Grav\Common\GPM\Common\Package as BasePackage;
class Package extends BasePackage
class Package extends BasePackage implements \JsonSerializable
{
public function __construct($package, $package_type = null)
{
$data = new Data($package);
parent::__construct($data, $package_type);
}
public function jsonSerialize()
{
return $this->data;
}
}

View File

@@ -414,9 +414,7 @@ class Page implements PageInterface
$this->markdown_extra = (bool)$this->header->markdown_extra;
}
if (isset($this->header->taxonomy)) {
foreach ((array)$this->header->taxonomy as $taxonomy => $taxitems) {
$this->taxonomy[$taxonomy] = (array)$taxitems;
}
$this->taxonomy($this->header->taxonomy);
}
if (isset($this->header->max_count)) {
$this->max_count = (int)$this->header->max_count;
@@ -2296,6 +2294,14 @@ class Page implements PageInterface
public function taxonomy($var = null)
{
if ($var !== null) {
// make sure first level are arrays
array_walk($var, function(&$value) {
$value = (array) $value;
});
// make sure all values are strings
array_walk_recursive($var, function(&$value) {
$value = (string) $value;
});
$this->taxonomy = $var;
}

View File

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

View File

@@ -187,11 +187,9 @@ class Uri
$this->extension = $parts['extension'];
}
$valid_page_types = implode('|', $config->get('system.pages.types'));
// Strip the file extension for valid page types
if (preg_match('/\.(' . $valid_page_types . ')$/', $parts['basename'])) {
$path = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, $parts['dirname']), DS) . '/' . $parts['filename'];
if ($this->isValidExtension($this->extension)) {
$path = Utils::replaceLastOccurrence(".{$this->extension}", '', $path);
}
// set the new url
@@ -586,13 +584,16 @@ class Uri
public function toArray()
{
$root_path = $this->root_path ?? '';
$extension = isset($this->extension) && $this->isValidExtension($this->extension) ? '.' . $this->extension : '';
$path = $root_path . $this->path . $extension;
return [
'scheme' => $this->scheme,
'host' => $this->host,
'port' => $this->port,
'user' => $this->user,
'pass' => $this->password,
'path' => $this->path,
'path' => $path,
'params' => $this->params,
'query' => $this->query,
'fragment' => $this->fragment
@@ -1326,6 +1327,38 @@ class Uri
return null;
}
/**
* Check if this is a valid Grav extension
*
* @param $extension
* @return bool
*/
public function isValidExtension($extension)
{
$valid_page_types = implode('|', Grav::instance()['config']->get('system.pages.types'));
// Strip the file extension for valid page types
if (preg_match('/(' . $valid_page_types . ')/', $extension)) {
return true;
}
return false;
}
/**
* Allow overriding of any element (be careful!)
*
* @param $data
* @return Uri
*/
public function setUriProperties($data)
{
foreach (get_object_vars($this) as $property => $default) {
if (!array_key_exists($property, $data)) continue;
$this->{$property} = $data[$property]; // assign value to object
}
return $this;
}
/**
* Get the base URI with port if needed
*

View File

@@ -20,7 +20,9 @@ abstract class Utils
{
protected static $nonces = [];
protected const ROOTURL_REGEX = '{^(\/*)}';
protected const ROOTURL_REGEX = '{^((?:http[s]?:\/\/[^\/]+)|(?:\/\/[^\/]+))(.*)}';
// ^((?:http[s]?:)?[\/]?(?:\/))
/**
* Simple helper method to make getting a Grav URL easier
@@ -784,26 +786,46 @@ abstract class Utils
*/
public static function normalizePath($path)
{
// Resolve any streams
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($path)) {
$path = $locator->findResource($path);
}
// Set root properly for any URLs
$root = '';
preg_match(self::ROOTURL_REGEX, $path, $matches);
if ($matches) {
$root = $matches[0];
$root = $matches[1];
$path = $matches[2];
}
$clean_path = static::replaceFirstOccurrence($root, '', $path);
$segments = explode('/', trim($clean_path, '/'));
$ret = [];
foreach ($segments as $segment) {
if (($segment === '.') || $segment === '') {
continue;
}
if ($segment === '..') {
array_pop($ret);
} else {
$ret[] = $segment;
}
// Strip off leading / to ensure explode is accurate
if (Utils::startsWith($path,'/')) {
$root .= '/';
$path = ltrim($path, '/');
}
$normalized = $root . implode('/', $ret);
// If there are any relative paths (..) handle those
if (Utils::contains($path, '..')) {
$segments = explode('/', trim($path, '/'));
$ret = [];
foreach ($segments as $segment) {
if (($segment === '.') || $segment === '') {
continue;
}
if ($segment === '..') {
array_pop($ret);
} else {
$ret[] = $segment;
}
}
$path = implode('/', $ret);
}
// Stick everything back together
$normalized = $root . $path;
return $normalized;
}
@@ -1383,10 +1405,10 @@ abstract class Utils
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size);
$size = preg_replace('/[^0-9\.]/', '', $size);
if ($unit) {
return (int)((int)$size * (1024 ** stripos('bkmgtpezy', $unit[0])));
return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
} else {
return round($size);
}
return (int)$size;
}
/**

View File

@@ -13,7 +13,7 @@ use Grav\Common\Cache;
use Grav\Console\ConsoleCommand;
use Symfony\Component\Console\Input\InputOption;
class CacheCommand extends ConsoleCommand
class ClearCacheCommand extends ConsoleCommand
{
protected function configure()
{

View File

@@ -13,7 +13,7 @@ use Grav\Common\Cache;
use Grav\Common\Grav;
use Grav\Common\Composer;
use Grav\Common\GravTrait;
use Grav\Console\Cli\CacheCommand;
use Grav\Console\Cli\ClearCacheCommand;
use RocketTheme\Toolbox\File\YamlFile;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\ArrayInput;
@@ -107,7 +107,7 @@ trait ConsoleTrait
$all = ['--all' => true];
}
$command = new CacheCommand();
$command = new ClearCacheCommand();
$input = new ArrayInput($all);
return $command->run($input, $this->output);
}

View File

@@ -71,7 +71,7 @@ class FolderStorage extends AbstractFilesystemStorage
*/
public function hasKey(string $key): bool
{
return $key && !strpos($key, '@@') && file_exists($this->getPathFromKey($key));
return $key && strpos($key, '@@') === false && file_exists($this->getPathFromKey($key));
}
/**

View File

@@ -71,7 +71,11 @@ class SimpleStorage extends AbstractFilesystemStorage
*/
public function hasKey(string $key): bool
{
return $key && !strpos($key, '@@') && isset($this->data[$key]);
if (null === $this->data) {
$this->buildIndex();
}
return $key && strpos($key, '@@') === false && isset($this->data[$key]);
}
/**
@@ -80,6 +84,10 @@ class SimpleStorage extends AbstractFilesystemStorage
*/
public function createRows(array $rows): array
{
if (null === $this->data) {
$this->buildIndex();
}
$list = [];
foreach ($rows as $key => $row) {
$key = $this->getNewKey();
@@ -99,6 +107,10 @@ class SimpleStorage extends AbstractFilesystemStorage
*/
public function readRows(array $rows, array &$fetched = null): array
{
if (null === $this->data) {
$this->buildIndex();
}
$list = [];
foreach ($rows as $key => $row) {
if (null === $row || (!\is_object($row) && !\is_array($row))) {
@@ -123,6 +135,10 @@ class SimpleStorage extends AbstractFilesystemStorage
*/
public function updateRows(array $rows): array
{
if (null === $this->data) {
$this->buildIndex();
}
$list = [];
foreach ($rows as $key => $row) {
$key = (string)$key;
@@ -144,6 +160,10 @@ class SimpleStorage extends AbstractFilesystemStorage
*/
public function deleteRows(array $rows): array
{
if (null === $this->data) {
$this->buildIndex();
}
$list = [];
foreach ($rows as $key => $row) {
$key = (string)$key;
@@ -166,6 +186,10 @@ class SimpleStorage extends AbstractFilesystemStorage
*/
public function replaceRows(array $rows): array
{
if (null === $this->data) {
$this->buildIndex();
}
$list = [];
foreach ($rows as $key => $row) {
$this->data[$key] = $list[$key] = $row;
@@ -184,6 +208,10 @@ class SimpleStorage extends AbstractFilesystemStorage
*/
public function renameRow(string $src, string $dst): bool
{
if (null === $this->data) {
$this->buildIndex();
}
if ($this->hasKey($dst)) {
throw new \RuntimeException("Cannot rename object: key '{$dst}' is already taken");
}
@@ -221,6 +249,10 @@ class SimpleStorage extends AbstractFilesystemStorage
protected function save() : void
{
if (null === $this->data) {
$this->buildIndex();
}
try {
$file = $this->getFile($this->getStoragePath());
$file->save($this->data);

View File

@@ -16,7 +16,6 @@ use Grav\Common\Form\FormFlash;
use Grav\Common\Grav;
use Grav\Common\Utils;
use Grav\Framework\Form\Interfaces\FormInterface;
use Grav\Framework\Session\Session;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UploadedFileInterface;
@@ -309,24 +308,30 @@ trait FormTrait
public function getFlash(): FormFlash
{
if (null === $this->flash) {
/** @var Grav $grav */
$grav = Grav::instance();
$user = $grav['user'];
$id = null;
$rememberState = $this->getBlueprint()->get('form/remember_state');
if ($rememberState === 'user') {
$id = $user->username;
$user = $grav['user'] ?? null;
if (isset($user)) {
$rememberState = $this->getBlueprint()->get('form/remember_state');
if ($rememberState === 'user') {
$id = $user->username;
}
}
// By default store flash by the session id.
if (null === $id) {
/** @var Session $session */
$session = $grav['session'];
$id = $session->getId();
}
// Session Required for flash form
$session = $grav['session'] ?? null;
if (isset($session)) {
// By default store flash by the session id.
if (null === $id) {
$id = $session->getId();
}
$this->flash = new FormFlash($id, $this->getUniqueId(), $this->getName());
$this->flash->setUrl($grav['uri']->url)->setUser($user);
$this->flash = new FormFlash($id, $this->getUniqueId(), $this->getName());
$this->flash->setUrl($grav['uri']->url)->setUser($user);
}
}
return $this->flash;

View File

@@ -573,7 +573,7 @@ class UriTest extends \Codeception\TestCase\Test
'rootUrl' => 'http://localhost',
'extension' => 'html',
'addNonce' => 'http://localhost/a-page.html/nonce:{{nonce}}',
'__toString' => 'http://localhost/a-page', // FIXME <-
'__toString' => 'http://localhost/a-page.html',
],
'http://localhost/a-page.json' => [
'scheme' => 'http://',
@@ -596,7 +596,7 @@ class UriTest extends \Codeception\TestCase\Test
'rootUrl' => 'http://localhost',
'extension' => 'json',
'addNonce' => 'http://localhost/a-page.json/nonce:{{nonce}}',
'__toString' => 'http://localhost/a-page', // FIX ME <-
'__toString' => 'http://localhost/a-page.json',
],
'http://localhost/admin/ajax.json/task:getnewsfeed' => [
'scheme' => 'http://',
@@ -619,7 +619,7 @@ class UriTest extends \Codeception\TestCase\Test
'rootUrl' => 'http://localhost',
'extension' => 'json',
'addNonce' => 'http://localhost/admin/ajax.json/task:getnewsfeed/nonce:{{nonce}}',
'__toString' => 'http://localhost/admin/ajax/task:getnewsfeed',
'__toString' => 'http://localhost/admin/ajax.json/task:getnewsfeed',
],
'http://localhost/grav/admin/media.json/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==' => [
'scheme' => 'http://',
@@ -642,7 +642,7 @@ class UriTest extends \Codeception\TestCase\Test
'rootUrl' => 'http://localhost',
'extension' => 'json',
'addNonce' => 'http://localhost/grav/admin/media.json/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==/nonce:{{nonce}}',
'__toString' => 'http://localhost/grav/admin/media/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==', // FIXME <-
'__toString' => 'http://localhost/grav/admin/media.json/route:L1VzZXJzL3JodWsvd29ya3NwYWNlL2dyYXYtZGVtby1zYW1wbGVyL3VzZXIvYXNzZXRzL3FRMXB4Vk1ERTNJZzh5Ni5qcGc=/task:removeFileFromBlueprint/proute:/blueprint:Y29uZmlnL2RldGFpbHM=/type:config/field:deep.nested.custom_file/path:dXNlci9hc3NldHMvcVExcHhWTURFM0lnOHk2LmpwZw==',
],
'http://localhost/a-page.foo' => [
'scheme' => 'http://',
@@ -1121,6 +1121,24 @@ class UriTest extends \Codeception\TestCase\Test
];
$this->assertSame('http://foo:bar@localhost:8080/test?x=2#xxx', Uri::buildUrl($parsed_url));
/** @var Uri $uri */
$uri = Grav::instance()['uri'];
$uri->initializeWithUrlAndRootPath('https://testing.dev/subdir/path1/path2/file.html', '/subdir')->init();
$this->assertSame('https://testing.dev/subdir/path1/path2/file.html', Uri::buildUrl($uri->toArray()));
$uri->initializeWithUrlAndRootPath('https://testing.dev/subdir/path1/path2/file.foo', '/subdir')->init();
$this->assertSame('https://testing.dev/subdir/path1/path2/file.foo', Uri::buildUrl($uri->toArray()));
$uri->initializeWithUrlAndRootPath('https://testing.dev/subdir/path1/path2/file.html', '/subdir/path1')->init();
$this->assertSame('https://testing.dev/subdir/path1/path2/file.html', Uri::buildUrl($uri->toArray()));
$uri->initializeWithUrlAndRootPath('https://testing.dev/subdir/path1/path2/file.html/foo:blah/bang:boom', '/subdir')->init();
$this->assertSame('https://testing.dev/subdir/path1/path2/file.html/foo:blah/bang:boom', Uri::buildUrl($uri->toArray()));
$uri->initializeWithUrlAndRootPath('https://testing.dev/subdir/path1/path2/file.html/foo:blah/bang:boom?fig=something', '/subdir')->init();
$this->assertSame('https://testing.dev/subdir/path1/path2/file.html/foo:blah/bang:boom?fig=something', Uri::buildUrl($uri->toArray()));
}
public function testConvertUrl()

View File

@@ -224,10 +224,19 @@ class UtilsTest extends \Codeception\TestCase\Test
$this->assertEquals('test', Utils::normalizePath('../test'));
$this->assertEquals('/test', Utils::normalizePath('/../test'));
$this->assertEquals('/test2', Utils::normalizePath('/test/../test2'));
$this->assertEquals('/test/test2', Utils::normalizePath('/test/./test2'));
$this->assertEquals('//something/test/test2', Utils::normalizePath('//../something/test/test2'));
$this->assertEquals('//something/test2', Utils::normalizePath('//something/test/../test2'));
$this->assertEquals('//test2', Utils::normalizePath('//something/../test/../test2'));
$this->assertEquals('/test3', Utils::normalizePath('/test/../test2/../test3'));
$this->assertEquals('//cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css', Utils::normalizePath('//cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css'));
$this->assertEquals('//use.fontawesome.com/releases/v5.8.1/css/all.css', Utils::normalizePath('//use.fontawesome.com/releases/v5.8.1/css/all.css'));
$this->assertEquals('//use.fontawesome.com/releases/v5.8.1/webfonts/fa-brands-400.eot', Utils::normalizePath('//use.fontawesome.com/releases/v5.8.1/css/../webfonts/fa-brands-400.eot'));
$this->assertEquals('http://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css', Utils::normalizePath('http://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css'));
$this->assertEquals('http://use.fontawesome.com/releases/v5.8.1/css/all.css', Utils::normalizePath('http://use.fontawesome.com/releases/v5.8.1/css/all.css'));
$this->assertEquals('http://use.fontawesome.com/releases/v5.8.1/webfonts/fa-brands-400.eot', Utils::normalizePath('http://use.fontawesome.com/releases/v5.8.1/css/../webfonts/fa-brands-400.eot'));
$this->assertEquals('https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css', Utils::normalizePath('https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css'));
$this->assertEquals('https://use.fontawesome.com/releases/v5.8.1/css/all.css', Utils::normalizePath('https://use.fontawesome.com/releases/v5.8.1/css/all.css'));
$this->assertEquals('https://use.fontawesome.com/releases/v5.8.1/webfonts/fa-brands-400.eot', Utils::normalizePath('https://use.fontawesome.com/releases/v5.8.1/css/../webfonts/fa-brands-400.eot'));
}
public function testIsFunctionDisabled()