| 1 |
<?php |
| 2 |
|
| 3 |
namespace Dudlewebs\WPMCS\s3\JmesPath; |
| 4 |
|
| 5 |
/** |
| 6 |
* Compiles JMESPath expressions to PHP source code and executes it. |
| 7 |
* |
| 8 |
* JMESPath file names are stored in the cache directory using the following |
| 9 |
* logic to determine the filename: |
| 10 |
* |
| 11 |
* 1. Start with the string "jmespath_" |
| 12 |
* 2. Append the MD5 checksum of the expression. |
| 13 |
* 3. Append ".php" |
| 14 |
*/ |
| 15 |
class CompilerRuntime |
| 16 |
{ |
| 17 |
private $parser; |
| 18 |
private $compiler; |
| 19 |
private $cacheDir; |
| 20 |
private $interpreter; |
| 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 |
if (!\is_dir($dir) && !\mkdir($dir, 0755, \true)) { |
| 32 |
throw new \RuntimeException("Unable to create cache directory: {$dir}"); |
| 33 |
} |
| 34 |
$this->cacheDir = \realpath($dir); |
| 35 |
$this->interpreter = new TreeInterpreter(); |
| 36 |
} |
| 37 |
/** |
| 38 |
* Returns data from the provided input that matches a given JMESPath |
| 39 |
* expression. |
| 40 |
* |
| 41 |
* @param string $expression JMESPath expression to evaluate |
| 42 |
* @param mixed $data Data to search. This data should be data that |
| 43 |
* is similar to data returned from json_decode |
| 44 |
* using associative arrays rather than objects. |
| 45 |
* |
| 46 |
* @return mixed Returns the matching data or null |
| 47 |
* @throws \RuntimeException |
| 48 |
*/ |
| 49 |
public function __invoke($expression, $data) |
| 50 |
{ |
| 51 |
$functionName = 'jmespath_' . \md5($expression); |
| 52 |
if (!\function_exists($functionName)) { |
| 53 |
$filename = "{$this->cacheDir}/{$functionName}.php"; |
| 54 |
if (!\file_exists($filename)) { |
| 55 |
$this->compile($filename, $expression, $functionName); |
| 56 |
} |
| 57 |
require $filename; |
| 58 |
} |
| 59 |
return $functionName($this->interpreter, $data); |
| 60 |
} |
| 61 |
private function compile($filename, $expression, $functionName) |
| 62 |
{ |
| 63 |
$code = $this->compiler->visit($this->parser->parse($expression), $functionName, $expression); |
| 64 |
if (!\file_put_contents($filename, $code)) { |
| 65 |
throw new \RuntimeException(\sprintf('Unable to write the compiled PHP code to: %s (%s)', $filename, \var_export(\error_get_last(), \true))); |
| 66 |
} |
| 67 |
} |
| 68 |
} |
| 69 |
|