| Current Path : /home/juvelize/saulnois/administrator/components/com_icagenda/src/Model/ |
| Current File : /home/juvelize/saulnois/administrator/components/com_icagenda/src/Model/ThemesModel.php |
<?php
/**
*----------------------------------------------------------------------------
* iCagenda Events Management Extension for Joomla!
*----------------------------------------------------------------------------
* @version 4.0.0 2025-12-21
*
* @package iCagenda.Admin
* @subpackage src.Model
* @link https://www.joomlic.com
*
* @author Cyril Reze
* @copyright (c) 2012-2026 Cyril Reze / JoomliC. All rights reserved.
* @license GNU General Public License version 3 or later; see LICENSE.txt
*
* @since 2.0
*----------------------------------------------------------------------------
*/
namespace WebiC\Component\iCagenda\Administrator\Model;
\defined('_JEXEC') or die;
use Joomla\Archive\Archive;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Log\Log;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\CMS\Table\Table;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\Filesystem\Path;
/**
* iCagenda Component Themes Model
*/
class ThemesModel extends ListModel
{
protected $_paths = array();
protected $_manifest = null;
protected $option = 'com_icagenda';
protected $text_prefix = 'com_icagenda';
/**
* Constructor.
*
* @param array $config An optional associative array of configuration settings.
*/
public function __construct($config = array())
{
parent::__construct($config);
}
function install($theme)
{
$app = Factory::getApplication();
$package = $this->_getPackageFromUpload();
if ( ! $package)
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_FIND_INSTALL_PACKAGE'), 'warning');
$this->deleteTempFiles();
return false;
}
if ($package['dir'] && is_dir($package['dir']))
{
$this->setPath('source', $package['dir']);
}
else
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_INSTALL_PATH_NOT_EXISTS'), 'warning');
$this->deleteTempFiles();
return false;
}
// We need to find the installation manifest file
if ( ! $this->_findManifest())
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_FIND_INFO_INSTALL_PACKAGE'), 'warning');
$this->deleteTempFiles();
return false;
}
// Files - copy files in manifest
foreach ($this->_manifest->children() as $child)
{
// if (is_a($child, 'JXMLElement') && $child->getName() == 'files')
if ($child->getName() == 'files')
{
if ($this->parseFiles($child) === false)
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_FIND_INFO_INSTALL_PACKAGE'), 'warning');
$this->deleteTempFiles();
return false;
}
}
}
// File - copy the xml file
$copyFile = array();
$path['src'] = $this->getPath( 'manifest' ); // XML file will be copied too
$path['dest'] = JPATH_SITE . '/components/com_icagenda/themes/' . basename($this->getPath('manifest'));
$copyFile[] = $path;
$this->copyFiles($copyFile, array());
$this->deleteTempFiles();
// -------------------
// Themes
// -------------------
// Params - Get new themes params
$paramsThemes = $this->getParamsThemes();
// -------------------
// Component
// -------------------
if (isset($theme['component']) && $theme['component'] == 1 )
{
$component = 'com_icagenda';
$paramsC = ComponentHelper::getParams($component) ;
foreach ($paramsThemes as $keyT => $valueT)
{
$paramsC->set($valueT['name'], $valueT['value']);
}
$data['params'] = $paramsC->toArray();
$table = Table::getInstance('extension');
$idCom = $table->find( array('element' => $component ));
$table->load($idCom);
if ( ! $table->bind($data))
{
$app->enqueueMessage(Text::_('Not a valid component'), 'warning');
return false;
}
// pre-save checks
if ( ! $table->check())
{
$app->enqueueMessage(Text::_('Check Problem'), 'warning');
return false;
}
// save the changes
if ( ! $table->store())
{
$app->enqueueMessage(Text::_('Store Problem'), 'warning');
return false;
}
}
return true;
}
function _getPackageFromUpload()
{
$app = Factory::getApplication();
// Get the uploaded file information
// Do not change the filter type 'raw'. We need this to let files containing PHP code to upload. See JInputFiles::get.
$userfile = $app->input->files->get('Filedata', null, 'raw');
// Make sure that file uploads are enabled in php
if ( ! (bool) ini_get('file_uploads'))
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_INSTALL_FILE_UPLOAD'), 'warning');
return false;
}
// Make sure that zlib is loaded so that the package can be unzipped
if ( ! extension_loaded('zlib'))
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_INSTALL_ZLIB'), 'warning');
return false;
}
// If there is no uploaded file, we have a problem...
if ( ! is_array($userfile))
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_NO_FILE_SELECTED'), 'warning');
return false;
}
// Check if there was a problem uploading the file.
if ($userfile['error'] || $userfile['size'] < 1)
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_UPLOAD_FILE'), 'warning');
return false;
}
// Build the appropriate paths
$config = Factory::getConfig();
$tmp_dest = $config->get('tmp_path') . '/' . $userfile['name'];
$tmp_src = $userfile['tmp_name'];
// Move uploaded file
$uploaded = File::upload($tmp_src, $tmp_dest, false, true);
// Unpack the downloaded package file
$package = self::unpack($tmp_dest);
$this->_manifest =& $manifest;
$this->setPath('packagefile', $package['packagefile']);
$this->setPath('extractdir', $package['extractdir']);
return $package;
}
function getPath($name, $Default = null)
{
return ( ! empty($this->_paths[$name])) ? $this->_paths[$name] : $Default;
}
function setPath($name, $value)
{
$this->_paths[$name] = $value;
}
function _findManifest()
{
$app = Factory::getApplication();
// Get an array of all the xml files from teh installation directory
$xmlfiles = Folder::files($this->getPath('source'), '.xml$', 1, true);
// If at least one xml file exists
if (count($xmlfiles) > 0)
{
foreach ($xmlfiles as $file)
{
// Is it a valid joomla installation manifest file?
$manifest = $this->_isManifest($file);
if ( ! is_null($manifest))
{
$attr = $manifest->attributes();
if ((string) $attr->method != 'icthemes')
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_NO_THEME_FILE'), 'warning');
return false;
}
// Set the manifest object and path
$this->_manifest =& $manifest;
$this->setPath('manifest', $file);
// Set the installation source path to that of the manifest file
$this->setPath('source', dirname($file));
return true;
}
}
// None of the xml files found were valid install files
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_XML_INSTALL_ICAGENDA'), 'warning');
return false;
}
else
{
// No xml files were found in the install folder
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_XML_INSTALL'), 'warning');
return false;
}
}
function _isManifest($file)
{
// $xml = Factory::getXML($file, true);
$xml = simplexml_load_file($file);
if ( ! $xml)
{
unset ($xml);
return null;
}
if ( ! is_object($xml) || ($xml->getName() != 'install' && $xml->getName() != 'installtheme'))
{
unset ($xml);
return null;
}
return $xml;
}
function parseFiles($element, $cid = 0)
{
$copyfiles = array();
$copyfolders = array();
// if ( ! is_a($element, 'JXMLElement') || ! count($element->children()))
if ( ! count($element->children()))
{
return 0; // Either the tag does not exist or has no children therefore we return zero files processed.
}
$files = $element->children();// Get the array of file nodes to process
if (count($files) == 0)
{
return 0; // No files to process
}
$source = $this->getPath('source');
$destination = JPATH_SITE . '/components/com_icagenda/themes';
$destination2 = JPATH_SITE . '/components/com_icagenda/themes/packs';
if ( ! empty($files->folder))
{
foreach ($files->folder as $fk => $fv)
{
$path['src'] = $source . '/' . $fv;
$path['dest'] = $destination2 . '/' . $fv;
$copyfolders[] = $path;
}
}
if ( ! empty($files->filename))
{
foreach ($files->filename as $fik => $fiv)
{
$path['src'] = $source . '/' . $fiv;
$path['dest'] = $destination . '/' . $fiv;
$copyfiles[] = $path;
}
}
return $this->copyFiles($copyfiles, $copyfolders);
}
function copyFiles($files, $folders)
{
$app = Factory::getApplication();
$i = 0;
$fileIncluded = $folderIncluded = 0;
if (is_array($folders) && count($folders) > 0)
{
foreach ($folders as $folder)
{
// Get the source and destination paths
$foldersource = Path::clean($folder['src']);
$folderdest = Path::clean($folder['dest']);
if ( ! is_dir($foldersource))
{
$app->enqueueMessage(Text::sprintf('COM_ICAGENDA_FOLDER_NOT_EXISTS', $foldersource), 'warning');
return false;
}
else
{
if ( ! (Folder::copy($foldersource, $folderdest, '', true)))
{
$app->enqueueMessage(Text::sprintf('COM_ICAGENDA_ERROR_COPY_FOLDER_TO', $foldersource, $folderdest), 'warning');
return false;
}
else
{
$i++;
}
}
}
$folderIncluded = 1;
}
if (is_array($files) && count($files) > 0)
{
foreach ($files as $file)
{
// Get the source and destination paths
$filesource = Path::clean($file['src']);
$filedest = Path::clean($file['dest']);
if ( ! file_exists($filesource))
{
$app->enqueueMessage(Text::sprintf('COM_ICAGENDA_FILE_NOT_EXISTS', $filesource), 'warning');
return false;
}
else
{
if ( ! (File::copy($filesource, $filedest)))
{
$app->enqueueMessage(Text::sprintf('COM_ICAGENDA_ERROR_COPY_FILE_TO', $filesource, $filedest), 'warning');
return false;
}
else
{
$i++;
}
}
}
$fileIncluded = 1;
}
if ($fileIncluded == 0 && $folderIncluded ==0)
{
$app->enqueueMessage(Text::_('COM_ICAGENDA_ERROR_INSTALL_FILE'), 'warning');
return false;
}
return $i; // Possible TO DO, now it returns count folders and files togeter, //return count($files);
}
protected function getParamsThemes()
{
$element = $this->_manifest->children()->params;
if ( ! is_a($element, 'JXMLElement') || ! count($element->children()))
{
return null; // Either the tag does not exist or has no children therefore we return zero files processed.
}
$params = $element->children();
if (count($params) == 0)
{
return null; // No params to process
}
// Process each parameter in the $params array.
$paramsArray = array();
$i = 0;
foreach ($params as $param)
{
if ( ! $name = $param['name'])
{
continue;
}
if ( ! $value = $param['default'])
{
continue;
}
$paramsArray[$i]['name'] = (string)$name;
$paramsArray[$i]['value'] = (string)$value;
$i++;
}
return $paramsArray;
}
function deleteTempFiles()
{
$path = $this->getPath('source');
if (is_dir($path))
{
$val = Folder::delete($path);
}
elseif (is_file($path))
{
$val = File::delete($path);
}
$packageFile = $this->getPath('packagefile');
if (is_file($packageFile))
{
$val = File::delete($packageFile);
}
$extractDir = $this->getPath('extractdir');
if (is_dir($extractDir))
{
$val = Folder::delete($extractDir);
}
}
/*
* Added @since 3.0.
*/
public static function unpack($p_filename)
{
// Path to the archive
$archivename = $p_filename;
// Temporary folder to extract the archive into
$tmpdir = uniqid('install_');
// Clean the paths to use for archive extraction
$extractdir = Path::clean(dirname($p_filename) . '/' . $tmpdir);
$archivename = Path::clean($archivename);
// Do the unpacking of the archive
try
{
$archive = new Archive(array('tmp_path' => Factory::getApplication()->get('tmp_path')));
$extract = $archive->extract($archivename, $extractdir);
}
catch (\Exception $e)
{
return false;
}
/*
* Let's set the extraction directory and package file in the result array so we can
* cleanup everything properly later on.
*/
$retval['extractdir'] = $extractdir;
$retval['packagefile'] = $archivename;
/*
* Try to find the correct install directory. In case the package is inside a
* subdirectory detect this and set the install directory to the correct path.
*
* List all the items in the installation directory. If there is only one, and
* it is a folder, then we will set that folder to be the installation folder.
*/
$dirList = array_merge(Folder::files($extractdir, ''), Folder::folders($extractdir, ''));
if (count($dirList) == 1)
{
if (is_dir($extractdir . '/' . $dirList[0]))
{
$extractdir = Path::clean($extractdir . '/' . $dirList[0]);
}
}
/*
* We have found the install directory so lets set it and then move on
* to detecting the extension type.
*/
$retval['dir'] = $extractdir;
/*
* Get the extension type and return the directory/type array on success or
* false on fail.
*/
$retval['type'] = self::detectType($extractdir);
if ($retval['type'])
{
return $retval;
}
else
{
return false;
}
}
/*
* Added @since 3.0.
*/
public static function detectType($p_dir)
{
// Search the install dir for an XML file
$files = Folder::files($p_dir, '\.xml$', 1, true);
if ( ! count($files))
{
Log::add(Text::_('JLIB_INSTALLER_ERROR_NOTFINDXMLSETUPFILE'), Log::WARNING, 'jerror');
return false;
}
foreach ($files as $file)
{
$xml = \simplexml_load_file($file);
if ( ! $xml)
{
continue;
}
if ($xml->getName() != 'install' && $xml->getName() != 'installtheme')
{
unset($xml);
continue;
}
$type = (string) $xml->attributes()->type;
// Free up memory
unset($xml);
return $type;
}
Log::add(Text::_('JLIB_INSTALLER_ERROR_NOTFINDJOOMLAXMLSETUPFILE'), Log::WARNING, 'jerror');
// Free up memory.
unset($xml);
return false;
}
}