2264 lines
65 KiB
PHP
2264 lines
65 KiB
PHP
|
<?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;
|
||
|
|
||
|
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];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Convert it into a string
|
||
|
*/
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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) == 2 || $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;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get any component's model
|
||
|
*/
|
||
|
public static function getModel($name, $path = JPATH_COMPONENT_SITE, $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;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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 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;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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);
|
||
|
}
|
||
|
}
|
||
|
|