这是@Elin建议的无错误/无错版本(以防有人想进一步讨论)。这个解决方案对我来说不起作用,但我认为它有其道理。
<?php
/**
* A JApplicationCli application built on the Joomla Platform
*
* To run this place it in the cli folder of your Joomla CMS installation (or adjust the references).
*
* @package Joomla.CleanupFailedInsall
* @copyright Copyright (C) 2013 Open Source Matters. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
/*
* This application cleans up database leftovers from a failed install
*
* To run from the command line type
* php cleanupfailedinstall.php -e='extensionname'
*/
if (!defined('_JEXEC'))
{
// Initialize Joomla framework
define('_JEXEC', 1);
}
@ini_set('zend.ze1_compatibility_mode', '0');
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Load system defines
if (file_exists(dirname(__DIR__) . '/defines.php'))
{
require_once dirname(__DIR__) . '/defines.php';
}
if (!defined('JPATH_BASE'))
{
define('JPATH_BASE', dirname(__DIR__));
}
if (!defined('_JDEFINES'))
{
require_once JPATH_BASE . '/includes/defines.php';
}
// Get the framework.
require_once JPATH_LIBRARIES . '/import.php';
// Get the framework.
//require_once JPATH_LIBRARIES . '/import.legacy.php';
// Bootstrap the CMS libraries.
require_once JPATH_LIBRARIES . '/cms.php';
// Import the configuration.
require_once JPATH_CONFIGURATION . '/configuration.php';
// Uncomment this if you want to log
/*
// Include the JLog class.
jimport('joomla.log.log');
// Add the logger.
JLog::addLogger(
// Pass an array of configuration options
array(
// Set the name of the log file
'text_file' => 'test.log.php',
// (optional) you can change the directory
'text_file_path' => 'logs'
)
);
// start logging...
JLog::add('Starting to log');
*/
/**
* Cleanup Failed Install
*
* @package Joomla.Shell
*
* @since 1.0
*/
class CleanupFailedInstall extends JApplicationCli
{
public function __construct()
{
// Note, this will throw an exception if there is an error
// System configuration.
$config = new JConfig;
// Creating the database connection.
$this->db = JDatabase::getInstance(
array(
'driver' => $config->dbtype,
'host' => $config->host,
'user' => $config->user,
'password' => $config->password,
'database' => $config->db,
'prefix' => $config->dbprefix,
)
);
// Call the parent __construct method so it bootstraps the application class.
parent::__construct();
require_once JPATH_CONFIGURATION . '/configuration.php';
}
/**
* Entry point for the script
*
* @return void
*
* @since 1.0
*/
public function execute()
{
// Long args
$extensionname = $this->input->get('extensionname', 'urlaubsrechner', 'STRING');
// Short args
if (!$extensionname)
{
$extensionname = $this->input->get('e', null, 'STRING');
}
require_once JPATH_LIBRARIES . '/joomla/database/table/extension.php';
$extensionTable = new JTableExtension($this->db);
$extensionId = $extensionTable->find(array('name' => $extensionname));
if (! $extensionId)
{
throw new Exception('Could not find extension with name: ' . $extensionname);
}
// This block taken from the platform component install adapter with minor modifications
// Remove the schema version
$query = $this->db->getQuery(true)
->delete('#__schemas')
->where('extension_id = ' . $extensionId);
$this->db->setQuery($query);
$this->db->execute();
// Remove the component container in the assets table.
$asset = JTable::getInstance('Asset');
if ($asset->loadByName($extensionname))
{
$asset->delete();
}
$extensionTable->delete($extensionId);
$this->_removeAdminMenus($extensionId);
// Remove categories for this component
$query->clear()
->delete('#__categories')
->where('extension=' . $this->db->quote($extensionname), 'OR')
->where('extension LIKE ' . $this->db->quote($extensionname . '.%'));
$this->db->setQuery($query);
$this->db->execute();
// Clobber any possible pending updates
$update = JTable::getInstance('update');
$uid = $update->find(array('element' => $extensionTable->element, 'type' => 'component', 'client_id' => 1, 'folder' => ''));
if ($uid)
{
$update->delete($uid);
}
}
/**
* Taken from the core installer component adapter
* Method to remove admin menu references to a component
*
* @param object &$row Component table object.
*
* @return boolean True if successful.
*
* @since 3.1
*/
protected function _removeAdminMenus($extensionId)
{
$db = JFactory::getDbo();
$table = JTable::getInstance('menu');
// Get the ids of the menu items
$query = $db->getQuery(true)
->select('id')
->from('#__menu')
->where($db->quoteName('client_id') . ' = 1')
->where($db->quoteName('component_id') . ' = ' . (int) $extensionId);
$db->setQuery($query);
$ids = $db->loadColumn();
// Check for error
if (!empty($ids))
{
// Iterate the items to delete each one.
foreach ($ids as $menuid)
{
if (!$table->delete((int) $menuid))
{
$this->setError($table->getError());
return false;
}
}
// Rebuild the whole tree
$table->rebuild();
}
return true;
}
}
JApplicationCli::getInstance('CleanupFailedInstall')->execute();