1
0
mirror of https://github.com/flextype/flextype.git synced 2025-08-12 16:14:16 +02:00

feat(entries): rethinking Entries API philosophy #436

This commit is contained in:
Awilum
2020-07-13 11:39:30 +03:00
parent 4e4d287838
commit 751d1b2218

View File

@@ -51,53 +51,6 @@ class Entries
*/
public $entries = [];
/**
* Expression
*
* @var array
* @access public
*/
public $expression = [
'eq' => Comparison::EQ,
'=' => Comparison::EQ,
'<>' => Comparison::NEQ,
'!=' => Comparison::NEQ,
'neq' => Comparison::NEQ,
'<' => Comparison::LT,
'lt' => Comparison::LT,
'<=' => Comparison::LTE,
'lte' => Comparison::LTE,
'>' => Comparison::GT,
'gt' => Comparison::GT,
'>=' => Comparison::GTE,
'gte' => Comparison::GTE,
'is' => Comparison::IS,
'in' => Comparison::IN,
'nin' => Comparison::NIN,
'contains' => Comparison::CONTAINS,
'like' => Comparison::CONTAINS,
'member_of' => Comparison::MEMBER_OF,
'start_with' => Comparison::STARTS_WITH,
'ends_with' => Comparison::ENDS_WITH,
];
/**
* Entires Order Direction
*
* @var array
* @access public
*/
public $direction = [
'asc' => Criteria::ASC,
'desc' => Criteria::DESC,
];
/**
* Entries Visibility
*
@@ -147,36 +100,36 @@ class Entries
/**
* Fetch entry(entries)
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
* @param array|null $filter Select items in collection by given conditions.
*
* @return array The entry array data.
*
* @access public
*/
public function fetch(string $id, ?array $filter = null) : array
public function fetch(string $path, ?array $filter = null) : array
{
// If filter is array then it is entries collection request
if (is_array($filter)) {
return $this->fetchCollection($id, $filter);
return $this->fetchCollection($path, $filter);
}
return $this->fetchSingle($id);
return $this->fetchSingle($path);
}
/**
* Fetch single entry
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
*
* @return array The entry array data.
*
* @access public
*/
public function fetchSingle(string $id) : array
public function fetchSingle(string $path) : array
{
// Get entry file location
$entry_file = $this->getFileLocation($id);
$entry_file = $this->getFileLocation($path);
// If requested entry file founded then process it
if (Filesystem::has($entry_file)) {
@@ -218,7 +171,7 @@ class Entries
$entry_decoded['modified_at'] = (int) Filesystem::getTimestamp($entry_file);
// Entry Slug
$entry_decoded['slug'] = isset($entry_decoded['slug']) ? (string) $entry_decoded['slug'] : (string) ltrim(rtrim($id, '/'), '/');
$entry_decoded['slug'] = isset($entry_decoded['slug']) ? (string) $entry_decoded['slug'] : (string) ltrim(rtrim($path, '/'), '/');
// Entry Routable
$entry_decoded['routable'] = isset($entry_decoded['routable']) ? (bool) $entry_decoded['routable'] : true;
@@ -283,14 +236,14 @@ class Entries
/**
* Fetch entries collection
*
* @param string $id Unique identifier of the entry(entries).
* @param array $filter Select items in collection by given conditions.
* @param string $path Unique identifier of the entry(entries).
* @param array $deep
*
* @return array The entries array data.
*
* @access public
*/
public function fetchCollection(string $id, array $filter = []) : array
public function fetchCollection(string $path, $recursive = false) : array
{
// Init Entries
$entries = [];
@@ -298,76 +251,14 @@ class Entries
// Init Entries
$this->entries = $entries;
// Set Expression
$expression = $this->expression;
// Set Direction
$direction = $this->direction;
// Bind: Entry ID
$bind_id = $id;
// Bind: recursive
$bind_recursive = $filter['recursive'] ?? false;
// Bind: set first result
$bind_set_first_result = $filter['set_first_result'] ?? false;
// Bind: set max result
$bind_set_max_result = $filter['set_max_result'] ?? false;
// Bind: where
$bind_where = [];
if (isset($filter['where']['key']) && isset($filter['where']['expr']) && isset($filter['where']['value'])) {
$bind_where['where']['key'] = $filter['where']['key'];
$bind_where['where']['expr'] = $expression[$filter['where']['expr']];
$bind_where['where']['value'] = $filter['where']['value'];
}
// Bind: and where
$bind_and_where = [];
if (isset($filter['and_where'])) {
foreach ($filter['and_where'] as $key => $value) {
if (! isset($value['key']) || ! isset($value['expr']) || ! isset($value['value'])) {
continue;
}
$bind_and_where[$key] = $value;
}
}
// Bind: or where
$bind_or_where = [];
if (isset($filter['or_where'])) {
foreach ($filter['or_where'] as $key => $value) {
if (! isset($value['key']) || ! isset($value['expr']) || ! isset($value['value'])) {
continue;
}
$bind_or_where[$key] = $value;
}
}
// Bind: order by
$bind_order_by = [];
if (isset($filter['order_by']['field']) && isset($filter['order_by']['direction'])) {
$bind_order_by['order_by']['field'] = $filter['order_by']['field'];
$bind_order_by['order_by']['direction'] = $filter['order_by']['direction'];
}
// Get entries path
$entries_path = $this->getDirLocation($bind_id);
$entries_path = $this->getDirLocation($path);
// Get entries list
$entries_list = Filesystem::listContents($entries_path, $bind_recursive);
$entries_list = Filesystem::listContents($entries_path, $recursive);
// If entries founded in entries folder
if (count($entries_list) > 0) {
// Entries IDs
$entries_ids = '';
// Entries IDs timestamps
$entries_ids_timestamps = '';
// Create entries array from entries list and ignore current requested entry
foreach ($entries_list as $current_entry) {
@@ -390,113 +281,16 @@ class Entries
// Add entry into the entries
$entries[$uid] = $entry;
// Create entries IDs list
$entries_ids .= $uid;
// Create entries IDs timestamps
$entries_ids_timestamps .= Filesystem::getTimestamp($current_entry['path'] . '/entry' . '.' . $this->flextype->registry->get('flextype.settings.entries.extension'));
}
}
}
// Create unique entries $cache_id
$cache_id = md5(
$bind_id .
$entries_ids .
$entries_ids_timestamps .
($bind_recursive ? 'true' : 'false') .
($bind_set_max_result ? $bind_set_max_result : '') .
($bind_set_first_result ? $bind_set_first_result : '') .
json_encode($bind_where) .
json_encode($bind_and_where) .
json_encode($bind_or_where) .
json_encode($bind_order_by)
);
// If requested entries exist with a specific cache_id,
// then we take them from the cache otherwise we look for them.
if ($this->flextype['cache']->contains($cache_id)) {
$entries = $this->flextype['cache']->fetch($cache_id);
} else {
// Save error_reporting state and turn it off
// because PHP Doctrine Collections don't works with collections
// if there is no requested fields to search:
// vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php
// line 40: return $object[$field];
//
// @todo research this issue and find possible better solution to avoid this in the future
$oldErrorReporting = error_reporting();
error_reporting(0);
// Create Array Collection from entries array
$collection = new ArrayCollection($entries);
// Create Criteria for filtering Selectable collections.
$criteria = new Criteria();
// Exec: where
if (isset($bind_where['where']['key']) && isset($bind_where['where']['expr']) && isset($bind_where['where']['value'])) {
$expr = new Comparison($bind_where['where']['key'], $bind_where['where']['expr'], $bind_where['where']['value']);
$criteria->where($expr);
}
// Exec: and where
if (isset($bind_and_where)) {
$_expr = [];
foreach ($bind_and_where as $key => $value) {
$_expr[$key] = new Comparison($value['key'], $expression[$value['expr']], $value['value']);
$criteria->andWhere($_expr[$key]);
}
}
// Exec: or where
if (isset($bind_or_where)) {
$_expr = [];
foreach ($bind_or_where as $key => $value) {
$_expr[$key] = new Comparison($value['key'], $expression[$value['expr']], $value['value']);
$criteria->orWhere($_expr[$key]);
}
}
// Exec: order by
if (isset($bind_order_by['order_by']['field']) && isset($bind_order_by['order_by']['direction'])) {
$criteria->orderBy([$bind_order_by['order_by']['field'] => $direction[$bind_order_by['order_by']['direction']]]);
}
// Exec: set max result
if ($bind_set_max_result) {
$criteria->setMaxResults($bind_set_max_result);
}
// Exec: set first result
if ($bind_set_first_result) {
$criteria->setFirstResult($bind_set_first_result);
}
// Get entries for matching criterias
$entries = $collection->matching($criteria);
// Gets a native PHP array representation of the collection.
$entries = $entries->toArray();
// Magic is here... dot and undot for entries array
// 1. Flatten a multi-dimensional entries array with dots.
// 2. Restore entries array with dots into correct multi-dimensional entries array
$entries = Arr::undot(Arr::dot($entries));
// Restore error_reporting
error_reporting($oldErrorReporting);
// Save entries into the cache
$this->flextype['cache']->save($cache_id, $entries);
}
// Set entries into the property entries
$this->entries = $entries;
// Run event onEntriesAfterInitialized
$this->flextype['emitter']->emit('onEntriesAfterInitialized');
}
// Return entries
@@ -506,17 +300,17 @@ class Entries
/**
* Rename entry
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
* @param string $new_id New Unique identifier of the entry(entries).
*
* @return bool True on success, false on failure.
*
* @access public
*/
public function rename(string $id, string $new_id) : bool
public function rename(string $path, string $new_id) : bool
{
if (!Filesystem::has($this->getDirLocation($new_id))) {
return rename($this->getDirLocation($id), $this->getDirLocation($new_id));
return rename($this->getDirLocation($path), $this->getDirLocation($new_id));
} else {
return false;
}
@@ -525,16 +319,16 @@ class Entries
/**
* Update entry
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
* @param array $data Data to update for the entry.
*
* @return bool True on success, false on failure.
*
* @access public
*/
public function update(string $id, array $data) : bool
public function update(string $path, array $data) : bool
{
$entry_file = $this->getFileLocation($id);
$entry_file = $this->getFileLocation($path);
if (Filesystem::has($entry_file)) {
$body = Filesystem::read($entry_file);
@@ -549,16 +343,16 @@ class Entries
/**
* Create entry
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
* @param array $data Data to create for the entry.
*
* @return bool True on success, false on failure.
*
* @access public
*/
public function create(string $id, array $data) : bool
public function create(string $path, array $data) : bool
{
$entry_dir = $this->getDirLocation($id);
$entry_dir = $this->getDirLocation($path);
if (! Filesystem::has($entry_dir)) {
// Try to create directory for new entry
@@ -596,21 +390,21 @@ class Entries
/**
* Delete entry
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
*
* @return bool True on success, false on failure.
*
* @access public
*/
public function delete(string $id) : bool
public function delete(string $path) : bool
{
return Filesystem::deleteDir($this->getDirLocation($id));
return Filesystem::deleteDir($this->getDirLocation($path));
}
/**
* Copy entry(s)
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
* @param string $new_id New Unique identifier of the entry(entries).
* @param bool $recursive Recursive copy entries.
*
@@ -618,50 +412,50 @@ class Entries
*
* @access public
*/
public function copy(string $id, string $new_id, bool $recursive = false) : ?bool
public function copy(string $path, string $new_id, bool $recursive = false) : ?bool
{
return Filesystem::copy($this->getDirLocation($id), $this->getDirLocation($new_id), $recursive);
return Filesystem::copy($this->getDirLocation($path), $this->getDirLocation($new_id), $recursive);
}
/**
* Check whether entry exists
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
*
* @return bool True on success, false on failure.
*
* @access public
*/
public function has(string $id) : bool
public function has(string $path) : bool
{
return Filesystem::has($this->getFileLocation($id));
return Filesystem::has($this->getFileLocation($path));
}
/**
* Get entry file location
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
*
* @return string entry file location
*
* @access private
*/
public function getFileLocation(string $id) : string
public function getFileLocation(string $path) : string
{
return PATH['project'] . '/entries/' . $id . '/entry' . '.' . $this->flextype->registry->get('flextype.settings.entries.extension');
return PATH['project'] . '/entries/' . $path . '/entry' . '.' . $this->flextype->registry->get('flextype.settings.entries.extension');
}
/**
* Get entry directory location
*
* @param string $id Unique identifier of the entry(entries).
* @param string $path Unique identifier of the entry(entries).
*
* @return string entry directory location
*
* @access private
*/
public function getDirLocation(string $id) : string
public function getDirLocation(string $path) : string
{
return PATH['project'] . '/entries/' . $id;
return PATH['project'] . '/entries/' . $path;
}
}