2019-05-09 18:54:39 +12:00
|
|
|
<?php
|
|
|
|
|
2020-03-25 06:56:32 +13:00
|
|
|
namespace Appwrite\Database;
|
2019-05-09 18:54:39 +12:00
|
|
|
|
|
|
|
use Exception;
|
2020-03-25 06:56:32 +13:00
|
|
|
use Appwrite\Database\Validator\Authorization;
|
|
|
|
use Appwrite\Database\Validator\Structure;
|
|
|
|
use Appwrite\Database\Exception\Authorization as AuthorizationException;
|
|
|
|
use Appwrite\Database\Exception\Structure as StructureException;
|
2019-05-09 18:54:39 +12:00
|
|
|
|
|
|
|
class Database
|
|
|
|
{
|
|
|
|
// System Core
|
|
|
|
const SYSTEM_COLLECTION_COLLECTIONS = 0;
|
|
|
|
const SYSTEM_COLLECTION_RULES = 'rules';
|
|
|
|
|
|
|
|
// Project
|
|
|
|
const SYSTEM_COLLECTION_PROJECTS = 'projects';
|
|
|
|
const SYSTEM_COLLECTION_WEBHOOKS = 'webhooks';
|
|
|
|
const SYSTEM_COLLECTION_KEYS = 'keys';
|
|
|
|
const SYSTEM_COLLECTION_TASKS = 'tasks';
|
|
|
|
const SYSTEM_COLLECTION_PLATFORMS = 'platforms';
|
|
|
|
const SYSTEM_COLLECTION_USAGES = 'usages'; //TODO add structure
|
2020-02-21 09:45:12 +13:00
|
|
|
const SYSTEM_COLLECTION_DOMAINS = 'domains';
|
|
|
|
const SYSTEM_COLLECTION_CERTIFICATES = 'certificates';
|
2020-07-03 09:48:37 +12:00
|
|
|
const SYSTEM_COLLECTION_RESERVED = 'reserved';
|
2019-05-09 18:54:39 +12:00
|
|
|
|
|
|
|
// Auth, Account and Users (private to user)
|
|
|
|
const SYSTEM_COLLECTION_USERS = 'users';
|
2021-02-20 01:12:47 +13:00
|
|
|
const SYSTEM_COLLECTION_SESSIONS = 'sessions';
|
2019-05-09 18:54:39 +12:00
|
|
|
const SYSTEM_COLLECTION_TOKENS = 'tokens';
|
|
|
|
|
|
|
|
// Teams (shared among team members)
|
|
|
|
const SYSTEM_COLLECTION_MEMBERSHIPS = 'memberships';
|
|
|
|
const SYSTEM_COLLECTION_TEAMS = 'teams';
|
|
|
|
|
|
|
|
// Storage
|
|
|
|
const SYSTEM_COLLECTION_FILES = 'files';
|
|
|
|
|
2020-05-05 02:35:01 +12:00
|
|
|
// Functions
|
|
|
|
const SYSTEM_COLLECTION_FUNCTIONS = 'functions';
|
2020-05-06 05:30:12 +12:00
|
|
|
const SYSTEM_COLLECTION_TAGS = 'tags';
|
2020-05-05 02:35:01 +12:00
|
|
|
const SYSTEM_COLLECTION_EXECUTIONS = 'executions';
|
|
|
|
|
|
|
|
// Var Types
|
|
|
|
const SYSTEM_VAR_TYPE_TEXT = 'text';
|
|
|
|
const SYSTEM_VAR_TYPE_NUMERIC = 'numeric';
|
|
|
|
const SYSTEM_VAR_TYPE_BOOLEAN = 'boolean';
|
|
|
|
const SYSTEM_VAR_TYPE_DOCUMENT = 'document';
|
|
|
|
const SYSTEM_VAR_TYPE_WILDCARD = 'wildcard';
|
|
|
|
const SYSTEM_VAR_TYPE_EMAIL = 'email';
|
|
|
|
const SYSTEM_VAR_TYPE_IP = 'ip';
|
|
|
|
const SYSTEM_VAR_TYPE_URL = 'url';
|
|
|
|
const SYSTEM_VAR_TYPE_KEY = 'key';
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
static protected $filters = [];
|
|
|
|
|
2021-01-16 00:56:39 +13:00
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
static protected $statusFilters = true;
|
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
2019-08-10 02:46:09 +12:00
|
|
|
protected $mocks = [];
|
2019-05-09 18:54:39 +12:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Adapter
|
|
|
|
*/
|
|
|
|
protected $adapter;
|
|
|
|
|
|
|
|
/**
|
2019-09-07 05:04:26 +12:00
|
|
|
* Set Adapter.
|
2019-05-09 18:54:39 +12:00
|
|
|
*
|
|
|
|
* @param Adapter $adapter
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setAdapter(Adapter $adapter)
|
|
|
|
{
|
|
|
|
$this->adapter = $adapter;
|
2019-09-07 05:04:26 +12:00
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-07 05:04:26 +12:00
|
|
|
* Set Namespace.
|
2019-05-09 18:54:39 +12:00
|
|
|
*
|
|
|
|
* Set namespace to divide different scope of data sets
|
|
|
|
*
|
|
|
|
* @param $namespace
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @return $this
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function setNamespace($namespace)
|
|
|
|
{
|
|
|
|
$this->adapter->setNamespace($namespace);
|
2019-09-07 05:04:26 +12:00
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-07 05:04:26 +12:00
|
|
|
* Get Namespace.
|
2019-05-09 18:54:39 +12:00
|
|
|
*
|
|
|
|
* Get namespace of current set scope
|
|
|
|
*
|
|
|
|
* @return string
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function getNamespace()
|
|
|
|
{
|
|
|
|
return $this->adapter->getNamespace();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-07 05:04:26 +12:00
|
|
|
* Create Namespace.
|
|
|
|
*
|
2020-10-27 13:08:29 +13:00
|
|
|
* @param string $namespace
|
2019-05-09 18:54:39 +12:00
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function createNamespace($namespace)
|
|
|
|
{
|
|
|
|
return $this->adapter->createNamespace($namespace);
|
|
|
|
}
|
|
|
|
|
2019-08-23 08:53:50 +12:00
|
|
|
/**
|
2019-09-07 05:04:26 +12:00
|
|
|
* Delete Namespace.
|
|
|
|
*
|
2020-10-27 13:08:29 +13:00
|
|
|
* @param string $namespace
|
2019-08-23 08:53:50 +12:00
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function deleteNamespace($namespace)
|
|
|
|
{
|
|
|
|
return $this->adapter->deleteNamespace($namespace);
|
|
|
|
}
|
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
/**
|
|
|
|
* @param array $options
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2020-06-29 07:28:18 +12:00
|
|
|
* @return Document[]
|
2019-05-09 18:54:39 +12:00
|
|
|
*/
|
|
|
|
public function getCollection(array $options)
|
|
|
|
{
|
2020-06-20 23:05:43 +12:00
|
|
|
$options = \array_merge([
|
2019-05-09 18:54:39 +12:00
|
|
|
'offset' => 0,
|
|
|
|
'limit' => 15,
|
|
|
|
'search' => '',
|
|
|
|
'relations' => true,
|
2020-12-13 12:22:55 +13:00
|
|
|
'orderField' => '',
|
2019-05-09 18:54:39 +12:00
|
|
|
'orderType' => 'ASC',
|
|
|
|
'orderCast' => 'int',
|
|
|
|
'filters' => [],
|
|
|
|
], $options);
|
|
|
|
|
|
|
|
$results = $this->adapter->getCollection($options);
|
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
foreach ($results as &$node) {
|
2020-10-30 00:32:39 +13:00
|
|
|
$node = $this->decode(new Document($node));
|
2019-05-09 18:54:39 +12:00
|
|
|
}
|
|
|
|
|
2020-06-27 02:41:13 +12:00
|
|
|
return $results;
|
|
|
|
}
|
2019-05-09 18:54:39 +12:00
|
|
|
|
2020-06-27 02:41:13 +12:00
|
|
|
/**
|
|
|
|
* @param array $options
|
|
|
|
*
|
|
|
|
* @return Document
|
|
|
|
*/
|
|
|
|
public function getCollectionFirst(array $options)
|
|
|
|
{
|
|
|
|
$results = $this->getCollection($options);
|
|
|
|
return \reset($results);
|
|
|
|
}
|
2019-05-09 18:54:39 +12:00
|
|
|
|
2020-06-27 02:41:13 +12:00
|
|
|
/**
|
|
|
|
* @param array $options
|
|
|
|
*
|
|
|
|
* @return Document
|
|
|
|
*/
|
|
|
|
public function getCollectionLast(array $options)
|
|
|
|
{
|
|
|
|
$results = $this->getCollection($options);
|
|
|
|
return \end($results);
|
2019-05-09 18:54:39 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-10-27 13:08:29 +13:00
|
|
|
* @param string $id
|
2019-05-09 18:54:39 +12:00
|
|
|
* @param bool $mock is mocked data allowed?
|
2020-10-27 13:08:29 +13:00
|
|
|
* @param bool $decode enable decoding?
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @return Document
|
|
|
|
*/
|
2020-10-27 13:08:29 +13:00
|
|
|
public function getDocument($id, bool $mock = true, bool $decode = true)
|
2019-05-09 18:54:39 +12:00
|
|
|
{
|
2020-06-20 23:05:43 +12:00
|
|
|
if (\is_null($id)) {
|
2020-10-27 13:08:29 +13:00
|
|
|
return new Document();
|
2019-05-09 18:54:39 +12:00
|
|
|
}
|
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
$document = new Document((isset($this->mocks[$id]) && $mock) ? $this->mocks[$id] : $this->adapter->getDocument($id));
|
|
|
|
$validator = new Authorization($document, 'read');
|
2019-07-04 07:50:04 +12:00
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
if (!$validator->isValid($document->getPermissions())) { // Check if user has read access to this document
|
2020-10-27 13:08:29 +13:00
|
|
|
return new Document();
|
2019-05-09 18:54:39 +12:00
|
|
|
}
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
$document = ($decode) ? $this->decode($document) : $document;
|
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
return $document;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $data
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2021-01-27 08:16:03 +13:00
|
|
|
* @return Document
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @throws AuthorizationException
|
|
|
|
* @throws StructureException
|
|
|
|
*/
|
2020-03-22 10:10:06 +13:00
|
|
|
public function createDocument(array $data, array $unique = [])
|
2019-05-09 18:54:39 +12:00
|
|
|
{
|
|
|
|
$document = new Document($data);
|
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
$validator = new Authorization($document, 'write');
|
2019-05-09 18:54:39 +12:00
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
if (!$validator->isValid($document->getPermissions())) { // Check if user has write access to this document
|
2019-05-09 18:54:39 +12:00
|
|
|
throw new AuthorizationException($validator->getDescription());
|
|
|
|
}
|
|
|
|
|
|
|
|
$validator = new Structure($this);
|
2020-05-13 10:00:00 +12:00
|
|
|
|
|
|
|
$document = $this->encode($document);
|
2019-05-09 18:54:39 +12:00
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
if (!$validator->isValid($document)) {
|
2019-05-09 18:54:39 +12:00
|
|
|
throw new StructureException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
|
|
|
|
}
|
2020-05-13 10:00:00 +12:00
|
|
|
|
|
|
|
$document = new Document($this->adapter->createDocument($document->getArrayCopy(), $unique));
|
|
|
|
|
|
|
|
$document = $this->decode($document);
|
2019-05-09 18:54:39 +12:00
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
return $document;
|
2019-05-09 18:54:39 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $data
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @return Document|false
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function updateDocument(array $data)
|
|
|
|
{
|
2020-02-17 20:16:11 +13:00
|
|
|
if (!isset($data['$id'])) {
|
|
|
|
throw new Exception('Must define $id attribute');
|
2019-05-09 18:54:39 +12:00
|
|
|
}
|
|
|
|
|
2020-02-17 20:16:11 +13:00
|
|
|
$document = $this->getDocument($data['$id']); // TODO make sure user don\'t need read permission for write operations
|
2019-05-09 18:54:39 +12:00
|
|
|
|
|
|
|
// Make sure reserved keys stay constant
|
2020-02-17 20:16:11 +13:00
|
|
|
$data['$id'] = $document->getId();
|
2019-05-09 18:54:39 +12:00
|
|
|
$data['$collection'] = $document->getCollection();
|
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
$validator = new Authorization($document, 'write');
|
2019-05-09 18:54:39 +12:00
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
if (!$validator->isValid($document->getPermissions())) { // Check if user has write access to this document
|
2019-05-09 18:54:39 +12:00
|
|
|
throw new AuthorizationException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$new = new Document($data);
|
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
if (!$validator->isValid($new->getPermissions())) { // Check if user has write access to this document
|
2019-05-09 18:54:39 +12:00
|
|
|
throw new AuthorizationException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
|
|
|
|
}
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
$new = $this->encode($new);
|
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
$validator = new Structure($this);
|
|
|
|
|
2020-02-17 20:16:11 +13:00
|
|
|
if (!$validator->isValid($new)) { // Make sure updated structure still apply collection rules (if any)
|
|
|
|
throw new StructureException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
|
|
|
|
}
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
$new = new Document($this->adapter->updateDocument($new->getArrayCopy()));
|
|
|
|
|
|
|
|
$new = $this->decode($new);
|
|
|
|
|
|
|
|
return $new;
|
2020-02-17 20:16:11 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $data
|
|
|
|
*
|
|
|
|
* @return Document|false
|
|
|
|
*
|
|
|
|
* @throws Exception
|
|
|
|
*/
|
|
|
|
public function overwriteDocument(array $data)
|
|
|
|
{
|
|
|
|
if (!isset($data['$id'])) {
|
|
|
|
throw new Exception('Must define $id attribute');
|
|
|
|
}
|
|
|
|
|
|
|
|
$document = $this->getDocument($data['$id']); // TODO make sure user don\'t need read permission for write operations
|
|
|
|
|
|
|
|
$validator = new Authorization($document, 'write');
|
|
|
|
|
|
|
|
if (!$validator->isValid($document->getPermissions())) { // Check if user has write access to this document
|
|
|
|
throw new AuthorizationException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$new = new Document($data);
|
|
|
|
|
|
|
|
if (!$validator->isValid($new->getPermissions())) { // Check if user has write access to this document
|
|
|
|
throw new AuthorizationException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
|
|
|
|
}
|
|
|
|
|
2020-10-30 00:32:39 +13:00
|
|
|
$new = $this->encode($new);
|
|
|
|
|
2020-02-17 20:16:11 +13:00
|
|
|
$validator = new Structure($this);
|
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
if (!$validator->isValid($new)) { // Make sure updated structure still apply collection rules (if any)
|
2019-05-09 18:54:39 +12:00
|
|
|
throw new StructureException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
|
|
|
|
}
|
|
|
|
|
2020-10-30 00:32:39 +13:00
|
|
|
$new = new Document($this->adapter->updateDocument($new->getArrayCopy()));
|
|
|
|
|
|
|
|
$new = $this->decode($new);
|
|
|
|
|
|
|
|
return $new;
|
2019-05-09 18:54:39 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-10-27 13:08:29 +13:00
|
|
|
* @param string $id
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @return Document|false
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @throws AuthorizationException
|
|
|
|
*/
|
2020-10-27 13:08:29 +13:00
|
|
|
public function deleteDocument(string $id)
|
2019-05-09 18:54:39 +12:00
|
|
|
{
|
|
|
|
$document = $this->getDocument($id);
|
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
$validator = new Authorization($document, 'write');
|
2019-05-09 18:54:39 +12:00
|
|
|
|
2019-09-07 05:04:26 +12:00
|
|
|
if (!$validator->isValid($document->getPermissions())) { // Check if user has write access to this document
|
2019-05-09 18:54:39 +12:00
|
|
|
throw new AuthorizationException($validator->getDescription());
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Document($this->adapter->deleteDocument($id));
|
|
|
|
}
|
|
|
|
|
2020-08-29 06:53:19 +12:00
|
|
|
/**
|
|
|
|
* @param int $key
|
|
|
|
*
|
|
|
|
* @return Document|false
|
|
|
|
*
|
|
|
|
* @throws AuthorizationException
|
|
|
|
*/
|
|
|
|
public function deleteUniqueKey($key)
|
|
|
|
{
|
|
|
|
return new Document($this->adapter->deleteUniqueKey($key));
|
|
|
|
}
|
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
/**
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getDebug()
|
|
|
|
{
|
|
|
|
return $this->adapter->getDebug();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function getSum()
|
|
|
|
{
|
|
|
|
$debug = $this->getDebug();
|
|
|
|
|
|
|
|
return (isset($debug['sum'])) ? $debug['sum'] : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $options
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2019-05-09 18:54:39 +12:00
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function getCount(array $options)
|
|
|
|
{
|
2020-06-20 23:05:43 +12:00
|
|
|
$options = \array_merge([
|
2019-05-09 18:54:39 +12:00
|
|
|
'filters' => [],
|
|
|
|
], $options);
|
|
|
|
|
|
|
|
$results = $this->adapter->getCount($options);
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
2019-08-10 02:11:22 +12:00
|
|
|
/**
|
|
|
|
* @param string $key
|
|
|
|
* @param string $value
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2020-10-27 13:08:29 +13:00
|
|
|
* @return self
|
2019-08-10 02:11:22 +12:00
|
|
|
*/
|
2020-10-27 13:08:29 +13:00
|
|
|
public function setMock($key, $value): self
|
2019-09-07 05:04:26 +12:00
|
|
|
{
|
2019-08-10 02:11:22 +12:00
|
|
|
$this->mocks[$key] = $value;
|
2019-09-07 05:04:26 +12:00
|
|
|
|
2019-08-10 02:11:22 +12:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2019-08-10 02:46:09 +12:00
|
|
|
/**
|
2020-10-27 13:08:29 +13:00
|
|
|
* @param array $mocks
|
2019-09-07 05:04:26 +12:00
|
|
|
*
|
2020-10-27 13:08:29 +13:00
|
|
|
* @return self
|
2019-08-10 02:46:09 +12:00
|
|
|
*/
|
2020-10-27 13:08:29 +13:00
|
|
|
public function setMocks(array $mocks): self
|
2019-09-07 05:04:26 +12:00
|
|
|
{
|
2019-08-10 02:46:09 +12:00
|
|
|
$this->mocks = $mocks;
|
2019-09-07 05:04:26 +12:00
|
|
|
|
2019-08-10 02:46:09 +12:00
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
/**
|
|
|
|
* @return array
|
|
|
|
*/
|
2019-09-07 05:04:26 +12:00
|
|
|
public function getMocks()
|
|
|
|
{
|
2019-05-09 18:54:39 +12:00
|
|
|
return $this->mocks;
|
|
|
|
}
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
/**
|
|
|
|
* Add Attribute Filter
|
2020-10-27 13:08:29 +13:00
|
|
|
*
|
2020-05-13 10:00:00 +12:00
|
|
|
* @param string $name
|
|
|
|
* @param callable $encode
|
|
|
|
* @param callable $decode
|
2020-10-27 13:08:29 +13:00
|
|
|
*
|
|
|
|
* @return void
|
2020-05-13 10:00:00 +12:00
|
|
|
*/
|
2020-10-27 13:08:29 +13:00
|
|
|
static public function addFilter(string $name, callable $encode, callable $decode): void
|
2020-05-13 10:00:00 +12:00
|
|
|
{
|
|
|
|
self::$filters[$name] = [
|
|
|
|
'encode' => $encode,
|
|
|
|
'decode' => $decode,
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2021-01-16 00:56:39 +13:00
|
|
|
/**
|
|
|
|
* Disable Attribute decoding
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public static function disableFilters(): void
|
|
|
|
{
|
|
|
|
self::$statusFilters = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enable Attribute decoding
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public static function enableFilters(): void
|
|
|
|
{
|
|
|
|
self::$statusFilters = true;
|
|
|
|
}
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
public function encode(Document $document):Document
|
|
|
|
{
|
2021-02-01 23:24:52 +13:00
|
|
|
if (!self::$statusFilters) {
|
|
|
|
return $document;
|
|
|
|
}
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
$collection = $this->getDocument($document->getCollection(), true , false);
|
|
|
|
$rules = $collection->getAttribute('rules', []);
|
|
|
|
|
|
|
|
foreach ($rules as $key => $rule) {
|
|
|
|
$key = $rule->getAttribute('key', null);
|
2020-11-21 12:31:17 +13:00
|
|
|
$type = $rule->getAttribute('type', null);
|
|
|
|
$array = $rule->getAttribute('array', false);
|
|
|
|
$filters = $rule->getAttribute('filter', []);
|
2020-05-13 10:00:00 +12:00
|
|
|
$value = $document->getAttribute($key, null);
|
|
|
|
|
2020-11-21 12:31:17 +13:00
|
|
|
if (($value !== null)) {
|
|
|
|
if ($type === self::SYSTEM_VAR_TYPE_DOCUMENT) {
|
|
|
|
if($array) {
|
|
|
|
$list = [];
|
|
|
|
foreach ($value as $child) {
|
|
|
|
$list[] = $this->encode($child);
|
|
|
|
}
|
|
|
|
|
|
|
|
$document->setAttribute($key, $list);
|
|
|
|
} else {
|
|
|
|
$document->setAttribute($key, $this->encode($value));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($filters as $filter) {
|
|
|
|
$value = $this->encodeAttribute($filter, $value);
|
|
|
|
$document->setAttribute($key, $value);
|
|
|
|
}
|
2020-05-13 10:00:00 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $document;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function decode(Document $document):Document
|
|
|
|
{
|
2021-02-01 23:24:52 +13:00
|
|
|
if (!self::$statusFilters) {
|
|
|
|
return $document;
|
|
|
|
}
|
|
|
|
|
2020-05-13 10:00:00 +12:00
|
|
|
$collection = $this->getDocument($document->getCollection(), true , false);
|
|
|
|
$rules = $collection->getAttribute('rules', []);
|
|
|
|
|
|
|
|
foreach ($rules as $key => $rule) {
|
|
|
|
$key = $rule->getAttribute('key', null);
|
2020-11-21 12:31:17 +13:00
|
|
|
$type = $rule->getAttribute('type', null);
|
|
|
|
$array = $rule->getAttribute('array', false);
|
|
|
|
$filters = $rule->getAttribute('filter', []);
|
2020-05-13 10:00:00 +12:00
|
|
|
$value = $document->getAttribute($key, null);
|
|
|
|
|
2020-11-21 12:31:17 +13:00
|
|
|
if (($value !== null)) {
|
|
|
|
if ($type === self::SYSTEM_VAR_TYPE_DOCUMENT) {
|
|
|
|
if($array) {
|
|
|
|
$list = [];
|
|
|
|
foreach ($value as $child) {
|
|
|
|
$list[] = $this->decode($child);
|
|
|
|
}
|
|
|
|
|
|
|
|
$document->setAttribute($key, $list);
|
|
|
|
} else {
|
|
|
|
$document->setAttribute($key, $this->decode($value));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach (array_reverse($filters) as $filter) {
|
|
|
|
$value = $this->decodeAttribute($filter, $value);
|
|
|
|
$document->setAttribute($key, $value);
|
|
|
|
}
|
2020-05-13 10:00:00 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $document;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Encode Attribute
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @param mixed $value
|
|
|
|
*/
|
|
|
|
static protected function encodeAttribute(string $name, $value)
|
|
|
|
{
|
2020-10-28 08:44:15 +13:00
|
|
|
if (!isset(self::$filters[$name])) {
|
2020-11-21 12:31:17 +13:00
|
|
|
return $value;
|
2020-05-13 10:00:00 +12:00
|
|
|
throw new Exception('Filter not found');
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$value = self::$filters[$name]['encode']($value);
|
|
|
|
} catch (\Throwable $th) {
|
|
|
|
$value = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decode Attribute
|
|
|
|
*
|
|
|
|
* @param string $name
|
|
|
|
* @param mixed $value
|
|
|
|
*/
|
|
|
|
static protected function decodeAttribute(string $name, $value)
|
|
|
|
{
|
2020-10-28 08:44:15 +13:00
|
|
|
if (!isset(self::$filters[$name])) {
|
2020-11-21 12:31:17 +13:00
|
|
|
return $value;
|
2020-05-13 10:00:00 +12:00
|
|
|
throw new Exception('Filter not found');
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$value = self::$filters[$name]['decode']($value);
|
|
|
|
} catch (\Throwable $th) {
|
|
|
|
$value = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $value;
|
|
|
|
}
|
|
|
|
|
2019-05-09 18:54:39 +12:00
|
|
|
/**
|
2019-09-07 05:04:26 +12:00
|
|
|
* Get Last Modified.
|
2019-05-09 18:54:39 +12:00
|
|
|
*
|
2020-06-24 23:18:33 +12:00
|
|
|
* Return Unix timestamp of last time a node queried in current session has been changed
|
2019-05-09 18:54:39 +12:00
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public function lastModified()
|
|
|
|
{
|
|
|
|
return $this->adapter->lastModified();
|
|
|
|
}
|
2019-09-07 05:04:26 +12:00
|
|
|
}
|