Skip to content

Commit f81d6ed

Browse files
committed
MDL-78511 lib: Include JmesPath library
JMESPath library is required by AWS SDK for PHP library
1 parent 9b98f78 commit f81d6ed

19 files changed

+2926
-0
lines changed

lib/classes/component.php

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class core_component {
122122
'GuzzleHttp' => 'lib/guzzlehttp/guzzle/src',
123123
'Kevinrob\\GuzzleCache' => 'lib/guzzlehttp/kevinrob/guzzlecache/src',
124124
'Aws' => 'lib/aws-sdk/src',
125+
'JmesPath' => 'lib/jmespath/src',
125126
];
126127

127128
/**

lib/jmespath/CHANGELOG.md

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# CHANGELOG
2+
3+
## 2.6.0 - 2020-07-31
4+
5+
* Support for PHP 8.0.
6+
7+
## 2.5.0 - 2019-12-30
8+
9+
* Full support for PHP 7.0-7.4.
10+
* Fixed autoloading when run from within vendor folder.
11+
* Full multibyte (UTF-8) string support.
12+
13+
## 2.4.0 - 2016-12-03
14+
15+
* Added support for floats when interpreting data.
16+
* Added a function_exists check to work around redeclaration issues.
17+
18+
## 2.3.0 - 2016-01-05
19+
20+
* Added support for [JEP-9](https://github.com/jmespath/jmespath.site/blob/master/docs/proposals/improved-filters.rst),
21+
including unary filter expressions, and `&&` filter expressions.
22+
* Fixed various parsing issues, including not removing escaped single quotes
23+
from raw string literals.
24+
* Added support for the `map` function.
25+
* Fixed several issues with code generation.
26+
27+
## 2.2.0 - 2015-05-27
28+
29+
* Added support for [JEP-12](https://github.com/jmespath/jmespath.site/blob/master/docs/proposals/raw-string-literals.rst)
30+
and raw string literals (e.g., `'foo'`).
31+
32+
## 2.1.0 - 2014-01-13
33+
34+
* Added `JmesPath\Env::cleanCompileDir()` to delete any previously compiled
35+
JMESPath expressions.
36+
37+
## 2.0.0 - 2014-01-11
38+
39+
* Moving to a flattened namespace structure.
40+
* Runtimes are now only PHP callables.
41+
* Fixed an error in the way empty JSON literals are parsed so that they now
42+
return an empty string to match the Python and JavaScript implementations.
43+
* Removed functions from runtimes. Instead there is now a function dispatcher
44+
class, FnDispatcher, that provides function implementations behind a single
45+
dispatch function.
46+
* Removed ExprNode in lieu of just using a PHP callable with bound variables.
47+
* Removed debug methods from runtimes and instead into a new Debugger class.
48+
* Heavily cleaned up function argument validation.
49+
* Slice syntax is now properly validated (i.e., colons are followed by the
50+
appropriate value).
51+
* Lots of code cleanup and performance improvements.
52+
* Added a convenient `JmesPath\search()` function.
53+
* **IMPORTANT**: Relocating the project to https://github.com/jmespath/jmespath.php
54+
55+
## 1.1.1 - 2014-10-08
56+
57+
* Added support for using ArrayAccess and Countable as arrays and objects.
58+
59+
## 1.1.0 - 2014-08-06
60+
61+
* Added the ability to search data returned from json_decode() where JSON
62+
objects are returned as stdClass objects.

lib/jmespath/LICENSE

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2014 Michael Dowling, https://github.com/mtdowling
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

lib/jmespath/README.rst

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
============
2+
jmespath.php
3+
============
4+
5+
JMESPath (pronounced "jaymz path") allows you to declaratively specify how to
6+
extract elements from a JSON document. *jmespath.php* allows you to use
7+
JMESPath in PHP applications with PHP data structures. It requires PHP 5.4 or
8+
greater and can be installed through `Composer <http://getcomposer.org/doc/00-intro.md>`_
9+
using the ``mtdowling/jmespath.php`` package.
10+
11+
.. code-block:: php
12+
13+
require 'vendor/autoload.php';
14+
15+
$expression = 'foo.*.baz';
16+
17+
$data = [
18+
'foo' => [
19+
'bar' => ['baz' => 1],
20+
'bam' => ['baz' => 2],
21+
'boo' => ['baz' => 3]
22+
]
23+
];
24+
25+
JmesPath\search($expression, $data);
26+
// Returns: [1, 2, 3]
27+
28+
- `JMESPath Tutorial <http://jmespath.org/tutorial.html>`_
29+
- `JMESPath Grammar <http://jmespath.org/specification.html#grammar>`_
30+
- `JMESPath Python library <https://github.com/jmespath/jmespath.py>`_
31+
32+
PHP Usage
33+
=========
34+
35+
The ``JmesPath\search`` function can be used in most cases when using the
36+
library. This function utilizes a JMESPath runtime based on your environment.
37+
The runtime utilized can be configured using environment variables and may at
38+
some point in the future automatically utilize a C extension if available.
39+
40+
.. code-block:: php
41+
42+
$result = JmesPath\search($expression, $data);
43+
44+
// or, if you require PSR-4 compliance.
45+
$result = JmesPath\Env::search($expression, $data);
46+
47+
Runtimes
48+
--------
49+
50+
jmespath.php utilizes *runtimes*. There are currently two runtimes:
51+
AstRuntime and CompilerRuntime.
52+
53+
AstRuntime is utilized by ``JmesPath\search()`` and ``JmesPath\Env::search()``
54+
by default.
55+
56+
AstRuntime
57+
~~~~~~~~~~
58+
59+
The AstRuntime will parse an expression, cache the resulting AST in memory,
60+
and interpret the AST using an external tree visitor. AstRuntime provides a
61+
good general approach for interpreting JMESPath expressions that have a low to
62+
moderate level of reuse.
63+
64+
.. code-block:: php
65+
66+
$runtime = new JmesPath\AstRuntime();
67+
$runtime('foo.bar', ['foo' => ['bar' => 'baz']]);
68+
// > 'baz'
69+
70+
CompilerRuntime
71+
~~~~~~~~~~~~~~~
72+
73+
``JmesPath\CompilerRuntime`` provides the most performance for
74+
applications that have a moderate to high level of reuse of JMESPath
75+
expressions. The CompilerRuntime will walk a JMESPath AST and emit PHP source
76+
code, resulting in anywhere from 7x to 60x speed improvements.
77+
78+
Compiling JMESPath expressions to source code is a slower process than just
79+
walking and interpreting a JMESPath AST (via the AstRuntime). However,
80+
running the compiled JMESPath code results in much better performance than
81+
walking an AST. This essentially means that there is a warm-up period when
82+
using the ``CompilerRuntime``, but after the warm-up period, it will provide
83+
much better performance.
84+
85+
Use the CompilerRuntime if you know that you will be executing JMESPath
86+
expressions more than once or if you can pre-compile JMESPath expressions
87+
before executing them (for example, server-side applications).
88+
89+
.. code-block:: php
90+
91+
// Note: The cache directory argument is optional.
92+
$runtime = new JmesPath\CompilerRuntime('/path/to/compile/folder');
93+
$runtime('foo.bar', ['foo' => ['bar' => 'baz']]);
94+
// > 'baz'
95+
96+
Environment Variables
97+
^^^^^^^^^^^^^^^^^^^^^
98+
99+
You can utilize the CompilerRuntime in ``JmesPath\search()`` by setting
100+
the ``JP_PHP_COMPILE`` environment variable to "on" or to a directory
101+
on disk used to store cached expressions.
102+
103+
Testing
104+
=======
105+
106+
A comprehensive list of test cases can be found at
107+
https://github.com/jmespath/jmespath.php/tree/master/tests/compliance.
108+
These compliance tests are utilized by jmespath.php to ensure consistency with
109+
other implementations, and can serve as examples of the language.
110+
111+
jmespath.php is tested using PHPUnit. In order to run the tests, you need to
112+
first install the dependencies using Composer as described in the *Installation*
113+
section. Next you just need to run the tests via make:
114+
115+
.. code-block:: bash
116+
117+
make test
118+
119+
You can run a suite of performance tests as well:
120+
121+
.. code-block:: bash
122+
123+
make perf

lib/jmespath/composer.json

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "mtdowling/jmespath.php",
3+
"description": "Declaratively specify how to extract elements from a JSON document",
4+
"keywords": ["json", "jsonpath"],
5+
"license": "MIT",
6+
7+
"authors": [
8+
{
9+
"name": "Michael Dowling",
10+
"email": "[email protected]",
11+
"homepage": "https://github.com/mtdowling"
12+
}
13+
],
14+
15+
"require": {
16+
"php": "^5.4 || ^7.0 || ^8.0",
17+
"symfony/polyfill-mbstring": "^1.17"
18+
},
19+
20+
"require-dev": {
21+
"composer/xdebug-handler": "^1.4 || ^2.0",
22+
"phpunit/phpunit": "^4.8.36 || ^7.5.15"
23+
},
24+
25+
"autoload": {
26+
"psr-4": {
27+
"JmesPath\\": "src/"
28+
},
29+
"files": ["src/JmesPath.php"]
30+
},
31+
32+
"bin": ["bin/jp.php"],
33+
34+
"extra": {
35+
"branch-alias": {
36+
"dev-master": "2.6-dev"
37+
}
38+
}
39+
}

lib/jmespath/readme_moodle.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Instructions to import/update jmespath library into Moodle:
2+
3+
Update jmespath library
4+
1. Download the latest jmespath.php library package from https://github.com/jmespath/jmespath.php/releases
5+
2. Copy the src directory to lib/jmespath/src folder
6+
3. Copy the associated files LICENCE, README.md etc. to jmespath directory

lib/jmespath/src/AstRuntime.php

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
namespace JmesPath;
3+
4+
/**
5+
* Uses an external tree visitor to interpret an AST.
6+
*/
7+
class AstRuntime
8+
{
9+
private $parser;
10+
private $interpreter;
11+
private $cache = [];
12+
private $cachedCount = 0;
13+
14+
public function __construct(
15+
Parser $parser = null,
16+
callable $fnDispatcher = null
17+
) {
18+
$fnDispatcher = $fnDispatcher ?: FnDispatcher::getInstance();
19+
$this->interpreter = new TreeInterpreter($fnDispatcher);
20+
$this->parser = $parser ?: new Parser();
21+
}
22+
23+
/**
24+
* Returns data from the provided input that matches a given JMESPath
25+
* expression.
26+
*
27+
* @param string $expression JMESPath expression to evaluate
28+
* @param mixed $data Data to search. This data should be data that
29+
* is similar to data returned from json_decode
30+
* using associative arrays rather than objects.
31+
*
32+
* @return mixed Returns the matching data or null
33+
*/
34+
public function __invoke($expression, $data)
35+
{
36+
if (!isset($this->cache[$expression])) {
37+
// Clear the AST cache when it hits 1024 entries
38+
if (++$this->cachedCount > 1024) {
39+
$this->cache = [];
40+
$this->cachedCount = 0;
41+
}
42+
$this->cache[$expression] = $this->parser->parse($expression);
43+
}
44+
45+
return $this->interpreter->visit($this->cache[$expression], $data);
46+
}
47+
}

lib/jmespath/src/CompilerRuntime.php

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
namespace JmesPath;
3+
4+
/**
5+
* Compiles JMESPath expressions to PHP source code and executes it.
6+
*
7+
* JMESPath file names are stored in the cache directory using the following
8+
* logic to determine the filename:
9+
*
10+
* 1. Start with the string "jmespath_"
11+
* 2. Append the MD5 checksum of the expression.
12+
* 3. Append ".php"
13+
*/
14+
class CompilerRuntime
15+
{
16+
private $parser;
17+
private $compiler;
18+
private $cacheDir;
19+
private $interpreter;
20+
21+
/**
22+
* @param string|null $dir Directory used to store compiled PHP files.
23+
* @param Parser|null $parser JMESPath parser to utilize
24+
* @throws \RuntimeException if the cache directory cannot be created
25+
*/
26+
public function __construct($dir = null, Parser $parser = null)
27+
{
28+
$this->parser = $parser ?: new Parser();
29+
$this->compiler = new TreeCompiler();
30+
$dir = $dir ?: sys_get_temp_dir();
31+
32+
if (!is_dir($dir) && !mkdir($dir, 0755, true)) {
33+
throw new \RuntimeException("Unable to create cache directory: $dir");
34+
}
35+
36+
$this->cacheDir = realpath($dir);
37+
$this->interpreter = new TreeInterpreter();
38+
}
39+
40+
/**
41+
* Returns data from the provided input that matches a given JMESPath
42+
* expression.
43+
*
44+
* @param string $expression JMESPath expression to evaluate
45+
* @param mixed $data Data to search. This data should be data that
46+
* is similar to data returned from json_decode
47+
* using associative arrays rather than objects.
48+
*
49+
* @return mixed Returns the matching data or null
50+
* @throws \RuntimeException
51+
*/
52+
public function __invoke($expression, $data)
53+
{
54+
$functionName = 'jmespath_' . md5($expression);
55+
56+
if (!function_exists($functionName)) {
57+
$filename = "{$this->cacheDir}/{$functionName}.php";
58+
if (!file_exists($filename)) {
59+
$this->compile($filename, $expression, $functionName);
60+
}
61+
require $filename;
62+
}
63+
64+
return $functionName($this->interpreter, $data);
65+
}
66+
67+
private function compile($filename, $expression, $functionName)
68+
{
69+
$code = $this->compiler->visit(
70+
$this->parser->parse($expression),
71+
$functionName,
72+
$expression
73+
);
74+
75+
if (!file_put_contents($filename, $code)) {
76+
throw new \RuntimeException(sprintf(
77+
'Unable to write the compiled PHP code to: %s (%s)',
78+
$filename,
79+
var_export(error_get_last(), true)
80+
));
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)