mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 07:23:13 +00:00
Convert dates to date ranges on timestamp keys
This commit is contained in:
@@ -20,22 +20,22 @@ class RangeExpression extends Node
|
||||
|
||||
public static function lessThan(Key $key, $bound)
|
||||
{
|
||||
return new self($key, $bound, false);
|
||||
return new self($key, null, false, $bound, false);
|
||||
}
|
||||
|
||||
public static function lessThanOrEqual(Key $key, $bound)
|
||||
{
|
||||
return new self($key, $bound, true);
|
||||
return new self($key, null, false, $bound, true);
|
||||
}
|
||||
|
||||
public static function greaterThan(Key $key, $bound)
|
||||
{
|
||||
return new self($key, null, false, $bound, false);
|
||||
return new self($key, $bound, false);
|
||||
}
|
||||
|
||||
public static function greaterThanOrEqual(Key $key, $bound)
|
||||
{
|
||||
return new self($key, null, false, $bound, true);
|
||||
return new self($key, $bound, true);
|
||||
}
|
||||
|
||||
public function __construct(Key $key, $lb, $li = false, $hb = null, $hi = false)
|
||||
@@ -57,17 +57,17 @@ class RangeExpression extends Node
|
||||
if ($this->lower_bound !== null) {
|
||||
$this->assertValueCompatible($this->lower_bound, $context);
|
||||
if ($this->lower_inclusive) {
|
||||
$params['lte'] = $this->lower_bound;
|
||||
$params['gte'] = $this->lower_bound;
|
||||
} else {
|
||||
$params['lt'] = $this->lower_bound;
|
||||
$params['gt'] = $this->lower_bound;
|
||||
}
|
||||
}
|
||||
if ($this->higher_bound !== null) {
|
||||
$this->assertValueCompatible($this->higher_bound, $context);
|
||||
if ($this->higher_inclusive) {
|
||||
$params['gte'] = $this->higher_bound;
|
||||
$params['lte'] = $this->higher_bound;
|
||||
} else {
|
||||
$params['gt'] = $this->higher_bound;
|
||||
$params['lt'] = $this->higher_bound;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,16 +98,16 @@ class RangeExpression extends Node
|
||||
$string = '';
|
||||
if ($this->lower_bound !== null) {
|
||||
if ($this->lower_inclusive) {
|
||||
$string .= sprintf(' lte="%s"', $this->lower_bound);
|
||||
$string .= sprintf(' gte="%s"', $this->lower_bound);
|
||||
} else {
|
||||
$string .= sprintf(' lt="%s"', $this->lower_bound);
|
||||
$string .= sprintf(' gt="%s"', $this->lower_bound);
|
||||
}
|
||||
}
|
||||
if ($this->higher_bound !== null) {
|
||||
if ($this->higher_inclusive) {
|
||||
$string .= sprintf(' gte="%s"', $this->higher_bound);
|
||||
$string .= sprintf(' lte="%s"', $this->higher_bound);
|
||||
} else {
|
||||
$string .= sprintf(' gt="%s"', $this->higher_bound);
|
||||
$string .= sprintf(' lt="%s"', $this->higher_bound);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\SearchEngine\Elastic\Search;
|
||||
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Mapping;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Field;
|
||||
|
||||
class QueryHelper
|
||||
@@ -107,4 +108,42 @@ class QueryHelper
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getRangeFromDateString($string)
|
||||
{
|
||||
$formats = ['Y/m/d', 'Y/m', 'Y'];
|
||||
$deltas = ['+1 day', '+1 month', '+1 year'];
|
||||
$to = null;
|
||||
while ($format = array_pop($formats)) {
|
||||
$delta = array_pop($deltas);
|
||||
$from = date_create_from_format($format, $string);
|
||||
if ($from !== false) {
|
||||
// Rewind to start of range
|
||||
$month = 1;
|
||||
$day = 1;
|
||||
switch ($format) {
|
||||
case 'Y/m/d':
|
||||
$day = (int) $from->format('d');
|
||||
case 'Y/m':
|
||||
$month = (int) $from->format('m');
|
||||
case 'Y':
|
||||
$year = (int) $from->format('Y');
|
||||
}
|
||||
date_date_set($from, $year, $month, $day);
|
||||
date_time_set($from, 0, 0, 0);
|
||||
// Create end of the the range
|
||||
$to = date_modify(clone $from, $delta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$from || !$to) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid date "%s".', $string));
|
||||
}
|
||||
|
||||
return [
|
||||
'from' => $from->format(Mapping::DATE_FORMAT_CAPTION_PHP),
|
||||
'to' => $to->format(Mapping::DATE_FORMAT_CAPTION_PHP)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ namespace Alchemy\Phrasea\SearchEngine\Elastic\Search;
|
||||
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\AST;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\Exception;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryHelper;
|
||||
use Hoa\Compiler\Llk\TreeNode;
|
||||
use Hoa\Visitor\Element;
|
||||
use Hoa\Visitor\Visit;
|
||||
@@ -176,10 +177,29 @@ class QueryVisitor implements Visit
|
||||
private function visitEqualNode(TreeNode $node)
|
||||
{
|
||||
return $this->handleBinaryExpression($node, function($left, $right) {
|
||||
if ($this->isDateKey($left)) {
|
||||
try {
|
||||
// Try to create a range for incomplete dates
|
||||
$range = QueryHelper::getRangeFromDateString($right);
|
||||
return new AST\KeyValue\RangeExpression(
|
||||
$left,
|
||||
$range['from'], true,
|
||||
$range['to'], false
|
||||
);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
// Fall back to equal expression
|
||||
}
|
||||
}
|
||||
|
||||
return new AST\KeyValue\EqualExpression($left, $right);
|
||||
});
|
||||
}
|
||||
|
||||
private function isDateKey(AST\KeyValue\Key $key)
|
||||
{
|
||||
return $key instanceof AST\KeyValue\TimestampKey;
|
||||
}
|
||||
|
||||
private function visitTerm(Element $element)
|
||||
{
|
||||
$words = array();
|
||||
|
Reference in New Issue
Block a user