Added FlexObjectInterface::search() and FlexCollectionInterface::search() methods

This commit is contained in:
Matias Griese
2019-03-06 12:34:00 +02:00
parent 85d5b6e889
commit c7a4e8e4bb
7 changed files with 133 additions and 31 deletions

View File

@@ -5,6 +5,7 @@
* Grav 1.6: Renamed `$grav['users']` service to `$grav['accounts']`
* Added `Flex::getObjects()` and `Flex::getMixedCollection()` methods for co-mingled collections
* Added support to use single Flex key parameter in `Flex::getObject()` method
* Added `FlexObjectInterface::search()` and `FlexCollectionInterface::search()` methods
1. [](#improved)
* Renamed `Grav\Framework\File\Formatter\FormatterInterface` to `Grav\Framework\File\Interfaces\FileFormatterInterface`
* Improved `File::save()` to use a temporary file if file isn't locked

View File

@@ -61,7 +61,16 @@ class AccountsServiceProvider implements ServiceProviderInterface
'object' => User::class, // Use User class for backwards compatibility.
'collection' => FlexUser\UserCollection::class,
'index' => FlexUser\UserIndex::class,
'storage' => $this->getFlexStorage($config->get('system.accounts.storage', 'file'))
'storage' => $this->getFlexStorage($config->get('system.accounts.storage', 'file')),
'search' => [
'options' => [
'contains' => true
],
'fields' => [
'key',
'email'
]
]
]
] + ($config->get('plugins.flex-objects.object') ?: []);

View File

@@ -98,34 +98,4 @@ class UserCollection extends FlexCollection implements UserCollectionInterface
return $exists;
}
/**
* @param string $text
* @param bool $case_sensitive
* @param bool $strict
* @return UserCollection
*/
public function search(string $text, bool $case_sensitive = false, bool $strict = false) : UserCollection
{
$text = trim($text);
if (!$text) {
return $this;
}
$matching = [];
/**
* @var string $key
* @var User $object
*/
foreach ($this as $key => $object) {
if ($strict && Utils::startsWith($object->getProperty('email'), $text, $case_sensitive)) {
$matching[$key] = $object;
} elseif (!$strict && Utils::contains($object->getProperty('email'), $text, $case_sensitive)) {
$matching[$key] = $object;
}
}
return $this->createFrom($matching);
}
}

View File

@@ -53,6 +53,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
'render' => false,
'isAuthorized' => 'session',
'search' => true,
'sort' => true,
];
}
@@ -124,6 +125,27 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
return $type . $this->_flexDirectory->getType();
}
/**
* @param string $search
* @param string|string[]|null $properties
* @param array|null $options
* @return FlexCollectionInterface
*/
public function search(string $search, $properties = null, array $options = null) // : FlexCollectionInterface
{
$matching = $this->call('search', [$search, $properties, $options]);
$matching = array_filter($matching);
if ($matching) {
uksort($matching, function ($a, $b) {
return -($a <=> $b);
});
}
return $this->select(array_keys($matching));
}
public function sort(array $order) // : FlexCollection
{
$criteria = Criteria::create()->orderBy($order);

View File

@@ -108,6 +108,86 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
$this->objectConstruct($elements, $key);
}
/**
* @param string $search
* @param string|string[]|null $properties
* @param array|null $options
* @return float
*/
public function search(string $search, $properties = null, array $options = null): float
{
$options = $options ?? $this->getFlexDirectory()->getConfig('data.search.options', []);
$properties = $properties ?? $this->getFlexDirectory()->getConfig('data.search.fields', []);
$weight = 0;
foreach ((array)$properties as $property) {
$weight += $this->searchNestedProperty($property, $search, $options);
}
return $weight > 0 ? min($weight, 1) : 0;
}
/**
* @param string $property
* @param string $search
* @param array|null $options
* @return float
*/
public function searchProperty(string $property, string $search, array $options = null): float
{
$options = $options ?? $this->getFlexDirectory()->getConfig('data.search.options', []);
$value = $this->getProperty($property);
return $this->searchValue($property, $value, $search, $options);
}
/**
* @param string $property
* @param string $search
* @param array|null $options
* @return float
*/
public function searchNestedProperty(string $property, string $search, array $options = null): float
{
$options = $options ?? $this->getFlexDirectory()->getConfig('data.search.options', []);
$value = $this->getNestedProperty($property);
return $this->searchValue($property, $value, $search, $options);
}
/**
* @param string $name
* @param $value
* @param string $search
* @param array|null $options
* @return float
*/
protected function searchValue(string $name, $value, string $search, array $options = null): float
{
$search = trim($search);
if ($search === '') {
return 0;
}
if (!\is_string($value) || $value === '') {
return 0;
}
$tested = false;
if (($tested |= !empty($options['starts_with'])) && Utils::startsWith($value, $search, $options['case_sensitive'] ?? false)) {
return (float)$options['starts_with'];
}
if (($tested |= !empty($options['ends_with'])) && Utils::endsWith($value, $search, $options['case_sensitive'] ?? false)) {
return (float)$options['ends_with'];
}
if ((!$tested || !empty($options['contains'])) && Utils::contains($value, $search, $options['case_sensitive'] ?? false)) {
return (float)$options['contains'];
}
return 0;
}
/**
* @param array $data
* @param array $files

View File

@@ -37,6 +37,14 @@ interface FlexCollectionInterface extends ObjectCollectionInterface, NestedObjec
*/
public function __construct(array $elements, FlexDirectory $type);
/**
* @param string $search
* @param string|string[]|null $properties
* @param array|null $options
* @return FlexCollectionInterface
*/
public function search(string $search, $properties = null, array $options = null); // : FlexCollection
/**
* @return FlexDirectory
*/

View File

@@ -31,6 +31,18 @@ interface FlexObjectInterface extends NestedObjectInterface, \ArrayAccess
*/
public function __construct(array $elements, $key, FlexDirectory $type);
/**
* Search object, returns weight between 0 and 1.
*
* Note: If you override this function, make sure you return value in range 0...1!
*
* @param string $search
* @param string|string[]|null $properties
* @param array|null $options
* @return float Weight between 0...1
*/
public function search(string $search, $properties = null, array $options = null): float;
/**
* Returns the directory where the object belongs into.
*