362 lines
11 KiB
Plaintext
362 lines
11 KiB
Plaintext
/**
|
|
* The external code/string to be added
|
|
*
|
|
* @var array
|
|
* @since 3.2.0
|
|
*/
|
|
protected array $code = [];
|
|
|
|
/**
|
|
* The external code/string cutter
|
|
*
|
|
* @var array
|
|
* @since 3.2.0
|
|
*/
|
|
protected array $cutter = [];
|
|
|
|
/**
|
|
* Compiler Placeholder
|
|
*
|
|
* @var Placeholder
|
|
* @since 3.2.0
|
|
**/
|
|
protected Placeholder $placeholder;
|
|
|
|
/**
|
|
* Database object to query local DB
|
|
*
|
|
* @var \JDatabaseDriver
|
|
* @since 3.2.0
|
|
**/
|
|
protected \JDatabaseDriver $db;
|
|
|
|
/**
|
|
* User object
|
|
*
|
|
* @var User
|
|
* @since 3.2.0
|
|
**/
|
|
protected User $user;
|
|
|
|
/**
|
|
* Database object to query local DB
|
|
*
|
|
* @var CMSApplication
|
|
* @since 3.2.0
|
|
**/
|
|
protected CMSApplication $app;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param Placeholder|null $placeholder The compiler placeholder object.
|
|
* @param \JDatabaseDriver|null $db The Database Driver object.
|
|
* @param User|null $user The User object.
|
|
* @param CMSApplication|null $app The CMS Application object.
|
|
*
|
|
* @throws \Exception
|
|
* @since 3.2.0
|
|
*/
|
|
public function __construct(?Placeholder $placeholder = null,
|
|
?\JDatabaseDriver $db = null, ?User $user = null, ?CMSApplication $app = null)
|
|
{
|
|
$this->placeholder = $placeholder ?: Compiler::_('Placeholder');
|
|
$this->db = $db ?: Factory::getDbo();
|
|
$this->user = $user ?: Factory::getUser();
|
|
$this->app = $app ?: Factory::getApplication();
|
|
}
|
|
|
|
/**
|
|
* Set the external code string & load it in to string
|
|
*
|
|
* @param string $string The content to check
|
|
* @param int $debug The switch to debug the update
|
|
*
|
|
* @return string
|
|
* @since 3.2.0
|
|
*/
|
|
public function set(string $string, int $debug = 0): string
|
|
{
|
|
// check if content has custom code placeholder
|
|
if (strpos($string, '[EXTERNA' . 'LCODE=') !== false)
|
|
{
|
|
// if debug
|
|
if ($debug)
|
|
{
|
|
echo 'External Code String:';
|
|
var_dump($string);
|
|
}
|
|
// target content
|
|
$bucket = [];
|
|
$found = GetHelper::allBetween(
|
|
$string, '[EXTERNA' . 'LCODE=', ']'
|
|
);
|
|
if (ArrayHelper::check($found))
|
|
{
|
|
// build local bucket
|
|
foreach ($found as $target)
|
|
{
|
|
// check for cutting sequence
|
|
// example: >{3|4
|
|
// will cut 3 rows at top and 4 rows at bottom
|
|
// if the external code has 8 or more lines
|
|
if (($pos = strpos((string) $target, '>{')) !== false)
|
|
{
|
|
// the length
|
|
$target_len = strlen((string) $target);
|
|
// where to cut
|
|
$cutting = $target_len - $pos;
|
|
// get the sequence
|
|
$sequence = substr((string) $target, "-$cutting");
|
|
// remove from the URL
|
|
$target_url = str_replace($sequence, '', (string) $target);
|
|
// set the cut key for this target if not set
|
|
$this->cutter[trim((string) $target)] = str_replace('>{', '', $sequence);
|
|
}
|
|
else
|
|
{
|
|
$target_url = $target;
|
|
}
|
|
// check if the target is valid URL or path
|
|
if ((!filter_var($target_url, FILTER_VALIDATE_URL) === false
|
|
&& FileHelper::exists($target_url))
|
|
|| (Path::clean($target_url) === $target_url
|
|
&& FileHelper::exists($target_url)))
|
|
{
|
|
$this->getCode($target, $bucket);
|
|
}
|
|
// give notice that target is not a valid url/path
|
|
else
|
|
{
|
|
// set key
|
|
$key = '[EXTERNA' . 'LCODE=' . $target . ']';
|
|
// set the notice
|
|
$this->app->enqueueMessage(
|
|
Text::_('<hr /><h3>External Code Warning</h3>'
|
|
), 'Warning'
|
|
);
|
|
$this->app->enqueueMessage(
|
|
Text::sprintf('The <b>%s</b> is not a valid url/path!',
|
|
$key
|
|
), 'Warning'
|
|
);
|
|
// remove the placeholder
|
|
$bucket[$key] = '';
|
|
}
|
|
}
|
|
// now update local string if bucket has values
|
|
if (ArrayHelper::check($bucket))
|
|
{
|
|
$string = $this->placeholder->update($string, $bucket);
|
|
}
|
|
}
|
|
// if debug
|
|
if ($debug)
|
|
{
|
|
echo 'External Code String After Update:';
|
|
var_dump($string);
|
|
}
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Get the External Code/String
|
|
*
|
|
* @param string $string The content to check
|
|
* @param array $bucket The Placeholders bucket
|
|
*
|
|
* @return void
|
|
* @since 3.2.0
|
|
*/
|
|
protected function getCode(string $target, array &$bucket)
|
|
{
|
|
// set URL key
|
|
$target_key = trim($target);
|
|
// set key
|
|
$key = '[EXTERNA' . 'LCODE=' . $target . ']';
|
|
// remove the cut sequence from the url
|
|
if (isset($this->cutter[$target_key]))
|
|
{
|
|
// remove from the URL
|
|
$target_url = trim(str_replace('>{' . $this->cutter[$target_key], '', $target));
|
|
}
|
|
else
|
|
{
|
|
$target_url = trim($target);
|
|
}
|
|
// check if we already fetched this
|
|
if (!isset($this->code[$target_key]))
|
|
{
|
|
// get the data string (code)
|
|
$this->code[$target_key]
|
|
= FileHelper::getContent($target_url);
|
|
// check if we must cut this
|
|
if (isset($this->cutter[$target_key]) &&
|
|
$this->cutter[$target_key])
|
|
{
|
|
$this->code[$target_key] = $this->cut(
|
|
$this->code[$target_key],
|
|
$this->cutter[$target_key],
|
|
$key
|
|
);
|
|
}
|
|
// did we get any value
|
|
if (StringHelper::check(
|
|
$this->code[$target_key]
|
|
))
|
|
{
|
|
// check for changes
|
|
$live_hash = md5($this->code[$target_key]);
|
|
// check if it exists local
|
|
if ($hash = GetHelper::var(
|
|
'external_code', $target_key, 'target', 'hash'
|
|
))
|
|
{
|
|
// must be an admin make a change to use EXTERNAL code (we may add a custom access switch - use ADMIN for now)
|
|
if ($hash !== $live_hash && $this->user->authorise(
|
|
'core.admin', 'com_componentbuilder'
|
|
))
|
|
{
|
|
// update the hash since it changed
|
|
$object = new \stdClass();
|
|
$object->target = $target_key;
|
|
$object->hash = $live_hash;
|
|
// update local hash
|
|
$this->db->updateObject(
|
|
'#__componentbuilder_external_code', $object,
|
|
'target'
|
|
);
|
|
// give notice of the change
|
|
$this->app->enqueueMessage(
|
|
Text::_('<hr /><h3>External Code Warning</h3>'),
|
|
'Warning'
|
|
);
|
|
$this->app->enqueueMessage(
|
|
Text::sprintf('The code/string from <b>%s</b> has been <b>changed</b> since the last compilation. Please investigate to ensure the changes are safe! <b>Should you not expect this change to the external code/string being added, then this is a serious issue! and requires immediate attention!</b> Do not ignore this warning as it will only show <b>once</b>.',
|
|
$key
|
|
), 'Warning'
|
|
);
|
|
}
|
|
elseif ($hash !== $live_hash)
|
|
{
|
|
// set the notice
|
|
$this->app->enqueueMessage(
|
|
Text::_('<hr /><h3>External Code Error</h3>'),
|
|
'Error'
|
|
);
|
|
$this->app->enqueueMessage(
|
|
Text::sprintf('%s, we detected a change in <b>EXTERNALCODE</b>, but you do not have permission to allow this change so <b>%s</b> was removed from the compilation. Please contact your system administrator for more info!<br /><small>(admin access required)</small>',
|
|
$this->user->get('name'), $key
|
|
), 'Error'
|
|
);
|
|
// remove the code/string
|
|
$this->code[$target_key] = '';
|
|
}
|
|
}
|
|
// only an admin can add new EXTERNAL code (we may add a custom access switch - use ADMIN for now)
|
|
elseif ($this->user->authorise(
|
|
'core.admin', 'com_componentbuilder'
|
|
))
|
|
{
|
|
// add the hash to track changes
|
|
$object = new \stdClass();
|
|
$object->target = $target_key;
|
|
$object->hash = $live_hash;
|
|
// insert local hash
|
|
$this->db->insertObject(
|
|
'#__componentbuilder_external_code', $object
|
|
);
|
|
// give notice the first time this is added
|
|
$this->app->enqueueMessage(
|
|
Text::_('<hr /><h3>External Code Notice</h3>'),
|
|
'Warning'
|
|
);
|
|
$this->app->enqueueMessage(
|
|
Text::sprintf('The code/string from <b>%s</b> has been added for the <b>first time</b>. Please <i>investigate</i> to ensure the correct code/string was used! <b>Should you not know about this NEW external code/string being added, then this is a serious danger! and requires immediate attention!</b> Do not ignore this warning as it will only show <b>once</b>.',
|
|
$key
|
|
), 'Warning'
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// set the notice
|
|
$this->app->enqueueMessage(
|
|
Text::_('<hr /><h3>External Code Error</h3>'),
|
|
'Error'
|
|
);
|
|
$this->app->enqueueMessage(
|
|
Text::sprintf('%s, we detected <b>NEW EXTERNALCODE</b>, but you do not have permission to allow this new code/string so <b>%s</b> was removed from the compilation. Please contact you system administrator for more info!<br /><small>(admin access required)</small>',
|
|
$this->user->get('name'), $key
|
|
), 'Error'
|
|
);
|
|
// remove the code/string
|
|
$this->code[$target_key] = '';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// set notice that we could not get a valid string from the target
|
|
$this->app->enqueueMessage(
|
|
Text::_('<hr /><h3>External Code Warning</h3>'), 'Error'
|
|
);
|
|
$this->app->enqueueMessage(
|
|
Text::sprintf('The <b>%s</b> returned an invalid string!', $key
|
|
), 'Error'
|
|
);
|
|
}
|
|
}
|
|
|
|
// add to local bucket
|
|
$bucket[$key] = $this->code[$target_key] ?? '';
|
|
}
|
|
|
|
/**
|
|
* Cut the External Code/String
|
|
*
|
|
* @param string $string The content to cut
|
|
* @param string $sequence The cutting sequence
|
|
* @param string $key The content key
|
|
*
|
|
* @return string
|
|
* @since 3.2.0
|
|
*/
|
|
protected function cut(string $string, string $sequence, string $key): string
|
|
{
|
|
// we first break the string up in rows
|
|
$rows = (array) explode(PHP_EOL, $string);
|
|
// get the cutting sequence
|
|
$cutter = (array) explode('|', $sequence);
|
|
// we only continue if we have more rows than we have to cut
|
|
if (array_sum($cutter) < ArrayHelper::check($rows))
|
|
{
|
|
// remove the rows at the bottom if needed
|
|
if (isset($cutter[1]) && $cutter[1] > 0)
|
|
{
|
|
array_splice($rows, "-$cutter[1]");
|
|
}
|
|
// remove the rows at the top if needed
|
|
if ($cutter[0] > 0)
|
|
{
|
|
$rows = array_splice($rows, $cutter[0]);
|
|
}
|
|
|
|
// return the remaining rows
|
|
return implode(PHP_EOL, $rows);
|
|
}
|
|
|
|
// we set an error message about too few lines to cut
|
|
$this->app->enqueueMessage(
|
|
Text::_('<hr /><h3>External Code Notice</h3>'),
|
|
'Error'
|
|
);
|
|
$this->app->enqueueMessage(
|
|
Text::sprintf('The <b>%s</b> cut sequence failed on the returned external code/string as more lines has to be cut then was found in the code/string. We have completely removed the code. Please check this code/string!',
|
|
$key
|
|
), 'Error'
|
|
);
|
|
|
|
return '';
|
|
}
|