diff --git a/README.md b/README.md
index 07db697c4..52c479f86 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*: 1st January, 2023
++ *Last Build*: 8th January, 2023
+ *Version*: 3.1.13
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
-+ *Line count*: **342047**
++ *Line count*: **344993**
+ *Field count*: **2009**
-+ *File count*: **2225**
-+ *Folder count*: **391**
++ *File count*: **2240**
++ *Folder count*: **399**
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com).
> Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)
diff --git a/admin/README.txt b/admin/README.txt
index 07db697c4..52c479f86 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*: 1st January, 2023
++ *Last Build*: 8th January, 2023
+ *Version*: 3.1.13
+ *Copyright*: Copyright (C) 2015 Vast Development Method. All rights reserved.
+ *License*: GNU General Public License version 2 or later; see LICENSE.txt
-+ *Line count*: **342047**
++ *Line count*: **344993**
+ *Field count*: **2009**
-+ *File count*: **2225**
-+ *Folder count*: **391**
++ *File count*: **2240**
++ *Folder count*: **399**
> This **component** was build with a [Joomla](https://extensions.joomla.org/extension/component-builder/) [Automated Component Builder](https://www.joomlacomponentbuilder.com).
> Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com)
diff --git a/admin/helpers/compiler/a_Get.php b/admin/helpers/compiler/a_Get.php
index 8adf46b61..a396974bf 100644
--- a/admin/helpers/compiler/a_Get.php
+++ b/admin/helpers/compiler/a_Get.php
@@ -1557,7 +1557,7 @@ class Get
// build the site_views settings
$component->site_views = array_map(
function ($array) {
- // has become a lacacy issue, can't remove this
+ // has become a legacy issue, can't remove this
$array['view'] = $array['siteview'];
$array['settings'] = $this->getCustomViewData(
$array['view']
@@ -1596,7 +1596,7 @@ class Get
// build the custom_admin_views settings
$component->custom_admin_views = array_map(
function ($array) {
- // has become a lacacy issue, can't remove this
+ // has become a legacy issue, can't remove this
$array['view'] = $array['customadminview'];
$array['settings'] = $this->getCustomViewData(
$array['view'], 'custom_admin_view'
diff --git a/admin/helpers/compiler/e_Interpretation.php b/admin/helpers/compiler/e_Interpretation.php
index c558a718a..09285183e 100644
--- a/admin/helpers/compiler/e_Interpretation.php
+++ b/admin/helpers/compiler/e_Interpretation.php
@@ -25,6 +25,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Factory as CFactory;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Placefix;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Indent;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Line;
+use VDM\Joomla\Componentbuilder\Compiler\Utilities\Minify;
/**
* Compiler class
@@ -16680,32 +16681,26 @@ class Interpretation extends Fields
$list_fileScript = '';
CFactory::_('Content')->set_($nameListCode, 'ADMIN_ADD_JAVASCRIPT_FILE', '');
}
- // minfy the script
+ // minify the script
if (CFactory::_('Config')->get('minify', 0) && isset($list_fileScript)
&& StringHelper::check($list_fileScript))
{
- // minify the fielScript javscript
- $minifier = new JS;
- $minifier->add($list_fileScript);
- $list_fileScript = $minifier->minify();
+ // minify the fileScript javascript
+ $list_fileScript = Minify::js($list_fileScript);
}
- // minfy the script
+ // minify the script
if (CFactory::_('Config')->get('minify', 0) && isset($fileScript)
&& StringHelper::check($fileScript))
{
- // minify the fielScript javscript
- $minifier = new JS;
- $minifier->add($fileScript);
- $fileScript = $minifier->minify();
+ // minify the fileScript javascript
+ $fileScript = Minify::js($fileScript);
}
- // minfy the script
+ // minify the script
if (CFactory::_('Config')->get('minify', 0) && isset($footerScript)
&& StringHelper::check($footerScript))
{
- // minify the footerScript javscript
- $minifier = new JS;
- $minifier->add($footerScript);
- $footerScript = $minifier->minify();
+ // minify the footerScript javascript
+ $footerScript = Minify::js($footerScript);
}
// make sure there is script to add
if (isset($list_fileScript)
diff --git a/admin/helpers/compiler/f_Infusion.php b/admin/helpers/compiler/f_Infusion.php
index cb026ceee..075028cca 100644
--- a/admin/helpers/compiler/f_Infusion.php
+++ b/admin/helpers/compiler/f_Infusion.php
@@ -23,6 +23,7 @@ use VDM\Joomla\Componentbuilder\Compiler\Factory as CFactory;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Placefix;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Indent;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Line;
+use VDM\Joomla\Componentbuilder\Compiler\Utilities\Minify;
/**
* Infusion class
@@ -837,12 +838,8 @@ class Infusion extends Interpretation
if (CFactory::_('Config')->get('minify', 0)
&& strpos((string) $footerScript, 'add($footerScript);
- $footerScript = $minifier->minify();
- // clear some memory
- unset($minifier);
+ // minify the script
+ $footerScript = Minify::js($footerScript);
}
CFactory::_('Content')->set_($nameListCode, 'VIEWS_FOOTER_SCRIPT', PHP_EOL . '");
diff --git a/admin/helpers/componentbuilder.php b/admin/helpers/componentbuilder.php
index 97cede206..df9820666 100644
--- a/admin/helpers/componentbuilder.php
+++ b/admin/helpers/componentbuilder.php
@@ -24,7 +24,9 @@ spl_autoload_register(function ($class) {
// project-specific base directories and namespace prefix
$search = [
'libraries/jcb_powers/VDM.Joomla' => 'VDM\\Joomla',
- 'libraries/jcb_powers/VDM.Gitea' => 'VDM\\Gitea'
+ 'libraries/jcb_powers/VDM.Minify' => 'VDM\\Minify',
+ 'libraries/jcb_powers/VDM.Gitea' => 'VDM\\Gitea',
+ 'libraries/jcb_powers/VDM.Psr' => 'VDM\\Psr'
];
// Start the search and load if found
$found = false;
@@ -1078,8 +1080,6 @@ abstract class ComponentbuilderHelper
{
// import the Joomla librarys
jimport('joomla.application.component.modellist');
- // include class to minify js
- require_once JPATH_ADMINISTRATOR.'/components/com_componentbuilder/helpers/js.php';
}
// load only if smart
if ('smart' === $type)
diff --git a/admin/helpers/keywords_after.txt b/admin/helpers/keywords_after.txt
deleted file mode 100644
index 7ad651f54..000000000
--- a/admin/helpers/keywords_after.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-in
-public
-extends
-private
-protected
-implements
-instanceof
\ No newline at end of file
diff --git a/admin/helpers/keywords_before.txt b/admin/helpers/keywords_before.txt
deleted file mode 100644
index c63026039..000000000
--- a/admin/helpers/keywords_before.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-do
-in
-let
-new
-var
-case
-else
-enum
-void
-with
-class
-const
-yield
-delete
-export
-import
-public
-return
-static
-typeof
-extends
-package
-private
-continue
-function
-protected
-implements
-instanceof
\ No newline at end of file
diff --git a/admin/helpers/keywords_reserved.txt b/admin/helpers/keywords_reserved.txt
deleted file mode 100644
index 626306fe5..000000000
--- a/admin/helpers/keywords_reserved.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-do
-if
-in
-for
-let
-new
-try
-var
-case
-else
-enum
-eval
-null
-this
-true
-void
-with
-break
-catch
-class
-const
-false
-super
-throw
-while
-yield
-delete
-export
-import
-public
-return
-static
-switch
-typeof
-default
-extends
-finally
-package
-private
-continue
-debugger
-function
-arguments
-interface
-protected
-implements
-instanceof
\ No newline at end of file
diff --git a/admin/helpers/minify.php b/admin/helpers/minify.php
deleted file mode 100644
index b126a1f58..000000000
--- a/admin/helpers/minify.php
+++ /dev/null
@@ -1,381 +0,0 @@
-
- @github Joomla Component Builder
- @copyright Copyright (C) 2015. All Rights Reserved
- @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
-
- Builds Complex Joomla Components
-
-/-----------------------------------------------------------------------------------------------------------------------------*/
-
-// No direct access to this file
-defined('_JEXEC') or die('Restricted access');
-
-/**
- * Abstract minifier class.
- *
- * Please report bugs on https://github.com/matthiasmullie/minify/issues
- *
- * @author Matthias Mullie
- *
- * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved.
- * @license MIT License
- */
-abstract class Minify
-{
- /**
- * The data to be minified
- *
- * @var string[]
- */
- protected $data = array();
-
- /**
- * Array of patterns to match.
- *
- * @var string[]
- */
- protected $patterns = array();
-
- /**
- * This array will hold content of strings and regular expressions that have
- * been extracted from the JS source code, so we can reliably match "code",
- * without having to worry about potential "code-like" characters inside.
- *
- * @var string[]
- */
- public $extracted = array();
-
- /**
- * Init the minify class - optionally, code may be passed along already.
- */
- public function __construct(/* $data = null, ... */)
- {
- // it's possible to add the source through the constructor as well ;)
- if (func_num_args()) {
- call_user_func_array(array($this, 'add'), func_get_args());
- }
- }
-
- /**
- * Add a file or straight-up code to be minified.
- *
- * @param string $data
- */
- public function add($data /* $data = null, ... */)
- {
- // bogus "usage" of parameter $data: scrutinizer warns this variable is
- // not used (we're using func_get_args instead to support overloading),
- // but it still needs to be defined because it makes no sense to have
- // this function without argument :)
- $args = array($data) + func_get_args();
-
- // this method can be overloaded
- foreach ($args as $data) {
- // redefine var
- $data = (string) $data;
-
- // load data
- $value = $this->load($data);
- $key = ($data != $value) ? $data : count($this->data);
-
- // store data
- $this->data[$key] = $value;
- }
- }
-
- /**
- * Load data.
- *
- * @param string $data Either a path to a file or the content itself.
- * @return string
- */
- protected function load($data)
- {
- // check if the data is a file
- if (@file_exists($data) && is_file($data)) {
- $data = @file_get_contents($data);
-
- // strip BOM, if any
- if (substr($data, 0, 3) == "\xef\xbb\xbf") {
- $data = substr($data, 3);
- }
- }
-
- return $data;
- }
-
- /**
- * Save to file
- *
- * @param string $content The minified data.
- * @param string $path The path to save the minified data to.
- * @throws Exception
- */
- protected function save($content, $path)
- {
- // create file & open for writing
- if (($handler = @fopen($path, 'w')) === false) {
- throw new Exception('The file "'.$path.'" could not be opened. Check if PHP has enough permissions.');
- }
-
- // write to file
- if (@fwrite($handler, $content) === false) {
- throw new Exception('The file "'.$path.'" could not be written to. Check if PHP has enough permissions.');
- }
-
- // close the file
- @fclose($handler);
- }
-
- /**
- * Minify the data & (optionally) saves it to a file.
- *
- * @param string[optional] $path Path to write the data to.
- * @return string The minified data.
- */
- public function minify($path = null)
- {
- $content = $this->execute($path);
-
- // save to path
- if ($path !== null) {
- $this->save($content, $path);
- }
-
- return $content;
- }
-
- /**
- * Minify & gzip the data & (optionally) saves it to a file.
- *
- * @param string[optional] $path Path to write the data to.
- * @param int[optional] $level Compression level, from 0 to 9.
- * @return string The minified & gzipped data.
- */
- public function gzip($path = null, $level = 9)
- {
- $content = $this->execute($path);
- $content = gzencode($content, $level, FORCE_GZIP);
-
- // save to path
- if ($path !== null) {
- $this->save($content, $path);
- }
-
- return $content;
- }
-
- /**
- * Minify the data.
- *
- * @param string[optional] $path Path to write the data to.
- * @return string The minified data.
- */
- abstract protected function execute($path = null);
-
- /**
- * Register a pattern to execute against the source content.
- *
- * @param string $pattern PCRE pattern.
- * @param string|callable $replacement Replacement value for matched pattern.
- * @throws Exception
- */
- protected function registerPattern($pattern, $replacement = '')
- {
- // study the pattern, we'll execute it more than once
- $pattern .= 'S';
-
- $this->patterns[] = array($pattern, $replacement);
- }
-
- /**
- * We can't "just" run some regular expressions against JavaScript: it's a
- * complex language. E.g. having an occurrence of // xyz would be a comment,
- * unless it's used within a string. Of you could have something that looks
- * like a 'string', but inside a comment.
- * The only way to accurately replace these pieces is to traverse the JS one
- * character at a time and try to find whatever starts first.
- *
- * @param string $content The content to replace patterns in.
- * @return string The (manipulated) content.
- */
- protected function replace($content)
- {
- $processed = '';
- $positions = array_fill(0, count($this->patterns), -1);
- $matches = array();
-
- while ($content) {
- // find first match for all patterns
- foreach ($this->patterns as $i => $pattern) {
- list($pattern, $replacement) = $pattern;
-
- // no need to re-run matches that are still in the part of the
- // content that hasn't been processed
- if ($positions[$i] >= 0) {
- continue;
- }
-
- $match = null;
- if (preg_match($pattern, $content, $match)) {
- $matches[$i] = $match;
-
- // we'll store the match position as well; that way, we
- // don't have to redo all preg_matches after changing only
- // the first (we'll still know where those others are)
- $positions[$i] = strpos($content, $match[0]);
- } else {
- // if the pattern couldn't be matched, there's no point in
- // executing it again in later runs on this same content;
- // ignore this one until we reach end of content
- unset($matches[$i]);
- $positions[$i] = strlen($content);
- }
- }
-
- // no more matches to find: everything's been processed, break out
- if (!$matches) {
- $processed .= $content;
- break;
- }
-
- // see which of the patterns actually found the first thing (we'll
- // only want to execute that one, since we're unsure if what the
- // other found was not inside what the first found)
- $discardLength = min($positions);
- $firstPattern = array_search($discardLength, $positions);
- $match = $matches[$firstPattern][0];
-
- // execute the pattern that matches earliest in the content string
- list($pattern, $replacement) = $this->patterns[$firstPattern];
- $replacement = $this->replacePattern($pattern, $replacement, $content);
-
- // figure out which part of the string was unmatched; that's the
- // part we'll execute the patterns on again next
- $content = substr($content, $discardLength);
- $unmatched = (string) substr($content, strpos($content, $match) + strlen($match));
-
- // move the replaced part to $processed and prepare $content to
- // again match batch of patterns against
- $processed .= substr($replacement, 0, strlen($replacement) - strlen($unmatched));
- $content = $unmatched;
-
- // first match has been replaced & that content is to be left alone,
- // the next matches will start after this replacement, so we should
- // fix their offsets
- foreach ($positions as $i => $position) {
- $positions[$i] -= $discardLength + strlen($match);
- }
- }
-
- return $processed;
- }
-
- /**
- * This is where a pattern is matched against $content and the matches
- * are replaced by their respective value.
- * This function will be called plenty of times, where $content will always
- * move up 1 character.
- *
- * @param string $pattern Pattern to match.
- * @param string|callable $replacement Replacement value.
- * @param string $content Content to match pattern against.
- * @return string
- */
- protected function replacePattern($pattern, $replacement, $content)
- {
- if (is_callable($replacement)) {
- return preg_replace_callback($pattern, $replacement, $content, 1, $count);
- } else {
- return preg_replace($pattern, $replacement, $content, 1, $count);
- }
- }
-
- /**
- * Strings are a pattern we need to match, in order to ignore potential
- * code-like content inside them, but we just want all of the string
- * content to remain untouched.
- *
- * This method will replace all string content with simple STRING#
- * placeholder text, so we've rid all strings from characters that may be
- * misinterpreted. Original string content will be saved in $this->extracted
- * and after doing all other minifying, we can restore the original content
- * via restoreStrings()
- *
- * @param string[optional] $chars
- */
- protected function extractStrings($chars = '\'"')
- {
- // PHP only supports $this inside anonymous functions since 5.4
- $minifier = $this;
- $callback = function ($match) use ($minifier) {
- if (!$match[1]) {
- /*
- * Empty strings need no placeholder; they can't be confused for
- * anything else anyway.
- * But we still needed to match them, for the extraction routine
- * to skip over this particular string.
- */
- return $match[0];
- }
-
- $count = count($minifier->extracted);
- $placeholder = $match[1].$count.$match[1];
- $minifier->extracted[$placeholder] = $match[1].$match[2].$match[1];
-
- return $placeholder;
- };
-
- /*
- * The \\ messiness explained:
- * * Don't count ' or " as end-of-string if it's escaped (has backslash
- * in front of it)
- * * Unless... that backslash itself is escaped (another leading slash),
- * in which case it's no longer escaping the ' or "
- * * So there can be either no backslash, or an even number
- * * multiply all of that times 4, to account for the escaping that has
- * to be done to pass the backslash into the PHP string without it being
- * considered as escape-char (times 2) and to get it in the regex,
- * escaped (times 2)
- */
- $this->registerPattern('/(['.$chars.'])(.*?((?extracted.
- *
- * @param string $content
- * @return string
- */
- protected function restoreExtractedData($content)
- {
- if (!$this->extracted) {
- // nothing was extracted, nothing to restore
- return $content;
- }
-
- $content = strtr($content, $this->extracted);
-
- $this->extracted = array();
-
- return $content;
- }
-}
diff --git a/admin/helpers/operators_after.txt b/admin/helpers/operators_after.txt
deleted file mode 100644
index 68b7943d3..000000000
--- a/admin/helpers/operators_after.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-+
--
-*
-/
-%
-=
-+=
--=
-*=
-/=
-%=
-<<=
->>=
->>>=
-&=
-^=
-|=
-&
-|
-^
-~
-<<
->>
->>>
-==
-===
-!=
-!==
->
-<
->=
-<=
-&&
-||
-.
-[
-]
-?
-:
-,
-;
-(
-)
-{
-}
\ No newline at end of file
diff --git a/admin/helpers/operators_before.txt b/admin/helpers/operators_before.txt
deleted file mode 100644
index 3bc220ac7..000000000
--- a/admin/helpers/operators_before.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-+
--
-*
-/
-%
-=
-+=
--=
-*=
-/=
-%=
-<<=
->>=
->>>=
-&=
-^=
-|=
-&
-|
-^
-~
-<<
->>
->>>
-==
-===
-!=
-!==
->
-<
->=
-<=
-&&
-||
-!
-.
-[
-?
-:
-,
-;
-(
-{
\ No newline at end of file
diff --git a/admin/sql/install.mysql.utf8.sql b/admin/sql/install.mysql.utf8.sql
index d650c8a0d..33e76ec24 100644
--- a/admin/sql/install.mysql.utf8.sql
+++ b/admin/sql/install.mysql.utf8.sql
@@ -1980,11 +1980,11 @@ INSERT INTO `#__componentbuilder_power` (`id`, `add_head`, `description`, `exten
(10, 1, 'Control the naming of a field\r\n\r\n@since 3.0.9', '', '', '9ef0eb24-aae4-4f5a-99af-d724db44808f', 'dXNlIEpvb21sYVxDTVNcQ29tcG9uZW50XENvbXBvbmVudEhlbHBlcjs=', '', '', '{}', 'CS8qKg0KCSAqIFRoZSBmaWVsZCBidWlsZGVyIHN3aXRjaA0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwcm90ZWN0ZWQgc3RhdGljICRidWlsZGVyID0gZmFsc2U7DQoNCgkvKioNCgkgKiBNYWtpbmcgZmllbGQgbmFtZXMgc2FmZQ0KCSAqDQoJICogQGlucHV0CXN0cmluZyAgICAgICBUaGUgc3RyaW5nIHlvdSB3b3VsZCBsaWtlIHRvIG1ha2Ugc2FmZQ0KCSAqIEBpbnB1dAlib29sZWFuICAgICAgVGhlIHN3aXRjaCB0byByZXR1cm4gYW4gQUxMIFVQUEVSIENBU0Ugc3RyaW5nDQoJICogQGlucHV0CXN0cmluZyAgICAgICBUaGUgc3RyaW5nIHRvIHVzZSBpbiB3aGl0ZSBzcGFjZQ0KCSAqDQoJICogQHJldHVybnMgc3RyaW5nIG9uIHN1Y2Nlc3MNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBzYWZlKCRzdHJpbmcsICRhbGxjYXAgPSBmYWxzZSwgJHNwYWNlciA9ICdfJykNCgl7DQoJCS8vIGdldCBnbG9iYWwgdmFsdWUNCgkJaWYgKHNlbGY6OiRidWlsZGVyID09PSBmYWxzZSkNCgkJew0KCQkJc2VsZjo6JGJ1aWxkZXIgPSBIZWxwZXI6OmdldFBhcmFtcygpLT5nZXQoJ2ZpZWxkX25hbWVfYnVpbGRlcicsIDEpOw0KCQl9DQoNCgkJLy8gdXNlIHRoZSBuZXcgY29udmVudGlvbg0KCQlpZiAoMiA9PSBzZWxmOjokYnVpbGRlcikNCgkJew0KCQkJLy8gMG5seSBjb250aW51ZSBpZiB3ZSBoYXZlIGEgc3RyaW5nDQoJCQlpZiAoU3RyaW5nSGVscGVyOjpjaGVjaygkc3RyaW5nKSkNCgkJCXsNCgkJCQkvLyBjaGVjayB0aGF0IHRoZSBmaXJzdCBjaGFyYWN0ZXIgaXMgbm90IGEgbnVtYmVyDQoJCQkJaWYgKGlzX251bWVyaWMoc3Vic3RyKChzdHJpbmcpJHN0cmluZywgMCwgMSkpKQ0KCQkJCXsNCgkJCQkJJHN0cmluZyA9IFN0cmluZ0hlbHBlcjo6bnVtYmVycygkc3RyaW5nKTsNCgkJCQl9DQoNCgkJCQkvLyByZW1vdmUgYWxsIG90aGVyIHN0cmFuZ2UgY2hhcmFjdGVycw0KCQkJCSRzdHJpbmcgPSB0cmltKChzdHJpbmcpICRzdHJpbmcpOw0KCQkJCSRzdHJpbmcgPSBwcmVnX3JlcGxhY2UoJy8nLiRzcGFjZXIuJysvJywgJyAnLCAkc3RyaW5nKTsNCgkJCQkkc3RyaW5nID0gcHJlZ19yZXBsYWNlKCcvXHMrLycsICcgJywgJHN0cmluZyk7DQoNCgkJCQkvLyBUcmFuc2xpdGVyYXRlIHN0cmluZw0KCQkJCSRzdHJpbmcgPSBTdHJpbmdIZWxwZXI6OnRyYW5zbGl0ZXJhdGUoJHN0cmluZyk7DQoNCgkJCQkvLyByZW1vdmUgYWxsIGFuZCBrZWVwIG9ubHkgY2hhcmFjdGVycyBhbmQgbnVtYmVycw0KCQkJCSRzdHJpbmcgPSBwcmVnX3JlcGxhY2UoIi9bXkEtWmEtejAtOSBdLyIsICcnLCAoc3RyaW5nKSAkc3RyaW5nKTsNCg0KCQkJCS8vIHJlcGxhY2Ugd2hpdGUgc3BhY2Ugd2l0aCB1bmRlcnNjb3JlIChTQUZFU1QgT1BUSU9OKQ0KCQkJCSRzdHJpbmcgPSBwcmVnX3JlcGxhY2UoJy9ccysvJywgKHN0cmluZykgJHNwYWNlciwgJHN0cmluZyk7DQoNCgkJCQkvLyByZXR1cm4gYWxsIGNhcHMNCgkJCQlpZiAoJGFsbGNhcCkNCgkJCQl7DQoJCQkJCXJldHVybiBzdHJ0b3VwcGVyKCRzdHJpbmcpOw0KCQkJCX0NCg0KCQkJCS8vIGRlZmF1bHQgaXMgdG8gcmV0dXJuIGxvd2VyDQoJCQkJcmV0dXJuIHN0cnRvbG93ZXIoJHN0cmluZyk7DQoJCQl9DQoJCQkvLyBub3QgYSBzdHJpbmcNCgkJCXJldHVybiAnJzsNCgkJfQ0KDQoJCS8vIHJldHVybiBhbGwgY2Fwcw0KCQlpZiAoJGFsbGNhcCkNCgkJew0KCQkJcmV0dXJuIFN0cmluZ0hlbHBlcjo6c2FmZSgkc3RyaW5nLCAnVScpOw0KCQl9DQoNCgkJLy8gdXNlIHRoZSBkZWZhdWx0IChvcmlnaW5hbCBiZWhhdmlvci9jb252ZW50aW9uKQ0KCQlyZXR1cm4gU3RyaW5nSGVscGVyOjpzYWZlKCRzdHJpbmcpOw0KCX0NCg==', '{}', 'FieldHelper', 'VDM\\Joomla\\Utilities.String.FieldHelper', '1.0.0', '{}', 'String Field Helper', 'abstract class', '{\"use_selection0\":{\"use\":\"1f28cb53-60d9-4db1-b517-3c7dc6b429ef\",\"as\":\"default\"},\"use_selection1\":{\"use\":\"640b5352-fb09-425f-a26e-cd44eda03f15\",\"as\":\"default\"}}', '', 1, '2022-03-08 20:46:56', '2023-01-14 18:06:18', 22, 5),
(11, '', 'The json checker\r\n\r\n@since 3.0.9', '', '', '4b225c51-d293-48e4-b3f6-5136cf5c3f18', '', '', '', '{\"load_selection0\":{\"load\":\"1f28cb53-60d9-4db1-b517-3c7dc6b429ef\"},\"load_selection1\":{\"load\":\"0a59c65c-9daf-4bc9-baf4-e063ff9e6a8a\"},\"load_selection2\":{\"load\":\"db87c339-5bb6-4291-a7ef-2c48ea1b06bc\"}}', 'CS8qKg0KCSAqIENoZWNrIGlmIHlvdSBoYXZlIGEganNvbiBzdHJpbmcNCgkgKg0KCSAqIEBpbnB1dCAgICBzdHJpbmcgICRzdHJpbmcgIFRoZSBqc29uIHN0cmluZyB0byBjaGVjaw0KCSAqDQoJICogQHJldHVybnMgYm9vbCB0cnVlIG9uIHN1Y2Nlc3MNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBjaGVjaygkc3RyaW5nKTogYm9vbA0KCXsNCgkJaWYgKFN0cmluZ0hlbHBlcjo6Y2hlY2soJHN0cmluZykpDQoJCXsNCgkJCWpzb25fZGVjb2RlKChzdHJpbmcpICRzdHJpbmcpOw0KCQkJcmV0dXJuIChqc29uX2xhc3RfZXJyb3IoKSA9PT0gSlNPTl9FUlJPUl9OT05FKTsNCgkJfQ0KDQoJCXJldHVybiBmYWxzZTsNCgl9DQoNCgkvKioNCgkgKiBDb252ZXJ0IGEganNvbiBvYmplY3QgdG8gYSBzdHJpbmcNCgkgKg0KCSAqIEBpbnB1dCAgICBzdHJpbmcgICR2YWx1ZSAgVGhlIGpzb24gc3RyaW5nIHRvIGNvbnZlcnQNCgkgKg0KCSAqIEByZXR1cm5zIGEgc3RyaW5nDQoJICogDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gc3RyaW5nKCR2YWx1ZSwgJHNlcGFyYXRvciA9ICIsICIsICR0YWJsZSA9IG51bGwsICRpZCA9ICdpZCcsICRuYW1lID0gJ25hbWUnKQ0KCXsNCgkJLy8gZG8gc29tZSB0YWJsZSBmb290IHdvcmsNCgkJJGV4dGVybmFsID0gZmFsc2U7DQoJCWlmIChpc19zdHJpbmcoJHRhYmxlKSAmJiBzdHJwb3MoKHN0cmluZykgJHRhYmxlLCAnI19fJykgIT09IGZhbHNlKQ0KCQl7DQoJCQkkZXh0ZXJuYWwgPSB0cnVlOw0KCQkJJHRhYmxlID0gc3RyX3JlcGxhY2UoJyNfXycsICcnLCAoc3RyaW5nKSAkdGFibGUpOw0KCQl9DQoNCgkJLy8gY2hlY2sgaWYgc3RyaW5nIGlzIEpTT04NCgkJJHJlc3VsdCA9IGpzb25fZGVjb2RlKChzdHJpbmcpICR2YWx1ZSwgdHJ1ZSk7DQoJCWlmIChqc29uX2xhc3RfZXJyb3IoKSA9PT0gSlNPTl9FUlJPUl9OT05FKQ0KCQl7DQoJCQkvLyBpcyBKU09ODQoJCQlpZiAoQXJyYXlIZWxwZXI6OmNoZWNrKCRyZXN1bHQpKQ0KCQkJew0KCQkJCWlmIChTdHJpbmdIZWxwZXI6OmNoZWNrKCR0YWJsZSkpDQoJCQkJew0KCQkJCQkkbmFtZXMgPSBhcnJheSgpOw0KCQkJCQlmb3JlYWNoICgkcmVzdWx0IGFzICR2YWwpDQoJCQkJCXsNCgkJCQkJCWlmICgkZXh0ZXJuYWwpDQoJCQkJCQl7DQoJCQkJCQkJaWYgKCRfbmFtZSA9IEdldEhlbHBlcjo6dmFyKG51bGwsICR2YWwsICRpZCwgJG5hbWUsICc9JywgJHRhYmxlKSkNCgkJCQkJCQl7DQoJCQkJCQkJCSRuYW1lc1tdID0gJF9uYW1lOw0KCQkJCQkJCX0NCgkJCQkJCX0NCgkJCQkJCWVsc2UNCgkJCQkJCXsNCgkJCQkJCQlpZiAoJF9uYW1lID0gR2V0SGVscGVyOjp2YXIoJHRhYmxlLCAkdmFsLCAkaWQsICRuYW1lKSkNCgkJCQkJCQl7DQoJCQkJCQkJCSRuYW1lc1tdID0gJF9uYW1lOw0KCQkJCQkJCX0NCgkJCQkJCX0NCgkJCQkJfQ0KCQkJCQlpZiAoQXJyYXlIZWxwZXI6OmNoZWNrKCRuYW1lcykpDQoJCQkJCXsNCgkJCQkJCXJldHVybiAoc3RyaW5nKSBpbXBsb2RlKCRzZXBhcmF0b3IsICRuYW1lcyk7DQoJCQkJCX0JDQoJCQkJfQ0KCQkJCXJldHVybiAoc3RyaW5nKSBpbXBsb2RlKCRzZXBhcmF0b3IsICRyZXN1bHQpOw0KCQkJfQ0KCQkJcmV0dXJuIChzdHJpbmcpIGpzb25fZGVjb2RlKChzdHJpbmcpICR2YWx1ZSk7DQoJCX0NCgkJcmV0dXJuICR2YWx1ZTsNCgl9DQo=', '{}', 'JsonHelper', 'VDM\\Joomla\\Utilities.JsonHelper', '1.0.0', '{}', 'Utilities Json Helper', 'abstract class', '{}', '', 1, '2022-03-08 21:03:54', '2023-01-14 18:11:18', 22, 6),
(12, 1, 'Some string tricks\r\n\r\n@since 3.0.9', '', '', '1f28cb53-60d9-4db1-b517-3c7dc6b429ef', 'dXNlIEpvb21sYVxDTVNcRmlsdGVyXElucHV0RmlsdGVyOw0KdXNlIEpvb21sYVxDTVNcTGFuZ3VhZ2VcTGFuZ3VhZ2U7', '', '', '{\"load_selection0\":{\"load\":\"0a59c65c-9daf-4bc9-baf4-e063ff9e6a8a\"}}', 'CS8qKg0KCSAqIFRoZSBNYWluIEFjdGl2ZSBMYW5ndWFnZQ0KCSAqIA0KCSAqIEB2YXIgICAgICBzdHJpbmcNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyAkbGFuZ1RhZzsNCg0KCS8qKg0KCSAqIENoZWNrIGlmIHdlIGhhdmUgYSBzdHJpbmcgd2l0aCBhIGxlbmd0aA0KCSAqDQoJICogQGlucHV0ICAgIHN0cmluZyAgJHN0cmluZyBUaGUgc3RyaW5nIHRvIGNoZWNrDQoJICoNCgkgKiBAcmV0dXJucyBib29sIHRydWUgb24gc3VjY2Vzcw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGNoZWNrKCRzdHJpbmcpOiBib29sDQoJew0KCQlyZXR1cm4gaXNfc3RyaW5nKCRzdHJpbmcpICYmIHN0cmxlbigkc3RyaW5nKSA+IDA7DQoJfQ0KDQoJLyoqDQoJICogU2hvcnRlbiBhIHN0cmluZw0KCSAqDQoJICogQGlucHV0CXN0cmluZyAgIFRoZSB5b3Ugd291bGQgbGlrZSB0byBzaG9ydGVuDQoJICoNCgkgKiBAcmV0dXJucyBzdHJpbmcgb24gc3VjY2Vzcw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHNob3J0ZW4oJHN0cmluZywgJGxlbmd0aCA9IDQwLCAkYWRkVGlwID0gdHJ1ZSkNCgl7DQoJCWlmIChzZWxmOjpjaGVjaygkc3RyaW5nKSkNCgkJew0KCQkJJGluaXRpYWwgPSBzdHJsZW4oKHN0cmluZykgJHN0cmluZyk7DQoJCQkkd29yZHMgPSBwcmVnX3NwbGl0KCcvKFtcc1xuXHJdKykvJywgKHN0cmluZykgJHN0cmluZywgbnVsbCwgUFJFR19TUExJVF9ERUxJTV9DQVBUVVJFKTsNCgkJCSR3b3Jkc19jb3VudCA9IGNvdW50KChhcnJheSkkd29yZHMpOw0KDQoJCQkkd29yZF9sZW5ndGggPSAwOw0KCQkJJGxhc3Rfd29yZCA9IDA7DQoJCQlmb3IgKDsgJGxhc3Rfd29yZCA8ICR3b3Jkc19jb3VudDsgKyskbGFzdF93b3JkKQ0KCQkJew0KCQkJCSR3b3JkX2xlbmd0aCArPSBzdHJsZW4oJHdvcmRzWyRsYXN0X3dvcmRdKTsNCgkJCQlpZiAoJHdvcmRfbGVuZ3RoID4gJGxlbmd0aCkNCgkJCQl7DQoJCQkJCWJyZWFrOw0KCQkJCX0NCgkJCX0NCg0KCQkJJG5ld1N0cmluZwk9IGltcGxvZGUoYXJyYXlfc2xpY2UoJHdvcmRzLCAwLCAkbGFzdF93b3JkKSk7DQoJCQkkZmluYWwJPSBzdHJsZW4oJG5ld1N0cmluZyk7DQoJCQlpZiAoJGluaXRpYWwgIT09ICRmaW5hbCAmJiAkYWRkVGlwKQ0KCQkJew0KCQkJCSR0aXRsZSA9IHNlbGY6OnNob3J0ZW4oJHN0cmluZywgNDAwICwgZmFsc2UpOw0KCQkJCXJldHVybiAnPHNwYW4gY2xhc3M9Imhhc1RpcCIgdGl0bGU9IicgLiAkdGl0bGUgLiAnIiBzdHlsZT0iY3Vyc29yOmhlbHAiPicgLiB0cmltKCRuZXdTdHJpbmcpIC4gJy4uLjwvc3Bhbj4nOw0KCQkJfQ0KCQkJZWxzZWlmICgkaW5pdGlhbCAhPT0gJGZpbmFsICYmICEkYWRkVGlwKQ0KCQkJew0KCQkJCXJldHVybiB0cmltKCRuZXdTdHJpbmcpIC4gJy4uLic7DQoJCQl9DQoJCX0NCgkJcmV0dXJuICRzdHJpbmc7DQoJfQ0KDQoJLyoqDQoJICogTWFraW5nIHN0cmluZ3Mgc2FmZSAodmFyaW91cyB3YXlzKQ0KCSAqDQoJICogQGlucHV0CXN0cmluZyAgIFRoZSB5b3Ugd291bGQgbGlrZSB0byBtYWtlIHNhZmUNCgkgKg0KCSAqIEByZXR1cm5zIHN0cmluZyBvbiBzdWNjZXNzDQoJICogDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gc2FmZSgkc3RyaW5nLCAkdHlwZSA9ICdMJywgJHNwYWNlciA9ICdfJywgJHJlcGxhY2VOdW1iZXJzID0gdHJ1ZSwgJGtlZXBPbmx5Q2hhcmFjdGVycyA9IHRydWUpDQoJew0KCQlpZiAoJHJlcGxhY2VOdW1iZXJzID09PSB0cnVlKQ0KCQl7DQoJCQkvLyByZW1vdmUgYWxsIG51bWJlcnMgYW5kIHJlcGxhY2Ugd2l0aCBFbmdsaXNoIHRleHQgdmVyc2lvbiAod29ya3Mgd2VsbCBvbmx5IHVwIHRvIG1pbGxpb25zKQ0KCQkJJHN0cmluZyA9IHNlbGY6Om51bWJlcnMoJHN0cmluZyk7DQoJCX0NCgkJLy8gMG5seSBjb250aW51ZSBpZiB3ZSBoYXZlIGEgc3RyaW5nDQoJCWlmIChzZWxmOjpjaGVjaygkc3RyaW5nKSkNCgkJew0KCQkJLy8gY3JlYXRlIGZpbGUgbmFtZSB3aXRob3V0IHRoZSBleHRlbnNpb24gdGhhdCBpcyBzYWZlDQoJCQlpZiAoJHR5cGUgPT09ICdmaWxlbmFtZScpDQoJCQl7DQoJCQkJLy8gbWFrZSBzdXJlIFZETSBpcyBub3QgaW4gdGhlIHN0cmluZw0KCQkJCSRzdHJpbmcgPSBzdHJfcmVwbGFjZSgnVkRNJywgJ3ZEbScsIChzdHJpbmcpICRzdHJpbmcpOw0KCQkJCS8vIFJlbW92ZSBhbnl0aGluZyB3aGljaCBpc24ndCBhIHdvcmQsIHdoaXRlc3BhY2UsIG51bWJlcg0KCQkJCS8vIG9yIGFueSBvZiB0aGUgZm9sbG93aW5nIGNhcmFjdGVycyAtXygpDQoJCQkJLy8gSWYgeW91IGRvbid0IG5lZWQgdG8gaGFuZGxlIG11bHRpLWJ5dGUgY2hhcmFjdGVycw0KCQkJCS8vIHlvdSBjYW4gdXNlIHByZWdfcmVwbGFjZSByYXRoZXIgdGhhbiBtYl9lcmVnX3JlcGxhY2UNCgkJCQkvLyBUaGFua3MgQMWBdWthc3ogUnlzaWFrIQ0KCQkJCS8vICRzdHJpbmcgPSBtYl9lcmVnX3JlcGxhY2UoIihbXlx3XHNcZFwtX1woXCldKSIsICcnLCAkc3RyaW5nKTsNCgkJCQkkc3RyaW5nID0gcHJlZ19yZXBsYWNlKCIoW15cd1xzXGRcLV9cKFwpXSkiLCAnJywgJHN0cmluZyk7DQoNCgkJCQkvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMDIxNzI5LzE0Mjk2NzcNCgkJCQlyZXR1cm4gcHJlZ19yZXBsYWNlKCcvXHMrLycsICcgJywgJHN0cmluZyk7DQoJCQl9DQoJCQkvLyByZW1vdmUgYWxsIG90aGVyIGNoYXJhY3RlcnMNCgkJCSRzdHJpbmcgPSB0cmltKChzdHJpbmcpICRzdHJpbmcpOw0KCQkJJHN0cmluZyA9IHByZWdfcmVwbGFjZSgnLycuJHNwYWNlci4nKy8nLCAnICcsICRzdHJpbmcpOw0KCQkJJHN0cmluZyA9IHByZWdfcmVwbGFjZSgnL1xzKy8nLCAnICcsICRzdHJpbmcpOw0KCQkJLy8gVHJhbnNsaXRlcmF0ZSBzdHJpbmcNCgkJCSRzdHJpbmcgPSBzZWxmOjp0cmFuc2xpdGVyYXRlKCRzdHJpbmcpOw0KCQkJLy8gcmVtb3ZlIGFsbCBhbmQga2VlcCBvbmx5IGNoYXJhY3RlcnMNCgkJCWlmICgka2VlcE9ubHlDaGFyYWN0ZXJzKQ0KCQkJew0KCQkJCSRzdHJpbmcgPSBwcmVnX3JlcGxhY2UoIi9bXkEtWmEteiBdLyIsICcnLCAkc3RyaW5nKTsNCgkJCX0NCgkJCS8vIGtlZXAgYm90aCBudW1iZXJzIGFuZCBjaGFyYWN0ZXJzDQoJCQllbHNlDQoJCQl7DQoJCQkJJHN0cmluZyA9IHByZWdfcmVwbGFjZSgiL1teQS1aYS16MC05IF0vIiwgJycsICRzdHJpbmcpOw0KCQkJfQ0KCQkJLy8gc2VsZWN0IGZpbmFsIGFkYXB0YXRpb25zDQoJCQlpZiAoJHR5cGUgPT09ICdMJyB8fCAkdHlwZSA9PT0gJ3N0cnRvbG93ZXInKQ0KCQkJew0KCQkJCS8vIHJlcGxhY2Ugd2hpdGUgc3BhY2Ugd2l0aCB1bmRlcnNjb3JlDQoJCQkJJHN0cmluZyA9IHByZWdfcmVwbGFjZSgnL1xzKy8nLCAoc3RyaW5nKSAkc3BhY2VyLCAkc3RyaW5nKTsNCgkJCQkvLyBkZWZhdWx0IGlzIHRvIHJldHVybiBsb3dlcg0KCQkJCXJldHVybiBzdHJ0b2xvd2VyKCRzdHJpbmcpOw0KCQkJfQ0KCQkJZWxzZWlmICgkdHlwZSA9PT0gJ1cnKQ0KCQkJew0KCQkJCS8vIHJldHVybiBhIHN0cmluZyB3aXRoIGFsbCBmaXJzdCBsZXR0ZXIgb2YgZWFjaCB3b3JkIHVwcGVyY2FzZShubyB1bmRlcnNjb3JlKQ0KCQkJCXJldHVybiB1Y3dvcmRzKHN0cnRvbG93ZXIoJHN0cmluZykpOw0KCQkJfQ0KCQkJZWxzZWlmICgkdHlwZSA9PT0gJ3cnIHx8ICR0eXBlID09PSAnd29yZCcpDQoJCQl7DQoJCQkJLy8gcmV0dXJuIGEgc3RyaW5nIHdpdGggYWxsIGxvd2VyY2FzZShubyB1bmRlcnNjb3JlKQ0KCQkJCXJldHVybiBzdHJ0b2xvd2VyKCRzdHJpbmcpOw0KCQkJfQ0KCQkJZWxzZWlmICgkdHlwZSA9PT0gJ1d3JyB8fCAkdHlwZSA9PT0gJ1dvcmQnKQ0KCQkJew0KCQkJCS8vIHJldHVybiBhIHN0cmluZyB3aXRoIGZpcnN0IGxldHRlciBvZiB0aGUgZmlyc3Qgd29yZCB1cHBlcmNhc2UgYW5kIGFsbCB0aGUgcmVzdCBsb3dlcmNhc2Uobm8gdW5kZXJzY29yZSkNCgkJCQlyZXR1cm4gdWNmaXJzdChzdHJ0b2xvd2VyKCRzdHJpbmcpKTsNCgkJCX0NCgkJCWVsc2VpZiAoJHR5cGUgPT09ICdXVycgfHwgJHR5cGUgPT09ICdXT1JEJykNCgkJCXsNCgkJCQkvLyByZXR1cm4gYSBzdHJpbmcgd2l0aCBhbGwgdGhlIHVwcGVyY2FzZShubyB1bmRlcnNjb3JlKQ0KCQkJCXJldHVybiBzdHJ0b3VwcGVyKCRzdHJpbmcpOw0KCQkJfQ0KCQkJZWxzZWlmICgkdHlwZSA9PT0gJ1UnIHx8ICR0eXBlID09PSAnc3RydG91cHBlcicpDQoJCQl7DQoJCQkJCS8vIHJlcGxhY2Ugd2hpdGUgc3BhY2Ugd2l0aCB1bmRlcnNjb3JlDQoJCQkJCSRzdHJpbmcgPSBwcmVnX3JlcGxhY2UoJy9ccysvJywgKHN0cmluZykgJHNwYWNlciwgJHN0cmluZyk7DQoJCQkJCS8vIHJldHVybiBhbGwgdXBwZXINCgkJCQkJcmV0dXJuIHN0cnRvdXBwZXIoJHN0cmluZyk7DQoJCQl9DQoJCQllbHNlaWYgKCR0eXBlID09PSAnRicgfHwgJHR5cGUgPT09ICd1Y2ZpcnN0JykNCgkJCXsNCgkJCQkJLy8gcmVwbGFjZSB3aGl0ZSBzcGFjZSB3aXRoIHVuZGVyc2NvcmUNCgkJCQkJJHN0cmluZyA9IHByZWdfcmVwbGFjZSgnL1xzKy8nLCAoc3RyaW5nKSAkc3BhY2VyLCAkc3RyaW5nKTsNCgkJCQkJLy8gcmV0dXJuIHdpdGggZmlyc3QgY2hhcmFjdGVyIHRvIHVwcGVyDQoJCQkJCXJldHVybiB1Y2ZpcnN0KHN0cnRvbG93ZXIoJHN0cmluZykpOw0KCQkJfQ0KCQkJZWxzZWlmICgkdHlwZSA9PT0gJ2NBJyB8fCAkdHlwZSA9PT0gJ2NBbWVsJyB8fCAkdHlwZSA9PT0gJ2NhbWVsY2FzZScpDQoJCQl7DQoJCQkJLy8gY29udmVydCBhbGwgd29yZHMgdG8gZmlyc3QgbGV0dGVyIHVwcGVyY2FzZQ0KCQkJCSRzdHJpbmcgPSB1Y3dvcmRzKHN0cnRvbG93ZXIoJHN0cmluZykpOw0KCQkJCS8vIHJlbW92ZSB3aGl0ZSBzcGFjZQ0KCQkJCSRzdHJpbmcgPSBwcmVnX3JlcGxhY2UoJy9ccysvJywgJycsICRzdHJpbmcpOw0KCQkJCS8vIG5vdyByZXR1cm4gZmlyc3QgbGV0dGVyIGxvd2VyY2FzZQ0KCQkJCXJldHVybiBsY2ZpcnN0KCRzdHJpbmcpOw0KCQkJfQ0KCQkJLy8gcmV0dXJuIHN0cmluZw0KCQkJcmV0dXJuICRzdHJpbmc7DQoJCX0NCgkJLy8gbm90IGEgc3RyaW5nDQoJCXJldHVybiAnJzsNCgl9DQoNCgkvKioNCgkgKiBDb252ZXJ0IG5vbmUgRW5nbGlzaCBzdHJpbmdzIHRvIGNvZGUgdXNhYmxlIHN0cmluZw0KCSAqDQoJICogQGlucHV0CWFuIHN0cmluZw0KCSAqDQoJICogQHJldHVybnMgYSBzdHJpbmcNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiB0cmFuc2xpdGVyYXRlKCRzdHJpbmcpDQoJew0KCQkvLyBzZXQgdGFnIG9ubHkgb25jZQ0KCQlpZiAoIXNlbGY6OmNoZWNrKHNlbGY6OiRsYW5nVGFnKSkNCgkJew0KCQkJLy8gZ2V0IGdsb2JhbCB2YWx1ZQ0KCQkJc2VsZjo6JGxhbmdUYWcgPSBIZWxwZXI6OmdldFBhcmFtcygpLT5nZXQoJ2xhbmd1YWdlJywgJ2VuLUdCJyk7DQoJCX0NCg0KCQkvLyBUcmFuc2xpdGVyYXRlIG9uIHRoZSBsYW5ndWFnZSByZXF1ZXN0ZWQNCgkJJGxhbmcgPSBMYW5ndWFnZTo6Z2V0SW5zdGFuY2Uoc2VsZjo6JGxhbmdUYWcpOw0KDQoJCXJldHVybiAkbGFuZy0+dHJhbnNsaXRlcmF0ZSgkc3RyaW5nKTsNCgl9DQoNCgkvKioNCgkgKiBtYWtlIHN1cmUgYSBzdHJpbmcgaXMgSFRNTCBzYXZlDQoJICoNCgkgKiBAaW5wdXQJYW4gaHRtbCBzdHJpbmcNCgkgKg0KCSAqIEByZXR1cm5zIGEgc3RyaW5nDQoJICogDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gaHRtbCgkdmFyLCAkY2hhcnNldCA9ICdVVEYtOCcsICRzaG9ydGVuID0gZmFsc2UsICRsZW5ndGggPSA0MCwgJGFkZFRpcCA9IHRydWUpDQoJew0KCQlpZiAoc2VsZjo6Y2hlY2soJHZhcikpDQoJCXsNCgkJCSRmaWx0ZXIgPSBuZXcgSW5wdXRGaWx0ZXIoKTsNCgkJCSRzdHJpbmcgPSAkZmlsdGVyLT5jbGVhbigNCgkJCQlodG1sX2VudGl0eV9kZWNvZGUoDQoJCQkJCWh0bWxlbnRpdGllcygNCgkJCQkJCShzdHJpbmcpICR2YXIsDQoJCQkJCQlFTlRfQ09NUEFULA0KCQkJCQkJJGNoYXJzZXQNCgkJCQkJKQ0KCQkJCSksDQoJCQkJJ0hUTUwnDQoJCQkpOw0KCQkJaWYgKCRzaG9ydGVuKQ0KCQkJew0KCQkJCXJldHVybiBzZWxmOjpzaG9ydGVuKCRzdHJpbmcsICRsZW5ndGgsICRhZGRUaXApOw0KCQkJfQ0KCQkJcmV0dXJuICRzdHJpbmc7DQoJCX0NCgkJZWxzZQ0KCQl7DQoJCQlyZXR1cm4gJyc7DQoJCX0NCgl9DQoNCgkvKioNCgkgKiBDb252ZXJ0IGFsbCBpbnQgaW4gYSBzdHJpbmcgdG8gYW4gRW5nbGlzaCB3b3JkIHN0cmluZw0KCSAqDQoJICogQGlucHV0CWFuIHN0cmluZyB3aXRoIG51bWJlcnMNCgkgKg0KCSAqIEByZXR1cm5zIGEgc3RyaW5nDQoJICogDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gbnVtYmVycygkc3RyaW5nKQ0KCXsNCgkJLy8gc2V0IG51bWJlcnMgYXJyYXkNCgkJJG51bWJlcnMgPSBbXTsNCgkJJHNlYXJjaF9yZXBsYWNlPSBbXTsNCg0KCQkvLyBmaXJzdCBnZXQgYWxsIG51bWJlcnMNCgkJcHJlZ19tYXRjaF9hbGwoJyFcZCshJywgKHN0cmluZykgJHN0cmluZywgJG51bWJlcnMpOw0KDQoJCS8vIGNoZWNrIGlmIHdlIGhhdmUgYW55IG51bWJlcnMNCgkJaWYgKGlzc2V0KCRudW1iZXJzWzBdKSAmJiBBcnJheUhlbHBlcjo6Y2hlY2soJG51bWJlcnNbMF0pKQ0KCQl7DQoJCQlmb3JlYWNoICgkbnVtYmVyc1swXSBhcyAkbnVtYmVyKQ0KCQkJew0KCQkJCSRzZWFyY2hfcmVwbGFjZVskbnVtYmVyXSA9IHNlbGY6Om51bWJlcigoaW50KSRudW1iZXIpOw0KCQkJfQ0KDQoJCQkvLyBub3cgcmVwbGFjZSBudW1iZXJzIGluIHN0cmluZw0KCQkJJHN0cmluZyA9IHN0cl9yZXBsYWNlKGFycmF5X2tleXMoJHNlYXJjaF9yZXBsYWNlKSwgYXJyYXlfdmFsdWVzKCRzZWFyY2hfcmVwbGFjZSksIChzdHJpbmcpICRzdHJpbmcpOw0KDQoJCQkvLyBjaGVjayBpZiB3ZSBtaXNzZWQgYW55LCBzdHJhbmdlIGlmIHdlIGRpZC4NCgkJCXJldHVybiBzZWxmOjpudW1iZXJzKCRzdHJpbmcpOw0KCQl9DQoNCgkJLy8gcmV0dXJuIHRoZSBzdHJpbmcgd2l0aCBubyBudW1iZXJzIHJlbWFpbmluZy4NCgkJcmV0dXJuICRzdHJpbmc7DQoJfQ0KDQoJLyoqDQoJICogQ29udmVydCBhbiBpbnRlZ2VyIGludG8gYW4gRW5nbGlzaCB3b3JkIHN0cmluZw0KCSAqIFRoYW5rcyB0byBUb20gTmljaG9sc29uIDxodHRwOi8vcGhwLm5ldC9tYW51YWwvZW4vZnVuY3Rpb24uc3RydmFsLnBocCM0MTk4OD4NCgkgKg0KCSAqIEBpbnB1dAlhbiBpbnQNCgkgKiBAcmV0dXJucyBhIHN0cmluZw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIG51bWJlcigkeCkNCgl7DQoJCSRud29yZHMgPSBhcnJheSggInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwNCgkJCSJlaWdodCIsICJuaW5lIiwgInRlbiIsICJlbGV2ZW4iLCAidHdlbHZlIiwgInRoaXJ0ZWVuIiwNCgkJCSJmb3VydGVlbiIsICJmaWZ0ZWVuIiwgInNpeHRlZW4iLCAic2V2ZW50ZWVuIiwgImVpZ2h0ZWVuIiwNCgkJCSJuaW5ldGVlbiIsICJ0d2VudHkiLCAzMCA9PiAidGhpcnR5IiwgNDAgPT4gImZvcnR5IiwNCgkJCTUwID0+ICJmaWZ0eSIsIDYwID0+ICJzaXh0eSIsIDcwID0+ICJzZXZlbnR5IiwgODAgPT4gImVpZ2h0eSIsDQoJCQk5MCA9PiAibmluZXR5IiApOw0KDQoJCWlmKCFpc19udW1lcmljKCR4KSkNCgkJew0KCQkJJHcgPSAkeDsNCgkJfQ0KCQllbHNlaWYoZm1vZCgkeCwgMSkgIT0gMCkNCgkJew0KCQkJJHcgPSAkeDsNCgkJfQ0KCQllbHNlDQoJCXsNCgkJCWlmKCR4IDwgMCkNCgkJCXsNCgkJCQkkdyA9ICdtaW51cyAnOw0KCQkJCSR4ID0gLSR4Ow0KCQkJfQ0KCQkJZWxzZQ0KCQkJew0KCQkJCSR3ID0gJyc7DQoJCQkJLy8gLi4uIG5vdyAkeCBpcyBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyLg0KCQkJfQ0KDQoJCQlpZigkeCA8IDIxKSAgIC8vIDAgdG8gMjANCgkJCXsNCgkJCQkkdyAuPSAkbndvcmRzWyR4XTsNCgkJCX0NCgkJCWVsc2VpZigkeCA8IDEwMCkgIC8vIDIxIHRvIDk5DQoJCQl7IA0KCQkJCSR3IC49ICRud29yZHNbMTAgKiBmbG9vcigkeC8xMCldOw0KCQkJCSRyID0gZm1vZCgkeCwgMTApOw0KCQkJCWlmKCRyID4gMCkNCgkJCQl7DQoJCQkJCSR3IC49ICcgJyAuICRud29yZHNbJHJdOw0KCQkJCX0NCgkJCX0NCgkJCWVsc2VpZigkeCA8IDEwMDApICAvLyAxMDAgdG8gOTk5DQoJCQl7DQoJCQkJJHcgLj0gJG53b3Jkc1tmbG9vcigkeC8xMDApXSAuJyBodW5kcmVkJzsNCgkJCQkkciA9IGZtb2QoJHgsIDEwMCk7DQoJCQkJaWYoJHIgPiAwKQ0KCQkJCXsNCgkJCQkJJHcgLj0gJyBhbmQgJy4gc2VsZjo6bnVtYmVyKCRyKTsNCgkJCQl9DQoJCQl9DQoJCQllbHNlaWYoJHggPCAxMDAwMDAwKSAgLy8gMTAwMCB0byA5OTk5OTkNCgkJCXsNCgkJCQkkdyAuPSBzZWxmOjpudW1iZXIoZmxvb3IoJHgvMTAwMCkpIC4nIHRob3VzYW5kJzsNCgkJCQkkciA9IGZtb2QoJHgsIDEwMDApOw0KCQkJCWlmKCRyID4gMCkNCgkJCQl7DQoJCQkJCSR3IC49ICcgJzsNCgkJCQkJaWYoJHIgPCAxMDApDQoJCQkJCXsNCgkJCQkJCSR3IC49ICdhbmQgJzsNCgkJCQkJfQ0KCQkJCQkkdyAuPSBzZWxmOjpudW1iZXIoJHIpOw0KCQkJCX0NCgkJCX0gDQoJCQllbHNlIC8vICBtaWxsaW9ucw0KCQkJeyAgICANCgkJCQkkdyAuPSBzZWxmOjpudW1iZXIoZmxvb3IoJHgvMTAwMDAwMCkpIC4nIG1pbGxpb24nOw0KCQkJCSRyID0gZm1vZCgkeCwgMTAwMDAwMCk7DQoJCQkJaWYoJHIgPiAwKQ0KCQkJCXsNCgkJCQkJJHcgLj0gJyAnOw0KCQkJCQlpZigkciA8IDEwMCkNCgkJCQkJew0KCQkJCQkJJHcgLj0gJ2FuZCAnOw0KCQkJCQl9DQoJCQkJCSR3IC49IHNlbGY6Om51bWJlcigkcik7DQoJCQkJfQ0KCQkJfQ0KCQl9DQoJCXJldHVybiAkdzsNCgl9DQoNCgkvKioNCgkgKiBSYW5kb20gS2V5DQoJICoNCgkgKiBAcmV0dXJucyBhIHN0cmluZw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHJhbmRvbSgkc2l6ZSk6IHN0cmluZw0KCXsNCgkJJGJhZyA9ICJhYmNlZmdoaWprbm9wcXJzdHV3eHl6QUJDRERFRkdISUpLTExNTU5PUFFSU1RVVlZXWFlaYWJjZGRlZmdoaWprbGxtbW5vcHFyc3R1dnZ3eHl6QUJDRUZHSElKS05PUFFSU1RVV1hZWiI7DQoJCSRrZXkgPSBhcnJheSgpOw0KCQkkYmFnc2l6ZSA9IHN0cmxlbigkYmFnKSAtIDE7DQoNCgkJZm9yICgkaSA9IDA7ICRpIDwgJHNpemU7ICRpKyspDQoJCXsNCgkJCSRnZXQgPSByYW5kKDAsICRiYWdzaXplKTsNCgkJCSRrZXlbXSA9ICRiYWdbJGdldF07DQoJCX0NCg0KCQlyZXR1cm4gaW1wbG9kZSgka2V5KTsNCgl9DQo=', '{}', 'StringHelper', 'VDM\\Joomla\\Utilities.StringHelper', '1.0.0', '{}', 'Utilities String Helper', 'abstract class', '{\"use_selection0\":{\"use\":\"640b5352-fb09-425f-a26e-cd44eda03f15\",\"as\":\"default\"}}', '', 1, '2022-03-08 21:35:37', '2023-01-14 17:54:57', 30, 7),
-(13, '', 'Some array tricks helper\r\n\r\n@since 3.0.9', '', '', '0a59c65c-9daf-4bc9-baf4-e063ff9e6a8a', '', '', '', '{}', 'CS8qKg0KCSAqIENoZWNrIGlmIGhhdmUgYW4gYXJyYXkgd2l0aCBhIGxlbmd0aA0KCSAqDQoJICogQGlucHV0CWFycmF5ICAgVGhlIGFycmF5IHRvIGNoZWNrDQoJICoNCgkgKiBAcmV0dXJucyBib29sL2ludCAgbnVtYmVyIG9mIGl0ZW1zIGluIGFycmF5IG9uIHN1Y2Nlc3MNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBjaGVjaygkYXJyYXksICRyZW1vdmVFbXB0eVN0cmluZyA9IGZhbHNlKQ0KCXsNCgkJaWYgKGlzX2FycmF5KCRhcnJheSkgJiYgKCRuciA9IGNvdW50KChhcnJheSkkYXJyYXkpKSA+IDApDQoJCXsNCgkJCS8vIGFsc28gbWFrZSBzdXJlIHRoZSBlbXB0eSBzdHJpbmdzIGFyZSByZW1vdmVkDQoJCQlpZiAoJHJlbW92ZUVtcHR5U3RyaW5nKQ0KCQkJew0KCQkJCWZvcmVhY2ggKCRhcnJheSBhcyAka2V5ID0+ICRzdHJpbmcpDQoJCQkJew0KCQkJCQlpZiAoZW1wdHkoJHN0cmluZykpDQoJCQkJCXsNCgkJCQkJCXVuc2V0KCRhcnJheVska2V5XSk7DQoJCQkJCX0NCgkJCQl9DQoJCQkJcmV0dXJuIHNlbGY6OmNoZWNrKCRhcnJheSwgZmFsc2UpOw0KCQkJfQ0KCQkJcmV0dXJuICRucjsNCgkJfQ0KCQlyZXR1cm4gZmFsc2U7DQoJfQ0KDQoJLyoqDQoJICogTWVyZ2UgYW4gYXJyYXkgb2YgYXJyYXkncw0KCSAqDQoJICogQGlucHV0CWFycmF5ICAgVGhlIGFycmF5cyB5b3Ugd291bGQgbGlrZSB0byBtZXJnZQ0KCSAqDQoJICogQHJldHVybnMgYXJyYXkgb24gc3VjY2Vzcw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIG1lcmdlKCRhcnJheXMpDQoJew0KCQlpZihzZWxmOjpjaGVjaygkYXJyYXlzKSkNCgkJew0KCQkJJGFycmF5QnVrZXQgPSBhcnJheSgpOw0KCQkJZm9yZWFjaCAoJGFycmF5cyBhcyAkYXJyYXkpDQoJCQl7DQoJCQkJaWYgKHNlbGY6OmNoZWNrKCRhcnJheSkpDQoJCQkJew0KCQkJCQkkYXJyYXlCdWtldCA9IGFycmF5X21lcmdlKCRhcnJheUJ1a2V0LCAkYXJyYXkpOw0KCQkJCX0NCgkJCX0NCgkJCXJldHVybiAkYXJyYXlCdWtldDsNCgkJfQ0KCQlyZXR1cm4gZmFsc2U7DQoJfQ0KDQoJLyoqDQoJICogQ2hlY2sgaWYgYXJyYXlzIGludGVyc2VjdA0KCSAqDQoJICogQGlucHV0CWFycmF5ICAgVGhlIGZpcnN0IGFycmF5DQoJICogQGlucHV0CWFycmF5ICAgVGhlIHNlY29uZCBhcnJheQ0KCSAqDQoJICogQHJldHVybnMgYm9vbCAgdHJ1ZSBpZiBpbnRlcnNlY3QgZWxzZSBmYWxzZQ0KCSAqIA0KCSAqIEBzaW5jZSAgMy4xLjENCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGludGVyc2VjdCgkYV9hcnJheSwgJGJfYXJyYXkpOiBib29sDQoJew0KCQkvLyBmbGlwIHRoZSBzZWNvbmQgYXJyYXkNCgkJJGJfYXJyYXkgPSBhcnJheV9mbGlwKCRiX2FycmF5KTsNCg0KCQkvLyBsb29wIHRoZSBmaXJzdCBhcnJheQ0KCQlmb3JlYWNoICgkYV9hcnJheSBhcyAkdikNCgkJew0KCQkJaWYgKGlzc2V0KCRiX2FycmF5WyR2XSkpDQoJCQl7DQoJCQkJcmV0dXJuIHRydWU7DQoJCQl9DQoJCX0NCgkJcmV0dXJuIGZhbHNlOw0KCX0NCg==', '{}', 'ArrayHelper', 'VDM\\Joomla\\Utilities.ArrayHelper', '1.0.0', '{}', 'Utilities Array Helper', 'abstract class', '{}', '', 1, '2022-03-08 22:53:52', '2023-01-14 21:12:28', 18, 8),
+(13, '', 'Some array tricks helper\r\n\r\n@since 3.0.9', '', '', '0a59c65c-9daf-4bc9-baf4-e063ff9e6a8a', '', '', '', '{}', 'CS8qKg0KCSAqIENoZWNrIGlmIGhhdmUgYW4gYXJyYXkgd2l0aCBhIGxlbmd0aA0KCSAqDQoJICogQGlucHV0CWFycmF5ICAgVGhlIGFycmF5IHRvIGNoZWNrDQoJICoNCgkgKiBAcmV0dXJucyBpbnR8ZmFsc2UgIG51bWJlciBvZiBpdGVtcyBpbiBhcnJheSBvbiBzdWNjZXNzDQoJICogDQoJICogQHNpbmNlICAzLjIuMA0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gY2hlY2soJGFycmF5LCAkcmVtb3ZlRW1wdHlTdHJpbmcgPSBmYWxzZSkNCgl7DQoJCWlmIChpc19hcnJheSgkYXJyYXkpICYmICgkbnIgPSBjb3VudCgoYXJyYXkpJGFycmF5KSkgPiAwKQ0KCQl7DQoJCQkvLyBhbHNvIG1ha2Ugc3VyZSB0aGUgZW1wdHkgc3RyaW5ncyBhcmUgcmVtb3ZlZA0KCQkJaWYgKCRyZW1vdmVFbXB0eVN0cmluZykNCgkJCXsNCgkJCQkkYXJyYXkgPSBhcnJheV9maWx0ZXIoJGFycmF5KTsNCg0KCQkJCWlmIChlbXB0eSgkYXJyYXkpKQ0KCQkJCXsNCgkJCQkJcmV0dXJuIGZhbHNlOw0KCQkJCX0NCg0KCQkJCXJldHVybiBjb3VudCgkYXJyYXkpOw0KCQkJfQ0KDQoJCQlyZXR1cm4gJG5yOw0KCQl9DQoNCgkJcmV0dXJuIGZhbHNlOw0KCX0NCg0KCS8qKg0KCSAqIE1lcmdlIGFuIGFycmF5IG9mIGFycmF5J3MNCgkgKg0KCSAqIEBpbnB1dAlhcnJheSAgIFRoZSBhcnJheXMgeW91IHdvdWxkIGxpa2UgdG8gbWVyZ2UNCgkgKg0KCSAqIEByZXR1cm5zIGFycmF5fG51bGwgIG1lcmdlZCBhcnJheSBvbiBzdWNjZXNzDQoJICogDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gbWVyZ2UoJGFycmF5cyk6ID9hcnJheQ0KCXsNCgkJaWYoc2VsZjo6Y2hlY2soJGFycmF5cykpDQoJCXsNCgkJCSRtZXJnZWQgPSBbXTsNCgkJCWZvcmVhY2ggKCRhcnJheXMgYXMgJGFycmF5KQ0KCQkJew0KCQkJCWlmIChzZWxmOjpjaGVjaygkYXJyYXkpKQ0KCQkJCXsNCgkJCQkJJG1lcmdlZCA9IGFycmF5X21lcmdlKCRtZXJnZWQsICRhcnJheSk7DQoJCQkJfQ0KCQkJfQ0KCQkJcmV0dXJuICRtZXJnZWQ7DQoJCX0NCgkJcmV0dXJuIG51bGw7DQoJfQ0KDQoJLyoqDQoJICogQ2hlY2sgaWYgYXJyYXlzIGludGVyc2VjdA0KCSAqDQoJICogQGlucHV0CWFycmF5ICAgVGhlIGZpcnN0IGFycmF5DQoJICogQGlucHV0CWFycmF5ICAgVGhlIHNlY29uZCBhcnJheQ0KCSAqDQoJICogQHJldHVybnMgYm9vbCAgdHJ1ZSBpZiBpbnRlcnNlY3QgZWxzZSBmYWxzZQ0KCSAqIA0KCSAqIEBzaW5jZSAgMy4xLjENCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGludGVyc2VjdCgkYV9hcnJheSwgJGJfYXJyYXkpOiBib29sDQoJew0KCQkvLyBmbGlwIHRoZSBzZWNvbmQgYXJyYXkNCgkJJGJfYXJyYXkgPSBhcnJheV9mbGlwKCRiX2FycmF5KTsNCg0KCQkvLyBsb29wIHRoZSBmaXJzdCBhcnJheQ0KCQlmb3JlYWNoICgkYV9hcnJheSBhcyAkdikNCgkJew0KCQkJaWYgKGlzc2V0KCRiX2FycmF5WyR2XSkpDQoJCQl7DQoJCQkJcmV0dXJuIHRydWU7DQoJCQl9DQoJCX0NCgkJcmV0dXJuIGZhbHNlOw0KCX0NCg==', '{}', 'ArrayHelper', 'VDM\\Joomla\\Utilities.ArrayHelper', '1.0.0', '{}', 'Utilities Array Helper', 'abstract class', '{}', '', 1, '2022-03-08 22:53:52', '2023-01-18 22:09:16', 20, 8),
(14, '', 'Control the naming of a namespace helper\r\n\r\n@since 3.0.9', '', '', 'ce8cf834-6bac-44fb-941c-861f7e046cc0', '', '', '', '{}', 'CS8qKg0KCSAqIE1ha2luZyBuYW1lc3BhY2Ugc2FmZQ0KCSAqDQoJICogQGlucHV0ICAgIHN0cmluZyAgICRzdHJpbmcgICAgICAgICAgIFRoZSB5b3Ugd291bGQgbGlrZSB0byBtYWtlIHNhZmUNCgkgKiBAaW5wdXQgICAgYm9vbCAgICAgJHJlbW92ZU51bWJlcnMgICAgVGhlIHN3aXRjaCB0byByZW1vdmUgbnVtYmVycw0KCSAqDQoJICogQHJldHVybnMgc3RyaW5nIG9uIHN1Y2Nlc3MNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBzYWZlKHN0cmluZyAkc3RyaW5nLCBib29sICRyZW1vdmVOdW1iZXJzID0gdHJ1ZSk6IHN0cmluZw0KCXsNCgkJLy8gMG5seSBjb250aW51ZSBpZiB3ZSBoYXZlIGEgc3RyaW5nIHdpdGggbGVuZ3RoDQoJCWlmIChTdHJpbmdIZWxwZXI6OmNoZWNrKCRzdHJpbmcpKQ0KCQl7DQoJCQkvLyBtYWtlIHN1cmUgaXQgaGFzIG5vdCBudW1iZXJzDQoJCQlpZiAoJHJlbW92ZU51bWJlcnMpDQoJCQl7DQoJCQkJJHN0cmluZyA9IFN0cmluZ0hlbHBlcjo6bnVtYmVycygkc3RyaW5nKTsNCgkJCX0NCg0KCQkJLy8gVHJhbnNsaXRlcmF0ZSBzdHJpbmcgVE9ETzogbG9vayBhZ2FpbiBhcyB0aGlzIG1ha2VzIGl0IGxvd2VyY2FzZQ0KCQkJLy8gJHN0cmluZyA9IFN0cmluZ0hlbHBlcjo6dHJhbnNsaXRlcmF0ZSgkc3RyaW5nKTsNCg0KCQkJLy8gZmlyc3QgcmVtb3ZlIGFsbCBbXF0gYmFja3NsYXNoZXMNCgkJCSRzdHJpbmcgPSBzdHJfcmVwbGFjZSgnXFwnLCAnKycsIChzdHJpbmcpICRzdHJpbmcpOw0KDQoJCQkvLyByZW1vdmUgYWxsIGFuZCBrZWVwIG9ubHkgY2hhcmFjdGVycyBhbmQgW1xdIGJhY2tzbGFzaGVzIGluc2lkZSBvZiB0aGUgc3RyaW5nDQoJCQlpZiAoJHJlbW92ZU51bWJlcnMpDQoJCQl7DQoJCQkJJHN0cmluZyA9IHRyaW0oIHByZWdfcmVwbGFjZSgiL1teQS1aYS16XCtdLyIsICcnLCAkc3RyaW5nKSwgJysnKTsNCgkJCX0NCgkJCWVsc2UNCgkJCXsNCgkJCQkkc3RyaW5nID0gdHJpbSggcHJlZ19yZXBsYWNlKCIvW15BLVphLXowLTlcK10vIiwgJycsICRzdHJpbmcpLCAnKycpOw0KCQkJfQ0KDQoJCQkvLyBwbGFjZSB0aGUgW1xdIGJhY2tzbGFzaGVzIGJhY2sNCgkJCXJldHVybiB0cmltKCBwcmVnX3JlcGxhY2UoIi9cKysvIiwgJ1xcJywgJHN0cmluZykpOw0KCQl9DQoNCgkJLy8gbm90IGEgc3RyaW5nDQoJCXJldHVybiAnJzsNCgl9DQo=', '{}', 'NamespaceHelper', 'VDM\\Joomla\\Utilities.String.NamespaceHelper', '1.0.0', '{}', 'String Namespace Helper', 'abstract class', '{\"use_selection0\":{\"use\":\"1f28cb53-60d9-4db1-b517-3c7dc6b429ef\",\"as\":\"default\"}}', '', 1, '2022-03-08 23:27:57', '2023-01-14 18:04:48', 19, 5),
(15, 1, 'Control the naming of a field type\r\n\r\n@since 3.0.9', '', '', 'a8935cbe-7701-40dc-bfd5-675f2d600954', 'dXNlIEpvb21sYVxDTVNcQ29tcG9uZW50XENvbXBvbmVudEhlbHBlcjs=', '', '', '{}', 'CS8qKg0KCSAqIFRoZSBmaWVsZCBidWlsZGVyIHN3aXRjaA0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwcm90ZWN0ZWQgc3RhdGljICRidWlsZGVyID0gZmFsc2U7DQoNCgkvKioNCgkgKiBNYWtpbmcgZmllbGQgdHlwZSBuYW1lIHNhZmUNCgkgKg0KCSAqIEBwYXJhbSAgIFN0cmluZyAgICAgICRzdHJpbmcgICAgIFRoZSB5b3Ugd291bGQgbGlrZSB0byBtYWtlIHNhZmUNCgkgKiBAcGFyYW0gICBTdHJpbmcgICAgICAkb3B0aW9uICAgIFRoZSBvcHRpb24gZm9yIHRoZSBjb21wb25lbnQuDQoJICoNCgkgKiBAcmV0dXJucyBzdHJpbmcgb24gc3VjY2Vzcw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHNhZmUoJHN0cmluZywgJG9wdGlvbiA9IG51bGwpDQoJew0KCQkvLyBnZXQgZ2xvYmFsIHZhbHVlDQoJCWlmIChzZWxmOjokYnVpbGRlciA9PT0gZmFsc2UpDQoJCXsNCgkJCXNlbGY6OiRidWlsZGVyID0gSGVscGVyOjpnZXRQYXJhbXMoJG9wdGlvbiktPmdldCgndHlwZV9uYW1lX2J1aWxkZXInLCAxKTsNCgkJfQ0KDQoJCS8vIHVzZSB0aGUgbmV3IGNvbnZlbnRpb24NCgkJaWYgKDIgPT0gc2VsZjo6JGJ1aWxkZXIpDQoJCXsNCgkJCS8vIDBubHkgY29udGludWUgaWYgd2UgaGF2ZSBhIHN0cmluZw0KCQkJaWYgKFN0cmluZ0hlbHBlcjo6Y2hlY2soJHN0cmluZykpDQoJCQl7DQoJCQkJLy8gY2hlY2sgdGhhdCB0aGUgZmlyc3QgY2hhcmFjdGVyIGlzIG5vdCBhIG51bWJlcg0KCQkJCWlmIChpc19udW1lcmljKHN1YnN0cigkc3RyaW5nLCAwLCAxKSkpDQoJCQkJew0KCQkJCQkkc3RyaW5nID0gU3RyaW5nSGVscGVyOjpudW1iZXJzKCRzdHJpbmcpOw0KCQkJCX0NCg0KCQkJCS8vIFRyYW5zbGl0ZXJhdGUgc3RyaW5nDQoJCQkJJHN0cmluZyA9IFN0cmluZ0hlbHBlcjo6dHJhbnNsaXRlcmF0ZSgkc3RyaW5nKTsNCg0KCQkJCS8vIHJlbW92ZSBhbGwgYW5kIGtlZXAgb25seSBjaGFyYWN0ZXJzIGFuZCBudW1iZXJzIGFuZCBwb2ludCAoVE9ETyBqdXN0IG9uZSBwb2ludCkNCgkJCQkkc3RyaW5nID0gdHJpbShwcmVnX3JlcGxhY2UoIi9bXkEtWmEtejAtOVwuXS8iLCAnJywgKHN0cmluZykgJHN0cmluZykpOw0KDQoJCQkJLy8gYmVzdCBpcyB0byByZXR1cm4gbG93ZXIgKGZvciBhbGwgc3RyaW5nIGVxdWFsaXR5IGluIGNvbXBpbGVyKQ0KCQkJCXJldHVybiBzdHJ0b2xvd2VyKCRzdHJpbmcpOw0KCQkJfQ0KCQkJLy8gbm90IGEgc3RyaW5nDQoJCQlyZXR1cm4gJyc7DQoJCX0NCg0KCQkvLyB1c2UgdGhlIGRlZmF1bHQgKG9yaWdpbmFsIGJlaGF2aW91ci9jb252ZW50aW9uKQ0KCQlyZXR1cm4gU3RyaW5nSGVscGVyOjpzYWZlKCRzdHJpbmcpOw0KCX0NCg==', '{}', 'TypeHelper', 'VDM\\Joomla\\Utilities.String.TypeHelper', '1.0.0', '{}', 'String Type Helper', 'abstract class', '{\"use_selection0\":{\"use\":\"1f28cb53-60d9-4db1-b517-3c7dc6b429ef\",\"as\":\"default\"},\"use_selection1\":{\"use\":\"640b5352-fb09-425f-a26e-cd44eda03f15\",\"as\":\"default\"}}', '', 1, '2022-03-08 23:33:09', '2023-01-14 17:56:28', 16, 5),
(16, '', 'Control the naming of a class and function\r\n\r\n@since 3.0.9', '', '', '30c5b4c2-f75f-4d15-869a-f8bfedd87358', '', '', '', '{}', 'CS8qKg0KCSAqIE1ha2luZyBjbGFzcyBvciBmdW5jdGlvbiBuYW1lIHNhZmUNCgkgKg0KCSAqIEBpbnB1dAlzdHJpbmcgICAgICAgVGhlIG5hbWUgeW91IHdvdWxkIGxpa2UgdG8gbWFrZSBzYWZlDQoJICoNCgkgKiBAcmV0dXJucyBzdHJpbmcgb24gc3VjY2Vzcw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHNhZmUoJG5hbWUpDQoJew0KCQkvLyByZW1vdmUgbnVtYmVycyBpZiB0aGUgZmlyc3QgY2hhcmFjdGVyIGlzIGEgbnVtYmVyDQoJCWlmIChpc19udW1lcmljKHN1YnN0cigoc3RyaW5nKSAkbmFtZSwgMCwgMSkpKQ0KCQl7DQoJCQkkbmFtZSA9IFN0cmluZ0hlbHBlcjo6bnVtYmVycygkbmFtZSk7DQoJCX0NCg0KCQkvLyByZW1vdmUgYWxsIHNwYWNlcyBhbmQgc3RyYW5nZSBjaGFyYWN0ZXJzDQoJCXJldHVybiB0cmltKHByZWdfcmVwbGFjZSgiL1teQS1aYS16MC05Xy1dLyIsICcnLCAoc3RyaW5nKSAkbmFtZSkpOw0KCX0NCg==', '{}', 'ClassfunctionHelper', 'VDM\\Joomla\\Utilities.String.ClassfunctionHelper', '1.0.0', '{}', 'String Classfunction Helper', 'abstract class', '{\"use_selection0\":{\"use\":\"1f28cb53-60d9-4db1-b517-3c7dc6b429ef\",\"as\":\"default\"}}', '', 1, '2022-03-08 23:43:10', '2023-01-14 18:07:10', 16, 5),
-(17, 1, 'Some easy get...\r\n\r\n@since 3.0.9', '', '', 'db87c339-5bb6-4291-a7ef-2c48ea1b06bc', 'dXNlIEpvb21sYVxDTVNcRmFjdG9yeTs=', '', '', '{\"load_selection0\":{\"load\":\"0a59c65c-9daf-4bc9-baf4-e063ff9e6a8a\"},\"load_selection1\":{\"load\":\"1f28cb53-60d9-4db1-b517-3c7dc6b429ef\"}}', 'CS8qKg0KCSAqIEdldCBhIFZhcmlhYmxlIA0KCSAqDQoJICogQHBhcmFtICAgc3RyaW5nfG51bGwgICR0YWJsZSAgICAgICAgVGhlIHRhYmxlIGZyb20gd2hpY2ggdG8gZ2V0IHRoZSB2YXJpYWJsZQ0KCSAqIEBwYXJhbSAgIG1peGVkICAgICAgICAkd2hlcmUgICAgICAgIFRoZSB2YWx1ZSB3aGVyZQ0KCSAqIEBwYXJhbSAgIHN0cmluZyAgICAgICAkd2hlcmVTdHJpbmcgIFRoZSB0YXJnZXQvZmllbGQgc3RyaW5nIHdoZXJlL25hbWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJHdoYXQgICAgICAgICBUaGUgcmV0dXJuIGZpZWxkDQoJICogQHBhcmFtICAgc3RyaW5nICAgICAgICRvcGVyYXRvciAgICAgVGhlIG9wZXJhdG9yIGJldHdlZW4gJHdoZXJlU3RyaW5nL2ZpZWxkIGFuZCAkd2hlcmUvdmFsdWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJG1haW4gICAgICAgICBUaGUgY29tcG9uZW50IGluIHdoaWNoIHRoZSB0YWJsZSBpcyBmb3VuZA0KCSAqDQoJICogQHJldHVybiAgbWl4ZWQgc3RyaW5nL2ludC9mbG9hdA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHZhcig/c3RyaW5nICR0YWJsZSA9IG51bGwsICR3aGVyZSA9IG51bGwsDQoJCXN0cmluZyAkd2hlcmVTdHJpbmcgPSAndXNlcicsIHN0cmluZyAkd2hhdCA9ICdpZCcsDQoJCXN0cmluZyAkb3BlcmF0b3IgPSAnPScsID9zdHJpbmcgJG1haW4gPSBudWxsKQ0KCXsNCgkJaWYoZW1wdHkoJHdoZXJlKSkNCgkJew0KCQkJJHdoZXJlID0gRmFjdG9yeTo6Z2V0VXNlcigpLT5pZDsNCgkJfQ0KDQoJCWlmKGVtcHR5KCRtYWluKSkNCgkJew0KCQkJJG1haW4gPSBIZWxwZXI6OmdldENvZGUoKTsNCgkJfQ0KDQoJCS8vIEdldCBhIGRiIGNvbm5lY3Rpb24uDQoJCSRkYiA9IEZhY3Rvcnk6OmdldERibygpOw0KDQoJCS8vIENyZWF0ZSBhIG5ldyBxdWVyeSBvYmplY3QuDQoJCSRxdWVyeSA9ICRkYi0+Z2V0UXVlcnkodHJ1ZSk7DQoJCSRxdWVyeS0+c2VsZWN0KCRkYi0+cXVvdGVOYW1lKGFycmF5KCR3aGF0KSkpOw0KDQoJCWlmIChlbXB0eSgkdGFibGUpKQ0KCQl7DQoJCQkkcXVlcnktPmZyb20oJGRiLT5xdW90ZU5hbWUoJyNfXycgLiAkbWFpbikpOw0KCQl9DQoJCWVsc2UNCgkJew0KCQkJJHF1ZXJ5LT5mcm9tKCRkYi0+cXVvdGVOYW1lKCcjX18nIC4gJG1haW4gLiAnXycgLiAkdGFibGUpKTsNCgkJfQ0KDQoJCWlmIChpc19udW1lcmljKCR3aGVyZSkpDQoJCXsNCgkJCSRxdWVyeS0+d2hlcmUoJGRiLT5xdW90ZU5hbWUoJHdoZXJlU3RyaW5nKSAuICcgJyAuICRvcGVyYXRvciAuICcgJyAuIChpbnQpICR3aGVyZSk7DQoJCX0NCgkJZWxzZWlmIChpc19zdHJpbmcoJHdoZXJlKSkNCgkJew0KCQkJJHF1ZXJ5LT53aGVyZSgkZGItPnF1b3RlTmFtZSgkd2hlcmVTdHJpbmcpIC4gJyAnIC4gJG9wZXJhdG9yIC4gJyAnIC4gJGRiLT5xdW90ZSgoc3RyaW5nKSR3aGVyZSkpOw0KCQl9DQoJCWVsc2UNCgkJew0KCQkJcmV0dXJuIGZhbHNlOw0KCQl9DQoNCgkJJGRiLT5zZXRRdWVyeSgkcXVlcnkpOw0KCQkkZGItPmV4ZWN1dGUoKTsNCg0KCQlpZiAoJGRiLT5nZXROdW1Sb3dzKCkpDQoJCXsNCgkJCXJldHVybiAkZGItPmxvYWRSZXN1bHQoKTsNCgkJfQ0KDQoJCXJldHVybiBmYWxzZTsNCgl9DQoNCgkvKioNCgkgKiBHZXQgYXJyYXkgb2YgdmFyaWFibGVzDQoJICoNCgkgKiBAcGFyYW0gICBzdHJpbmd8bnVsbCAgJHRhYmxlICAgICAgICBUaGUgdGFibGUgZnJvbSB3aGljaCB0byBnZXQgdGhlIHZhcmlhYmxlcw0KCSAqIEBwYXJhbSAgIG1peGVkICAgICAgICAkd2hlcmUgICAgICAgIFRoZSB2YWx1ZSB3aGVyZQ0KCSAqIEBwYXJhbSAgIHN0cmluZyAgICAgICAkd2hlcmVTdHJpbmcgIFRoZSB0YXJnZXQvZmllbGQgc3RyaW5nIHdoZXJlL25hbWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJHdoYXQgICAgICAgICBUaGUgcmV0dXJuIGZpZWxkDQoJICogQHBhcmFtICAgc3RyaW5nICAgICAgICRvcGVyYXRvciAgICAgVGhlIG9wZXJhdG9yIGJldHdlZW4gJHdoZXJlU3RyaW5nL2ZpZWxkIGFuZCAkd2hlcmUvdmFsdWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJG1haW4gICAgICAgICBUaGUgY29tcG9uZW50IGluIHdoaWNoIHRoZSB0YWJsZSBpcyBmb3VuZA0KCSAqIEBwYXJhbSAgIGJvb2wgICAgICAgICAkdW5pcXVlICAgICAgIFRoZSBzd2l0Y2ggdG8gcmV0dXJuIGEgdW5pcXVlIGFycmF5DQoJICoNCgkgKiBAcmV0dXJuICBhcnJheXxudWxsDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gdmFycyg/c3RyaW5nICR0YWJsZSA9IG51bGwsICR3aGVyZSA9IG51bGwsDQoJCXN0cmluZyAkd2hlcmVTdHJpbmcgPSAndXNlcicsIHN0cmluZyAkd2hhdCA9ICdpZCcsIHN0cmluZyAkb3BlcmF0b3IgPSAnSU4nLA0KCQk/c3RyaW5nICRtYWluID0gbnVsbCwgYm9vbCAkdW5pcXVlID0gdHJ1ZSk6ID9hcnJheQ0KCXsNCgkJaWYoZW1wdHkoJHdoZXJlKSkNCgkJew0KCQkJJHdoZXJlID0gRmFjdG9yeTo6Z2V0VXNlcigpLT5pZDsNCgkJfQ0KDQoJCWlmKGlzX251bGwoJG1haW4pKQ0KCQl7DQoJCQkkbWFpbiA9IEhlbHBlcjo6Z2V0Q29kZSgpOw0KCQl9DQoNCgkJaWYgKCFBcnJheUhlbHBlcjo6Y2hlY2soJHdoZXJlKSAmJiAkd2hlcmUgPiAwKQ0KCQl7DQoJCQkkd2hlcmUgPSBhcnJheSgkd2hlcmUpOw0KCQl9DQoNCgkJaWYgKEFycmF5SGVscGVyOjpjaGVjaygkd2hlcmUpKQ0KCQl7DQoJCQkvLyBwcmVwIG1haW4gPC0tIHdoeT8gd2VsbCBpZiAkbWFpbj0nJyBpcyBlbXB0eSB0aGVuICR0YWJsZSBjYW4gYmUgY2F0ZWdvcmllcyBvciB1c2Vycw0KCQkJaWYgKFN0cmluZ0hlbHBlcjo6Y2hlY2soJG1haW4pKQ0KCQkJew0KCQkJCSRtYWluID0gJ18nIC4gbHRyaW0oJG1haW4sICdfJyk7DQoJCQl9DQoNCgkJCS8vIEdldCBhIGRiIGNvbm5lY3Rpb24uDQoJCQkkZGIgPSBGYWN0b3J5OjpnZXREYm8oKTsNCg0KCQkJLy8gQ3JlYXRlIGEgbmV3IHF1ZXJ5IG9iamVjdC4NCgkJCSRxdWVyeSA9ICRkYi0+Z2V0UXVlcnkodHJ1ZSk7DQoJCQkkcXVlcnktPnNlbGVjdCgkZGItPnF1b3RlTmFtZShhcnJheSgkd2hhdCkpKTsNCg0KCQkJaWYgKGVtcHR5KCR0YWJsZSkpDQoJCQl7DQoJCQkJJHF1ZXJ5LT5mcm9tKCRkYi0+cXVvdGVOYW1lKCcjX18nIC4gJG1haW4pKTsNCgkJCX0NCgkJCWVsc2UNCgkJCXsNCgkJCQkkcXVlcnktPmZyb20oJGRiLT5xdW90ZU5hbWUoJyNfJyAuICRtYWluIC4gJ18nIC4gJHRhYmxlKSk7DQoJCQl9DQoNCgkJCS8vIGFkZCBzdHJpbmdzIHRvIGFycmF5IHNlYXJjaA0KCQkJaWYgKCdJTl9TVFJJTkdTJyA9PT0gJG9wZXJhdG9yIHx8ICdOT1QgSU5fU1RSSU5HUycgPT09ICRvcGVyYXRvcikNCgkJCXsNCgkJCQkkcXVlcnktPndoZXJlKCRkYi0+cXVvdGVOYW1lKCR3aGVyZVN0cmluZykgLiAnICcgLiBzdHJfcmVwbGFjZSgnX1NUUklOR1MnLCAnJywgJG9wZXJhdG9yKSAuICcgKCInIC4gaW1wbG9kZSgnIiwiJywgJHdoZXJlKSAuICciKScpOw0KCQkJfQ0KCQkJZWxzZQ0KCQkJew0KCQkJCSRxdWVyeS0+d2hlcmUoJGRiLT5xdW90ZU5hbWUoJHdoZXJlU3RyaW5nKSAuICcgJyAuICRvcGVyYXRvciAuICcgKCcgLiBpbXBsb2RlKCcsJywgJHdoZXJlKSAuICcpJyk7DQoJCQl9DQoNCgkJCSRkYi0+c2V0UXVlcnkoJHF1ZXJ5KTsNCgkJCSRkYi0+ZXhlY3V0ZSgpOw0KDQoJCQlpZiAoJGRiLT5nZXROdW1Sb3dzKCkpDQoJCQl7DQoJCQkJaWYgKCR1bmlxdWUpDQoJCQkJew0KCQkJCQlyZXR1cm4gYXJyYXlfdW5pcXVlKCRkYi0+bG9hZENvbHVtbigpKTsNCgkJCQl9DQoJCQkJcmV0dXJuICRkYi0+bG9hZENvbHVtbigpOw0KCQkJfQ0KCQl9DQoNCgkJcmV0dXJuIG51bGw7DQoJfQ0KDQoJLyoqDQoJICogZ2V0IGFsbCBzdHJpbmdzIGJldHdlZW4gdHdvIG90aGVyIHN0cmluZ3MNCgkgKiANCgkgKiBAcGFyYW0gIHN0cmluZyAgICAgICAkY29udGVudCAgICBUaGUgY29udGVudCB0byBzZWFyY2gNCgkgKiBAcGFyYW0gIHN0cmluZyAgICAgICAkc3RhcnQgICAgICBUaGUgc3RhcnRpbmcgdmFsdWUNCgkgKiBAcGFyYW0gIHN0cmluZyAgICAgICAkZW5kICAgICAgICBUaGUgZW5kaW5nIHZhbHVlDQoJICoNCgkgKiBAcmV0dXJuICBhcnJheXxudWxsICAgICAgICAgIE9uIHN1Y2Nlc3MNCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBhbGxCZXR3ZWVuKHN0cmluZyAkY29udGVudCwgc3RyaW5nICRzdGFydCwgc3RyaW5nICRlbmQpOiA/YXJyYXkNCgl7DQoJCS8vIHJlc2V0IGJ1Y2tldA0KCQkkYnVja2V0ID0gW107DQoJCWZvciAoJGkgPSAwOyA7ICRpKyspDQoJCXsNCgkJCS8vIHNlYXJjaCBmb3Igc3RyaW5nDQoJCQkkZm91bmQgPSBzZWxmOjpiZXR3ZWVuKCRjb250ZW50LCAkc3RhcnQsICRlbmQpOw0KDQoJCQlpZiAoU3RyaW5nSGVscGVyOjpjaGVjaygkZm91bmQpKQ0KCQkJew0KCQkJCS8vIGFkZCB0byBidWNrZXQNCgkJCQkkYnVja2V0W10gPSAkZm91bmQ7DQoNCgkJCQkvLyBidWlsZCByZW1vdmFsIHN0cmluZw0KCQkJCSRyZW1vdmUgPSAkc3RhcnQgLiAkZm91bmQgLiAkZW5kOw0KDQoJCQkJLy8gcmVtb3ZlIGZyb20gY29udGVudA0KCQkJCSRjb250ZW50ID0gc3RyX3JlcGxhY2UoJHJlbW92ZSwgJycsICRjb250ZW50KTsNCgkJCX0NCgkJCWVsc2UNCgkJCXsNCgkJCQlicmVhazsNCgkJCX0NCg0KCQkJLy8gc2FmZXR5IGNhdGNoDQoJCQlpZiAoJGkgPT0gNTAwKQ0KCQkJew0KCQkJCWJyZWFrOw0KCQkJfQ0KCQl9DQoNCgkJLy8gb25seSByZXR1cm4gdW5pcXVlIGFycmF5IG9mIHZhbHVlcw0KCQlpZiAoQXJyYXlIZWxwZXI6OmNoZWNrKCRidWNrZXQpKQ0KCQl7DQoJCQlyZXR1cm4gIGFycmF5X3VuaXF1ZSgkYnVja2V0KTsNCgkJfQ0KDQoJCXJldHVybiBudWxsOw0KCX0NCg0KCS8qKg0KCSAqIGdldCBhIHN0cmluZyBiZXR3ZWVuIHR3byBvdGhlciBzdHJpbmdzDQoJICogDQoJICogQHBhcmFtICBzdHJpbmcgICAgICAgJGNvbnRlbnQgICAgVGhlIGNvbnRlbnQgdG8gc2VhcmNoDQoJICogQHBhcmFtICBzdHJpbmcgICAgICAgJHN0YXJ0ICAgICAgVGhlIHN0YXJ0aW5nIHZhbHVlDQoJICogQHBhcmFtICBzdHJpbmcgICAgICAgJGVuZCAgICAgICAgVGhlIGVuZGluZyB2YWx1ZQ0KCSAqIEBwYXJhbSAgc3RyaW5nICAgICAgICRkZWZhdWx0ICAgIFRoZSBkZWZhdWx0IHZhbHVlIGlmIG5vbmUgZm91bmQNCgkgKg0KCSAqIEByZXR1cm4gIHN0cmluZyAgICAgICAgICBPbiBzdWNjZXNzIC8gZW1wdHkgc3RyaW5nIG9uIGZhaWx1cmUNCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBiZXR3ZWVuKHN0cmluZyAkY29udGVudCwgc3RyaW5nICRzdGFydCwgc3RyaW5nICRlbmQsIHN0cmluZyAkZGVmYXVsdCA9ICcnKTogc3RyaW5nDQoJew0KCQkkYXJyYXkgPSBleHBsb2RlKCRzdGFydCwgJGNvbnRlbnQpOw0KCQlpZiAoaXNzZXQoJGFycmF5WzFdKSAmJiBzdHJwb3MoJGFycmF5WzFdLCAkZW5kKSAhPT0gZmFsc2UpDQoJCXsNCgkJCSRhcnJheSA9IGV4cGxvZGUoJGVuZCwgJGFycmF5WzFdKTsNCg0KCQkJLy8gcmV0dXJuIHN0cmluZyBmb3VuZCBiZXR3ZWVuDQoJCQlyZXR1cm4gJGFycmF5WzBdOw0KCQl9DQoNCgkJcmV0dXJuICRkZWZhdWx0Ow0KCX0NCg==', '{}', 'GetHelper', 'VDM\\Joomla\\Utilities.GetHelper', '1.0.0', '{}', 'Utilities GetHelper', 'abstract class', '{\"use_selection0\":{\"use\":\"640b5352-fb09-425f-a26e-cd44eda03f15\",\"as\":\"default\"}}', '', 1, '2022-03-09 00:21:06', '2022-10-21 15:26:39', 27, 9),
+(17, 1, 'Some easy get...\r\n\r\n@since 3.0.9', '', '', 'db87c339-5bb6-4291-a7ef-2c48ea1b06bc', 'dXNlIEpvb21sYVxDTVNcRmFjdG9yeTs=', '', '', '{\"load_selection0\":{\"load\":\"0a59c65c-9daf-4bc9-baf4-e063ff9e6a8a\"},\"load_selection1\":{\"load\":\"1f28cb53-60d9-4db1-b517-3c7dc6b429ef\"}}', 'CS8qKg0KCSAqIEdldCBhIFZhcmlhYmxlIA0KCSAqDQoJICogQHBhcmFtICAgc3RyaW5nfG51bGwgICR0YWJsZSAgICAgICAgVGhlIHRhYmxlIGZyb20gd2hpY2ggdG8gZ2V0IHRoZSB2YXJpYWJsZQ0KCSAqIEBwYXJhbSAgIG1peGVkICAgICAgICAkd2hlcmUgICAgICAgIFRoZSB2YWx1ZSB3aGVyZQ0KCSAqIEBwYXJhbSAgIHN0cmluZyAgICAgICAkd2hlcmVTdHJpbmcgIFRoZSB0YXJnZXQvZmllbGQgc3RyaW5nIHdoZXJlL25hbWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJHdoYXQgICAgICAgICBUaGUgcmV0dXJuIGZpZWxkDQoJICogQHBhcmFtICAgc3RyaW5nICAgICAgICRvcGVyYXRvciAgICAgVGhlIG9wZXJhdG9yIGJldHdlZW4gJHdoZXJlU3RyaW5nL2ZpZWxkIGFuZCAkd2hlcmUvdmFsdWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJG1haW4gICAgICAgICBUaGUgY29tcG9uZW50IGluIHdoaWNoIHRoZSB0YWJsZSBpcyBmb3VuZA0KCSAqDQoJICogQHJldHVybiAgbWl4ZWQgc3RyaW5nL2ludC9mbG9hdA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHZhcig/c3RyaW5nICR0YWJsZSA9IG51bGwsICR3aGVyZSA9IG51bGwsDQoJCXN0cmluZyAkd2hlcmVTdHJpbmcgPSAndXNlcicsIHN0cmluZyAkd2hhdCA9ICdpZCcsDQoJCXN0cmluZyAkb3BlcmF0b3IgPSAnPScsID9zdHJpbmcgJG1haW4gPSBudWxsKQ0KCXsNCgkJaWYoZW1wdHkoJHdoZXJlKSkNCgkJew0KCQkJJHdoZXJlID0gRmFjdG9yeTo6Z2V0VXNlcigpLT5pZDsNCgkJfQ0KDQoJCWlmKGVtcHR5KCRtYWluKSkNCgkJew0KCQkJJG1haW4gPSBIZWxwZXI6OmdldENvZGUoKTsNCgkJfQ0KDQoJCS8vIEdldCBhIGRiIGNvbm5lY3Rpb24uDQoJCSRkYiA9IEZhY3Rvcnk6OmdldERibygpOw0KDQoJCS8vIENyZWF0ZSBhIG5ldyBxdWVyeSBvYmplY3QuDQoJCSRxdWVyeSA9ICRkYi0+Z2V0UXVlcnkodHJ1ZSk7DQoJCSRxdWVyeS0+c2VsZWN0KCRkYi0+cXVvdGVOYW1lKGFycmF5KCR3aGF0KSkpOw0KDQoJCWlmIChlbXB0eSgkdGFibGUpKQ0KCQl7DQoJCQkkcXVlcnktPmZyb20oJGRiLT5xdW90ZU5hbWUoJyNfXycgLiAkbWFpbikpOw0KCQl9DQoJCWVsc2UNCgkJew0KCQkJJHF1ZXJ5LT5mcm9tKCRkYi0+cXVvdGVOYW1lKCcjX18nIC4gJG1haW4gLiAnXycgLiAkdGFibGUpKTsNCgkJfQ0KDQoJCWlmIChpc19udW1lcmljKCR3aGVyZSkpDQoJCXsNCgkJCSRxdWVyeS0+d2hlcmUoJGRiLT5xdW90ZU5hbWUoJHdoZXJlU3RyaW5nKSAuICcgJyAuICRvcGVyYXRvciAuICcgJyAuIChpbnQpICR3aGVyZSk7DQoJCX0NCgkJZWxzZWlmIChpc19zdHJpbmcoJHdoZXJlKSkNCgkJew0KCQkJJHF1ZXJ5LT53aGVyZSgkZGItPnF1b3RlTmFtZSgkd2hlcmVTdHJpbmcpIC4gJyAnIC4gJG9wZXJhdG9yIC4gJyAnIC4gJGRiLT5xdW90ZSgoc3RyaW5nKSR3aGVyZSkpOw0KCQl9DQoJCWVsc2UNCgkJew0KCQkJcmV0dXJuIGZhbHNlOw0KCQl9DQoNCgkJJGRiLT5zZXRRdWVyeSgkcXVlcnkpOw0KCQkkZGItPmV4ZWN1dGUoKTsNCg0KCQlpZiAoJGRiLT5nZXROdW1Sb3dzKCkpDQoJCXsNCgkJCXJldHVybiAkZGItPmxvYWRSZXN1bHQoKTsNCgkJfQ0KDQoJCXJldHVybiBmYWxzZTsNCgl9DQoNCgkvKioNCgkgKiBHZXQgYXJyYXkgb2YgdmFyaWFibGVzDQoJICoNCgkgKiBAcGFyYW0gICBzdHJpbmd8bnVsbCAgJHRhYmxlICAgICAgICBUaGUgdGFibGUgZnJvbSB3aGljaCB0byBnZXQgdGhlIHZhcmlhYmxlcw0KCSAqIEBwYXJhbSAgIG1peGVkICAgICAgICAkd2hlcmUgICAgICAgIFRoZSB2YWx1ZSB3aGVyZQ0KCSAqIEBwYXJhbSAgIHN0cmluZyAgICAgICAkd2hlcmVTdHJpbmcgIFRoZSB0YXJnZXQvZmllbGQgc3RyaW5nIHdoZXJlL25hbWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJHdoYXQgICAgICAgICBUaGUgcmV0dXJuIGZpZWxkDQoJICogQHBhcmFtICAgc3RyaW5nICAgICAgICRvcGVyYXRvciAgICAgVGhlIG9wZXJhdG9yIGJldHdlZW4gJHdoZXJlU3RyaW5nL2ZpZWxkIGFuZCAkd2hlcmUvdmFsdWUNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAgICAgJG1haW4gICAgICAgICBUaGUgY29tcG9uZW50IGluIHdoaWNoIHRoZSB0YWJsZSBpcyBmb3VuZA0KCSAqIEBwYXJhbSAgIGJvb2wgICAgICAgICAkdW5pcXVlICAgICAgIFRoZSBzd2l0Y2ggdG8gcmV0dXJuIGEgdW5pcXVlIGFycmF5DQoJICoNCgkgKiBAcmV0dXJuICBhcnJheXxudWxsDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gdmFycyg/c3RyaW5nICR0YWJsZSA9IG51bGwsICR3aGVyZSA9IG51bGwsDQoJCXN0cmluZyAkd2hlcmVTdHJpbmcgPSAndXNlcicsIHN0cmluZyAkd2hhdCA9ICdpZCcsIHN0cmluZyAkb3BlcmF0b3IgPSAnSU4nLA0KCQk/c3RyaW5nICRtYWluID0gbnVsbCwgYm9vbCAkdW5pcXVlID0gdHJ1ZSk6ID9hcnJheQ0KCXsNCgkJaWYoZW1wdHkoJHdoZXJlKSkNCgkJew0KCQkJJHdoZXJlID0gRmFjdG9yeTo6Z2V0VXNlcigpLT5pZDsNCgkJfQ0KDQoJCWlmKGlzX251bGwoJG1haW4pKQ0KCQl7DQoJCQkkbWFpbiA9IEhlbHBlcjo6Z2V0Q29kZSgpOw0KCQl9DQoNCgkJaWYgKCFBcnJheUhlbHBlcjo6Y2hlY2soJHdoZXJlKSAmJiAkd2hlcmUgPiAwKQ0KCQl7DQoJCQkkd2hlcmUgPSBhcnJheSgkd2hlcmUpOw0KCQl9DQoNCgkJaWYgKEFycmF5SGVscGVyOjpjaGVjaygkd2hlcmUpKQ0KCQl7DQoJCQkvLyBwcmVwIG1haW4gPC0tIHdoeT8gd2VsbCBpZiAkbWFpbj0nJyBpcyBlbXB0eSB0aGVuICR0YWJsZSBjYW4gYmUgY2F0ZWdvcmllcyBvciB1c2Vycw0KCQkJaWYgKFN0cmluZ0hlbHBlcjo6Y2hlY2soJG1haW4pKQ0KCQkJew0KCQkJCSRtYWluID0gJ18nIC4gbHRyaW0oJG1haW4sICdfJyk7DQoJCQl9DQoNCgkJCS8vIEdldCBhIGRiIGNvbm5lY3Rpb24uDQoJCQkkZGIgPSBGYWN0b3J5OjpnZXREYm8oKTsNCg0KCQkJLy8gQ3JlYXRlIGEgbmV3IHF1ZXJ5IG9iamVjdC4NCgkJCSRxdWVyeSA9ICRkYi0+Z2V0UXVlcnkodHJ1ZSk7DQoJCQkkcXVlcnktPnNlbGVjdCgkZGItPnF1b3RlTmFtZShhcnJheSgkd2hhdCkpKTsNCg0KCQkJaWYgKGVtcHR5KCR0YWJsZSkpDQoJCQl7DQoJCQkJJHF1ZXJ5LT5mcm9tKCRkYi0+cXVvdGVOYW1lKCcjX18nIC4gJG1haW4pKTsNCgkJCX0NCgkJCWVsc2UNCgkJCXsNCgkJCQkkcXVlcnktPmZyb20oJGRiLT5xdW90ZU5hbWUoJyNfJyAuICRtYWluIC4gJ18nIC4gJHRhYmxlKSk7DQoJCQl9DQoNCgkJCS8vIGFkZCBzdHJpbmdzIHRvIGFycmF5IHNlYXJjaA0KCQkJaWYgKCdJTl9TVFJJTkdTJyA9PT0gJG9wZXJhdG9yIHx8ICdOT1QgSU5fU1RSSU5HUycgPT09ICRvcGVyYXRvcikNCgkJCXsNCgkJCQkkcXVlcnktPndoZXJlKCRkYi0+cXVvdGVOYW1lKCR3aGVyZVN0cmluZykgLiAnICcgLiBzdHJfcmVwbGFjZSgnX1NUUklOR1MnLCAnJywgJG9wZXJhdG9yKSAuICcgKCInIC4gaW1wbG9kZSgnIiwiJywgJHdoZXJlKSAuICciKScpOw0KCQkJfQ0KCQkJZWxzZQ0KCQkJew0KCQkJCSRxdWVyeS0+d2hlcmUoJGRiLT5xdW90ZU5hbWUoJHdoZXJlU3RyaW5nKSAuICcgJyAuICRvcGVyYXRvciAuICcgKCcgLiBpbXBsb2RlKCcsJywgJHdoZXJlKSAuICcpJyk7DQoJCQl9DQoNCgkJCSRkYi0+c2V0UXVlcnkoJHF1ZXJ5KTsNCgkJCSRkYi0+ZXhlY3V0ZSgpOw0KDQoJCQlpZiAoJGRiLT5nZXROdW1Sb3dzKCkpDQoJCQl7DQoJCQkJaWYgKCR1bmlxdWUpDQoJCQkJew0KCQkJCQlyZXR1cm4gYXJyYXlfdW5pcXVlKCRkYi0+bG9hZENvbHVtbigpKTsNCgkJCQl9DQoJCQkJcmV0dXJuICRkYi0+bG9hZENvbHVtbigpOw0KCQkJfQ0KCQl9DQoNCgkJcmV0dXJuIG51bGw7DQoJfQ0KDQoJLyoqDQoJICogZ2V0IGFsbCBzdHJpbmdzIGJldHdlZW4gdHdvIG90aGVyIHN0cmluZ3MNCgkgKiANCgkgKiBAcGFyYW0gIHN0cmluZyAgICAgICAkY29udGVudCAgICBUaGUgY29udGVudCB0byBzZWFyY2gNCgkgKiBAcGFyYW0gIHN0cmluZyAgICAgICAkc3RhcnQgICAgICBUaGUgc3RhcnRpbmcgdmFsdWUNCgkgKiBAcGFyYW0gIHN0cmluZyAgICAgICAkZW5kICAgICAgICBUaGUgZW5kaW5nIHZhbHVlDQoJICoNCgkgKiBAcmV0dXJuICBhcnJheXxudWxsICAgICAgICAgIE9uIHN1Y2Nlc3MNCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBhbGxCZXR3ZWVuKHN0cmluZyAkY29udGVudCwgc3RyaW5nICRzdGFydCwgc3RyaW5nICRlbmQpOiA/YXJyYXkNCgl7DQoJCS8vIHJlc2V0IGJ1Y2tldA0KCQkkYnVja2V0ID0gW107DQoJCWZvciAoJGkgPSAwOyA7ICRpKyspDQoJCXsNCgkJCS8vIHNlYXJjaCBmb3Igc3RyaW5nDQoJCQkkZm91bmQgPSBzZWxmOjpiZXR3ZWVuKCRjb250ZW50LCAkc3RhcnQsICRlbmQpOw0KDQoJCQlpZiAoU3RyaW5nSGVscGVyOjpjaGVjaygkZm91bmQpKQ0KCQkJew0KCQkJCS8vIGFkZCB0byBidWNrZXQNCgkJCQkkYnVja2V0W10gPSAkZm91bmQ7DQoNCgkJCQkvLyBidWlsZCByZW1vdmFsIHN0cmluZw0KCQkJCSRyZW1vdmUgPSAkc3RhcnQgLiAkZm91bmQgLiAkZW5kOw0KDQoJCQkJLy8gcmVtb3ZlIGZyb20gY29udGVudA0KCQkJCSRjb250ZW50ID0gc3RyX3JlcGxhY2UoJHJlbW92ZSwgJycsICRjb250ZW50KTsNCgkJCX0NCgkJCWVsc2UNCgkJCXsNCgkJCQlicmVhazsNCgkJCX0NCg0KCQkJLy8gc2FmZXR5IGNhdGNoDQoJCQlpZiAoJGkgPT0gNTAwKQ0KCQkJew0KCQkJCWJyZWFrOw0KCQkJfQ0KCQl9DQoNCgkJLy8gb25seSByZXR1cm4gdW5pcXVlIGFycmF5IG9mIHZhbHVlcw0KCQlpZiAoQXJyYXlIZWxwZXI6OmNoZWNrKCRidWNrZXQpKQ0KCQl7DQoJCQlyZXR1cm4gIGFycmF5X3VuaXF1ZSgkYnVja2V0KTsNCgkJfQ0KDQoJCXJldHVybiBudWxsOw0KCX0NCg0KCS8qKg0KCSAqIGdldCBhIHN0cmluZyBiZXR3ZWVuIHR3byBvdGhlciBzdHJpbmdzDQoJICogDQoJICogQHBhcmFtICBzdHJpbmcgICAgICAgJGNvbnRlbnQgICAgVGhlIGNvbnRlbnQgdG8gc2VhcmNoDQoJICogQHBhcmFtICBzdHJpbmcgICAgICAgJHN0YXJ0ICAgICAgVGhlIHN0YXJ0aW5nIHZhbHVlDQoJICogQHBhcmFtICBzdHJpbmcgICAgICAgJGVuZCAgICAgICAgVGhlIGVuZGluZyB2YWx1ZQ0KCSAqIEBwYXJhbSAgc3RyaW5nICAgICAgICRkZWZhdWx0ICAgIFRoZSBkZWZhdWx0IHZhbHVlIGlmIG5vbmUgZm91bmQNCgkgKg0KCSAqIEByZXR1cm4gIHN0cmluZyAgICAgICAgICBPbiBzdWNjZXNzIC8gZW1wdHkgc3RyaW5nIG9uIGZhaWx1cmUNCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBiZXR3ZWVuKHN0cmluZyAkY29udGVudCwgc3RyaW5nICRzdGFydCwgc3RyaW5nICRlbmQsIHN0cmluZyAkZGVmYXVsdCA9ICcnKTogc3RyaW5nDQoJew0KCQkkYXJyYXkgPSBleHBsb2RlKCRzdGFydCwgJGNvbnRlbnQpOw0KCQlpZiAoaXNzZXQoJGFycmF5WzFdKSAmJiBzdHJwb3MoJGFycmF5WzFdLCAkZW5kKSAhPT0gZmFsc2UpDQoJCXsNCgkJCSRhcnJheSA9IGV4cGxvZGUoJGVuZCwgJGFycmF5WzFdKTsNCg0KCQkJLy8gcmV0dXJuIHN0cmluZyBmb3VuZCBiZXR3ZWVuDQoJCQlyZXR1cm4gJGFycmF5WzBdOw0KCQl9DQoNCgkJcmV0dXJuICRkZWZhdWx0Ow0KCX0NCg==', '{}', 'GetHelper', 'VDM\\Joomla\\Utilities.GetHelper', '1.0.0', '{}', 'Utilities GetHelper', 'abstract class', '{\"use_selection0\":{\"use\":\"640b5352-fb09-425f-a26e-cd44eda03f15\",\"as\":\"default\"}}', '', 1, '2022-03-09 00:21:06', '2023-01-18 22:46:18', 26, 9),
(18, '', 'Some object tricks\r\n\r\n@since 3.0.9', '', '', '91004529-94a9-4590-b842-e7c6b624ecf5', '', '', '', '{}', 'CS8qKg0KCSAqIENoZWNrIGlmIGhhdmUgYW4gb2JqZWN0IHdpdGggYSBsZW5ndGgNCgkgKg0KCSAqIEBpbnB1dAlvYmplY3QgICBUaGUgb2JqZWN0IHRvIGNoZWNrDQoJICoNCgkgKiBAcmV0dXJucyBib29sIHRydWUgb24gc3VjY2Vzcw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGNoZWNrKCRvYmplY3QpDQoJew0KCQlpZiAoaXNfb2JqZWN0KCRvYmplY3QpKQ0KCQl7DQoJCQlyZXR1cm4gY291bnQoKGFycmF5KSAkb2JqZWN0KSA+IDA7DQoJCX0NCg0KCQlyZXR1cm4gZmFsc2U7DQoJfQ0K', '{}', 'ObjectHelper', 'VDM\\Joomla\\Utilities.ObjectHelper', '1.0.0', '{}', 'Utilities Object Helper', 'abstract class', '{}', '', 1, '2022-03-09 00:35:23', '2022-09-20 09:51:31', 15, 8),
(19, '', 'Basic Math Helper\r\n\r\n@since 3.0.9', '', '', '152c8793-8b75-4715-996a-257b9f65451c', '', '', '', '{}', 'CS8qKg0KCSAqIGJjIG1hdGggd3JhcHBlciAodmVyeSBiYXNpYyBub3QgZm9yIGFjY291bnRpbmcpDQoJICoNCgkgKiBAcGFyYW0gICBzdHJpbmcgICAkdHlwZSAgICBUaGUgdHlwZSBiYyBtYXRoDQoJICogQHBhcmFtICAgaW50ICAgICAgJHZhbDEgICAgVGhlIGZpcnN0IHZhbHVlDQoJICogQHBhcmFtICAgaW50ICAgICAgJHZhbDIgICAgVGhlIHNlY29uZCB2YWx1ZQ0KCSAqIEBwYXJhbSAgIGludCAgICAgICRzY2FsZSAgIFRoZSBzY2FsZSB2YWx1ZQ0KCSAqDQoJICogQHJldHVybiBpbnQNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBiYygkdHlwZSwgJHZhbDEsICR2YWwyLCAkc2NhbGUgPSAwKQ0KCXsNCgkJLy8gYnVpbGQgZnVuY3Rpb24gbmFtZQ0KCQkkZnVuY3Rpb24gPSAnYmMnIC4gJHR5cGU7DQoJCS8vIHVzZSB0aGUgYmNtYXRoIGZ1bmN0aW9uIGlmIGF2YWlsYWJsZQ0KCQlpZiAoZnVuY3Rpb25fZXhpc3RzKCRmdW5jdGlvbikpDQoJCXsNCgkJCXJldHVybiAkZnVuY3Rpb24oJHZhbDEsICR2YWwyLCAkc2NhbGUpOw0KCQl9DQoJCS8vIGlmIGZ1bmN0aW9uIGRvZXMgbm90IGV4aXN0IHdlIHVzZSArLSovIG9wZXJhdG9ycyAoZmFsbGJhY2sgLSBub3QgaWRlYWwpDQoJCXN3aXRjaCAoJHR5cGUpDQoJCXsNCgkJCS8vIE11bHRpcGx5IHR3byBudW1iZXJzDQoJCQljYXNlICdtdWwnOg0KCQkJCXJldHVybiAoc3RyaW5nKSByb3VuZCgkdmFsMSAqICR2YWwyLCAkc2NhbGUpOw0KCQkJCWJyZWFrOw0KCQkJLy8gRGl2aWRlIG9mIHR3byBudW1iZXJzDQoJCQljYXNlICdkaXYnOg0KCQkJCXJldHVybiAoc3RyaW5nKSByb3VuZCgkdmFsMSAvICR2YWwyLCAkc2NhbGUpOw0KCQkJCWJyZWFrOw0KCQkJLy8gQWRkaW5nIHR3byBudW1iZXJzDQoJCQljYXNlICdhZGQnOg0KCQkJCXJldHVybiAoc3RyaW5nKSByb3VuZCgkdmFsMSArICR2YWwyLCAkc2NhbGUpOw0KCQkJCWJyZWFrOw0KCQkJLy8gU3VidHJhY3Qgb25lIG51bWJlciBmcm9tIHRoZSBvdGhlcg0KCQkJY2FzZSAnc3ViJzoNCgkJCQlyZXR1cm4gKHN0cmluZykgcm91bmQoJHZhbDEgLSAkdmFsMiwgJHNjYWxlKTsNCgkJCQlicmVhazsNCgkJCS8vIFJhaXNlIGFuIGFyYml0cmFyeSBwcmVjaXNpb24gbnVtYmVyIHRvIGFub3RoZXINCgkJCWNhc2UgJ3Bvdyc6DQoJCQkJcmV0dXJuIChzdHJpbmcpIHJvdW5kKHBvdygkdmFsMSwgJHZhbDIpLCAkc2NhbGUpOw0KCQkJCWJyZWFrOw0KCQkJLy8gQ29tcGFyZSB0d28gYXJiaXRyYXJ5IHByZWNpc2lvbiBudW1iZXJzDQoJCQljYXNlICdjb21wJzoNCgkJCQlyZXR1cm4gKHJvdW5kKCR2YWwxLDIpID09IHJvdW5kKCR2YWwyLDIpKTsNCgkJCQlicmVhazsNCgkJfQ0KCQlyZXR1cm4gZmFsc2U7DQoJfQ0KDQoJLyoqDQoJICogQmFzaWMgc3VtIG9mIGFuIGFycmF5IHdpdGggbW9yZSBwcmVjaXNpb24NCgkgKg0KCSAqIEBwYXJhbSAgIGFycmF5ICAgJGFycmF5ICAgIFRoZSB2YWx1ZXMgdG8gc3VtDQoJICogQHBhcmFtICAgaW50ICAgICAgJHNjYWxlICAgVGhlIHNjYWxlIHZhbHVlDQoJICoNCgkgKiBAcmV0dXJuIGZsb2F0DQoJICogDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gc3VtKCRhcnJheSwgJHNjYWxlID0gNCkNCgl7DQoJCS8vIHVzZSB0aGUgYmNhZGQgZnVuY3Rpb24gaWYgYXZhaWxhYmxlDQoJCWlmIChmdW5jdGlvbl9leGlzdHMoJ2JjYWRkJykpDQoJCXsNCgkJCS8vIHNldCB0aGUgc3RhcnQgdmFsdWUNCgkJCSR2YWx1ZSA9IDAuMDsNCgkJCS8vIGxvb3AgdGhlIHZhbHVlcyBhbmQgcnVuIGJjYWRkDQoJCQlmb3JlYWNoKCRhcnJheSBhcyAkdmFsKQ0KCQkJew0KCQkJCSR2YWx1ZSA9IGJjYWRkKCR2YWx1ZSwgJHZhbCwgJHNjYWxlKTsNCgkJCX0NCgkJCXJldHVybiAkdmFsdWU7DQoJCX0NCgkJLy8gZmFsbCBiYWNrIG9uIGFycmF5IHN1bQ0KCQlyZXR1cm4gYXJyYXlfc3VtKCRhcnJheSk7DQoJfQ0K', '{}', 'MathHelper', 'VDM\\Joomla\\Utilities.MathHelper', '1.0.0', '{}', 'Utilities Math Helper', 'abstract class', '{}', '', 1, '2022-03-09 13:05:39', '2022-09-20 09:51:26', 11, 9),
(20, '', 'Control the naming of a plugin\r\n\r\n@since 3.0.9', '', '', '3cf76fbf-fd95-4a33-878e-7aff6d36b7f6', '', '', '', '{}', 'CS8qKg0KCSAqIE1ha2luZyBwbHVnaW4gZm9sZGVyIG5hbWUgc2FmZQ0KCSAqDQoJICogQGlucHV0CXN0cmluZyAgICAkY29kZU5hbWUgICBUaGUgbmFtZQ0KCSAqIEBpbnB1dAlzdHJpbmcgICAgJGdyb3VwICAgVGhlIGdyb3VwIG5hbWUNCgkgKg0KCSAqIEByZXR1cm5zIHN0cmluZyBvbiBzdWNjZXNzDQoJICogDQoJICogQHNpbmNlICAzLjAuOQ0KCSAqLw0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gc2FmZUZvbGRlck5hbWUoc3RyaW5nICRjb2RlTmFtZSwgc3RyaW5nICRncm91cCk6IHN0cmluZw0KCXsNCgkJLy8gZWRpdG9ycy14dGQgZ3JvdXAgcGx1Z2lucyBtdXN0IGhhdmUgYSBjbGFzcyB3aXRoIHBsZ0J1dHRvbjxQbHVnaW5OYW1lPiBzdHJ1Y3R1cmUNCgkJaWYgKCRncm91cCA9PT0gJ2VkaXRvcnMteHRkJykNCgkJew0KCQkJJGdyb3VwID0gJ0J1dHRvbic7DQoJCX0NCg0KCQlyZXR1cm4gJ3BsZ18nIC4gc3RydG9sb3dlcigkZ3JvdXApIC4gJ18nIC4gc3RydG9sb3dlcigNCgkJCSRjb2RlTmFtZQ0KCQkpOw0KCX0NCg0KCS8qKg0KCSAqIE1ha2luZyBwbHVnaW4gY2xhc3MgbmFtZSBzYWZlDQoJICoNCgkgKiBAaW5wdXQJc3RyaW5nICAgICRjb2RlTmFtZSAgIFRoZSBuYW1lDQoJICogQGlucHV0CXN0cmluZyAgICAkZ3JvdXAgICBUaGUgZ3JvdXAgbmFtZQ0KCSAqDQoJICogQHJldHVybnMgc3RyaW5nIG9uIHN1Y2Nlc3MNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBzYWZlQ2xhc3NOYW1lKHN0cmluZyAkY29kZU5hbWUsIHN0cmluZyAkZ3JvdXApOiBzdHJpbmcNCgl7DQoJCS8vIGVkaXRvcnMteHRkIGdyb3VwIHBsdWdpbnMgbXVzdCBoYXZlIGEgY2xhc3Mgd2l0aCBwbGdCdXR0b248UGx1Z2luTmFtZT4gc3RydWN0dXJlDQoJCWlmICgkZ3JvdXAgPT09ICdlZGl0b3JzLXh0ZCcpDQoJCXsNCgkJCSRncm91cCA9ICdCdXR0b24nOw0KCQl9DQoNCgkJcmV0dXJuICdQbGcnIC4gdWNmaXJzdCgkZ3JvdXApIC4gdWNmaXJzdCgNCgkJCSRjb2RlTmFtZQ0KCQkpOw0KCX0NCg0KCS8qKg0KCSAqIE1ha2luZyBwbHVnaW4gaW5zdGFsbCBjbGFzcyBuYW1lIHNhZmUNCgkgKg0KCSAqIEBpbnB1dAlzdHJpbmcgICAgJGNvZGVOYW1lICAgVGhlIG5hbWUNCgkgKiBAaW5wdXQJc3RyaW5nICAgICRncm91cCAgIFRoZSBncm91cCBuYW1lDQoJICoNCgkgKiBAcmV0dXJucyBzdHJpbmcgb24gc3VjY2Vzcw0KCSAqIA0KCSAqIEBzaW5jZSAgMy4wLjkNCgkgKi8NCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHNhZmVJbnN0YWxsQ2xhc3NOYW1lKHN0cmluZyAkY29kZU5hbWUsIHN0cmluZyAkZ3JvdXApOiBzdHJpbmcNCgl7DQoJCS8vIGVkaXRvcnMteHRkIGdyb3VwIHBsdWdpbnMgbXVzdCBoYXZlIGEgY2xhc3Mgd2l0aCBwbGdCdXR0b248UGx1Z2luTmFtZT4gc3RydWN0dXJlDQoJCWlmICgkZ3JvdXAgPT09ICdlZGl0b3JzLXh0ZCcpDQoJCXsNCgkJCSRncm91cCA9ICdCdXR0b24nOw0KCQl9DQoNCgkJcmV0dXJuICdwbGcnIC4gdWNmaXJzdCgkZ3JvdXApIC4gdWNmaXJzdCgNCgkJCSRjb2RlTmFtZQ0KCQkpIC4gJ0luc3RhbGxlclNjcmlwdCc7DQoJfQ0KDQoJLyoqDQoJICogTWFraW5nIGxhbmd1YWdlIHByZWZpeCBzYWZlDQoJICoNCgkgKiBAaW5wdXQJc3RyaW5nICAgICRjb2RlTmFtZSAgIFRoZSBuYW1lDQoJICogQGlucHV0CXN0cmluZyAgICAkZ3JvdXAgICBUaGUgZ3JvdXAgbmFtZQ0KCSAqDQoJICogQHJldHVybnMgc3RyaW5nIG9uIHN1Y2Nlc3MNCgkgKiANCgkgKiBAc2luY2UgIDMuMC45DQoJICovDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBzYWZlTGFuZ1ByZWZpeChzdHJpbmcgJGNvZGVOYW1lLCBzdHJpbmcgJGdyb3VwKTogc3RyaW5nDQoJew0KCQkvLyBlZGl0b3JzLXh0ZCBncm91cCBwbHVnaW5zIG11c3QgaGF2ZSBhIGNsYXNzIHdpdGggcGxnQnV0dG9uPFBsdWdpbk5hbWU+IHN0cnVjdHVyZQ0KCQlpZiAoJGdyb3VwID09PSAnZWRpdG9ycy14dGQnKQ0KCQl7DQoJCQkkZ3JvdXAgPSAnQnV0dG9uJzsNCgkJfQ0KDQoJCXJldHVybiAnUExHXycgLiBzdHJ0b3VwcGVyKCRncm91cCkgLiAnXycgLiBzdHJ0b3VwcGVyKA0KCQkJJGNvZGVOYW1lDQoJCSk7DQoJfQ0K', '{}', 'PluginHelper', 'VDM\\Joomla\\Utilities.String.PluginHelper', '1.0.0', '{}', 'String Plugin Helper', 'abstract class', '{}', '', 1, '2022-03-09 14:44:58', '2023-01-14 18:00:42', 16, 5),
diff --git a/componentbuilder.xml b/componentbuilder.xml
index d15b0072a..c2c1075dd 100644
--- a/componentbuilder.xml
+++ b/componentbuilder.xml
@@ -1,7 +1,7 @@
COM_COMPONENTBUILDER
- 1st January, 2023
+ 8th January, 2023
Llewellyn van der Merwe
joomla@vdm.io
https://dev.vdm.io
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Abstraction/Mapper.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Abstraction/Mapper.php
new file mode 100644
index 000000000..50e889b42
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Abstraction/Mapper.php
@@ -0,0 +1,259 @@
+
+ * @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\Abstraction;
+
+
+use VDM\Joomla\Componentbuilder\Interfaces\Mapperdoubleinterface;
+use VDM\Joomla\Componentbuilder\Interfaces\Mappersingleinterface;
+
+
+/**
+ * Compiler Mapper
+ *
+ * @since 3.2.0
+ */
+abstract class Mapper implements Mapperdoubleinterface, Mappersingleinterface
+{
+
+ /**
+ * The Content
+ *
+ * @var array
+ * @since 3.2.0
+ **/
+ public array $active = [];
+
+ /**
+ * Set content
+ *
+ * @param string $key The main string key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function set(string $key, $value)
+ {
+ $this->active[$this->key($key)] = $value;
+ }
+
+ /**
+ * Get content
+ *
+ * @param string $key The main string key
+ * @param mixed $value The values to set
+ *
+ * @return mixed
+ * @since 3.2.0
+ */
+ public function get(string $key)
+ {
+ return $this->active[$this->key($key)] ?? null;
+ }
+
+ /**
+ * Does key exist
+ *
+ * @param string $key The main string key
+ *
+ * @return bool
+ * @since 3.2.0
+ */
+ public function exist(string $key): bool
+ {
+ if (isset($this->active[$this->key($key)]))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Add content
+ *
+ * @param string $key The main string key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function add(string $key, $value)
+ {
+ if (isset($this->active[$this->key($key)]))
+ {
+ $this->active[$this->key($key)] .= $value;
+ }
+ else
+ {
+ $this->active[$this->key($key)] = $value;
+ }
+ }
+
+ /**
+ * Remove content
+ *
+ * @param string $key The main string key
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function remove(string $key)
+ {
+ unset($this->active[$this->key($key)]);
+ }
+
+ /**
+ * Model the key
+ *
+ * @param string $key The key to model
+ *
+ * @return string
+ * @since 3.2.0
+ */
+ abstract protected function key(string $key): string;
+
+ /**
+ * The Dynamic Content
+ *
+ * @var array
+ * @since 3.2.0
+ **/
+ public array $_active = [];
+
+ /**
+ * Set dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string $secondKey The second key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function set_(string $firstKey, string $secondKey, $value)
+ {
+ $this->_active[$this->firstKey($firstKey)]
+ [$this->secondKey($secondKey)] = $value;
+ }
+
+ /**
+ * Get dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string $secondKey The second key
+ *
+ * @return mixed
+ * @since 3.2.0
+ */
+ public function get_(string $firstKey, ?string $secondKey = null)
+ {
+ if (is_string($secondKey))
+ {
+ return $this->_active[$this->firstKey($firstKey)]
+ [$this->secondKey($secondKey)] ?? null;
+ }
+ return $this->_active[$this->firstKey($firstKey)] ?? null;
+ }
+
+ /**
+ * Does keys exist
+ *
+ * @param string $firstKey The first key
+ * @param string|null $secondKey The second key
+ *
+ * @return bool
+ * @since 3.2.0
+ */
+ public function exist_(string $firstKey, ?string $secondKey = null): bool
+ {
+ if (is_string($secondKey) && isset($this->_active[$this->firstKey($firstKey)]) &&
+ isset($this->_active[$this->firstKey($firstKey)]
+ [$this->secondKey($secondKey)]))
+ {
+ return true;
+ }
+ elseif (is_null($secondKey) && isset($this->_active[$this->firstKey($firstKey)]))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Add dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string $secondKey The second key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function add_(string $firstKey, string $secondKey, $value)
+ {
+ if (isset($this->_active[$this->firstKey($firstKey)]) &&
+ isset($this->_active[$this->firstKey($firstKey)]
+ [$this->secondKey($secondKey)]))
+ {
+ $this->_active[$this->firstKey($firstKey)]
+ [$this->secondKey($secondKey)] .= $value;
+ }
+ else
+ {
+ $this->_active[$this->firstKey($firstKey)]
+ [$this->secondKey($secondKey)] = $value;
+ }
+ }
+
+ /**
+ * Remove dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string|null $secondKey The second key
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function remove_(string $firstKey, ?string $secondKey = null)
+ {
+ if (is_string($secondKey))
+ {
+ unset($this->_active[$this->firstKey($firstKey)]
+ [$this->secondKey($secondKey)]);
+ }
+ else
+ {
+ unset($this->_active[$this->firstKey($firstKey)]);
+ }
+ }
+
+ /**
+ * Model the first key
+ *
+ * @param string $key The first key to model
+ *
+ * @return string
+ * @since 3.2.0
+ */
+ abstract protected function firstKey(string $key): string;
+
+ /**
+ * Model the second key
+ *
+ * @param string $key The second key to model
+ *
+ * @return string
+ * @since 3.2.0
+ */
+ abstract protected function secondKey(string $key): string;
+}
+
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Content.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Content.php
index f4e3e35df..bbde8a29b 100644
--- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Content.php
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Content.php
@@ -13,6 +13,9 @@ namespace VDM\Joomla\Componentbuilder\Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Utilities\Placefix;
+use VDM\Joomla\Componentbuilder\Interfaces\Mapperdoubleinterface;
+use VDM\Joomla\Componentbuilder\Interfaces\Mappersingleinterface;
+use VDM\Joomla\Componentbuilder\Abstraction\Mapper;
/**
@@ -20,202 +23,45 @@ use VDM\Joomla\Componentbuilder\Compiler\Utilities\Placefix;
*
* @since 3.2.0
*/
-class Content
+class Content extends Mapper implements Mapperdoubleinterface, Mappersingleinterface
{
/**
- * The Content
+ * Model the key
*
- * @var array
- * @since 3.2.0
- **/
- public array $active = [];
-
- /**
- * The Dynamic Content
+ * @param string $key The key to model
*
- * @var array
- * @since 3.2.0
- **/
- public array $_active = [];
-
- /**
- * Set content
- *
- * @param string $key The main string key
- * @param mixed $value The values to set
- *
- * @return void
+ * @return string
* @since 3.2.0
*/
- public function set(string $key, $value)
+ protected function key(string $key): string
{
- $this->active[Placefix::_h($key)] = $value;
+ return Placefix::_h($key);
}
/**
- * Get content
+ * Model the first key
*
- * @param string $key The main string key
- * @param mixed $value The values to set
+ * @param string $key The first key to model
*
- * @return mixed
+ * @return string
* @since 3.2.0
*/
- public function get(string $key)
+ protected function firstKey(string $key): string
{
- return $this->active[Placefix::_h($key)] ?? null;
+ return $key;
}
/**
- * Does key exist
+ * Model the second key
*
- * @param string $key The main string key
+ * @param string $key The second key to model
*
- * @return bool
+ * @return string
* @since 3.2.0
*/
- public function exist(string $key): bool
+ protected function secondKey(string $key): string
{
- if (isset($this->active[Placefix::_h($key)]))
- {
- return true;
- }
- return false;
- }
-
- /**
- * Add content
- *
- * @param string $key The main string key
- * @param mixed $value The values to set
- *
- * @return void
- * @since 3.2.0
- */
- public function add(string $key, $value)
- {
- if (isset($this->active[Placefix::_h($key)]))
- {
- $this->active[Placefix::_h($key)] .= $value;
- }
- else
- {
- $this->active[Placefix::_h($key)] = $value;
- }
- }
-
- /**
- * Remove content
- *
- * @param string $key The main string key
- *
- * @return void
- * @since 3.2.0
- */
- public function remove(string $key)
- {
- unset($this->active[Placefix::_h($key)]);
- }
-
- /**
- * Set dynamic content
- *
- * @param string $view The view key
- * @param string $key The main string key
- * @param mixed $value The values to set
- *
- * @return void
- * @since 3.2.0
- */
- public function set_(string $view, string $key, $value)
- {
- $this->_active[$view][Placefix::_h($key)] = $value;
- }
-
- /**
- * Get dynamic content
- *
- * @param string $view The view key
- * @param string|null $key The main string key
- *
- * @return mixed
- * @since 3.2.0
- */
- public function get_(string $view, ?string $key = null)
- {
- if (is_string($key))
- {
- return $this->_active[$view][Placefix::_h($key)] ?? null;
- }
- return $this->_active[$view] ?? null;
- }
-
- /**
- * Does view key exist
- *
- * @param string $view The view key
- * @param string|null $key The main string key
- *
- * @return bool
- * @since 3.2.0
- */
- public function exist_(string $view, ?string $key = null): bool
- {
- if (is_string($key) && isset($this->_active[$view]) &&
- isset($this->_active[$view][Placefix::_h($key)]))
- {
- return true;
- }
- elseif (is_null($key) && isset($this->_active[$view]))
- {
- return true;
- }
- return false;
- }
-
- /**
- * Add dynamic content
- *
- * @param string $view The view key
- * @param string $key The main string key
- * @param mixed $value The values to set
- *
- * @return void
- * @since 3.2.0
- */
- public function add_(string $view, string $key, $value)
- {
- if (isset($this->_active[$view]) &&
- isset($this->_active[$view][Placefix::_h($key)]))
- {
- $this->_active[$view][Placefix::_h($key)] .= $value;
- }
- else
- {
- $this->_active[$view][Placefix::_h($key)] = $value;
- }
- }
-
- /**
- * Remove dynamic content
- *
- * @param string $view The view key
- * @param string|null $key The main string key
- *
- * @return void
- * @since 3.2.0
- */
- public function remove_(string $view, ?string $key = null)
- {
- if (is_string($key))
- {
- unset($this->_active[$view][Placefix::_h($key)]);
- }
- else
- {
- unset($this->_active[$view]);
- }
- }
-
+ return Placefix::_h($key);
+ }
}
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php
index 66ea8fb3d..c501b2519 100644
--- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Factory.php
@@ -17,6 +17,7 @@ use VDM\Joomla\Componentbuilder\Service\Crypt;
use VDM\Joomla\Componentbuilder\Service\Server;
use VDM\Joomla\Componentbuilder\Compiler\Service\Database;
use VDM\Joomla\Componentbuilder\Compiler\Service\Model;
+use VDM\Joomla\Componentbuilder\Compiler\Service\Mapper;
use VDM\Joomla\Componentbuilder\Compiler\Service\Compiler;
use VDM\Joomla\Componentbuilder\Compiler\Service\Event;
use VDM\Joomla\Componentbuilder\Compiler\Service\History;
@@ -113,6 +114,7 @@ abstract class Factory implements FactoryInterface
->registerServiceProvider(new Server())
->registerServiceProvider(new Database())
->registerServiceProvider(new Model())
+ ->registerServiceProvider(new Mapper())
->registerServiceProvider(new Compiler())
->registerServiceProvider(new Event())
->registerServiceProvider(new History())
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Service/Compiler.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Service/Compiler.php
index c2c332f46..de5451e6f 100644
--- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Service/Compiler.php
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Service/Compiler.php
@@ -16,7 +16,6 @@ use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use VDM\Joomla\Componentbuilder\Compiler\Config;
use VDM\Joomla\Componentbuilder\Compiler\Registry;
-use VDM\Joomla\Componentbuilder\Compiler\Content;
/**
@@ -41,9 +40,6 @@ class Compiler implements ServiceProviderInterface
$container->alias(Registry::class, 'Registry')
->share('Registry', [$this, 'getRegistry'], true);
-
- $container->alias(Content::class, 'Content')
- ->share('Content', [$this, 'getContent'], true);
}
/**
@@ -71,19 +67,6 @@ class Compiler implements ServiceProviderInterface
{
return new Registry();
}
-
- /**
- * Get the Compiler Content
- *
- * @param Container $container The DI container.
- *
- * @return Content
- * @since 3.2.0
- */
- public function getContent(Container $container): Content
- {
- return new Content();
- }
}
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Service/Mapper.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Service/Mapper.php
new file mode 100644
index 000000000..8860641c2
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Service/Mapper.php
@@ -0,0 +1,55 @@
+
+ * @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\Compiler\Service;
+
+
+use Joomla\DI\Container;
+use Joomla\DI\ServiceProviderInterface;
+use VDM\Joomla\Componentbuilder\Compiler\Content;
+
+
+/**
+ * Mapper Service Provider
+ *
+ * @since 3.2.0
+ */
+class Mapper implements ServiceProviderInterface
+{
+ /**
+ * Registers the service provider with a DI container.
+ *
+ * @param Container $container The DI container.
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function register(Container $container)
+ {
+ $container->alias(Content::class, 'Content')
+ ->share('Content', [$this, 'getContent'], true);
+ }
+
+ /**
+ * Get the Compiler Content
+ *
+ * @param Container $container The DI container.
+ *
+ * @return Content
+ * @since 3.2.0
+ */
+ public function getContent(Container $container): Content
+ {
+ return new Content();
+ }
+
+}
+
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Utilities/Minify.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Utilities/Minify.php
new file mode 100644
index 000000000..b6b4daacd
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Compiler/Utilities/Minify.php
@@ -0,0 +1,91 @@
+
+ * @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\Compiler\Utilities;
+
+
+use VDM\Minify\Css;
+use VDM\Minify\JavaScript;
+
+
+/**
+ * Compiler Minifier
+ *
+ * @since 3.2.0
+ */
+abstract class Minify
+{
+ /**
+ * Minify JavaScript Class
+ *
+ * @var JavaScript
+ * @since 3.2.0
+ */
+ public static JavaScript $js;
+
+ /**
+ * Minify Css Class
+ *
+ * @var Css
+ * @since 3.2.0
+ */
+ public static Css $css;
+
+ /**
+ * Minify JavaScript
+ *
+ * @param string $data
+ *
+ * @return string
+ * @since 3.2.0
+ */
+ public static function js(string $data): string
+ {
+ // check if instance already set
+ if (empty(self::$js))
+ {
+ // set instanceof on JavaScript
+ self::$js = new JavaScript;
+ }
+
+ // add the data
+ self::$js->add($data);
+
+ // return minified
+ return self::$js->minify();
+ }
+
+ /**
+ * Minify Css
+ *
+ * @param string $data
+ *
+ * @return string
+ * @since 3.2.0
+ */
+ public static function css(string $data): string
+ {
+ // check if instance already set
+ if (empty(self::$css))
+ {
+ // set instanceof on Css
+ self::$css = new Css;
+ }
+
+ // add the data
+ self::$css->add($data);
+
+ // return minified
+ return self::$css->minify();
+ }
+
+}
+
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Interfaces/Mapperdoubleinterface.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Interfaces/Mapperdoubleinterface.php
new file mode 100644
index 000000000..8b1cc8caf
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Interfaces/Mapperdoubleinterface.php
@@ -0,0 +1,78 @@
+
+ * @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\Interfaces;
+
+
+/**
+ * The Double Mapper Interface
+ */
+interface Mapperdoubleinterface
+{
+ /**
+ * Set dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string $secondKey The second key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function set_(string $firstKey, string $secondKey, $value);
+
+ /**
+ * Get dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string $secondKey The second key
+ *
+ * @return mixed
+ * @since 3.2.0
+ */
+ public function get_(string $firstKey, ?string $secondKey = null);
+
+ /**
+ * Does keys exist
+ *
+ * @param string $firstKey The first key
+ * @param string|null $secondKey The second key
+ *
+ * @return bool
+ * @since 3.2.0
+ */
+ public function exist_(string $firstKey, ?string $secondKey = null): bool;
+
+ /**
+ * Add dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string $secondKey The second key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function add_(string $firstKey, string $secondKey, $value);
+
+ /**
+ * Remove dynamic content
+ *
+ * @param string $firstKey The first key
+ * @param string|null $secondKey The second key
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function remove_(string $firstKey, ?string $secondKey = null);
+
+}
+
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Interfaces/Mappersingleinterface.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Interfaces/Mappersingleinterface.php
new file mode 100644
index 000000000..dcaa949bc
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Interfaces/Mappersingleinterface.php
@@ -0,0 +1,74 @@
+
+ * @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\Interfaces;
+
+
+/**
+ * The Single Mapper Interface
+ */
+interface Mappersingleinterface
+{
+ /**
+ * Set content
+ *
+ * @param string $key The main string key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function set(string $key, $value);
+
+ /**
+ * Get content
+ *
+ * @param string $key The main string key
+ * @param mixed $value The values to set
+ *
+ * @return mixed
+ * @since 3.2.0
+ */
+ public function get(string $key);
+
+ /**
+ * Does key exist
+ *
+ * @param string $key The main string key
+ *
+ * @return bool
+ * @since 3.2.0
+ */
+ public function exist(string $key): bool;
+
+ /**
+ * Add content
+ *
+ * @param string $key The main string key
+ * @param mixed $value The values to set
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function add(string $key, $value);
+
+ /**
+ * Remove content
+ *
+ * @param string $key The main string key
+ *
+ * @return void
+ * @since 3.2.0
+ */
+ public function remove(string $key);
+
+}
+
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Server/Model/Load.php b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Server/Model/Load.php
index 0fedf8e0a..2e7d54d41 100644
--- a/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Server/Model/Load.php
+++ b/libraries/jcb_powers/VDM.Joomla/src/Componentbuilder/Server/Model/Load.php
@@ -101,6 +101,7 @@ class Load extends Model implements ModelInterface
break;
}
}
+
return $value;
}
diff --git a/libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php b/libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php
index 1046f2c56..135629a82 100644
--- a/libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php
+++ b/libraries/jcb_powers/VDM.Joomla/src/Utilities/ArrayHelper.php
@@ -24,9 +24,9 @@ abstract class ArrayHelper
*
* @input array The array to check
*
- * @returns bool/int number of items in array on success
+ * @returns int|false number of items in array on success
*
- * @since 3.0.9
+ * @since 3.2.0
*/
public static function check($array, $removeEmptyString = false)
{
@@ -35,17 +35,19 @@ abstract class ArrayHelper
// also make sure the empty strings are removed
if ($removeEmptyString)
{
- foreach ($array as $key => $string)
+ $array = array_filter($array);
+
+ if (empty($array))
{
- if (empty($string))
- {
- unset($array[$key]);
- }
+ return false;
}
- return self::check($array, false);
+
+ return count($array);
}
+
return $nr;
}
+
return false;
}
@@ -54,25 +56,25 @@ abstract class ArrayHelper
*
* @input array The arrays you would like to merge
*
- * @returns array on success
+ * @returns array|null merged array on success
*
* @since 3.0.9
*/
- public static function merge($arrays)
+ public static function merge($arrays): ?array
{
if(self::check($arrays))
{
- $arrayBuket = array();
+ $merged = [];
foreach ($arrays as $array)
{
if (self::check($array))
{
- $arrayBuket = array_merge($arrayBuket, $array);
+ $merged = array_merge($merged, $array);
}
}
- return $arrayBuket;
+ return $merged;
}
- return false;
+ return null;
}
/**
diff --git a/libraries/jcb_powers/VDM.Minify/index.html b/libraries/jcb_powers/VDM.Minify/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/jcb_powers/VDM.Minify/src/Abstraction/BasicException.php b/libraries/jcb_powers/VDM.Minify/src/Abstraction/BasicException.php
new file mode 100644
index 000000000..f883162ec
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Abstraction/BasicException.php
@@ -0,0 +1,26 @@
+
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+namespace VDM\Minify\Abstraction;
+
+
+/**
+ * Basic exception.
+ *
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
+ *
+ * @author Matthias Mullie
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+abstract class BasicException extends \Exception
+{
+}
+
diff --git a/libraries/jcb_powers/VDM.Minify/src/Abstraction/Minify.php b/libraries/jcb_powers/VDM.Minify/src/Abstraction/Minify.php
new file mode 100644
index 000000000..d5abc69fd
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Abstraction/Minify.php
@@ -0,0 +1,513 @@
+
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+
+namespace VDM\Minify\Abstraction;
+
+
+use VDM\Minify\Exceptions\IOException;
+use VDM\Psr\Cache\CacheItemInterface;
+
+
+/**
+ * Abstract minifier class.
+ *
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
+ *
+ * @author Matthias Mullie
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+abstract class Minify
+{
+ /**
+ * The data to be minified.
+ *
+ * @var string[]
+ */
+ protected $data = array();
+
+ /**
+ * Array of patterns to match.
+ *
+ * @var string[]
+ */
+ protected $patterns = array();
+
+ /**
+ * This array will hold content of strings and regular expressions that have
+ * been extracted from the JS source code, so we can reliably match "code",
+ * without having to worry about potential "code-like" characters inside.
+ *
+ * @internal
+ *
+ * @var string[]
+ */
+ public $extracted = array();
+
+ /**
+ * Init the minify class - optionally, code may be passed along already.
+ */
+ public function __construct(/* $data = null, ... */)
+ {
+ // it's possible to add the source through the constructor as well ;)
+ if (func_num_args()) {
+ call_user_func_array(array($this, 'add'), func_get_args());
+ }
+ }
+
+ /**
+ * Add a file or straight-up code to be minified.
+ *
+ * @param string|string[] $data
+ *
+ * @return static
+ */
+ public function add($data /* $data = null, ... */)
+ {
+ // bogus "usage" of parameter $data: scrutinizer warns this variable is
+ // not used (we're using func_get_args instead to support overloading),
+ // but it still needs to be defined because it makes no sense to have
+ // this function without argument :)
+ $args = array($data) + func_get_args();
+
+ // this method can be overloaded
+ foreach ($args as $data) {
+ if (is_array($data)) {
+ call_user_func_array(array($this, 'add'), $data);
+ continue;
+ }
+
+ // redefine var
+ $data = (string) $data;
+
+ // load data
+ $value = $this->load($data);
+ $key = ($data != $value) ? $data : count($this->data);
+
+ // replace CR linefeeds etc.
+ // @see https://github.com/matthiasmullie/minify/pull/139
+ $value = str_replace(array("\r\n", "\r"), "\n", $value);
+
+ // store data
+ $this->data[$key] = $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a file to be minified.
+ *
+ * @param string|string[] $data
+ *
+ * @return static
+ *
+ * @throws IOException
+ */
+ public function addFile($data /* $data = null, ... */)
+ {
+ // bogus "usage" of parameter $data: scrutinizer warns this variable is
+ // not used (we're using func_get_args instead to support overloading),
+ // but it still needs to be defined because it makes no sense to have
+ // this function without argument :)
+ $args = array($data) + func_get_args();
+
+ // this method can be overloaded
+ foreach ($args as $path) {
+ if (is_array($path)) {
+ call_user_func_array(array($this, 'addFile'), $path);
+ continue;
+ }
+
+ // redefine var
+ $path = (string) $path;
+
+ // check if we can read the file
+ if (!$this->canImportFile($path)) {
+ throw new IOException('The file "' . $path . '" could not be opened for reading. Check if PHP has enough permissions.');
+ }
+
+ $this->add($path);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Minify the data & (optionally) saves it to a file.
+ *
+ * @param string[optional] $path Path to write the data to
+ *
+ * @return string The minified data
+ */
+ public function minify($path = null)
+ {
+ $content = $this->execute($path);
+
+ // save to path
+ if ($path !== null) {
+ $this->save($content, $path);
+ }
+
+ return $content;
+ }
+
+ /**
+ * Minify & gzip the data & (optionally) saves it to a file.
+ *
+ * @param string[optional] $path Path to write the data to
+ * @param int[optional] $level Compression level, from 0 to 9
+ *
+ * @return string The minified & gzipped data
+ */
+ public function gzip($path = null, $level = 9)
+ {
+ $content = $this->execute($path);
+ $content = gzencode($content, $level, FORCE_GZIP);
+
+ // save to path
+ if ($path !== null) {
+ $this->save($content, $path);
+ }
+
+ return $content;
+ }
+
+ /**
+ * Minify the data & write it to a CacheItemInterface object.
+ *
+ * @param CacheItemInterface $item Cache item to write the data to
+ *
+ * @return CacheItemInterface Cache item with the minifier data
+ */
+ public function cache(CacheItemInterface $item)
+ {
+ $content = $this->execute();
+ $item->set($content);
+
+ return $item;
+ }
+
+ /**
+ * Minify the data.
+ *
+ * @param string[optional] $path Path to write the data to
+ *
+ * @return string The minified data
+ */
+ abstract public function execute($path = null);
+
+ /**
+ * Load data.
+ *
+ * @param string $data Either a path to a file or the content itself
+ *
+ * @return string
+ */
+ protected function load($data)
+ {
+ // check if the data is a file
+ if ($this->canImportFile($data)) {
+ $data = file_get_contents($data);
+
+ // strip BOM, if any
+ if (substr($data, 0, 3) == "\xef\xbb\xbf") {
+ $data = substr($data, 3);
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Save to file.
+ *
+ * @param string $content The minified data
+ * @param string $path The path to save the minified data to
+ *
+ * @throws IOException
+ */
+ protected function save($content, $path)
+ {
+ $handler = $this->openFileForWriting($path);
+
+ $this->writeToFile($handler, $content);
+
+ @fclose($handler);
+ }
+
+ /**
+ * Register a pattern to execute against the source content.
+ *
+ * If $replacement is a string, it must be plain text. Placeholders like $1 or \2 don't work.
+ * If you need that functionality, use a callback instead.
+ *
+ * @param string $pattern PCRE pattern
+ * @param string|callable $replacement Replacement value for matched pattern
+ */
+ protected function registerPattern($pattern, $replacement = '')
+ {
+ // study the pattern, we'll execute it more than once
+ $pattern .= 'S';
+
+ $this->patterns[] = array($pattern, $replacement);
+ }
+
+ /**
+ * We can't "just" run some regular expressions against JavaScript: it's a
+ * complex language. E.g. having an occurrence of // xyz would be a comment,
+ * unless it's used within a string. Of you could have something that looks
+ * like a 'string', but inside a comment.
+ * The only way to accurately replace these pieces is to traverse the JS one
+ * character at a time and try to find whatever starts first.
+ *
+ * @param string $content The content to replace patterns in
+ *
+ * @return string The (manipulated) content
+ */
+ protected function replace($content)
+ {
+ $contentLength = strlen($content);
+ $output = '';
+ $processedOffset = 0;
+ $positions = array_fill(0, count($this->patterns), -1);
+ $matches = array();
+
+ while ($processedOffset < $contentLength) {
+ // find first match for all patterns
+ foreach ($this->patterns as $i => $pattern) {
+ list($pattern, $replacement) = $pattern;
+
+ // we can safely ignore patterns for positions we've unset earlier,
+ // because we know these won't show up anymore
+ if (array_key_exists($i, $positions) == false) {
+ continue;
+ }
+
+ // no need to re-run matches that are still in the part of the
+ // content that hasn't been processed
+ if ($positions[$i] >= $processedOffset) {
+ continue;
+ }
+
+ $match = null;
+ if (preg_match($pattern, $content, $match, PREG_OFFSET_CAPTURE, $processedOffset)) {
+ $matches[$i] = $match;
+
+ // we'll store the match position as well; that way, we
+ // don't have to redo all preg_matches after changing only
+ // the first (we'll still know where those others are)
+ $positions[$i] = $match[0][1];
+ } else {
+ // if the pattern couldn't be matched, there's no point in
+ // executing it again in later runs on this same content;
+ // ignore this one until we reach end of content
+ unset($matches[$i], $positions[$i]);
+ }
+ }
+
+ // no more matches to find: everything's been processed, break out
+ if (!$matches) {
+ // output the remaining content
+ $output .= substr($content, $processedOffset);
+ break;
+ }
+
+ // see which of the patterns actually found the first thing (we'll
+ // only want to execute that one, since we're unsure if what the
+ // other found was not inside what the first found)
+ $matchOffset = min($positions);
+ $firstPattern = array_search($matchOffset, $positions);
+ $match = $matches[$firstPattern];
+
+ // execute the pattern that matches earliest in the content string
+ list(, $replacement) = $this->patterns[$firstPattern];
+
+ // add the part of the input between $processedOffset and the first match;
+ // that content wasn't matched by anything
+ $output .= substr($content, $processedOffset, $matchOffset - $processedOffset);
+ // add the replacement for the match
+ $output .= $this->executeReplacement($replacement, $match);
+ // advance $processedOffset past the match
+ $processedOffset = $matchOffset + strlen($match[0][0]);
+ }
+
+ return $output;
+ }
+
+ /**
+ * If $replacement is a callback, execute it, passing in the match data.
+ * If it's a string, just pass it through.
+ *
+ * @param string|callable $replacement Replacement value
+ * @param array $match Match data, in PREG_OFFSET_CAPTURE form
+ *
+ * @return string
+ */
+ protected function executeReplacement($replacement, $match)
+ {
+ if (!is_callable($replacement)) {
+ return $replacement;
+ }
+ // convert $match from the PREG_OFFSET_CAPTURE form to the form the callback expects
+ foreach ($match as &$matchItem) {
+ $matchItem = $matchItem[0];
+ }
+
+ return $replacement($match);
+ }
+
+ /**
+ * Strings are a pattern we need to match, in order to ignore potential
+ * code-like content inside them, but we just want all of the string
+ * content to remain untouched.
+ *
+ * This method will replace all string content with simple STRING#
+ * placeholder text, so we've rid all strings from characters that may be
+ * misinterpreted. Original string content will be saved in $this->extracted
+ * and after doing all other minifying, we can restore the original content
+ * via restoreStrings().
+ *
+ * @param string[optional] $chars
+ * @param string[optional] $placeholderPrefix
+ */
+ protected function extractStrings($chars = '\'"', $placeholderPrefix = '')
+ {
+ // PHP only supports $this inside anonymous functions since 5.4
+ $minifier = $this;
+ $callback = function ($match) use ($minifier, $placeholderPrefix) {
+ // check the second index here, because the first always contains a quote
+ if ($match[2] === '') {
+ /*
+ * Empty strings need no placeholder; they can't be confused for
+ * anything else anyway.
+ * But we still needed to match them, for the extraction routine
+ * to skip over this particular string.
+ */
+ return $match[0];
+ }
+
+ $count = count($minifier->extracted);
+ $placeholder = $match[1] . $placeholderPrefix . $count . $match[1];
+ $minifier->extracted[$placeholder] = $match[1] . $match[2] . $match[1];
+
+ return $placeholder;
+ };
+
+ /*
+ * The \\ messiness explained:
+ * * Don't count ' or " as end-of-string if it's escaped (has backslash
+ * in front of it)
+ * * Unless... that backslash itself is escaped (another leading slash),
+ * in which case it's no longer escaping the ' or "
+ * * So there can be either no backslash, or an even number
+ * * multiply all of that times 4, to account for the escaping that has
+ * to be done to pass the backslash into the PHP string without it being
+ * considered as escape-char (times 2) and to get it in the regex,
+ * escaped (times 2)
+ */
+ $this->registerPattern('/([' . $chars . '])(.*?(?extracted.
+ *
+ * @param string $content
+ *
+ * @return string
+ */
+ protected function restoreExtractedData($content)
+ {
+ if (!$this->extracted) {
+ // nothing was extracted, nothing to restore
+ return $content;
+ }
+
+ $content = strtr($content, $this->extracted);
+
+ $this->extracted = array();
+
+ return $content;
+ }
+
+ /**
+ * Check if the path is a regular file and can be read.
+ *
+ * @param string $path
+ *
+ * @return bool
+ */
+ protected function canImportFile($path)
+ {
+ $parsed = parse_url($path);
+ if (
+ // file is elsewhere
+ isset($parsed['host']) ||
+ // file responds to queries (may change, or need to bypass cache)
+ isset($parsed['query'])
+ ) {
+ return false;
+ }
+
+ return strlen($path) < PHP_MAXPATHLEN && @is_file($path) && is_readable($path);
+ }
+
+ /**
+ * Attempts to open file specified by $path for writing.
+ *
+ * @param string $path The path to the file
+ *
+ * @return resource Specifier for the target file
+ *
+ * @throws IOException
+ */
+ protected function openFileForWriting($path)
+ {
+ if ($path === '' || ($handler = @fopen($path, 'w')) === false) {
+ throw new IOException('The file "' . $path . '" could not be opened for writing. Check if PHP has enough permissions.');
+ }
+
+ return $handler;
+ }
+
+ /**
+ * Attempts to write $content to the file specified by $handler. $path is used for printing exceptions.
+ *
+ * @param resource $handler The resource to write to
+ * @param string $content The content to write
+ * @param string $path The path to the file (for exception printing only)
+ *
+ * @throws IOException
+ */
+ protected function writeToFile($handler, $content, $path = '')
+ {
+ if (
+ !is_resource($handler) ||
+ ($result = @fwrite($handler, $content)) === false ||
+ ($result < strlen($content))
+ ) {
+ throw new IOException('The file "' . $path . '" could not be written to. Check your disk space and file permissions.');
+ }
+ }
+
+ protected static function str_replace_first($search, $replace, $subject)
+ {
+ $pos = strpos($subject, $search);
+ if ($pos !== false) {
+ return substr_replace($subject, $replace, $pos, strlen($search));
+ }
+
+ return $subject;
+ }
+}
+
diff --git a/libraries/jcb_powers/VDM.Minify/src/Abstraction/index.html b/libraries/jcb_powers/VDM.Minify/src/Abstraction/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Abstraction/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/jcb_powers/VDM.Minify/src/Css.php b/libraries/jcb_powers/VDM.Minify/src/Css.php
new file mode 100644
index 000000000..c2435a92b
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Css.php
@@ -0,0 +1,758 @@
+
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+namespace VDM\Minify;
+
+
+use VDM\Minify\Exceptions\FileImportException;
+use VDM\Minify\Path\Converter;
+use VDM\Minify\Path\Interfaces\ConverterInterface;
+use VDM\Minify\Abstraction\Minify;
+
+
+/**
+ * CSS minifier.
+ *
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
+ *
+ * @author Matthias Mullie
+ * @author Tijs Verkoyen
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+class Css extends Minify
+{
+ /**
+ * @var int maximum inport size in kB
+ */
+ protected $maxImportSize = 5;
+
+ /**
+ * @var string[] valid import extensions
+ */
+ protected $importExtensions = array(
+ 'gif' => 'data:image/gif',
+ 'png' => 'data:image/png',
+ 'jpe' => 'data:image/jpeg',
+ 'jpg' => 'data:image/jpeg',
+ 'jpeg' => 'data:image/jpeg',
+ 'svg' => 'data:image/svg+xml',
+ 'woff' => 'data:application/x-font-woff',
+ 'woff2' => 'data:application/x-font-woff2',
+ 'avif' => 'data:image/avif',
+ 'apng' => 'data:image/apng',
+ 'webp' => 'data:image/webp',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'xbm' => 'image/x-xbitmap',
+ );
+
+ /**
+ * Set the maximum size if files to be imported.
+ *
+ * Files larger than this size (in kB) will not be imported into the CSS.
+ * Importing files into the CSS as data-uri will save you some connections,
+ * but we should only import relatively small decorative images so that our
+ * CSS file doesn't get too bulky.
+ *
+ * @param int $size Size in kB
+ */
+ public function setMaxImportSize($size)
+ {
+ $this->maxImportSize = $size;
+ }
+
+ /**
+ * Set the type of extensions to be imported into the CSS (to save network
+ * connections).
+ * Keys of the array should be the file extensions & respective values
+ * should be the data type.
+ *
+ * @param string[] $extensions Array of file extensions
+ */
+ public function setImportExtensions(array $extensions)
+ {
+ $this->importExtensions = $extensions;
+ }
+
+ /**
+ * Move any import statements to the top.
+ *
+ * @param string $content Nearly finished CSS content
+ *
+ * @return string
+ */
+ protected function moveImportsToTop($content)
+ {
+ if (preg_match_all('/(;?)(@import (?url\()?(?P["\']?).+?(?P=quotes)(?(url)\)));?/', $content, $matches)) {
+ // remove from content
+ foreach ($matches[0] as $import) {
+ $content = str_replace($import, '', $content);
+ }
+
+ // add to top
+ $content = implode(';', $matches[2]) . ';' . trim($content, ';');
+ }
+
+ return $content;
+ }
+
+ /**
+ * Combine CSS from import statements.
+ *
+ * Import statements will be loaded and their content merged into the original
+ * file, to save HTTP requests.
+ *
+ * @param string $source The file to combine imports for
+ * @param string $content The CSS content to combine imports for
+ * @param string[] $parents Parent paths, for circular reference checks
+ *
+ * @return string
+ *
+ * @throws FileImportException
+ */
+ protected function combineImports($source, $content, $parents)
+ {
+ $importRegexes = array(
+ // @import url(xxx)
+ '/
+ # import statement
+ @import
+ # whitespace
+ \s+
+ # open url()
+ url\(
+ # (optional) open path enclosure
+ (?P["\']?)
+ # fetch path
+ (?P.+?)
+ # (optional) close path enclosure
+ (?P=quotes)
+ # close url()
+ \)
+ # (optional) trailing whitespace
+ \s*
+ # (optional) media statement(s)
+ (?P[^;]*)
+ # (optional) trailing whitespace
+ \s*
+ # (optional) closing semi-colon
+ ;?
+ /ix',
+
+ // @import 'xxx'
+ '/
+ # import statement
+ @import
+ # whitespace
+ \s+
+ # open path enclosure
+ (?P["\'])
+ # fetch path
+ (?P.+?)
+ # close path enclosure
+ (?P=quotes)
+ # (optional) trailing whitespace
+ \s*
+ # (optional) media statement(s)
+ (?P[^;]*)
+ # (optional) trailing whitespace
+ \s*
+ # (optional) closing semi-colon
+ ;?
+ /ix',
+ );
+
+ // find all relative imports in css
+ $matches = array();
+ foreach ($importRegexes as $importRegex) {
+ if (preg_match_all($importRegex, $content, $regexMatches, PREG_SET_ORDER)) {
+ $matches = array_merge($matches, $regexMatches);
+ }
+ }
+
+ $search = array();
+ $replace = array();
+
+ // loop the matches
+ foreach ($matches as $match) {
+ // get the path for the file that will be imported
+ $importPath = dirname($source) . '/' . $match['path'];
+
+ // only replace the import with the content if we can grab the
+ // content of the file
+ if (!$this->canImportByPath($match['path']) || !$this->canImportFile($importPath)) {
+ continue;
+ }
+
+ // check if current file was not imported previously in the same
+ // import chain.
+ if (in_array($importPath, $parents)) {
+ throw new FileImportException('Failed to import file "' . $importPath . '": circular reference detected.');
+ }
+
+ // grab referenced file & minify it (which may include importing
+ // yet other @import statements recursively)
+ $minifier = new self($importPath);
+ $minifier->setMaxImportSize($this->maxImportSize);
+ $minifier->setImportExtensions($this->importExtensions);
+ $importContent = $minifier->execute($source, $parents);
+
+ // check if this is only valid for certain media
+ if (!empty($match['media'])) {
+ $importContent = '@media ' . $match['media'] . '{' . $importContent . '}';
+ }
+
+ // add to replacement array
+ $search[] = $match[0];
+ $replace[] = $importContent;
+ }
+
+ // replace the import statements
+ return str_replace($search, $replace, $content);
+ }
+
+ /**
+ * Import files into the CSS, base64-ized.
+ *
+ * @url(image.jpg) images will be loaded and their content merged into the
+ * original file, to save HTTP requests.
+ *
+ * @param string $source The file to import files for
+ * @param string $content The CSS content to import files for
+ *
+ * @return string
+ */
+ protected function importFiles($source, $content)
+ {
+ $regex = '/url\((["\']?)(.+?)\\1\)/i';
+ if ($this->importExtensions && preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) {
+ $search = array();
+ $replace = array();
+
+ // loop the matches
+ foreach ($matches as $match) {
+ $extension = substr(strrchr($match[2], '.'), 1);
+ if ($extension && !array_key_exists($extension, $this->importExtensions)) {
+ continue;
+ }
+
+ // get the path for the file that will be imported
+ $path = $match[2];
+ $path = dirname($source) . '/' . $path;
+
+ // only replace the import with the content if we're able to get
+ // the content of the file, and it's relatively small
+ if ($this->canImportFile($path) && $this->canImportBySize($path)) {
+ // grab content && base64-ize
+ $importContent = $this->load($path);
+ $importContent = base64_encode($importContent);
+
+ // build replacement
+ $search[] = $match[0];
+ $replace[] = 'url(' . $this->importExtensions[$extension] . ';base64,' . $importContent . ')';
+ }
+ }
+
+ // replace the import statements
+ $content = str_replace($search, $replace, $content);
+ }
+
+ return $content;
+ }
+
+ /**
+ * Minify the data.
+ * Perform CSS optimizations.
+ *
+ * @param string[optional] $path Path to write the data to
+ * @param string[] $parents Parent paths, for circular reference checks
+ *
+ * @return string The minified data
+ */
+ public function execute($path = null, $parents = array())
+ {
+ $content = '';
+
+ // loop CSS data (raw data and files)
+ foreach ($this->data as $source => $css) {
+ /*
+ * Let's first take out strings & comments, since we can't just
+ * remove whitespace anywhere. If whitespace occurs inside a string,
+ * we should leave it alone. E.g.:
+ * p { content: "a test" }
+ */
+ $this->extractStrings();
+ $this->stripComments();
+ $this->extractMath();
+ $this->extractCustomProperties();
+ $css = $this->replace($css);
+
+ $css = $this->stripWhitespace($css);
+ $css = $this->shortenColors($css);
+ $css = $this->shortenZeroes($css);
+ $css = $this->shortenFontWeights($css);
+ $css = $this->stripEmptyTags($css);
+
+ // restore the string we've extracted earlier
+ $css = $this->restoreExtractedData($css);
+
+ $source = is_int($source) ? '' : $source;
+ $parents = $source ? array_merge($parents, array($source)) : $parents;
+ $css = $this->combineImports($source, $css, $parents);
+ $css = $this->importFiles($source, $css);
+
+ /*
+ * If we'll save to a new path, we'll have to fix the relative paths
+ * to be relative no longer to the source file, but to the new path.
+ * If we don't write to a file, fall back to same path so no
+ * conversion happens (because we still want it to go through most
+ * of the move code, which also addresses url() & @import syntax...)
+ */
+ $converter = $this->getPathConverter($source, $path ?: $source);
+ $css = $this->move($converter, $css);
+
+ // combine css
+ $content .= $css;
+ }
+
+ $content = $this->moveImportsToTop($content);
+
+ return $content;
+ }
+
+ /**
+ * Moving a css file should update all relative urls.
+ * Relative references (e.g. ../images/image.gif) in a certain css file,
+ * will have to be updated when a file is being saved at another location
+ * (e.g. ../../images/image.gif, if the new CSS file is 1 folder deeper).
+ *
+ * @param ConverterInterface $converter Relative path converter
+ * @param string $content The CSS content to update relative urls for
+ *
+ * @return string
+ */
+ protected function move(ConverterInterface $converter, $content)
+ {
+ /*
+ * Relative path references will usually be enclosed by url(). @import
+ * is an exception, where url() is not necessary around the path (but is
+ * allowed).
+ * This *could* be 1 regular expression, where both regular expressions
+ * in this array are on different sides of a |. But we're using named
+ * patterns in both regexes, the same name on both regexes. This is only
+ * possible with a (?J) modifier, but that only works after a fairly
+ * recent PCRE version. That's why I'm doing 2 separate regular
+ * expressions & combining the matches after executing of both.
+ */
+ $relativeRegexes = array(
+ // url(xxx)
+ '/
+ # open url()
+ url\(
+ \s*
+ # open path enclosure
+ (?P["\'])?
+ # fetch path
+ (?P.+?)
+ # close path enclosure
+ (?(quotes)(?P=quotes))
+ \s*
+ # close url()
+ \)
+ /ix',
+
+ // @import "xxx"
+ '/
+ # import statement
+ @import
+ # whitespace
+ \s+
+ # we don\'t have to check for @import url(), because the
+ # condition above will already catch these
+ # open path enclosure
+ (?P["\'])
+ # fetch path
+ (?P.+?)
+ # close path enclosure
+ (?P=quotes)
+ /ix',
+ );
+
+ // find all relative urls in css
+ $matches = array();
+ foreach ($relativeRegexes as $relativeRegex) {
+ if (preg_match_all($relativeRegex, $content, $regexMatches, PREG_SET_ORDER)) {
+ $matches = array_merge($matches, $regexMatches);
+ }
+ }
+
+ $search = array();
+ $replace = array();
+
+ // loop all urls
+ foreach ($matches as $match) {
+ // determine if it's a url() or an @import match
+ $type = (strpos($match[0], '@import') === 0 ? 'import' : 'url');
+
+ $url = $match['path'];
+ if ($this->canImportByPath($url)) {
+ // attempting to interpret GET-params makes no sense, so let's discard them for awhile
+ $params = strrchr($url, '?');
+ $url = $params ? substr($url, 0, -strlen($params)) : $url;
+
+ // fix relative url
+ $url = $converter->convert($url);
+
+ // now that the path has been converted, re-apply GET-params
+ $url .= $params;
+ }
+
+ /*
+ * Urls with control characters above 0x7e should be quoted.
+ * According to Mozilla's parser, whitespace is only allowed at the
+ * end of unquoted urls.
+ * Urls with `)` (as could happen with data: uris) should also be
+ * quoted to avoid being confused for the url() closing parentheses.
+ * And urls with a # have also been reported to cause issues.
+ * Urls with quotes inside should also remain escaped.
+ *
+ * @see https://developer.mozilla.org/nl/docs/Web/CSS/url#The_url()_functional_notation
+ * @see https://hg.mozilla.org/mozilla-central/rev/14abca4e7378
+ * @see https://github.com/matthiasmullie/minify/issues/193
+ */
+ $url = trim($url);
+ if (preg_match('/[\s\)\'"#\x{7f}-\x{9f}]/u', $url)) {
+ $url = $match['quotes'] . $url . $match['quotes'];
+ }
+
+ // build replacement
+ $search[] = $match[0];
+ if ($type === 'url') {
+ $replace[] = 'url(' . $url . ')';
+ } elseif ($type === 'import') {
+ $replace[] = '@import "' . $url . '"';
+ }
+ }
+
+ // replace urls
+ return str_replace($search, $replace, $content);
+ }
+
+ /**
+ * Shorthand hex color codes.
+ * #FF0000 -> #F00.
+ *
+ * @param string $content The CSS content to shorten the hex color codes for
+ *
+ * @return string
+ */
+ protected function shortenColors($content)
+ {
+ $content = preg_replace('/(?<=[: ])#([0-9a-z])\\1([0-9a-z])\\2([0-9a-z])\\3(?:([0-9a-z])\\4)?(?=[; }])/i', '#$1$2$3$4', $content);
+
+ // remove alpha channel if it's pointless...
+ $content = preg_replace('/(?<=[: ])#([0-9a-z]{6})ff?(?=[; }])/i', '#$1', $content);
+ $content = preg_replace('/(?<=[: ])#([0-9a-z]{3})f?(?=[; }])/i', '#$1', $content);
+
+ $colors = array(
+ // we can shorten some even more by replacing them with their color name
+ '#F0FFFF' => 'azure',
+ '#F5F5DC' => 'beige',
+ '#A52A2A' => 'brown',
+ '#FF7F50' => 'coral',
+ '#FFD700' => 'gold',
+ '#808080' => 'gray',
+ '#008000' => 'green',
+ '#4B0082' => 'indigo',
+ '#FFFFF0' => 'ivory',
+ '#F0E68C' => 'khaki',
+ '#FAF0E6' => 'linen',
+ '#800000' => 'maroon',
+ '#000080' => 'navy',
+ '#808000' => 'olive',
+ '#CD853F' => 'peru',
+ '#FFC0CB' => 'pink',
+ '#DDA0DD' => 'plum',
+ '#800080' => 'purple',
+ '#F00' => 'red',
+ '#FA8072' => 'salmon',
+ '#A0522D' => 'sienna',
+ '#C0C0C0' => 'silver',
+ '#FFFAFA' => 'snow',
+ '#D2B48C' => 'tan',
+ '#FF6347' => 'tomato',
+ '#EE82EE' => 'violet',
+ '#F5DEB3' => 'wheat',
+ // or the other way around
+ 'WHITE' => '#fff',
+ 'BLACK' => '#000',
+ );
+
+ return preg_replace_callback(
+ '/(?<=[: ])(' . implode('|', array_keys($colors)) . ')(?=[; }])/i',
+ function ($match) use ($colors) {
+ return $colors[strtoupper($match[0])];
+ },
+ $content
+ );
+ }
+
+ /**
+ * Shorten CSS font weights.
+ *
+ * @param string $content The CSS content to shorten the font weights for
+ *
+ * @return string
+ */
+ protected function shortenFontWeights($content)
+ {
+ $weights = array(
+ 'normal' => 400,
+ 'bold' => 700,
+ );
+
+ $callback = function ($match) use ($weights) {
+ return $match[1] . $weights[$match[2]];
+ };
+
+ return preg_replace_callback('/(font-weight\s*:\s*)(' . implode('|', array_keys($weights)) . ')(?=[;}])/', $callback, $content);
+ }
+
+ /**
+ * Shorthand 0 values to plain 0, instead of e.g. -0em.
+ *
+ * @param string $content The CSS content to shorten the zero values for
+ *
+ * @return string
+ */
+ protected function shortenZeroes($content)
+ {
+ // we don't want to strip units in `calc()` expressions:
+ // `5px - 0px` is valid, but `5px - 0` is not
+ // `10px * 0` is valid (equates to 0), and so is `10 * 0px`, but
+ // `10 * 0` is invalid
+ // we've extracted calcs earlier, so we don't need to worry about this
+
+ // reusable bits of code throughout these regexes:
+ // before & after are used to make sure we don't match lose unintended
+ // 0-like values (e.g. in #000, or in http://url/1.0)
+ // units can be stripped from 0 values, or used to recognize non 0
+ // values (where wa may be able to strip a .0 suffix)
+ $before = '(?<=[:(, ])';
+ $after = '(?=[ ,);}])';
+ $units = '(em|ex|%|px|cm|mm|in|pt|pc|ch|rem|vh|vw|vmin|vmax|vm)';
+
+ // strip units after zeroes (0px -> 0)
+ // NOTE: it should be safe to remove all units for a 0 value, but in
+ // practice, Webkit (especially Safari) seems to stumble over at least
+ // 0%, potentially other units as well. Only stripping 'px' for now.
+ // @see https://github.com/matthiasmullie/minify/issues/60
+ $content = preg_replace('/' . $before . '(-?0*(\.0+)?)(?<=0)px' . $after . '/', '\\1', $content);
+
+ // strip 0-digits (.0 -> 0)
+ $content = preg_replace('/' . $before . '\.0+' . $units . '?' . $after . '/', '0\\1', $content);
+ // strip trailing 0: 50.10 -> 50.1, 50.10px -> 50.1px
+ $content = preg_replace('/' . $before . '(-?[0-9]+\.[0-9]+)0+' . $units . '?' . $after . '/', '\\1\\2', $content);
+ // strip trailing 0: 50.00 -> 50, 50.00px -> 50px
+ $content = preg_replace('/' . $before . '(-?[0-9]+)\.0+' . $units . '?' . $after . '/', '\\1\\2', $content);
+ // strip leading 0: 0.1 -> .1, 01.1 -> 1.1
+ $content = preg_replace('/' . $before . '(-?)0+([0-9]*\.[0-9]+)' . $units . '?' . $after . '/', '\\1\\2\\3', $content);
+
+ // strip negative zeroes (-0 -> 0) & truncate zeroes (00 -> 0)
+ $content = preg_replace('/' . $before . '-?0+' . $units . '?' . $after . '/', '0\\1', $content);
+
+ // IE doesn't seem to understand a unitless flex-basis value (correct -
+ // it goes against the spec), so let's add it in again (make it `%`,
+ // which is only 1 char: 0%, 0px, 0 anything, it's all just the same)
+ // @see https://developer.mozilla.org/nl/docs/Web/CSS/flex
+ $content = preg_replace('/flex:([0-9]+\s[0-9]+\s)0([;\}])/', 'flex:${1}0%${2}', $content);
+ $content = preg_replace('/flex-basis:0([;\}])/', 'flex-basis:0%${1}', $content);
+
+ return $content;
+ }
+
+ /**
+ * Strip empty tags from source code.
+ *
+ * @param string $content
+ *
+ * @return string
+ */
+ protected function stripEmptyTags($content)
+ {
+ $content = preg_replace('/(?<=^)[^\{\};]+\{\s*\}/', '', $content);
+ $content = preg_replace('/(?<=(\}|;))[^\{\};]+\{\s*\}/', '', $content);
+
+ return $content;
+ }
+
+ /**
+ * Strip comments from source code.
+ */
+ protected function stripComments()
+ {
+ // PHP only supports $this inside anonymous functions since 5.4
+ $minifier = $this;
+ $callback = function ($match) use ($minifier) {
+ $count = count($minifier->extracted);
+ $placeholder = '/*' . $count . '*/';
+ $minifier->extracted[$placeholder] = $match[0];
+
+ return $placeholder;
+ };
+ $this->registerPattern('/\n?\/\*(!|.*?@license|.*?@preserve).*?\*\/\n?/s', $callback);
+
+ $this->registerPattern('/\/\*.*?\*\//s', '');
+ }
+
+ /**
+ * Strip whitespace.
+ *
+ * @param string $content The CSS content to strip the whitespace for
+ *
+ * @return string
+ */
+ protected function stripWhitespace($content)
+ {
+ // remove leading & trailing whitespace
+ $content = preg_replace('/^\s*/m', '', $content);
+ $content = preg_replace('/\s*$/m', '', $content);
+
+ // replace newlines with a single space
+ $content = preg_replace('/\s+/', ' ', $content);
+
+ // remove whitespace around meta characters
+ // inspired by stackoverflow.com/questions/15195750/minify-compress-css-with-regex
+ $content = preg_replace('/\s*([\*$~^|]?+=|[{};,>~]|!important\b)\s*/', '$1', $content);
+ $content = preg_replace('/([\[(:>\+])\s+/', '$1', $content);
+ $content = preg_replace('/\s+([\]\)>\+])/', '$1', $content);
+ $content = preg_replace('/\s+(:)(?![^\}]*\{)/', '$1', $content);
+
+ // whitespace around + and - can only be stripped inside some pseudo-
+ // classes, like `:nth-child(3+2n)`
+ // not in things like `calc(3px + 2px)`, shorthands like `3px -2px`, or
+ // selectors like `div.weird- p`
+ $pseudos = array('nth-child', 'nth-last-child', 'nth-last-of-type', 'nth-of-type');
+ $content = preg_replace('/:(' . implode('|', $pseudos) . ')\(\s*([+-]?)\s*(.+?)\s*([+-]?)\s*(.*?)\s*\)/', ':$1($2$3$4$5)', $content);
+
+ // remove semicolon/whitespace followed by closing bracket
+ $content = str_replace(';}', '}', $content);
+
+ return trim($content);
+ }
+
+ /**
+ * Replace all occurrences of functions that may contain math, where
+ * whitespace around operators needs to be preserved (e.g. calc, clamp).
+ */
+ protected function extractMath()
+ {
+ $functions = array('calc', 'clamp', 'min', 'max');
+ $pattern = '/\b(' . implode('|', $functions) . ')(\(.+?)(?=$|;|})/m';
+
+ // PHP only supports $this inside anonymous functions since 5.4
+ $minifier = $this;
+ $callback = function ($match) use ($minifier, $pattern, &$callback) {
+ $function = $match[1];
+ $length = strlen($match[2]);
+ $expr = '';
+ $opened = 0;
+
+ // the regular expression for extracting math has 1 significant problem:
+ // it can't determine the correct closing parenthesis...
+ // instead, it'll match a larger portion of code to where it's certain that
+ // the calc() musts have ended, and we'll figure out which is the correct
+ // closing parenthesis here, by counting how many have opened
+ for ($i = 0; $i < $length; ++$i) {
+ $char = $match[2][$i];
+ $expr .= $char;
+ if ($char === '(') {
+ ++$opened;
+ } elseif ($char === ')' && --$opened === 0) {
+ break;
+ }
+ }
+
+ // now that we've figured out where the calc() starts and ends, extract it
+ $count = count($minifier->extracted);
+ $placeholder = 'math(' . $count . ')';
+ $minifier->extracted[$placeholder] = $function . '(' . trim(substr($expr, 1, -1)) . ')';
+
+ // and since we've captured more code than required, we may have some leftover
+ // calc() in here too - go recursive on the remaining but of code to go figure
+ // that out and extract what is needed
+ $rest = $minifier->str_replace_first($function . $expr, '', $match[0]);
+ $rest = preg_replace_callback($pattern, $callback, $rest);
+
+ return $placeholder . $rest;
+ };
+
+ $this->registerPattern($pattern, $callback);
+ }
+
+ /**
+ * Replace custom properties, whose values may be used in scenarios where
+ * we wouldn't want them to be minified (e.g. inside calc).
+ */
+ protected function extractCustomProperties()
+ {
+ // PHP only supports $this inside anonymous functions since 5.4
+ $minifier = $this;
+ $this->registerPattern(
+ '/(?<=^|[;}{])\s*(--[^:;{}"\'\s]+)\s*:([^;{}]+)/m',
+ function ($match) use ($minifier) {
+ $placeholder = '--custom-' . count($minifier->extracted) . ':0';
+ $minifier->extracted[$placeholder] = $match[1] . ':' . trim($match[2]);
+
+ return $placeholder;
+ }
+ );
+ }
+
+ /**
+ * Check if file is small enough to be imported.
+ *
+ * @param string $path The path to the file
+ *
+ * @return bool
+ */
+ protected function canImportBySize($path)
+ {
+ return ($size = @filesize($path)) && $size <= $this->maxImportSize * 1024;
+ }
+
+ /**
+ * Check if file a file can be imported, going by the path.
+ *
+ * @param string $path
+ *
+ * @return bool
+ */
+ protected function canImportByPath($path)
+ {
+ return preg_match('/^(data:|https?:|\\/)/', $path) === 0;
+ }
+
+ /**
+ * Return a converter to update relative paths to be relative to the new
+ * destination.
+ *
+ * @param string $source
+ * @param string $target
+ *
+ * @return ConverterInterface
+ */
+ protected function getPathConverter($source, $target)
+ {
+ return new Converter($source, $target);
+ }
+}
+
diff --git a/libraries/jcb_powers/VDM.Minify/src/Exceptions/FileImportException.php b/libraries/jcb_powers/VDM.Minify/src/Exceptions/FileImportException.php
new file mode 100644
index 000000000..73be9bb71
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Exceptions/FileImportException.php
@@ -0,0 +1,25 @@
+
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+namespace VDM\Minify\Exceptions;
+
+
+use VDM\Minify\Abstraction\BasicException;
+
+
+/**
+ * File Import Exception Class.
+ *
+ * @author Matthias Mullie
+ */
+class FileImportException extends BasicException
+{
+}
+
diff --git a/libraries/jcb_powers/VDM.Minify/src/Exceptions/IOException.php b/libraries/jcb_powers/VDM.Minify/src/Exceptions/IOException.php
new file mode 100644
index 000000000..11bd955df
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Exceptions/IOException.php
@@ -0,0 +1,25 @@
+
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+namespace VDM\Minify\Exceptions;
+
+
+use VDM\Minify\Abstraction\BasicException;
+
+
+/**
+ * IO Exception Class.
+ *
+ * @author Matthias Mullie
+ */
+class IOException extends BasicException
+{
+}
+
diff --git a/libraries/jcb_powers/VDM.Minify/src/Exceptions/index.html b/libraries/jcb_powers/VDM.Minify/src/Exceptions/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Exceptions/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/admin/helpers/js.php b/libraries/jcb_powers/VDM.Minify/src/JavaScript.php
similarity index 57%
rename from admin/helpers/js.php
rename to libraries/jcb_powers/VDM.Minify/src/JavaScript.php
index 47d0f75cd..eb7fb4abf 100644
--- a/admin/helpers/js.php
+++ b/libraries/jcb_powers/VDM.Minify/src/JavaScript.php
@@ -1,64 +1,116 @@
- @github Joomla Component Builder
- @copyright Copyright (C) 2015. All Rights Reserved
- @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
-
- Builds Complex Joomla Components
-
-/-----------------------------------------------------------------------------------------------------------------------------*/
-
-// No direct access to this file
-defined('_JEXEC') or die('Restricted access');
-
-require_once JPATH_ADMINISTRATOR.'/components/com_componentbuilder/helpers/minify.php';
-
/**
* JavaScript minifier.
*
* Please report bugs on https://github.com/matthiasmullie/minify/issues
*
* @author Matthias Mullie
- * @author Tijs Verkoyen
- *
- * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved.
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
* @license MIT License
- */
-class JS extends Minify
-{
+ */
+namespace VDM\Minify;
+
+
+use VDM\Minify\Abstraction\Minify;
+
+
+/**
+ * JavaScript Minifier Class.
+ *
+ * Please report bugs on https://github.com/matthiasmullie/minify/issues
+ *
+ * @author Matthias Mullie
+ * @author Tijs Verkoyen
+ * @copyright Copyright (c) 2012, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+class JavaScript extends Minify
+{
/**
- * Var-matching regex based on http://stackoverflow.com/a/9337047/802993
+ * Var-matching regex based on http://stackoverflow.com/a/9337047/802993.
*
* Note that regular expressions using that bit must have the PCRE_UTF8
* pattern modifier (/u) set.
*
+ * @internal
+ *
* @var string
*/
const REGEX_VARIABLE = '\b[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\x{02c1}\x{02c6}-\x{02d1}\x{02e0}-\x{02e4}\x{02ec}\x{02ee}\x{0370}-\x{0374}\x{0376}\x{0377}\x{037a}-\x{037d}\x{0386}\x{0388}-\x{038a}\x{038c}\x{038e}-\x{03a1}\x{03a3}-\x{03f5}\x{03f7}-\x{0481}\x{048a}-\x{0527}\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0587}\x{05d0}-\x{05ea}\x{05f0}-\x{05f2}\x{0620}-\x{064a}\x{066e}\x{066f}\x{0671}-\x{06d3}\x{06d5}\x{06e5}\x{06e6}\x{06ee}\x{06ef}\x{06fa}-\x{06fc}\x{06ff}\x{0710}\x{0712}-\x{072f}\x{074d}-\x{07a5}\x{07b1}\x{07ca}-\x{07ea}\x{07f4}\x{07f5}\x{07fa}\x{0800}-\x{0815}\x{081a}\x{0824}\x{0828}\x{0840}-\x{0858}\x{08a0}\x{08a2}-\x{08ac}\x{0904}-\x{0939}\x{093d}\x{0950}\x{0958}-\x{0961}\x{0971}-\x{0977}\x{0979}-\x{097f}\x{0985}-\x{098c}\x{098f}\x{0990}\x{0993}-\x{09a8}\x{09aa}-\x{09b0}\x{09b2}\x{09b6}-\x{09b9}\x{09bd}\x{09ce}\x{09dc}\x{09dd}\x{09df}-\x{09e1}\x{09f0}\x{09f1}\x{0a05}-\x{0a0a}\x{0a0f}\x{0a10}\x{0a13}-\x{0a28}\x{0a2a}-\x{0a30}\x{0a32}\x{0a33}\x{0a35}\x{0a36}\x{0a38}\x{0a39}\x{0a59}-\x{0a5c}\x{0a5e}\x{0a72}-\x{0a74}\x{0a85}-\x{0a8d}\x{0a8f}-\x{0a91}\x{0a93}-\x{0aa8}\x{0aaa}-\x{0ab0}\x{0ab2}\x{0ab3}\x{0ab5}-\x{0ab9}\x{0abd}\x{0ad0}\x{0ae0}\x{0ae1}\x{0b05}-\x{0b0c}\x{0b0f}\x{0b10}\x{0b13}-\x{0b28}\x{0b2a}-\x{0b30}\x{0b32}\x{0b33}\x{0b35}-\x{0b39}\x{0b3d}\x{0b5c}\x{0b5d}\x{0b5f}-\x{0b61}\x{0b71}\x{0b83}\x{0b85}-\x{0b8a}\x{0b8e}-\x{0b90}\x{0b92}-\x{0b95}\x{0b99}\x{0b9a}\x{0b9c}\x{0b9e}\x{0b9f}\x{0ba3}\x{0ba4}\x{0ba8}-\x{0baa}\x{0bae}-\x{0bb9}\x{0bd0}\x{0c05}-\x{0c0c}\x{0c0e}-\x{0c10}\x{0c12}-\x{0c28}\x{0c2a}-\x{0c33}\x{0c35}-\x{0c39}\x{0c3d}\x{0c58}\x{0c59}\x{0c60}\x{0c61}\x{0c85}-\x{0c8c}\x{0c8e}-\x{0c90}\x{0c92}-\x{0ca8}\x{0caa}-\x{0cb3}\x{0cb5}-\x{0cb9}\x{0cbd}\x{0cde}\x{0ce0}\x{0ce1}\x{0cf1}\x{0cf2}\x{0d05}-\x{0d0c}\x{0d0e}-\x{0d10}\x{0d12}-\x{0d3a}\x{0d3d}\x{0d4e}\x{0d60}\x{0d61}\x{0d7a}-\x{0d7f}\x{0d85}-\x{0d96}\x{0d9a}-\x{0db1}\x{0db3}-\x{0dbb}\x{0dbd}\x{0dc0}-\x{0dc6}\x{0e01}-\x{0e30}\x{0e32}\x{0e33}\x{0e40}-\x{0e46}\x{0e81}\x{0e82}\x{0e84}\x{0e87}\x{0e88}\x{0e8a}\x{0e8d}\x{0e94}-\x{0e97}\x{0e99}-\x{0e9f}\x{0ea1}-\x{0ea3}\x{0ea5}\x{0ea7}\x{0eaa}\x{0eab}\x{0ead}-\x{0eb0}\x{0eb2}\x{0eb3}\x{0ebd}\x{0ec0}-\x{0ec4}\x{0ec6}\x{0edc}-\x{0edf}\x{0f00}\x{0f40}-\x{0f47}\x{0f49}-\x{0f6c}\x{0f88}-\x{0f8c}\x{1000}-\x{102a}\x{103f}\x{1050}-\x{1055}\x{105a}-\x{105d}\x{1061}\x{1065}\x{1066}\x{106e}-\x{1070}\x{1075}-\x{1081}\x{108e}\x{10a0}-\x{10c5}\x{10c7}\x{10cd}\x{10d0}-\x{10fa}\x{10fc}-\x{1248}\x{124a}-\x{124d}\x{1250}-\x{1256}\x{1258}\x{125a}-\x{125d}\x{1260}-\x{1288}\x{128a}-\x{128d}\x{1290}-\x{12b0}\x{12b2}-\x{12b5}\x{12b8}-\x{12be}\x{12c0}\x{12c2}-\x{12c5}\x{12c8}-\x{12d6}\x{12d8}-\x{1310}\x{1312}-\x{1315}\x{1318}-\x{135a}\x{1380}-\x{138f}\x{13a0}-\x{13f4}\x{1401}-\x{166c}\x{166f}-\x{167f}\x{1681}-\x{169a}\x{16a0}-\x{16ea}\x{16ee}-\x{16f0}\x{1700}-\x{170c}\x{170e}-\x{1711}\x{1720}-\x{1731}\x{1740}-\x{1751}\x{1760}-\x{176c}\x{176e}-\x{1770}\x{1780}-\x{17b3}\x{17d7}\x{17dc}\x{1820}-\x{1877}\x{1880}-\x{18a8}\x{18aa}\x{18b0}-\x{18f5}\x{1900}-\x{191c}\x{1950}-\x{196d}\x{1970}-\x{1974}\x{1980}-\x{19ab}\x{19c1}-\x{19c7}\x{1a00}-\x{1a16}\x{1a20}-\x{1a54}\x{1aa7}\x{1b05}-\x{1b33}\x{1b45}-\x{1b4b}\x{1b83}-\x{1ba0}\x{1bae}\x{1baf}\x{1bba}-\x{1be5}\x{1c00}-\x{1c23}\x{1c4d}-\x{1c4f}\x{1c5a}-\x{1c7d}\x{1ce9}-\x{1cec}\x{1cee}-\x{1cf1}\x{1cf5}\x{1cf6}\x{1d00}-\x{1dbf}\x{1e00}-\x{1f15}\x{1f18}-\x{1f1d}\x{1f20}-\x{1f45}\x{1f48}-\x{1f4d}\x{1f50}-\x{1f57}\x{1f59}\x{1f5b}\x{1f5d}\x{1f5f}-\x{1f7d}\x{1f80}-\x{1fb4}\x{1fb6}-\x{1fbc}\x{1fbe}\x{1fc2}-\x{1fc4}\x{1fc6}-\x{1fcc}\x{1fd0}-\x{1fd3}\x{1fd6}-\x{1fdb}\x{1fe0}-\x{1fec}\x{1ff2}-\x{1ff4}\x{1ff6}-\x{1ffc}\x{2071}\x{207f}\x{2090}-\x{209c}\x{2102}\x{2107}\x{210a}-\x{2113}\x{2115}\x{2119}-\x{211d}\x{2124}\x{2126}\x{2128}\x{212a}-\x{212d}\x{212f}-\x{2139}\x{213c}-\x{213f}\x{2145}-\x{2149}\x{214e}\x{2160}-\x{2188}\x{2c00}-\x{2c2e}\x{2c30}-\x{2c5e}\x{2c60}-\x{2ce4}\x{2ceb}-\x{2cee}\x{2cf2}\x{2cf3}\x{2d00}-\x{2d25}\x{2d27}\x{2d2d}\x{2d30}-\x{2d67}\x{2d6f}\x{2d80}-\x{2d96}\x{2da0}-\x{2da6}\x{2da8}-\x{2dae}\x{2db0}-\x{2db6}\x{2db8}-\x{2dbe}\x{2dc0}-\x{2dc6}\x{2dc8}-\x{2dce}\x{2dd0}-\x{2dd6}\x{2dd8}-\x{2dde}\x{2e2f}\x{3005}-\x{3007}\x{3021}-\x{3029}\x{3031}-\x{3035}\x{3038}-\x{303c}\x{3041}-\x{3096}\x{309d}-\x{309f}\x{30a1}-\x{30fa}\x{30fc}-\x{30ff}\x{3105}-\x{312d}\x{3131}-\x{318e}\x{31a0}-\x{31ba}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{4e00}-\x{9fcc}\x{a000}-\x{a48c}\x{a4d0}-\x{a4fd}\x{a500}-\x{a60c}\x{a610}-\x{a61f}\x{a62a}\x{a62b}\x{a640}-\x{a66e}\x{a67f}-\x{a697}\x{a6a0}-\x{a6ef}\x{a717}-\x{a71f}\x{a722}-\x{a788}\x{a78b}-\x{a78e}\x{a790}-\x{a793}\x{a7a0}-\x{a7aa}\x{a7f8}-\x{a801}\x{a803}-\x{a805}\x{a807}-\x{a80a}\x{a80c}-\x{a822}\x{a840}-\x{a873}\x{a882}-\x{a8b3}\x{a8f2}-\x{a8f7}\x{a8fb}\x{a90a}-\x{a925}\x{a930}-\x{a946}\x{a960}-\x{a97c}\x{a984}-\x{a9b2}\x{a9cf}\x{aa00}-\x{aa28}\x{aa40}-\x{aa42}\x{aa44}-\x{aa4b}\x{aa60}-\x{aa76}\x{aa7a}\x{aa80}-\x{aaaf}\x{aab1}\x{aab5}\x{aab6}\x{aab9}-\x{aabd}\x{aac0}\x{aac2}\x{aadb}-\x{aadd}\x{aae0}-\x{aaea}\x{aaf2}-\x{aaf4}\x{ab01}-\x{ab06}\x{ab09}-\x{ab0e}\x{ab11}-\x{ab16}\x{ab20}-\x{ab26}\x{ab28}-\x{ab2e}\x{abc0}-\x{abe2}\x{ac00}-\x{d7a3}\x{d7b0}-\x{d7c6}\x{d7cb}-\x{d7fb}\x{f900}-\x{fa6d}\x{fa70}-\x{fad9}\x{fb00}-\x{fb06}\x{fb13}-\x{fb17}\x{fb1d}\x{fb1f}-\x{fb28}\x{fb2a}-\x{fb36}\x{fb38}-\x{fb3c}\x{fb3e}\x{fb40}\x{fb41}\x{fb43}\x{fb44}\x{fb46}-\x{fbb1}\x{fbd3}-\x{fd3d}\x{fd50}-\x{fd8f}\x{fd92}-\x{fdc7}\x{fdf0}-\x{fdfb}\x{fe70}-\x{fe74}\x{fe76}-\x{fefc}\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}\x{ff66}-\x{ffbe}\x{ffc2}-\x{ffc7}\x{ffca}-\x{ffcf}\x{ffd2}-\x{ffd7}\x{ffda}-\x{ffdc}0-9\x{0300}-\x{036f}\x{0483}-\x{0487}\x{0591}-\x{05bd}\x{05bf}\x{05c1}\x{05c2}\x{05c4}\x{05c5}\x{05c7}\x{0610}-\x{061a}\x{064b}-\x{0669}\x{0670}\x{06d6}-\x{06dc}\x{06df}-\x{06e4}\x{06e7}\x{06e8}\x{06ea}-\x{06ed}\x{06f0}-\x{06f9}\x{0711}\x{0730}-\x{074a}\x{07a6}-\x{07b0}\x{07c0}-\x{07c9}\x{07eb}-\x{07f3}\x{0816}-\x{0819}\x{081b}-\x{0823}\x{0825}-\x{0827}\x{0829}-\x{082d}\x{0859}-\x{085b}\x{08e4}-\x{08fe}\x{0900}-\x{0903}\x{093a}-\x{093c}\x{093e}-\x{094f}\x{0951}-\x{0957}\x{0962}\x{0963}\x{0966}-\x{096f}\x{0981}-\x{0983}\x{09bc}\x{09be}-\x{09c4}\x{09c7}\x{09c8}\x{09cb}-\x{09cd}\x{09d7}\x{09e2}\x{09e3}\x{09e6}-\x{09ef}\x{0a01}-\x{0a03}\x{0a3c}\x{0a3e}-\x{0a42}\x{0a47}\x{0a48}\x{0a4b}-\x{0a4d}\x{0a51}\x{0a66}-\x{0a71}\x{0a75}\x{0a81}-\x{0a83}\x{0abc}\x{0abe}-\x{0ac5}\x{0ac7}-\x{0ac9}\x{0acb}-\x{0acd}\x{0ae2}\x{0ae3}\x{0ae6}-\x{0aef}\x{0b01}-\x{0b03}\x{0b3c}\x{0b3e}-\x{0b44}\x{0b47}\x{0b48}\x{0b4b}-\x{0b4d}\x{0b56}\x{0b57}\x{0b62}\x{0b63}\x{0b66}-\x{0b6f}\x{0b82}\x{0bbe}-\x{0bc2}\x{0bc6}-\x{0bc8}\x{0bca}-\x{0bcd}\x{0bd7}\x{0be6}-\x{0bef}\x{0c01}-\x{0c03}\x{0c3e}-\x{0c44}\x{0c46}-\x{0c48}\x{0c4a}-\x{0c4d}\x{0c55}\x{0c56}\x{0c62}\x{0c63}\x{0c66}-\x{0c6f}\x{0c82}\x{0c83}\x{0cbc}\x{0cbe}-\x{0cc4}\x{0cc6}-\x{0cc8}\x{0cca}-\x{0ccd}\x{0cd5}\x{0cd6}\x{0ce2}\x{0ce3}\x{0ce6}-\x{0cef}\x{0d02}\x{0d03}\x{0d3e}-\x{0d44}\x{0d46}-\x{0d48}\x{0d4a}-\x{0d4d}\x{0d57}\x{0d62}\x{0d63}\x{0d66}-\x{0d6f}\x{0d82}\x{0d83}\x{0dca}\x{0dcf}-\x{0dd4}\x{0dd6}\x{0dd8}-\x{0ddf}\x{0df2}\x{0df3}\x{0e31}\x{0e34}-\x{0e3a}\x{0e47}-\x{0e4e}\x{0e50}-\x{0e59}\x{0eb1}\x{0eb4}-\x{0eb9}\x{0ebb}\x{0ebc}\x{0ec8}-\x{0ecd}\x{0ed0}-\x{0ed9}\x{0f18}\x{0f19}\x{0f20}-\x{0f29}\x{0f35}\x{0f37}\x{0f39}\x{0f3e}\x{0f3f}\x{0f71}-\x{0f84}\x{0f86}\x{0f87}\x{0f8d}-\x{0f97}\x{0f99}-\x{0fbc}\x{0fc6}\x{102b}-\x{103e}\x{1040}-\x{1049}\x{1056}-\x{1059}\x{105e}-\x{1060}\x{1062}-\x{1064}\x{1067}-\x{106d}\x{1071}-\x{1074}\x{1082}-\x{108d}\x{108f}-\x{109d}\x{135d}-\x{135f}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}\x{1753}\x{1772}\x{1773}\x{17b4}-\x{17d3}\x{17dd}\x{17e0}-\x{17e9}\x{180b}-\x{180d}\x{1810}-\x{1819}\x{18a9}\x{1920}-\x{192b}\x{1930}-\x{193b}\x{1946}-\x{194f}\x{19b0}-\x{19c0}\x{19c8}\x{19c9}\x{19d0}-\x{19d9}\x{1a17}-\x{1a1b}\x{1a55}-\x{1a5e}\x{1a60}-\x{1a7c}\x{1a7f}-\x{1a89}\x{1a90}-\x{1a99}\x{1b00}-\x{1b04}\x{1b34}-\x{1b44}\x{1b50}-\x{1b59}\x{1b6b}-\x{1b73}\x{1b80}-\x{1b82}\x{1ba1}-\x{1bad}\x{1bb0}-\x{1bb9}\x{1be6}-\x{1bf3}\x{1c24}-\x{1c37}\x{1c40}-\x{1c49}\x{1c50}-\x{1c59}\x{1cd0}-\x{1cd2}\x{1cd4}-\x{1ce8}\x{1ced}\x{1cf2}-\x{1cf4}\x{1dc0}-\x{1de6}\x{1dfc}-\x{1dff}\x{200c}\x{200d}\x{203f}\x{2040}\x{2054}\x{20d0}-\x{20dc}\x{20e1}\x{20e5}-\x{20f0}\x{2cef}-\x{2cf1}\x{2d7f}\x{2de0}-\x{2dff}\x{302a}-\x{302f}\x{3099}\x{309a}\x{a620}-\x{a629}\x{a66f}\x{a674}-\x{a67d}\x{a69f}\x{a6f0}\x{a6f1}\x{a802}\x{a806}\x{a80b}\x{a823}-\x{a827}\x{a880}\x{a881}\x{a8b4}-\x{a8c4}\x{a8d0}-\x{a8d9}\x{a8e0}-\x{a8f1}\x{a900}-\x{a909}\x{a926}-\x{a92d}\x{a947}-\x{a953}\x{a980}-\x{a983}\x{a9b3}-\x{a9c0}\x{a9d0}-\x{a9d9}\x{aa29}-\x{aa36}\x{aa43}\x{aa4c}\x{aa4d}\x{aa50}-\x{aa59}\x{aa7b}\x{aab0}\x{aab2}-\x{aab4}\x{aab7}\x{aab8}\x{aabe}\x{aabf}\x{aac1}\x{aaeb}-\x{aaef}\x{aaf5}\x{aaf6}\x{abe3}-\x{abea}\x{abec}\x{abed}\x{abf0}-\x{abf9}\x{fb1e}\x{fe00}-\x{fe0f}\x{fe20}-\x{fe26}\x{fe33}\x{fe34}\x{fe4d}-\x{fe4f}\x{ff10}-\x{ff19}\x{ff3f}]*\b';
/**
* Full list of JavaScript reserved words.
- * Will be loaded from /data/js/keywords_reserved.txt
+ * Will be loaded from /data/js/keywords_reserved.txt.
*
* @see https://mathiasbynens.be/notes/reserved-keywords
+ *
* @var string[]
*/
- protected $keywordsReserved = array();
+ protected $keywordsReserved = [
+ 'do',
+ 'if',
+ 'in',
+ 'for',
+ 'let',
+ 'new',
+ 'try',
+ 'var',
+ 'case',
+ 'else',
+ 'enum',
+ 'eval',
+ 'null',
+ 'this',
+ 'true',
+ 'void',
+ 'with',
+ 'break',
+ 'catch',
+ 'class',
+ 'const',
+ 'false',
+ 'super',
+ 'throw',
+ 'while',
+ 'yield',
+ 'delete',
+ 'export',
+ 'import',
+ 'public',
+ 'return',
+ 'static',
+ 'switch',
+ 'typeof',
+ 'default',
+ 'extends',
+ 'finally',
+ 'package',
+ 'private',
+ 'continue',
+ 'debugger',
+ 'function',
+ 'arguments',
+ 'interface',
+ 'protected',
+ 'implements',
+ 'instanceof',
+ 'abstract',
+ 'boolean',
+ 'byte',
+ 'char',
+ 'double',
+ 'final',
+ 'float',
+ 'goto',
+ 'int',
+ 'long',
+ 'native',
+ 'short',
+ 'synchronized',
+ 'throws',
+ 'transient',
+ 'volatile'
+ ];
/**
* List of JavaScript reserved words that accept a
@@ -73,7 +125,34 @@ class JS extends Minify
*
* @var string[]
*/
- protected $keywordsBefore = array();
+ protected $keywordsBefore = [
+ 'do',
+ 'in',
+ 'let',
+ 'new',
+ 'var',
+ 'case',
+ 'else',
+ 'enum',
+ 'void',
+ 'with',
+ 'class',
+ 'const',
+ 'yield',
+ 'delete',
+ 'export',
+ 'import',
+ 'public',
+ 'static',
+ 'typeof',
+ 'extends',
+ 'package',
+ 'private',
+ 'function',
+ 'protected',
+ 'implements',
+ 'instanceof'
+ ];
/**
* List of JavaScript reserved words that accept a
@@ -88,31 +167,141 @@ class JS extends Minify
*
* @var string[]
*/
- protected $keywordsAfter = array();
+ protected $keywordsAfter = [
+ 'in',
+ 'public',
+ 'extends',
+ 'private',
+ 'protected',
+ 'implements',
+ 'instanceof'
+ ];
+
+ /**
+ * List of all JavaScript operators.
+ *
+ * Will be loaded from /data/js/operators.txt
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
+ *
+ * @var string[]
+ */
+ protected $operators = [
+ '+',
+ '-',
+ '*',
+ '/',
+ '%',
+ '=',
+ '+=',
+ '-=',
+ '*=',
+ '/=',
+ '%=',
+ '<<=',
+ '>>=',
+ '>>>=',
+ '&=',
+ '^=',
+ '|=',
+ '&',
+ '|',
+ '^',
+ '~',
+ '<<',
+ '>>',
+ '>>>',
+ '==',
+ '===',
+ '!=',
+ '!==',
+ '>',
+ '<',
+ '>=',
+ '<=',
+ '&&',
+ '||',
+ '!',
+ '.',
+ '[',
+ ']',
+ '?',
+ ':',
+ ',',
+ ';',
+ '(',
+ ')',
+ '{',
+ '}'
+ ];
/**
* List of JavaScript operators that accept a after
* them. Some end of lines are not the end of a statement, like with these
* operators.
-
*
- * Note: Most operators are fine, we've only removed !, ++ and --.
- * There can't be a newline separating ! and whatever it is negating.
+ * Note: Most operators are fine, we've only removed ++ and --.
* ++ & -- have to be joined with the value they're in-/decrementing.
*
* Will be loaded from /data/js/operators_before.txt
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
+ *
* @var string[]
*/
- protected $operatorsBefore = array();
+ protected $operatorsBefore = [
+ '+',
+ '-',
+ '*',
+ '/',
+ '%',
+ '=',
+ '+=',
+ '-=',
+ '*=',
+ '/=',
+ '%=',
+ '<<=',
+ '>>=',
+ '>>>=',
+ '&=',
+ '^=',
+ '|=',
+ '&',
+ '|',
+ '^',
+ '~',
+ '<<',
+ '>>',
+ '>>>',
+ '==',
+ '===',
+ '!=',
+ '!==',
+ '>',
+ '<',
+ '>=',
+ '<=',
+ '&&',
+ '||',
+ '!',
+ '.',
+ '[',
+ '?',
+ ':',
+ ',',
+ ';',
+ '(',
+ '{',
+ ];
/**
* List of JavaScript operators that accept a before
* them. Some end of lines are not the end of a statement, like when
* continued by one of these operators on the newline.
*
- * Note: Most operators are fine, we've only removed ), ], ++ and --.
+ * Note: Most operators are fine, we've only removed ), ], ++, --, ! and ~.
+ * There can't be a newline separating ! or ~ and whatever it is negating.
* ++ & -- have to be joined with the value they're in-/decrementing.
* ) & ] are "special" in that they have lots or usecases. () for example
* is used for function calls, for grouping, in if () and for (), ...
@@ -120,50 +309,67 @@ class JS extends Minify
* Will be loaded from /data/js/operators_after.txt
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
+ *
* @var string[]
*/
- protected $operatorsAfter = array();
-
- /**
- * {@inheritDoc}
- */
- public function __construct()
- {
- call_user_func_array(array('parent', '__construct'), func_get_args());
-
- $dataDir = JPATH_ADMINISTRATOR.'/components/com_componentbuilder/helpers/';
- $options = FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES;
- $this->keywordsReserved = file($dataDir.'keywords_reserved.txt', $options);
- $this->keywordsBefore = file($dataDir.'keywords_before.txt', $options);
- $this->keywordsAfter = file($dataDir.'keywords_after.txt', $options);
- $this->operatorsBefore = file($dataDir.'operators_before.txt', $options);
- $this->operatorsAfter = file($dataDir.'operators_after.txt', $options);
- }
+ protected $operatorsAfter = [
+ '+',
+ '-',
+ '*',
+ '/',
+ '%',
+ '=',
+ '+=',
+ '-=',
+ '*=',
+ '/=',
+ '%=',
+ '<<=',
+ '>>=',
+ '>>>=',
+ '&=',
+ '^=',
+ '|=',
+ '&',
+ '|',
+ '^',
+ '<<',
+ '>>',
+ '>>>',
+ '==',
+ '===',
+ '!=',
+ '!==',
+ '>',
+ '<',
+ '>=',
+ '<=',
+ '&&',
+ '||',
+ '.',
+ '[',
+ ']',
+ '?',
+ ':',
+ ',',
+ ';',
+ '(',
+ ')',
+ '}',
+ ];
/**
* Minify the data.
* Perform JS optimizations.
*
- * @param string[optional] $path Path to write the data to.
- * @return string The minified data.
+ * @param string[optional] $path Path to write the data to
+ *
+ * @return string The minified data
*/
public function execute($path = null)
{
$content = '';
- // loop files
- foreach ($this->data as $source => $js) {
- /*
- * Combine js: separating the scripts by a ;
- * I'm also adding a newline: it will be eaten when whitespace is
- * stripped, but we need to make sure we're not just appending
- * a new script right after a previous script that ended with a
- * singe-line comment on the last line (in which case it would also
- * be seen as part of that comment)
- */
- $content .= $js."\n;";
- }
-
/*
* Let's first take out strings, comments and regular expressions.
* All of these can contain JS code-like characters, and we should make
@@ -178,11 +384,24 @@ class JS extends Minify
$this->extractStrings('\'"`');
$this->stripComments();
$this->extractRegex();
- $content = $this->replace($content);
- $content = $this->stripWhitespace($content);
- $content = $this->propertyNotation($content);
- $content = $this->shortenBools($content);
+ // loop files
+ foreach ($this->data as $source => $js) {
+ // take out strings, comments & regex (for which we've registered
+ // the regexes just a few lines earlier)
+ $js = $this->replace($js);
+
+ $js = $this->propertyNotation($js);
+ $js = $this->shortenBools($js);
+ $js = $this->stripWhitespace($js);
+
+ // combine js: separating the scripts by a ;
+ $content .= $js . ';';
+ }
+
+ // clean up leftover `;`s from the combination of multiple scripts
+ $content = ltrim($content, ';');
+ $content = (string) substr($content, 0, -1);
/*
* Earlier, we extracted strings & regular expressions and replaced them
@@ -198,15 +417,35 @@ class JS extends Minify
*/
protected function stripComments()
{
- // single-line comments
- $this->registerPattern('/\/\/.*$/m', '');
+ // PHP only supports $this inside anonymous functions since 5.4
+ $minifier = $this;
+ $callback = function ($match) use ($minifier) {
+ if (
+ substr($match[2], 0, 1) === '!' ||
+ strpos($match[2], '@license') !== false ||
+ strpos($match[2], '@preserve') !== false
+ ) {
+ // preserve multi-line comments that start with /*!
+ // or contain @license or @preserve annotations
+ $count = count($minifier->extracted);
+ $placeholder = '/*' . $count . '*/';
+ $minifier->extracted[$placeholder] = $match[0];
+
+ return $match[1] . $placeholder . $match[3];
+ }
+
+ return $match[1] . $match[3];
+ };
// multi-line comments
- $this->registerPattern('/\/\*.*?\*\//s', '');
+ $this->registerPattern('/(\n?)\/\*(.*?)\*\/(\n?)/s', $callback);
+
+ // single-line comments
+ $this->registerPattern('/\/\/.*$/m', '');
}
/**
- * JS can have /-delimited regular expressions, like: /ab+c/.match(string)
+ * JS can have /-delimited regular expressions, like: /ab+c/.match(string).
*
* The content inside the regex can contain characters that may be confused
* for JS code: e.g. it could contain whitespace it needs to match & we
@@ -228,17 +467,71 @@ class JS extends Minify
$minifier = $this;
$callback = function ($match) use ($minifier) {
$count = count($minifier->extracted);
- $placeholder = '/'.$count.'/';
- $minifier->extracted[$placeholder] = '/'.$match[1].'/';
+ $placeholder = '"' . $count . '"';
+ $minifier->extracted[$placeholder] = $match[0];
return $placeholder;
};
- // it's a regex if we can find an opening (not preceded by variable,
- // value or similar) & (non-escaped) closing /,
- $before = $this->getOperatorsForRegex($this->operatorsBefore, '/');
- $this->registerPattern('/^\s*+\K\/(.*?(?registerPattern('/(?:'.implode('|', $before).')\s*+\K\/(.*?(?registerPattern('/' . $before . '\K' . $pattern . $after . '/', $callback);
+
+ // regular expressions following a `)` are rather annoying to detect...
+ // quite often, `/` after `)` is a division operator & if it happens to
+ // be followed by another one (or a comment), it is likely to be
+ // confused for a regular expression
+ // however, it's perfectly possible for a regex to follow a `)`: after
+ // a single-line `if()`, `while()`, ... statement, for example
+ // since, when they occur like that, they're always the start of a
+ // statement, there's only a limited amount of ways they can be useful:
+ // by calling the regex methods directly
+ // if a regex following `)` is not followed by `.`,
+ // it's quite likely not a regex
+ $before = '\)\s*';
+ $after = '(?=\s*\.(' . implode('|', $propertiesAndMethods) . '))';
+ $this->registerPattern('/' . $before . '\K' . $pattern . $after . '/', $callback);
+
+ // 1 more edge case: a regex can be followed by a lot more operators or
+ // keywords if there's a newline (ASI) in between, where the operator
+ // actually starts a new statement
+ // (https://github.com/matthiasmullie/minify/issues/56)
+ $operators = $this->getOperatorsForRegex($this->operatorsBefore, '/');
+ $operators += $this->getOperatorsForRegex($this->keywordsReserved, '/');
+ $after = '(?=\s*\n\s*(' . implode('|', $operators) . '))';
+ $this->registerPattern('/' . $pattern . $after . '/', $callback);
}
/**
@@ -253,7 +546,8 @@ class JS extends Minify
* Because it's sometimes hard to tell if a newline is part of a statement
* that should be terminated or not, we'll just leave some of them alone.
*
- * @param string $content The content to strip the whitespace for.
+ * @param string $content The content to strip the whitespace for
+ *
* @return string
*/
protected function stripWhitespace($content)
@@ -270,16 +564,37 @@ class JS extends Minify
// collapse consecutive line feeds into just 1
$content = preg_replace('/\n+/', "\n", $content);
+ $operatorsBefore = $this->getOperatorsForRegex($this->operatorsBefore, '/');
+ $operatorsAfter = $this->getOperatorsForRegex($this->operatorsAfter, '/');
+ $operators = $this->getOperatorsForRegex($this->operators, '/');
+ $keywordsBefore = $this->getKeywordsForRegex($this->keywordsBefore, '/');
+ $keywordsAfter = $this->getKeywordsForRegex($this->keywordsAfter, '/');
+
// strip whitespace that ends in (or next line begin with) an operator
// that allows statements to be broken up over multiple lines
- $before = $this->getOperatorsForRegex($this->operatorsBefore, '/');
- $after = $this->getOperatorsForRegex($this->operatorsAfter, '/');
- $content = preg_replace('/('.implode('|', $before).')\s+/', '\\1', $content);
- $content = preg_replace('/\s+('.implode('|', $after).')/', '\\1', $content);
+ unset($operatorsBefore['+'], $operatorsBefore['-'], $operatorsAfter['+'], $operatorsAfter['-']);
+ $content = preg_replace(
+ array(
+ '/(' . implode('|', $operatorsBefore) . ')\s+/',
+ '/\s+(' . implode('|', $operatorsAfter) . ')/',
+ ),
+ '\\1',
+ $content
+ );
// make sure + and - can't be mistaken for, or joined into ++ and --
- $content = preg_replace('/(?getOperatorsForRegex($this->operatorsBefore + $this->operatorsAfter, '/');
- $content = preg_replace('/([\}\)\]])[^\S\n]+(?!'.implode('|', $operators).')/', '\\1', $content);
+ $operatorsDiffBefore = array_diff($operators, $operatorsBefore);
+ $operatorsDiffAfter = array_diff($operators, $operatorsAfter);
+ $content = preg_replace('/(' . implode('|', $operatorsDiffBefore) . ')[^\S\n]+/', '\\1', $content);
+ $content = preg_replace('/[^\S\n]+(' . implode('|', $operatorsDiffAfter) . ')/', '\\1', $content);
- // collapse whitespace around reserved words into single space
- $before = $this->getKeywordsForRegex($this->keywordsBefore, '/');
- $after = $this->getKeywordsForRegex($this->keywordsAfter, '/');
- $content = preg_replace('/(^|[;\}\s])\K('.implode('|', $before).')\s+/', '\\2 ', $content);
- $content = preg_replace('/\s+('.implode('|', $after).')(?=([;\{\s]|$))/', ' \\1', $content);
+ /*
+ * Whitespace after `return` can be omitted in a few occasions
+ * (such as when followed by a string or regex)
+ * Same for whitespace in between `)` and `{`, or between `{` and some
+ * keywords.
+ */
+ $content = preg_replace('/\breturn\s+(["\'\/\+\-])/', 'return$1', $content);
+ $content = preg_replace('/\)\s+\{/', '){', $content);
+ $content = preg_replace('/}\n(else|catch|finally)\b/', '}$1', $content);
- // get rid of double semicolons, except when followed by closing-),
- // where semicolons can be used like: "for(v=1,_=b;;)"
- $content = preg_replace('/;+(?!\))/', ';', $content);
+ /*
+ * Get rid of double semicolons, except where they can be used like:
+ * "for(v=1,_=b;;)", "for(v=1;;v++)" or "for(;;ja||(ja=true))".
+ * I'll safeguard these double semicolons inside for-loops by
+ * temporarily replacing them with an invalid condition: they won't have
+ * a double semicolon and will be easy to spot to restore afterwards.
+ */
+ $content = preg_replace('/\bfor\(([^;]*);;([^;]*)\)/', 'for(\\1;-;\\2)', $content);
+ $content = preg_replace('/;+/', ';', $content);
+ $content = preg_replace('/\bfor\(([^;]*);-;([^;]*)\)/', 'for(\\1;;\\2)', $content);
/*
* Next, we'll be removing all semicolons where ASI kicks in.
* for-loops however, can have an empty body (ending in only a
- * semicolon), like: `for(i=1;i<3;i++);`
+ * semicolon), like: `for(i=1;i<3;i++);`, of `for(i in list);`
* Here, nothing happens during the loop; it's just used to keep
* increasing `i`. With that ; omitted, the next line would be expected
- * to be the for-loop's body...
+ * to be the for-loop's body... Same goes for while loops.
* I'm going to double that semicolon (if any) so after the next line,
* which strips semicolons here & there, we're still left with this one.
+ * Note the special recursive construct in the three inner parts of the for:
+ * (\{([^\{\}]*(?-2))*[^\{\}]*\})? - it is intended to match inline
+ * functions bodies, e.g.: i%&|', $delimiter);
+ $operators['='] = '(?getKeywordsForRegex($keywords);
- $keywords = '(?
+ * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+namespace VDM\Minify\Path;
+
+
+use VDM\Minify\Path\Interfaces\ConverterInterface;
+
+class Converter implements ConverterInterface
+{
+ /**
+ * @var string
+ */
+ protected $from;
+
+ /**
+ * @var string
+ */
+ protected $to;
+
+ /**
+ * @param string $from The original base path (directory, not file!)
+ * @param string $to The new base path (directory, not file!)
+ * @param string $root Root directory (defaults to `getcwd`)
+ */
+ public function __construct($from, $to, $root = '')
+ {
+ $shared = $this->shared($from, $to);
+ if ($shared === '') {
+ // when both paths have nothing in common, one of them is probably
+ // absolute while the other is relative
+ $root = $root ?: getcwd();
+ $from = strpos($from, $root) === 0 ? $from : preg_replace('/\/+/', '/', $root . '/' . $from);
+ $to = strpos($to, $root) === 0 ? $to : preg_replace('/\/+/', '/', $root . '/' . $to);
+
+ // or traveling the tree via `..`
+ // attempt to resolve path, or assume it's fine if it doesn't exist
+ $from = @realpath($from) ?: $from;
+ $to = @realpath($to) ?: $to;
+ }
+
+ $from = $this->dirname($from);
+ $to = $this->dirname($to);
+
+ $from = $this->normalize($from);
+ $to = $this->normalize($to);
+
+ $this->from = $from;
+ $this->to = $to;
+ }
+
+ /**
+ * Normalize path.
+ *
+ * @param string $path
+ *
+ * @return string
+ */
+ protected function normalize($path)
+ {
+ // deal with different operating systems' directory structure
+ $path = rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '/');
+
+ // remove leading current directory.
+ if (substr($path, 0, 2) === './') {
+ $path = substr($path, 2);
+ }
+
+ // remove references to current directory in the path.
+ $path = str_replace('/./', '/', $path);
+
+ /*
+ * Example:
+ * /home/forkcms/frontend/cache/compiled_templates/../../core/layout/css/../images/img.gif
+ * to
+ * /home/forkcms/frontend/core/layout/images/img.gif
+ */
+ do {
+ $path = preg_replace('/[^\/]+(? $chunk) {
+ if (isset($path2[$i]) && $path1[$i] == $path2[$i]) {
+ $shared[] = $chunk;
+ } else {
+ break;
+ }
+ }
+
+ return implode('/', $shared);
+ }
+
+ /**
+ * Convert paths relative from 1 file to another.
+ *
+ * E.g.
+ * ../images/img.gif relative to /home/forkcms/frontend/core/layout/css
+ * should become:
+ * ../../core/layout/images/img.gif relative to
+ * /home/forkcms/frontend/cache/minified_css
+ *
+ * @param string $path The relative path that needs to be converted
+ *
+ * @return string The new relative path
+ */
+ public function convert($path)
+ {
+ // quit early if conversion makes no sense
+ if ($this->from === $this->to) {
+ return $path;
+ }
+
+ $path = $this->normalize($path);
+ // if we're not dealing with a relative path, just return absolute
+ if (strpos($path, '/') === 0) {
+ return $path;
+ }
+
+ // normalize paths
+ $path = $this->normalize($this->from . '/' . $path);
+
+ // strip shared ancestor paths
+ $shared = $this->shared($path, $this->to);
+ $path = mb_substr($path, mb_strlen($shared));
+ $to = mb_substr($this->to, mb_strlen($shared));
+
+ // add .. for every directory that needs to be traversed to new path
+ $to = str_repeat('../', count(array_filter(explode('/', $to))));
+
+ return $to . ltrim($path, '/');
+ }
+
+ /**
+ * Attempt to get the directory name from a path.
+ *
+ * @param string $path
+ *
+ * @return string
+ */
+ protected function dirname($path)
+ {
+ if (@is_file($path)) {
+ return dirname($path);
+ }
+
+ if (@is_dir($path)) {
+ return rtrim($path, '/');
+ }
+
+ // no known file/dir, start making assumptions
+
+ // ends in / = dir
+ if (mb_substr($path, -1) === '/') {
+ return rtrim($path, '/');
+ }
+
+ // has a dot in the name, likely a file
+ if (preg_match('/.*\..*$/', basename($path)) !== 0) {
+ return dirname($path);
+ }
+
+ // you're on your own here!
+ return $path;
+ }
+}
+
diff --git a/libraries/jcb_powers/VDM.Minify/src/Path/Interfaces/ConverterInterface.php b/libraries/jcb_powers/VDM.Minify/src/Path/Interfaces/ConverterInterface.php
new file mode 100644
index 000000000..e64774dd4
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Path/Interfaces/ConverterInterface.php
@@ -0,0 +1,24 @@
+
+ * @copyright Copyright (c) 2015, Matthias Mullie. All rights reserved
+ * @license MIT License
+ */
+namespace VDM\Minify\Path\Interfaces;
+
+interface ConverterInterface
+{
+ /**
+ * Convert file paths.
+ *
+ * @param string $path The path to be converted
+ *
+ * @return string The new path
+ */
+ public function convert($path);
+}
+
diff --git a/libraries/jcb_powers/VDM.Minify/src/Path/Interfaces/index.html b/libraries/jcb_powers/VDM.Minify/src/Path/Interfaces/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Path/Interfaces/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/jcb_powers/VDM.Minify/src/Path/index.html b/libraries/jcb_powers/VDM.Minify/src/Path/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/Path/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/jcb_powers/VDM.Minify/src/index.html b/libraries/jcb_powers/VDM.Minify/src/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Minify/src/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/jcb_powers/VDM.Psr/index.html b/libraries/jcb_powers/VDM.Psr/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Psr/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/libraries/jcb_powers/VDM.Psr/src/Cache/CacheItemInterface.php b/libraries/jcb_powers/VDM.Psr/src/Cache/CacheItemInterface.php
new file mode 100644
index 000000000..458e1dbe4
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Psr/src/Cache/CacheItemInterface.php
@@ -0,0 +1,114 @@
+
+ * @git Caching Interface
+ * @license MIT
+ */
+namespace VDM\Psr\Cache;
+
+
+/**
+ * CacheItemInterface defines an interface for interacting with objects inside a cache.
+ *
+ * Each Item object MUST be associated with a specific key, which can be set
+ * according to the implementing system and is typically passed by the
+ * Cache\CacheItemPoolInterface object.
+ *
+ * The Cache\CacheItemInterface object encapsulates the storage and retrieval of
+ * cache items. Each Cache\CacheItemInterface is generated by a
+ * Cache\CacheItemPoolInterface object, which is responsible for any required
+ * setup as well as associating the object with a unique Key.
+ * Cache\CacheItemInterface objects MUST be able to store and retrieve any type
+ * of PHP value defined in the Data section of the specification.
+ *
+ * Calling Libraries MUST NOT instantiate Item objects themselves. They may only
+ * be requested from a Pool object via the getItem() method. Calling Libraries
+ * SHOULD NOT assume that an Item created by one Implementing Library is
+ * compatible with a Pool from another Implementing Library.
+ */
+interface CacheItemInterface
+{
+ /**
+ * Returns the key for the current cache item.
+ *
+ * The key is loaded by the Implementing Library, but should be available to
+ * the higher level callers when needed.
+ *
+ * @return string
+ * The key string for this cache item.
+ */
+ public function getKey(): string;
+
+ /**
+ * Retrieves the value of the item from the cache associated with this object's key.
+ *
+ * The value returned must be identical to the value originally stored by set().
+ *
+ * If isHit() returns false, this method MUST return null. Note that null
+ * is a legitimate cached value, so the isHit() method SHOULD be used to
+ * differentiate between "null value was found" and "no value was found."
+ *
+ * @return mixed
+ * The value corresponding to this cache item's key, or null if not found.
+ */
+ public function get(): mixed;
+
+ /**
+ * Confirms if the cache item lookup resulted in a cache hit.
+ *
+ * Note: This method MUST NOT have a race condition between calling isHit()
+ * and calling get().
+ *
+ * @return bool
+ * True if the request resulted in a cache hit. False otherwise.
+ */
+ public function isHit(): bool;
+
+ /**
+ * Sets the value represented by this cache item.
+ *
+ * The $value argument may be any item that can be serialized by PHP,
+ * although the method of serialization is left up to the Implementing
+ * Library.
+ *
+ * @param mixed $value
+ * The serializable value to be stored.
+ *
+ * @return static
+ * The invoked object.
+ */
+ public function set(mixed $value): static;
+
+ /**
+ * Sets the expiration time for this cache item.
+ *
+ * @param ?\DateTimeInterface $expiration
+ * The point in time after which the item MUST be considered expired.
+ * If null is passed explicitly, a default value MAY be used. If none is set,
+ * the value should be stored permanently or for as long as the
+ * implementation allows.
+ *
+ * @return static
+ * The called object.
+ */
+ public function expiresAt(?\DateTimeInterface $expiration): static;
+
+ /**
+ * Sets the expiration time for this cache item.
+ *
+ * @param int|\DateInterval|null $time
+ * The period of time from the present after which the item MUST be considered
+ * expired. An integer parameter is understood to be the time in seconds until
+ * expiration. If null is passed explicitly, a default value MAY be used.
+ * If none is set, the value should be stored permanently or for as long as the
+ * implementation allows.
+ *
+ * @return static
+ * The called object.
+ */
+ public function expiresAfter(int|\DateInterval|null $time): static;
+}
+
diff --git a/libraries/jcb_powers/VDM.Psr/src/Cache/index.html b/libraries/jcb_powers/VDM.Psr/src/Cache/index.html
new file mode 100644
index 000000000..fa6d84e80
--- /dev/null
+++ b/libraries/jcb_powers/VDM.Psr/src/Cache/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/site/helpers/componentbuilder.php b/site/helpers/componentbuilder.php
index 392df101e..bd3b49350 100644
--- a/site/helpers/componentbuilder.php
+++ b/site/helpers/componentbuilder.php
@@ -24,7 +24,9 @@ spl_autoload_register(function ($class) {
// project-specific base directories and namespace prefix
$search = [
'libraries/jcb_powers/VDM.Joomla' => 'VDM\\Joomla',
- 'libraries/jcb_powers/VDM.Gitea' => 'VDM\\Gitea'
+ 'libraries/jcb_powers/VDM.Minify' => 'VDM\\Minify',
+ 'libraries/jcb_powers/VDM.Gitea' => 'VDM\\Gitea',
+ 'libraries/jcb_powers/VDM.Psr' => 'VDM\\Psr'
];
// Start the search and load if found
$found = false;
@@ -1075,8 +1077,6 @@ abstract class ComponentbuilderHelper
{
// import the Joomla librarys
jimport('joomla.application.component.modellist');
- // include class to minify js
- require_once JPATH_ADMINISTRATOR.'/components/com_componentbuilder/helpers/js.php';
}
// load only if smart
if ('smart' === $type)