From 08ef023fa7ebf4b82696a005bf469b59623545fe Mon Sep 17 00:00:00 2001 From: Awilum Date: Fri, 28 Jun 2019 00:07:53 +0300 Subject: [PATCH] Flextype Core: Entries #175 #165 - Collections implementation / new code for fetchAll() method --- flextype/core/Entries.php | 213 ++++++++++++++++++++++++++++++-------- 1 file changed, 169 insertions(+), 44 deletions(-) diff --git a/flextype/core/Entries.php b/flextype/core/Entries.php index 5171c9ff..c12b610c 100755 --- a/flextype/core/Entries.php +++ b/flextype/core/Entries.php @@ -14,6 +14,9 @@ namespace Flextype; use Flextype\Component\Arr\Arr; use Flextype\Component\Filesystem\Filesystem; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Criteria; +use Doctrine\Common\Collections\Expr\Comparison; class Entries { @@ -51,46 +54,68 @@ class Entries } /** - * Fetch entry + * Fetch single entry * * @access public - * @param string $id Entry id + * @param string $id Entry ID * @return array|false The entry contents or false on failure. */ public function fetch(string $id) { + // Get entry file location $entry_file = $this->_file_location($id); + // If requested entry founded then process it if (Filesystem::has($entry_file)) { // Create unique entry cache_id - $cache_id = md5('entry' . $entry_file . ((Filesystem::getTimestamp($entry_file) === false) ? '' : Filesystem::getTimestamp($entry_file))); + // Entry Cache ID = entry + entry file + entry file time stamp + $entry_cache_id = md5('entry' . $entry_file . Filesystem::getTimestamp($entry_file)); - // Try to get the entry from cache - if ($this->flextype['cache']->contains($cache_id)) { - if ($entry_decoded = $this->flextype['cache']->fetch($cache_id)) { - return $entry_decoded; + // Try to get the requested entry from cache + if ($this->flextype['cache']->contains($entry_cache_id)) { + + // Try to fetch requested entry from the cache + if ($entry = $this->flextype['cache']->fetch($entry_cache_id)) { + + // Run event onEntryAfterInitialized + $this->flextype['emitter']->emit('onEntryAfterInitialized'); + + // Return entry + return $entry; } else { return false; } + + // else Try to get requested entry from the filesystem } else { + + // Try to get requested entry body content if ($entry_body = Filesystem::read($entry_file)) { + + // Try to decode requested entry body content if ($entry_decoded = JsonParser::decode($entry_body)) { - // Create default entry items + // + // Add predefined entry items + // + + // Entry Date $entry_decoded['date'] = $entry_decoded['date'] ?? date($this->flextype['registry']->get('settings.date_format'), Filesystem::getTimestamp($entry_file)); + + // Entry Slug $entry_decoded['slug'] = $entry_decoded['slug'] ?? ltrim(rtrim($id, '/'), '/'); // Save decoded entry content into the cache - $this->flextype['cache']->save($cache_id, $entry_decoded); + $this->flextype['cache']->save($entry_cache_id, $entry_decoded); - // Set entry + // Set entry to the Entry class property $entry $this->entry = $entry_decoded; // Run event onEntryAfterInitialized $this->flextype['emitter']->emit('onEntryAfterInitialized'); - // Return entry + // Return entry from the Entry class property $entry return $this->entry; } else { return false; @@ -105,43 +130,110 @@ class Entries } /** - * Fetch all entries + * Fetch entries collection * * @access public - * @param string $id Entry id - * @param string $order_by Order by specific entry field. - * @param string $order_type Order type: DESC or ASC - * @param int $offset Offset - * @param int $length Length - * @param bool $recursive Whether to list recursively. + * @param array $args Query arguments * @return array The entries */ - public function fetchAll(string $id, string $order_by = 'date', string $order_type = 'DESC', int $offset = null, int $length = null, bool $recursive = false) : array + public function fetchAll(array $args) : array { - // Set empty entries array where founded entries will stored - $entries = []; + // Bind: entry id + $bind_id = ($args['id']) ?? ''; - // Set empty cache id for the entries - $cache_id = ''; + // Bind: recursive + $bind_recursive = ($args['recursive']) ? true : false; + + // Bind: set first result + $bind_set_first_result = ($args['set_first_result']) ?? false; + + // Bind: set max result + $bind_set_max_result = ($args['set_max_result']) ?? false; + + // Bind: where + if ($args['where'] && is_array($args['where'])) { + $bind_where['where'] = []; + $bind_where['where']['key'] = $args['where']['key']; + $bind_where['where']['expr'] = $args['where']['expr']; + $bind_where['where']['value'] = $args['where']['value']; + } else { + $bind_where = false; + } + + // Bind: and where + if ($args['and_where'] && is_array($args['and_where'])) { + $bind_and_where['and_where'] = []; + $bind_and_where['and_where']['key'] = $args['and_where']['key']; + $bind_and_where['and_where']['expr'] = $args['and_where']['expr']; + $bind_and_where['and_where']['value'] = $args['and_where']['value']; + } else { + $bind_and_where = false; + } + + // Bind: or where + if ($args['or_where'] && is_array($args['or_where'])) { + $bind_or_where['or_where'] = []; + $bind_or_where['or_where']['key'] = $args['or_where']['key']; + $bind_or_where['or_where']['expr'] = $args['or_where']['expr']; + $bind_or_where['or_where']['value'] = $args['or_where']['value']; + } else { + $bind_or_where = false; + } + + // Bind: order by + if ($args['order_by'] && is_array($args['order_by'])) { + $bind_order_by['order_by'] = []; + $bind_order_by['order_by']['field'] = $args['order_by']['field']; + $bind_order_by['order_by']['direction'] = $args['order_by']['direction']; + } else { + $bind_order_by = false; + } // Get entries path - $entries_path = $this->_dir_location($id); + $entries_path = $this->_dir_location($bind_id); // Get entries list - $entries_list = Filesystem::listContents($entries_path, $recursive); + $entries_list = Filesystem::listContents($entries_path, $bind_recursive); - // Create unique entries cache_id + // Create unique entries $_entries_ids + // 1. Go through all entries + // 2. set all entries IDs and their timestamps into the $_entries_ids + $_entries_ids = ''; foreach ($entries_list as $current_entry) { - if (strpos($current_entry['path'], $id . '/entry.json') !== false) { + if (strpos($current_entry['path'], $bind_id . '/entry.json') !== false) { // ignore ... } else { if ($current_entry['type'] == 'dir' && Filesystem::has($current_entry['path'] . '/entry.json')) { - $cache_id .= md5('entries' . $current_entry['path'] . Filesystem::getTimestamp($current_entry['path'] . '/entry.json')); + $_entries_ids .= 'entry:' . ltrim(rtrim(str_replace(PATH['entries'], '', $current_entry['path']), '/'), '/') . ' timestamp:' . Filesystem::getTimestamp($current_entry['path'] . '/entry.json') . ' '; } } } - // If the entries exist at a specific cache_id, + // Create unique entries $cache_id + $cache_id = md5($_entries_ids . + $bind_id . + ($bind_recursive) ? 'true' : 'false' . + ($bind_set_max_result) ? $bind_set_max_result : 'false' . + ($bind_set_first_result) ? $bind_set_first_result : 'false' . + ($bind_set_max_result) ? $bind_set_max_result : 'false' . + ($bind_where['where']) ? 'true' : 'false' . + ($bind_where['where']['key']) ? $bind_where['where']['key'] : 'false' . + ($bind_where['where']['expr']) ? $bind_where['where']['expr'] : 'false' . + ($bind_where['where']['value']) ? $bind_where['where']['value'] : 'false' . + ($bind_and_where['and_where']) ? 'true' : 'false' . + ($bind_and_where['and_where']['key']) ? $bind_and_where['and_where']['key'] : 'false' . + ($bind_and_where['and_where']['expr']) ? $bind_and_where['and_where']['expr'] : 'false' . + ($bind_and_where['and_where']['value']) ? $bind_and_where['and_where']['value'] : 'false' . + ($bind_or_where['or_where']) ? 'true' : 'false' . + ($bind_or_where['or_where']['key']) ? $bind_or_where['or_where']['key'] : 'false' . + ($bind_or_where['or_where']['expr']) ? $bind_or_where['or_where']['expr'] : 'false' . + ($bind_or_where['or_where']['value']) ? $bind_or_where['or_where']['value'] : 'false' . + ($bind_or_where['order_by']) ? 'true' : 'false' . + ($bind_or_where['order_by']['field']) ? $bind_or_where['order_by']['field'] : 'false' . + ($bind_or_where['order_by']['direction']) ? $bind_or_where['order_by']['direction'] : 'false' + ); + + // 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); @@ -149,7 +241,7 @@ class Entries // Create entries array from entries list and ignore current requested entry foreach ($entries_list as $current_entry) { - if (strpos($current_entry['path'], $id . '/entry.json') !== false) { + if (strpos($current_entry['path'], $bind_id . '/entry.json') !== false) { // ignore ... } else { // We are checking... @@ -162,28 +254,61 @@ class Entries $uid = ltrim(rtrim(str_replace(PATH['entries'], '', $current_entry['path']), '/'), '/'); // For each founded entry we should create $entries array. - $entries[$uid] = $this->fetch($uid); + $entry = $this->fetch($uid); + + // Add entry into the entries + $entries[$uid] = $entry; } } } + // Create Array Collection from entries array + $collection = new ArrayCollection($entries); + + // Create Criteria for filtering Selectable collections. + $criteria = new Criteria(); + + // Exec: where + if ($bind_where) { + $expr = new Comparison($bind_where['where']['key'], $bind_where['where']['expr'], $bind_where['where']['value']); + $criteria->where($expr); + } + + // Exec: and where + if ($bind_and_where) { + $expr = new Comparison($bind_and_where['and_where']['key'], $bind_and_where['and_where']['expr'], $bind_and_where['and_where']['value']); + $criteria->where($expr); + } + + // Exec: or where + if ($bind_or_where) { + $expr = new Comparison($bind_or_where['or_where']['key'], $bind_or_where['or_where']['expr'], $bind_or_where['or_where']['value']); + $criteria->where($expr); + } + + // Exec: order by + if ($bind_order_by) { + $criteria->orderBy($bind_order_by['field'], $bind_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); + // Save entries into the cache $this->flextype['cache']->save($cache_id, $entries); } - // If count of the entries more then 0 then sort and slice them. - if (count($entries) > 0) { - - // Sort entries - $entries = Arr::sort($entries, $order_by, $order_type); - - // Slice entries - if ($offset !== null && $length !== null) { - $entries = array_slice($entries, $offset, $length); - } - } - - // Set entries + // Set entries into the property entries $this->entries = $entries; // Run event onEntriesAfterInitialized