mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-11 12:03:14 +00:00
port to 4.1 date with time on phraseanet
This commit is contained in:
@@ -30,6 +30,11 @@ class FieldKey implements Key, QueryPostProcessor
|
|||||||
return $this->getField($context)->getIndexField($raw);
|
return $this->getField($context)->getIndexField($raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFieldType(QueryContext $context)
|
||||||
|
{
|
||||||
|
return $this->getField($context)->getType();
|
||||||
|
}
|
||||||
|
|
||||||
public function isValueCompatible($value, QueryContext $context)
|
public function isValueCompatible($value, QueryContext $context)
|
||||||
{
|
{
|
||||||
return ValueChecker::isValueCompatible($this->getField($context), $value);
|
return ValueChecker::isValueCompatible($this->getField($context), $value);
|
||||||
|
@@ -6,6 +6,7 @@ use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext;
|
|||||||
|
|
||||||
interface Key
|
interface Key
|
||||||
{
|
{
|
||||||
|
public function getFieldType(QueryContext $context);
|
||||||
public function getIndexField(QueryContext $context, $raw = false);
|
public function getIndexField(QueryContext $context, $raw = false);
|
||||||
public function isValueCompatible($value, QueryContext $context);
|
public function isValueCompatible($value, QueryContext $context);
|
||||||
public function __toString();
|
public function __toString();
|
||||||
|
@@ -23,6 +23,11 @@ class MetadataKey implements Key
|
|||||||
return $this->getTag($context)->getIndexField($raw);
|
return $this->getTag($context)->getIndexField($raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFieldType(QueryContext $context)
|
||||||
|
{
|
||||||
|
return $this->getTag($context)->getType();
|
||||||
|
}
|
||||||
|
|
||||||
public function isValueCompatible($value, QueryContext $context)
|
public function isValueCompatible($value, QueryContext $context)
|
||||||
{
|
{
|
||||||
return ValueChecker::isValueCompatible($this->getTag($context), $value);
|
return ValueChecker::isValueCompatible($this->getTag($context), $value);
|
||||||
|
@@ -52,6 +52,11 @@ class NativeKey implements Key
|
|||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFieldType(QueryContext $context)
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
public function getIndexField(QueryContext $context, $raw = false)
|
public function getIndexField(QueryContext $context, $raw = false)
|
||||||
{
|
{
|
||||||
return $this->key;
|
return $this->key;
|
||||||
|
@@ -2,18 +2,20 @@
|
|||||||
|
|
||||||
namespace Alchemy\Phrasea\SearchEngine\Elastic\AST\KeyValue;
|
namespace Alchemy\Phrasea\SearchEngine\Elastic\AST\KeyValue;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\SearchEngine\Elastic\FieldMapping;
|
||||||
|
use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper;
|
||||||
|
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Field as StructureField;
|
||||||
use Assert\Assertion;
|
use Assert\Assertion;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\AST\KeyValue\FieldKey;
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\AST\KeyValue\Key;
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\AST\Node;
|
use Alchemy\Phrasea\SearchEngine\Elastic\AST\Node;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\QueryException;
|
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\QueryException;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext;
|
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryContext;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryHelper;
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryPostProcessor;
|
use Alchemy\Phrasea\SearchEngine\Elastic\Search\QueryPostProcessor;
|
||||||
|
|
||||||
class RangeExpression extends Node
|
class RangeExpression extends Node
|
||||||
{
|
{
|
||||||
|
/** @var FieldKey */
|
||||||
private $key;
|
private $key;
|
||||||
|
|
||||||
private $lower_bound;
|
private $lower_bound;
|
||||||
private $lower_inclusive;
|
private $lower_inclusive;
|
||||||
private $higher_bound;
|
private $higher_bound;
|
||||||
@@ -55,20 +57,34 @@ class RangeExpression extends Node
|
|||||||
public function buildQuery(QueryContext $context)
|
public function buildQuery(QueryContext $context)
|
||||||
{
|
{
|
||||||
$params = array();
|
$params = array();
|
||||||
if ($this->lower_bound !== null) {
|
/** @var StructureField $field */
|
||||||
$this->assertValueCompatible($this->lower_bound, $context);
|
// $field = $this->key->getField($context);
|
||||||
if ($this->lower_inclusive) {
|
$lower_bound = $this->lower_bound;
|
||||||
$params['gte'] = $this->lower_bound;
|
$higher_bound = $this->higher_bound;
|
||||||
} else {
|
|
||||||
$params['gt'] = $this->lower_bound;
|
if($this->key->getFieldType($context) === FieldMapping::TYPE_DATE) {
|
||||||
|
if($lower_bound !== null) {
|
||||||
|
$lower_bound = RecordHelper::sanitizeDate($lower_bound);
|
||||||
|
}
|
||||||
|
if($higher_bound !== null) {
|
||||||
|
$higher_bound = RecordHelper::sanitizeDate($higher_bound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->higher_bound !== null) {
|
|
||||||
$this->assertValueCompatible($this->higher_bound, $context);
|
if ($lower_bound !== null) {
|
||||||
if ($this->higher_inclusive) {
|
$this->assertValueCompatible($lower_bound, $context);
|
||||||
$params['lte'] = $this->higher_bound;
|
if ($this->lower_inclusive) {
|
||||||
|
$params['gte'] = $lower_bound;
|
||||||
} else {
|
} else {
|
||||||
$params['lt'] = $this->higher_bound;
|
$params['gt'] = $lower_bound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($higher_bound !== null) {
|
||||||
|
$this->assertValueCompatible($higher_bound, $context);
|
||||||
|
if ($this->higher_inclusive) {
|
||||||
|
$params['lte'] = $higher_bound;
|
||||||
|
} else {
|
||||||
|
$params['lt'] = $higher_bound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,6 +34,11 @@ class TimestampKey implements Key, Typed
|
|||||||
return FieldMapping::TYPE_DATE;
|
return FieldMapping::TYPE_DATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFieldType(QueryContext $context)
|
||||||
|
{
|
||||||
|
return FieldMapping::TYPE_DATE;
|
||||||
|
}
|
||||||
|
|
||||||
public function getIndexField(QueryContext $context, $raw = false)
|
public function getIndexField(QueryContext $context, $raw = false)
|
||||||
{
|
{
|
||||||
return $this->index_field;
|
return $this->index_field;
|
||||||
|
@@ -396,10 +396,10 @@ class ElasticSearchEngine implements SearchEngineInterface
|
|||||||
if ($options->getDateFields() && ($options->getMaxDate() || $options->getMinDate())) {
|
if ($options->getDateFields() && ($options->getMaxDate() || $options->getMinDate())) {
|
||||||
$range = [];
|
$range = [];
|
||||||
if ($options->getMaxDate()) {
|
if ($options->getMaxDate()) {
|
||||||
$range['lte'] = $options->getMaxDate()->format(FieldMapping::DATE_FORMAT_CAPTION_PHP);
|
$range['lte'] = $options->getMaxDate()->format('Y-m-d');
|
||||||
}
|
}
|
||||||
if ($options->getMinDate()) {
|
if ($options->getMinDate()) {
|
||||||
$range['gte'] = $options->getMinDate()->format(FieldMapping::DATE_FORMAT_CAPTION_PHP);
|
$range['gte'] = $options->getMinDate()->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($options->getDateFields() as $dateField) {
|
foreach ($options->getDateFields() as $dateField) {
|
||||||
|
@@ -16,8 +16,7 @@ class FieldMapping
|
|||||||
|
|
||||||
const DATE_FORMAT_MYSQL = 'yyyy-MM-dd HH:mm:ss';
|
const DATE_FORMAT_MYSQL = 'yyyy-MM-dd HH:mm:ss';
|
||||||
const DATE_FORMAT_CAPTION = 'yyyy/MM/dd'; // ES format
|
const DATE_FORMAT_CAPTION = 'yyyy/MM/dd'; // ES format
|
||||||
const DATE_FORMAT_MYSQL_OR_CAPTION = 'yyyy-MM-dd HH:mm:ss||yyyy/MM/dd';
|
const DATE_FORMAT_MYSQL_OR_CAPTION = 'yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||yyyy-MM||yyyy';
|
||||||
const DATE_FORMAT_CAPTION_PHP = 'Y/m/d'; // PHP format
|
|
||||||
|
|
||||||
// Core types
|
// Core types
|
||||||
const TYPE_STRING = 'string';
|
const TYPE_STRING = 'string';
|
||||||
|
@@ -57,6 +57,9 @@ class DateFieldMapping extends ComplexFieldMapping
|
|||||||
*/
|
*/
|
||||||
protected function getProperties()
|
protected function getProperties()
|
||||||
{
|
{
|
||||||
return array_merge([ 'format' => $this->format ], parent::getProperties());
|
return array_merge([
|
||||||
|
'format' => $this->format,
|
||||||
|
'ignore_malformed' => true
|
||||||
|
], parent::getProperties());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -89,31 +89,45 @@ class RecordHelper
|
|||||||
return $this->collectionMap;
|
return $this->collectionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $date
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function validateDate($date)
|
|
||||||
{
|
|
||||||
$d = DateTime::createFromFormat(FieldMapping::DATE_FORMAT_CAPTION_PHP, $date);
|
|
||||||
|
|
||||||
return $d && $d->format(FieldMapping::DATE_FORMAT_CAPTION_PHP) == $date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $value
|
* @param string $value
|
||||||
* @return null|string
|
* @return null|string
|
||||||
*/
|
*/
|
||||||
public static function sanitizeDate($value)
|
public static function sanitizeDate($value)
|
||||||
{
|
{
|
||||||
// introduced in https://github.com/alchemy-fr/Phraseanet/commit/775ce804e0257d3a06e4e068bd17330a79eb8370#diff-bee690ed259e0cf73a31dee5295d2edcR286
|
$v_fix = null;
|
||||||
// not sure if it's really needed
|
|
||||||
try {
|
try {
|
||||||
$date = new \DateTime($value);
|
$a = explode(';', preg_replace('/\D+/', ';', trim($value)));
|
||||||
|
switch (count($a)) {
|
||||||
return $date->format(FieldMapping::DATE_FORMAT_CAPTION_PHP);
|
case 1: // yyyy
|
||||||
|
$date = new \DateTime($a[0] . '-01-01'); // will throw if date is not valid
|
||||||
|
$v_fix = $date->format('Y');
|
||||||
|
break;
|
||||||
|
case 2: // yyyy;mm
|
||||||
|
$date = new \DateTime( $a[0] . '-' . $a[1] . '-01');
|
||||||
|
$v_fix = $date->format('Y-m');
|
||||||
|
break;
|
||||||
|
case 3: // yyyy;mm;dd
|
||||||
|
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2]);
|
||||||
|
$v_fix = $date->format('Y-m-d');
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':00:00');
|
||||||
|
$v_fix = $date->format('Y-m-d H:i:s');
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':00');
|
||||||
|
$v_fix = $date->format('Y-m-d H:i:s');
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':' . $a[5]);
|
||||||
|
$v_fix = $date->format('Y-m-d H:i:s');
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return null;
|
// no-op, v_fix = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $v_fix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -110,41 +110,50 @@ class QueryHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getRangeFromDateString($string)
|
public static function getRangeFromDateString($value)
|
||||||
{
|
{
|
||||||
$formats = ['Y/m/d', 'Y/m', 'Y'];
|
$date_from = null;
|
||||||
$deltas = ['+1 day', '+1 month', '+1 year'];
|
$date_to = null;
|
||||||
$to = null;
|
try {
|
||||||
while ($format = array_pop($formats)) {
|
$a = explode(';', preg_replace('/\D+/', ';', trim($value)));
|
||||||
$delta = array_pop($deltas);
|
switch (count($a)) {
|
||||||
$from = date_create_from_format($format, $string);
|
case 1: // yyyy
|
||||||
if ($from !== false) {
|
$date_to = clone($date_from = new \DateTime($a[0] . '-01-01 00:00:00')); // will throw if date is not valid
|
||||||
// Rewind to start of range
|
$date_to->add(new \DateInterval('P1Y'));
|
||||||
$month = 1;
|
break;
|
||||||
$day = 1;
|
case 2: // yyyy;mm
|
||||||
switch ($format) {
|
$date_to = clone($date_from = new \DateTime($a[0] . '-' . $a[1] . '-01 00:00:00')); // will throw if date is not valid
|
||||||
case 'Y/m/d':
|
$date_to->add(new \DateInterval('P1M'));
|
||||||
$day = (int) $from->format('d');
|
break;
|
||||||
case 'Y/m':
|
case 3: // yyyy;mm;dd
|
||||||
$month = (int) $from->format('m');
|
$date_to = clone($date_from = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' 00:00:00')); // will throw if date is not valid
|
||||||
case 'Y':
|
$date_to->add(new \DateInterval('P1D'));
|
||||||
$year = (int) $from->format('Y');
|
break;
|
||||||
}
|
case 4:
|
||||||
date_date_set($from, $year, $month, $day);
|
$date_to = clone($date_from = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':00:00'));
|
||||||
date_time_set($from, 0, 0, 0);
|
$date_to->add(new \DateInterval('PT1H'));
|
||||||
// Create end of the the range
|
break;
|
||||||
$to = date_modify(clone $from, $delta);
|
case 5:
|
||||||
break;
|
$date_to = clone($date_from = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':00'));
|
||||||
|
$date_to->add(new \DateInterval('PT1M'));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
$date_to = clone($date_from = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':' . $a[5]));
|
||||||
|
// $date_to->add(new \DateInterval('PT1S')); // no need since precision is 1 sec, a "equal" will be generated when from==to
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
if (!$from || !$to) {
|
if ($date_from === null || $date_to === null) {
|
||||||
throw new \InvalidArgumentException(sprintf('Invalid date "%s".', $string));
|
throw new \InvalidArgumentException(sprintf('Invalid date "%s".', $value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'from' => $from->format(FieldMapping::DATE_FORMAT_CAPTION_PHP),
|
'from' => $date_from->format('Y-m-d H:i:s'),
|
||||||
'to' => $to->format(FieldMapping::DATE_FORMAT_CAPTION_PHP)
|
'to' => $date_to->format('Y-m-d H:i:s')
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ namespace Alchemy\Phrasea\SearchEngine\Elastic\Search;
|
|||||||
use Alchemy\Phrasea\SearchEngine\Elastic\AST;
|
use Alchemy\Phrasea\SearchEngine\Elastic\AST;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\Exception;
|
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\Exception;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\FieldMapping;
|
use Alchemy\Phrasea\SearchEngine\Elastic\FieldMapping;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Mapping;
|
use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure;
|
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure;
|
||||||
use Hoa\Compiler\Llk\TreeNode;
|
use Hoa\Compiler\Llk\TreeNode;
|
||||||
use Hoa\Visitor\Element;
|
use Hoa\Visitor\Element;
|
||||||
@@ -166,6 +166,12 @@ class QueryVisitor implements Visit
|
|||||||
$key = $node->getChild(0)->accept($this);
|
$key = $node->getChild(0)->accept($this);
|
||||||
$boundary = $node->getChild(1)->accept($this);
|
$boundary = $node->getChild(1)->accept($this);
|
||||||
|
|
||||||
|
if ($this->isDateKey($key)) {
|
||||||
|
if(($v = RecordHelper::sanitizeDate($boundary)) !== null) {
|
||||||
|
$boundary = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch ($node->getId()) {
|
switch ($node->getId()) {
|
||||||
case NodeTypes::LT_EXPR:
|
case NodeTypes::LT_EXPR:
|
||||||
return AST\KeyValue\RangeExpression::lessThan($key, $boundary);
|
return AST\KeyValue\RangeExpression::lessThan($key, $boundary);
|
||||||
@@ -195,11 +201,15 @@ class QueryVisitor implements Visit
|
|||||||
try {
|
try {
|
||||||
// Try to create a range for incomplete dates
|
// Try to create a range for incomplete dates
|
||||||
$range = QueryHelper::getRangeFromDateString($right);
|
$range = QueryHelper::getRangeFromDateString($right);
|
||||||
return new AST\KeyValue\RangeExpression(
|
if ($range['from'] === $range['to']) {
|
||||||
$left,
|
return new AST\KeyValue\EqualExpression($left, $range['from']);
|
||||||
$range['from'], true,
|
} else {
|
||||||
$range['to'], false
|
return new AST\KeyValue\RangeExpression(
|
||||||
);
|
$left,
|
||||||
|
$range['from'], true,
|
||||||
|
$range['to'], false
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (\InvalidArgumentException $e) {
|
} catch (\InvalidArgumentException $e) {
|
||||||
// Fall back to equal expression
|
// Fall back to equal expression
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
namespace Alchemy\Phrasea\SearchEngine\Elastic\Structure;
|
namespace Alchemy\Phrasea\SearchEngine\Elastic\Structure;
|
||||||
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\FieldMapping;
|
use Alchemy\Phrasea\SearchEngine\Elastic\FieldMapping;
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\Mapping;
|
|
||||||
use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper;
|
use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper;
|
||||||
use Assert\Assertion;
|
use Assert\Assertion;
|
||||||
|
|
||||||
@@ -20,7 +19,7 @@ class ValueChecker
|
|||||||
{
|
{
|
||||||
Assertion::allIsInstanceOf($list, Typed::class);
|
Assertion::allIsInstanceOf($list, Typed::class);
|
||||||
$is_numeric = is_numeric($value);
|
$is_numeric = is_numeric($value);
|
||||||
$is_valid_date = RecordHelper::validateDate($value);
|
$is_valid_date = (RecordHelper::sanitizeDate($value) !== null);
|
||||||
$filtered = [];
|
$filtered = [];
|
||||||
foreach ($list as $item) {
|
foreach ($list as $item) {
|
||||||
switch ($item->getType()) {
|
switch ($item->getType()) {
|
||||||
|
@@ -127,7 +127,10 @@ class WriteMetadataJob extends AbstractJob
|
|||||||
|
|
||||||
// check exiftool known tags to skip Phraseanet:tf-*
|
// check exiftool known tags to skip Phraseanet:tf-*
|
||||||
try {
|
try {
|
||||||
TagFactory::getFromRDFTagname($tagName);
|
$tag = TagFactory::getFromRDFTagname($tagName);
|
||||||
|
if(!$tag->isWritable()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
} catch (TagUnknown $e) {
|
} catch (TagUnknown $e) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -147,21 +150,34 @@ class WriteMetadataJob extends AbstractJob
|
|||||||
$fieldValue = array_pop($fieldValues);
|
$fieldValue = array_pop($fieldValues);
|
||||||
$value = $this->removeNulChar($fieldValue->getValue());
|
$value = $this->removeNulChar($fieldValue->getValue());
|
||||||
|
|
||||||
$value = new Value\Mono($value);
|
// fix the dates edited into phraseanet
|
||||||
|
if($fieldStructure->get_type() === $fieldStructure::TYPE_DATE) {
|
||||||
|
try {
|
||||||
|
$value = self::fixDate($value); // will return NULL if the date is not valid
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
$value = null; // do NOT write back to iptc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($value !== null) { // do not write invalid dates
|
||||||
|
$value = new Value\Mono($value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch(\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
// the field is not set in the record, erase it
|
// the field is not set in the record, erase it
|
||||||
if ($fieldStructure->is_multi()) {
|
if ($fieldStructure->is_multi()) {
|
||||||
$value = new Value\Multi(array(''));
|
$value = new Value\Multi(array(''));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$value = new Value\Mono('');
|
$value = new Value\Mono('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$metadata->add(
|
if($value !== null) { // do not write invalid data
|
||||||
new Metadata\Metadata($fieldStructure->get_tag(), $value)
|
$metadata->add(
|
||||||
);
|
new Metadata\Metadata($fieldStructure->get_tag(), $value)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$writer = $this->getMetadataWriter($jobData->getApplication());
|
$writer = $this->getMetadataWriter($jobData->getApplication());
|
||||||
@@ -220,4 +236,34 @@ class WriteMetadataJob extends AbstractJob
|
|||||||
{
|
{
|
||||||
return str_replace("\0", "", $value);
|
return str_replace("\0", "", $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* re-format a phraseanet date for iptc writing
|
||||||
|
* return NULL if the date is not valid
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
private static function fixDate($value)
|
||||||
|
{
|
||||||
|
$date = null;
|
||||||
|
try {
|
||||||
|
$a = explode(';', preg_replace('/\D+/', ';', trim($value)));
|
||||||
|
switch (count($a)) {
|
||||||
|
case 3: // yyyy;mm;dd
|
||||||
|
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2]);
|
||||||
|
$date = $date->format('Y-m-d H:i:s');
|
||||||
|
break;
|
||||||
|
case 6: // yyyy;mm;dd;hh;mm;ss
|
||||||
|
$date = new \DateTime($a[0] . '-' . $a[1] . '-' . $a[2] . ' ' . $a[3] . ':' . $a[4] . ':' . $a[5]);
|
||||||
|
$date = $date->format('Y-m-d H:i:s');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
$date = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $date;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,7 @@ class RangeExpressionTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$query_context = $this->prophesize(QueryContext::class)->reveal();
|
$query_context = $this->prophesize(QueryContext::class)->reveal();
|
||||||
$key_prophecy = $this->prophesize(Key::class);
|
$key_prophecy = $this->prophesize(Key::class);
|
||||||
|
$key_prophecy->getFieldType($query_context)->willReturn('text');
|
||||||
$key_prophecy->getIndexField($query_context)->willReturn('foo');
|
$key_prophecy->getIndexField($query_context)->willReturn('foo');
|
||||||
$key_prophecy->isValueCompatible('bar', $query_context)->willReturn(true);
|
$key_prophecy->isValueCompatible('bar', $query_context)->willReturn(true);
|
||||||
$key = $key_prophecy->reveal();
|
$key = $key_prophecy->reveal();
|
||||||
@@ -73,6 +74,7 @@ class RangeExpressionTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$query_context = $this->prophesize(QueryContext::class)->reveal();
|
$query_context = $this->prophesize(QueryContext::class)->reveal();
|
||||||
$key = $this->prophesize(FieldKey::class);
|
$key = $this->prophesize(FieldKey::class);
|
||||||
|
$key->getFieldType($query_context)->willReturn('text');
|
||||||
$key->getIndexField($query_context)->willReturn('baz');
|
$key->getIndexField($query_context)->willReturn('baz');
|
||||||
$key->isValueCompatible('bar', $query_context)->willReturn(true);
|
$key->isValueCompatible('bar', $query_context)->willReturn(true);
|
||||||
$key->postProcessQuery(Argument::any(), $query_context)->willReturnArgument(0);
|
$key->postProcessQuery(Argument::any(), $query_context)->willReturnArgument(0);
|
||||||
|
@@ -53,6 +53,7 @@ foo < 42|<range:field.foo lt="42">
|
|||||||
foo ≤ 42|<range:field.foo lte="42">
|
foo ≤ 42|<range:field.foo lte="42">
|
||||||
foo > 42|<range:field.foo gt="42">
|
foo > 42|<range:field.foo gt="42">
|
||||||
foo ≥ 42|<range:field.foo gte="42">
|
foo ≥ 42|<range:field.foo gte="42">
|
||||||
|
foo = 2015/01/01|(<field.foo> == <value:"2015/01/01">)
|
||||||
foo < 2015/01/01|<range:field.foo lt="2015/01/01">
|
foo < 2015/01/01|<range:field.foo lt="2015/01/01">
|
||||||
foo ≤ 2015/01/01|<range:field.foo lte="2015/01/01">
|
foo ≤ 2015/01/01|<range:field.foo lte="2015/01/01">
|
||||||
foo > 2015/01/01|<range:field.foo gt="2015/01/01">
|
foo > 2015/01/01|<range:field.foo gt="2015/01/01">
|
||||||
@@ -93,19 +94,93 @@ id:90 AND foo|(<record_identifier:"90"> AND <text:"foo">)
|
|||||||
id:90 foo|(<record_identifier:"90"> AND <text:"foo">)
|
id:90 foo|(<record_identifier:"90"> AND <text:"foo">)
|
||||||
recordid:90|<record_identifier:"90">
|
recordid:90|<record_identifier:"90">
|
||||||
|
|
||||||
# Timestamps
|
# Timestamps yyyy
|
||||||
created_on < "2015/01/01"|<range:creation lt="2015/01/01">
|
created_on < "2015"|<range:creation lt="2015">
|
||||||
created_on ≤ "2015/01/01"|<range:creation lte="2015/01/01">
|
created_on ≤ "2015"|<range:creation lte="2015">
|
||||||
created_on = "2015/01/01"|<range:creation gte="2015/01/01" lt="2015/01/02">
|
created_on = "2015"|<range:creation gte="2015-01-01 00:00:00" lt="2016-01-01 00:00:00">
|
||||||
created_on ≥ "2015/01/01"|<range:creation gte="2015/01/01">
|
created_on ≥ "2015"|<range:creation gte="2015">
|
||||||
created_on > "2015/01/01"|<range:creation gt="2015/01/01">
|
created_on > "2015"|<range:creation gt="2015">
|
||||||
updated_on < "2015/01/01"|<range:update lt="2015/01/01">
|
updated_on < "2015"|<range:update lt="2015">
|
||||||
updated_on ≤ "2015/01/01"|<range:update lte="2015/01/01">
|
updated_on ≤ "2015"|<range:update lte="2015">
|
||||||
updated_on = "2015/01/01"|<range:update gte="2015/01/01" lt="2015/01/02">
|
updated_on = "2015"|<range:update gte="2015-01-01 00:00:00" lt="2016-01-01 00:00:00">
|
||||||
updated_on ≥ "2015/01/01"|<range:update gte="2015/01/01">
|
updated_on ≥ "2015"|<range:update gte="2015">
|
||||||
updated_on > "2015/01/01"|<range:update gt="2015/01/01">
|
updated_on > "2015"|<range:update gt="2015">
|
||||||
created_at > "2015/01/01"|<range:creation gt="2015/01/01">
|
created_at > "2015"|<range:creation gt="2015">
|
||||||
updated_at > "2015/01/01"|<range:update gt="2015/01/01">
|
updated_at > "2015"|<range:update gt="2015">
|
||||||
|
|
||||||
|
# Timestamps yyyy/mm
|
||||||
|
created_on < "2015/01"|<range:creation lt="2015-01">
|
||||||
|
created_on ≤ "2015/01"|<range:creation lte="2015-01">
|
||||||
|
created_on = "2015/01"|<range:creation gte="2015-01-01 00:00:00" lt="2015-02-01 00:00:00">
|
||||||
|
created_on ≥ "2015/01"|<range:creation gte="2015-01">
|
||||||
|
created_on > "2015/01"|<range:creation gt="2015-01">
|
||||||
|
updated_on < "2015/01"|<range:update lt="2015-01">
|
||||||
|
updated_on ≤ "2015/01"|<range:update lte="2015-01">
|
||||||
|
updated_on = "2015/01"|<range:update gte="2015-01-01 00:00:00" lt="2015-02-01 00:00:00">
|
||||||
|
updated_on ≥ "2015/01"|<range:update gte="2015-01">
|
||||||
|
updated_on > "2015/01"|<range:update gt="2015-01">
|
||||||
|
created_at > "2015/01"|<range:creation gt="2015-01">
|
||||||
|
updated_at > "2015/01"|<range:update gt="2015-01">
|
||||||
|
|
||||||
|
# Timestamps yyyy/mm/dd
|
||||||
|
created_on < "2015/01/01"|<range:creation lt="2015-01-01">
|
||||||
|
created_on ≤ "2015/01/01"|<range:creation lte="2015-01-01">
|
||||||
|
created_on = "2015/01/01"|<range:creation gte="2015-01-01 00:00:00" lt="2015-01-02 00:00:00">
|
||||||
|
created_on ≥ "2015/01/01"|<range:creation gte="2015-01-01">
|
||||||
|
created_on > "2015/01/01"|<range:creation gt="2015-01-01">
|
||||||
|
updated_on < "2015/01/01"|<range:update lt="2015-01-01">
|
||||||
|
updated_on ≤ "2015/01/01"|<range:update lte="2015-01-01">
|
||||||
|
updated_on = "2015/01/01"|<range:update gte="2015-01-01 00:00:00" lt="2015-01-02 00:00:00">
|
||||||
|
updated_on ≥ "2015/01/01"|<range:update gte="2015-01-01">
|
||||||
|
updated_on > "2015/01/01"|<range:update gt="2015-01-01">
|
||||||
|
created_at > "2015/01/01"|<range:creation gt="2015-01-01">
|
||||||
|
updated_at > "2015/01/01"|<range:update gt="2015-01-01">
|
||||||
|
|
||||||
|
# Timestamps yyyy/mm/dd hh
|
||||||
|
created_on < "2015/01/01 12"|<range:creation lt="2015-01-01 12:00:00">
|
||||||
|
created_on ≤ "2015/01/01 12"|<range:creation lte="2015-01-01 12:00:00">
|
||||||
|
created_on = "2015/01/01 12"|<range:creation gte="2015-01-01 12:00:00" lt="2015-01-01 13:00:00">
|
||||||
|
created_on ≥ "2015/01/01 12"|<range:creation gte="2015-01-01 12:00:00">
|
||||||
|
created_on > "2015/01/01 12"|<range:creation gt="2015-01-01 12:00:00">
|
||||||
|
updated_on < "2015/01/01 12"|<range:update lt="2015-01-01 12:00:00">
|
||||||
|
updated_on ≤ "2015/01/01 12"|<range:update lte="2015-01-01 12:00:00">
|
||||||
|
updated_on = "2015/01/01 12"|<range:update gte="2015-01-01 12:00:00" lt="2015-01-01 13:00:00">
|
||||||
|
updated_on ≥ "2015/01/01 12"|<range:update gte="2015-01-01 12:00:00">
|
||||||
|
updated_on > "2015/01/01 12"|<range:update gt="2015-01-01 12:00:00">
|
||||||
|
created_at > "2015/01/01 12"|<range:creation gt="2015-01-01 12:00:00">
|
||||||
|
updated_at > "2015/01/01 12"|<range:update gt="2015-01-01 12:00:00">
|
||||||
|
|
||||||
|
# Timestamps yyyy/mm/dd hh:mm
|
||||||
|
created_on < "2015/01/01 12.34"|<range:creation lt="2015-01-01 12:34:00">
|
||||||
|
created_on ≤ "2015/01/01 12.34"|<range:creation lte="2015-01-01 12:34:00">
|
||||||
|
created_on = "2015/01/01 12.34"|<range:creation gte="2015-01-01 12:34:00" lt="2015-01-01 12:35:00">
|
||||||
|
created_on ≥ "2015/01/01 12.34"|<range:creation gte="2015-01-01 12:34:00">
|
||||||
|
created_on > "2015/01/01 12.34"|<range:creation gt="2015-01-01 12:34:00">
|
||||||
|
updated_on < "2015/01/01 12.34"|<range:update lt="2015-01-01 12:34:00">
|
||||||
|
updated_on ≤ "2015/01/01 12.34"|<range:update lte="2015-01-01 12:34:00">
|
||||||
|
updated_on = "2015/01/01 12.34"|<range:update gte="2015-01-01 12:34:00" lt="2015-01-01 12:35:00">
|
||||||
|
updated_on ≥ "2015/01/01 12.34"|<range:update gte="2015-01-01 12:34:00">
|
||||||
|
updated_on > "2015/01/01 12.34"|<range:update gt="2015-01-01 12:34:00">
|
||||||
|
created_at > "2015/01/01 12.34"|<range:creation gt="2015-01-01 12:34:00">
|
||||||
|
updated_at > "2015/01/01 12.34"|<range:update gt="2015-01-01 12:34:00">
|
||||||
|
|
||||||
|
# Timestamps yyyy/mm/dd hh.mm.ss
|
||||||
|
created_on < "2015/01/01 12.34.56"|<range:creation lt="2015-01-01 12:34:56">
|
||||||
|
created_on ≤ "2015/01/01 12.34.56"|<range:creation lte="2015-01-01 12:34:56">
|
||||||
|
created_on = "2015/01/01 12.34.56"|(<creation> == <value:"2015-01-01 12:34:56">)
|
||||||
|
created_on ≥ "2015/01/01 12.34.56"|<range:creation gte="2015-01-01 12:34:56">
|
||||||
|
created_on > "2015/01/01 12.34.56"|<range:creation gt="2015-01-01 12:34:56">
|
||||||
|
updated_on < "2015/01/01 12.34.56"|<range:update lt="2015-01-01 12:34:56">
|
||||||
|
updated_on ≤ "2015/01/01 12.34.56"|<range:update lte="2015-01-01 12:34:56">
|
||||||
|
updated_on = "2015/01/01 12.34.56"|(<update> == <value:"2015-01-01 12:34:56">)
|
||||||
|
updated_on ≥ "2015/01/01 12.34.56"|<range:update gte="2015-01-01 12:34:56">
|
||||||
|
updated_on > "2015/01/01 12.34.56"|<range:update gt="2015-01-01 12:34:56">
|
||||||
|
created_at > "2015/01/01 12.34.56"|<range:creation gt="2015-01-01 12:34:56">
|
||||||
|
updated_at > "2015/01/01 12.34.56"|<range:update gt="2015-01-01 12:34:56">
|
||||||
|
|
||||||
|
# timestamps missing zeros
|
||||||
|
created_on = "2015/1/2 1.3.5"|(<creation> == <value:"2015-01-02 01:03:05">)
|
||||||
|
|
||||||
|
|
||||||
# Flag matcher
|
# Flag matcher
|
||||||
flag.foo:true|<flag:foo set>
|
flag.foo:true|<flag:foo set>
|
||||||
|
Can't render this file because it contains an unexpected character in line 1 and column 11.
|
Reference in New Issue
Block a user