first commit

This commit is contained in:
alazhar
2020-01-02 22:20:31 +07:00
commit 10eb3340ad
5753 changed files with 631345 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View 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
{
}

View File

@ -0,0 +1 @@
<!DOCTYPE html><title></title>

View 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
{
}

View 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
{
}

File diff suppressed because it is too large Load Diff

View 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
{
}

View 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
{
}

View 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
{
}