You've already forked joomla_test
first commit
This commit is contained in:
1895
libraries/cms/installer/adapter/component.php
Normal file
1895
libraries/cms/installer/adapter/component.php
Normal file
File diff suppressed because it is too large
Load Diff
814
libraries/cms/installer/adapter/file.php
Normal file
814
libraries/cms/installer/adapter/file.php
Normal file
@ -0,0 +1,814 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.base.adapterinstance');
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
/**
|
||||
* File installer
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
*/
|
||||
class JInstallerAdapterFile extends JAdapterInstance
|
||||
{
|
||||
protected $route = 'install';
|
||||
|
||||
/**
|
||||
* Custom loadLanguage method
|
||||
*
|
||||
* @param string $path The path on which to find language files.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function loadLanguage($path)
|
||||
{
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
$extension = 'files_' . str_replace('files_', '', strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd')));
|
||||
$lang = JFactory::getLanguage();
|
||||
$source = $path;
|
||||
$lang->load($extension . '.sys', $source, null, false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_SITE, null, false, false)
|
||||
|| $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_SITE, $lang->getDefault(), false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom install method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
// Get the extension manifest object
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Manifest Document Setup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Set the extension's name
|
||||
$name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'string');
|
||||
$this->set('name', $name);
|
||||
|
||||
// Set element
|
||||
$manifestPath = JPath::clean($this->parent->getPath('manifest'));
|
||||
$element = preg_replace('/\.xml/', '', basename($manifestPath));
|
||||
$this->set('element', $element);
|
||||
|
||||
// Get the component description
|
||||
$description = (string) $this->manifest->description;
|
||||
|
||||
if ($description)
|
||||
{
|
||||
$this->parent->set('message', JText::_($description));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->set('message', '');
|
||||
}
|
||||
|
||||
// Check if the extension by the same name is already installed
|
||||
if ($this->extensionExistsInSystem($element))
|
||||
{
|
||||
// Package with same name already exists
|
||||
if (!$this->parent->isOverwrite())
|
||||
{
|
||||
// We're not overwriting so abort
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_SAME_NAME'));
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swap to the update route
|
||||
$this->route = 'update';
|
||||
}
|
||||
}
|
||||
// Set the file root path
|
||||
if ($name == 'files_joomla')
|
||||
{
|
||||
// If we are updating the Joomla core, set the root path to the root of Joomla
|
||||
$this->parent->setPath('extension_root', JPATH_ROOT);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->setPath('extension_root', JPATH_MANIFESTS . '/files/' . $this->get('element'));
|
||||
}
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Installer Trigger Loading
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet)
|
||||
$this->scriptElement = $this->manifest->scriptfile;
|
||||
$manifestScript = (string) $this->manifest->scriptfile;
|
||||
|
||||
if ($manifestScript)
|
||||
{
|
||||
$manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript;
|
||||
|
||||
if (is_file($manifestScriptFile))
|
||||
{
|
||||
// Load the file
|
||||
include_once $manifestScriptFile;
|
||||
}
|
||||
|
||||
// Set the class name
|
||||
$classname = $element . 'InstallerScript';
|
||||
|
||||
if (class_exists($classname))
|
||||
{
|
||||
// Create a new instance
|
||||
$this->parent->manifestClass = new $classname($this);
|
||||
|
||||
// And set this so we can copy it later
|
||||
$this->set('manifest_script', $manifestScript);
|
||||
}
|
||||
}
|
||||
|
||||
// Run preflight if possible (since we know we're not an update)
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight'))
|
||||
{
|
||||
if ($this->parent->manifestClass->preflight($this->route, $this) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create msg object; first use here
|
||||
$msg = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// Populate File and Folder List to copy
|
||||
$this->populateFilesAndFolderList();
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Filesystem Processing Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Now that we have folder list, lets start creating them
|
||||
foreach ($this->folderList as $folder)
|
||||
{
|
||||
if (!JFolder::exists($folder))
|
||||
{
|
||||
|
||||
if (!$created = JFolder::create($folder))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $folder), JLog::WARNING, 'jerror');
|
||||
|
||||
// If installation fails, rollback
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we created a directory and will want to remove it if we have to roll back.
|
||||
// The installation due to some errors, let's add it to the installation step stack.
|
||||
|
||||
if ($created)
|
||||
{
|
||||
$this->parent->pushStep(array('type' => 'folder', 'path' => $folder));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Now that we have file list, let's start copying them
|
||||
$this->parent->copyFiles($this->fileList);
|
||||
|
||||
// Parse optional tags
|
||||
$this->parent->parseLanguages($this->manifest->languages);
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Finalization and Cleanup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Get a database connector object
|
||||
$db = $this->parent->getDbo();
|
||||
|
||||
/*
|
||||
* Check to see if a file extension by the same name is already installed
|
||||
* If it is, then update the table because if the files aren't there
|
||||
* we can assume that it was (badly) uninstalled
|
||||
* If it isn't, add an entry to extensions
|
||||
*/
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('file'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote($element));
|
||||
$db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$db->execute();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
$id = $db->loadResult();
|
||||
$row = JTable::getInstance('extension');
|
||||
|
||||
if ($id)
|
||||
{
|
||||
// Load the entry and update the manifest_cache
|
||||
$row->load($id);
|
||||
|
||||
// Update name
|
||||
$row->set('name', $this->get('name'));
|
||||
|
||||
// Update manifest
|
||||
$row->manifest_cache = $this->parent->generateManifestCache();
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add an entry to the extension table with a whole heap of defaults
|
||||
$row->set('name', $this->get('name'));
|
||||
$row->set('type', 'file');
|
||||
$row->set('element', $this->get('element'));
|
||||
|
||||
// There is no folder for files so leave it blank
|
||||
$row->set('folder', '');
|
||||
$row->set('enabled', 1);
|
||||
$row->set('protected', 0);
|
||||
$row->set('access', 0);
|
||||
$row->set('client_id', 0);
|
||||
$row->set('params', '');
|
||||
$row->set('system_data', '');
|
||||
$row->set('manifest_cache', $this->parent->generateManifestCache());
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_ROLLBACK', $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we have created a module item, we add it to the installation step stack
|
||||
// so that if we have to rollback the changes we can undo it.
|
||||
$this->parent->pushStep(array('type' => 'extension', 'extension_id' => $row->extension_id));
|
||||
}
|
||||
|
||||
// Let's run the queries for the file
|
||||
if (strtolower($this->route) == 'install')
|
||||
{
|
||||
$result = $this->parent->parseSQLFiles($this->manifest->install->sql);
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the schema version to be the latest update version
|
||||
if ($this->manifest->update)
|
||||
{
|
||||
$this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id);
|
||||
}
|
||||
}
|
||||
elseif (strtolower($this->route) == 'update')
|
||||
{
|
||||
if ($this->manifest->update)
|
||||
{
|
||||
$result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id);
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_UPDATE_SQL_ERROR', $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to run the script file's custom method based on the route
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route))
|
||||
{
|
||||
if ($this->parent->manifestClass->{$this->route}($this) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Append messages
|
||||
$msg .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// Lastly, we will copy the manifest file to its appropriate place.
|
||||
$manifest = array();
|
||||
$manifest['src'] = $this->parent->getPath('manifest');
|
||||
$manifest['dest'] = JPATH_MANIFESTS . '/files/' . basename($this->parent->getPath('manifest'));
|
||||
|
||||
if (!$this->parent->copyFiles(array($manifest), true))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_COPY_SETUP'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is a manifest script, let's copy it.
|
||||
if ($this->get('manifest_script'))
|
||||
{
|
||||
// First, we have to create a folder for the script if one isn't present
|
||||
if (!file_exists($this->parent->getPath('extension_root')))
|
||||
{
|
||||
JFolder::create($this->parent->getPath('extension_root'));
|
||||
}
|
||||
|
||||
$path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script');
|
||||
$path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script');
|
||||
|
||||
if (!file_exists($path['dest']) || $this->parent->isOverwrite())
|
||||
{
|
||||
if (!$this->parent->copyFiles(array($path)))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clobber any possible pending updates
|
||||
$update = JTable::getInstance('update');
|
||||
$uid = $update->find(
|
||||
array('element' => $this->get('element'), 'type' => 'file', 'client_id' => '', 'folder' => '')
|
||||
);
|
||||
|
||||
if ($uid)
|
||||
{
|
||||
$update->delete($uid);
|
||||
}
|
||||
|
||||
// And now we run the postflight
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight'))
|
||||
{
|
||||
$this->parent->manifestClass->postflight($this->route, $this);
|
||||
}
|
||||
|
||||
// Append messages
|
||||
$msg .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if ($msg != '')
|
||||
{
|
||||
$this->parent->set('extension_message', $msg);
|
||||
}
|
||||
|
||||
return $row->get('extension_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom update method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
// Set the overwrite setting
|
||||
$this->parent->setOverwrite(true);
|
||||
$this->parent->setUpgrade(true);
|
||||
$this->route = 'update';
|
||||
|
||||
// ...and adds new files
|
||||
return $this->install();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom uninstall method
|
||||
*
|
||||
* @param string $id The id of the file to uninstall
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function uninstall($id)
|
||||
{
|
||||
$row = JTable::getInstance('extension');
|
||||
|
||||
if (!$row->load($id))
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_ENTRY'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($row->protected)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_WARNCOREFILE'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$retval = true;
|
||||
$manifestFile = JPATH_MANIFESTS . '/files/' . $row->element . '.xml';
|
||||
|
||||
// Because files may not have their own folders we cannot use the standard method of finding an installation manifest
|
||||
if (file_exists($manifestFile))
|
||||
{
|
||||
// Set the files root path
|
||||
$this->parent->setPath('extension_root', JPATH_MANIFESTS . '/files/' . $row->element);
|
||||
|
||||
$xml = simplexml_load_file($manifestFile);
|
||||
|
||||
// If we cannot load the XML file return null
|
||||
if (!$xml)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_LOAD_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a valid XML root tag.
|
||||
if ($xml->getName() != 'extension')
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->manifest = $xml;
|
||||
|
||||
// If there is an manifest class file, let's load it
|
||||
$this->scriptElement = $this->manifest->scriptfile;
|
||||
$manifestScript = (string) $this->manifest->scriptfile;
|
||||
|
||||
if ($manifestScript)
|
||||
{
|
||||
$manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript;
|
||||
|
||||
if (is_file($manifestScriptFile))
|
||||
{
|
||||
// Load the file
|
||||
include_once $manifestScriptFile;
|
||||
}
|
||||
|
||||
// Set the class name
|
||||
$classname = $row->element . 'InstallerScript';
|
||||
|
||||
if (class_exists($classname))
|
||||
{
|
||||
// Create a new instance
|
||||
$this->parent->manifestClass = new $classname($this);
|
||||
|
||||
// And set this so we can copy it later
|
||||
$this->set('manifest_script', $manifestScript);
|
||||
}
|
||||
}
|
||||
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
// Run uninstall if possible
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall'))
|
||||
{
|
||||
$this->parent->manifestClass->uninstall($this);
|
||||
}
|
||||
|
||||
$msg = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if ($msg != '')
|
||||
{
|
||||
$this->parent->set('extension_message', $msg);
|
||||
}
|
||||
|
||||
$db = JFactory::getDbo();
|
||||
|
||||
// Let's run the uninstall queries for the extension
|
||||
$result = $this->parent->parseSQLFiles($this->manifest->uninstall->sql);
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_SQL_ERROR', $db->stderr(true)), JLog::WARNING, 'jerror');
|
||||
$retval = false;
|
||||
}
|
||||
|
||||
// Remove the schema version
|
||||
$query = $db->getQuery(true)
|
||||
->delete('#__schemas')
|
||||
->where('extension_id = ' . $row->extension_id);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
// Loop through all elements and get list of files and folders
|
||||
foreach ($xml->fileset->files as $eFiles)
|
||||
{
|
||||
$target = (string) $eFiles->attributes()->target;
|
||||
|
||||
// Create folder path
|
||||
if (empty($target))
|
||||
{
|
||||
$targetFolder = JPATH_ROOT;
|
||||
}
|
||||
else
|
||||
{
|
||||
$targetFolder = JPATH_ROOT . '/' . $target;
|
||||
}
|
||||
|
||||
$folderList = array();
|
||||
|
||||
// Check if all children exists
|
||||
if (count($eFiles->children()) > 0)
|
||||
{
|
||||
// Loop through all filenames elements
|
||||
foreach ($eFiles->children() as $eFileName)
|
||||
{
|
||||
if ($eFileName->getName() == 'folder')
|
||||
{
|
||||
$folderList[] = $targetFolder . '/' . $eFileName;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$fileName = $targetFolder . '/' . $eFileName;
|
||||
JFile::delete($fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete any folders that don't have any content in them.
|
||||
foreach ($folderList as $folder)
|
||||
{
|
||||
$files = JFolder::files($folder);
|
||||
|
||||
if (!count($files))
|
||||
{
|
||||
JFolder::delete($folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JFile::delete($manifestFile);
|
||||
|
||||
// Lastly, remove the extension_root
|
||||
$folder = $this->parent->getPath('extension_root');
|
||||
|
||||
if (JFolder::exists($folder))
|
||||
{
|
||||
JFolder::delete($folder);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_FILE_UNINSTALL_INVALID_NOTFOUND_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
// Delete the row because its broken
|
||||
$row->delete();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->parent->removeFiles($xml->languages);
|
||||
|
||||
$row->delete();
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to check if extension is already installed
|
||||
*
|
||||
* @param string $extension The element name of the extension to install
|
||||
*
|
||||
* @return boolean True if extension exists
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function extensionExistsInSystem($extension = null)
|
||||
{
|
||||
// Get a database connector object
|
||||
$db = $this->parent->getDBO();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('file'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote($extension));
|
||||
$db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$db->execute();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_ROLLBACK', $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
$id = $db->loadResult();
|
||||
|
||||
if (empty($id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to populate files and folder list
|
||||
*
|
||||
* @return boolean none
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function populateFilesAndFolderList()
|
||||
{
|
||||
// Initialise variable
|
||||
$this->folderList = array();
|
||||
$this->fileList = array();
|
||||
|
||||
// Set root folder names
|
||||
$packagePath = $this->parent->getPath('source');
|
||||
$jRootPath = JPath::clean(JPATH_ROOT);
|
||||
|
||||
// Loop through all elements and get list of files and folders
|
||||
foreach ($this->manifest->fileset->files as $eFiles)
|
||||
{
|
||||
// Check if the element is files element
|
||||
$folder = (string) $eFiles->attributes()->folder;
|
||||
$target = (string) $eFiles->attributes()->target;
|
||||
|
||||
// Split folder names into array to get folder names. This will help in creating folders
|
||||
$arrList = preg_split("#/|\\/#", $target);
|
||||
|
||||
$folderName = $jRootPath;
|
||||
|
||||
foreach ($arrList as $dir)
|
||||
{
|
||||
if (empty($dir))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$folderName .= '/' . $dir;
|
||||
|
||||
// Check if folder exists, if not then add to the array for folder creation
|
||||
if (!JFolder::exists($folderName))
|
||||
{
|
||||
array_push($this->folderList, $folderName);
|
||||
}
|
||||
}
|
||||
|
||||
// Create folder path
|
||||
$sourceFolder = empty($folder) ? $packagePath : $packagePath . '/' . $folder;
|
||||
$targetFolder = empty($target) ? $jRootPath : $jRootPath . '/' . $target;
|
||||
|
||||
// Check if source folder exists
|
||||
if (!JFolder::exists($sourceFolder))
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_INSTALLER_ABORT_FILE_INSTALL_FAIL_SOURCE_DIRECTORY', $sourceFolder), JLog::WARNING, 'jerror');
|
||||
|
||||
// If installation fails, rollback
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if all children exists
|
||||
if (count($eFiles->children()))
|
||||
{
|
||||
// Loop through all filenames elements
|
||||
foreach ($eFiles->children() as $eFileName)
|
||||
{
|
||||
$path['src'] = $sourceFolder . '/' . $eFileName;
|
||||
$path['dest'] = $targetFolder . '/' . $eFileName;
|
||||
$path['type'] = 'file';
|
||||
|
||||
if ($eFileName->getName() == 'folder')
|
||||
{
|
||||
$folderName = $targetFolder . '/' . $eFileName;
|
||||
array_push($this->folderList, $folderName);
|
||||
$path['type'] = 'folder';
|
||||
}
|
||||
|
||||
array_push($this->fileList, $path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$files = JFolder::files($sourceFolder);
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$path['src'] = $sourceFolder . '/' . $file;
|
||||
$path['dest'] = $targetFolder . '/' . $file;
|
||||
|
||||
array_push($this->fileList, $path);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the extension table cache
|
||||
*
|
||||
* @return boolean result of operation, true if updated, false on failure
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function refreshManifestCache()
|
||||
{
|
||||
// Need to find to find where the XML file is since we don't store this normally
|
||||
$manifestPath = JPATH_MANIFESTS . '/files/' . $this->parent->extension->element . '.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
|
||||
try
|
||||
{
|
||||
return $this->parent->extension->store();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated class placeholder. You should use JInstallerAdapterFile instead.
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
* @deprecated 4.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class JInstallerFile extends JInstallerAdapterFile
|
||||
{
|
||||
}
|
1
libraries/cms/installer/adapter/index.html
Normal file
1
libraries/cms/installer/adapter/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
670
libraries/cms/installer/adapter/language.php
Normal file
670
libraries/cms/installer/adapter/language.php
Normal file
@ -0,0 +1,670 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.base.adapterinstance');
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
/**
|
||||
* Language installer
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
*/
|
||||
class JInstallerAdapterLanguage extends JAdapterInstance
|
||||
{
|
||||
/**
|
||||
* Core language pack flag
|
||||
*
|
||||
* @var boolean
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $core = false;
|
||||
|
||||
/**
|
||||
* Custom install method
|
||||
*
|
||||
* Note: This behaves badly due to hacks made in the middle of 1.5.x to add
|
||||
* the ability to install multiple distinct packs in one install. The
|
||||
* preferred method is to use a package to install multiple language packs.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
$source = $this->parent->getPath('source');
|
||||
|
||||
if (!$source)
|
||||
{
|
||||
$this->parent
|
||||
->setPath(
|
||||
'source',
|
||||
($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/language/' . $this->parent->extension->element
|
||||
);
|
||||
}
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
// Get the client application target
|
||||
if ($cname = (string) $this->manifest->attributes()->client)
|
||||
{
|
||||
// Attempt to map the client to a base path
|
||||
$client = JApplicationHelper::getClientInfo($cname, true);
|
||||
|
||||
if ($client === null)
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_UNKNOWN_CLIENT_TYPE', $cname)));
|
||||
|
||||
return false;
|
||||
}
|
||||
$basePath = $client->path;
|
||||
$clientId = $client->id;
|
||||
$element = $this->manifest->files;
|
||||
|
||||
return $this->_install($cname, $basePath, $clientId, $element);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No client attribute was found so we assume the site as the client
|
||||
$cname = 'site';
|
||||
$basePath = JPATH_SITE;
|
||||
$clientId = 0;
|
||||
$element = $this->manifest->files;
|
||||
|
||||
return $this->_install($cname, $basePath, $clientId, $element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install function that is designed to handle individual clients
|
||||
*
|
||||
* @param string $cname Cname @todo: not used
|
||||
* @param string $basePath The base name.
|
||||
* @param integer $clientId The client id.
|
||||
* @param object &$element The XML element.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function _install($cname, $basePath, $clientId, &$element)
|
||||
{
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
// Get the language name
|
||||
// Set the extensions name
|
||||
$name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd');
|
||||
$this->set('name', $name);
|
||||
|
||||
// Get the Language tag [ISO tag, eg. en-GB]
|
||||
$tag = (string) $this->manifest->tag;
|
||||
|
||||
// Check if we found the tag - if we didn't, we may be trying to install from an older language package
|
||||
if (!$tag)
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::_('JLIB_INSTALLER_ERROR_NO_LANGUAGE_TAG')));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->set('tag', $tag);
|
||||
|
||||
// Set the language installation path
|
||||
$this->parent->setPath('extension_site', $basePath . '/language/' . $tag);
|
||||
|
||||
// Do we have a meta file in the file list? In other words... is this a core language pack?
|
||||
if ($element && count($element->children()))
|
||||
{
|
||||
$files = $element->children();
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if ((string) $file->attributes()->file == 'meta')
|
||||
{
|
||||
$this->core = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the language directory does not exist, let's create it
|
||||
$created = false;
|
||||
|
||||
if (!file_exists($this->parent->getPath('extension_site')))
|
||||
{
|
||||
if (!$created = JFolder::create($this->parent->getPath('extension_site')))
|
||||
{
|
||||
$this->parent
|
||||
->abort(
|
||||
JText::sprintf(
|
||||
'JLIB_INSTALLER_ABORT',
|
||||
JText::sprintf('JLIB_INSTALLER_ERROR_CREATE_FOLDER_FAILED', $this->parent->getPath('extension_site'))
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for an update function or update tag
|
||||
$updateElement = $this->manifest->update;
|
||||
|
||||
// Upgrade manually set or update tag detected
|
||||
if ($this->parent->isUpgrade() || $updateElement)
|
||||
{
|
||||
// Transfer control to the update function
|
||||
return $this->update();
|
||||
}
|
||||
elseif (!$this->parent->isOverwrite())
|
||||
{
|
||||
// Overwrite is set
|
||||
// We didn't have overwrite set, find an update function or find an update tag so lets call it safe
|
||||
if (file_exists($this->parent->getPath('extension_site')))
|
||||
{
|
||||
// If the site exists say so.
|
||||
JLog::add(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_FOLDER_IN_USE', $this->parent->getPath('extension_site'))),
|
||||
JLog::WARNING, 'jerror'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the admin exists say so.
|
||||
JLog::add(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_FOLDER_IN_USE', $this->parent->getPath('extension_administrator'))),
|
||||
JLog::WARNING, 'jerror'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we created the language directory we will want to remove it if we
|
||||
* have to roll back the installation, so let's add it to the installation
|
||||
* step stack
|
||||
*/
|
||||
if ($created)
|
||||
{
|
||||
$this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_site')));
|
||||
}
|
||||
|
||||
// Copy all the necessary files
|
||||
if ($this->parent->parseFiles($element) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse optional tags
|
||||
$this->parent->parseMedia($this->manifest->media);
|
||||
|
||||
// Copy all the necessary font files to the common pdf_fonts directory
|
||||
$this->parent->setPath('extension_site', $basePath . '/language/pdf_fonts');
|
||||
$overwrite = $this->parent->setOverwrite(true);
|
||||
|
||||
if ($this->parent->parseFiles($this->manifest->fonts) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->parent->setOverwrite($overwrite);
|
||||
|
||||
// Get the language description
|
||||
$description = (string) $this->manifest->description;
|
||||
|
||||
if ($description)
|
||||
{
|
||||
$this->parent->set('message', JText::_($description));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->set('message', '');
|
||||
}
|
||||
|
||||
// Add an entry to the extension table with a whole heap of defaults
|
||||
$row = JTable::getInstance('extension');
|
||||
$row->set('name', $this->get('name'));
|
||||
$row->set('type', 'language');
|
||||
$row->set('element', $this->get('tag'));
|
||||
|
||||
// There is no folder for languages
|
||||
$row->set('folder', '');
|
||||
$row->set('enabled', 1);
|
||||
$row->set('protected', 0);
|
||||
$row->set('access', 0);
|
||||
$row->set('client_id', $clientId);
|
||||
$row->set('params', $this->parent->getParams());
|
||||
$row->set('manifest_cache', $this->parent->generateManifestCache());
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', $row->getError()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clobber any possible pending updates
|
||||
$update = JTable::getInstance('update');
|
||||
$uid = $update->find(array('element' => $this->get('tag'), 'type' => 'language', 'client_id' => '', 'folder' => ''));
|
||||
|
||||
if ($uid)
|
||||
{
|
||||
$update->delete($uid);
|
||||
}
|
||||
|
||||
return $row->get('extension_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom update method
|
||||
*
|
||||
* @return boolean True on success, false on failure
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$xml = $this->parent->getManifest();
|
||||
|
||||
$this->manifest = $xml;
|
||||
|
||||
$cname = $xml->attributes()->client;
|
||||
|
||||
// Attempt to map the client to a base path
|
||||
$client = JApplicationHelper::getClientInfo($cname, true);
|
||||
|
||||
if ($client === null || (empty($cname) && $cname !== 0))
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::sprintf('JLIB_INSTALLER_ERROR_UNKNOWN_CLIENT_TYPE', $cname)));
|
||||
|
||||
return false;
|
||||
}
|
||||
$basePath = $client->path;
|
||||
$clientId = $client->id;
|
||||
|
||||
// Get the language name
|
||||
// Set the extensions name
|
||||
$name = (string) $this->manifest->name;
|
||||
$name = JFilterInput::getInstance()->clean($name, 'cmd');
|
||||
$this->set('name', $name);
|
||||
|
||||
// Get the Language tag [ISO tag, eg. en-GB]
|
||||
$tag = (string) $xml->tag;
|
||||
|
||||
// Check if we found the tag - if we didn't, we may be trying to install from an older language package
|
||||
if (!$tag)
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', JText::_('JLIB_INSTALLER_ERROR_NO_LANGUAGE_TAG')));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->set('tag', $tag);
|
||||
|
||||
// Set the language installation path
|
||||
$this->parent->setPath('extension_site', $basePath . '/language/' . $tag);
|
||||
|
||||
// Do we have a meta file in the file list? In other words... is this a core language pack?
|
||||
if (count($xml->files->children()))
|
||||
{
|
||||
foreach ($xml->files->children() as $file)
|
||||
{
|
||||
if ((string) $file->attributes()->file == 'meta')
|
||||
{
|
||||
$this->core = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy all the necessary files
|
||||
if ($this->parent->parseFiles($xml->files) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse optional tags
|
||||
$this->parent->parseMedia($xml->media);
|
||||
|
||||
// Copy all the necessary font files to the common pdf_fonts directory
|
||||
$this->parent->setPath('extension_site', $basePath . '/language/pdf_fonts');
|
||||
$overwrite = $this->parent->setOverwrite(true);
|
||||
|
||||
if ($this->parent->parseFiles($xml->fonts) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->parent->setOverwrite($overwrite);
|
||||
|
||||
// Get the language description and set it as message
|
||||
$this->parent->set('message', (string) $xml->description);
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Finalization and Cleanup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Clobber any possible pending updates
|
||||
$update = JTable::getInstance('update');
|
||||
$uid = $update->find(array('element' => $this->get('tag'), 'type' => 'language', 'client_id' => $clientId));
|
||||
|
||||
if ($uid)
|
||||
{
|
||||
$update->delete($uid);
|
||||
}
|
||||
|
||||
// Update an entry to the extension table
|
||||
$row = JTable::getInstance('extension');
|
||||
$eid = $row->find(array('element' => strtolower($this->get('tag')), 'type' => 'language', 'client_id' => $clientId));
|
||||
|
||||
if ($eid)
|
||||
{
|
||||
$row->load($eid);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the defaults
|
||||
|
||||
// There is no folder for language
|
||||
$row->set('folder', '');
|
||||
$row->set('enabled', 1);
|
||||
$row->set('protected', 0);
|
||||
$row->set('access', 0);
|
||||
$row->set('client_id', $clientId);
|
||||
$row->set('params', $this->parent->getParams());
|
||||
}
|
||||
$row->set('name', $this->get('name'));
|
||||
$row->set('type', 'language');
|
||||
$row->set('element', $this->get('tag'));
|
||||
$row->set('manifest_cache', $this->parent->generateManifestCache());
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT', $row->getError()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $row->get('extension_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom uninstall method
|
||||
*
|
||||
* @param string $eid The tag of the language to uninstall
|
||||
*
|
||||
* @return mixed Return value for uninstall method in component uninstall file
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function uninstall($eid)
|
||||
{
|
||||
// Load up the extension details
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->load($eid);
|
||||
|
||||
// Grab a copy of the client details
|
||||
$client = JApplicationHelper::getClientInfo($extension->get('client_id'));
|
||||
|
||||
// Check the element isn't blank to prevent nuking the languages directory...just in case
|
||||
$element = $extension->get('element');
|
||||
|
||||
if (empty($element))
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_ELEMENT_EMPTY'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the language is not protected, Normally en-GB.
|
||||
$protected = $extension->get('protected');
|
||||
|
||||
if ($protected == 1)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_PROTECTED'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify that it's not the default language for that client
|
||||
$params = JComponentHelper::getParams('com_languages');
|
||||
|
||||
if ($params->get($client->name) == $element)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_DEFAULT'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct the path from the client, the language and the extension element name
|
||||
$path = $client->path . '/language/' . $element;
|
||||
|
||||
// Get the package manifest object and remove media
|
||||
$this->parent->setPath('source', $path);
|
||||
|
||||
// We do findManifest to avoid problem when uninstalling a list of extension: getManifest cache its manifest file
|
||||
$this->parent->findManifest();
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
$this->parent->removeFiles($this->manifest->media);
|
||||
|
||||
// Check it exists
|
||||
if (!JFolder::exists($path))
|
||||
{
|
||||
// If the folder doesn't exist lets just nuke the row as well and presume the user killed it for us
|
||||
$extension->delete();
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_PATH_EMPTY'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JFolder::delete($path))
|
||||
{
|
||||
// If deleting failed we'll leave the extension entry in tact just in case
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LANG_UNINSTALL_DIRECTORY'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the extension table entry
|
||||
$extension->delete();
|
||||
|
||||
// Setting the language of users which have this language as the default language
|
||||
$db = JFactory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->from('#__users')
|
||||
->select('*');
|
||||
$db->setQuery($query);
|
||||
$users = $db->loadObjectList();
|
||||
|
||||
if ($client->name == 'administrator')
|
||||
{
|
||||
$param_name = 'admin_language';
|
||||
}
|
||||
else
|
||||
{
|
||||
$param_name = 'language';
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ($users as $user)
|
||||
{
|
||||
$registry = new JRegistry;
|
||||
$registry->loadString($user->params);
|
||||
|
||||
if ($registry->get($param_name) == $element)
|
||||
{
|
||||
$registry->set($param_name, '');
|
||||
$query->clear()
|
||||
->update('#__users')
|
||||
->set('params=' . $db->quote($registry))
|
||||
->where('id=' . (int) $user->id);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
if (!empty($count))
|
||||
{
|
||||
JLog::add(JText::plural('JLIB_INSTALLER_NOTICE_LANG_RESET_USERS', $count), JLog::NOTICE, 'jerror');
|
||||
}
|
||||
|
||||
// All done!
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom discover method
|
||||
* Finds language files
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function discover()
|
||||
{
|
||||
$results = array();
|
||||
$site_languages = JFolder::folders(JPATH_SITE . '/language');
|
||||
$admin_languages = JFolder::folders(JPATH_ADMINISTRATOR . '/language');
|
||||
|
||||
foreach ($site_languages as $language)
|
||||
{
|
||||
if (file_exists(JPATH_SITE . '/language/' . $language . '/' . $language . '.xml'))
|
||||
{
|
||||
$manifest_details = JInstaller::parseXMLInstallFile(JPATH_SITE . '/language/' . $language . '/' . $language . '.xml');
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->set('type', 'language');
|
||||
$extension->set('client_id', 0);
|
||||
$extension->set('element', $language);
|
||||
$extension->set('folder', '');
|
||||
$extension->set('name', $language);
|
||||
$extension->set('state', -1);
|
||||
$extension->set('manifest_cache', json_encode($manifest_details));
|
||||
$extension->set('params', '{}');
|
||||
$results[] = $extension;
|
||||
}
|
||||
}
|
||||
foreach ($admin_languages as $language)
|
||||
{
|
||||
if (file_exists(JPATH_ADMINISTRATOR . '/language/' . $language . '/' . $language . '.xml'))
|
||||
{
|
||||
$manifest_details = JInstaller::parseXMLInstallFile(JPATH_ADMINISTRATOR . '/language/' . $language . '/' . $language . '.xml');
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->set('type', 'language');
|
||||
$extension->set('client_id', 1);
|
||||
$extension->set('element', $language);
|
||||
$extension->set('folder', '');
|
||||
$extension->set('name', $language);
|
||||
$extension->set('state', -1);
|
||||
$extension->set('manifest_cache', json_encode($manifest_details));
|
||||
$extension->set('params', '{}');
|
||||
$results[] = $extension;
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom discover install method
|
||||
* Basically updates the manifest cache and leaves everything alone
|
||||
*
|
||||
* @return integer The extension id
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function discover_install()
|
||||
{
|
||||
// Need to find to find where the XML file is since we don't store this normally
|
||||
$client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
|
||||
$short_element = $this->parent->extension->element;
|
||||
$manifestPath = $client->path . '/language/' . $short_element . '/' . $short_element . '.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
$this->parent->setPath('source', $client->path . '/language/' . $short_element);
|
||||
$this->parent->setPath('extension_root', $this->parent->getPath('source'));
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->state = 0;
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
$this->parent->extension->enabled = 1;
|
||||
|
||||
// @todo remove code: $this->parent->extension->params = $this->parent->getParams();
|
||||
try
|
||||
{
|
||||
$this->parent->extension->store();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LANG_DISCOVER_STORE_DETAILS'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
return $this->parent->extension->get('extension_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the extension table cache
|
||||
*
|
||||
* @return boolean result of operation, true if updated, false on failure
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function refreshManifestCache()
|
||||
{
|
||||
$client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
|
||||
$manifestPath = $client->path . '/language/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
|
||||
if ($this->parent->extension->store())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated class placeholder. You should use JInstallerAdapterLanguage instead.
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
* @deprecated 4.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class JInstallerLanguage extends JInstallerAdapterLanguage
|
||||
{
|
||||
}
|
479
libraries/cms/installer/adapter/library.php
Normal file
479
libraries/cms/installer/adapter/library.php
Normal file
@ -0,0 +1,479 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.base.adapterinstance');
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
/**
|
||||
* Library installer
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
*/
|
||||
class JInstallerAdapterLibrary extends JAdapterInstance
|
||||
{
|
||||
/**
|
||||
* Custom loadLanguage method
|
||||
*
|
||||
* @param string $path The path where to find language files.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function loadLanguage($path = null)
|
||||
{
|
||||
$source = $this->parent->getPath('source');
|
||||
|
||||
if (!$source)
|
||||
{
|
||||
$this->parent->setPath('source', JPATH_PLATFORM . '/' . $this->parent->extension->element);
|
||||
}
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
$extension = 'lib_' . strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd'));
|
||||
$name = strtolower((string) $this->manifest->libraryname);
|
||||
$lang = JFactory::getLanguage();
|
||||
$source = $path ? $path : JPATH_PLATFORM . "/$name";
|
||||
$lang->load($extension . '.sys', $source, null, false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_SITE, null, false, false)
|
||||
|| $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_SITE, $lang->getDefault(), false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom install method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
// Get the extension manifest object
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Manifest Document Setup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Set the extension's name
|
||||
$name = JFilterInput::getInstance()->clean((string) $this->manifest->name, 'string');
|
||||
$element = str_replace('.xml', '', basename($this->parent->getPath('manifest')));
|
||||
$this->set('name', $name);
|
||||
$this->set('element', $element);
|
||||
|
||||
$db = $this->parent->getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('library'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote($element));
|
||||
$db->setQuery($query);
|
||||
$result = $db->loadResult();
|
||||
|
||||
if ($result)
|
||||
{
|
||||
// Already installed, can we upgrade?
|
||||
if ($this->parent->isOverwrite() || $this->parent->isUpgrade())
|
||||
{
|
||||
// We can upgrade, so uninstall the old one
|
||||
$installer = new JInstaller; // we don't want to compromise this instance!
|
||||
$installer->uninstall('library', $result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Abort the install, no upgrade possible
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_ALREADY_INSTALLED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the library's description
|
||||
$description = (string) $this->manifest->description;
|
||||
|
||||
if ($description)
|
||||
{
|
||||
$this->parent->set('message', JText::_($description));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->set('message', '');
|
||||
}
|
||||
|
||||
// Set the installation path
|
||||
$group = (string) $this->manifest->libraryname;
|
||||
|
||||
if (!$group)
|
||||
{
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_NOFILE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->setPath('extension_root', JPATH_PLATFORM . '/' . implode(DIRECTORY_SEPARATOR, explode('/', $group)));
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Filesystem Processing Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// If the library directory does not exist, let's create it
|
||||
$created = false;
|
||||
|
||||
if (!file_exists($this->parent->getPath('extension_root')))
|
||||
{
|
||||
if (!$created = JFolder::create($this->parent->getPath('extension_root')))
|
||||
{
|
||||
$this->parent->abort(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_LIB_INSTALL_FAILED_TO_CREATE_DIRECTORY', $this->parent->getPath('extension_root'))
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we created the library directory and will want to remove it if we
|
||||
* have to roll back the installation, let's add it to the installation
|
||||
* step stack
|
||||
*/
|
||||
if ($created)
|
||||
{
|
||||
$this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root')));
|
||||
}
|
||||
|
||||
// Copy all necessary files
|
||||
if ($this->parent->parseFiles($this->manifest->files, -1) === false)
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse optional tags
|
||||
$this->parent->parseLanguages($this->manifest->languages);
|
||||
$this->parent->parseMedia($this->manifest->media);
|
||||
|
||||
// Extension Registration
|
||||
$row = JTable::getInstance('extension');
|
||||
$row->name = $this->get('name');
|
||||
$row->type = 'library';
|
||||
$row->element = $this->get('element');
|
||||
|
||||
// There is no folder for libraries
|
||||
$row->folder = '';
|
||||
$row->enabled = 1;
|
||||
$row->protected = 0;
|
||||
$row->access = 1;
|
||||
$row->client_id = 0;
|
||||
$row->params = $this->parent->getParams();
|
||||
|
||||
// Custom data
|
||||
$row->custom_data = '';
|
||||
$row->manifest_cache = $this->parent->generateManifestCache();
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_LIB_INSTALL_ROLLBACK', $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Finalization and Cleanup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Lastly, we will copy the manifest file to its appropriate place.
|
||||
$manifest = array();
|
||||
$manifest['src'] = $this->parent->getPath('manifest');
|
||||
$manifest['dest'] = JPATH_MANIFESTS . '/libraries/' . basename($this->parent->getPath('manifest'));
|
||||
|
||||
if (!$this->parent->copyFiles(array($manifest), true))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_LIB_INSTALL_COPY_SETUP'));
|
||||
|
||||
return false;
|
||||
}
|
||||
return $row->get('extension_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom update method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
// Since this is just files, an update removes old files
|
||||
// Get the extension manifest object
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Manifest Document Setup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Set the extensions name
|
||||
$name = (string) $this->manifest->name;
|
||||
$name = JFilterInput::getInstance()->clean($name, 'string');
|
||||
$element = str_replace('.xml', '', basename($this->parent->getPath('manifest')));
|
||||
$this->set('name', $name);
|
||||
$this->set('element', $element);
|
||||
|
||||
// We don't want to compromise this instance!
|
||||
$installer = new JInstaller;
|
||||
$db = $this->parent->getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('library'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote($element));
|
||||
$db->setQuery($query);
|
||||
$result = $db->loadResult();
|
||||
|
||||
if ($result)
|
||||
{
|
||||
// Already installed, which would make sense
|
||||
$installer->uninstall('library', $result);
|
||||
}
|
||||
// Now create the new files
|
||||
return $this->install();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom uninstall method
|
||||
*
|
||||
* @param string $id The id of the library to uninstall.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function uninstall($id)
|
||||
{
|
||||
$retval = true;
|
||||
|
||||
// First order of business will be to load the module object table from the database.
|
||||
// This should give us the necessary information to proceed.
|
||||
$row = JTable::getInstance('extension');
|
||||
|
||||
if (!$row->load((int) $id) || !strlen($row->element))
|
||||
{
|
||||
JLog::add(JText::_('ERRORUNKOWNEXTENSION'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the library we are trying to uninstall a core one?
|
||||
// Because that is not a good idea...
|
||||
if ($row->protected)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_WARNCORELIBRARY'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$manifestFile = JPATH_MANIFESTS . '/libraries/' . $row->element . '.xml';
|
||||
|
||||
// Because libraries may not have their own folders we cannot use the standard method of finding an installation manifest
|
||||
if (file_exists($manifestFile))
|
||||
{
|
||||
$manifest = new JInstallerManifestLibrary($manifestFile);
|
||||
|
||||
// Set the library root path
|
||||
$this->parent->setPath('extension_root', JPATH_PLATFORM . '/' . $manifest->libraryname);
|
||||
|
||||
$xml = simplexml_load_file($manifestFile);
|
||||
|
||||
// If we cannot load the XML file return null
|
||||
if (!$xml)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_LOAD_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a valid XML root tag.
|
||||
if ($xml->getName() != 'extension')
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_INVALID_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->parent->removeFiles($xml->files, -1);
|
||||
JFile::delete($manifestFile);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove this row entry since its invalid
|
||||
$row->delete($row->extension_id);
|
||||
unset($row);
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LIB_UNINSTALL_INVALID_NOTFOUND_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Change this so it walked up the path backwards so we clobber multiple empties
|
||||
// If the folder is empty, let's delete it
|
||||
if (JFolder::exists($this->parent->getPath('extension_root')))
|
||||
{
|
||||
if (is_dir($this->parent->getPath('extension_root')))
|
||||
{
|
||||
$files = JFolder::files($this->parent->getPath('extension_root'));
|
||||
|
||||
if (!count($files))
|
||||
{
|
||||
JFolder::delete($this->parent->getPath('extension_root'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->parent->removeFiles($xml->media);
|
||||
$this->parent->removeFiles($xml->languages);
|
||||
|
||||
$row->delete($row->extension_id);
|
||||
unset($row);
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom discover method
|
||||
*
|
||||
* @return array JExtension list of extensions available
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function discover()
|
||||
{
|
||||
$results = array();
|
||||
$file_list = JFolder::files(JPATH_MANIFESTS . '/libraries', '\.xml$');
|
||||
|
||||
foreach ($file_list as $file)
|
||||
{
|
||||
$manifest_details = JInstaller::parseXMLInstallFile(JPATH_MANIFESTS . '/libraries/' . $file);
|
||||
$file = JFile::stripExt($file);
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->set('type', 'library');
|
||||
$extension->set('client_id', 0);
|
||||
$extension->set('element', $file);
|
||||
$extension->set('folder', '');
|
||||
$extension->set('name', $file);
|
||||
$extension->set('state', -1);
|
||||
$extension->set('manifest_cache', json_encode($manifest_details));
|
||||
$extension->set('params', '{}');
|
||||
$results[] = $extension;
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom discover_install method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function discover_install()
|
||||
{
|
||||
/* Libraries are a strange beast; they are actually references to files
|
||||
* There are two parts to a library which are disjunct in their locations
|
||||
* 1) The manifest file (stored in /JPATH_MANIFESTS/libraries)
|
||||
* 2) The actual files (stored in /JPATH_PLATFORM/libraryname)
|
||||
* Thus installation of a library is the process of dumping files
|
||||
* in two different places. As such it is impossible to perform
|
||||
* any operation beyond mere registration of a library under the presumption
|
||||
* that the files exist in the appropriate location so that come uninstall
|
||||
* time they can be adequately removed.
|
||||
*/
|
||||
|
||||
$manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->state = 0;
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
$this->parent->extension->enabled = 1;
|
||||
$this->parent->extension->params = $this->parent->getParams();
|
||||
|
||||
if ($this->parent->extension->store())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LIB_DISCOVER_STORE_DETAILS'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the extension table cache
|
||||
*
|
||||
* @return boolean Result of operation, true if updated, false on failure
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function refreshManifestCache()
|
||||
{
|
||||
// Need to find to find where the XML file is since we don't store this normally
|
||||
$manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
|
||||
try
|
||||
{
|
||||
return $this->parent->extension->store();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_LIB_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated class placeholder. You should use JInstallerAdapterLibrary instead.
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
* @deprecated 4.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class JInstallerLibrary extends JInstallerAdapterLibrary
|
||||
{
|
||||
}
|
1005
libraries/cms/installer/adapter/module.php
Normal file
1005
libraries/cms/installer/adapter/module.php
Normal file
File diff suppressed because it is too large
Load Diff
631
libraries/cms/installer/adapter/package.php
Normal file
631
libraries/cms/installer/adapter/package.php
Normal file
@ -0,0 +1,631 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.base.adapterinstance');
|
||||
|
||||
/**
|
||||
* Package installer
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
*/
|
||||
class JInstallerAdapterPackage extends JAdapterInstance
|
||||
{
|
||||
/**
|
||||
* Method of system
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected $route = 'install';
|
||||
|
||||
/**
|
||||
* Load language from a path
|
||||
*
|
||||
* @param string $path The path of the language.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function loadLanguage($path)
|
||||
{
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
$extension = 'pkg_' . strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->packagename, 'cmd'));
|
||||
$lang = JFactory::getLanguage();
|
||||
$source = $path;
|
||||
$lang->load($extension . '.sys', $source, null, false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_SITE, null, false, false)
|
||||
|| $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_SITE, $lang->getDefault(), false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom install method
|
||||
*
|
||||
* @return int The extension id
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
// Get the extension manifest object
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Manifest Document Setup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Set the extensions name
|
||||
$filter = JFilterInput::getInstance();
|
||||
$name = (string) $this->manifest->packagename;
|
||||
$name = $filter->clean($name, 'cmd');
|
||||
$this->set('name', $name);
|
||||
|
||||
$element = 'pkg_' . $filter->clean($this->manifest->packagename, 'cmd');
|
||||
$this->set('element', $element);
|
||||
|
||||
// Get the component description
|
||||
$description = (string) $this->manifest->description;
|
||||
|
||||
if ($description)
|
||||
{
|
||||
$this->parent->set('message', JText::_($description));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->set('message', '');
|
||||
}
|
||||
|
||||
// Set the installation path
|
||||
$files = $this->manifest->files;
|
||||
$group = (string) $this->manifest->packagename;
|
||||
|
||||
if (!empty($group))
|
||||
{
|
||||
$this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . implode(DIRECTORY_SEPARATOR, explode('/', $group)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_PACK', JText::_('JLIB_INSTALLER_' . strtoupper($this->route))));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the package manifest already exists, then we will assume that the package is already
|
||||
* installed.
|
||||
*/
|
||||
|
||||
if (file_exists(JPATH_MANIFESTS . '/packages/' . basename($this->parent->getPath('manifest'))))
|
||||
{
|
||||
// Look for an update function or update tag
|
||||
$updateElement = $this->manifest->update;
|
||||
|
||||
// If $this->upgrade has already been set, or an update property exists in the manifest, update the extensions
|
||||
if ($this->parent->isUpgrade() || $updateElement)
|
||||
{
|
||||
// Use the update route for all packaged extensions
|
||||
$this->route = 'update';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Installer Trigger Loading
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// If there is an manifest class file, lets load it; we'll copy it later (don't have dest yet)
|
||||
$this->scriptElement = $this->manifest->scriptfile;
|
||||
$manifestScript = (string) $this->manifest->scriptfile;
|
||||
|
||||
if ($manifestScript)
|
||||
{
|
||||
$manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript;
|
||||
|
||||
if (is_file($manifestScriptFile))
|
||||
{
|
||||
// Load the file
|
||||
include_once $manifestScriptFile;
|
||||
}
|
||||
|
||||
// Set the class name
|
||||
$classname = $element . 'InstallerScript';
|
||||
|
||||
if (class_exists($classname))
|
||||
{
|
||||
// Create a new instance
|
||||
$this->parent->manifestClass = new $classname($this);
|
||||
|
||||
// And set this so we can copy it later
|
||||
$this->set('manifest_script', $manifestScript);
|
||||
}
|
||||
}
|
||||
|
||||
// Run preflight if possible (since we know we're not an update)
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight'))
|
||||
{
|
||||
if ($this->parent->manifestClass->preflight($this->route, $this) === false)
|
||||
{
|
||||
// Preflight failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_CUSTOM_INSTALL_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create msg object; first use here
|
||||
$msg = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Filesystem Processing Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
if ($folder = $files->attributes()->folder)
|
||||
{
|
||||
$source = $this->parent->getPath('source') . '/' . $folder;
|
||||
}
|
||||
else
|
||||
{
|
||||
$source = $this->parent->getPath('source');
|
||||
}
|
||||
|
||||
// Install all necessary files
|
||||
if (count($this->manifest->files->children()))
|
||||
{
|
||||
$i = 0;
|
||||
|
||||
foreach ($this->manifest->files->children() as $child)
|
||||
{
|
||||
$file = $source . '/' . $child;
|
||||
|
||||
if (is_dir($file))
|
||||
{
|
||||
// If it's actually a directory then fill it up
|
||||
$package = array();
|
||||
$package['dir'] = $file;
|
||||
$package['type'] = JInstallerHelper::detectType($file);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's an archive
|
||||
$package = JInstallerHelper::unpack($file);
|
||||
}
|
||||
$tmpInstaller = new JInstaller;
|
||||
$installResult = $tmpInstaller->{$this->route}($package['dir']);
|
||||
|
||||
if (!$installResult)
|
||||
{
|
||||
$this->parent->abort(
|
||||
JText::sprintf(
|
||||
'JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION', JText::_('JLIB_INSTALLER_' . strtoupper($this->route)),
|
||||
basename($file)
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$results[$i] = array(
|
||||
'name' => $tmpInstaller->manifest->name,
|
||||
'result' => $installResult
|
||||
);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES', JText::_('JLIB_INSTALLER_' . strtoupper($this->route))));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse optional tags
|
||||
$this->parent->parseLanguages($this->manifest->languages);
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Extension Registration
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
$row = JTable::getInstance('extension');
|
||||
$eid = $row->find(array('element' => strtolower($this->get('element')), 'type' => 'package'));
|
||||
|
||||
if ($eid)
|
||||
{
|
||||
$row->load($eid);
|
||||
}
|
||||
else
|
||||
{
|
||||
$row->name = $this->get('name');
|
||||
$row->type = 'package';
|
||||
$row->element = $this->get('element');
|
||||
|
||||
// There is no folder for modules
|
||||
$row->folder = '';
|
||||
$row->enabled = 1;
|
||||
$row->protected = 0;
|
||||
$row->access = 1;
|
||||
$row->client_id = 0;
|
||||
|
||||
// Custom data
|
||||
$row->custom_data = '';
|
||||
$row->params = $this->parent->getParams();
|
||||
}
|
||||
// Update the manifest cache for the entry
|
||||
$row->manifest_cache = $this->parent->generateManifestCache();
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_ROLLBACK', $row->getError()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Finalization and Cleanup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Run the custom method based on the route
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route))
|
||||
{
|
||||
if ($this->parent->manifestClass->{$this->route}($this) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_FILE_INSTALL_CUSTOM_INSTALL_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Append messages
|
||||
$msg .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// Lastly, we will copy the manifest file to its appropriate place.
|
||||
$manifest = array();
|
||||
$manifest['src'] = $this->parent->getPath('manifest');
|
||||
$manifest['dest'] = JPATH_MANIFESTS . '/packages/' . basename($this->parent->getPath('manifest'));
|
||||
|
||||
if (!$this->parent->copyFiles(array($manifest), true))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_PACK_INSTALL_COPY_SETUP', JText::_('JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES'))
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is a manifest script, let's copy it.
|
||||
if ($this->get('manifest_script'))
|
||||
{
|
||||
// First, we have to create a folder for the script if one isn't present
|
||||
if (!file_exists($this->parent->getPath('extension_root')))
|
||||
{
|
||||
JFolder::create($this->parent->getPath('extension_root'));
|
||||
}
|
||||
|
||||
$path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script');
|
||||
$path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script');
|
||||
|
||||
if (!file_exists($path['dest']) || $this->parent->isOverwrite())
|
||||
{
|
||||
if (!$this->parent->copyFiles(array($path)))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PACKAGE_INSTALL_MANIFEST'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And now we run the postflight
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight'))
|
||||
{
|
||||
$this->parent->manifestClass->postflight($this->route, $this, $results);
|
||||
}
|
||||
|
||||
// Append messages
|
||||
$msg .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if ($msg != '')
|
||||
{
|
||||
$this->parent->set('extension_message', $msg);
|
||||
}
|
||||
return $row->extension_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a package
|
||||
*
|
||||
* The only difference between an update and a full install
|
||||
* is how we handle the database
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$this->route = 'update';
|
||||
$this->install();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom uninstall method
|
||||
*
|
||||
* @param integer $id The id of the package to uninstall.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function uninstall($id)
|
||||
{
|
||||
$row = null;
|
||||
$retval = true;
|
||||
|
||||
$row = JTable::getInstance('extension');
|
||||
$row->load($id);
|
||||
|
||||
if ($row->protected)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_WARNCOREPACK'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$manifestFile = JPATH_MANIFESTS . '/packages/' . $row->get('element') . '.xml';
|
||||
$manifest = new JInstallerManifestPackage($manifestFile);
|
||||
|
||||
// Set the package root path
|
||||
$this->parent->setPath('extension_root', JPATH_MANIFESTS . '/packages/' . $manifest->packagename);
|
||||
|
||||
// Because packages may not have their own folders we cannot use the standard method of finding an installation manifest
|
||||
if (!file_exists($manifestFile))
|
||||
{
|
||||
// TODO: Fail?
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSINGMANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
$xml = simplexml_load_file($manifestFile);
|
||||
|
||||
// If we cannot load the XML file return false
|
||||
if (!$xml)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_LOAD_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a valid XML root tag.
|
||||
if ($xml->getName() != 'extension')
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_INVALID_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is an manifest class file, let's load it
|
||||
$this->scriptElement = $manifest->scriptfile;
|
||||
$manifestScript = (string) $manifest->scriptfile;
|
||||
|
||||
if ($manifestScript)
|
||||
{
|
||||
$manifestScriptFile = $this->parent->getPath('extension_root') . '/' . $manifestScript;
|
||||
|
||||
if (is_file($manifestScriptFile))
|
||||
{
|
||||
// Load the file
|
||||
include_once $manifestScriptFile;
|
||||
}
|
||||
|
||||
// Set the class name
|
||||
$classname = $row->element . 'InstallerScript';
|
||||
|
||||
if (class_exists($classname))
|
||||
{
|
||||
// Create a new instance
|
||||
$this->parent->manifestClass = new $classname($this);
|
||||
|
||||
// And set this so we can copy it later
|
||||
$this->set('manifest_script', $manifestScript);
|
||||
}
|
||||
}
|
||||
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
// Run uninstall if possible
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall'))
|
||||
{
|
||||
$this->parent->manifestClass->uninstall($this);
|
||||
}
|
||||
|
||||
$msg = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if ($msg != '')
|
||||
{
|
||||
$this->parent->set('extension_message', $msg);
|
||||
}
|
||||
|
||||
$error = false;
|
||||
|
||||
foreach ($manifest->filelist as $extension)
|
||||
{
|
||||
$tmpInstaller = new JInstaller;
|
||||
$id = $this->_getExtensionID($extension->type, $extension->id, $extension->client, $extension->group);
|
||||
$client = JApplicationHelper::getClientInfo($extension->client, true);
|
||||
|
||||
if ($id)
|
||||
{
|
||||
if (!$tmpInstaller->uninstall($extension->type, $id, $client->id))
|
||||
{
|
||||
$error = true;
|
||||
JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_NOT_PROPER', basename($extension->filename)), JLog::WARNING, 'jerror');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_UNKNOWN_EXTENSION'), JLog::WARNING, 'jerror');
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any language files
|
||||
$this->parent->removeFiles($xml->languages);
|
||||
|
||||
// Clean up manifest file after we're done if there were no errors
|
||||
if (!$error)
|
||||
{
|
||||
JFile::delete($manifestFile);
|
||||
$folder = $this->parent->getPath('extension_root');
|
||||
|
||||
if (JFolder::exists($folder))
|
||||
{
|
||||
JFolder::delete($folder);
|
||||
}
|
||||
$row->delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MANIFEST_NOT_REMOVED'), JLog::WARNING, 'jerror');
|
||||
}
|
||||
|
||||
// Return the result up the line
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extension id.
|
||||
*
|
||||
* @param string $type The extension type.
|
||||
* @param string $id The name of the extension (the element field).
|
||||
* @param integer $client The application id (0: Joomla CMS site; 1: Joomla CMS administrator).
|
||||
* @param string $group The extension group (mainly for plugins).
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function _getExtensionID($type, $id, $client, $group)
|
||||
{
|
||||
$db = $this->parent->getDbo();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('extension_id')
|
||||
->from('#__extensions')
|
||||
->where('type = ' . $db->quote($type))
|
||||
->where('element = ' . $db->quote($id));
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
case 'plugin':
|
||||
// Plugins have a folder but not a client
|
||||
$query->where('folder = ' . $db->quote($group));
|
||||
break;
|
||||
|
||||
case 'library':
|
||||
case 'package':
|
||||
case 'component':
|
||||
// Components, packages and libraries don't have a folder or client.
|
||||
// Included for completeness.
|
||||
break;
|
||||
|
||||
case 'language':
|
||||
case 'module':
|
||||
case 'template':
|
||||
// Languages, modules and templates have a client but not a folder
|
||||
$client = JApplicationHelper::getClientInfo($client, true);
|
||||
$query->where('client_id = ' . (int) $client->id);
|
||||
break;
|
||||
}
|
||||
|
||||
$db->setQuery($query);
|
||||
$result = $db->loadResult();
|
||||
|
||||
// Note: For templates, libraries and packages their unique name is their key.
|
||||
// This means they come out the same way they came in.
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the extension table cache
|
||||
*
|
||||
* @return boolean Result of operation, true if updated, false on failure
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function refreshManifestCache()
|
||||
{
|
||||
// Need to find to find where the XML file is since we don't store this normally
|
||||
$manifestPath = JPATH_MANIFESTS . '/packages/' . $this->parent->extension->element . '.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
|
||||
try
|
||||
{
|
||||
return $this->parent->extension->store();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PACK_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated class placeholder. You should use JInstallerAdapterPackage instead.
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
* @deprecated 4.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class JInstallerPackage extends JInstallerAdapterPackage
|
||||
{
|
||||
}
|
923
libraries/cms/installer/adapter/plugin.php
Normal file
923
libraries/cms/installer/adapter/plugin.php
Normal file
@ -0,0 +1,923 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.base.adapterinstance');
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
/**
|
||||
* Plugin installer
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
*/
|
||||
class JInstallerAdapterPlugin extends JAdapterInstance
|
||||
{
|
||||
/**
|
||||
* Install function routing
|
||||
*
|
||||
* @var string
|
||||
* @since 3.1
|
||||
* */
|
||||
protected $route = 'install';
|
||||
|
||||
/**
|
||||
* The installation manifest XML object
|
||||
*
|
||||
* @var
|
||||
* @since 3.1
|
||||
* */
|
||||
protected $manifest = null;
|
||||
|
||||
/**
|
||||
* A path to the PHP file that the scriptfile declaration in
|
||||
* the manifest refers to.
|
||||
*
|
||||
* @var
|
||||
* @since 3.1
|
||||
* */
|
||||
protected $manifest_script = null;
|
||||
|
||||
/**
|
||||
* Name of the extension
|
||||
*
|
||||
* @var
|
||||
* @since 3.1
|
||||
* */
|
||||
protected $name = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @var
|
||||
* @since 3.1
|
||||
* */
|
||||
protected $scriptElement = null;
|
||||
|
||||
/**
|
||||
* @var
|
||||
* @since 3.1
|
||||
*/
|
||||
protected $oldFiles = null;
|
||||
|
||||
/**
|
||||
* Custom loadLanguage method
|
||||
*
|
||||
* @param string $path The path where to find language files.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function loadLanguage($path = null)
|
||||
{
|
||||
$source = $this->parent->getPath('source');
|
||||
|
||||
if (!$source)
|
||||
{
|
||||
$this->parent->setPath('source', JPATH_PLUGINS . '/' . $this->parent->extension->folder . '/' . $this->parent->extension->element);
|
||||
}
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
$element = $this->manifest->files;
|
||||
|
||||
if ($element)
|
||||
{
|
||||
$group = strtolower((string) $this->manifest->attributes()->group);
|
||||
$name = '';
|
||||
|
||||
if (count($element->children()))
|
||||
{
|
||||
foreach ($element->children() as $file)
|
||||
{
|
||||
if ((string) $file->attributes()->plugin)
|
||||
{
|
||||
$name = strtolower((string) $file->attributes()->plugin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($name)
|
||||
{
|
||||
$extension = "plg_${group}_${name}";
|
||||
$lang = JFactory::getLanguage();
|
||||
$source = $path ? $path : JPATH_PLUGINS . "/$group/$name";
|
||||
$folder = (string) $element->attributes()->folder;
|
||||
|
||||
if ($folder && file_exists("$path/$folder"))
|
||||
{
|
||||
$source = "$path/$folder";
|
||||
}
|
||||
$lang->load($extension . '.sys', $source, null, false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, null, false, false)
|
||||
|| $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
|
||||
|| $lang->load($extension . '.sys', JPATH_ADMINISTRATOR, $lang->getDefault(), false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom install method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
// Get a database connector object
|
||||
$db = $this->parent->getDbo();
|
||||
|
||||
// Get the extension manifest object
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
$xml = $this->manifest;
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Manifest Document Setup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Set the extension name
|
||||
$name = (string) $xml->name;
|
||||
$name = JFilterInput::getInstance()->clean($name, 'string');
|
||||
$this->set('name', $name);
|
||||
|
||||
// Get the plugin description
|
||||
$description = (string) $xml->description;
|
||||
|
||||
if ($description)
|
||||
{
|
||||
$this->parent->set('message', JText::_($description));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->set('message', '');
|
||||
}
|
||||
|
||||
/*
|
||||
* Backward Compatibility
|
||||
* @todo Deprecate in future version
|
||||
*/
|
||||
$type = (string) $xml->attributes()->type;
|
||||
|
||||
// Set the installation path
|
||||
if (count($xml->files->children()))
|
||||
{
|
||||
foreach ($xml->files->children() as $file)
|
||||
{
|
||||
if ((string) $file->attributes()->$type)
|
||||
{
|
||||
$element = (string) $file->attributes()->$type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$group = (string) $xml->attributes()->group;
|
||||
|
||||
if (!empty($element) && !empty($group))
|
||||
{
|
||||
$this->parent->setPath('extension_root', JPATH_PLUGINS . '/' . $group . '/' . $element);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_NO_FILE', JText::_('JLIB_INSTALLER_' . $this->route)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we should enable overwrite settings
|
||||
|
||||
// Check to see if a plugin by the same name is already installed.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('folder') . ' = ' . $db->quote($group))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote($element));
|
||||
$db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$db->execute();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent
|
||||
->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
$id = $db->loadResult();
|
||||
|
||||
// If it's on the fs...
|
||||
if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite() || $this->parent->isUpgrade()))
|
||||
{
|
||||
$updateElement = $xml->update;
|
||||
|
||||
// Upgrade manually set or update function available or update tag detected
|
||||
if ($this->parent->isUpgrade() || ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'update'))
|
||||
|| $updateElement)
|
||||
{
|
||||
// Force this one
|
||||
$this->parent->setOverwrite(true);
|
||||
$this->parent->setUpgrade(true);
|
||||
|
||||
if ($id)
|
||||
{
|
||||
// If there is a matching extension mark this as an update; semantics really
|
||||
$this->route = 'update';
|
||||
}
|
||||
}
|
||||
elseif (!$this->parent->isOverwrite())
|
||||
{
|
||||
// Overwrite is set
|
||||
// We didn't have overwrite set, find an update function or find an update tag so lets call it safe
|
||||
$this->parent
|
||||
->abort(
|
||||
JText::sprintf(
|
||||
'JLIB_INSTALLER_ABORT_PLG_INSTALL_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route),
|
||||
$this->parent->getPath('extension_root')
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Installer Trigger Loading
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// If there is an manifest class file, let's load it; we'll copy it later (don't have destination yet).
|
||||
if ((string) $xml->scriptfile)
|
||||
{
|
||||
$manifestScript = (string) $xml->scriptfile;
|
||||
$manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript;
|
||||
|
||||
if (is_file($manifestScriptFile))
|
||||
{
|
||||
// Load the file
|
||||
include_once $manifestScriptFile;
|
||||
}
|
||||
// If a dash is present in the group name, remove it
|
||||
$groupClass = str_replace('-', '', $group);
|
||||
|
||||
// Set the class name
|
||||
$classname = 'plg' . $groupClass . $element . 'InstallerScript';
|
||||
|
||||
if (class_exists($classname))
|
||||
{
|
||||
// Create a new instance
|
||||
$this->parent->manifestClass = new $classname($this);
|
||||
|
||||
// And set this so we can copy it later
|
||||
$this->set('manifest_script', $manifestScript);
|
||||
}
|
||||
}
|
||||
|
||||
// Run preflight if possible (since we know we're not an update)
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight'))
|
||||
{
|
||||
if ($this->parent->manifestClass->preflight($this->route, $this) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create msg object; first use here
|
||||
$msg = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Filesystem Processing Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// If the plugin directory does not exist, lets create it
|
||||
$created = false;
|
||||
|
||||
if (!file_exists($this->parent->getPath('extension_root')))
|
||||
{
|
||||
if (!$created = JFolder::create($this->parent->getPath('extension_root')))
|
||||
{
|
||||
$this->parent
|
||||
->abort(
|
||||
JText::sprintf(
|
||||
'JLIB_INSTALLER_ABORT_PLG_INSTALL_CREATE_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route),
|
||||
$this->parent->getPath('extension_root')
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're updating at this point when there is always going to be an extension_root find the old XML files
|
||||
if ($this->route == 'update')
|
||||
{
|
||||
// Hunt for the original XML file
|
||||
$old_manifest = null;
|
||||
|
||||
// Create a new installer because findManifest sets stuff; side effects!
|
||||
$tmpInstaller = new JInstaller;
|
||||
|
||||
// Look in the extension root
|
||||
$tmpInstaller->setPath('source', $this->parent->getPath('extension_root'));
|
||||
|
||||
if ($tmpInstaller->findManifest())
|
||||
{
|
||||
$old_manifest = $tmpInstaller->getManifest();
|
||||
$this->oldFiles = $old_manifest->files;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we created the plugin directory and will want to remove it if we
|
||||
* have to roll back the installation, let's add it to the installation
|
||||
* step stack
|
||||
*/
|
||||
|
||||
if ($created)
|
||||
{
|
||||
$this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root')));
|
||||
}
|
||||
|
||||
// Copy all necessary files
|
||||
if ($this->parent->parseFiles($xml->files, -1, $this->oldFiles) === false)
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse optional tags -- media and language files for plugins go in admin app
|
||||
$this->parent->parseMedia($xml->media, 1);
|
||||
$this->parent->parseLanguages($xml->languages, 1);
|
||||
|
||||
// If there is a manifest script, lets copy it.
|
||||
if ($this->get('manifest_script'))
|
||||
{
|
||||
$path['src'] = $this->parent->getPath('source') . '/' . $this->get('manifest_script');
|
||||
$path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->get('manifest_script');
|
||||
|
||||
if (!file_exists($path['dest']))
|
||||
{
|
||||
if (!$this->parent->copyFiles(array($path)))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent
|
||||
->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_MANIFEST', JText::_('JLIB_INSTALLER_' . $this->route)));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Database Processing Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
$row = JTable::getInstance('extension');
|
||||
|
||||
// Was there a plugin with the same name already installed?
|
||||
if ($id)
|
||||
{
|
||||
if (!$this->parent->isOverwrite())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent
|
||||
->abort(
|
||||
JText::sprintf(
|
||||
'JLIB_INSTALLER_ABORT_PLG_INSTALL_ALLREADY_EXISTS', JText::_('JLIB_INSTALLER_' . $this->route),
|
||||
$this->get('name')
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
$row->load($id);
|
||||
$row->name = $this->get('name');
|
||||
$row->manifest_cache = $this->parent->generateManifestCache();
|
||||
|
||||
// Update the manifest cache and name
|
||||
$row->store();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Store in the extensions table (1.6)
|
||||
$row->name = $this->get('name');
|
||||
$row->type = 'plugin';
|
||||
$row->ordering = 0;
|
||||
$row->element = $element;
|
||||
$row->folder = $group;
|
||||
$row->enabled = 0;
|
||||
$row->protected = 0;
|
||||
$row->access = 1;
|
||||
$row->client_id = 0;
|
||||
$row->params = $this->parent->getParams();
|
||||
|
||||
// Custom data
|
||||
$row->custom_data = '';
|
||||
|
||||
// System data
|
||||
$row->system_data = '';
|
||||
$row->manifest_cache = $this->parent->generateManifestCache();
|
||||
|
||||
// Editor plugins are published by default
|
||||
if ($group == 'editors')
|
||||
{
|
||||
$row->enabled = 1;
|
||||
}
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent
|
||||
->abort(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_ROLLBACK', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we have created a plugin item, we add it to the installation step stack
|
||||
// so that if we have to rollback the changes we can undo it.
|
||||
$this->parent->pushStep(array('type' => 'extension', 'id' => $row->extension_id));
|
||||
$id = $row->extension_id;
|
||||
}
|
||||
|
||||
// Let's run the queries for the plugin
|
||||
if (strtolower($this->route) == 'install')
|
||||
{
|
||||
$result = $this->parent->parseSQLFiles($this->manifest->install->sql);
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent
|
||||
->abort(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_SQL_ERROR', JText::_('JLIB_INSTALLER_' . $this->route), $db->stderr(true))
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the schema version to be the latest update version
|
||||
if ($this->manifest->update)
|
||||
{
|
||||
$this->parent->setSchemaVersion($this->manifest->update->schemas, $row->extension_id);
|
||||
}
|
||||
}
|
||||
elseif (strtolower($this->route) == 'update')
|
||||
{
|
||||
if ($this->manifest->update)
|
||||
{
|
||||
$result = $this->parent->parseSchemaUpdates($this->manifest->update->schemas, $row->extension_id);
|
||||
|
||||
if ($result === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_UPDATE_SQL_ERROR', $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the custom method based on the route
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, $this->route))
|
||||
{
|
||||
if ($this->parent->manifestClass->{$this->route}($this) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Append messages
|
||||
$msg .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Finalization and Cleanup Section
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Lastly, we will copy the manifest file to its appropriate place.
|
||||
if (!$this->parent->copyManifest(-1))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_INSTALL_COPY_SETUP', JText::_('JLIB_INSTALLER_' . $this->route)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// And now we run the postflight
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'postflight'))
|
||||
{
|
||||
$this->parent->manifestClass->postflight($this->route, $this);
|
||||
}
|
||||
|
||||
// Append messages
|
||||
$msg .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if ($msg != '')
|
||||
{
|
||||
$this->parent->set('extension_message', $msg);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom update method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
// Set the overwrite setting
|
||||
$this->parent->setOverwrite(true);
|
||||
$this->parent->setUpgrade(true);
|
||||
|
||||
// Set the route for the install
|
||||
$this->route = 'update';
|
||||
|
||||
// Go to install which handles updates properly
|
||||
return $this->install();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom uninstall method
|
||||
*
|
||||
* @param integer $id The id of the plugin to uninstall
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function uninstall($id)
|
||||
{
|
||||
$this->route = 'uninstall';
|
||||
|
||||
$row = null;
|
||||
$retval = true;
|
||||
$db = $this->parent->getDbo();
|
||||
|
||||
// First order of business will be to load the plugin object table from the database.
|
||||
// This should give us the necessary information to proceed.
|
||||
$row = JTable::getInstance('extension');
|
||||
|
||||
if (!$row->load((int) $id))
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_ERRORUNKOWNEXTENSION'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the plugin we are trying to uninstall a core one?
|
||||
// Because that is not a good idea...
|
||||
if ($row->protected)
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_WARNCOREPLUGIN', $row->name), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the plugin folder so we can properly build the plugin path
|
||||
if (trim($row->folder) == '')
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PLG_UNINSTALL_FOLDER_FIELD_EMPTY'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the plugin root path
|
||||
$this->parent->setPath('extension_root', JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element);
|
||||
|
||||
$this->parent->setPath('source', $this->parent->getPath('extension_root'));
|
||||
|
||||
$this->parent->findManifest();
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
|
||||
// Attempt to load the language file; might have uninstall strings
|
||||
$this->parent->setPath('source', JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element);
|
||||
$this->loadLanguage(JPATH_PLUGINS . '/' . $row->folder . '/' . $row->element);
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Installer Trigger Loading
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// If there is an manifest class file, let's load it; we'll copy it later (don't have dest yet)
|
||||
$manifestScript = (string) $this->manifest->scriptfile;
|
||||
|
||||
if ($manifestScript)
|
||||
{
|
||||
$manifestScriptFile = $this->parent->getPath('source') . '/' . $manifestScript;
|
||||
|
||||
if (is_file($manifestScriptFile))
|
||||
{
|
||||
// Load the file
|
||||
include_once $manifestScriptFile;
|
||||
}
|
||||
// If a dash is present in the folder, remove it
|
||||
$folderClass = str_replace('-', '', $row->folder);
|
||||
|
||||
// Set the class name
|
||||
$classname = 'plg' . $folderClass . $row->element . 'InstallerScript';
|
||||
|
||||
if (class_exists($classname))
|
||||
{
|
||||
// Create a new instance
|
||||
$this->parent->manifestClass = new $classname($this);
|
||||
|
||||
// And set this so we can copy it later
|
||||
$this->set('manifest_script', $manifestScript);
|
||||
}
|
||||
}
|
||||
|
||||
// Run preflight if possible (since we know we're not an update)
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'preflight'))
|
||||
{
|
||||
if ($this->parent->manifestClass->preflight($this->route, $this) === false)
|
||||
{
|
||||
// Preflight failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_PLG_INSTALL_CUSTOM_INSTALL_FAILURE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the $msg object and append messages from preflight
|
||||
$msg = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// Let's run the queries for the plugin
|
||||
$utfresult = $this->parent->parseSQLFiles($this->manifest->uninstall->sql);
|
||||
|
||||
if ($utfresult === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_PLG_UNINSTALL_SQL_ERROR', $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run the custom uninstall method if possible
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
if ($this->parent->manifestClass && method_exists($this->parent->manifestClass, 'uninstall'))
|
||||
{
|
||||
$this->parent->manifestClass->uninstall($this);
|
||||
}
|
||||
|
||||
// Append messages
|
||||
$msg .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
// Remove the plugin files
|
||||
$this->parent->removeFiles($this->manifest->files, -1);
|
||||
|
||||
// Remove all media and languages as well
|
||||
$this->parent->removeFiles($this->manifest->media);
|
||||
$this->parent->removeFiles($this->manifest->languages, 1);
|
||||
|
||||
// Remove the schema version
|
||||
$query = $db->getQuery(true)
|
||||
->delete('#__schemas')
|
||||
->where('extension_id = ' . $row->extension_id);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
// Now we will no longer need the plugin object, so let's delete it
|
||||
$row->delete($row->extension_id);
|
||||
unset($row);
|
||||
|
||||
// Remove the plugin's folder
|
||||
JFolder::delete($this->parent->getPath('extension_root'));
|
||||
|
||||
if ($msg != '')
|
||||
{
|
||||
$this->parent->set('extension_message', $msg);
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom discover method
|
||||
*
|
||||
* @return array JExtension) list of extensions available
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function discover()
|
||||
{
|
||||
$results = array();
|
||||
$folder_list = JFolder::folders(JPATH_SITE . '/plugins');
|
||||
|
||||
foreach ($folder_list as $folder)
|
||||
{
|
||||
$file_list = JFolder::files(JPATH_SITE . '/plugins/' . $folder, '\.xml$');
|
||||
|
||||
foreach ($file_list as $file)
|
||||
{
|
||||
$manifest_details = JInstaller::parseXMLInstallFile(JPATH_SITE . '/plugins/' . $folder . '/' . $file);
|
||||
$file = JFile::stripExt($file);
|
||||
|
||||
// Ignore example plugins
|
||||
if ($file == 'example')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->set('type', 'plugin');
|
||||
$extension->set('client_id', 0);
|
||||
$extension->set('element', $file);
|
||||
$extension->set('folder', $folder);
|
||||
$extension->set('name', $file);
|
||||
$extension->set('state', -1);
|
||||
$extension->set('manifest_cache', json_encode($manifest_details));
|
||||
$extension->set('params', '{}');
|
||||
$results[] = $extension;
|
||||
}
|
||||
$folder_list = JFolder::folders(JPATH_SITE . '/plugins/' . $folder);
|
||||
|
||||
foreach ($folder_list as $plugin_folder)
|
||||
{
|
||||
$file_list = JFolder::files(JPATH_SITE . '/plugins/' . $folder . '/' . $plugin_folder, '\.xml$');
|
||||
|
||||
foreach ($file_list as $file)
|
||||
{
|
||||
$manifest_details = JInstaller::parseXMLInstallFile(
|
||||
JPATH_SITE . '/plugins/' . $folder . '/' . $plugin_folder . '/' . $file
|
||||
);
|
||||
$file = JFile::stripExt($file);
|
||||
|
||||
if ($file == 'example')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore example plugins
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->set('type', 'plugin');
|
||||
$extension->set('client_id', 0);
|
||||
$extension->set('element', $file);
|
||||
$extension->set('folder', $folder);
|
||||
$extension->set('name', $file);
|
||||
$extension->set('state', -1);
|
||||
$extension->set('manifest_cache', json_encode($manifest_details));
|
||||
$extension->set('params', '{}');
|
||||
$results[] = $extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom discover_install method.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function discover_install()
|
||||
{
|
||||
/*
|
||||
* Plugins use the extensions table as their primary store
|
||||
* Similar to modules and templates, rather easy
|
||||
* If it's not in the extensions table we just add it
|
||||
*/
|
||||
$client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
|
||||
|
||||
if (is_dir($client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element))
|
||||
{
|
||||
$manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '/'
|
||||
. $this->parent->extension->element . '.xml';
|
||||
}
|
||||
else
|
||||
{
|
||||
$manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '.xml';
|
||||
}
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$description = (string) $this->parent->manifest->description;
|
||||
|
||||
if ($description)
|
||||
{
|
||||
$this->parent->set('message', JText::_($description));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->set('message', '');
|
||||
}
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($manifestPath);
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->state = 0;
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
$this->parent->extension->enabled = ('editors' == $this->parent->extension->folder) ? 1 : 0;
|
||||
$this->parent->extension->params = $this->parent->getParams();
|
||||
|
||||
if ($this->parent->extension->store())
|
||||
{
|
||||
return $this->parent->extension->get('extension_id');
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PLG_DISCOVER_STORE_DETAILS'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the extension table cache.
|
||||
*
|
||||
* @return boolean Result of operation, true if updated, false on failure.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function refreshManifestCache()
|
||||
{
|
||||
/*
|
||||
* Plugins use the extensions table as their primary store
|
||||
* Similar to modules and templates, rather easy
|
||||
* If it's not in the extensions table we just add it
|
||||
*/
|
||||
$client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
|
||||
$manifestPath = $client->path . '/plugins/' . $this->parent->extension->folder . '/' . $this->parent->extension->element . '/'
|
||||
. $this->parent->extension->element . '.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
|
||||
if ($this->parent->extension->store())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_PLG_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated class placeholder. You should use JInstallerAdapterPlugin instead.
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
* @deprecated 4.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class JInstallerPlugin extends JInstallerAdapterPlugin
|
||||
{
|
||||
}
|
661
libraries/cms/installer/adapter/template.php
Normal file
661
libraries/cms/installer/adapter/template.php
Normal file
@ -0,0 +1,661 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
jimport('joomla.base.adapterinstance');
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
/**
|
||||
* Template installer
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
*/
|
||||
class JInstallerAdapterTemplate extends JAdapterInstance
|
||||
{
|
||||
/**
|
||||
* Copy of the XML manifest file
|
||||
*
|
||||
* @var string
|
||||
* @since 3.1
|
||||
*/
|
||||
protected $manifest = null;
|
||||
|
||||
/**
|
||||
* Name of the extension
|
||||
*
|
||||
* @var string
|
||||
* @since 3.1
|
||||
* */
|
||||
protected $name = null;
|
||||
|
||||
/**
|
||||
* The unique identifier for the extension (e.g. mod_login)
|
||||
*
|
||||
* @var string
|
||||
* @since 3.1
|
||||
* */
|
||||
protected $element = null;
|
||||
|
||||
/**
|
||||
* Method of system
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected $route = 'install';
|
||||
|
||||
/**
|
||||
* Custom loadLanguage method
|
||||
*
|
||||
* @param string $path The path where to find language files.
|
||||
*
|
||||
* @return JInstallerTemplate
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function loadLanguage($path = null)
|
||||
{
|
||||
$source = $this->parent->getPath('source');
|
||||
|
||||
if (!$source)
|
||||
{
|
||||
$this->parent
|
||||
->setPath(
|
||||
'source',
|
||||
($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/templates/' . $this->parent->extension->element
|
||||
);
|
||||
}
|
||||
|
||||
$this->manifest = $this->parent->getManifest();
|
||||
$name = strtolower(JFilterInput::getInstance()->clean((string) $this->manifest->name, 'cmd'));
|
||||
$client = (string) $this->manifest->attributes()->client;
|
||||
|
||||
// Load administrator language if not set.
|
||||
if (!$client)
|
||||
{
|
||||
$client = 'ADMINISTRATOR';
|
||||
}
|
||||
|
||||
$extension = "tpl_$name";
|
||||
$lang = JFactory::getLanguage();
|
||||
$source = $path ? $path : ($this->parent->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/templates/' . $name;
|
||||
$lang->load($extension . '.sys', $source, null, false, false)
|
||||
|| $lang->load($extension . '.sys', constant('JPATH_' . strtoupper($client)), null, false, false)
|
||||
|| $lang->load($extension . '.sys', $source, $lang->getDefault(), false, false)
|
||||
|| $lang->load($extension . '.sys', constant('JPATH_' . strtoupper($client)), $lang->getDefault(), false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom install method
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
// Get a database connector object
|
||||
$db = $this->parent->getDbo();
|
||||
|
||||
$lang = JFactory::getLanguage();
|
||||
$xml = $this->parent->getManifest();
|
||||
|
||||
// Get the client application target
|
||||
if ($cname = (string) $xml->attributes()->client)
|
||||
{
|
||||
// Attempt to map the client to a base path
|
||||
$client = JApplicationHelper::getClientInfo($cname, true);
|
||||
|
||||
if ($client === false)
|
||||
{
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_UNKNOWN_CLIENT', $cname));
|
||||
|
||||
return false;
|
||||
}
|
||||
$basePath = $client->path;
|
||||
$clientId = $client->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No client attribute was found so we assume the site as the client
|
||||
$basePath = JPATH_SITE;
|
||||
$clientId = 0;
|
||||
}
|
||||
|
||||
// Set the extension's name
|
||||
$name = JFilterInput::getInstance()->clean((string) $xml->name, 'cmd');
|
||||
|
||||
$element = strtolower(str_replace(" ", "_", $name));
|
||||
$this->set('name', $name);
|
||||
$this->set('element', $element);
|
||||
|
||||
// Check to see if a template by the same name is already installed.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('template'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote($element));
|
||||
$db->setQuery($query);
|
||||
|
||||
try
|
||||
{
|
||||
$id = $db->loadResult();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_ROLLBACK'), $e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the template root path
|
||||
$this->parent->setPath('extension_root', $basePath . '/templates/' . $element);
|
||||
|
||||
// If it's on the fs...
|
||||
if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite() || $this->parent->isUpgrade()))
|
||||
{
|
||||
$updateElement = $xml->update;
|
||||
|
||||
// Upgrade manually set or update tag detected
|
||||
if ($this->parent->isUpgrade() || $updateElement)
|
||||
{
|
||||
// Force this one
|
||||
$this->parent->setOverwrite(true);
|
||||
$this->parent->setUpgrade(true);
|
||||
|
||||
if ($id)
|
||||
{
|
||||
// If there is a matching extension mark this as an update; semantics really
|
||||
$this->route = 'update';
|
||||
}
|
||||
}
|
||||
elseif (!$this->parent->isOverwrite())
|
||||
{
|
||||
// Overwrite is not set
|
||||
// If we didn't have overwrite set, find an update function or find an update tag so let's call it safe
|
||||
$this->parent
|
||||
->abort(
|
||||
JText::sprintf(
|
||||
'JLIB_INSTALLER_ABORT_TPL_INSTALL_ANOTHER_TEMPLATE_USING_DIRECTORY', JText::_('JLIB_INSTALLER_' . $this->route),
|
||||
$this->parent->getPath('extension_root')
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the template directory already exists, then we will assume that the template is already
|
||||
* installed or another template is using that directory.
|
||||
*/
|
||||
if (file_exists($this->parent->getPath('extension_root')) && !$this->parent->isOverwrite())
|
||||
{
|
||||
JLog::add(
|
||||
JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_ANOTHER_TEMPLATE_USING_DIRECTORY', $this->parent->getPath('extension_root')),
|
||||
JLog::WARNING, 'jerror'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the template directory does not exist, let's create it
|
||||
$created = false;
|
||||
|
||||
if (!file_exists($this->parent->getPath('extension_root')))
|
||||
{
|
||||
if (!$created = JFolder::create($this->parent->getPath('extension_root')))
|
||||
{
|
||||
$this->parent
|
||||
->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_FAILED_CREATE_DIRECTORY', $this->parent->getPath('extension_root')));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we created the template directory and will want to remove it if we have to roll back
|
||||
// the installation, let's add it to the installation step stack
|
||||
if ($created)
|
||||
{
|
||||
$this->parent->pushStep(array('type' => 'folder', 'path' => $this->parent->getPath('extension_root')));
|
||||
}
|
||||
|
||||
// Copy all the necessary files
|
||||
if ($this->parent->parseFiles($xml->files, -1) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->parent->parseFiles($xml->images, -1) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->parent->parseFiles($xml->css, -1) === false)
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse optional tags
|
||||
$this->parent->parseMedia($xml->media);
|
||||
$this->parent->parseLanguages($xml->languages, $clientId);
|
||||
|
||||
// Get the template description
|
||||
$this->parent->set('message', JText::_((string) $xml->description));
|
||||
|
||||
// Lastly, we will copy the manifest file to its appropriate place.
|
||||
if (!$this->parent->copyManifest(-1))
|
||||
{
|
||||
// Install failed, rollback changes
|
||||
$this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_TPL_INSTALL_COPY_SETUP'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
* Extension Registration
|
||||
* ---------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
$row = JTable::getInstance('extension');
|
||||
|
||||
if ($this->route == 'update' && $id)
|
||||
{
|
||||
$row->load($id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$row->type = 'template';
|
||||
$row->element = $this->get('element');
|
||||
|
||||
// There is no folder for templates
|
||||
$row->folder = '';
|
||||
$row->enabled = 1;
|
||||
$row->protected = 0;
|
||||
$row->access = 1;
|
||||
$row->client_id = $clientId;
|
||||
$row->params = $this->parent->getParams();
|
||||
|
||||
// Custom data
|
||||
$row->custom_data = '';
|
||||
}
|
||||
|
||||
// Name might change in an update
|
||||
$row->name = $this->get('name');
|
||||
$row->manifest_cache = $this->parent->generateManifestCache();
|
||||
|
||||
if (!$row->store())
|
||||
{
|
||||
// Install failed, roll back changes
|
||||
$this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_ROLLBACK', $db->stderr(true)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->route == 'install')
|
||||
{
|
||||
$debug = $lang->setDebug(false);
|
||||
|
||||
$columns = array($db->quoteName('template'),
|
||||
$db->quoteName('client_id'),
|
||||
$db->quoteName('home'),
|
||||
$db->quoteName('title'),
|
||||
$db->quoteName('params')
|
||||
);
|
||||
|
||||
$values = array(
|
||||
$db->quote($row->element), $clientId, $db->quote(0),
|
||||
$db->quote(JText::sprintf('JLIB_INSTALLER_DEFAULT_STYLE', JText::_($this->get('name')))),
|
||||
$db->quote($row->params) );
|
||||
|
||||
$lang->setDebug($debug);
|
||||
|
||||
// Insert record in #__template_styles
|
||||
$query->clear()
|
||||
->insert($db->quoteName('#__template_styles'))
|
||||
->columns($columns)
|
||||
->values(implode(',', $values));
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
// There is a chance this could fail but we don't care...
|
||||
$db->execute();
|
||||
}
|
||||
|
||||
return $row->get('extension_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom update method for components
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$this->route = 'update';
|
||||
|
||||
return $this->install();
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom uninstall method
|
||||
*
|
||||
* @param integer $id The extension ID
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function uninstall($id)
|
||||
{
|
||||
// First order of business will be to load the template object table from the database.
|
||||
// This should give us the necessary information to proceed.
|
||||
$row = JTable::getInstance('extension');
|
||||
|
||||
if (!$row->load((int) $id) || !strlen($row->element))
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_ERRORUNKOWNEXTENSION'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the template we are trying to uninstall a core one?
|
||||
// Because that is not a good idea...
|
||||
if ($row->protected)
|
||||
{
|
||||
JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_WARNCORETEMPLATE', $row->name), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$name = $row->element;
|
||||
$clientId = $row->client_id;
|
||||
|
||||
// For a template the id will be the template name which represents the subfolder of the templates folder that the template resides in.
|
||||
if (!$name)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_ID_EMPTY'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deny remove default template
|
||||
$db = $this->parent->getDbo();
|
||||
$query = "SELECT COUNT(*) FROM #__template_styles WHERE home = '1' AND template = " . $db->quote($name);
|
||||
$db->setQuery($query);
|
||||
|
||||
if ($db->loadResult() != 0)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_DEFAULT'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the template root path
|
||||
$client = JApplicationHelper::getClientInfo($clientId);
|
||||
|
||||
if (!$client)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_INVALID_CLIENT'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->parent->setPath('extension_root', $client->path . '/templates/' . strtolower($name));
|
||||
$this->parent->setPath('source', $this->parent->getPath('extension_root'));
|
||||
|
||||
// We do findManifest to avoid problem when uninstalling a list of extensions: getManifest cache its manifest file
|
||||
$this->parent->findManifest();
|
||||
$manifest = $this->parent->getManifest();
|
||||
|
||||
if (!($manifest instanceof SimpleXMLElement))
|
||||
{
|
||||
// Kill the extension entry
|
||||
$row->delete($row->extension_id);
|
||||
unset($row);
|
||||
|
||||
// Make sure we delete the folders
|
||||
JFolder::delete($this->parent->getPath('extension_root'));
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_INVALID_NOTFOUND_MANIFEST'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove files
|
||||
$this->parent->removeFiles($manifest->media);
|
||||
$this->parent->removeFiles($manifest->languages, $clientId);
|
||||
|
||||
// Delete the template directory
|
||||
if (JFolder::exists($this->parent->getPath('extension_root')))
|
||||
{
|
||||
$retval = JFolder::delete($this->parent->getPath('extension_root'));
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_UNINSTALL_TEMPLATE_DIRECTORY'), JLog::WARNING, 'jerror');
|
||||
$retval = false;
|
||||
}
|
||||
|
||||
// Set menu that assigned to the template back to default template
|
||||
$query = 'UPDATE #__menu'
|
||||
. ' SET template_style_id = 0'
|
||||
. ' WHERE template_style_id in ('
|
||||
. ' SELECT s.id FROM #__template_styles s'
|
||||
. ' WHERE s.template = ' . $db->quote(strtolower($name)) . ' AND s.client_id = ' . $clientId . ')';
|
||||
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$query = 'DELETE FROM #__template_styles WHERE template = ' . $db->quote($name) . ' AND client_id = ' . $clientId;
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$row->delete($row->extension_id);
|
||||
unset($row);
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover existing but uninstalled templates
|
||||
*
|
||||
* @return array JExtensionTable list
|
||||
*/
|
||||
public function discover()
|
||||
{
|
||||
$results = array();
|
||||
$site_list = JFolder::folders(JPATH_SITE . '/templates');
|
||||
$admin_list = JFolder::folders(JPATH_ADMINISTRATOR . '/templates');
|
||||
$site_info = JApplicationHelper::getClientInfo('site', true);
|
||||
$admin_info = JApplicationHelper::getClientInfo('administrator', true);
|
||||
|
||||
foreach ($site_list as $template)
|
||||
{
|
||||
if ($template == 'system')
|
||||
{
|
||||
// Ignore special system template
|
||||
continue;
|
||||
}
|
||||
$manifest_details = JInstaller::parseXMLInstallFile(JPATH_SITE . "/templates/$template/templateDetails.xml");
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->set('type', 'template');
|
||||
$extension->set('client_id', $site_info->id);
|
||||
$extension->set('element', $template);
|
||||
$extension->set('folder', '');
|
||||
$extension->set('name', $template);
|
||||
$extension->set('state', -1);
|
||||
$extension->set('manifest_cache', json_encode($manifest_details));
|
||||
$extension->set('params', '{}');
|
||||
$results[] = $extension;
|
||||
}
|
||||
|
||||
foreach ($admin_list as $template)
|
||||
{
|
||||
if ($template == 'system')
|
||||
{
|
||||
// Ignore special system template
|
||||
continue;
|
||||
}
|
||||
|
||||
$manifest_details = JInstaller::parseXMLInstallFile(JPATH_ADMINISTRATOR . "/templates/$template/templateDetails.xml");
|
||||
$extension = JTable::getInstance('extension');
|
||||
$extension->set('type', 'template');
|
||||
$extension->set('client_id', $admin_info->id);
|
||||
$extension->set('element', $template);
|
||||
$extension->set('folder', '');
|
||||
$extension->set('name', $template);
|
||||
$extension->set('state', -1);
|
||||
$extension->set('manifest_cache', json_encode($manifest_details));
|
||||
$extension->set('params', '{}');
|
||||
$results[] = $extension;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover_install
|
||||
* Perform an install for a discovered extension
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function discover_install()
|
||||
{
|
||||
// Templates are one of the easiest
|
||||
// If its not in the extensions table we just add it
|
||||
$client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
|
||||
$manifestPath = $client->path . '/templates/' . $this->parent->extension->element . '/templateDetails.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$description = (string) $this->parent->manifest->description;
|
||||
|
||||
if ($description)
|
||||
{
|
||||
$this->parent->set('message', JText::_($description));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parent->set('message', '');
|
||||
}
|
||||
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->state = 0;
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
$this->parent->extension->enabled = 1;
|
||||
|
||||
$data = new JObject;
|
||||
|
||||
foreach ($manifest_details as $key => $value)
|
||||
{
|
||||
$data->set($key, $value);
|
||||
}
|
||||
|
||||
$this->parent->extension->params = $this->parent->getParams();
|
||||
|
||||
if ($this->parent->extension->store())
|
||||
{
|
||||
$db = $this->parent->getDbo();
|
||||
|
||||
// Insert record in #__template_styles
|
||||
$lang = JFactory::getLanguage();
|
||||
$debug = $lang->setDebug(false);
|
||||
$columns = array($db->quoteName('template'),
|
||||
$db->quoteName('client_id'),
|
||||
$db->quoteName('home'),
|
||||
$db->quoteName('title'),
|
||||
$db->quoteName('params')
|
||||
);
|
||||
$query = $db->getQuery(true)
|
||||
->insert($db->quoteName('#__template_styles'))
|
||||
->columns($columns)
|
||||
->values(
|
||||
$db->quote($this->parent->extension->element)
|
||||
. ',' . $db->quote($this->parent->extension->client_id)
|
||||
. ',' . $db->quote(0)
|
||||
. ',' . $db->quote(JText::sprintf('JLIB_INSTALLER_DEFAULT_STYLE', $this->parent->extension->name))
|
||||
. ',' . $db->quote($this->parent->extension->params)
|
||||
);
|
||||
$lang->setDebug($debug);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
return $this->parent->extension->get('extension_id');
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_DISCOVER_STORE_DETAILS'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the extension table cache
|
||||
*
|
||||
* @return boolean Result of operation, true if updated, false on failure
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public function refreshManifestCache()
|
||||
{
|
||||
// Need to find to find where the XML file is since we don't store this normally.
|
||||
$client = JApplicationHelper::getClientInfo($this->parent->extension->client_id);
|
||||
$manifestPath = $client->path . '/templates/' . $this->parent->extension->element . '/templateDetails.xml';
|
||||
$this->parent->manifest = $this->parent->isManifest($manifestPath);
|
||||
$this->parent->setPath('manifest', $manifestPath);
|
||||
|
||||
$manifest_details = JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
|
||||
$this->parent->extension->manifest_cache = json_encode($manifest_details);
|
||||
$this->parent->extension->name = $manifest_details['name'];
|
||||
|
||||
try
|
||||
{
|
||||
return $this->parent->extension->store();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
JLog::add(JText::_('JLIB_INSTALLER_ERROR_TPL_REFRESH_MANIFEST_CACHE'), JLog::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated class placeholder. You should use JInstallerAdapterTemplate instead.
|
||||
*
|
||||
* @package Joomla.Libraries
|
||||
* @subpackage Installer
|
||||
* @since 3.1
|
||||
* @deprecated 4.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class JInstallerTemplate extends JInstallerAdapterTemplate
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user