com_extensiondistributor/admin/helpers/extensiondistributor.php

2353 lines
70 KiB
PHP
Raw Normal View History

2022-06-02 15:01:28 +00:00
<?php
/*----------------------------------------------------------------------------------| www.vdm.io |----/
Agence Agerix
/-------------------------------------------------------------------------------------------------------/
@version 1.x.x
@build 2nd June, 2022
@created 12th December, 2020
@package Extension Distributor
@subpackage extensiondistributor.php
@author Emmanuel Danan <https://agerix.fr>
@copyright Copyright (C) 2021. All Rights Reserved.
@license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
____ _____ _____ __ __ __ __ ___ _____ __ __ ____ _____ _ _ ____ _ _ ____
(_ _)( _ )( _ )( \/ )( ) /__\ / __)( _ )( \/ )( _ \( _ )( \( )( ___)( \( )(_ _)
.-_)( )(_)( )(_)( ) ( )(__ /(__)\ ( (__ )(_)( ) ( )___/ )(_)( ) ( )__) ) ( )(
\____) (_____)(_____)(_/\/\_)(____)(__)(__) \___)(_____)(_/\/\_)(__) (_____)(_)\_)(____)(_)\_) (__)
/------------------------------------------------------------------------------------------------------*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Language\Language;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
use Joomla\Utilities\ArrayHelper;
/**
* Extensiondistributor component helper.
*/
abstract class ExtensiondistributorHelper
{
/**
* Composer Switch
*
* @var array
*/
protected static $composer = array();
/**
* The Main Active Language
*
* @var string
*/
public static $langTag;
/**
* The Global Admin Event Method.
**/
public static function globalEvent($document)
{
global $cparams;
$app = JFactory::getApplication();
$cparams = JComponentHelper::getParams('com_extensiondistributor');
$folder = JPATH_SITE . '/' . $cparams->get('import_directory', 'extmanagerimport');
$files = JFolder::files($folder,'.zip',false,true);
$model = self::getModel('maintenance');
$orphans = $model->getOrphans();
$missing = $model->getMissing();
$duplicates = $model->getDuplicates();
$problems = count(@$orphans) + count(@$missing) + count(@$duplicates);
$copyright = '<div class=\"text-center mt40\"> Made with <i class=\"icon-joomla\"></i>and <a href=\"https://www.joomlacomponentbuilder.com/\" target=\"_blank\"><span class=\"label label-info\">JCB</span></a>&nbsp;&nbsp;with a lot of&nbsp;&nbsp;<span class=\"love\"><span class=\"icon-heart\"></span></span><br><a href=\"mailto:emmanuel.danan@gmail.com\" target=\"_blank\">Emmanuel Danan</a> - <a href=\"https://agerix.fr\" target=\"_blank\">Agence Agerix</a></div>';
$count = self::checkArray($files) ? count($files) : 0;
$script = '';
if ($count > 0) {
$badge = '&nbsp;&nbsp;<span class=\"badge badge-important\">'.$count.'</span>';
$floatbadge = '<span style=\"float: right;\"><span class=\"badge badge-important\">'.$count.'</span></span>';
$script .= '
jQuery(document).ready(function() {
jQuery("#sidebar #submenu li:nth-child(9) a").append("'.$badge.'");
jQuery("#dashboard_left .accordion-inner .dashboard-wraper:nth-child(6) a").prepend("'.$floatbadge.'");
});
';
}
if ($problems > 0) {
$badge = '&nbsp;&nbsp;<span class=\"badge badge-warning\">'.$problems.'</span>';
$floatbadge = '<span style=\"float: right;\"><span class=\"badge badge-warning\">'.$problems.'</span></span>';
$script .= '
jQuery(document).ready(function() {
jQuery("#sidebar #submenu li:nth-child(10) a").append("'.$badge.'");
jQuery("#dashboard_left .accordion-inner .dashboard-wraper:nth-child(7) a").prepend("'.$floatbadge.'");
});
';
}
$copyscript = '
jQuery(document).ready(function() {
jQuery("#j-main-container").append("'.$copyright.'");
});
';
if (!empty($script)) {
$document->addScriptDeclaration($script);
}
$document->addScriptDeclaration($copyscript);
}
public static function getReleases($id, $view = 'extension', $latest = false)
{
if (!$id) {
return null;
}
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName(
array('id','version_number','release_date','reltype','stability','file','extension','package')
))
->from($db->quoteName('#__extensiondistributor_release'))
->where(
array(
$db->quoteName($view) . ' = ' . (int)$id,
$db->quoteName('published') . ' = 1'
)
)
->order('INET_ATON(version_number) DESC')
;
$db->setQuery($query);
return $latest ? $db->loadObject() : $db->loadObjectList();
}
public static function getPackageContent($packageId): array
{
$package = self::getPackageObject($packageId);
// We first get the extensions of the package
$extensions = $package->files;
$extensions = json_decode($extensions,true);
$files = array();
foreach ($extensions as &$extension)
{
$data = self::getReleases($extension['extension'],'extension',true);
$details = self::getExtensionObject($extension['extension']);
$extension['details'] = $details;
$extension['release'] = $data;
if (isset($data->file)) {
$files[$data->id] = $data->file;
}
}
return array('extensions' => $extensions, 'files' => $files, 'package' => $package);
}
public static function createPackage($packageId,$release)
{
$cparams = JComponentHelper::getParams('com_extensiondistributor');
$content = self::getPackageContent($packageId);
$package = $content['package'];
$extensions = $content['extensions'];
$files = $content['files'];
$lists = self::getApplicationLists();
$releaseFolder = JPATH_SITE . '/' . $cparams->get('releases_directory');
$tmpFolder = JPATH_SITE . '/tmp/' . $package->packagename;
$update_path = $cparams->get('updates_directory','updates');
$update_file = $cparams->get('updateserver_url', JUri::root()).$update_path.'/'.$package->update;
// We first create the temporary folder
JFolder::create($tmpFolder);
// We create the packages folder and copy the files inside
JFolder::create($tmpFolder . '/packages');
foreach ($files as $file) {
JFile::copy($releaseFolder . '/' . $file, $tmpFolder . '/packages/' . $file);
}
$zipFilename = self::createPackageFileName($package, $release->version_number, $release->stability);
$xmldoc = new DOMDocument();
$xmldoc->encoding = 'UTF-8';
$xmldoc->xmlVersion = '1.0';
$xmldoc->formatOutput = true;
$xml_file_name = $tmpFolder .'/pkg_'.$package->packagename.'.xml';
// Extension
$root = $xmldoc->createElement('extension');
$root->setAttributeNode(new DOMAttr('type', 'package'));
$root->setAttributeNode(new DOMAttr('version', '3.8'));
$root->setAttributeNode(new DOMAttr('method', 'upgrade'));
$root->appendChild($xmldoc->createElement('name', $package->name));
$root->appendChild($xmldoc->createElement('version', $release->version_number)); // => release
$root->appendChild($xmldoc->createElement('author', $package->author));
$root->appendChild($xmldoc->createElement('authorUrl', $package->authorurl));
$root->appendChild($xmldoc->createElement('authorEmail', $package->authoremail));
$root->appendChild($xmldoc->createElement('creationDate', JHtml::date($release->release_date,'M Y'))); // => release
$root->appendChild($xmldoc->createElement('packagename', $package->packagename));
$root->appendChild($xmldoc->createElement('packager', $package->packager));
$root->appendChild($xmldoc->createElement('packagerurl', $package->packagerurl));
$root->appendChild($xmldoc->createElement('copyright', $package->copyright));
$root->appendChild($xmldoc->createElement('license', $package->license));
$root->appendChild($xmldoc->createElement('description'))->appendChild($xmldoc->createCDATASection($package->description));
$root->appendChild($xmldoc->createElement('scriptfile', 'script.php')); // => dynamic A venir
if ($package->blockchilduninstall) {
$root->appendChild($xmldoc->createElement('blockChildUninstall', 'true'));
}
$files_node = $xmldoc->createElement('files');
$files_node->setAttributeNode(new DOMAttr('folder', 'packages'));
foreach ($extensions as $extension)
{
switch ($extension['details']->type)
{
case 'component' :
case 'library' :
$child_node_file = $xmldoc->createElement('file', $extension['release']->file);
$child_node_file->setAttributeNode(new DOMAttr('type', $extension['details']->type));
$child_node_file->setAttributeNode(new DOMAttr('id', $extension['details']->element));
$files_node->appendChild($child_node_file);
break;
case 'module' :
case 'template' :
case 'language' :
$child_node_file = $xmldoc->createElement('file', $extension['release']->file);
$child_node_file->setAttributeNode(new DOMAttr('type', $extension['details']->type));
$child_node_file->setAttributeNode(new DOMAttr('id', $extension['details']->element));
$child_node_file->setAttributeNode(new DOMAttr('client', $extension['release']->client));
$files_node->appendChild($child_node_file);
break;
case 'plugin' :
$child_node_file = $xmldoc->createElement('file', $extension['release']->file);
$child_node_file->setAttributeNode(new DOMAttr('type', $extension['details']->type));
$child_node_file->setAttributeNode(new DOMAttr('id', $extension['details']->element));
$child_node_file->setAttributeNode(new DOMAttr('group', $extension['details']->group));
$files_node->appendChild($child_node_file);
break;
}
}
$root->appendChild($files_node);
$updateservers_node = $xmldoc->createElement('updateservers');
$child_node_server = $xmldoc->createElement('server', $update_file);
$child_node_server->setAttributeNode(new DOMAttr('type', 'extension'));
$child_node_server->setAttributeNode(new DOMAttr('priority', '1'));
$child_node_server->setAttributeNode(new DOMAttr('name', $cparams->get('server_name')));
$updateservers_node->appendChild($child_node_server);
$root->appendChild($updateservers_node);
$xmldoc->appendChild($root);
$xmldoc->save($xml_file_name);
// We create the script file
self::createScriptFile($packageId, $tmpFolder);
// We zip everything in a package
self::zipPackage($releaseFolder.'/'.$zipFilename,$tmpFolder);
JFolder::delete($tmpFolder);
return $zipFilename;
}
public static function zipPackage($zipFile, $zipDir)
{
$zip = new ZipArchive();
$zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($zipDir),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file)
{
// Skip directories (they would be added automatically)
if (!$file->isDir())
{
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($zipDir) + 1);
// Add current file to archive
$zip->addFile($filePath, $relativePath);
}
}
$zip->close();
}
protected static $tabSpacerBucket = array();
protected static $tabSpacer = "\t";
protected static $debugLinenr = false;
public static function _t($nr)
{
// check if we already have the string
if (!isset(self::$tabSpacerBucket[$nr]))
{
// get the string
self::$tabSpacerBucket[$nr] = str_repeat(self::$tabSpacer, (int) $nr);
}
// return stored string
return self::$tabSpacerBucket[$nr];
}
public static function getExtensionInstallClass(&$extension)
{
// yes we are adding it
$script = PHP_EOL . '/**';
$script .= PHP_EOL . ' * ' . $extension->official_name
. ' script file.';
$script .= PHP_EOL . ' *';
$script .= PHP_EOL . ' * @package ' . $extension->class_name;
$script .= PHP_EOL . ' */';
$script .= PHP_EOL . 'class ' . $extension->installer_class_name;
$script .= PHP_EOL . '{';
// set constructor
if (isset($extension->add_php_script_construct)
&& $extension->add_php_script_construct == 1
&& self::checkString(
$extension->php_script_construct
))
{
$script .= self::setInstallMethodScript(
'construct', $extension->php_script_construct
);
}
// add PHP in extension install
$addScriptMethods = array('php_preflight', 'php_postflight',
'php_method');
$addScriptTypes = array('install', 'update', 'uninstall',
'discover_install');
// set some buckets for sorting
$function_install = array();
$function_update = array();
$function_uninstall = array();
$has_php_preflight = false;
$function_php_preflight = array('install' => array(),
'uninstall' => array(),
'discover_install' => array(),
'update' => array());
$has_php_postflight = false;
$function_php_postflight = array('install' => array(),
'uninstall' => array(),
'discover_install' => array(),
'update' => array());
// the function sorter
foreach ($addScriptMethods as $scriptMethod)
{
foreach ($addScriptTypes as $scriptType)
{
if (isset(
$extension->{'add_' . $scriptMethod . '_' . $scriptType}
)
&& $extension->{'add_' . $scriptMethod . '_' . $scriptType}
== 1
&& self::checkString(
$extension->{$scriptMethod . '_' . $scriptType}
))
{
// add to the main methods
if ('php_method' === $scriptMethod)
{
${'function_' . $scriptType}[]
= $extension->{$scriptMethod . '_' . $scriptType};
}
else
{
${'function_' . $scriptMethod}[$scriptType][]
= $extension->{$scriptMethod
. '_' . $scriptType};
${'has_' . $scriptMethod} = true;
}
}
}
}
// now add the install script.
if (self::checkArray($function_install))
{
$script .= self::setInstallMethodScript(
'install', $function_install
);
}
// now add the update script.
if (self::checkArray($function_update))
{
$script .= self::setInstallMethodScript(
'update', $function_update
);
}
// now add the uninstall script.
if (self::checkArray($function_uninstall))
{
$script .= self::setInstallMethodScript(
'uninstall', $function_uninstall
);
}
// now add the preflight script.
if ($has_php_preflight)
{
$script .= self::setInstallMethodScript(
'preflight', $function_php_preflight
);
}
// now add the postflight script.
if ($has_php_postflight)
{
$script .= self::setInstallMethodScript(
'postflight', $function_php_postflight
);
}
$script .= PHP_EOL . '}' . PHP_EOL;
return $script;
}
public static function setInstallMethodScript($function_name, &$scripts)
{
$script = '';
// build function
switch ($function_name)
{
case 'install':
case 'update':
case 'uninstall':
// the main function types
$script = PHP_EOL . PHP_EOL . self::_t(1) . '/**';
$script .= PHP_EOL . self::_t(1) . ' * Called on '
. $function_name;
$script .= PHP_EOL . self::_t(1) . ' *';
$script .= PHP_EOL . self::_t(1)
. ' * @param JAdapterInstance $adapter The object responsible for running this script';
$script .= PHP_EOL . self::_t(1) . ' *';
$script .= PHP_EOL . self::_t(1)
. ' * @return boolean True on success';
$script .= PHP_EOL . self::_t(1) . ' */';
$script .= PHP_EOL . self::_t(1) . 'public function '
. $function_name . '(JAdapterInstance $adapter)';
$script .= PHP_EOL . self::_t(1) . '{';
$script .= PHP_EOL . implode(PHP_EOL . PHP_EOL, $scripts);
// Added the HTML message
$script .= PHP_EOL . '// Custom HTML message uninstall';
// return true
if ('uninstall' !== $function_name)
{
$script .= PHP_EOL . self::_t(2) . 'return true;';
}
break;
case 'preflight':
case 'postflight':
// the pre/post function types
$script = PHP_EOL . PHP_EOL . self::_t(1) . '/**';
$script .= PHP_EOL . self::_t(1)
. ' * Called before any type of action';
$script .= PHP_EOL . self::_t(1) . ' *';
$script .= PHP_EOL . self::_t(1)
. ' * @param string $route Which action is happening (install|uninstall|discover_install|update)';
$script .= PHP_EOL . self::_t(1)
. ' * @param JAdapterInstance $adapter The object responsible for running this script';
$script .= PHP_EOL . self::_t(1) . ' *';
$script .= PHP_EOL . self::_t(1)
. ' * @return boolean True on success';
$script .= PHP_EOL . self::_t(1) . ' */';
$script .= PHP_EOL . self::_t(1) . 'public function '
. $function_name . '($route, JAdapterInstance $adapter)';
$script .= PHP_EOL . self::_t(1) . '{';
$script .= PHP_EOL . self::_t(2) . '//' . self::setLine(
__LINE__
) . ' get application';
$script .= PHP_EOL . self::_t(2)
. '$app = JFactory::getApplication();' . PHP_EOL;
// add the default version check (TODO) must make this dynamic
if ('preflight' === $function_name)
{
$script .= PHP_EOL . self::_t(2) . '//' . self::setLine(
__LINE__
) . ' the default for both install and update';
$script .= PHP_EOL . self::_t(2)
. '$jversion = new JVersion();';
$script .= PHP_EOL . self::_t(2)
. "if (!\$jversion->isCompatible('3.8.0'))";
$script .= PHP_EOL . self::_t(2) . '{';
$script .= PHP_EOL . self::_t(3)
. "\$app->enqueueMessage('Please upgrade to at least Joomla! 3.8.0 before continuing!', 'error');";
$script .= PHP_EOL . self::_t(3) . 'return false;';
$script .= PHP_EOL . self::_t(2) . '}' . PHP_EOL;
}
// now add the scripts
foreach ($scripts as $route => $_script)
{
if (self::checkArray($_script))
{
// set the if and script
$script .= PHP_EOL . self::_t(2) . "if ('" . $route
. "' === \$route)";
$script .= PHP_EOL . self::_t(2) . '{';
$script .= PHP_EOL . self::_t(3) . implode(
PHP_EOL, $_script
);
// Ajouté pour la gestion du block custom html
if ($route === 'install') {
$script .= PHP_EOL . '// Custom HTML message install';
} elseif ($route === 'update') {
$script .= PHP_EOL . '// Custom HTML message update';
} elseif ($route === 'uninstall') {
$script .= PHP_EOL . '// Custom HTML message uninstall';
}
// Fin de l'ajout
$script .= PHP_EOL . self::_t(2) . '}' . PHP_EOL;
}
}
// return true
$script .= PHP_EOL . self::_t(2) . 'return true;';
break;
case 'construct':
// the __construct script
$script = PHP_EOL . PHP_EOL . self::_t(1) . '/**';
$script .= PHP_EOL . self::_t(1) . ' * Constructor';
$script .= PHP_EOL . self::_t(1) . ' *';
$script .= PHP_EOL . self::_t(1)
. ' * @param JAdapterInstance $adapter The object responsible for running this script';
$script .= PHP_EOL . self::_t(1) . ' */';
$script .= PHP_EOL . self::_t(1)
. 'public function __construct(JAdapterInstance $adapter)';
$script .= PHP_EOL . self::_t(1) . '{';
$script .= PHP_EOL . $scripts;
break;
default:
// oops error
return '';
}
// close the function
$script .= PHP_EOL . self::_t(1) . '}';
return $script;
}
private static function setLine($nr)
{
if (self::$debugLinenr)
{
return ' [Interpretation ' . $nr . ']';
}
return '';
}
public static function createScriptFile($packageId, $path)
{
$extension = self::getPackageObject(1);
$extension->official_name = $extension->name;
$extension->class_name = 'Pkg_'.$extension->packagename;
$extension->installer_class_name = $extension->class_name . 'InstallerScript';
$extension->php_method_uninstall = base64_decode($extension->php_method_uninstall);
$extension->php_postflight_install = base64_decode($extension->php_postflight_install);
$extension->php_postflight_update = base64_decode($extension->php_postflight_update);
$extension->php_preflight_install = base64_decode($extension->php_preflight_install);
$extension->php_preflight_uninstall = base64_decode($extension->php_preflight_uninstall);
$extension->php_preflight_update = base64_decode($extension->php_preflight_update);
$script = self::getExtensionInstallClass($extension);
$file = $path . '/script.php';
file_put_contents($file, "<?php" . PHP_EOL);
file_put_contents($file, "// No direct access to this file" . PHP_EOL, FILE_APPEND | LOCK_EX);
file_put_contents($file, "defined('_JEXEC') or die('Restricted access');" . PHP_EOL . PHP_EOL, FILE_APPEND | LOCK_EX);
file_put_contents($file, "JHTML::_('behavior.modal');" . PHP_EOL, FILE_APPEND | LOCK_EX);
file_put_contents($file, $script, FILE_APPEND | LOCK_EX);
}
public static function getExtensionObject($extension)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName(
array(
'id',
'alias',
'catid',
'client',
'description',
'element',
'group',
'image',
'keepfilename',
'name',
'newfilename',
'release_date',
'type',
'update',
'version_number',
'published'
)
))
->from($db->quoteName('#__extensiondistributor_extension'))
->where($db->quoteName('id') . ' = ' . (int)$extension)
;
$db->setQuery($query);
return $db->loadObject();
}
public static function getPackageObject($package)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select('*')
->from($db->quoteName('#__extensiondistributor_package'))
->where($db->quoteName('id') . ' = ' . (int)$package)
;
$db->setQuery($query);
return $db->loadObject();
}
public static function isExtension($type,$element,$group,$client)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName('id'))
->from($db->quoteName('#__extensiondistributor_extension'))
->where(
array(
$db->quoteName('type') . ' = ' . $db->quote($type),
$db->quoteName('element') . ' = ' . $db->quote($element),
$db->quoteName('group') . ' = ' . $db->quote($group),
$db->quoteName('client') . ' = ' . $db->quote($client)
)
)
;
$db->setQuery($query);
return $db->loadResult();
}
public static function extensionsLastId()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName('id'))
->from($db->quoteName('#__extensiondistributor_extension'))
->order('id DESC')
;
$db->setQuery($query,0,1);
return $db->loadResult();
}
public static function isRelease($extensionId,$version)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName('id'))
->from($db->quoteName('#__extensiondistributor_release'))
->where(
array(
$db->quoteName('extension') . ' = ' . (int)$extensionId,
$db->quoteName('version_number') . ' = ' . $db->quote($version)
)
)
;
$db->setQuery($query);
return $db->loadResult();
}
public static function getApplicationLists(): array
{
$lists = array();
$lists['stability'] = array(
'0' => array(
'label' => 'Development',
'color' => 'default'
),
'1' => array(
'label' => 'Alpha',
'color' => 'important'
),
'2' => array(
'label' => 'Beta',
'color' => 'warning'
),
'3' => array(
'label' => 'RC',
'color' => 'warning'
),
'4' => array(
'label' => 'Stable',
'color' => 'success'
)
);
$lists['extensionTypes'] = array(
'component' => 'com',
'plugin' => 'plg',
'module' => 'mod',
'library' => 'lib',
'template' => 'tpl',
'language' => 'lang',
'file' => 'file'
);
return $lists;
}
public static function createBadge($id, $name, $type, $group = '', $client = ''): string
{
$tooltip = '';
$tooltip .= '<strong>';
$tooltip .= ucfirst($type);
$tooltip .= ' ' . $group;
$tooltip .= ' ' . $client;
$tooltip .= '</strong>';
$tooltip .= '<br>';
$tooltip .= "<span class='icon-pencil'></span>";
$tooltip .= $name;
$return = base64_encode(urlencode(JUri::getInstance()->toString()));
$bagde = '<a href="index.php?option=com_extensiondistributor&view=extensions&task=extension.edit&id='.(int)$id.'&ref=packages&return='.$return.'">';
$bagde .= '<span class="hasTooltip circle circle-'.$type.'" title="'.$tooltip.'">';
$bagde .= strtoupper(substr($type,0,1));
$bagde .= '<small>';
if (!empty($group)) {
$bagde .= strtolower(substr($group,0,1));
}
if (!empty($client)) {
$bagde .= strtolower(substr($client,0,1));
}
$bagde .= '</small>';
$bagde .= '</span>';
$bagde .= '</a>';
return $bagde;
}
public static function getReleaseToFile()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName(array('id','file')))
->from($db->quoteName('#__extensiondistributor_release'))
;
$db->setQuery($query);
return $db->loadAssocList('id','file');
}
public static function createExtensionFileName($extension, $version, $stability, $file)
{
if ($extension->keepfilename) { // if we keep the filename no need to waste more time
return $file;
}
$lists = self::getApplicationLists();
$extensionTypes = $lists['extensionTypes'];
$stabilityList = $lists['stability'];
$pattern = $extension->newfilename;
$version = explode('.',$version);
$replacements = array(
'type' => $extensionTypes[$extension->type],
'element' => str_replace(array('com_','mod_'),'',$extension->element),
'client' => $extension->client,
'_client' => $extension->client ? '_'.$extension->client : '', // Find a cleaner solution after
'group' => $extension->group,
'_group' => $extension->group ? '_'.$extension->group : '', // Find a cleaner solution after
'stability' => $stabilityList[$stability]['label'],
'major' => $version[0],
'minor' => $version[1],
'release' => $version[2]
);
foreach ($replacements as $k => $v) {
$pattern = str_replace('{'.$k.'}',$v,$pattern);
}
return strtolower($pattern);
}
public static function createPackageFileName($package, $version, $stability)
{
$lists = self::getApplicationLists();
$stabilityList = $lists['stability'];
$pattern = $package->newfilename;
$version = explode('.',$version);
$replacements = array(
'type' => 'pkg',
'packagename' => $package->packagename,
'stability' => $stabilityList[$stability]['label'],
'major' => $version[0],
'minor' => $version[1],
'release' => $version[2]
);
foreach ($replacements as $k => $v) {
$pattern = str_replace('{'.$k.'}',$v,$pattern);
}
return strtolower($pattern);
}
public static function getXmlVersions($xml_file)
{
$updates = simplexml_load_file($xml_file);
$versions = array();
foreach ($updates->children() as $update) {
$versions[] = $update->version;
}
return $versions;
}
public static function getReleaseDetails($releaseId)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName(
array('r.id','r.version_number','r.release_date','r.reltype','r.stability','r.file','r.extension','r.package'),
array('r_id','r_version_number','r_release_date','r_reltype','r_stability','r_file','r_extension','r_package')
))
->select('p.*')
->join('LEFT','#__extensiondistributor_package AS p ON p.id = r.package')
->from($db->quoteName('#__extensiondistributor_release','r'))
->where($db->quoteName('r.id') . ' = ' . (int)$releaseId)
;
$db->setQuery($query);
return $db->loadObject();
}
public static function getReleaseFile($releaseId, $key = null): array
{
$file = true;
$msg = '';
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$cparams = JComponentHelper::getParams('com_extensiondistributor');
$folder = $cparams->get('releases_directory');
$folder = JPath::clean(JPATH_SITE . '/' . $folder . '/');
$query
->clear()
->select($db->quoteName(
array('id','file','extension','package','published')
))
->from($db->quoteName('#__extensiondistributor_release'))
->where($db->quoteName('id') . ' = ' . (int)$releaseId)
;
$db->setQuery($query);
$release = $db->loadObject();
if (is_null($release) || !$release) {
$file = false;
$msg = 'The requested file does not exist';
return array('file' => $file, 'msg' => $msg);
}
if ($release->published != 1) {
$file = false;
$msg = 'The requested file is not published';
return array('file' => $file, 'msg' => $msg);
}
if ($release->extension > 0) {
// For extensions we do not check the key
$file = false;
$msg = 'The individual extension download is not authorized';
return array('file' => $file, 'msg' => $msg);
}
if ($release->package > 0) {
$latest = self::getPackageObject($release->package);
if (is_null($latest) || !$latest) {
$file = false;
$msg = 'The requested package is not available anymore';
return array('file' => $file, 'msg' => $msg);
}
if (!$latest->free) {
if (is_null($key)) {
$file = false;
$msg = 'This is a commercial extension you need to provide a download key';
return array('file' => $file, 'msg' => $msg);
}
$userId = self::getVar('key',$key,'key','user');
if (!$userId) {
$file = false;
$msg = 'The download key you provided does not exists';
return array('file' => $file, 'msg' => $msg);
}
$isLegitimate = self::isLegitimate($userId,$release->package);
if (!$isLegitimate) {
$file = false;
$msg = 'Your subscription is not active anymore';
return array('file' => $file, 'msg' => $msg);
}
}
if (!JFile::exists($folder . $release->file)) {
$file = false;
$msg = sprintf('The file %s is not available', $release->file);
return array('file' => $file, 'msg' => $msg);
}
$file = true;
$msg = $release->file;
return array('file' => $file, 'msg' => $msg);
}
return array('file' => $file, 'msg' => $msg);
}
public static function isLegitimate($userId,$packageId): bool
{
$now = JFactory::getDate()->toSql();
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->clear()
->select($db->quoteName('id'))
->from($db->quoteName('#__extensiondistributor_subscription'))
->where(
array(
$db->quoteName('user') . ' = ' . (int)$userId,
$db->quoteName('active') . ' = 1',
$db->quoteName('date_start') . ' <= ' . $db->quote($now),
$db->quoteName('date_expire') . ' > ' . $db->quote($now)
)
)
->extendWhere('AND', array(
$db->quoteName('package') . ' = ' . (int)$packageId,
$db->quoteName('package') . ' = ' . $db->quote('All')
),'OR')
;
$db->setQuery($query);
$result = $db->loadResult();
return $db->loadResult() ? true : false;
}
public static function getRealIpAddr()
{
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
// Check IP from internet.
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
// Check IP is passed from proxy.
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
// Get IP address from remote address.
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
public static function getFileUsage($filename)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select($db->quoteName(
array('r.id','r.version_number','r.release_date','r.reltype','r.stability','r.file','r.extension','r.package')
))
->from($db->quoteName('#__extensiondistributor_release','r'))
->select($db->quoteName(
array('e.id','e.name','e.element','e.type','e.group','e.client'),
array('e_id','e_name','e_element','e_type','e_group','e_client')
))
->join('LEFT','#__extensiondistributor_extension AS e ON r.extension = e.id')
->select($db->quoteName(
array('p.id','p.packagename','p.name'),
array('p_id','p_packagename','p_name')
))
->join('LEFT','#__extensiondistributor_package AS p ON r.package = p.id')
->where($db->quoteName('r.file') . ' = ' . $db->quote($filename))
;
$db->setQuery($query);
return $db->loadObjectList('id');
}
public static function secureFolder($path, $action = 'secure')
{
$destPath = JPath::clean($path);
$srcPath = JPATH_ADMINISTRATOR.'/components/com_extensiondistributor/assets/security/';
$files = array(
'htaccess.txt' => '.htaccess',
'index.htm' => 'index.htm',
'index.html' => 'index.html',
'index.php' => 'index.php',
'web.config' => 'web.config'
);
foreach ($files as $src => $dest) {
if ($action === 'secure') {
if (JFile::exists($srcPath.$src)) {
JFile::copy($srcPath.$src, $destPath.$dest);
}
} else {
if (JFile::exists($path.$dest)) {
JFile::delete($path.$dest);
}
}
}
}
/**
* Load the Composer Vendors
*/
public static function composerAutoload($target)
{
// insure we load the composer vendor only once
if (!isset(self::$composer[$target]))
{
// get the function name
$functionName = self::safeString('compose' . $target);
// check if method exist
if (method_exists(__CLASS__, $functionName))
{
return self::{$functionName}();
}
return false;
}
return self::$composer[$target];
}
/**
* Load the Component xml manifest.
*/
public static function manifest()
{
$manifestUrl = JPATH_ADMINISTRATOR."/components/com_extensiondistributor/extensiondistributor.xml";
return simplexml_load_file($manifestUrl);
}
/**
* Joomla version object
*/
protected static $JVersion;
/**
* set/get Joomla version
*/
public static function jVersion()
{
// check if set
if (!self::checkObject(self::$JVersion))
{
self::$JVersion = new JVersion();
}
return self::$JVersion;
}
/**
* Load the Contributors details.
*/
public static function getContributors()
{
// get params
$params = JComponentHelper::getParams('com_extensiondistributor');
// start contributors array
$contributors = array();
// get all Contributors (max 20)
$searchArray = range('0','20');
foreach($searchArray as $nr)
{
if ((NULL !== $params->get("showContributor".$nr)) && ($params->get("showContributor".$nr) == 1 || $params->get("showContributor".$nr) == 3))
{
// set link based of selected option
if($params->get("useContributor".$nr) == 1)
{
$link_front = '<a href="mailto:'.$params->get("emailContributor".$nr).'" target="_blank">';
$link_back = '</a>';
}
elseif($params->get("useContributor".$nr) == 2)
{
$link_front = '<a href="'.$params->get("linkContributor".$nr).'" target="_blank">';
$link_back = '</a>';
}
else
{
$link_front = '';
$link_back = '';
}
$contributors[$nr]['title'] = self::htmlEscape($params->get("titleContributor".$nr));
$contributors[$nr]['name'] = $link_front.self::htmlEscape($params->get("nameContributor".$nr)).$link_back;
}
}
return $contributors;
}
/**
* Can be used to build help urls.
**/
public static function getHelpUrl($view)
{
return false;
}
/**
* Configure the Linkbar.
*/
public static function addSubmenu($submenu)
{
// load user for access menus
$user = JFactory::getUser();
// load the submenus to sidebar
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_DASHBOARD'), 'index.php?option=com_extensiondistributor&view=extensiondistributor', $submenu === 'extensiondistributor');
if ($user->authorise('package.access', 'com_extensiondistributor') && $user->authorise('package.submenu', 'com_extensiondistributor'))
{
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_PACKAGES'), 'index.php?option=com_extensiondistributor&view=packages', $submenu === 'packages');
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_PACKAGE_CATEGORIES'), 'index.php?option=com_categories&view=categories&extension=com_extensiondistributor', $submenu === 'categories');
}
if (JComponentHelper::isEnabled('com_fields'))
{
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_PACKAGES_FIELDS'), 'index.php?option=com_fields&context=com_extensiondistributor.package', $submenu === 'fields.fields');
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_PACKAGES_FIELDS_GROUPS'), 'index.php?option=com_fields&view=groups&context=com_extensiondistributor.package', $submenu === 'fields.groups');
}
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_EXTENSIONS'), 'index.php?option=com_extensiondistributor&view=extensions', $submenu === 'extensions');
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_SUBSCRIPTIONS'), 'index.php?option=com_extensiondistributor&view=subscriptions', $submenu === 'subscriptions');
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_KEYS'), 'index.php?option=com_extensiondistributor&view=keys', $submenu === 'keys');
// Access control (import.submenu).
if ($user->authorise('import.submenu', 'com_extensiondistributor'))
{
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_IMPORT'), 'index.php?option=com_extensiondistributor&view=import', $submenu === 'import');
}
// Access control (maintenance.submenu).
if ($user->authorise('maintenance.submenu', 'com_extensiondistributor'))
{
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_MAINTENANCE'), 'index.php?option=com_extensiondistributor&view=maintenance', $submenu === 'maintenance');
}
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_DOWNLOADS'), 'index.php?option=com_extensiondistributor&view=downloads', $submenu === 'downloads');
if ($user->authorise('statistics.submenu', 'com_extensiondistributor'))
{
JHtmlSidebar::addEntry(JText::_('COM_EXTENSIONDISTRIBUTOR_SUBMENU_STATISTICS'), 'index.php?option=com_extensiondistributor&view=statistics', $submenu === 'statistics');
}
}
/**
* Get a Variable
*
* @param string $table The table from which to get the variable
* @param string $where The value where
* @param string $whereString The target/field string where/name
* @param string $what The return field
* @param string $operator The operator between $whereString/field and $where/value
* @param string $main The component in which the table is found
*
* @return mix string/int/float
*
*/
public static function getVar($table, $where = null, $whereString = 'user', $what = 'id', $operator = '=', $main = 'extensiondistributor')
{
if(!$where)
{
$where = JFactory::getUser()->id;
}
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
$query->select($db->quoteName(array($what)));
if (empty($table))
{
$query->from($db->quoteName('#__'.$main));
}
else
{
$query->from($db->quoteName('#__'.$main.'_'.$table));
}
if (is_numeric($where))
{
$query->where($db->quoteName($whereString) . ' '.$operator.' '.(int) $where);
}
elseif (is_string($where))
{
$query->where($db->quoteName($whereString) . ' '.$operator.' '. $db->quote((string)$where));
}
else
{
return false;
}
$db->setQuery($query);
$db->execute();
if ($db->getNumRows())
{
return $db->loadResult();
}
return false;
}
/**
* Get array of variables
*
* @param string $table The table from which to get the variables
* @param string $where The value where
* @param string $whereString The target/field string where/name
* @param string $what The return field
* @param string $operator The operator between $whereString/field and $where/value
* @param string $main The component in which the table is found
* @param bool $unique The switch to return a unique array
*
* @return array
*
*/
public static function getVars($table, $where = null, $whereString = 'user', $what = 'id', $operator = 'IN', $main = 'extensiondistributor', $unique = true)
{
if(!$where)
{
$where = JFactory::getUser()->id;
}
if (!self::checkArray($where) && $where > 0)
{
$where = array($where);
}
if (self::checkArray($where))
{
// prep main <-- why? well if $main='' is empty then $table can be categories or users
if (self::checkString($main))
{
$main = '_'.ltrim($main, '_');
}
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
$query->select($db->quoteName(array($what)));
if (empty($table))
{
$query->from($db->quoteName('#__'.$main));
}
else
{
$query->from($db->quoteName('#_'.$main.'_'.$table));
}
// add strings to array search
if ('IN_STRINGS' === $operator || 'NOT IN_STRINGS' === $operator)
{
$query->where($db->quoteName($whereString) . ' ' . str_replace('_STRINGS', '', $operator) . ' ("' . implode('","',$where) . '")');
}
else
{
$query->where($db->quoteName($whereString) . ' ' . $operator . ' (' . implode(',',$where) . ')');
}
$db->setQuery($query);
$db->execute();
if ($db->getNumRows())
{
if ($unique)
{
return array_unique($db->loadColumn());
}
return $db->loadColumn();
}
}
return false;
}
public static function jsonToString($value, $sperator = ", ", $table = null, $id = 'id', $name = 'name')
{
// do some table foot work
$external = false;
if (strpos($table, '#__') !== false)
{
$external = true;
$table = str_replace('#__', '', $table);
}
// check if string is JSON
$result = json_decode($value, true);
if (json_last_error() === JSON_ERROR_NONE)
{
// is JSON
if (self::checkArray($result))
{
if (self::checkString($table))
{
$names = array();
foreach ($result as $val)
{
if ($external)
{
if ($_name = self::getVar(null, $val, $id, $name, '=', $table))
{
$names[] = $_name;
}
}
else
{
if ($_name = self::getVar($table, $val, $id, $name))
{
$names[] = $_name;
}
}
}
if (self::checkArray($names))
{
return (string) implode($sperator,$names);
}
}
return (string) implode($sperator,$result);
}
return (string) json_decode($value);
}
return $value;
}
public static function isPublished($id,$type)
{
if ($type == 'raw')
{
$type = 'item';
}
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select(array('a.published'));
$query->from('#__extensiondistributor_'.$type.' AS a');
$query->where('a.id = '. (int) $id);
$query->where('a.published = 1');
$db->setQuery($query);
$db->execute();
$found = $db->getNumRows();
if($found)
{
return true;
}
return false;
}
public static function getGroupName($id)
{
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select(array('a.title'));
$query->from('#__usergroups AS a');
$query->where('a.id = '. (int) $id);
$db->setQuery($query);
$db->execute();
$found = $db->getNumRows();
if($found)
{
return $db->loadResult();
}
return $id;
}
/**
* Get the action permissions
*
* @param string $view The related view name
* @param int $record The item to act upon
* @param string $views The related list view name
* @param mixed $target Only get this permission (like edit, create, delete)
* @param string $component The target component
* @param object $user The user whose permissions we are loading
*
* @return object The JObject of permission/authorised actions
*
*/
public static function getActions($view, &$record = null, $views = null, $target = null, $component = 'extensiondistributor', $user = 'null')
{
// load the user if not given
if (!self::checkObject($user))
{
// get the user object
$user = JFactory::getUser();
}
// load the JObject
$result = new JObject;
// make view name safe (just incase)
$view = self::safeString($view);
if (self::checkString($views))
{
$views = self::safeString($views);
}
// get all actions from component
$actions = JAccess::getActionsFromFile(
JPATH_ADMINISTRATOR . '/components/com_' . $component . '/access.xml',
"/access/section[@name='component']/"
);
// if non found then return empty JObject
if (empty($actions))
{
return $result;
}
// get created by if not found
if (self::checkObject($record) && !isset($record->created_by) && isset($record->id))
{
$record->created_by = self::getVar($view, $record->id, 'id', 'created_by', '=', $component);
}
// set actions only set in component settings
$componentActions = array('core.admin', 'core.manage', 'core.options', 'core.export');
// check if we have a target
$checkTarget = false;
if ($target)
{
// convert to an array
if (self::checkString($target))
{
$target = array($target);
}
// check if we are good to go
if (self::checkArray($target))
{
$checkTarget = true;
}
}
// loop the actions and set the permissions
foreach ($actions as $action)
{
// check target action filter
if ($checkTarget && self::filterActions($view, $action->name, $target))
{
continue;
}
// set to use component default
$fallback = true;
// reset permission per/action
$permission = false;
$catpermission = false;
// set area
$area = 'comp';
// check if the record has an ID and the action is item related (not a component action)
if (self::checkObject($record) && isset($record->id) && $record->id > 0 && !in_array($action->name, $componentActions) &&
(strpos($action->name, 'core.') !== false || strpos($action->name, $view . '.') !== false))
{
// we are in item
$area = 'item';
// The record has been set. Check the record permissions.
$permission = $user->authorise($action->name, 'com_' . $component . '.' . $view . '.' . (int) $record->id);
// if no permission found, check edit own
if (!$permission)
{
// With edit, if the created_by matches current user then dig deeper.
if (($action->name === 'core.edit' || $action->name === $view . '.edit') && $record->created_by > 0 && ($record->created_by == $user->id))
{
// the correct target
$coreCheck = (array) explode('.', $action->name);
// check that we have both local and global access
if ($user->authorise($coreCheck[0] . '.edit.own', 'com_' . $component . '.' . $view . '.' . (int) $record->id) &&
$user->authorise($coreCheck[0] . '.edit.own', 'com_' . $component))
{
// allow edit
$result->set($action->name, true);
// set not to use global default
// because we already validated it
$fallback = false;
}
else
{
// do not allow edit
$result->set($action->name, false);
$fallback = false;
}
}
}
elseif (self::checkString($views) && isset($record->catid) && $record->catid > 0)
{
// we are in item
$area = 'category';
// set the core check
$coreCheck = explode('.', $action->name);
$core = $coreCheck[0];
// make sure we use the core. action check for the categories
if (strpos($action->name, $view) !== false && strpos($action->name, 'core.') === false )
{
$coreCheck[0] = 'core';
$categoryCheck = implode('.', $coreCheck);
}
else
{
$categoryCheck = $action->name;
}
// The record has a category. Check the category permissions.
$catpermission = $user->authorise($categoryCheck, 'com_' . $component . '.' . $views . '.category.' . (int) $record->catid);
if (!$catpermission && !is_null($catpermission))
{
// With edit, if the created_by matches current user then dig deeper.
if (($action->name === 'core.edit' || $action->name === $view . '.edit') && $record->created_by > 0 && ($record->created_by == $user->id))
{
// check that we have both local and global access
if ($user->authorise('core.edit.own', 'com_' . $component . '.' . $views . '.category.' . (int) $record->catid) &&
$user->authorise($core . '.edit.own', 'com_' . $component))
{
// allow edit
$result->set($action->name, true);
// set not to use global default
// because we already validated it
$fallback = false;
}
else
{
// do not allow edit
$result->set($action->name, false);
$fallback = false;
}
}
}
}
}
// if allowed then fallback on component global settings
if ($fallback)
{
// if item/category blocks access then don't fall back on global
if ((($area === 'item') && !$permission) || (($area === 'category') && !$catpermission))
{
// do not allow
$result->set($action->name, false);
}
// Finally remember the global settings have the final say. (even if item allow)
// The local item permissions can block, but it can't open and override of global permissions.
// Since items are created by users and global permissions is set by system admin.
else
{
$result->set($action->name, $user->authorise($action->name, 'com_' . $component));
}
}
}
return $result;
}
/**
* Filter the action permissions
*
* @param string $action The action to check
* @param array $targets The array of target actions
*
* @return boolean true if action should be filtered out
*
*/
protected static function filterActions(&$view, &$action, &$targets)
{
foreach ($targets as $target)
{
if (strpos($action, $view . '.' . $target) !== false ||
strpos($action, 'core.' . $target) !== false)
{
return false;
break;
}
}
return true;
}
/**
* Get any component's model
*/
public static function getModel($name, $path = JPATH_COMPONENT_ADMINISTRATOR, $Component = 'Extensiondistributor', $config = array())
{
// fix the name
$name = self::safeString($name);
// full path to models
$fullPathModels = $path . '/models';
// load the model file
JModelLegacy::addIncludePath($fullPathModels, $Component . 'Model');
// make sure the table path is loaded
if (!isset($config['table_path']) || !self::checkString($config['table_path']))
{
// This is the JCB default path to tables in Joomla 3.x
$config['table_path'] = JPATH_ADMINISTRATOR . '/components/com_' . strtolower($Component) . '/tables';
}
// get instance
$model = JModelLegacy::getInstance($name, $Component . 'Model', $config);
// if model not found (strange)
if ($model == false)
{
jimport('joomla.filesystem.file');
// get file path
$filePath = $path . '/' . $name . '.php';
$fullPathModel = $fullPathModels . '/' . $name . '.php';
// check if it exists
if (File::exists($filePath))
{
// get the file
require_once $filePath;
}
elseif (File::exists($fullPathModel))
{
// get the file
require_once $fullPathModel;
}
// build class names
$modelClass = $Component . 'Model' . $name;
if (class_exists($modelClass))
{
// initialize the model
return new $modelClass($config);
}
}
return $model;
}
/**
* Add to asset Table
*/
public static function setAsset($id, $table, $inherit = true)
{
$parent = JTable::getInstance('Asset');
$parent->loadByName('com_extensiondistributor');
$parentId = $parent->id;
$name = 'com_extensiondistributor.'.$table.'.'.$id;
$title = '';
$asset = JTable::getInstance('Asset');
$asset->loadByName($name);
// Check for an error.
$error = $asset->getError();
if ($error)
{
return false;
}
else
{
// Specify how a new or moved node asset is inserted into the tree.
if ($asset->parent_id != $parentId)
{
$asset->setLocation($parentId, 'last-child');
}
// Prepare the asset to be stored.
$asset->parent_id = $parentId;
$asset->name = $name;
$asset->title = $title;
// get the default asset rules
$rules = self::getDefaultAssetRules('com_extensiondistributor', $table, $inherit);
if ($rules instanceof JAccessRules)
{
$asset->rules = (string) $rules;
}
if (!$asset->check() || !$asset->store())
{
JFactory::getApplication()->enqueueMessage($asset->getError(), 'warning');
return false;
}
else
{
// Create an asset_id or heal one that is corrupted.
$object = new stdClass();
// Must be a valid primary key value.
$object->id = $id;
$object->asset_id = (int) $asset->id;
// Update their asset_id to link to the asset table.
return JFactory::getDbo()->updateObject('#__extensiondistributor_'.$table, $object, 'id');
}
}
return false;
}
/**
* Gets the default asset Rules for a component/view.
*/
protected static function getDefaultAssetRules($component, $view, $inherit = true)
{
// if new or inherited
$assetId = 0;
// Only get the actual item rules if not inheriting
if (!$inherit)
{
// Need to find the asset id by the name of the component.
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__assets'))
->where($db->quoteName('name') . ' = ' . $db->quote($component));
$db->setQuery($query);
$db->execute();
// check that there is a value
if ($db->getNumRows())
{
// asset already set so use saved rules
$assetId = (int) $db->loadResult();
}
}
// get asset rules
$result = JAccess::getAssetRules($assetId);
if ($result instanceof JAccessRules)
{
$_result = (string) $result;
$_result = json_decode($_result);
foreach ($_result as $name => &$rule)
{
$v = explode('.', $name);
if ($view !== $v[0])
{
// remove since it is not part of this view
unset($_result->$name);
}
elseif ($inherit)
{
// clear the value since we inherit
$rule = array();
}
}
// check if there are any view values remaining
if (count((array) $_result))
{
$_result = json_encode($_result);
$_result = array($_result);
// Instantiate and return the JAccessRules object for the asset rules.
$rules = new JAccessRules($_result);
// return filtered rules
return $rules;
}
}
return $result;
}
/**
* xmlAppend
*
* @param SimpleXMLElement $xml The XML element reference in which to inject a comment
* @param mixed $node A SimpleXMLElement node to append to the XML element reference, or a stdClass object containing a comment attribute to be injected before the XML node and a fieldXML attribute containing a SimpleXMLElement
*
* @return null
*
*/
public static function xmlAppend(&$xml, $node)
{
if (!$node)
{
// element was not returned
return;
}
switch (get_class($node))
{
case 'stdClass':
if (property_exists($node, 'comment'))
{
self::xmlComment($xml, $node->comment);
}
if (property_exists($node, 'fieldXML'))
{
self::xmlAppend($xml, $node->fieldXML);
}
break;
case 'SimpleXMLElement':
$domXML = dom_import_simplexml($xml);
$domNode = dom_import_simplexml($node);
$domXML->appendChild($domXML->ownerDocument->importNode($domNode, true));
$xml = simplexml_import_dom($domXML);
break;
}
}
/**
* xmlComment
*
* @param SimpleXMLElement $xml The XML element reference in which to inject a comment
* @param string $comment The comment to inject
*
* @return null
*
*/
public static function xmlComment(&$xml, $comment)
{
$domXML = dom_import_simplexml($xml);
$domComment = new DOMComment($comment);
$nodeTarget = $domXML->ownerDocument->importNode($domComment, true);
$domXML->appendChild($nodeTarget);
$xml = simplexml_import_dom($domXML);
}
/**
* xmlAddAttributes
*
* @param SimpleXMLElement $xml The XML element reference in which to inject a comment
* @param array $attributes The attributes to apply to the XML element
*
* @return null
*
*/
public static function xmlAddAttributes(&$xml, $attributes = array())
{
foreach ($attributes as $key => $value)
{
$xml->addAttribute($key, $value);
}
}
/**
* xmlAddOptions
*
* @param SimpleXMLElement $xml The XML element reference in which to inject a comment
* @param array $options The options to apply to the XML element
*
* @return void
*
*/
public static function xmlAddOptions(&$xml, $options = array())
{
foreach ($options as $key => $value)
{
$addOption = $xml->addChild('option');
$addOption->addAttribute('value', $key);
$addOption[] = $value;
}
}
/**
* get the field object
*
* @param array $attributes The array of attributes
* @param string $default The default of the field
* @param array $options The options to apply to the XML element
*
* @return object
*
*/
public static function getFieldObject(&$attributes, $default = '', $options = null)
{
// make sure we have attributes and a type value
if (self::checkArray($attributes) && isset($attributes['type']))
{
// make sure the form helper class is loaded
if (!method_exists('JFormHelper', 'loadFieldType'))
{
jimport('joomla.form.form');
}
// get field type
$field = JFormHelper::loadFieldType($attributes['type'], true);
// get field xml
$XML = self::getFieldXML($attributes, $options);
// setup the field
$field->setup($XML, $default);
// return the field object
return $field;
}
return false;
}
/**
* get the field xml
*
* @param array $attributes The array of attributes
* @param array $options The options to apply to the XML element
*
* @return object
*
*/
public static function getFieldXML(&$attributes, $options = null)
{
// make sure we have attributes and a type value
if (self::checkArray($attributes))
{
// start field xml
$XML = new SimpleXMLElement('<field/>');
// load the attributes
self::xmlAddAttributes($XML, $attributes);
// check if we have options
if (self::checkArray($options))
{
// load the options
self::xmlAddOptions($XML, $options);
}
// return the field xml
return $XML;
}
return false;
}
/**
* Render Bool Button
*
* @param array $args All the args for the button
* 0) name
* 1) additional (options class) // not used at this time
* 2) default
* 3) yes (name)
* 4) no (name)
*
* @return string The input html of the button
*
*/
public static function renderBoolButton()
{
$args = func_get_args();
// check if there is additional button class
$additional = isset($args[1]) ? (string) $args[1] : ''; // not used at this time
// button attributes
$buttonAttributes = array(
'type' => 'radio',
'name' => isset($args[0]) ? self::htmlEscape($args[0]) : 'bool_button',
'label' => isset($args[0]) ? self::safeString(self::htmlEscape($args[0]), 'Ww') : 'Bool Button', // not seen anyway
'class' => 'btn-group',
'filter' => 'INT',
'default' => isset($args[2]) ? (int) $args[2] : 0);
// set the button options
$buttonOptions = array(
'1' => isset($args[3]) ? self::htmlEscape($args[3]) : 'JYES',
'0' => isset($args[4]) ? self::htmlEscape($args[4]) : 'JNO');
// return the input
return self::getFieldObject($buttonAttributes, $buttonAttributes['default'], $buttonOptions)->input;
}
/**
* Check if have an json string
*
* @input string The json string to check
*
* @returns bool true on success
*/
public static function checkJson($string)
{
if (self::checkString($string))
{
json_decode($string);
return (json_last_error() === JSON_ERROR_NONE);
}
return false;
}
/**
* Check if have an object with a length
*
* @input object The object to check
*
* @returns bool true on success
*/
public static function checkObject($object)
{
if (isset($object) && is_object($object))
{
return count((array)$object) > 0;
}
return false;
}
/**
* Check if have an array with a length
*
* @input array The array to check
*
* @returns bool/int number of items in array on success
*/
public static function checkArray($array, $removeEmptyString = false)
{
if (isset($array) && is_array($array) && ($nr = count((array)$array)) > 0)
{
// also make sure the empty strings are removed
if ($removeEmptyString)
{
foreach ($array as $key => $string)
{
if (empty($string))
{
unset($array[$key]);
}
}
return self::checkArray($array, false);
}
return $nr;
}
return false;
}
/**
* Check if have a string with a length
*
* @input string The string to check
*
* @returns bool true on success
*/
public static function checkString($string)
{
if (isset($string) && is_string($string) && strlen($string) > 0)
{
return true;
}
return false;
}
/**
* Check if we are connected
* Thanks https://stackoverflow.com/a/4860432/1429677
*
* @returns bool true on success
*/
public static function isConnected()
{
// If example.com is down, then probably the whole internet is down, since IANA maintains the domain. Right?
$connected = @fsockopen("www.example.com", 80);
// website, port (try 80 or 443)
if ($connected)
{
//action when connected
$is_conn = true;
fclose($connected);
}
else
{
//action in connection failure
$is_conn = false;
}
return $is_conn;
}
/**
* Merge an array of array's
*
* @input array The arrays you would like to merge
*
* @returns array on success
*/
public static function mergeArrays($arrays)
{
if(self::checkArray($arrays))
{
$arrayBuket = array();
foreach ($arrays as $array)
{
if (self::checkArray($array))
{
$arrayBuket = array_merge($arrayBuket, $array);
}
}
return $arrayBuket;
}
return false;
}
// typo sorry!
public static function sorten($string, $length = 40, $addTip = true)
{
return self::shorten($string, $length, $addTip);
}
/**
* Shorten a string
*
* @input string The you would like to shorten
*
* @returns string on success
*/
public static function shorten($string, $length = 40, $addTip = true)
{
if (self::checkString($string))
{
$initial = strlen($string);
$words = preg_split('/([\s\n\r]+)/', $string, null, PREG_SPLIT_DELIM_CAPTURE);
$words_count = count((array)$words);
$word_length = 0;
$last_word = 0;
for (; $last_word < $words_count; ++$last_word)
{
$word_length += strlen($words[$last_word]);
if ($word_length > $length)
{
break;
}
}
$newString = implode(array_slice($words, 0, $last_word));
$final = strlen($newString);
if ($initial != $final && $addTip)
{
$title = self::shorten($string, 400 , false);
return '<span class="hasTip" title="'.$title.'" style="cursor:help">'.trim($newString).'...</span>';
}
elseif ($initial != $final && !$addTip)
{
return trim($newString).'...';
}
}
return $string;
}
/**
* Making strings safe (various ways)
*
* @input string The you would like to make safe
*
* @returns string on success
*/
public static function safeString($string, $type = 'L', $spacer = '_', $replaceNumbers = true, $keepOnlyCharacters = true)
{
if ($replaceNumbers === true)
{
// remove all numbers and replace with english text version (works well only up to millions)
$string = self::replaceNumbers($string);
}
// 0nly continue if we have a string
if (self::checkString($string))
{
// create file name without the extention that is safe
if ($type === 'filename')
{
// make sure VDM is not in the string
$string = str_replace('VDM', 'vDm', $string);
// Remove anything which isn't a word, whitespace, number
// or any of the following caracters -_()
// If you don't need to handle multi-byte characters
// you can use preg_replace rather than mb_ereg_replace
// Thanks @Łukasz Rysiak!
// $string = mb_ereg_replace("([^\w\s\d\-_\(\)])", '', $string);
$string = preg_replace("([^\w\s\d\-_\(\)])", '', $string);
// http://stackoverflow.com/a/2021729/1429677
return preg_replace('/\s+/', ' ', $string);
}
// remove all other characters
$string = trim($string);
$string = preg_replace('/'.$spacer.'+/', ' ', $string);
$string = preg_replace('/\s+/', ' ', $string);
// Transliterate string
$string = self::transliterate($string);
// remove all and keep only characters
if ($keepOnlyCharacters)
{
$string = preg_replace("/[^A-Za-z ]/", '', $string);
}
// keep both numbers and characters
else
{
$string = preg_replace("/[^A-Za-z0-9 ]/", '', $string);
}
// select final adaptations
if ($type === 'L' || $type === 'strtolower')
{
// replace white space with underscore
$string = preg_replace('/\s+/', $spacer, $string);
// default is to return lower
return strtolower($string);
}
elseif ($type === 'W')
{
// return a string with all first letter of each word uppercase(no undersocre)
return ucwords(strtolower($string));
}
elseif ($type === 'w' || $type === 'word')
{
// return a string with all lowercase(no undersocre)
return strtolower($string);
}
elseif ($type === 'Ww' || $type === 'Word')
{
// return a string with first letter of the first word uppercase and all the rest lowercase(no undersocre)
return ucfirst(strtolower($string));
}
elseif ($type === 'WW' || $type === 'WORD')
{
// return a string with all the uppercase(no undersocre)
return strtoupper($string);
}
elseif ($type === 'U' || $type === 'strtoupper')
{
// replace white space with underscore
$string = preg_replace('/\s+/', $spacer, $string);
// return all upper
return strtoupper($string);
}
elseif ($type === 'F' || $type === 'ucfirst')
{
// replace white space with underscore
$string = preg_replace('/\s+/', $spacer, $string);
// return with first caracter to upper
return ucfirst(strtolower($string));
}
elseif ($type === 'cA' || $type === 'cAmel' || $type === 'camelcase')
{
// convert all words to first letter uppercase
$string = ucwords(strtolower($string));
// remove white space
$string = preg_replace('/\s+/', '', $string);
// now return first letter lowercase
return lcfirst($string);
}
// return string
return $string;
}
// not a string
return '';
}
public static function transliterate($string)
{
// set tag only once
if (!self::checkString(self::$langTag))
{
// get global value
self::$langTag = JComponentHelper::getParams('com_extensiondistributor')->get('language', 'en-GB');
}
// Transliterate on the language requested
$lang = Language::getInstance(self::$langTag);
return $lang->transliterate($string);
}
public static function htmlEscape($var, $charset = 'UTF-8', $shorten = false, $length = 40)
{
if (self::checkString($var))
{
$filter = new JFilterInput();
$string = $filter->clean(html_entity_decode(htmlentities($var, ENT_COMPAT, $charset)), 'HTML');
if ($shorten)
{
return self::shorten($string,$length);
}
return $string;
}
else
{
return '';
}
}
public static function replaceNumbers($string)
{
// set numbers array
$numbers = array();
// first get all numbers
preg_match_all('!\d+!', $string, $numbers);
// check if we have any numbers
if (isset($numbers[0]) && self::checkArray($numbers[0]))
{
foreach ($numbers[0] as $number)
{
$searchReplace[$number] = self::numberToString((int)$number);
}
// now replace numbers in string
$string = str_replace(array_keys($searchReplace), array_values($searchReplace),$string);
// check if we missed any, strange if we did.
return self::replaceNumbers($string);
}
// return the string with no numbers remaining.
return $string;
}
/**
* Convert an integer into an English word string
* Thanks to Tom Nicholson <http://php.net/manual/en/function.strval.php#41988>
*
* @input an int
* @returns a string
*/
public static function numberToString($x)
{
$nwords = array( "zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
"nineteen", "twenty", 30 => "thirty", 40 => "forty",
50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty",
90 => "ninety" );
if(!is_numeric($x))
{
$w = $x;
}
elseif(fmod($x, 1) != 0)
{
$w = $x;
}
else
{
if($x < 0)
{
$w = 'minus ';
$x = -$x;
}
else
{
$w = '';
// ... now $x is a non-negative integer.
}
if($x < 21) // 0 to 20
{
$w .= $nwords[$x];
}
elseif($x < 100) // 21 to 99
{
$w .= $nwords[10 * floor($x/10)];
$r = fmod($x, 10);
if($r > 0)
{
$w .= ' '. $nwords[$r];
}
}
elseif($x < 1000) // 100 to 999
{
$w .= $nwords[floor($x/100)] .' hundred';
$r = fmod($x, 100);
if($r > 0)
{
$w .= ' and '. self::numberToString($r);
}
}
elseif($x < 1000000) // 1000 to 999999
{
$w .= self::numberToString(floor($x/1000)) .' thousand';
$r = fmod($x, 1000);
if($r > 0)
{
$w .= ' ';
if($r < 100)
{
$w .= 'and ';
}
$w .= self::numberToString($r);
}
}
else // millions
{
$w .= self::numberToString(floor($x/1000000)) .' million';
$r = fmod($x, 1000000);
if($r > 0)
{
$w .= ' ';
if($r < 100)
{
$w .= 'and ';
}
$w .= self::numberToString($r);
}
}
}
return $w;
}
/**
* Random Key
*
* @returns a string
*/
public static function randomkey($size)
{
$bag = "abcefghijknopqrstuwxyzABCDDEFGHIJKLLMMNOPQRSTUVVWXYZabcddefghijkllmmnopqrstuvvwxyzABCEFGHIJKNOPQRSTUWXYZ";
$key = array();
$bagsize = strlen($bag) - 1;
for ($i = 0; $i < $size; $i++)
{
$get = rand(0, $bagsize);
$key[] = $bag[$get];
}
return implode($key);
}
}