Question

When trying to install a component I am getting this error.

Component Install: DB function reports no errors

Error installing component

Was it helpful?

Solution

I am getting this error quite often on a test system when trying to install a component which uses SQL updates and causes first time when installing an error (even not SQL related, such a missing file from the manifest file).

Here are some steps on how to fix this, by manually uninstalling the component, as from the Extension manager the installation may / will fail.

Find the id of your extension (you may also find multiple entries)

SELECT * 
FROM  `#__extensions` 
WHERE  `name` LIKE  '%myextensionname%'
LIMIT 0 , 30

Remove from #__schemas the entries for extension, where extension_id is the previous found id. Remove also any entries for non existing extensions:

Remove any assets for your extension:

SELECT * 
FROM  `#__assets` 
WHERE  `name` LIKE  '%myextensionname%'
LIMIT 0 , 30

Remove any menu entries:

SELECT * FROM #__menu WHERE link LIKE '%myextensionname%' LIMIT 0 , 30

Reinstall.

OTHER TIPS

Not tested but this is the general idea I would use.

<?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 doExecute()
    {
        // Long args
        $extensionname = $this->input->get('extensionname', null,'STRING');

        // Short args
        if (!$extensionname)
        {
            $extensionname = $this->input->get('e', null, 'STRING');
        }

        $extensionTable = new JTableExtension();
        $extensionId = $extensionTable->find(array('name', $extensionname));

        // This block taken from the platform component install adapter with minor moifications
        // Remove the schema version
        $query = $db->getQuery(true)
            ->delete('#__schemas')
            ->where('extension_id = ' . $extensionId);
        $db->setQuery($query);
        $db->execute();

        // Remove the component container in the assets table.
        $asset = JTable::getInstance('Asset');

        if ($asset->loadByName($extensionname))
        {
            $asset->delete();
        }

        $extenstionTable->delete($extensionId);
            $this->removeAdminMenus($extensionId);

        // Remove categories for this component
        $query->clear()
            ->delete('#__categories')
            ->where('extension=' . $db->quote($exensionname), 'OR')
            ->where('extension LIKE ' . $db->quote($extensionname . '.%'));
        $db->setQuery($query);
        $db->execute();

        // Clobber any possible pending updates
        $update = JTable::getInstance('update');
        $uid = $update->find(array('element' => $row->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();

This an error / typo free version of what @Elin proposed (in case somebody wants to take this further). This solution did NOT work for me, but I think it has something in it.

<?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();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top