mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-30 13:34:28 +02:00
Allow to filter by the number of part lots.
This commit is contained in:
parent
99b25fb293
commit
b8c77ca855
4 changed files with 63 additions and 3 deletions
|
@ -7,6 +7,23 @@ use Doctrine\ORM\QueryBuilder;
|
||||||
trait FilterTrait
|
trait FilterTrait
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected $useHaving = false;
|
||||||
|
|
||||||
|
public function useHaving($value = true): self
|
||||||
|
{
|
||||||
|
$this->useHaving = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given input is an aggregateFunction like COUNT(part.partsLot) or so
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isAggregateFunctionString(string $input): bool
|
||||||
|
{
|
||||||
|
return preg_match('/^[a-zA-Z]+\(.*\)$/', $input) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a parameter identifier that can be used for the given property. It gives random results, to be unique, so you have to cache it.
|
* Generates a parameter identifier that can be used for the given property. It gives random results, to be unique, so you have to cache it.
|
||||||
* @param string $property
|
* @param string $property
|
||||||
|
@ -14,7 +31,10 @@ trait FilterTrait
|
||||||
*/
|
*/
|
||||||
protected function generateParameterIdentifier(string $property): string
|
protected function generateParameterIdentifier(string $property): string
|
||||||
{
|
{
|
||||||
return str_replace('.', '_', $property) . '_' . uniqid("", false);
|
//Replace all special characters with underscores
|
||||||
|
$property = preg_replace('/[^a-zA-Z0-9_]/', '_', $property);
|
||||||
|
//Add a random number to the end of the property name for uniqueness
|
||||||
|
return $property . '_' . uniqid("", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +47,12 @@ trait FilterTrait
|
||||||
*/
|
*/
|
||||||
protected function addSimpleAndConstraint(QueryBuilder $queryBuilder, string $property, string $parameterIdentifier, string $comparison_operator, $value): void
|
protected function addSimpleAndConstraint(QueryBuilder $queryBuilder, string $property, string $parameterIdentifier, string $comparison_operator, $value): void
|
||||||
{
|
{
|
||||||
$queryBuilder->andWhere(sprintf("%s %s (:%s)", $property, $comparison_operator, $parameterIdentifier));
|
if($this->useHaving || $this->isAggregateFunctionString($property)) { //If the property is an aggregate function, we have to use the "having" instead of the "where"
|
||||||
|
$queryBuilder->andHaving(sprintf("%s %s (:%s)", $property, $comparison_operator, $parameterIdentifier));
|
||||||
|
} else {
|
||||||
|
$queryBuilder->andWhere(sprintf("%s %s (:%s)", $property, $comparison_operator, $parameterIdentifier));
|
||||||
|
}
|
||||||
|
|
||||||
$queryBuilder->setParameter($parameterIdentifier, $value);
|
$queryBuilder->setParameter($parameterIdentifier, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
20
src/DataTables/Filters/Constraints/IntConstraint.php
Normal file
20
src/DataTables/Filters/Constraints/IntConstraint.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\DataTables\Filters\Constraints;
|
||||||
|
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
|
||||||
|
class IntConstraint extends NumberConstraint
|
||||||
|
{
|
||||||
|
public function apply(QueryBuilder $queryBuilder): void
|
||||||
|
{
|
||||||
|
if($this->value1 !== null) {
|
||||||
|
$this->value1 = (int) $this->value1;
|
||||||
|
}
|
||||||
|
if($this->value2 !== null) {
|
||||||
|
$this->value2 = (int) $this->value2;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::apply($queryBuilder);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ namespace App\DataTables\Filters;
|
||||||
use App\DataTables\Filters\Constraints\BooleanConstraint;
|
use App\DataTables\Filters\Constraints\BooleanConstraint;
|
||||||
use App\DataTables\Filters\Constraints\DateTimeConstraint;
|
use App\DataTables\Filters\Constraints\DateTimeConstraint;
|
||||||
use App\DataTables\Filters\Constraints\EntityConstraint;
|
use App\DataTables\Filters\Constraints\EntityConstraint;
|
||||||
|
use App\DataTables\Filters\Constraints\IntConstraint;
|
||||||
use App\DataTables\Filters\Constraints\NumberConstraint;
|
use App\DataTables\Filters\Constraints\NumberConstraint;
|
||||||
use App\DataTables\Filters\Constraints\Part\TagsConstraint;
|
use App\DataTables\Filters\Constraints\Part\TagsConstraint;
|
||||||
use App\DataTables\Filters\Constraints\TextConstraint;
|
use App\DataTables\Filters\Constraints\TextConstraint;
|
||||||
|
@ -70,6 +71,9 @@ class PartFilter implements FilterInterface
|
||||||
/** @var EntityConstraint */
|
/** @var EntityConstraint */
|
||||||
protected $storelocation;
|
protected $storelocation;
|
||||||
|
|
||||||
|
/** @var NumberConstraint */
|
||||||
|
protected $lotCount;
|
||||||
|
|
||||||
/** @var EntityConstraint */
|
/** @var EntityConstraint */
|
||||||
protected $measurementUnit;
|
protected $measurementUnit;
|
||||||
|
|
||||||
|
@ -92,7 +96,7 @@ class PartFilter implements FilterInterface
|
||||||
$this->needsReview = new BooleanConstraint('part.needs_review');
|
$this->needsReview = new BooleanConstraint('part.needs_review');
|
||||||
$this->measurementUnit = new EntityConstraint($nodesListBuilder, MeasurementUnit::class, 'part.partUnit');
|
$this->measurementUnit = new EntityConstraint($nodesListBuilder, MeasurementUnit::class, 'part.partUnit');
|
||||||
$this->mass = new NumberConstraint('part.mass');
|
$this->mass = new NumberConstraint('part.mass');
|
||||||
$this->dbId = new NumberConstraint('part.id');
|
$this->dbId = new IntConstraint('part.id');
|
||||||
$this->addedDate = new DateTimeConstraint('part.addedDate');
|
$this->addedDate = new DateTimeConstraint('part.addedDate');
|
||||||
$this->lastModified = new DateTimeConstraint('part.lastModified');
|
$this->lastModified = new DateTimeConstraint('part.lastModified');
|
||||||
|
|
||||||
|
@ -104,6 +108,7 @@ class PartFilter implements FilterInterface
|
||||||
$this->manufacturer_product_url = new TextConstraint('part.manufacturer_product_url');
|
$this->manufacturer_product_url = new TextConstraint('part.manufacturer_product_url');
|
||||||
|
|
||||||
$this->storelocation = new EntityConstraint($nodesListBuilder, Storelocation::class, 'partLots.storage_location');
|
$this->storelocation = new EntityConstraint($nodesListBuilder, Storelocation::class, 'partLots.storage_location');
|
||||||
|
$this->lotCount = new IntConstraint('COUNT(partLots)');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function apply(QueryBuilder $queryBuilder): void
|
public function apply(QueryBuilder $queryBuilder): void
|
||||||
|
@ -244,6 +249,11 @@ class PartFilter implements FilterInterface
|
||||||
return $this->manufacturer_product_number;
|
return $this->manufacturer_product_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getLotCount(): NumberConstraint
|
||||||
|
{
|
||||||
|
return $this->lotCount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return TagsConstraint
|
* @return TagsConstraint
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -142,6 +142,11 @@ class PartFilterType extends AbstractType
|
||||||
'min' => 0,
|
'min' => 0,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$builder->add('lotCount', NumberConstraintType::class, [
|
||||||
|
'label' => 'part.filter.lot_count',
|
||||||
|
'min' => 0
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
$builder->add('submit', SubmitType::class, [
|
$builder->add('submit', SubmitType::class, [
|
||||||
'label' => 'Update',
|
'label' => 'Update',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue