mirror of
https://github.com/grocy/grocy.git
synced 2025-10-14 17:24:07 +00:00
Filtering of API-Results (#985)
* Add FilteredApiResponse * Use FilteredApiResponse for Generic-Entity-Search * Use FilteredApiResponse for Recipe-Fullfillment * Use FilteredApiResponse for GetUsers * Use FilteredApiResponse for current Tasks * Use FilteredApiResponse for ProductStockEntries & ProductStockLocations * Use FilteredApiResponse for current chores * Use FilteredApiResponse for batteries-current * Fix missing highlighting of "< X days" * Keep to use existing views Co-authored-by: Bernd Bestel <bernd@berrnd.de>
This commit is contained in:
committed by
GitHub
parent
60f3d900e8
commit
32a4f81f62
@@ -2,10 +2,16 @@
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use LessQL\Result;
|
||||
|
||||
class BaseApiController extends BaseController
|
||||
{
|
||||
protected $OpenApiSpec = null;
|
||||
|
||||
const PATTERN_FIELD = '[A-Za-z_][A-Za-z0-9_]+';
|
||||
const PATTERN_OPERATOR = '!?(=|~|<|>|(>=)|(<=))';
|
||||
const PATTERN_VALUE = '[A-Za-z_0-9.]+';
|
||||
|
||||
public function __construct(\DI\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
@@ -29,6 +35,68 @@ class BaseApiController extends BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
public function FilteredApiResponse(\Psr\Http\Message\ResponseInterface $response, Result $data, array $query)
|
||||
{
|
||||
$data = $this->queryData($data, $query);
|
||||
return $this->ApiResponse($response, $data);
|
||||
}
|
||||
|
||||
protected function queryData(Result $data, array $query)
|
||||
{
|
||||
if (isset($query['query']))
|
||||
$data = $this->filter($data, $query['query']);
|
||||
if (isset($query['limit']))
|
||||
$data = $data->limit(intval($query['limit']), intval($query['offset'] ?? 0));
|
||||
if (isset($query['order']))
|
||||
$data = $data->orderBy($query['order']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function filter(Result $data, array $query): Result
|
||||
{
|
||||
foreach ($query as $q) {
|
||||
$matches = array();
|
||||
preg_match('/(?P<field>' . self::PATTERN_FIELD . ')'
|
||||
. '(?P<op>' . self::PATTERN_OPERATOR . ')'
|
||||
. '(?P<value>' . self::PATTERN_VALUE . ')/',
|
||||
$q, $matches
|
||||
);
|
||||
error_log(var_export($matches, true));
|
||||
switch ($matches['op']) {
|
||||
case '=':
|
||||
$data = $data->where($matches['field'], $matches['value']);
|
||||
break;
|
||||
case '!=':
|
||||
$data = $data->whereNot($matches['field'], $matches['value']);
|
||||
break;
|
||||
case '~':
|
||||
$data = $data->where($matches['field'] . ' LIKE ?', '%' . $matches['value'] . '%');
|
||||
break;
|
||||
case '!~':
|
||||
$data = $data->where($matches['field'] . ' NOT LIKE ?', '%' . $matches['value'] . '%');
|
||||
break;
|
||||
case '!>=':
|
||||
case '<':
|
||||
$data = $data->where($matches['field'] . ' < ?', $matches['value']);
|
||||
break;
|
||||
case '!<=':
|
||||
case '>':
|
||||
$data = $data->where($matches['field'] . ' > ?', $matches['value']);
|
||||
break;
|
||||
case '!<':
|
||||
case '>=':
|
||||
$data = $data->where($matches['field'] . ' >= ?', $matches['value']);
|
||||
break;
|
||||
case '!>':
|
||||
case '<=':
|
||||
$data = $data->where($matches['field'] . ' <= ?', $matches['value']);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getOpenApispec()
|
||||
{
|
||||
if ($this->OpenApiSpec == null)
|
||||
|
@@ -21,7 +21,7 @@ class BatteriesApiController extends BaseApiController
|
||||
|
||||
public function Current(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getBatteriesService()->GetCurrent());
|
||||
return $this->FilteredApiResponse($response, $this->getBatteriesService()->GetCurrent(), $request->getQueryParams());
|
||||
}
|
||||
|
||||
public function TrackChargeCycle(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
|
@@ -58,7 +58,7 @@ class ChoresApiController extends BaseApiController
|
||||
|
||||
public function Current(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getChoresService()->GetCurrent());
|
||||
return $this->FilteredApiResponse($response, $this->getChoresService()->GetCurrent(), $request->getQueryParams());
|
||||
}
|
||||
|
||||
public function TrackChoreExecution(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
|
@@ -3,6 +3,7 @@
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Controllers\Users\User;
|
||||
use Slim\Exception\HttpBadRequestException;
|
||||
|
||||
class GenericEntityApiController extends BaseApiController
|
||||
{
|
||||
@@ -178,12 +179,13 @@ class GenericEntityApiController extends BaseApiController
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getDatabase()->{$args['entity']}
|
||||
()->where('name LIKE ?', '%' . $args['searchString'] . '%'));
|
||||
return $this->FilteredApiResponse($response, $this->getDatabase()->{$args['entity']}
|
||||
()->where('name LIKE ?', '%' . $args['searchString'] . '%'), $request->getQueryParams());
|
||||
}
|
||||
catch (\PDOException $ex)
|
||||
{
|
||||
return $this->GenericErrorResponse($response, 'The given entity has no field "name"');
|
||||
throw new HttpBadRequestException($request, $ex->getMessage(), $ex);
|
||||
//return $this->GenericErrorResponse($response, 'The given entity has no field "name"', $ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@ class RecipesApiController extends BaseApiController
|
||||
{
|
||||
if (!isset($args['recipeId']))
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getRecipesService()->GetRecipesResolved());
|
||||
return $this->FilteredApiResponse($response, $this->getRecipesService()->GetRecipesResolved(), $request->getQueryParams());
|
||||
}
|
||||
|
||||
$recipeResolved = FindObjectInArrayByPropertyValue($this->getRecipesService()->GetRecipesResolved(), 'recipe_id', $args['recipeId']);
|
||||
|
@@ -552,12 +552,12 @@ class StockApiController extends BaseApiController
|
||||
$allowSubproductSubstitution = true;
|
||||
}
|
||||
|
||||
return $this->ApiResponse($response, $this->getStockService()->GetProductStockEntries($args['productId'], false, $allowSubproductSubstitution));
|
||||
return $this->FilteredApiResponse($response, $this->getStockService()->GetProductStockEntries($args['productId'], false, $allowSubproductSubstitution, false), $request->getQueryParams());
|
||||
}
|
||||
|
||||
public function ProductStockLocations(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getStockService()->GetProductStockLocations($args['productId']));
|
||||
return $this->FilteredApiResponse($response, $this->getStockService()->GetProductStockLocations($args['productId']), $request->getQueryParams());
|
||||
}
|
||||
|
||||
public function RemoveProductFromShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
|
@@ -8,7 +8,7 @@ class TasksApiController extends BaseApiController
|
||||
{
|
||||
public function Current(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getTasksService()->GetCurrent());
|
||||
return $this->FilteredApiResponse($response, $this->getTasksService()->GetCurrent(), $request->getQueryParams());
|
||||
}
|
||||
|
||||
public function MarkTaskAsCompleted(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
|
||||
|
@@ -123,7 +123,7 @@ class UsersApiController extends BaseApiController
|
||||
User::checkPermission($request, User::PERMISSION_USERS_READ);
|
||||
try
|
||||
{
|
||||
return $this->ApiResponse($response, $this->getUsersService()->GetUsersAsDto());
|
||||
return $this->FilteredApiResponse($response, $this->getUsersService()->GetUsersAsDto(), $request->getQueryParams());
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
|
Reference in New Issue
Block a user