mirror of
https://github.com/SociallyDev/Spaces-API.git
synced 2025-08-20 13:23:47 -07:00
v2: Updates
* Simplifies & beautifies everything * Introduces a new Class system. * Errors are defaulted to AWS's handler. * New function names & more efficient handling. * Should fix a majority of the errors. Please read the README for more!
This commit is contained in:
parent
ad0726e41e
commit
e6d7753dc8
1095 changed files with 45088 additions and 2911 deletions
|
@ -29,7 +29,7 @@ class AstRuntime
|
|||
* is similar to data returned from json_decode
|
||||
* using associative arrays rather than objects.
|
||||
*
|
||||
* @return mixed|null Returns the matching data or null
|
||||
* @return mixed Returns the matching data or null
|
||||
*/
|
||||
public function __invoke($expression, $data)
|
||||
{
|
||||
|
|
|
@ -19,8 +19,8 @@ class CompilerRuntime
|
|||
private $interpreter;
|
||||
|
||||
/**
|
||||
* @param string $dir Directory used to store compiled PHP files.
|
||||
* @param Parser $parser JMESPath parser to utilize
|
||||
* @param string|null $dir Directory used to store compiled PHP files.
|
||||
* @param Parser|null $parser JMESPath parser to utilize
|
||||
* @throws \RuntimeException if the cache directory cannot be created
|
||||
*/
|
||||
public function __construct($dir = null, Parser $parser = null)
|
||||
|
@ -46,7 +46,7 @@ class CompilerRuntime
|
|||
* is similar to data returned from json_decode
|
||||
* using associative arrays rather than objects.
|
||||
*
|
||||
* @return mixed|null Returns the matching data or null
|
||||
* @return mixed Returns the matching data or null
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __invoke($expression, $data)
|
||||
|
|
|
@ -20,14 +20,16 @@ final class Env
|
|||
* @param string $expression JMESPath expression to evaluate
|
||||
* @param mixed $data JSON-like data to search
|
||||
*
|
||||
* @return mixed|null Returns the matching data or null
|
||||
* @return mixed Returns the matching data or null
|
||||
*/
|
||||
public static function search($expression, $data)
|
||||
{
|
||||
static $runtime;
|
||||
|
||||
if (!$runtime) {
|
||||
$runtime = Env::createRuntime();
|
||||
}
|
||||
|
||||
return $runtime($expression, $data);
|
||||
}
|
||||
|
||||
|
@ -39,7 +41,7 @@ final class Env
|
|||
*/
|
||||
public static function createRuntime()
|
||||
{
|
||||
switch ($compileDir = getenv(self::COMPILE_DIR)) {
|
||||
switch ($compileDir = self::getEnvVariable(self::COMPILE_DIR)) {
|
||||
case false: return new AstRuntime();
|
||||
case 'on': return new CompilerRuntime();
|
||||
default: return new CompilerRuntime($compileDir);
|
||||
|
@ -55,7 +57,8 @@ final class Env
|
|||
public static function cleanCompileDir()
|
||||
{
|
||||
$total = 0;
|
||||
$compileDir = getenv(self::COMPILE_DIR) ?: sys_get_temp_dir();
|
||||
$compileDir = self::getEnvVariable(self::COMPILE_DIR) ?: sys_get_temp_dir();
|
||||
|
||||
foreach (glob("{$compileDir}/jmespath_*.php") as $file) {
|
||||
$total++;
|
||||
unlink($file);
|
||||
|
@ -63,4 +66,26 @@ final class Env
|
|||
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an environment variable from $_SERVER, $_ENV or via getenv().
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private static function getEnvVariable($name)
|
||||
{
|
||||
if (array_key_exists($name, $_SERVER)) {
|
||||
return $_SERVER[$name];
|
||||
}
|
||||
|
||||
if (array_key_exists($name, $_ENV)) {
|
||||
return $_ENV[$name];
|
||||
}
|
||||
|
||||
$value = getenv($name);
|
||||
|
||||
return $value === false ? null : $value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class FnDispatcher
|
|||
{
|
||||
$this->validate('avg', $args, [['array']]);
|
||||
$sum = $this->reduce('avg:0', $args[0], ['number'], function ($a, $b) {
|
||||
return $a + $b;
|
||||
return Utils::add($a, $b);
|
||||
});
|
||||
return $args[0] ? ($sum / count($args[0])) : null;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class FnDispatcher
|
|||
if (is_array($args[0])) {
|
||||
return in_array($args[1], $args[0]);
|
||||
} elseif (is_string($args[1])) {
|
||||
return strpos($args[0], $args[1]) !== false;
|
||||
return mb_strpos($args[0], $args[1], 0, 'UTF-8') !== false;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ class FnDispatcher
|
|||
{
|
||||
$this->validate('ends_with', $args, [['string'], ['string']]);
|
||||
list($search, $suffix) = $args;
|
||||
return $suffix === '' || substr($search, -strlen($suffix)) === $suffix;
|
||||
return $suffix === '' || mb_substr($search, -mb_strlen($suffix, 'UTF-8'), null, 'UTF-8') === $suffix;
|
||||
}
|
||||
|
||||
private function fn_floor(array $args)
|
||||
|
@ -112,13 +112,15 @@ class FnDispatcher
|
|||
private function fn_length(array $args)
|
||||
{
|
||||
$this->validate('length', $args, [['string', 'array', 'object']]);
|
||||
return is_string($args[0]) ? strlen($args[0]) : count((array) $args[0]);
|
||||
return is_string($args[0]) ? mb_strlen($args[0], 'UTF-8') : count((array) $args[0]);
|
||||
}
|
||||
|
||||
private function fn_max(array $args)
|
||||
{
|
||||
$this->validate('max', $args, [['array']]);
|
||||
$fn = function ($a, $b) { return $a >= $b ? $a : $b; };
|
||||
$fn = function ($a, $b) {
|
||||
return $a >= $b ? $a : $b;
|
||||
};
|
||||
return $this->reduce('max:0', $args[0], ['number', 'string'], $fn);
|
||||
}
|
||||
|
||||
|
@ -137,7 +139,9 @@ class FnDispatcher
|
|||
private function fn_min(array $args)
|
||||
{
|
||||
$this->validate('min', $args, [['array']]);
|
||||
$fn = function ($a, $b, $i) { return $i && $a <= $b ? $a : $b; };
|
||||
$fn = function ($a, $b, $i) {
|
||||
return $i && $a <= $b ? $a : $b;
|
||||
};
|
||||
return $this->reduce('min:0', $args[0], ['number', 'string'], $fn);
|
||||
}
|
||||
|
||||
|
@ -167,7 +171,9 @@ class FnDispatcher
|
|||
private function fn_sum(array $args)
|
||||
{
|
||||
$this->validate('sum', $args, [['array']]);
|
||||
$fn = function ($a, $b) { return $a + $b; };
|
||||
$fn = function ($a, $b) {
|
||||
return Utils::add($a, $b);
|
||||
};
|
||||
return $this->reduce('sum:0', $args[0], ['number'], $fn);
|
||||
}
|
||||
|
||||
|
@ -201,7 +207,7 @@ class FnDispatcher
|
|||
{
|
||||
$this->validate('starts_with', $args, [['string'], ['string']]);
|
||||
list($search, $prefix) = $args;
|
||||
return $prefix === '' || strpos($search, $prefix) === 0;
|
||||
return $prefix === '' || mb_strpos($search, $prefix, 0, 'UTF-8') === 0;
|
||||
}
|
||||
|
||||
private function fn_type(array $args)
|
||||
|
@ -234,7 +240,7 @@ class FnDispatcher
|
|||
if ($type == 'number') {
|
||||
return $value;
|
||||
} elseif ($type == 'string' && is_numeric($value)) {
|
||||
return strpos($value, '.') ? (float) $value : (int) $value;
|
||||
return mb_strpos($value, '.', 0, 'UTF-8') ? (float) $value : (int) $value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -276,7 +282,7 @@ class FnDispatcher
|
|||
|
||||
private function typeError($from, $msg)
|
||||
{
|
||||
if (strpos($from, ':')) {
|
||||
if (mb_strpos($from, ':', 0, 'UTF-8')) {
|
||||
list($fn, $pos) = explode(':', $from);
|
||||
throw new \RuntimeException(
|
||||
sprintf('Argument %d of %s %s', $pos, $fn, $msg)
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace JmesPath;
|
|||
* @param string $expression Expression to search.
|
||||
* @param mixed $data Data to search.
|
||||
*
|
||||
* @return mixed|null
|
||||
* @return mixed
|
||||
*/
|
||||
if (!function_exists(__NAMESPACE__ . '\search')) {
|
||||
function search($expression, $data)
|
||||
|
|
|
@ -340,7 +340,7 @@ class Lexer
|
|||
eof:
|
||||
$tokens[] = [
|
||||
'type' => self::T_EOF,
|
||||
'pos' => strlen($input),
|
||||
'pos' => mb_strlen($input, 'UTF-8'),
|
||||
'value' => null
|
||||
];
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ class Parser
|
|||
];
|
||||
|
||||
/**
|
||||
* @param Lexer $lexer Lexer used to tokenize expressions
|
||||
* @param Lexer|null $lexer Lexer used to tokenize expressions
|
||||
*/
|
||||
public function __construct(Lexer $lexer = null)
|
||||
{
|
||||
|
@ -142,7 +142,8 @@ class Parser
|
|||
return ['type' => T::T_NOT, 'children' => [$this->expr(self::$bp[T::T_NOT])]];
|
||||
}
|
||||
|
||||
private function nud_lparen() {
|
||||
private function nud_lparen()
|
||||
{
|
||||
$this->next();
|
||||
$result = $this->expr(0);
|
||||
if ($this->token['type'] !== T::T_RPAREN) {
|
||||
|
|
|
@ -23,7 +23,7 @@ class TreeCompiler
|
|||
$this->source = $this->indentation = '';
|
||||
$this->write("<?php\n")
|
||||
->write('use JmesPath\\TreeInterpreter as Ti;')
|
||||
->write('use JmesPath\\FnDispatcher as Fn;')
|
||||
->write('use JmesPath\\FnDispatcher as Fd;')
|
||||
->write('use JmesPath\\Utils;')
|
||||
->write('')
|
||||
->write('function %s(Ti $interpreter, $value) {', $fnName)
|
||||
|
@ -257,7 +257,7 @@ class TreeCompiler
|
|||
}
|
||||
|
||||
return $this->write(
|
||||
'$value = Fn::getInstance()->__invoke("%s", %s);',
|
||||
'$value = Fd::getInstance()->__invoke("%s", %s);',
|
||||
$node['value'], $args
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ class TreeInterpreter
|
|||
private $fnDispatcher;
|
||||
|
||||
/**
|
||||
* @param callable $fnDispatcher Function dispatching function that accepts
|
||||
* a function name argument and an array of
|
||||
* function arguments and returns the result.
|
||||
* @param callable|null $fnDispatcher Function dispatching function that accepts
|
||||
* a function name argument and an array of
|
||||
* function arguments and returns the result.
|
||||
*/
|
||||
public function __construct(callable $fnDispatcher = null)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace JmesPath;
|
|||
|
||||
class Utils
|
||||
{
|
||||
static $typeMap = [
|
||||
public static $typeMap = [
|
||||
'boolean' => 'boolean',
|
||||
'string' => 'string',
|
||||
'NULL' => 'null',
|
||||
|
@ -126,6 +126,31 @@ class Utils
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely add together two values.
|
||||
*
|
||||
* @param mixed $a First value to add
|
||||
* @param mixed $b Second value to add
|
||||
*
|
||||
* @return int|float
|
||||
*/
|
||||
public static function add($a, $b)
|
||||
{
|
||||
if (is_numeric($a)) {
|
||||
if (is_numeric($b)) {
|
||||
return $a + $b;
|
||||
} else {
|
||||
return $a;
|
||||
}
|
||||
} else {
|
||||
if (is_numeric($b)) {
|
||||
return $b;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JMESPath requires a stable sorting algorithm, so here we'll implement
|
||||
* a simple Schwartzian transform that uses array index positions as tie
|
||||
|
@ -140,14 +165,18 @@ class Utils
|
|||
public static function stableSort(array $data, callable $sortFn)
|
||||
{
|
||||
// Decorate each item by creating an array of [value, index]
|
||||
array_walk($data, function (&$v, $k) { $v = [$v, $k]; });
|
||||
array_walk($data, function (&$v, $k) {
|
||||
$v = [$v, $k];
|
||||
});
|
||||
// Sort by the sort function and use the index as a tie-breaker
|
||||
uasort($data, function ($a, $b) use ($sortFn) {
|
||||
return $sortFn($a[0], $b[0]) ?: ($a[1] < $b[1] ? -1 : 1);
|
||||
});
|
||||
|
||||
// Undecorate each item and return the resulting sorted array
|
||||
return array_map(function ($v) { return $v[0]; }, array_values($data));
|
||||
return array_map(function ($v) {
|
||||
return $v[0];
|
||||
}, array_values($data));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -210,7 +239,7 @@ class Utils
|
|||
private static function sliceIndices($subject, $start, $stop, $step)
|
||||
{
|
||||
$type = gettype($subject);
|
||||
$len = $type == 'string' ? strlen($subject) : count($subject);
|
||||
$len = $type == 'string' ? mb_strlen($subject, 'UTF-8') : count($subject);
|
||||
list($start, $stop, $step) = self::adjustSlice($len, $start, $stop, $step);
|
||||
|
||||
$result = [];
|
||||
|
@ -224,6 +253,6 @@ class Utils
|
|||
}
|
||||
}
|
||||
|
||||
return $type == 'string' ? implode($result, '') : $result;
|
||||
return $type == 'string' ? implode('', $result) : $result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue