Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extend search conditions with with a few operators #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,57 @@ object(RapidWeb\Search\SearchResults)#731 (5) {
float(0.33661985397339)
}
```
### Using operators in conditions

Basic extra search conditions

Operators that can be used: **==**, **!=**, **<**, **>**, **<=**, **>=**, **in**, **!in**, **email**, **!email**
```php
// Operators can be used when filter Enabled
->enableFilter()
```
Unique Key/FieldName can only be used ones!
```php
// Row with id = 50 will be selected, because it is the last (id) condition
->enableFilter()
->setConditions([
'product_live' => 1,
'id:==' => 16,
'id:==' => 50
]);
````
Some condition examples
```php
// count larger than 500
// created (timestamp) smaller or equal
->enableFilter()
->setConditions([
'product_live' => 1,
'count:>' => 500,
'created:<=' => 1581828542
]);

// parent_id 17, 16 or 19
->enableFilter()
->setConditions([
'product_live' => 1,
'parent_id:in' => '17,16,9'
]);

// parent_id not 35, 45 or 89
->enableFilter()
->setConditions([
'product_live' => 1,
'id:!in' => '34,45,89'
]);

// Select invalid emailaddresses
->enableFilter()
->setConditions([
'emailaddress:!email' => ''
]);
````


### Caching Source Data

Expand Down
36 changes: 30 additions & 6 deletions src/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

class Search {

use SearchExtendConditions;

private $useFilter = false;
private $pdo;
private $table;
private $primaryKey;
Expand Down Expand Up @@ -45,6 +48,11 @@ public function setConditions(array $conditions = []) {
return $this;
}

public function enableFilter() {
$this->useFilter = true;
return $this;
}

public function setCache(CacheItemPoolInterface $cacheItemPool, $cacheExpiresAfter = 60*60*24) {
$this->cacheItemPool = $cacheItemPool;
$this->cacheExpiresAfter = $cacheExpiresAfter;
Expand All @@ -68,9 +76,16 @@ private function sanityCheck() {
$this->fields[] = $this->primaryKey;
}

foreach($this->conditions as $fieldName => $value) {
if (!in_array($fieldName, $this->fields)) {
$this->fields[] = $fieldName;
if($this->useFilter && method_exists($this, 'setFields')) {
// Call method from SearchFilter Trait
$this->setFields();
}
else {
// Handling without SearchFilter
foreach($this->conditions as $fieldName => $value) {
if (!in_array($fieldName, $this->fields)) {
$this->fields[] = $fieldName;
}
}
}
}
Expand Down Expand Up @@ -120,12 +135,21 @@ public function query($term, $limit = PHP_INT_MAX) {

$migrator->setDataRowManipulator(function($dataRow) use ($terms, &$results) {

foreach($this->conditions as $fieldName => $value) {
$dataItem = $dataRow->getDataItemByFieldName($fieldName);
if ($dataItem->value != $value) {
if($this->useFilter && method_exists($this, 'setDataItems')) {
// Call method from SearchFilter Trait
if (!$this->setDataItems($dataRow)) {
return;
}
}
else {
// Handling without SearchFilter
foreach($this->conditions as $fieldName => $value) {
$dataItem = $dataRow->getDataItemByFieldName($fieldName);
if ($dataItem->value != $value) {
return;
}
}
}

$dataItems = $dataRow->getDataItems();

Expand Down
118 changes: 118 additions & 0 deletions src/SearchExtendConditions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

namespace RapidWeb\Search;

trait SearchExtendConditions
{
/**
* Add to sanityCheck, to split operators from fieldname
* @param $id
*/
public function setFields() {
foreach($this->conditions as $fieldName => $value) {
// Undo fieldname from operators
$fieldName = $this->splitOperator($fieldName);
// No doubles
if (!in_array($fieldName, $this->fields)) {
$this->fields[] = $fieldName;
}
}
}

/**
* Walk true conditions for each dataRow
* @param $dataRow
* @return bool
*/
public function setDataItems(&$dataRow):bool {
$methods = get_class_methods($this);
$methods = array_filter($methods, function($method) {
return preg_match("/^__.*Filter$/",$method);
});

$result = true;
foreach($this->conditions as $fieldName => $value) {
// Split fieldname and operator
list($fieldName, $operator) = $this->splitOperator($fieldName, true);
$dataItem = $dataRow->getDataItemByFieldName($fieldName);

foreach ($methods as $filterMethod) {
if(method_exists($this, $filterMethod)) {
$result = $this->$filterMethod($dataItem, $operator, $value) ? $result : false;
}
}
}
return $result;
}

/**
* When there is an operator in the Fieldname, split
* return only fieldname or both
*
* @param string $fieldName
* @param bool $return
* @return array|string
*/
private function splitOperator(string $fieldName, bool $return = false): array | string {
$operator = "==";
if(preg_match("/:/",$fieldName)) {
// split fieldname and operator
list($fieldName, $operator) = preg_split("/:/", $fieldName);
}

if(!$return) return $fieldName;
return [$fieldName,$operator];
}

/**
* match emailadres
* @param \RapidWeb\uxdm\Objects\DataItem $dataItem
* @param string $operator
* @param mixed $value
* @return bool
*/
private function __emailFilter(\RapidWeb\uxdm\Objects\DataItem $dataItem, string $operator, mixed $value):bool {
$result = true;
if(preg_match("/email/", $operator)) {
if ($operator == '!email' && filter_var($value, FILTER_VALIDATE_EMAIL)) {
$result = false;
} elseif ($operator == 'email' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
$result = false;
}
}
return $result;
}

/**
* in or not in list
* @param \RapidWeb\uxdm\Objects\DataItem $dataItem
* @param string $operator
* @param mixed $value
* @return bool
*/
private function __inFilter(\RapidWeb\uxdm\Objects\DataItem $dataItem, string $operator, mixed $value):bool {
$result = true;
if(preg_match("/in/", $operator)) {
if ($operator == '!in' && in_array($dataItem->value, explode(",", $value))) {
$result = false;
} elseif ($operator == 'in' && !in_array($dataItem->value, explode(",", $value))) {
$result = false;
}
}
return $result;
}

/**
* value compare
* @param \RapidWeb\uxdm\Objects\DataItem $dataItem
* @param string $operator
* @param mixed $value
* @return bool
*/
private function __comparisonFilter(\RapidWeb\uxdm\Objects\DataItem $dataItem, string $operator, mixed $value):bool {
if(preg_match("/(<|>|==|\!=|<=|>=)/", $operator)) {
return eval('return (' . $dataItem->value . $operator . $value . ');');
}
return true;
}
}