View source
<?php
namespace Drupal\feeds_ex\Feeds\Parser;
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\feeds\FeedInterface;
use Drupal\feeds\Result\FetcherResultInterface;
use Drupal\feeds\Result\ParserResultInterface;
use Drupal\feeds\StateInterface;
use Drupal\feeds_ex\JmesRuntimeFactory;
use Drupal\feeds_ex\JmesRuntimeFactoryInterface;
use Drupal\feeds_ex\Utility\JsonUtility;
use JmesPath\SyntaxErrorException;
class JmesPathParser extends JsonParserBase {
protected $runtime;
protected $runtimeFactory;
public function __construct(array $configuration, $plugin_id, array $plugin_definition, JsonUtility $utility) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $utility);
$this->runtimeFactory = new JmesRuntimeFactory();
}
public function setRuntimeFactory(JmesRuntimeFactoryInterface $factory) {
$this->runtimeFactory = $factory;
}
protected function search($expression, $data) {
if (!isset($this->runtime)) {
$this->runtime = $this->runtimeFactory
->createRuntime();
}
$runtime = $this->runtime;
return $runtime($expression, $data);
}
protected function executeContext(FeedInterface $feed, FetcherResultInterface $fetcher_result, StateInterface $state) {
$parsed = $this->utility
->decodeJsonObject($this
->prepareRaw($fetcher_result));
$parsed = $this
->search($this->configuration['context']['value'], $parsed);
if (!is_array($parsed) && !is_object($parsed)) {
throw new \RuntimeException($this
->t('The context expression must return an object or array.'));
}
if (is_object($parsed)) {
return [
$parsed,
];
}
if (!$state->total) {
$state->total = count($parsed);
}
$start = (int) $state->pointer;
$state->pointer = $start + $this->configuration['line_limit'];
return array_slice($parsed, $start, $this->configuration['line_limit']);
}
protected function cleanUp(FeedInterface $feed, ParserResultInterface $result, StateInterface $state) {
unset($this->runtime);
$state
->progress($state->total, $state->pointer);
}
protected function executeSourceExpression($machine_name, $expression, $row) {
try {
$result = $this
->search($expression, $row);
} catch (\Exception $e) {
throw new \RuntimeException($e
->getMessage());
}
if (is_object($result)) {
$result = (array) $result;
}
if (!is_array($result)) {
return $result;
}
$count = count($result);
if ($count === 0) {
return;
}
return count($result) === 1 ? reset($result) : array_values($result);
}
protected function validateExpression(&$expression) {
$expression = trim($expression);
if (!strlen($expression)) {
return;
}
try {
$this
->search($expression, []);
} catch (SyntaxErrorException $e) {
return $this
->formatSyntaxError($e
->getMessage());
} catch (\RuntimeException $e) {
if (strpos($e
->getMessage(), 'Argument 0') === 0) {
return;
}
throw $e;
}
}
protected function formatSyntaxError($message) {
$message = trim($message);
$message = nl2br($message);
$message = str_replace(' ', ' ', $message);
$message = str_replace("\n", '', $message);
return '<pre>' . $message . '</pre>';
}
protected function getErrors() {
if (!function_exists('json_last_error')) {
return [];
}
if (!($error = json_last_error())) {
return [];
}
$message = [
'message' => $this->utility
->translateError($error),
'variables' => [],
'severity' => RfcLogLevel::ERROR,
];
return [
$message,
];
}
protected function loadLibrary() {
if (!class_exists('JmesPath\\AstRuntime')) {
throw new \RuntimeException($this
->t('The JMESPath library is not installed.'));
}
}
}