<?php



/**

 * @package   	JCE

 * @copyright 	Copyright (c) 2009-2016 Ryan Demmer. All rights reserved.

 * @license   	GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

 * JCE is free software. This version may have been modified pursuant

 * to the GNU General Public License, and as distributed it includes or

 * is derivative of works licensed under the GNU General Public License or

 * other free or open source software licenses.

 */

defined('_JEXEC') or die('RESTRICTED');



jimport('joomla.installer.installer');



/**

 * Plugins Component Controller

 *

 * @package		Joomla

 * @subpackage	Plugins

 */

class WFInstaller extends JObject {

    

    protected   $_adapters = null;

    

    public      $installer = null;

    



    public function __construct() {

        $installer = JInstaller::getInstance();

        

        $this->installer = $installer;

    }

    

    /**

     * Returns the global Installer object, only creating it

     * if it doesn't already exist.

     *

     * @return  object  An installer object

     */

    public static function getInstance() {

        static $instance;



        if (!isset($instance)) {

            $instance = new WFInstaller;

        }

        return $instance;

    }



    /**

     * Set an installer adapter by name

     *

     * @access	public

     * @param	string	$name		Adapter name

     * @param	object	$adapter	Installer adapter object

     * @return	boolean True if successful

     */

    public function setAdapter($name, $adapter = null) {

        if (!is_object($adapter)) {

            $adapter = $this->getAdapter($name);

        }

        $this->_adapters[$name] = $adapter;

        return true;

    }



    /**

     * Get a JCE installer adapter

     * @param string $name adapter name eg: plugin.

     * @return $adapter instance

     */

    public function getAdapter($type) {

        // Try to load the adapter object

        require_once(dirname(dirname(__FILE__)) . '/adapters/' . strtolower($type) . '.php');



        $class = 'WFInstaller' . ucfirst($type);



        if (!class_exists($class)) {

            return false;

        }



        $adapter = new $class($this);



        // set parent as JInstaller instance

        $adapter->parent = $this->installer;



        return $adapter;

    }



    public function install($path) {        

        if ($path && JFolder::exists($path)) {

            $this->installer->setPath('source', $path);

        } else {

            $this->installer->abort(JText::_('JLIB_INSTALLER_ABORT_NOINSTALLPATH'));

            return false;

        }



        if (!$this->setupInstall()) {

            $this->installer->abort(JText::_('JLIB_INSTALLER_ABORT_DETECTMANIFEST'));

            return false;

        }



        // Load the adapter(s) for the install manifest

        $type = (string) $this->installer->manifest->attributes()->type;



        if ($type == 'extension') {

            $type = 'plugin';

        }



        if (is_object($this->_adapters[$type])) {

            // Add the languages from the package itself

            if (method_exists($this->_adapters[$type], 'loadLanguage')) {

                $this->_adapters[$type]->loadLanguage($path);

            }



            // Run the install

            $ret = $this->_adapters[$type]->install();

            

            $this->set('name', $this->installer->get('name'));

            $this->set('version', $this->installer->get('version'));

            $this->set('message', $this->installer->get('description'));

            $this->set('extension.message', $this->installer->get('extension.message'));

            

            return $ret;

        }

    }



    /**

     * Package uninstallation method

     *

     * @param   string   $type        Package type

     * @param   mixed    $identifier  Package identifier for adapter

     *

     * @return  boolean  True if successful

     */

    public function uninstall($type, $identifier) {

        if (!isset($this->_adapters[$type]) || !is_object($this->_adapters[$type])) {

            if (!$this->setAdapter($type)) {

                // We failed to get the right adapter

                return false;

            }

        }



        if (is_object($this->_adapters[$type])) {

            // Run the uninstall

            return $this->_adapters[$type]->uninstall($identifier);

        }



        return false;

    }



    /**

     * Prepare for installation: this method sets the installation directory, finds

     * and checks the installation file and verifies the installation type.

     *

     * @return  boolean  True on success

     */

    public function setupInstall() {

        // We need to find the installation manifest file

        if (!$this->findManifest()) {

            return false;

        }



        // Load the adapter(s) for the install manifest

        $type = (string) $this->installer->manifest->attributes()->type;



        if ($type == 'extension') {

            $type = 'plugin';

        }



        // Lazy load the adapter

        if (!isset($this->_adapters[$type]) || !is_object($this->_adapters[$type])) {

            $adapter = $this->getAdapter($type);



            if (!$adapter) {

                return false;

            }



            if (!$this->setAdapter($type, $adapter)) {

                return false;

            }

        }



        return true;

    }



    public function getManifest() {        

        if (!is_object($this->installer->manifest)) {

            $this->findManifest();

        }



        return $this->installer->manifest;

    }



    /**

     * Tries to find the package manifest file

     *

     * @return  boolean  True on success, False on error

     */

    public function findManifest() {

        jimport('joomla.filesystem.folder');



        // Get an array of all the XML files from the installation directory

        $xmlfiles = JFolder::files($this->installer->getPath('source'), '.xml$', 1, true);



        // If at least one XML file exists

        if (!empty($xmlfiles)) {



            foreach ($xmlfiles as $file) {

                // Is it a valid Joomla installation manifest file?

                $manifest = $this->isManifest($file);



                if (!is_null($manifest)) {

                    // If the root method attribute is set to upgrade, allow file overwrite

                    if ((string) $manifest->attributes()->method == 'upgrade') {

                        if (method_exists($this->installer, 'setUpgrade')) {

                            $this->installer->setUpgrade(true);

                        }

  

                        $this->installer->setOverwrite(true);

                    }



                    // If the overwrite option is set, allow file overwriting

                    if ((string) $manifest->attributes()->overwrite == 'true') {

                        $this->installer->setOverwrite(true);

                    }



                    // Set the manifest object and path

                    $this->installer->manifest = $manifest;

                    $this->installer->setPath('manifest', $file);



                    // Set the installation source path to that of the manifest file

                    $this->installer->setPath('source', dirname($file));



                    return true;

                }

            }



            // None of the XML files found were valid install files

            JError::raiseWarning(1, JText::_('WF_INSTALLER_MANIFEST_INVALID'));



            return false;

        } else {

            // No XML files were found in the install folder

            JError::raiseWarning(1, JText::_('WF_INSTALLER_MANIFEST_LOAD_ERROR'));

            return false;

        }

    }



    /**

     * Is the XML file a valid Joomla installation manifest file.

     *

     * @param   string  $file  An xmlfile path to check

     *

     * @return  mixed  A SimpleXMLElement, or null if the file failed to parse

     */

    public function isManifest($file) {

        $xml = @simplexml_load_file($file);



        // If we cannot load the XML file return null

        if (!$xml) {

            return null;

        }



        // Check for a valid XML root tag.

        if ($xml->getName() != 'extension' && $xml->getName() != 'install') {

            return null;

        }



        // Valid manifest file return the object

        return $xml;

    }



}



?>