Upgrade to 3.2.0
This commit is contained in:
@@ -9,11 +9,22 @@ namespace Kirby\Toolkit;
|
||||
*
|
||||
* @package Kirby Toolkit
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link http://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @link https://getkirby.com
|
||||
* @copyright Bastian Allgeier GmbH
|
||||
* @license https://opensource.org/licenses/MIT
|
||||
*/
|
||||
class Query
|
||||
{
|
||||
const PARTS = '!([a-zA-Z_]*(\(.*?\))?)\.|' . self::SKIP . '!';
|
||||
const METHOD = '!\((.*)\)!';
|
||||
const PARAMETERS = '!,|' . self::SKIP . '!';
|
||||
|
||||
const NO_PNTH = '\([^\(]+\)(*SKIP)(*FAIL)';
|
||||
const NO_SQBR = '\[[^]]+\](*SKIP)(*FAIL)';
|
||||
const NO_DLQU = '\"[^"]+\"(*SKIP)(*FAIL)';
|
||||
const NO_SLQU = '\'[^\']+\'(*SKIP)(*FAIL)';
|
||||
const SKIP = self::NO_PNTH . '|' . self::NO_SQBR . '|' .
|
||||
self::NO_DLQU . '|' . self::NO_SLQU;
|
||||
|
||||
/**
|
||||
* The query string
|
||||
@@ -33,7 +44,7 @@ class Query
|
||||
* Creates a new Query object
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $data
|
||||
* @param array|object $data
|
||||
*/
|
||||
public function __construct(string $query = null, $data = [])
|
||||
{
|
||||
@@ -53,13 +64,25 @@ class Query
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
$parts = $this->parts($this->query);
|
||||
return $this->resolve($this->query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the query if anything
|
||||
* can be found. Otherwise returns null.
|
||||
*
|
||||
* @param string $query
|
||||
* @return mixed
|
||||
*/
|
||||
protected function resolve(string $query)
|
||||
{
|
||||
$parts = $this->parts($query);
|
||||
$data = $this->data;
|
||||
$value = null;
|
||||
|
||||
while (count($parts)) {
|
||||
$part = array_shift($parts);
|
||||
$info = $this->info($part);
|
||||
$info = $this->part($part);
|
||||
$method = $info['method'];
|
||||
$value = null;
|
||||
|
||||
@@ -86,64 +109,90 @@ class Query
|
||||
/**
|
||||
* Breaks the query string down into its components
|
||||
*
|
||||
* @param string $token
|
||||
* @param string $query
|
||||
* @return array
|
||||
*/
|
||||
protected function parts(string $token): array
|
||||
protected function parts(string $query): array
|
||||
{
|
||||
$token = trim($token);
|
||||
$token = preg_replace_callback('!\((.*?)\)!', function ($match) {
|
||||
return '(' . str_replace('.', '@@@', $match[1]) . ')';
|
||||
}, $token);
|
||||
$query = trim($query);
|
||||
|
||||
$parts = explode('.', $token);
|
||||
// match all parts but the last
|
||||
preg_match_all(self::PARTS, $query, $match);
|
||||
|
||||
return $parts;
|
||||
// remove all matched parts from the query to retrieve last part
|
||||
foreach ($match[0] as $part) {
|
||||
$query = Str::after($query, $part);
|
||||
}
|
||||
|
||||
array_push($match[1], $query);
|
||||
return $match[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes each part of the query string and
|
||||
* extracts methods and method arguments.
|
||||
*
|
||||
* @param string $token
|
||||
* @param string $part
|
||||
* @return array
|
||||
*/
|
||||
protected function info(string $token): array
|
||||
protected function part(string $part): array
|
||||
{
|
||||
$args = [];
|
||||
$method = preg_replace_callback('!\((.*?)\)!', function ($match) use (&$args) {
|
||||
$args = array_map(function ($arg) {
|
||||
$arg = trim($arg);
|
||||
$arg = str_replace('@@@', '.', $arg);
|
||||
|
||||
if (substr($arg, 0, 1) === '"') {
|
||||
return trim($arg, '"');
|
||||
}
|
||||
|
||||
if (substr($arg, 0, 1) === '\'') {
|
||||
return trim($arg, '\'');
|
||||
}
|
||||
|
||||
switch ($arg) {
|
||||
case 'null':
|
||||
return null;
|
||||
case 'false':
|
||||
return false;
|
||||
case 'true':
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_numeric($arg) === true) {
|
||||
return (float)$arg;
|
||||
}
|
||||
|
||||
return $arg;
|
||||
}, str_getcsv($match[1], ','));
|
||||
}, $token);
|
||||
$method = preg_replace_callback(self::METHOD, function ($match) use (&$args) {
|
||||
$args = preg_split(self::PARAMETERS, $match[1]);
|
||||
$args = array_map('self::parameter', $args);
|
||||
}, $part);
|
||||
|
||||
return [
|
||||
'method' => $method,
|
||||
'args' => $args
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a parameter of query to
|
||||
* proper type.
|
||||
*
|
||||
* @param mixed $arg
|
||||
* @return mixed
|
||||
*/
|
||||
protected function parameter($arg)
|
||||
{
|
||||
$arg = trim($arg);
|
||||
|
||||
// string with double quotes
|
||||
if (substr($arg, 0, 1) === '"') {
|
||||
return trim($arg, '"');
|
||||
}
|
||||
|
||||
// string with single quotes
|
||||
if (substr($arg, 0, 1) === '\'') {
|
||||
return trim($arg, '\'');
|
||||
}
|
||||
|
||||
// boolean or null
|
||||
switch ($arg) {
|
||||
case 'null':
|
||||
return null;
|
||||
case 'false':
|
||||
return false;
|
||||
case 'true':
|
||||
return true;
|
||||
}
|
||||
|
||||
// numeric
|
||||
if (is_numeric($arg) === true) {
|
||||
return (float)$arg;
|
||||
}
|
||||
|
||||
// array: split and recursive sanitizing
|
||||
if (substr($arg, 0, 1) === '[' && substr($arg, -1) === ']') {
|
||||
$arg = substr($arg, 1, -1);
|
||||
$arg = preg_split(self::PARAMETERS, $arg);
|
||||
return array_map('self::parameter', $arg);
|
||||
}
|
||||
|
||||
// resolve parameter for objects and methods itself
|
||||
return $this->resolve($arg);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user