Skip to content

Commit

Permalink
Merge pull request #1 from belisarh/belisarh-patch-1
Browse files Browse the repository at this point in the history
Belisarh patch 1
  • Loading branch information
belisarh authored Mar 16, 2018
2 parents b62ea68 + 6c87f31 commit 996f1f3
Show file tree
Hide file tree
Showing 48 changed files with 1,093 additions and 308 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
CHANGELOG
=========

4.0.0
-----

* the first argument of the `ExpressionLanguage` constructor must be an instance
of `CacheItemPoolInterface`
* removed the `ArrayParserCache` and `ParserCacheAdapter` classes
* removed the `ParserCacheInterface`

2.6.0
-----

* Added ExpressionFunction and ExpressionFunctionProviderInterface

2.4.0
-----

Expand Down
10 changes: 4 additions & 6 deletions Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ public function reset()
/**
* Compiles a node.
*
* @param Node\Node $node The node to compile
*
* @return Compiler The current compiler instance
* @return $this
*/
public function compile(Node\Node $node)
{
Expand All @@ -80,7 +78,7 @@ public function subcompile(Node\Node $node)
*
* @param string $string The string
*
* @return Compiler The current compiler instance
* @return $this
*/
public function raw($string)
{
Expand All @@ -94,7 +92,7 @@ public function raw($string)
*
* @param string $value The string
*
* @return Compiler The current compiler instance
* @return $this
*/
public function string($value)
{
Expand All @@ -108,7 +106,7 @@ public function string($value)
*
* @param mixed $value The value to convert
*
* @return Compiler The current compiler instance
* @return $this
*/
public function repr($value)
{
Expand Down
9 changes: 2 additions & 7 deletions Expression.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,9 @@ class Expression
{
protected $expression;

/**
* Constructor.
*
* @param string $expression An expression
*/
public function __construct($expression)
public function __construct(string $expression)
{
$this->expression = (string) $expression;
$this->expression = $expression;
}

/**
Expand Down
100 changes: 100 additions & 0 deletions ExpressionFunction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\ExpressionLanguage;

/**
* Represents a function that can be used in an expression.
*
* A function is defined by two PHP callables. The callables are used
* by the language to compile and/or evaluate the function.
*
* The "compiler" function is used at compilation time and must return a
* PHP representation of the function call (it receives the function
* arguments as arguments).
*
* The "evaluator" function is used for expression evaluation and must return
* the value of the function call based on the values defined for the
* expression (it receives the values as a first argument and the function
* arguments as remaining arguments).
*
* @author Fabien Potencier <[email protected]>
*/
class ExpressionFunction
{
private $name;
private $compiler;
private $evaluator;

/**
* @param string $name The function name
* @param callable $compiler A callable able to compile the function
* @param callable $evaluator A callable able to evaluate the function
*/
public function __construct(string $name, callable $compiler, callable $evaluator)
{
$this->name = $name;
$this->compiler = $compiler;
$this->evaluator = $evaluator;
}

public function getName()
{
return $this->name;
}

public function getCompiler()
{
return $this->compiler;
}

public function getEvaluator()
{
return $this->evaluator;
}

/**
* Creates an ExpressionFunction from a PHP function name.
*
* @param string $phpFunctionName The PHP function name
* @param string|null $expressionFunctionName The expression function name (default: same than the PHP function name)
*
* @return self
*
* @throws \InvalidArgumentException if given PHP function name does not exist
* @throws \InvalidArgumentException if given PHP function name is in namespace
* and expression function name is not defined
*/
public static function fromPhp($phpFunctionName, $expressionFunctionName = null)
{
$phpFunctionName = ltrim($phpFunctionName, '\\');
if (!function_exists($phpFunctionName)) {
throw new \InvalidArgumentException(sprintf('PHP function "%s" does not exist.', $phpFunctionName));
}

$parts = explode('\\', $phpFunctionName);
if (!$expressionFunctionName && count($parts) > 1) {
throw new \InvalidArgumentException(sprintf('An expression function name must be defined when PHP function "%s" is namespaced.', $phpFunctionName));
}

$compiler = function () use ($phpFunctionName) {
return sprintf('\%s(%s)', $phpFunctionName, implode(', ', func_get_args()));
};

$evaluator = function () use ($phpFunctionName) {
$args = func_get_args();

return call_user_func_array($phpFunctionName, array_splice($args, 1));
};

return new self($expressionFunctionName ?: end($parts), $compiler, $evaluator);
}
}
23 changes: 23 additions & 0 deletions ExpressionFunctionProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\ExpressionLanguage;

/**
* @author Fabien Potencier <[email protected]>
*/
interface ExpressionFunctionProviderInterface
{
/**
* @return ExpressionFunction[] An array of Function instances
*/
public function getFunctions();
}
78 changes: 47 additions & 31 deletions ExpressionLanguage.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

namespace Symfony\Component\ExpressionLanguage;

use Symfony\Component\ExpressionLanguage\ParserCache\ArrayParserCache;
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;

/**
* Allows to compile and evaluate expressions written in your own DSL.
Expand All @@ -21,20 +21,24 @@
*/
class ExpressionLanguage
{
/**
* @var ParserCacheInterface
*/
private $cache;
private $lexer;
private $parser;
private $compiler;

protected $functions = array();

public function __construct(ParserCacheInterface $cache = null)
/**
* @param CacheItemPoolInterface $cache
* @param ExpressionFunctionProviderInterface[] $providers
*/
public function __construct(CacheItemPoolInterface $cache = null, array $providers = array())
{
$this->cache = $cache ?: new ArrayParserCache();
$this->cache = $cache ?: new ArrayAdapter();
$this->registerFunctions();
foreach ($providers as $provider) {
$this->registerProvider($provider);
}
}

/**
Expand Down Expand Up @@ -77,13 +81,21 @@ public function parse($expression, $names)
return $expression;
}

$key = $expression.'//'.implode('-', $names);
asort($names);
$cacheKeyItems = array();

if (null === $parsedExpression = $this->cache->fetch($key)) {
foreach ($names as $nameKey => $name) {
$cacheKeyItems[] = is_int($nameKey) ? $name : $nameKey.':'.$name;
}

$cacheItem = $this->cache->getItem(rawurlencode($expression.'//'.implode('|', $cacheKeyItems)));

if (null === $parsedExpression = $cacheItem->get()) {
$nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names);
$parsedExpression = new ParsedExpression((string) $expression, $nodes);

$this->cache->save($key, $parsedExpression);
$cacheItem->set($parsedExpression);
$this->cache->save($cacheItem);
}

return $parsedExpression;
Expand All @@ -92,37 +104,41 @@ public function parse($expression, $names)
/**
* Registers a function.
*
* A function is defined by two PHP callables. The callables are used
* by the language to compile and/or evaluate the function.
*
* The first function is used at compilation time and must return a
* PHP representation of the function call (it receives the function
* arguments as arguments).
*
* The second function is used for expression evaluation and must return
* the value of the function call based on the values defined for the
* expression (it receives the values as a first argument and the function
* arguments as remaining arguments).
*
* @param string $name The function name
* @param callable $compiler A callable able to compile the function
* @param callable $evaluator A callable able to evaluate the function
*
* @throws \LogicException when registering a function after calling evaluate(), compile() or parse()
*
* @see ExpressionFunction
*/
public function register($name, $compiler, $evaluator)
public function register($name, callable $compiler, callable $evaluator)
{
if (null !== $this->parser) {
throw new \LogicException('Registering functions after calling evaluate(), compile() or parse() is not supported.');
}

$this->functions[$name] = array('compiler' => $compiler, 'evaluator' => $evaluator);
}

public function addFunction(ExpressionFunction $function)
{
$this->register($function->getName(), $function->getCompiler(), $function->getEvaluator());
}

public function registerProvider(ExpressionFunctionProviderInterface $provider)
{
foreach ($provider->getFunctions() as $function) {
$this->addFunction($function);
}
}

protected function registerFunctions()
{
$this->register('constant', function ($constant) {
return sprintf('constant(%s)', $constant);
}, function (array $values, $constant) {
return constant($constant);
});
$this->addFunction(ExpressionFunction::fromPhp('constant'));
}

private function getLexer()
private function getLexer(): Lexer
{
if (null === $this->lexer) {
$this->lexer = new Lexer();
Expand All @@ -131,7 +147,7 @@ private function getLexer()
return $this->lexer;
}

private function getParser()
private function getParser(): Parser
{
if (null === $this->parser) {
$this->parser = new Parser($this->functions);
Expand All @@ -140,7 +156,7 @@ private function getParser()
return $this->parser;
}

private function getCompiler()
private function getCompiler(): Compiler
{
if (null === $this->compiler) {
$this->compiler = new Compiler($this->functions);
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2004-2014 Fabien Potencier
Copyright (c) 2004-2018 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit 996f1f3

Please sign in to comment.