From c53ece2a2d221ae6ee7b58ab9568ace2c4cb0f99 Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe <llewellyn@vdm.io> Date: Fri, 16 Sep 2022 23:41:41 +0200 Subject: [PATCH] Adds more classes, and refactoring to the search feature. Adds test search to search page. #952 --- README.md | 8 +- admin/README.txt | 8 +- .../en-GB/en-GB.com_componentbuilder.ini | 1 - admin/models/ajax.php | 16 +- admin/views/search/tmpl/default.php | 25 +- componentbuilder.xml | 2 +- .../src/Componentbuilder/Search/Agent.php | 2 +- .../Componentbuilder/Search/Agent/Replace.php | 2 +- .../Componentbuilder/Search/Agent/Search.php | 253 ++++++++++++++++-- .../Componentbuilder/Search/Agent/Update.php | 115 ++++++-- .../src/Componentbuilder/Search/Config.php | 8 +- .../Search/Interfaces/FindInterface.php | 3 +- .../Search/Interfaces/ModelInterface.php | 10 +- .../Search/Interfaces/SearchInterface.php | 56 ++++ .../Search/Interfaces/SearchTypeInterface.php | 43 +++ .../src/Componentbuilder/Search/Model.php | 51 +++- .../src/Componentbuilder/Search/Model/Get.php | 10 +- .../Componentbuilder/Search/Service/Agent.php | 6 +- .../Search/Service/Search.php | 77 ++++++ .../Componentbuilder/Search/Type/Basic.php | 127 +++++++++ .../Componentbuilder/Search/Type/Regex.php | 112 ++++++++ .../Componentbuilder/Search/Type/index.html | 1 + 22 files changed, 845 insertions(+), 91 deletions(-) create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchInterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchTypeInterface.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Basic.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Regex.php create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/index.html diff --git a/README.md b/README.md index 20ac6437d..342c18d3f 100644 --- a/README.md +++ b/README.md @@ -140,14 +140,14 @@ TODO + *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) + *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder) + *First Build*: 30th April, 2015 -+ *Last Build*: 14th September, 2022 ++ *Last Build*: 16th September, 2022 + *Version*: 3.1.5 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **330282** ++ *Line count*: **331035** + *Field count*: **2002** -+ *File count*: **2161** -+ *Folder count*: **374** ++ *File count*: **2166** ++ *Folder count*: **375** > This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com). > Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) diff --git a/admin/README.txt b/admin/README.txt index 20ac6437d..342c18d3f 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -140,14 +140,14 @@ TODO + *Author*: [Llewellyn van der Merwe](mailto:joomla@vdm.io) + *Name*: [Component Builder](https://git.vdm.dev/joomla/Component-Builder) + *First Build*: 30th April, 2015 -+ *Last Build*: 14th September, 2022 ++ *Last Build*: 16th September, 2022 + *Version*: 3.1.5 + *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved. + *License*: GNU General Public License version 2 or later; see LICENSE.txt -+ *Line count*: **330282** ++ *Line count*: **331035** + *Field count*: **2002** -+ *File count*: **2161** -+ *Folder count*: **374** ++ *File count*: **2166** ++ *Folder count*: **375** > This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com). > Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.ini b/admin/language/en-GB/en-GB.com_componentbuilder.ini index 5d19974ee..8fb1a0828 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.ini @@ -7760,7 +7760,6 @@ COM_COMPONENTBUILDER_MODEL_AFTER_MODELLING="Model (after modelling)" COM_COMPONENTBUILDER_MODEL_BEFORE_MODELLING="Model (before modelling)" COM_COMPONENTBUILDER_MODULE="Module" COM_COMPONENTBUILDER_MODULES="Modules" -COM_COMPONENTBUILDER_MORE_SOON="More soon" COM_COMPONENTBUILDER_MOVE="Move" COM_COMPONENTBUILDER_NAME="Name" COM_COMPONENTBUILDER_NAME_ASC="Name (Asc)" diff --git a/admin/models/ajax.php b/admin/models/ajax.php index 9c3ce9a3e..b347bafa8 100644 --- a/admin/models/ajax.php +++ b/admin/models/ajax.php @@ -3622,17 +3622,17 @@ class ComponentbuilderModelAjax extends ListModel int $matchCase, int $wholeWord, int $regexSearch, int $componentId): ?array { // check if this is a valid table - if (SearchFactory('Table')->exist($tableName)) + if (SearchFactory::_('Table')->exist($tableName)) { // load the configurations - SearchFactory('Config')->table_name = $tableName; - SearchFactory('Config')->search_value = $searchValue; - SearchFactory('Config')->match_case = $matchCase; - SearchFactory('Config')->whole_word = $wholeWord; - SearchFactory('Config')->regex_search = $regexSearch; - SearchFactory('Config')->component_id = $componentId; + SearchFactory::_('Config')->table_name = $tableName; + SearchFactory::_('Config')->search_value = $searchValue; + SearchFactory::_('Config')->match_case = $matchCase; + SearchFactory::_('Config')->whole_word = $wholeWord; + SearchFactory::_('Config')->regex_search = $regexSearch; + SearchFactory::_('Config')->component_id = $componentId; - if (($items = SearchFactory('Agent')->find()) !== null) + if (($items = SearchFactory::_('Agent')->find()) !== null) { return ['success' => JText::sprintf('COM_COMPONENTBUILDER_WE_FOUND_SOME_INSTANCES_IN_S', $tableName), 'items' => $items]; } diff --git a/admin/views/search/tmpl/default.php b/admin/views/search/tmpl/default.php index d28ecae59..5413d57c0 100644 --- a/admin/views/search/tmpl/default.php +++ b/admin/views/search/tmpl/default.php @@ -16,6 +16,7 @@ JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html'); JHtml::_('behavior.formvalidator'); JHtml::_('formbehavior.chosen', 'select'); JHtml::_('behavior.keepalive'); +use VDM\Joomla\Componentbuilder\Search\Factory as SearchFactory; ?> <?php if ($this->canDo->get('search.access')): ?> <script type="text/javascript"> @@ -41,7 +42,29 @@ JHtml::_('behavior.keepalive'); <?php else : ?> <div id="j-main-container"> <?php endif; ?> - <?php echo JText::_('COM_COMPONENTBUILDER_MORE_SOON'); ?> + <?php + // lets do some tests with the API + $tableName = 'admin_view'; + $searchValue = ' array('; + // set the search configurations + SearchFactory::_('Config')->table_name = $tableName; + SearchFactory::_('Config')->search_value = $searchValue; + SearchFactory::_('Config')->match_case = 0; + SearchFactory::_('Config')->whole_word = 0; + SearchFactory::_('Config')->regex_search = 0; + SearchFactory::_('Config')->component_id = 0; + + if (($items = SearchFactory::_('Agent')->find()) !== null) + { + echo JText::sprintf('COM_COMPONENTBUILDER_WE_FOUND_SOME_INSTANCES_IN_S', $tableName) . '<br /><pre>'; + var_dump($items); + echo '</pre>'; + } + else + { + echo JText::sprintf('COM_COMPONENTBUILDER_NO_INSTANCES_WHERE_FOUND_S', $tableName); + } + ?> </div> <input type="hidden" name="task" value="" /> <?php echo JHtml::_('form.token'); ?> diff --git a/componentbuilder.xml b/componentbuilder.xml index 522cc8fa3..112cdbfe8 100644 --- a/componentbuilder.xml +++ b/componentbuilder.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <extension type="component" version="4" method="upgrade"> <name>COM_COMPONENTBUILDER</name> - <creationDate>14th September, 2022</creationDate> + <creationDate>16th September, 2022</creationDate> <author>Llewellyn van der Merwe</author> <authorEmail>joomla@vdm.io</authorEmail> <authorUrl>https://dev.vdm.io</authorUrl> diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent.php index 34a5b8c5b..1708f1046 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent.php @@ -125,7 +125,7 @@ class Agent $set++; } - return $this->search->found($table); + return $this->search->get($table); } /** diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Replace.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Replace.php index c0de189bf..f96de3d4d 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Replace.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Replace.php @@ -117,7 +117,7 @@ class Replace implements ReplaceInterface { foreach ($item as $field => $value) { - if ($field !== 'id' && ($_value = $this->update->value($value, $id, $field, $table)) !== null) + if ($field !== 'id' && ($_value = $this->update->value($value)) !== null) { if (empty($this->updated[$table][$id])) { diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Search.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Search.php index 3aac163b5..4c0adb634 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Search.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Search.php @@ -12,9 +12,11 @@ namespace VDM\Joomla\Componentbuilder\Search\Agent; +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Componentbuilder\Search\Factory; -use VDM\Joomla\Componentbuilder\Search\Config; -use VDM\Joomla\Componentbuilder\Search\Table; +use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface as SearchEngine; +use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchInterface; /** @@ -22,52 +24,265 @@ use VDM\Joomla\Componentbuilder\Search\Table; * * @since 3.2.0 */ -class Search +class Search implements SearchInterface { /** - * Search Config + * Search results found * - * @var Config + * @var array * @since 3.2.0 */ - protected Config $config; + protected array $found = []; /** - * Table + * Search Engine * - * @var Table + * @var SearchEngine * @since 3.2.0 */ - protected Table $table; + protected SearchEngine $search; /** * Constructor * - * @param Config|null $config The search config object. - * @param Table|null $table The search table object. + * @param SearchEngine|null $search The search engine object. * * @since 3.2.0 */ - public function __construct(?Config $config = null, ?Table $table = null) + public function __construct(?SearchEngine $search = null) { - $this->config = $config ?: Factory::_('Config'); - $this->table = $table ?: Factory::_('Table'); + $this->search = $search ?: Factory::_('Search'); + } + + /** + * Get found values + * + * @param string $table The table being searched + * + * @return array|null + * @since 3.2.0 + */ + public function get(string $table): ?array + { + if (isset($this->found[$table])) + { + return $this->found[$table]; + } + + return null; } /** * Search inside a value * * @param mixed $value The field value - * @param int $id The item ID - * @param string $field The field key - * @param string|null $table The table + * @param int $id The item ID + * @param string $field The field key + * @param string $table The table * * @return bool * @since 3.2.0 */ - public function value($value, int $id, string $field, ?string $table = null): bool + public function value($value, int $id, string $field, string $table): bool { - return true; + // search the mixed value + $found = $this->searchValue($value); + + // check if we found any match + if (ArrayHelper::check($found)) + { + foreach ($found as $line => $line_value) + { + // may not be needed... but being old school + $this->prep($id, $field, $table); + + // load the detail into our multidimensional array... lol + // Table->Item_id->Field_name->Line_number = marked_full_line + // Search Example: soon... + // Marked Line Example: Soon.... + $this->found[$table][$id][$field][$line] = $line_value; + } + return true; + } + + return false; + } + + /** + * Empty the found values + * + * @param string $table The table being searched + * + * @return void + * @since 3.2.0 + */ + public function reset(string $table) + { + unset($this->found[$table]); + } + + /** + * Search inside a string + * + * @param mixed $value The field value + * + * @return array|null + * @since 3.2.0 + */ + protected function searchValue($value): ?array + { + // check if this is an array + $found = null; + + // I know this is a little crazy... TODO refactor into recursion functions + // the possibility of searching sub-forms in sub-forms + if (ArrayHelper::check($value)) + { + // first layer + foreach ($value as $keys => $rows) + { + if (ArrayHelper::check($rows)) + { + // second layer + foreach ($rows as $key => $row) + { + if (ArrayHelper::check($row)) + { + // third layer + foreach ($row as $ke => $ro) + { + if (ArrayHelper::check($ro)) + { + // forth layer + foreach ($ro as $k => $r) + { + if (StringHelper::check($r)) + { + if (($_found = $this->string($r)) !== null) + { + foreach ($_found as $_n => $_f) + { + $found[$keys . '.' . $key . '.' . $ke . '.' . $k . '.' . $_n] = $_f; + } + } + } + } + } + elseif (StringHelper::check($ro)) + { + if (($_found = $this->string($ro)) !== null) + { + foreach ($_found as $_n => $_f) + { + $found[$keys. '.' . $key . '.' . $ke . '.' . $_n] = $_f; + } + } + } + + } + } + elseif (StringHelper::check($row)) + { + if (($_found = $this->string($row)) !== null) + { + foreach ($_found as $_n => $_f) + { + $found[$keys. '.' . $key . '.' . $_n] = $_f; + } + } + } + } + } + elseif (StringHelper::check($rows)) + { + if (($_found = $this->string($rows)) !== null) + { + foreach ($_found as $_n => $_f) + { + $found[$keys. '.' . $_n] = $_f; + } + } + } + } + } + elseif (StringHelper::check($value)) + { + $found = $this->string($value); + } + + return $found; + } + + /** + * Search inside a string + * + * @param string $value The field value + * + * @return array|null + * @since 3.2.0 + */ + protected function string(string $value): ?array + { + // line counter + $line = 1; + + // check if string has a new line + if (\preg_match('/\R/', $value)) + { + $search_array = \preg_split('/\R/', $value); + + // start search bucket + $found = []; + + // loop over the lines + foreach ($search_array as $line_value) + { + if (($_found = $this->search->string($line_value)) !== null) + { + $found[$line] = $_found; + } + + // next line + $line++; + } + + if (ArrayHelper::check($found)) + { + return $found; + } + } + elseif (($found = $this->search->string($value)) !== null) + { + return [$line => $found]; + } + + return null; + } + + /** + * Prep the bucket + * + * @param int $id The item ID + * @param string $field The field key + * @param string $table The table + * + * @return void + * @since 3.2.0 + */ + protected function prep(int $id, string $field, string $table) + { + if (empty($this->found[$table])) + { + $this->found[$table] = []; + } + if (empty($this->found[$table][$id])) + { + $this->found[$table][$id] = []; + } + if (empty($this->found[$table][$id][$field])) + { + $this->found[$table][$id][$field] = []; + } } } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Update.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Update.php index b253e4bbd..635593ac0 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Update.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Agent/Update.php @@ -12,9 +12,10 @@ namespace VDM\Joomla\Componentbuilder\Search\Agent; +use VDM\Joomla\Utilities\ArrayHelper; +use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Componentbuilder\Search\Factory; -use VDM\Joomla\Componentbuilder\Search\Config; -use VDM\Joomla\Componentbuilder\Search\Table; +use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface as SearchEngine; /** @@ -25,49 +26,113 @@ use VDM\Joomla\Componentbuilder\Search\Table; class Update { /** - * Search Config + * Search Engine * - * @var Config + * @var SearchEngine * @since 3.2.0 */ - protected Config $config; - - /** - * Table - * - * @var Table - * @since 3.2.0 - */ - protected Table $table; + protected SearchEngine $search; /** * Constructor * - * @param Config|null $config The search config object. - * @param Table|null $table The search table object. + * @param SearchEngine|null $search The search engine object. * * @since 3.2.0 */ - public function __construct(?Config $config = null, ?Table $table = null) + public function __construct(?SearchEngine $search = null) { - $this->config = $config ?: Factory::_('Config'); - $this->table = $table ?: Factory::_('Table'); + $this->search = $search ?: Factory::_('Search'); } /** - * Update value + * Update the value * - * @param mixed $value The field value - * @param int $id The item ID - * @param string $field The field key - * @param string|null $table The table + * @param mixed $value The field value + * @param int $line The line to update (0 = all) * * @return mixed * @since 3.2.0 */ - public function value($value, int $id, string $field, ?string $table = null) + public function value($value, int $line = 0) { - return $value; + // update the value + $update = $this->updateValue($value, $line); + + // was anything updated + if ($value === $update) + { + return null; + } + + return $update; + } + + /** + * Update all search-replace instances inside a value + * + * @param mixed $value The field value + * @param int $line The line to update (0 = all) + * + * @return mixed + * @since 3.2.0 + */ + protected function updateValue($value, int $line = 0) + { + if (ArrayHelper::check($value)) + { + echo '<pre>'; var_dump($value); exit; + } + elseif (StringHelper::check($value)) + { + return $this->string($value, $line); + } + else + { + // this should not happen + echo '<pre>Error:<br />'; var_dump($value); exit; + } + } + + /** + * Update all search-replace instances inside a string + * + * @param string $value The field value + * @param int $line The line to update (0 = all) + * + * @return string + * @since 3.2.0 + */ + protected function string(string $value, int $line = 0): string + { + // check if string has a new line + if (\preg_match('/\R/', $value) && $line > 0) + { + // line counter + $line_number = 1; + + $search_array = \preg_split('/\R/', $value); + + // loop over the lines + foreach ($search_array as $nr => $line_value) + { + if ($line_number == $line) + { + $search_array[$nr] = $this->search->replace($line_value); + + // since we are targeting on line (and possibly one number) + // this can only happen once, and so we return at this point + return implode(PHP_EOL, $search_array); + } + // next line + $line_number++; + } + + // no update took place so we just return the original value + return $value; + } + + return $this->search->replace($value); } } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Config.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Config.php index 83e423980..a3a0eb8a8 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Config.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Config.php @@ -25,10 +25,10 @@ class Config extends BaseConfig /** * get posted search value * - * @return string Raw search value + * @return string|null Raw search value * @since 3.2.0 */ - protected function getSearchvalue(): string + protected function getSearchvalue(): ?string { return $this->input->post->get('search_value', null, 'RAW'); } @@ -36,10 +36,10 @@ class Config extends BaseConfig /** * get posted replace value * - * @return string Raw replace value + * @return string|null Raw replace value * @since 3.2.0 */ - protected function getReplacevalue(): string + protected function getReplacevalue(): ?string { return $this->input->post->get('replace_value', null, 'RAW'); } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/FindInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/FindInterface.php index d8bca4d6b..a1a8a1fc2 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/FindInterface.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/FindInterface.php @@ -60,6 +60,7 @@ interface FindInterface * @return void * @since 3.2.0 */ - public function reset(?string $table = null); + public function reset(?string $table = null); + } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/ModelInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/ModelInterface.php index c0aa6a2a2..e104b7f31 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/ModelInterface.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/ModelInterface.php @@ -34,15 +34,15 @@ interface ModelInterface /** * Model the values of an item - * Example: $this->item('table_name', Object); + * Example: $this->item(Object, 'table_name'); * - * @param string $table The table - * @param object $item The item object + * @param object $item The item object + * @param string|null $table The table * - * @return object + * @return object|null * @since 3.2.0 */ - public function item(object $item, ?string $table = null): object; + public function item(object $item, ?string $table = null): ?object; /** * Model the values of multiple items diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchInterface.php new file mode 100644 index 000000000..25a1a17bc --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchInterface.php @@ -0,0 +1,56 @@ +<?php +/** + * @package Joomla.Component.Builder + * + * @created 30th April, 2015 + * @author Llewellyn van der Merwe <https://dev.vdm.io> + * @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder> + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Componentbuilder\Search\Interfaces; + + +/** + * Search Interface + * + * @since 3.2.0 + */ +interface SearchInterface +{ + /** + * Get found values + * + * @param string $table The table being searched + * + * @return array|null + * @since 3.2.0 + */ + public function get(string $table): ?array; + + /** + * Search inside a value + * + * @param mixed $value The field value + * @param int $id The item ID + * @param string $field The field key + * @param string $table The table + * + * @return bool + * @since 3.2.0 + */ + public function value($value, int $id, string $field, string $table): bool; + + /** + * Empty the found values + * + * @param string $table The table being searched + * + * @return void + * @since 3.2.0 + */ + public function reset(string $table); + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchTypeInterface.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchTypeInterface.php new file mode 100644 index 000000000..9f3408b8e --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Interfaces/SearchTypeInterface.php @@ -0,0 +1,43 @@ +<?php +/** + * @package Joomla.Component.Builder + * + * @created 30th April, 2015 + * @author Llewellyn van der Merwe <https://dev.vdm.io> + * @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder> + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Componentbuilder\Search\Interfaces; + + +/** + * Search Type Interface + * + * @since 3.2.0 + */ +interface SearchTypeInterface +{ + /** + * Search inside a string + * + * @param string $value The string value + * + * @return string|null The marked string if found, else null + * @since 3.2.0 + */ + public function string(string $value): ?string; + + /** + * Replace found instances inside string value + * + * @param string $value The string value to update + * + * @return string The updated string + * @since 3.2.0 + */ + public function replace(string $value): string; + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model.php index 7e5cc2984..83b0f5f40 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model.php @@ -12,10 +12,11 @@ namespace VDM\Joomla\Componentbuilder\Search; +use VDM\Joomla\Utilities\StringHelper; +use VDM\Joomla\Utilities\ArrayHelper; use VDM\Joomla\Componentbuilder\Search\Factory; use VDM\Joomla\Componentbuilder\Search\Config; use VDM\Joomla\Componentbuilder\Search\Table; -use VDM\Joomla\Utilities\ArrayHelper; /** @@ -65,15 +66,15 @@ abstract class Model /** * Model the values of an item - * Example: $this->item(Object, 'table_name'); + * Example: $this->item('table_name', Object); * - * @param object $item The item object + * @param object $item The item object * @param string|null $table The table * - * @return object + * @return object|null * @since 3.2.0 */ - public function item(object $item, ?string $table = null): object + public function item(object $item, ?string $table = null): ?object { // set the table name if (empty($table)) @@ -81,19 +82,39 @@ abstract class Model $table = $this->config->table_name; } + // field counter + $field_number = 0; + // check if this is a valid table if (($fields = $this->table->fields($table)) !== null) { foreach ($fields as $field) { + // model a value if it exists if(isset($item->{$field})) { $item->{$field} = $this->value($item->{$field}, $field, $table); + + // remove empty values + if (!StringHelper::check($item->{$field}) && !ArrayHelper::check($item->{$field}, true)) + { + unset($item->{$field}); + } + else + { + $field_number++; + } } } } - return $item; + // all items must have more than one field or its empty (1 = id) + if ($field_number > 1) + { + return $item; + } + + return null; } /** @@ -120,14 +141,24 @@ abstract class Model foreach ($items as $id => &$item) { // model the item - $item = $this->item($item, $table); + if (($item = $this->item($item, $table)) !== null) + { + // add the last ID + $this->last[$table] = $item->id; + } + else + { + unset($items[$id]); + } + } - // add the last ID - $this->last[$table] = $item->id; + if (ArrayHelper::check($items)) + { + return $items; } } - return $items; + return null; } /** diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model/Get.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model/Get.php index 4f5b3d756..de3e80407 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model/Get.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Model/Get.php @@ -12,6 +12,8 @@ namespace VDM\Joomla\Componentbuilder\Search\Model; +use VDM\Joomla\Utilities\JsonHelper; +use VDM\Joomla\Utilities\StringHelper; use VDM\Joomla\Componentbuilder\Search\Interfaces\ModelInterface; use VDM\Joomla\Componentbuilder\Search\Model; @@ -43,7 +45,7 @@ class Get extends Model implements ModelInterface } // check if this is a valid table - if (($store = $this->table->get($table, $field, 'store')) !== null) + if (StringHelper::check($value) && ($store = $this->table->get($table, $field, 'store')) !== null) { // open the value based on the store method switch($store) @@ -52,7 +54,11 @@ class Get extends Model implements ModelInterface $value = \base64_decode($value); break; case 'json': - $value = \json_decode($value, true); + // check if there is a json string + if (JsonHelper::check($value)) + { + $value = \json_decode($value, true); + } break; } } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Agent.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Agent.php index d487ab809..41f8966d4 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Agent.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Agent.php @@ -117,8 +117,7 @@ class Agent implements ServiceProviderInterface public function getSearch(Container $container): Search { return new Search( - $container->get('Config'), - $container->get('Table') + $container->get('Search') ); } @@ -133,8 +132,7 @@ class Agent implements ServiceProviderInterface public function getUpdate(Container $container): Update { return new Update( - $container->get('Config'), - $container->get('Table') + $container->get('Search') ); } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Search.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Search.php index 6b26bf9aa..3eac97b83 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Search.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Service/Search.php @@ -16,6 +16,9 @@ use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use VDM\Joomla\Componentbuilder\Search\Config; use VDM\Joomla\Componentbuilder\Search\Table; +use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface as SearchEngine; +use VDM\Joomla\Componentbuilder\Search\Type\Regex; +use VDM\Joomla\Componentbuilder\Search\Type\Basic; /** @@ -25,6 +28,14 @@ use VDM\Joomla\Componentbuilder\Search\Table; */ class Search implements ServiceProviderInterface { + /** + * Selected search engine + * + * @var int + * @since 3.2.0 + **/ + protected $searchEngine = 101; + /** * Registers the service provider with a DI container. * @@ -40,6 +51,15 @@ class Search implements ServiceProviderInterface $container->alias(Table::class, 'Table') ->share('Table', [$this, 'getTable'], true); + + $container->alias(Regex::class, 'Search.Regex') + ->share('Search.Regex', [$this, 'getRegex'], true); + + $container->alias(Basic::class, 'Search.Basic') + ->share('Search.Basic', [$this, 'getBasic'], true); + + $container->alias(SearchEngine::class, 'Search') + ->share('Search', [$this, 'getSearch'], true); } /** @@ -69,6 +89,63 @@ class Search implements ServiceProviderInterface $container->get('Config') ); } + + /** + * Get the Regex Type Search Engine + * + * @param Container $container The DI container. + * + * @return Regex + * @since 3.2.0 + */ + public function getRegex(Container $container): Regex + { + return new Regex( + $container->get('Config') + ); + } + + /** + * Get the Basic Type Search Engine + * + * @param Container $container The DI container. + * + * @return Basic + * @since 3.2.0 + */ + public function getBasic(Container $container): Basic + { + return new Basic( + $container->get('Config') + ); + } + + /** + * Get the Search Engine + * + * @param Container $container The DI container. + * + * @return SearchEngine + * @since 3.2.0 + */ + public function getSearch(Container $container): SearchEngine + { + // set the search engine to use for this container + if ($this->searchEngine == 101) + { + $this->searchEngine = (int) $container->get('Config')->regex_search; + } + + // get the correct type of search engine + if ($this->searchEngine == 1) + { + return $container->get('Search.Regex'); + } + + // the default is the basic + return $container->get('Search.Basic'); + } + } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Basic.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Basic.php new file mode 100644 index 000000000..7f7d991a2 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Basic.php @@ -0,0 +1,127 @@ +<?php +/** + * @package Joomla.Component.Builder + * + * @created 30th April, 2015 + * @author Llewellyn van der Merwe <https://dev.vdm.io> + * @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder> + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Componentbuilder\Search\Type; + + +use VDM\Joomla\Componentbuilder\Search\Factory; +use VDM\Joomla\Componentbuilder\Search\Config; +use VDM\Joomla\Utilities\StringHelper; +use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface; + + +/** + * Search Type String + * + * @since 3.2.0 + */ +class Basic implements SearchTypeInterface +{ + /** + * Search Config + * + * @var Config + * @since 3.2.0 + */ + protected Config $config; + + /** + * Search Value + * + * @var string|null + * @since 3.2.0 + */ + protected ?string $searchValue; + + /** + * Replace Value + * + * @var string|null + * @since 3.2.0 + */ + protected ?string $replaceValue; + + /** + * Search Should Match Case + * + * @var int + * @since 3.2.0 + */ + protected int $matchCase = 0; + + /** + * Search Should Match Whole Word + * + * @var int + * @since 3.2.0 + */ + protected int $wholeWord = 0; + + /** + * Constructor + * + * @param Config|null $config The search config object. + * + * @since 3.2.0 + */ + public function __construct(?Config $config = null) + { + $this->config = $config ?: Factory::_('Config'); + + // set some class values + $this->searchValue = $this->config->search_value; + $this->replaceValue = $this->config->replace_value; // TODO + $this->matchCase = $this->config->match_case; + $this->wholeWord = $this->config->whole_word; // TODO + } + + /** + * Search inside a string + * + * @param string $value The string value + * + * @return string|null The marked string if found, else null + * @since 3.2.0 + */ + public function string(string $value): ?string + { + if (StringHelper::check($this->searchValue)) + { + if ($this->matchCase == 1) + { + if (strpos($value, $this->searchValue) !== false) + { + return trim(str_replace($this->searchValue, '{+' . '|' . '=[' . $this->searchValue . ']=' . '|' . '+}', $value)); + } + } + elseif (stripos($value, $this->searchValue) !== false) + { + return trim(str_ireplace($this->searchValue, '{+' . '|' . '=[' . $this->searchValue . ']=' . '|' . '+}', $value)); + } + } + return null; + } + + /** + * Replace found instances inside string value + * + * @param string $value The string value to update + * + * @return string The updated string + * @since 3.2.0 + */ + public function replace(string $value): string + { + return $value; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Regex.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Regex.php new file mode 100644 index 000000000..4ee4e23eb --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Regex.php @@ -0,0 +1,112 @@ +<?php +/** + * @package Joomla.Component.Builder + * + * @created 30th April, 2015 + * @author Llewellyn van der Merwe <https://dev.vdm.io> + * @git Joomla Component Builder <https://git.vdm.dev/joomla/Component-Builder> + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VDM\Joomla\Componentbuilder\Search\Type; + + +use VDM\Joomla\Componentbuilder\Search\Factory; +use VDM\Joomla\Componentbuilder\Search\Config; +use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface; + + +/** + * Search Type Regex + * + * @since 3.2.0 + */ +class Regex implements SearchTypeInterface +{ + /** + * Search Config + * + * @var Config + * @since 3.2.0 + */ + protected Config $config; + + /** + * Search Value + * + * @var string + * @since 3.2.0 + */ + protected string $searchValue; + + /** + * Replace Value + * + * @var string + * @since 3.2.0 + */ + protected string $replaceValue; + + /** + * Search Should Match Case + * + * @var int + * @since 3.2.0 + */ + protected int $matchCase = 0; + + /** + * Search Should Match Whole Word + * + * @var int + * @since 3.2.0 + */ + protected int $wholeWord = 0; + + /** + * Constructor + * + * @param Config|null $config The search config object. + * + * @since 3.2.0 + */ + public function __construct(?Config $config = null) + { + $this->config = $config ?: Factory::_('Config'); + + // set some class values + $this->searchValue = $this->config->search_value; + $this->replaceValue = $this->config->replace_value; // TODO + $this->matchCase = $this->config->match_case; + $this->wholeWord = $this->config->whole_word; // TODO + } + + /** + * Search inside a string + * + * @param string $value The string value + * + * @return string|null The marked string if found, else null + * @since 3.2.0 + */ + public function string(string $value): ?string + { + return null; + } + + /** + * Replace found instances inside string value + * + * @param string $value The string value to update + * + * @return string The updated string + * @since 3.2.0 + */ + public function replace(string $value): string + { + return $value; + } + +} + diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/index.html b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/index.html new file mode 100644 index 000000000..fa6d84e80 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/index.html @@ -0,0 +1 @@ +<html><body bgcolor="#FFFFFF"></body></html> \ No newline at end of file