name : ProcessModel.php
<?php
/**
 * @package         Regular Labs Extension Manager
 * @version         9.1.0
 * 
 * @author          Peter van Westen <[email protected]>
 * @link            https://regularlabs.com
 * @copyright       Copyright © 2025 Regular Labs All Rights Reserved
 * @license         GNU General Public License version 2 or later
 */

namespace RegularLabs\Component\RegularLabsExtensionsManager\Administrator\Model;

use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Installer\Installer as JInstaller;
use Joomla\CMS\Installer\InstallerHelper as JInstallerHelper;
use Joomla\CMS\Language\Text as JText;
use Joomla\CMS\MVC\Model\ListModel as JListModel;
use Joomla\CMS\Plugin\PluginHelper as JPluginHelper;
use Joomla\CMS\Updater\Update as JUpdate;
use Joomla\CMS\Uri\Uri as JUri;
use RegularLabs\Component\RegularLabsExtensionsManager\Administrator\Helper\ExtensionsHelper;
use RegularLabs\Library\DB as RL_DB;
use RegularLabs\Library\Input as RL_Input;
use RegularLabs\Library\Language as RL_Language;
use RegularLabs\Library\Parameters as RL_Parameters;

defined('_JEXEC') or die;

class ProcessModel extends JListModel
{
    protected $config;

    /**
     * @var   string    The prefix to use with controller messages.
     */
    protected $text_prefix = 'RL';

    /**
     * @param array    An optional associative array of configuration settings.
     */
    public function __construct($config = [])
    {
        parent::__construct($config);

        $this->config = RL_Parameters::getComponent('regularlabsmanager');
    }

    public function getItems()
    {
        $view       = RL_Input::getCmd('view');
        $extensions = ExtensionsHelper::getFromUrl();

        if ( ! empty($extensions))
        {
            return $extensions;
        }

        return match ($view)
        {
            'reinstall' => ExtensionsHelper::getBroken(),
            'update'    => ExtensionsHelper::getUpdates(),
            default     => [],
        };
    }

    /**
     * @return  boolean
     */
    public function install()
    {
        RL_Language::load('com_installer', JPATH_ADMINISTRATOR);

        $app = JFactory::getApplication();

        // Load installer plugins for assistance if required:
        JPluginHelper::importPlugin('installer');

        $package = $this->getPackageFromUrl();


        // This event allows a custom installation of the package or a customization of the package:
        $results = $app->triggerEvent('onInstallerBeforeInstaller', [$this, &$package]);

        if (in_array(true, $results, true))
        {
            return true;
        }

        if (in_array(false, $results, true))
        {
            $this->cleanupInstall($package);

            return false;
        }

        // Check if package was uploaded successfully.
        if ( ! is_array($package))
        {
            $app->enqueueMessage(JText::_('COM_INSTALLER_UNABLE_TO_FIND_INSTALL_PACKAGE'), 'error');

            return false;
        }

        // Was the package unpacked?
        if (empty($package['type']))
        {
            JInstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);

            $app->enqueueMessage(JText::_('JLIB_INSTALLER_ABORT_DETECTMANIFEST'), 'error');

            return false;
        }

        $installer = JInstaller::getInstance();

        $success = $installer->install($package['dir']) ? true : false;
        $msg     = '';

        $messages = $app->getMessageQueue();

        foreach ($messages as $message)
        {
            if ($message['type'] == 'error')
            {
                $this->cleanupInstall($package);

                return false;
            }
        }

        if ( ! $success)
        {
            $msg = JText::sprintf('COM_INSTALLER_INSTALL_ERROR', JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type'])));
        }

        // This event allows a custom a post-flight:
        $app->triggerEvent('onInstallerAfterInstaller', [$this, &$package, $installer, &$success, &$msg]);

        if ( ! $success)
        {
            $app->enqueueMessage($msg, 'error');
        }

        $this->cleanupInstall($package);

        // Clear the cached extension data and menu cache
        $this->cleanCache('_system');
        $this->cleanCache('com_modules');
        $this->cleanCache('com_plugins');
        $this->cleanCache('mod_menu');

        return $success;
    }

    /**
     * @return  boolean
     */
    public function uninstall()
    {
        RL_Language::load('com_installer', JPATH_ADMINISTRATOR);

        $app = JFactory::getApplication();

        if ( ! $app->getIdentity()->authorise('core.delete', 'com_installer'))
        {
            $app->enqueueMessage(JText::_('JERROR_CORE_DELETE_NOT_PERMITTED'), 'error');

            return false;
        }

        $extension = $this->getExtensionFromUrl();

        if ( ! $extension || ! $extension->type)
        {
            $app->enqueueMessage('Could not find an extension to uninstall.', 'error');

            return false;
        }

        $extension_type = JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($extension->type));


        $installer = JInstaller::getInstance();

        $result = $installer->uninstall($extension->type, $extension->id);

        // Clear the cached extension data and menu cache
        $this->cleanCache('_system');
        $this->cleanCache('com_modules');
        $this->cleanCache('com_plugins');
        $this->cleanCache('mod_menu');

        if ($result === false)
        {
            $app->enqueueMessage(JText::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $extension_type), 'error');

            return false;
        }

        $app->enqueueMessage(JText::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $extension_type), 'success');

        return true;
    }

    /**
     * @return  object|false
     */
    protected function getExtensionFromUrl()
    {
        $extensions = ExtensionsHelper::getFromUrl();

        if (empty($extensions))
        {
            return false;
        }

        $extension = $extensions[0];

        $query = RL_DB::getQuery()
            ->select([
                RL_DB::quoteName('extension_id', 'id'),
                'type',
            ])
            ->from('#__extensions');

        [$type, $folder] = explode('_', $extension->types[0]->type . '_');

        switch ($type)
        {
            case 'pkg':
                $query->where(RL_DB::is('type', 'package'))
                    ->where(RL_DB::is('element', 'pkg_' . $extension->extname));
                break;

            case 'com':
                $query->where(RL_DB::is('type', 'component'))
                    ->where(RL_DB::is('element', 'com_' . $extension->extname));
                break;

            case 'mod':
                $query->where(RL_DB::is('type', 'module'))
                    ->where(RL_DB::is('element', 'mod_' . $extension->extname));
                break;

            case 'plg':
                $query->where(RL_DB::is('type', 'plugin'))
                    ->where(RL_DB::is('folder', $folder))
                    ->where(RL_DB::is('element', $extension->extname));
                break;

            default:
                return false;
        }

        return RL_DB::get()->setQuery($query)->loadObject();
    }

    /**
     * @return  bool|array  Package details or false on failure.
     */
    protected function getPackageFromUrl()
    {
        $url = base64_decode(RL_Input::getBase64('url'));

        // Did you give us a URL?
        if ( ! $url)
        {
            JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_MSG_INSTALL_ENTER_A_URL'), 'error');

            return false;
        }

        // We only allow http & https here
        $uri = new JUri($url);

        if ( ! in_array($uri->getScheme(), ['http', 'https']))
        {
            JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL_SCHEME'), 'error');

            return false;
        }

        // Handle updater XML file case:
        if (preg_match('/\.xml\s*$/', $url))
        {
            $update = new JUpdate;
            $update->loadFromXml($url);
            $package_url = trim($update->get('downloadurl', false)->_data);

            if ($package_url)
            {
                $url = $package_url;
            }

            unset($update);
        }

        // Download the package at the URL given.
        $p_file = JInstallerHelper::downloadPackage($url);

        // Was the package downloaded?
        if ( ! $p_file)
        {
            JFactory::getApplication()->enqueueMessage(JText::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL'), 'error');

            return false;
        }

        $tmp_dest = JFactory::getApplication()->get('tmp_path');

        // Unpack the downloaded package file.
        $package = JInstallerHelper::unpack($tmp_dest . '/' . $p_file, true);

        return $package;
    }

    private function cleanupInstall($package)
    {
        // Cleanup the install files.
        if ( ! is_file($package['packagefile']))
        {
            $package['packagefile'] = JFactory::getApplication()->get('tmp_path') . '/' . $package['packagefile'];
        }

        JInstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
    }
}

© 2025 Cubjrnet7