Skip to content

Fail to uninstall the plugin #111

Description

@bontiv

Uninstalling the addressing plugin via the GLPI Marketplace interface (or via php bin/console plugin:uninstall addressing) throws an uncaught RuntimeException and leaves the plugin in a broken state.

Error

RuntimeException: MySQL query error: Table 'glpi.glpi_plugin_addressing_addressings' doesn't exist (1146)
in SQL query "SHOW COLUMNS FROM glpi_plugin_addressing_addressings"
at DBmysql.php line 416

Full stack trace:

./src/DBmysql.php:416
./src/DBmysql.php:942                DBmysql->doQuery()
./src/CommonDBTM.php:669             DBmysql->listFields()
./src/CommonDBTM.php:3261            CommonDBTM->getEmpty()
./src/CommonDBTM.php:5411            CommonDBTM->maybeDeleted()
./src/Profile.php:3528               CommonDBTM->getRights()
./marketplace/addressing/src/Profile.php:56   Profile::getRightsFor()
./marketplace/addressing/hook.php:311         GlpiPlugin\Addressing\Profile::getAllRights()
./src/Plugin.php:1144                         plugin_addressing_uninstall()

Steps to Reproduce

Install and activate the addressing plugin
Attempt to uninstall it via the Marketplace UI or php bin/console plugin:uninstall addressing
Observe the RuntimeException in files/_log/php-errors.log
Root Cause
In hook.php, plugin_addressing_uninstall() has an incorrect operation order:

Current (broken) order:

// 1. Tables are dropped FIRST
foreach ($tables as $table) {
    $migration->dropTable($table); // glpi_plugin_addressing_addressings is gone here
}

// 2. THEN rights cleanup is attempted — but it crashes
foreach (Profile::getAllRights() as $right) { // ← CRASH
    $profileRight->deleteByCriteria(['name' => $right['field']]);
}

Why it crashes:

Profile::getAllRights() (in src/Profile.php) calls \Profile::getRightsFor(Addressing::class), which internally calls getItemForItemtype() → new Addressing() → CommonDBTM->getRights() → CommonDBTM->getEmpty() → DBmysql->listFields() → SHOW COLUMNS FROM glpi_plugin_addressing_addressings — but that table was already dropped in step 1.

Consequences

The uninstall function never completes, leaving the plugin in a broken state (state=1 ACTIVATED in glpi_plugins but with no tables)
After reinstalling, the plugin configuration page is inaccessible (glpi_plugin_addressing_configs is missing)
A residual plugin_addressing_use_ping_in_equipment right entry may remain in glpi_profilerights

Fix

Move all rights/data cleanup before the dropTable() calls:

function plugin_addressing_uninstall()
{
    global $DB;

    $migration = new Migration(PLUGIN_ADDRESSING_VERSION);
    $tables    = [
        "glpi_plugin_addressing_addressings",
        "glpi_plugin_addressing_configs",
        "glpi_plugin_addressing_filters",
        "glpi_plugin_addressing_pinginfos",
        "glpi_plugin_addressing_ipcomments"
    ];

    $itemtypes = ['DisplayPreference', 'SavedSearch'];
    foreach ($itemtypes as $itemtype) {
        $item = new $itemtype;
        $item->deleteByCriteria(['itemtype' => Addressing::class]);
    }

    // Must be done BEFORE dropping tables: Profile::getAllRights() instantiates
    // the Addressing class, which triggers SHOW COLUMNS on its table.
    $profileRight = new ProfileRight();
    foreach (Profile::getAllRights() as $right) {
        $profileRight->deleteByCriteria(['name' => $right['field']]);
    }

    Profile::removeRightsFromSession();
    CronTask::unregister("addressing");

    // Drop tables last, after all references have been cleaned
    foreach ($tables as $table) {
        $migration->dropTable($table);
    }

    return true;
}

Environment

GLPI version: 11.x
Plugin version: 3.2.4
PHP version: 8.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions