From fca5bd5f420b967b3ddda0998e43abf8789cc830 Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe Date: Sat, 17 Sep 2022 23:59:31 +0200 Subject: [PATCH] Adds basic and regex search and replace types. --- README.md | 6 +- admin/README.txt | 6 +- admin/views/search/tmpl/default.php | 8 +- componentbuilder.xml | 2 +- .../src/Componentbuilder/Search/Config.php | 28 +- .../src/Componentbuilder/Search/Type.php | 113 ++++++++ .../Componentbuilder/Search/Type/Basic.php | 250 ++++++++++++++---- .../Componentbuilder/Search/Type/Regex.php | 106 +++++--- 8 files changed, 411 insertions(+), 108 deletions(-) create mode 100644 libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type.php diff --git a/README.md b/README.md index 342c18d3f..c75e3758a 100644 --- a/README.md +++ b/README.md @@ -140,13 +140,13 @@ 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*: 16th September, 2022 ++ *Last Build*: 17th 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*: **331035** ++ *Line count*: **331338** + *Field count*: **2002** -+ *File count*: **2166** ++ *File count*: **2167** + *Folder count*: **375** > This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com). diff --git a/admin/README.txt b/admin/README.txt index 342c18d3f..c75e3758a 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -140,13 +140,13 @@ 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*: 16th September, 2022 ++ *Last Build*: 17th 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*: **331035** ++ *Line count*: **331338** + *Field count*: **2002** -+ *File count*: **2166** ++ *File count*: **2167** + *Folder count*: **375** > This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](http://joomlacomponentbuilder.com). diff --git a/admin/views/search/tmpl/default.php b/admin/views/search/tmpl/default.php index 5413d57c0..3b6806e03 100644 --- a/admin/views/search/tmpl/default.php +++ b/admin/views/search/tmpl/default.php @@ -43,15 +43,15 @@ use VDM\Joomla\Componentbuilder\Search\Factory as SearchFactory;
table_name = $tableName; SearchFactory::_('Config')->search_value = $searchValue; - SearchFactory::_('Config')->match_case = 0; + SearchFactory::_('Config')->match_case = 1; SearchFactory::_('Config')->whole_word = 0; - SearchFactory::_('Config')->regex_search = 0; + SearchFactory::_('Config')->regex_search = 1; SearchFactory::_('Config')->component_id = 0; if (($items = SearchFactory::_('Agent')->find()) !== null) diff --git a/componentbuilder.xml b/componentbuilder.xml index 112cdbfe8..9e19b1461 100644 --- a/componentbuilder.xml +++ b/componentbuilder.xml @@ -1,7 +1,7 @@ COM_COMPONENTBUILDER - 16th September, 2022 + 17th September, 2022 Llewellyn van der Merwe joomla@vdm.io https://dev.vdm.io 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 a3a0eb8a8..66335b4fc 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Config.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Config.php @@ -36,12 +36,12 @@ class Config extends BaseConfig /** * get posted replace value * - * @return string|null Raw replace value + * @return string Raw replace value * @since 3.2.0 */ - protected function getReplacevalue(): ?string + protected function getReplacevalue(): string { - return $this->input->post->get('replace_value', null, 'RAW'); + return $this->input->post->get('replace_value', '', 'RAW'); } /** @@ -120,6 +120,28 @@ class Config extends BaseConfig { return $this->input->post->get('item_id', 0, 'INT'); } + + /** + * get the start marker + * + * @return string The string to use as the start marker + * @since 3.2.0 + */ + protected function getMarkerstart(): string + { + return '{+' . '|' . '=['; + } + + /** + * get the end marker + * + * @return string The string to use as the end marker + * @since 3.2.0 + */ + protected function getMarkerend(): string + { + return ']=' . '|' . '+}'; + } } diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type.php new file mode 100644 index 000000000..cfaff6418 --- /dev/null +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type.php @@ -0,0 +1,113 @@ + + * @git 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; + + +use VDM\Joomla\Componentbuilder\Search\Factory; +use VDM\Joomla\Componentbuilder\Search\Config; + + +/** + * Search Type Regex + * + * @since 3.2.0 + */ +abstract class Type +{ + /** + * 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; + + /** + * Start marker + * + * @var string + * @since 3.2.0 + */ + protected string $start = ''; + + /** + * End marker + * + * @var string + * @since 3.2.0 + */ + protected string $end = ''; + + /** + * 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 search value + $this->searchValue = $this->config->search_value; + + // set replace value + $this->replaceValue = $this->config->replace_value; + + // set match case + $this->matchCase = $this->config->match_case; + + // set whole word + $this->wholeWord = $this->config->whole_word; + + // set start marker + $this->start = $this->config->marker_start; + + // set end marker + $this->end = $this->config->marker_end; + } + +} + 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 index 7f7d991a2..f73800d65 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Basic.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Basic.php @@ -12,10 +12,11 @@ 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\Utilities\ArrayHelper; use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface; +use VDM\Joomla\Componentbuilder\Search\Type; /** @@ -23,64 +24,63 @@ use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface; * * @since 3.2.0 */ -class Basic implements SearchTypeInterface +class Basic extends Type implements SearchTypeInterface { /** - * Search Config + * Regex Search Value * - * @var Config + * @var string * @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; + protected string $regexValue = ''; /** * Constructor * - * @param Config|null $config The search config object. + * @param Config|null $config The search config object. * * @since 3.2.0 */ public function __construct(?Config $config = null) { - $this->config = $config ?: Factory::_('Config'); + parent::__construct($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 + // quote all regular expression characters + $searchValue = \preg_quote($this->searchValue); + + $start = ''; $end = ''; + + // if this is a whole word search we need to do some prep + if ($this->wholeWord == 1) + { + // get first character of search string + $first = mb_substr($this->searchValue, 0, 1); + // get last character of search string + $last = mb_substr($this->searchValue, -1); + + // set the start boundary behavior + $start = '(\b)'; + if (\preg_match("/\W/", $first)) + { + $start = '(\b|\B)'; + } + + // set the boundary behavior + $end = '(\b)'; + if (\preg_match("/\W/", $last)) + { + $end = '(\b|\B)'; + } + } + + // set search based on match case + $case = ''; + if ($this->matchCase == 0) + { + $case = 'i'; + } + + $this->regexValue = "/" . $start . '(' . $searchValue . ')' . $end . "/" . $case; } /** @@ -95,18 +95,16 @@ class Basic implements SearchTypeInterface { if (StringHelper::check($this->searchValue)) { - if ($this->matchCase == 1) + if ($this->wholeWord == 1) { - if (strpos($value, $this->searchValue) !== false) - { - return trim(str_replace($this->searchValue, '{+' . '|' . '=[' . $this->searchValue . ']=' . '|' . '+}', $value)); - } + return $this->searchWhole($value); } - elseif (stripos($value, $this->searchValue) !== false) + else { - return trim(str_ireplace($this->searchValue, '{+' . '|' . '=[' . $this->searchValue . ']=' . '|' . '+}', $value)); + return $this->searchAll($value); } } + return null; } @@ -120,6 +118,156 @@ class Basic implements SearchTypeInterface */ public function replace(string $value): string { + if (StringHelper::check($this->searchValue)) + { + if ($this->wholeWord == 1) + { + return $this->replaceWhole($value); + } + else + { + return $this->replaceAll($value); + } + } + return $value; + } + + /** + * Replace whole words + * + * @param string $value The string value + * + * @return string The marked string if found, else null + * @since 3.2.0 + */ + protected function replaceWhole(string $value): string + { + if ($this->match($value)) + { + return preg_replace( + $this->regexValue . 'm', + "$1" . $this->replaceValue . "$3", + $value + ); + } + + return $value; + } + + /** + * Search for whole words + * + * @param string $value The string value + * + * @return string|null The marked string if found, else null + * @since 3.2.0 + */ + protected function searchWhole(string $value): ?string + { + if ($this->match($value)) + { + return trim(preg_replace( + $this->regexValue . 'm', + "$1" . $this->start . "$2" . $this->end . "$3", + $value + )); + } + + return null; + } + + /** + * Math the Regular Expression + * + * @param string $value The string value + * + * @return bool true if match is found + * @since 3.0.9 + */ + public function match(string $value): bool + { + $match = []; + + preg_match($this->regexValue, $value, $match); + + $match = array_filter( + $match, + function ($found) { + return !empty($found); + } + ); + + if (ArrayHelper::check($match)) + { + return true; + } + + return false; + } + + /** + * Search for all instances + * + * @param string $value The string value + * + * @return string|null The marked string if found, else null + * @since 3.2.0 + */ + protected function searchAll(string $value): ?string + { + if ($this->matchCase == 1) + { + if (strpos($value, $this->searchValue) !== false) + { + return trim(preg_replace( + $this->regexValue . 'm', + $this->start . "$1" . $this->end, + $value + )); + } + } + elseif (stripos($value, $this->searchValue) !== false) + { + return trim(preg_replace( + $this->regexValue . 'm', + $this->start . "$1" . $this->end, + $value + )); + } + + return null; + } + + /** + * Replace for all instances + * + * @param string $value The string value + * + * @return string The marked string if found, else null + * @since 3.2.0 + */ + protected function replaceAll(string $value): string + { + if ($this->matchCase == 1) + { + if (strpos($value, $this->searchValue) !== false) + { + return preg_replace( + $this->regexValue . 'm', + $this->replaceValue, + $value + ); + } + } + elseif (stripos($value, $this->searchValue) !== false) + { + return preg_replace( + $this->regexValue . 'm', + $this->replaceValue, + $value + ); + } + 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 index 4ee4e23eb..a2b1e87ae 100644 --- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Regex.php +++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Search/Type/Regex.php @@ -12,9 +12,11 @@ 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\Utilities\ArrayHelper; use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface; +use VDM\Joomla\Componentbuilder\Search\Type; /** @@ -22,64 +24,35 @@ use VDM\Joomla\Componentbuilder\Search\Interfaces\SearchTypeInterface; * * @since 3.2.0 */ -class Regex implements SearchTypeInterface +class Regex extends Type implements SearchTypeInterface { /** - * Search Config - * - * @var Config - * @since 3.2.0 - */ - protected Config $config; - - /** - * Search Value + * Regex 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; + protected string $regexValue = ''; /** * Constructor * - * @param Config|null $config The search config object. + * @param Config|null $config The search config object. * * @since 3.2.0 */ public function __construct(?Config $config = null) { - $this->config = $config ?: Factory::_('Config'); + parent::__construct($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 + // set search based on match case + $case = ''; + if ($this->matchCase == 0) + { + $case = 'i'; + } + + $this->regexValue = "/(" . $this->searchValue . ")/" . $case; } /** @@ -92,6 +65,15 @@ class Regex implements SearchTypeInterface */ public function string(string $value): ?string { + if (StringHelper::check($this->searchValue) && $this->match($value)) + { + return trim(preg_replace( + $this->regexValue . 'm', + $this->start . "$1" . $this->end, + $value + )); + } + return null; } @@ -105,8 +87,46 @@ class Regex implements SearchTypeInterface */ public function replace(string $value): string { + if (StringHelper::check($this->searchValue) && $this->match($value)) + { + return preg_replace( + $this->regexValue . 'm', + $this->replaceValue, + $value + ); + } + return $value; } + + /** + * Math the Regular Expression + * + * @param string $value The string value + * + * @return bool true if match is found + * @since 3.0.9 + */ + public function match(string $value): bool + { + $match = []; + + preg_match($this->regexValue, $value, $match); + + $match = array_filter( + $match, + function ($found) { + return !empty($found); + } + ); + + if (ArrayHelper::check($match)) + { + return true; + } + + return false; + } }