mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-30 05:24:28 +02:00
Added an filter constraint based on part tags.
This commit is contained in:
parent
4d3ff7d7b5
commit
4ba58cc621
7 changed files with 234 additions and 4 deletions
137
src/DataTables/Filters/Constraints/Part/TagsConstraint.php
Normal file
137
src/DataTables/Filters/Constraints/Part/TagsConstraint.php
Normal file
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
namespace App\DataTables\Filters\Constraints\Part;
|
||||
|
||||
use App\DataTables\Filters\Constraints\AbstractConstraint;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
class TagsConstraint extends AbstractConstraint
|
||||
{
|
||||
public const ALLOWED_OPERATOR_VALUES = ['ANY', 'ALL', 'NONE'];
|
||||
|
||||
/**
|
||||
* @var string|null The operator to use
|
||||
*/
|
||||
protected $operator;
|
||||
|
||||
/**
|
||||
* @var string The value to compare to
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
public function __construct(string $property, string $identifier = null, $value = null, string $operator = '')
|
||||
{
|
||||
parent::__construct($property, $identifier);
|
||||
$this->value = $value;
|
||||
$this->operator = $operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOperator(): ?string
|
||||
{
|
||||
return $this->operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $operator
|
||||
*/
|
||||
public function setOperator(?string $operator): self
|
||||
{
|
||||
$this->operator = $operator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function setValue(string $value): self
|
||||
{
|
||||
$this->value = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->value !== null
|
||||
&& !empty($this->operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of tags based on the comma separated tags list
|
||||
* @return string[]
|
||||
*/
|
||||
public function getTags(): array
|
||||
{
|
||||
return explode(',', trim($this->value, ','));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an expression to query for a single tag
|
||||
* @param QueryBuilder $queryBuilder
|
||||
* @param string $tag
|
||||
* @return Expr\Orx
|
||||
*/
|
||||
protected function getExpressionForTag(QueryBuilder $queryBuilder, string $tag): Expr\Orx
|
||||
{
|
||||
$tag_identifier_prefix = uniqid($this->identifier . '_', false);
|
||||
|
||||
$expr = $queryBuilder->expr();
|
||||
|
||||
$tmp = $expr->orX(
|
||||
$expr->like($this->property, ':' . $tag_identifier_prefix . '_1'),
|
||||
$expr->like($this->property, ':' . $tag_identifier_prefix . '_2'),
|
||||
$expr->like($this->property, ':' . $tag_identifier_prefix . '_3'),
|
||||
$expr->eq($this->property, ':' . $tag_identifier_prefix . '_4'),
|
||||
);
|
||||
|
||||
//Set the parameters for the LIKE expression, in each variation of the tag (so with a comma, at the end, at the beginning, and on both ends, and equaling the tag)
|
||||
$queryBuilder->setParameter($tag_identifier_prefix . '_1', '%,' . $tag . ',%');
|
||||
$queryBuilder->setParameter($tag_identifier_prefix . '_2', '%,' . $tag);
|
||||
$queryBuilder->setParameter($tag_identifier_prefix . '_3', $tag . ',%');
|
||||
$queryBuilder->setParameter($tag_identifier_prefix . '_4', $tag);
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
public function apply(QueryBuilder $queryBuilder): void
|
||||
{
|
||||
if(!$this->isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!in_array($this->operator, self::ALLOWED_OPERATOR_VALUES, true)) {
|
||||
throw new \RuntimeException('Invalid operator '. $this->operator . ' provided. Valid operators are '. implode(', ', self::ALLOWED_OPERATOR_VALUES));
|
||||
}
|
||||
|
||||
$tagsExpressions = [];
|
||||
foreach ($this->getTags() as $tag) {
|
||||
$tagsExpressions[] = $this->getExpressionForTag($queryBuilder, $tag);
|
||||
}
|
||||
|
||||
if ($this->operator === 'ANY') {
|
||||
$queryBuilder->andWhere($queryBuilder->expr()->orX(...$tagsExpressions));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->operator === 'ALL') {
|
||||
$queryBuilder->andWhere($queryBuilder->expr()->andX(...$tagsExpressions));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->operator === 'NONE') {
|
||||
$queryBuilder->andWhere($queryBuilder->expr()->not($queryBuilder->expr()->orX(...$tagsExpressions)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ use App\DataTables\Filters\Constraints\BooleanConstraint;
|
|||
use App\DataTables\Filters\Constraints\DateTimeConstraint;
|
||||
use App\DataTables\Filters\Constraints\EntityConstraint;
|
||||
use App\DataTables\Filters\Constraints\NumberConstraint;
|
||||
use App\DataTables\Filters\Constraints\Part\TagsConstraint;
|
||||
use App\DataTables\Filters\Constraints\TextConstraint;
|
||||
use App\Entity\Parts\Category;
|
||||
use App\Entity\Parts\Footprint;
|
||||
|
@ -33,6 +34,9 @@ class PartFilter implements FilterInterface
|
|||
/** @var TextConstraint */
|
||||
protected $comment;
|
||||
|
||||
/** @var TagsConstraint */
|
||||
protected $tags;
|
||||
|
||||
/** @var NumberConstraint */
|
||||
protected $minAmount;
|
||||
|
||||
|
@ -82,6 +86,7 @@ class PartFilter implements FilterInterface
|
|||
$this->comment = new TextConstraint('part.comment');
|
||||
$this->category = new EntityConstraint($nodesListBuilder, Category::class, 'part.category');
|
||||
$this->footprint = new EntityConstraint($nodesListBuilder, Footprint::class, 'part.footprint');
|
||||
$this->tags = new TagsConstraint('part.tags');
|
||||
|
||||
$this->favorite = new BooleanConstraint('part.favorite');
|
||||
$this->needsReview = new BooleanConstraint('part.needs_review');
|
||||
|
@ -239,7 +244,11 @@ class PartFilter implements FilterInterface
|
|||
return $this->manufacturer_product_number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return TagsConstraint
|
||||
*/
|
||||
public function getTags(): TagsConstraint
|
||||
{
|
||||
return $this->tags;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue