From 59aad1c18035e12b3dc61c7ff14d2258d15d1f59 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Sat, 12 Dec 2020 10:44:27 +0100 Subject: [PATCH] Added REGEXP operator for API query filter (closes #1174) --- changelog/60_UNRELEASED_2020-xx-xx.md | 4 +++- controllers/BaseApiController.php | 7 +++++-- grocy.openapi.json | 2 +- services/DatabaseService.php | 8 ++++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/changelog/60_UNRELEASED_2020-xx-xx.md b/changelog/60_UNRELEASED_2020-xx-xx.md index 5335f544..509af72b 100644 --- a/changelog/60_UNRELEASED_2020-xx-xx.md +++ b/changelog/60_UNRELEASED_2020-xx-xx.md @@ -199,10 +199,12 @@ - `=` equal - `!=` not equal - `~` LIKE + - `!~` not LIKE - `<` less - `>` greater - - `>=` greater or equal - `<=` less or equal + - `>=` greater or equal + - `§` regular expression - `` is the value to search for - New endpoint `/stock/shoppinglist/add-overdue-products` to add all currently in-stock but overdue products to a shopping list (thanks @m-byte) - New endpoint `/stock/shoppinglist/add-expired-products` to add all currently in-stock but expired products to a shopping list diff --git a/controllers/BaseApiController.php b/controllers/BaseApiController.php index e63e8697..cd73e106 100644 --- a/controllers/BaseApiController.php +++ b/controllers/BaseApiController.php @@ -9,8 +9,8 @@ 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.]+'; + const PATTERN_OPERATOR = '!?(=|~|<|>|(>=)|(<=)|(§))'; + const PATTERN_VALUE = '[A-Za-z_0-9.$#^|]+'; public function __construct(\DI\Container $container) { @@ -123,6 +123,9 @@ class BaseApiController extends BaseController case '<=': $data = $data->where($matches['field'] . ' <= ?', $matches['value']); break; + case '§': + $data = $data->where($matches['field'] . ' REGEXP ?', $matches['value']); + break; } } diff --git a/grocy.openapi.json b/grocy.openapi.json index 672d9fb5..e73cdb71 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -5093,7 +5093,7 @@ "in": "query", "name": "query[]", "required": false, - "description": "An array of filter conditions, each of them is a string in the form of `` where
`` is a valid field name
`` is a comparison operator, one of
  `=` equal
  `!=` not equal
  `~` LIKE
  `<` less
  `>` greater
  `<=` less or equal
  `>=` (greater or equal
`` is the value to search for", + "description": "An array of filter conditions, each of them is a string in the form of `` where
`` is a valid field name
`` is a comparison operator, one of
  `=` equal
  `!=` not equal
  `~` LIKE
  `!~` not LIKE
  `<` less
  `>` greater
  `<=` less or equal
  `>=` greater or equal
  `§` regular expression
`` is the value to search for", "schema": { "type": "array", "items": { diff --git a/services/DatabaseService.php b/services/DatabaseService.php index 040b428c..d1080b04 100644 --- a/services/DatabaseService.php +++ b/services/DatabaseService.php @@ -5,9 +5,7 @@ namespace Grocy\Services; class DatabaseService { private static $DbConnection = null; - private static $DbConnectionRaw = null; - private static $instance = null; /** @@ -67,6 +65,12 @@ class DatabaseService { $pdo = new \PDO('sqlite:' . $this->GetDbFilePath()); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + + $pdo->sqliteCreateFunction('regexp', function ($pattern, $value) { + mb_regex_encoding('UTF-8'); + return (false !== mb_ereg($pattern, $value)) ? 1 : 0; + }); + self::$DbConnectionRaw = $pdo; }