Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[com_installer] [updatesites] Add options to delete and rebuild update sites #9744

Merged
merged 17 commits into from May 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 48 additions & 0 deletions administrator/components/com_installer/controllers/updatesites.php
Expand Up @@ -32,6 +32,8 @@ public function __construct($config = array())

$this->registerTask('unpublish', 'publish');
$this->registerTask('publish', 'publish');
$this->registerTask('delete', 'delete');
$this->registerTask('rebuild', 'rebuild');
}

/**
Expand Down Expand Up @@ -73,4 +75,50 @@ public function publish()

$this->setRedirect(JRoute::_('index.php?option=com_installer&view=updatesites', false));
}

/**
* Deletes an update site (if supported).
*
* @return void
*
* @since __DEPLOY_VERSION__
*
* @throws Exception on error
*/
public function delete()
{
// Check for request forgeries.
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

$ids = $this->input->get('cid', array(), 'array');

if (empty($ids))
{
throw new Exception(JText::_('COM_INSTALLER_ERROR_NO_UPDATESITES_SELECTED'), 500);
}

// Delete the records.
$this->getModel('Updatesites')->delete($ids);

$this->setRedirect(JRoute::_('index.php?option=com_installer&view=updatesites', false));
}

/**
* Rebuild update sites tables.
*
* @return void
*
* @since __DEPLOY_VERSION__
*/
public function rebuild()
{
// Check for request forgeries.
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

// Rebuild the update sites.
$this->getModel('Updatesites')->rebuild();

$this->setRedirect(JRoute::_('index.php?option=com_installer&view=updatesites', false));
}

}
249 changes: 249 additions & 0 deletions administrator/components/com_installer/models/updatesites.php
Expand Up @@ -121,6 +121,255 @@ public function publish(&$eid = array(), $value = 1)
return $result;
}

/**
* Deletes an update site.
*
* @param array $ids Extension ids to delete.
*
* @return void
*
* @since __DEPLOY_VERSION__
*
* @throws Exception on ACL error
*/
public function delete($ids = array())
{
$user = JFactory::getUser();

if (!$user->authorise('core.delete', 'com_installer'))
{
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 403);
}

// Ensure eid is an array of extension ids
if (!is_array($ids))
{
$ids = array($ids);
}

$db = JFactory::getDbo();
$app = JFactory::getApplication();

$count = 0;

// Gets the update site names.
$query = $db->getQuery(true)
->select($db->qn(array('update_site_id', 'name')))
->from($db->qn('#__update_sites'))
->where($db->qn('update_site_id') . ' IN (' . implode(', ', $ids) . ')');
$db->setQuery($query);
$updateSitesNames = $db->loadObjectList('update_site_id');

// Gets Joomla core update sites Ids.
$joomlaUpdateSitesIds = $this->getJoomlaUpdateSitesIds();

// Enable the update site in the table and store it in the database
foreach ($ids as $i => $id)
{
// Don't allow to delete Joomla Core update sites.
if (in_array((int) $id, $joomlaUpdateSitesIds))
{
$app->enqueueMessage(JText::sprintf('COM_INSTALLER_MSG_UPDATESITES_DELETE_CANNOT_DELETE', $updateSitesNames[$id]->name), 'error');
continue;
}

// Delete the update site from all tables.
try
{
$query = $db->getQuery(true)
->delete($db->qn('#__update_sites'))
->where($db->qn('update_site_id') . ' = ' . (int) $id);
$db->setQuery($query);
$db->execute();

$query = $db->getQuery(true)
->delete($db->qn('#__update_sites_extensions'))
->where($db->qn('update_site_id') . ' = ' . (int) $id);
$db->setQuery($query);
$db->execute();

$query = $db->getQuery(true)
->delete($db->qn('#__updates'))
->where($db->qn('update_site_id') . ' = ' . (int) $id);
$db->setQuery($query);
$db->execute();

$count++;
}
catch (RuntimeException $e)
{
$app->enqueueMessage(JText::sprintf('COM_INSTALLER_MSG_UPDATESITES_DELETE_ERROR', $updateSitesNames[$id]->name, $e->getMessage()), 'error');
}
}

if ($count > 0)
{
$app->enqueueMessage(JText::plural('COM_INSTALLER_MSG_UPDATESITES_DELETE_N_UPDATESITES_DELETED', $count), 'message');
}
}

/**
* Rebuild update sites tables.
*
* @return void
*
* @since __DEPLOY_VERSION__
*
* @throws Exception on ACL error
*/
public function rebuild()
{
$user = JFactory::getUser();

if (!$user->authorise('core.admin', 'com_installer'))
{
throw new Exception(JText::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_NOT_PERMITTED'), 403);
}

$db = JFactory::getDbo();
$app = JFactory::getApplication();

$clients = array(JPATH_SITE, JPATH_ADMINISTRATOR);
$extensionGroupFolders = array('components', 'modules', 'plugins', 'templates', 'language', 'manifests');

$pathsToSearch = array();

// Identifies which folders to search for manifest files.
foreach ($clients as $clientPath)
{
foreach ($extensionGroupFolders as $extensionGroupFolderName)
{
// Components, modules, plugins, templates, languages and manifest (files, libraries, etc)
if ($extensionGroupFolderName != 'plugins')
{
foreach (glob($clientPath . '/' . $extensionGroupFolderName . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath)
{
array_push($pathsToSearch, $extensionFolderPath);
}
}

// Plugins (another directory level is needed)
else
{
foreach (glob($clientPath . '/' . $extensionGroupFolderName . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $pluginGroupFolderPath)
{
foreach (glob($pluginGroupFolderPath . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath)
{
array_push($pathsToSearch, $extensionFolderPath);
}
}
}
}
}

// Gets Joomla core update sites Ids.
$joomlaUpdateSitesIds = implode(', ', $this->getJoomlaUpdateSitesIds());

// Delete from all tables (except joomla core update sites).
$query = $db->getQuery(true)
->delete($db->qn('#__update_sites'))
->where($db->qn('update_site_id') . ' NOT IN (' . $joomlaUpdateSitesIds . ')');
$db->setQuery($query);
$db->execute();

$query = $db->getQuery(true)
->delete($db->qn('#__update_sites_extensions'))
->where($db->qn('update_site_id') . ' NOT IN (' . $joomlaUpdateSitesIds . ')');
$db->setQuery($query);
$db->execute();

$query = $db->getQuery(true)
->delete($db->qn('#__updates'))
->where($db->qn('update_site_id') . ' NOT IN (' . $joomlaUpdateSitesIds . ')');
$db->setQuery($query);
$db->execute();

$count = 0;

// Search for updateservers in manifest files inside the folders to search.
foreach ($pathsToSearch as $extensionFolderPath)
{
$tmpInstaller = new JInstaller;

$tmpInstaller->setPath('source', $extensionFolderPath);

// Main folder manifests (higher priority)
$parentXmlfiles = JFolder::files($tmpInstaller->getPath('source'), '.xml$', false, true);

// Search for children manifests (lower priority)
$allXmlFiles = JFolder::files($tmpInstaller->getPath('source'), '.xml$', 1, true);

// Create an unique array of files ordered by priority
$xmlfiles = array_unique(array_merge($parentXmlfiles, $allXmlFiles));

if (!empty($xmlfiles))
{
foreach ($xmlfiles as $file)
{
// Is it a valid Joomla installation manifest file?
$manifest = $tmpInstaller->isManifest($file);

if (!is_null($manifest))
{
$query = $db->getQuery(true)
->select($db->qn('extension_id'))
->from($db->qn('#__extensions'))
->where($db->qn('name') . ' = ' . $db->q($manifest->name))
->where($db->qn('type') . ' = ' . $db->q($manifest['type']))
->where($db->qn('state') . ' != -1');
$db->setQuery($query);
$eid = (int) $db->loadResult();

if ($eid && $manifest->updateservers)
{
// Set the manifest object and path
$tmpInstaller->manifest = $manifest;
$tmpInstaller->setPath('manifest', $file);

// Load the extension plugin (if not loaded yet).
JPluginHelper::importPlugin('extension', 'joomla');

// Fire the onExtensionAfterUpdate
JEventDispatcher::getInstance()->trigger('onExtensionAfterUpdate', array('installer' => $tmpInstaller, 'eid' => $eid));

$count++;
}
}
}
}
}

if ($count > 0)
{
$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_SUCCESS'), 'message');
}
else
{
$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_WARNING'), 'warning');
}
}

/**
* Fetch the Joomla update sites ids.
*
* @return array Array with joomla core update site ids.
*
* @since __DEPLOY_VERSION__
*/
protected function getJoomlaUpdateSitesIds()
{
$db = JFactory::getDbo();

// Fetch the Joomla core Joomla update sites ids.
$query = $db->getQuery(true);
$query->select($db->qn('update_site_id'))
->from($db->qn('#__update_sites'))
->where($db->qn('location') . ' LIKE \'%update.joomla.org%\'');
$db->setQuery($query);

return $db->loadColumn();
}

/**
* Method to get the database query
*
Expand Down
Expand Up @@ -79,6 +79,17 @@ protected function addToolbar()
JToolbarHelper::divider();
}

if ($canDo->get('core.delete'))
{
JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'updatesites.delete', 'JTOOLBAR_DELETE');
JToolbarHelper::divider();
}

if ($canDo->get('core.admin') || $canDo->get('core.options'))
{
JToolbarHelper::custom('updatesites.rebuild', 'refresh.png', 'refresh_f2.png', 'JTOOLBAR_REBUILD', false);
}

JHtmlSidebar::setAction('index.php?option=com_installer&view=updatesites');

parent::addToolbar();
Expand Down
7 changes: 7 additions & 0 deletions administrator/language/en-GB/en-GB.com_installer.ini
Expand Up @@ -131,6 +131,13 @@ COM_INSTALLER_MSG_UPDATE_NOUPDATES="There are no updates available at the moment
COM_INSTALLER_MSG_UPDATE_SITES_COUNT_CHECK="Some update sites are disabled. You may want to check the <a href="_QQ_"%s"_QQ_">Update Sites Manager</a>."
COM_INSTALLER_MSG_UPDATE_SUCCESS="Updating %s was successful."
COM_INSTALLER_MSG_UPDATE_UPDATE="Update"
COM_INSTALLER_MSG_UPDATESITES_DELETE_ERROR="An error has occured while trying to delete "_QQ_"%s"_QQ_" update site: %s."
COM_INSTALLER_MSG_UPDATESITES_DELETE_CANNOT_DELETE="%s update site cannot be deleted."
COM_INSTALLER_MSG_UPDATESITES_N_DELETE_UPDATESITES_DELETED="%s update sites have been deleted."
COM_INSTALLER_MSG_UPDATESITES_N_DELETE_UPDATESITES_DELETED_1="1 update site has been deleted."
COM_INSTALLER_MSG_UPDATESITES_REBUILD_NOT_PERMITTED="Rebuilding update sites is not permitted."
COM_INSTALLER_MSG_UPDATESITES_REBUILD_WARNING="Update sites have been rebuilt. No extension with updates sites discovered."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure i this one is correct either - will need to find out exactly when it is displayed

COM_INSTALLER_MSG_UPDATESITES_REBUILD_SUCCESS="Update sites have been rebuilt from manifest files."
COM_INSTALLER_MSG_WARNINGFURTHERINFO="Further information on warnings"
COM_INSTALLER_MSG_WARNINGFURTHERINFODESC="For more information on warnings, see the <a href="_QQ_"https://docs.joomla.org"_QQ_" target="_QQ_"_blank"_QQ_">Joomla! Documentation Site</a>."
COM_INSTALLER_MSG_WARNINGS_FILEUPLOADISDISABLEDDESC="File uploads are required to upload extensions into the installer."
Expand Down