Skip to content

Commit

Permalink
styleci
Browse files Browse the repository at this point in the history
  • Loading branch information
recursivetree committed Nov 3, 2023
1 parent e59e95e commit 6ba895f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 32 deletions.
22 changes: 21 additions & 1 deletion src/Exceptions/InvalidFilterException.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
<?php

/*
* This file is part of SeAT
*
* Copyright (C) 2015 to present Leon Jacobs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

namespace Seat\Web\Exceptions;

class InvalidFilterException extends \Exception
{

}
}
43 changes: 25 additions & 18 deletions src/Models/Filterable.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,41 +36,46 @@ trait Filterable
{
/**
* The filters to use.
*
* @return \stdClass
*/
abstract public function getFilters(): stdClass;

/**
* Check if an entity is eligible
* @param Model $member The entity to check
* Check if an entity is eligible.
*
* @param Model $member The entity to check
* @return bool Whether the entity is eligible
*
* @throws InvalidFilterException If a invalid filter configuration is used
*/
final public function isEligible(Model $member): bool
{
// in case no filters exists, bypass check and return not eligible
if (!property_exists($this->getFilters(), 'and') && !property_exists($this->getFilters(), 'or'))
if (! property_exists($this->getFilters(), 'and') && ! property_exists($this->getFilters(), 'or'))
throw new InvalidFilterException('root filter configuration is not a rule group');

$query = new QueryGroupBuilder($member->newQuery(), true);

// make sure we only allow results of the entity we are checking count
$query->where(function (Builder $inner_query) use ($member) {
$inner_query->where($member->getKeyName(),$member->getKey());
$inner_query->where($member->getKeyName(), $member->getKey());
});

// wrap this in an inner query to ensure it is '(correct_entity_check) AND (rule1 AND/OR rule2)'
$query->where(function ($inner_query){
$query->where(function ($inner_query) {
$this->applyGroup($inner_query, $this->getFilters());
});

return $query->getUnderlyingQuery()->exists();
}

/**
* Applies a filter group to $query
* @param Builder $query the query to add the filter group to
* @param stdClass $group the filter group configuration
* Applies a filter group to $query.
*
* @param Builder $query the query to add the filter group to
* @param stdClass $group the filter group configuration
*
* @throws InvalidFilterException
*/
private function applyGroup(Builder $query, stdClass $group): void
Expand All @@ -81,7 +86,7 @@ private function applyGroup(Builder $query, stdClass $group): void

foreach ($rules as $rule){
// check if this is a nested group or not
if(property_exists($rule,'path')){
if(property_exists($rule, 'path')){
$this->applyRule($query_group, $rule);
} else {
// this is a nested group
Expand All @@ -93,30 +98,32 @@ private function applyGroup(Builder $query, stdClass $group): void
}

/**
* Applies a rule to a query group
* @param QueryGroupBuilder $query the query to add the rule to
* @param stdClass $rule the rule configuration
* Applies a rule to a query group.
*
* @param QueryGroupBuilder $query the query to add the rule to
* @param stdClass $rule the rule configuration
*
* @throws InvalidFilterException
*/
private function applyRule(QueryGroupBuilder $query, stdClass $rule): void {
// 'is' operator
if($rule->operator === '=' || $rule->operator === '<' || $rule->operator==='>'){
if($rule->operator === '=' || $rule->operator === '<' || $rule->operator === '>'){
// normal comparison operations need to relation to exist
$query->whereHas($rule->path, function (Builder $inner_query) use ($rule) {
$inner_query->where($rule->field,$rule->operator, $rule->criteria);
$inner_query->where($rule->field, $rule->operator, $rule->criteria);
});
} else if ($rule->operator === '<>' || $rule->operator === '!=') {
} elseif ($rule->operator === '<>' || $rule->operator === '!=') {
// not equal is special cased since a missing relation is the same as not equal
$query->whereDoesntHave($rule->path, function (Builder $inner_query) use ($rule) {
$inner_query->where($rule->field, $rule->criteria);
});
} else if($rule->operator === 'contains'){
} elseif($rule->operator === 'contains'){
// contains is maybe a misleading name, since it actually checks if json contains a value
$query->whereHas($rule->path, function (Builder $inner_query) use ($rule) {
$inner_query->whereJsonContains($rule->field,$rule->criteria);
$inner_query->whereJsonContains($rule->field, $rule->criteria);
});
} else {
throw new InvalidFilterException(sprintf('Unknown rule operator: \'%s\'',$rule->operator));
throw new InvalidFilterException(sprintf('Unknown rule operator: \'%s\'', $rule->operator));
}
}
}
56 changes: 43 additions & 13 deletions src/Models/QueryGroupBuilder.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
<?php

/*
* This file is part of SeAT
*
* Copyright (C) 2015 to present Leon Jacobs
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

namespace Seat\Web\Models;

use Closure;
use Illuminate\Database\Eloquent\Builder;

/**
* Helper to build query where clauses that are either connected by AND or by OR
* Helper to build query where clauses that are either connected by AND or by OR.
*/
class QueryGroupBuilder
{
Expand All @@ -20,10 +41,10 @@ class QueryGroupBuilder
protected Builder $query;

/**
* @param Builder $query The query builder to add the where clauses to
* @param bool $is_and_group Whether the where clauses should be linked by AND
* @param Builder $query The query builder to add the where clauses to
* @param bool $is_and_group Whether the where clauses should be linked by AND
*/
public function __construct(Builder $query, bool $is_and_group){
public function __construct(Builder $query, bool $is_and_group) {
$this->query = $query;
$this->is_and_group = $is_and_group;
}
Expand All @@ -44,9 +65,11 @@ public function getUnderlyingQuery(): Builder
}

/**
* Either adds a 'where' or 'orWhere' to the query, depending on if it is an AND linked group or not
* @param Closure $callback a callback to add constraints
* Either adds a 'where' or 'orWhere' to the query, depending on if it is an AND linked group or not.
*
* @param Closure $callback a callback to add constraints
* @return $this
*
* @see Builder::where
* @see Builder::orWhere
*/
Expand All @@ -56,14 +79,17 @@ public function where(Closure $callback): QueryGroupBuilder {
} else {
$this->query->orWhere($callback);
}

return $this;
}

/**
* Either adds a 'whereHas' or 'orWhereHas' to the query, depending on if it is an AND linked group or not
* @param string $relation the relation to check for existence
* @param Closure $callback a callback to add more constraints
* Either adds a 'whereHas' or 'orWhereHas' to the query, depending on if it is an AND linked group or not.
*
* @param string $relation the relation to check for existence
* @param Closure $callback a callback to add more constraints
* @return $this
*
* @see Builder::whereHas
* @see Builder::orWhereHas
*/
Expand All @@ -73,14 +99,17 @@ public function whereHas(string $relation, Closure $callback): QueryGroupBuilder
} else {
$this->query->orWhereHas($relation, $callback);
}

return $this;
}

/**
* Either adds a 'whereDoesntHave' or 'orWhereDoesntHave' to the query, depending on if it is an AND linked group or not
* @param string $relation the relation to check for absence
* @param Closure $callback a callback to add more constraints
* Either adds a 'whereDoesntHave' or 'orWhereDoesntHave' to the query, depending on if it is an AND linked group or not.
*
* @param string $relation the relation to check for absence
* @param Closure $callback a callback to add more constraints
* @return $this
*
* @see Builder::whereDoesntHave
* @see Builder::orWhereDoesntHave
*/
Expand All @@ -90,6 +119,7 @@ public function whereDoesntHave(string $relation, Closure $callback): QueryGroup
} else {
$this->query->orWhereDoesntHave($relation, $callback);
}

return $this;
}
}
}

0 comments on commit 6ba895f

Please sign in to comment.