Add new collection and object classes

This commit is contained in:
Matias Griese
2017-02-10 20:53:35 +02:00
parent f8822de6fe
commit 76c870ce04
15 changed files with 1341 additions and 3 deletions

View File

@@ -0,0 +1,59 @@
<?php
namespace Grav\Common\Collection;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccess;
use RocketTheme\Toolbox\ArrayTraits\Countable;
class AbstractCollection implements CollectionInterface
{
use ArrayAccess, Countable;
/**
* @var array
*/
protected $items = [];
/**
* @param array $variables
* @return static
*/
public static function __set_state(array $variables)
{
$instance = new static();
$instance->items = $variables['items'];
return $instance;
}
/**
* Add item to the list.
*
* @param mixed $item
* @param string $key
* @return $this
*/
public function add($item, $key = null)
{
$this->offsetSet($key, $item);
return $this;
}
/**
* Remove item from the list.
*
* @param $key
*/
public function remove($key)
{
$this->offsetUnset($key);
}
/**
* @return \ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->items);
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Grav\Common\Object;
use Grav\Common\Collection\CollectionInterface;
interface ObjectCollectionInterface extends CollectionInterface
{
/**
*
* Create a clone from this collection.
*
* @return static
*/
public function getClone();
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Grav\Common\Collection;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccess;
trait CloneCollectionTrait
{
use ArrayAccess;
public function __clone()
{
foreach ($this as $key => $value) {
if (is_object($value)) {
$this->offsetSet($key, clone $value);
}
}
}
/**
*
* Create a clone from this collection.
*
* @return static
*/
public function getClone()
{
return clone $this;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Grav\Common\Collection;
interface CollectionInterface extends \IteratorAggregate, \ArrayAccess, \Countable
{
/**
* Add item to the list.
*
* @param mixed $item
* @param string $key
* @return $this
*/
public function add($item, $key = null);
/**
* Remove item from the list.
*
* @param $key
*/
public function remove($key);
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Grav\Common\Collection;
interface ObjectCollectionInterface extends CollectionInterface
{
/**
* @param string $property Object property to be fetched.
* @return array Values of the property.
*/
public function get($property);
/**
* @param string $property Object property to be updated.
* @param string $value New value.
* @return $this
*/
public function set($property, $value);
/**
* @param string $name Method name.
* @param array $arguments List of arguments passed to the function.
* @return array Return values.
*/
public function __call($name, array $arguments);
}

View File

@@ -0,0 +1,127 @@
<?php
namespace Grav\Common\Collection;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccess;
trait ObjectCollectionTrait
{
use ArrayAccess;
/**
* @var string
*/
protected $keyProperty = null;
/**
* Add item to the list.
*
* @param object $object
* @param string $key
* @return $this
*/
public function add($object, $key = null)
{
$objKey = $key ?: $this->getObjectKey($object);
$this->offsetSet(is_null($objKey) ? $key : $objKey, $object);
return $this;
}
/**
* Remove item from the list.
*
* @param string|object $key
* @return $this
*/
public function remove($key)
{
if (is_object($key)) {
$key = $this->getObjectKey($key);
if (is_null($key)) {
return $this;
}
}
$this->offsetUnset($key);
return $this;
}
/**
* @param string $property Object property to be fetched.
* @return array Values of the property.
*/
public function get($property)
{
$list = [];
foreach ($this as $id => $object) {
$key = $this->getObjectKey($object);
$list[is_null($key) ? $id : $key] = $this->getObjectValue($object, $property);
}
return $list;
}
/**
* @param string $property Object property to be updated.
* @param string $value New value.
* @return $this
*/
public function set($property, $value)
{
foreach ($this as $object) {
$object->{$property} = $value;
}
return $this;
}
/**
* @param string $name Method name.
* @param array $arguments List of arguments passed to the function.
* @return array Return values.
*/
public function __call($name, array $arguments)
{
$list = [];
foreach ($this as $id => $object) {
$key = $this->getObjectKey($object);
$list[is_null($key) ? $id : $key] = $this->getObjectCallResult($object, $name, $arguments);
}
return $list;
}
/**
* @param object $object
* @return string|null
*/
protected function getObjectKey($object)
{
$keyProperty = $this->keyProperty;
return $keyProperty && isset($object->{$keyProperty}) ? (string) $object->{$keyProperty} : null;
}
/**
* @param object $object
* @param string $property
* @return mixed
*/
protected function getObjectValue($object, $property)
{
return isset($object->{$property}) ? $object->{$property} : null;
}
/**
* @param object $object
* @param string $name;
* @param array $arguments
* @return mixed
*/
protected function getObjectCallResult($object, $name, $arguments)
{
return method_exists($object, $name) ? call_user_func_array([$object, $name], $arguments) : null;
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace Grav\Common\Collection;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccess;
trait SortingCollectionTrait
{
use ArrayAccess;
/**
* Reverse the order of the items.
*
* @return $this
*/
public function reverse()
{
$this->items = array_reverse($this->items);
return $this;
}
/**
* Shuffle items.
*
* @return $this
*/
public function shuffle()
{
$keys = array_keys($this->items);
shuffle($keys);
$this->items = array_replace(array_flip($keys), $this->items);
return $this;
}
/**
* Sort collection by values using a user-defined comparison function.
*
* @param callable $callback
* @return $this
*/
public function sort(callable $callback)
{
uasort($this->items, $callback);
return $this;
}
/**
* Sort collection by keys.
*
* @return $this
*/
public function ksort($sort_flags = SORT_REGULAR)
{
ksort($this->items, $sort_flags);
return $this;
}
/**
* Sort collection by keys in reverse order.
*
* @return $this
*/
public function krsort($sort_flags = SORT_REGULAR)
{
krsort($this->items, $sort_flags);
return $this;
}
/**
* Sort collection by keys using a user-defined comparison function.
*
* @return $this
*/
public function uksort(callable $key_compare_func)
{
uksort($this->items, $key_compare_func);
return $this;
}}

View File

@@ -332,7 +332,8 @@ abstract class Folder
*/
public static function move($source, $target)
{
if (!is_dir($source)) {
if (!file_exists($target) || !is_dir($source)) {
// Rename fails if source folder does not exist.
throw new \RuntimeException('Cannot move non-existing folder.');
}
@@ -341,11 +342,24 @@ abstract class Folder
return;
}
if (file_exists($target)) {
// Rename fails if target folder exists.
throw new \RuntimeException('Cannot move files to existing folder/file.');
}
// Make sure that path to the target exists before moving.
self::create(dirname($target));
$success = @rename($source, $target);
if (!$success) {
// Silence warnings (chmod failed etc).
@rename($source, $target);
// Rename function can fail while still succeeding, so let's check if the folder exists.
if (!file_exists($target) || !is_dir($target)) {
// In some rare cases rename() creates file, not a folder. Get rid of it.
if (file_exists($target)) {
@unlink($target);
}
// Rename doesn't support moving folders across filesystems. Use copy instead.
self::copy($source, $target);
self::delete($source);
}
@@ -353,6 +367,7 @@ abstract class Folder
// Make sure that the change will be detected when caching.
@touch(dirname($source));
@touch(dirname($target));
@touch($target);
}
/**

View File

@@ -0,0 +1,374 @@
<?php
namespace Grav\Common\Object;
use Grav\Common\Object\Storage\StorageInterface;
use RocketTheme\Toolbox\ArrayTraits\ArrayAccessWithGetters;
use RocketTheme\Toolbox\ArrayTraits\Export;
/**
* Abstract base class for stored objects.
*
* @property string $id
*/
abstract class AbstractObject implements ObjectInterface
{
use ArrayAccessWithGetters, Export;
/**
* If you don't have global instance ids, override this in extending class.
* @var array
*/
static protected $instances = [];
/**
* If you don't have global storage, override this in extending class.
* @var StorageInterface
*/
static protected $storage;
/**
* Default properties for the object.
* @var array
*/
static protected $defaults = ['id' => null];
/**
* @var string
*/
static protected $collectionClass = 'Grav\\Common\\Object\\ObjectCollection';
/**
* Properties of the object.
* @var array
*/
protected $items;
/**
* Does object exist in storage?
* @var boolean
*/
protected $exists = false;
/**
* Readonly object.
* @var bool
*/
protected $readonly = false;
/**
* @var bool
*/
protected $initialized = false;
/**
* Returns the global instance to the object.
*
* Note that using array of fields will always make a query, but it's very useful feature if you want to search one
* item by using arbitrary set of matching fields. If there are more than one matching object, first one gets returned.
*
* @param string|array $keys An optional primary key value to load the object by, or an array of fields to match.
* @param boolean $reload Force object to reload.
*
* @return Object
*/
static public function instance($keys = null, $reload = false)
{
// If we are creating or loading a new item or we load instance by alternative keys, we need to create a new object.
if (!$keys || is_array($keys) || (is_scalar($keys) && !isset(static::$instances[$keys]))) {
$c = get_called_class();
$instance = new $c($keys);
/** @var Object $instance */
if (!$instance->exists()) return $instance;
// Instance exists: make sure that we return the global instance.
$keys = $instance->id;
}
// Return global instance from the identifier.
$instance = static::$instances[$keys];
if ($reload) {
$instance->load();
}
return $instance;
}
/**
* @param array $ids List of primary Ids or null to return everything that has been loaded.
* @param bool $readonly
* @return ObjectCollection
*/
static public function instances(array $ids = null, $readonly = true)
{
$collectionClass = static::$collectionClass;
if (is_null($ids)) {
return new $collectionClass(static::$instances);
}
if (empty($ids)) {
return new $collectionClass([]);
}
$results = [];
$list = [];
foreach ($ids as $id) {
if (!isset(static::$instances[$id])) {
$list[] = $id;
}
}
if ($list) {
$c = get_called_class();
$storage = static::getStorage();
$list = $storage->loadList($list);
foreach ($list as $keys) {
/** @var static $instance */
$instance = new $c();
$instance->set($keys);
$instance->exists(true);
$instance->initialize();
$id = $instance->id;
if ($id && !isset(static::$instances[$id])) {
static::$instances[$id] = $instance;
}
}
}
foreach ($ids as $id) {
if (isset(static::$instances[$id])) {
$results[$id] = $readonly ? clone static::$instances[$id] : static::$instances[$id];
}
}
return new $collectionClass($results);
}
/**
* Removes all or selected instances from the object cache.
*
* @param null|string|array $ids An optional primary key or list of keys.
*/
static public function freeInstances($ids = null)
{
if ($ids === null) {
$ids = array_keys(static::$instances);
}
$ids = (array) $ids;
foreach ($ids as $id) {
unset(static::$instances[$id]);
}
}
/**
* Class constructor, overridden in descendant classes.
*
* @param string|array $identifier Identifier.
*/
public function __construct($identifier = null)
{
if ($identifier) {
$this->load($identifier);
}
}
/**
* Override this function if you need to initialize object right after creating it.
*
* Can be used for example if the fields need to be converted from json strings to array.
*
* @return bool True if initialization was done, false if object was already initialized.
*/
public function initialize()
{
$initialized = $this->initialized;
$this->initialized = true;
return !$initialized;
}
/**
* Convert instance to a read only object.
*
* @return $this
*/
public function readonly()
{
$this->readonly = true;
return $this;
}
/**
* Returns true if the object exists.
*
* @param boolean $exists Internal parameter to change state.
*
* @return boolean True if object exists.
*/
public function exists($exists = null)
{
$return = $this->exists;
if ($exists !== null) {
$this->exists = (bool) $exists;
}
return $return;
}
/**
* Method to load object from the storage.
*
* @param mixed $keys An optional primary key value to load the object by, or an array of fields to match. If not
* set the instance key value is used.
*
* @return boolean True on success, false if the object doesn't exist.
*/
public function load($keys = null)
{
if (is_scalar($keys)) {
$keys = ['id' => (string) $keys];
}
// Get storage.
$storage = $this->getStorage();
// Load the object based on the keys.
$this->items = $storage->load($keys);
$this->exists = !empty($this->items);
// Append the keys and defaults if they were not set by load().
$this->items += $keys + static::$defaults;
$this->initialize();
if ($this->id) {
if (!isset(static::$instances[$this->id])) {
static::$instances[$this->id] = $this;
}
}
return $this->exists;
}
/**
* Method to save the object to the storage.
*
* Before saving the object, this method checks if object can be safely saved.
*
* @return boolean True on success.
*/
public function save()
{
// Check the object.
if ($this->readonly || !$this->check() || !$this->onBeforeSave()) {
return false;
}
// Get storage.
$storage = $this->getStorage();
// Save the object.
$id = $storage->save($this);
if (!$id) {
return false;
}
// If item was created, load the object.
if (!$this->exists) {
$this->load($id);
}
$this->onAfterSave();
return true;
}
/**
* Method to delete the object from the database.
*
* @return boolean True on success.
*/
public function delete()
{
if ($this->readonly || !$this->exists || !$this->onBeforeDelete()) {
return false;
}
// Get storage.
$storage = $this->getStorage();
if (!$storage->delete($this)) {
return false;
}
$this->exists = false;
$this->onAfterDelete();
return true;
}
/**
* Method to perform sanity checks on the instance properties to ensure they are safe to store in the storage.
*
* Child classes should override this method to make sure the data they are storing in the storage is safe and as
* expected before saving the object.
*
* @return boolean True if the instance is sane and able to be stored in the storage.
*/
public function check()
{
return !empty($this->id);
}
// Internal functions
/**
* @param array $items
* @return $this
*/
protected function set(array $items)
{
$this->items = $items;
return $this;
}
/**
* @return boolean
*/
protected function onBeforeSave()
{
return true;
}
protected function onAfterSave()
{
}
/**
* @return boolean
*/
protected function onBeforeDelete()
{
return true;
}
protected function onAfterDelete()
{
}
/**
* @return StorageInterface
*/
static protected function getStorage()
{
return static::$storage;
}
}

View File

@@ -0,0 +1,279 @@
<?php
namespace Grav\Common\Object;
use Grav\Common\Object\Storage\StorageInterface;
abstract class AbstractObjectFinder implements ObjectFinderInterface
{
/**
* Storage associated with the model.
*
* @var StorageInterface
*/
protected $storage;
/**
* @var int
*/
protected $start = 0;
/**
* @var int
*/
protected $limit = 0;
/**
* @var bool
*/
protected $skip = false;
/**
* List of query rules.
*
* @var array
*/
protected $query = [];
/**
* Finder constructor.
*
* @param array $options Query options.
*/
public function __construct(array $options = [])
{
if (!$this->storage) {
throw new \DomainException('Storage missing from ' . get_class($this));
}
if ($options) {
$this->parse($options);
}
}
/**
* Parse query options.
*
* @param array $options
* @return $this
*/
public function parse(array $options)
{
foreach ($options as $func => $params) {
if (method_exists($this, $func)) {
call_user_func_array([$this, $func], (array) $params);
}
}
return $this;
}
/**
* Set start position for the query.
*
* @param int $start
*
* @return $this
*/
public function start($start = null)
{
if (!is_null($start)) {
if ((string)(int)$start === (string)$start && $start>=0) {
throw new \RuntimeException('$start needs to be zero or a positive integer');
}
$this->start = (int)$start;
}
return $this;
}
/**
* Set limit to the query.
*
* If this function isn't used, RokClub will use threads per page configuration setting.
*
* @param int $limit
*
* @return $this
*/
public function limit($limit = null)
{
if (!is_null($limit))
{
if ((string)(int)$limit === (string)$limit && $limit>=0) {
throw new \RuntimeException('$limit needs to be zero or a positive integer');
}
$this->limit = (int)$limit;
}
return $this;
}
/**
* Set order by field and direction.
*
* This function can be used more than once to chain order by.
*
* @param string $field
* @param int $direction
*
* @return $this
*/
public function order($field, $direction = 1)
{
if (!is_string($field)) {
throw new \RuntimeException('$field needs to be a string');
}
if ((string)(int)$direction !== (string)$direction || $direction <= -1 || $direction >= 1) {
throw new \RuntimeException('$direction needs to be 1 (ascending), 0 (undefined) or -1 (descending)');
}
if ($direction) {
$this->query[] = ['order', $field, (int)$direction];
}
return $this;
}
/**
* Filter by field.
*
* @param string $field Field name.
* @param string $operation Operation (>|>=|<|<=|==|!=|BETWEEN|NOT BETWEEN|IN|NOT IN)
* @param mixed $value Value.
*
* @return $this
*/
public function where($field, $operation, $value = null)
{
if (!is_string($field)) {
throw new \RuntimeException('$field needs to be a string');
}
$operation = strtoupper((string)$operation);
switch ($operation)
{
case '>':
case '>=':
case '<':
case '<=':
$this->checkOperator($value);
$this->query[] = ['where', $field, $operation, $value];
break;
case '==':
case '!=':
$this->checkEqOperator($value);
$this->query[] = ['where', $field, $operation, $value];
break;
case 'BETWEEN':
case 'NOT BETWEEN':
$this->checkBetweenOperator($value);
$this->query[] = ['where', $field, $operation, array_values($value)];
break;
case 'IN':
if (is_null($value) || (is_array($value) && empty($value))) {
// IN (nothing): optimized to empty collection.
$this->skip = true;
} else {
$this->checkInOperator($value);
$this->query[] = ['where', $field, $operation, array_values((array)$value)];
}
break;
case 'NOT IN':
if (is_null($value) || (is_array($value) && empty($value))) {
// NOT IN (nothing): optimized away.
} else {
$this->checkInOperator($value);
$this->query[] = ['where', $field, $operation, array_values((array)$value)];
}
break;
default:
throw new \RuntimeException('$operation needs to be one of: > , >= , < , <= , == , != , BETWEEN , NOT BETWEEN , IN , NOT IN');
}
return $this;
}
/**
* Get items.
*
* Derived classes should generally override this function to return correct objects.
*
* @param int $start
* @param int $limit
* @return array
*/
public function find($start = null, $limit = null)
{
if ($this->skip)
{
return array();
}
$query = $this->query;
$this->start($start)->limit($limit);
$this->prepare();
$results = (array) $this->storage->find($this->query);
$this->query = $query;
return $results;
}
/**
* Count items.
*
* @return int
*/
public function count()
{
$query = $this->query;
$this->prepare();
$count = (int) $this->storage->count($this->query);
$this->query = $query;
return $count;
}
/**
* Override to include common rules.
*
* @return void
*/
protected function prepare()
{
}
protected function checkOperator($value)
{
if (!is_scalar($value)) {
throw new \RuntimeException('$value needs to be a scalar');
}
}
protected function checkEqOperator($value)
{
if (!is_null($value) || !is_scalar($value)) {
throw new \RuntimeException('$value needs to be a scalar or null');
}
}
protected function checkBetweenOperator($value)
{
if (!is_array($value) || count($value) !== 2) {
throw new \RuntimeException('$value needs to be a list with two values in it');
}
}
protected function checkInOperator($value)
{
if (!is_scalar($value) || !is_array($value)) {
throw new \RuntimeException('$value needs to be a single value or list of values');
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Grav\Common\Object;
use Grav\Common\Collection\AbstractCollection;
use Grav\Common\Collection\ObjectCollectionInterface;
use Grav\Common\Collection\ObjectCollectionTrait;
class ObjectCollection extends AbstractCollection implements ObjectCollectionInterface
{
use ObjectCollectionTrait;
/**
* Collection constructor.
* @param array|AbstractObject[] $items
*/
public function __construct(array $items)
{
$this->items = $items;
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace Grav\Common\Object;
interface ObjectFinderInterface
{
/**
* Finder constructor.
*
* @param array $options Query options.
*/
public function __construct(array $options = []);
/**
* Parse query options.
*
* @param array $options
* @return $this
*/
public function parse(array $options);
/**
* Set start position for the query.
*
* @param int $start
*
* @return $this
*/
public function start($start = null);
/**
* Set limit to the query.
*
* If this function isn't used, RokClub will use threads per page configuration setting.
*
* @param int $limit
*
* @return $this
*/
public function limit($limit = null);
/**
* Set order by field and direction.
*
* This function can be used more than once to chain order by.
*
* @param string $field
* @param int $direction
*
* @return $this
*/
public function order($field, $direction = 1);
/**
* Filter by field.
*
* @param string $field Field name.
* @param string $operation Operation (>|>=|<|<=|==|!=|BETWEEN|NOT BETWEEN|IN|NOT IN)
* @param mixed $value Value.
*
* @return $this
*/
public function where($field, $operation, $value = null);
/**
* Get items.
*
* Derived classes should generally override this function to return correct objects.
*
* @param int $start
* @param int $limit
* @return array
*/
public function find($start = null, $limit = null);
/**
* Count items.
*
* @return int
*/
public function count();
}

View File

@@ -0,0 +1,100 @@
<?php
namespace Grav\Common\Object;
interface ObjectInterface extends \ArrayAccess
{
/**
* Returns the global instance to the object.
*
* Note that using array of fields will always make a query, but it's very useful feature if you want to search one
* item by using arbitrary set of matching fields. If there are more than one matching object, first one gets returned.
*
* @param int|array $keys An optional primary key value to load the object by, or an array of fields to match.
* @param boolean $reload Force object to reload.
*
* @return Object
*/
static public function instance($keys = null, $reload = false);
/**
* @param array $ids List of primary Ids or null to return everything that has been loaded.
* @param bool $readonly
* @return ObjectCollection
*/
static public function instances(array $ids = null, $readonly = true);
/**
* Removes all or selected instances from the object cache.
*
* @param null|int|array $ids An optional primary key or list of keys.
*/
static public function freeInstances($ids = null);
/**
* Class constructor, overridden in descendant classes.
*
* @param string|array $identifier Identifier.
*/
public function __construct($identifier = null);
/**
* Override this function if you need to initialize object right after creating it.
*
* Can be used for example if the fields need to be converted from json strings to array.
*
* @return bool True if initialization was done, false if object was already initialized.
*/
public function initialize();
/**
* Convert instance to a read only object.
*
* @return $this
*/
public function readonly();
/**
* Returns true if the object exists.
*
* @param boolean $exists Internal parameter to change state.
*
* @return boolean True if object exists.
*/
public function exists($exists = null);
/**
* Method to load object from the storage.
*
* @param mixed $keys An optional primary key value to load the object by, or an array of fields to match. If not
* set the instance key value is used.
*
* @return boolean True on success, false if the object doesn't exist.
*/
public function load($keys = null);
/**
* Method to save the object to the storage.
*
* Before saving the object, this method checks if object can be safely saved.
*
* @return boolean True on success.
*/
public function save();
/**
* Method to delete the object from the database.
*
* @return boolean True on success.
*/
public function delete();
/**
* Method to perform sanity checks on the instance properties to ensure they are safe to store in the storage.
*
* Child classes should override this method to make sure the data they are storing in the storage is safe and as
* expected before saving the object.
*
* @return boolean True if the instance is sane and able to be stored in the storage.
*/
public function check();
}

View File

@@ -0,0 +1,67 @@
<?php
namespace Grav\Common\Object\Storage;
use Grav\Common\Object\AbstractObject;
class FilesystemStorage implements StorageInterface
{
/**
* @param array $keys
* @return array
*/
public function load(array $keys)
{
// TODO
return [];
}
/**
* @param AbstractObject $object
* @return string|int Id
*/
public function save(AbstractObject $object)
{
// TODO
return 'xxx';
}
/**
* @param AbstractObject $object
* @return bool
*/
public function delete(AbstractObject $object)
{
// TODO
return false;
}
/**
* @param array|int[]|string[] $list
* @return array
*/
public function loadList(array $list)
{
// TODO
return [];
}
/**
* @param array $query
* @return int
*/
public function count(array $query)
{
// TODO
return 0;
}
/**
* @param array $query
* @return array|int[]|string[]
*/
public function find(array $query)
{
// TODO
return [];
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Grav\Common\Object\Storage;
use Grav\Common\Object\AbstractObject;
interface StorageInterface
{
/**
* @param array $keys
* @return array
*/
public function load(array $keys);
/**
* @param AbstractObject $object
* @return string|int Id
*/
public function save(AbstractObject $object);
/**
* @param AbstractObject $object
* @return bool
*/
public function delete(AbstractObject $object);
/**
* @param array|int[]|string[] $list
* @return array
*/
public function loadList(array $list);
/**
* @param array $query
* @return int
*/
public function count(array $query);
/**
* @param array $query
* @return array|int[]|string[]
*/
public function find(array $query);
}