PHP Plugin für GLPI programmieren

Phil-DE

Cadet 3rd Year
Registriert
Okt. 2020
Beiträge
36
Mahlzeit zusammen!

Ich bin momentan dabei, bzw versuche ein Plugin für GLPI zu programmieren. Ich werde leider aus der Dokumentation und diversen Anleitungen leider nicht schlau draus...

Ich hab mich komplett an die Anleitungen und Dokumentationen gehalten. Mein Plugin kann erfolgreich installiert werden, aber sobald ich dieses installiert hab wird kein "Tab" angezeigt damit ich das Formular öffnen kann um dann mit meinem Plugin zu interagieren...

Hat jemand eine Idee woran es liegen kann?
Danke!

setup.php
Code:
<?php
    //Variablen Definition mit Plugin Informationen
    const PLUGIN_NAME = "Debitoren Plugin";
    const VERSION_NUMBER = "1.0";
    const AUTHOR = "Phil";
    const LICENSE = "GNU";
    const HOMEPAGE = "";
    const MINGLPIVERSION = "10.0.0";

    //Initialisierungsfunktion
    function plugin_init_debitoren()
    {
        global $PLUGIN_HOOKS;
        $Plugin = new Plugin();
        $PLUGIN_HOOKS['csrf_compliant']['debitoren'] = true;

        Plugin::registerClass('debitoren');
    }

    //Plugin Meta Daten festlegen
    function plugin_version_debitoren()
    {
        return array(
            "name"              =>  PLUGIN_NAME,
            "version"           =>  VERSION_NUMBER,
            "author"            =>  AUTHOR,
            "license"           =>  LICENSE,
            "homepage"          =>  HOMEPAGE,
            "minGlpiVersion"    =>  MINGLPIVERSION,
        );
    }

    //Überprüfung ob Server Anforderungen erfüllt sind
    function plugin_debitoren_check_prerequisites()
    {
        if(version_compare(GLPI_VERSION, MINGLPIVERSION, 'eq') || version_compare(GLPI_VERSION, MINGLPIVERSION, 'gt'))
        {
            return true;
        } else
        {
            echo "Das Plugin benötigt die Version " . MINGLPIVERSION . "! Installiert: " . GLPI_VERSION;
            return false;
        }
    }

    function plugin_debitoren_check_config()
    {
        return true;
    }

hook.php
PHP:
<?php
    function plugin_debitoren_install()
    {
        global $DB;

        $migrate = new Migration(100);

        //Check if Database Table exists
        if (!$DB->tableExists('glpi_plugin_debitoren_customer'))
        {
            $query = "CREATE TABLE glpi_plugin_customer_customer (
                id int(6) NOT NULL AUTO_INCREMENT,
                salutation varchar(255) NOT NULL,
                firstname varchar(255) NOT NULL,
                lastname varchar(255) NOT NULL,
                street varchar(255) NOT NULL,
                city varchar(255) NOT NULL,
                plz varchar(255) NOT NULL,
                country varchar(255) NOT NULL,
                primary key (id));";
            $DB->queryOrDie($query, $DB->error());
        }

        $migrate->executeMigration();
        return true;
    }

    function plugin_debitoren_uninstall()
    {
        global $DB;

        $tables = [
            'customer'
        ];

        foreach ($tables as $table) {
            $tablename = 'glpi_plugin_debitoren_' . $table;

            if ($DB->tableExists($tablename)) {
                $DB->queryOrDie(
                    "DROP TABLE `$tablename`",
                    $DB->error()
                );
            }
        }
        return true;
    }

inc/debitoren.class.php
PHP:
<?php
class PluginDebitorenAddNewDebitor extends CommonDBTM
{
    public function showForm($ID, $options = [])
    {
        global $CFG_GLPI;

        $this->initForm($ID, $options);
        $this->showFormHeader($options);

        if (!isset($options['display']))
        {
            // Standard Darstellung
            $options['display'] = true;
        }

        $params = $options;
        // Standardgemäß werden nicht alle Elemente angezeigt. Hier werden diese angezeigt oder zurückgegeben
        $params['display'] = false;

        $out = '<tr>';
        $out .= '<th>' . __('Debitoren hinzufügen', 'debitoren') . '</th>';

        $objectName = autoName(
            $this->fields["name"],
            "name",
            (isset($options['withtemplate']) && $options['withtemplate'] == 2),
            $this->getType(),
            $this->fields["entities_id"]
        );
        $out .= '<td>';
        $out .= Html::automcompletionTextField(
            $this,
            'name',
            [
                'value' => $objectName,
                'display' => false
            ]
        );
        $out .= '</td>';
        $out .= $this->showFormButtons($params);

        if ($options['display'])
        {
            echo $out;
        }
        else
        {
            return $out;
        }
    }
}

front/addnewdebitor.php
PHP:
<?php
include ("../../../inc/includes.php");

// Überprüfe ob das Plugin aktiviert ist
$plugin = new Plugin();
if (!$plugin->isInstalled('debitoren') || !$plugin->isActivated('debitoren')) {
   Html::displayNotFoundError();
}

// Überprüfe die Zugriffsrechte
if (PluginDebitorenAddNewDebitor::canView())
{
    //Berechtigung vorhanden, zeige Liste an

    //Füge Seitenüberschrift hinzu
    Html::header(
        __('Debitoren', 'debitoren'),
        $_SERVER['PHP_SELF'],
        'assets',
        'PluginDebitorenAddNewDebitor',
        'addnewdebitor'
    );

    Search::show('PluginDebitorenAddNewDebitor');

    Html::footer();
} else
{
    //Keine Berechtigung, zeige Fehlermeldung
    Html::displayRightError();
}

front/addnewdebitor.form.php
PHP:
<?php
include ("../../../inc/includes.php");

// Überprüfe ob das Plugin installiert und aktiviert ist
$plugin = new Plugin();
if (!$plugin->isInstalled('debitoren') || !$plugin->isActivated('debitoren')) {
   Html::displayNotFoundError();
}

$object = new PluginDebitorenAddNewDebitor();

if (isset($_POST['add']))
{
    // Überprüfe Create Rechte
    $object->check(-1, CREATE, $_POST);
    // Erstelle Objekt
    $newid = $object->add($_POST);
    // Navigiere zum neuen Objekt
    Html::redirect("{CFG_GLPI['root_doc']}/plugins/debitoren/front/debitor.form.php?id={$newid}");
} else if (isset($_POST['update']))
{
    // Überprüfe die Update Berechtigung
    $object->check($_POST['id'], UPDATE);
    // Aktualisiere Objekt
    $object->update($_POST);
    // Navigiere zum Objekt
    Html::back();
}
else if (isset($_POST['delete']))
{
    // Überprüfe die Delete Berechtigung
    $object->check($_POST['id'], DELETE);
    // Entferne Objekt
    $object->delete($_POST);
    // Navigiere zurück zur Übersicht
    $object->redirectToList();
}
else if (isset($_POST['purge']))
{
    // Überprüfe Purge Berechtigung
    $object->check($_POST['id'], PURGE);
    // Lösche Objekt
    $object->delete($_POST, 1);
    // Navigiere zur Objektübersicht
    Html::redirect("{$CFG_GLPI['root_doc']}/plugins/debitoren/front/debitor.php");
} else
{
    // Standard Display
    $withtemplate = (isset($_GET['withtemplate']) ? $_GET['withtemplate'] : 0);
    $object->display(
        [
          'id' => $_GET['id'],
          'withtemplate' => $withtemplate
        ]
    );
}
 
Ich habe persönlich null Ahnung von der Software. Gibt es Meldungen? Log Level erhöht? Hast du einen Trace gemacht? Breakpoints? Wäre meine Herangehensweise.

Wenn der Tab angezeigt wird, ist dein Plugin wohl installiert.
Grundsätzlich würde ich bei neuen Sachen erstmal so wenig Komplexität wie möglich reinbringen und nur das wesentliche testen. Also Tab + Ausgabe und mich im Nachhinein um Datenbank etc. kümmern. Wenn das Error handling sehr restriktiv ist, könnte das schon der Grund sein.
 
  • Gefällt mir
Reaktionen: Murray B. und Der Lord
Schonmal Danke für deine Antwort!

Bisher hab ich keine Fehlermeldungen oder dergleichen gefunden. Angeblich funktioniert alles wie es soll... Aber die Anwendung soll halt als "Tab" in dem Webinterface auftauchen. Das tut die leider nicht...

Und den Code den ich da habe, ist laut der Dokumentation die Minimalfassung. Abgesehen von der Datenbank.

Aber daran wird es aufjedenfall nicht liegen...
 
Hast du denn überhaupt Code für den Tab selbst geschrieben? Fehlt der Code oder hast du ihn hier nicht gepostet? Ref: https://glpi-developer-documentation.readthedocs.io/en/master/plugins/tips.html
Man geht davon aus, das du in deiner registrierten Klasse auch die hook Funktionen bereitgestellt hast dafür.
Gleichzeitig muss man auch angeben, an welches vorhandene Element der Tab angehängt werden soll.

In deiner setup.php
Code:
 Plugin::registerClass('debitoren');
fehlt die Angabe wo.
Ich finde die Dokumentation von GLPI jetzt nicht so prickelnd jetzt, da teilweise auch widersprüchlich (die Autoren halten sich in ihren Beispielen nicht an ihre eigenen Konventionen)
Ein Beispiel wo man es sehr gut sehen kann, wie man das Plugin strukturiert: https://github.com/yllen/reports
(dort in in der setup.php und entsprechend in /inc/profile.class.php ist eine Klasse mit Tab)

Bei dir dann also z.b. so:
Plugin[Name des Plugins][Name der Klasse]
Beispiel:
Code:
Plugin::registerClass('PluginDebitorenAddNewDebitor', ['addtabon' => 'wohin'])

Auf dem Dateisystem: {glpiroot}/plugins/debitoren/inc/addnewdebitor.class.php
In addnewdebitor.class.php:
Code:
class PluginDebitorenAddNewDebitor extends CommonDBTM { ... }
stimmt dann ja soweit.
Die getTabNameForItem() und displayTabContentForItem()-Methoden gehören in die Klasse für die ein Tab gemacht werden soll rein, also dann z.B. dort.

Der Grund also weswegen das so nicht funktioniert (hast du Debug aktiv?), ist das er eine Klasse 'debitoren' erwartet, weil du sie so registriert hast, er an der Stelle aber keinen Dateinamen sondern einen Klassennamen erwartet. Das mit den o.a. Dateinamen ist Konvention, sorgt aber für eine deutlich bessere Struktur.
Gleichzeitig gib es nichts anzuzeigen, da die einzige Klasse nur als Hilfsklasse registriert ist. Gibst du nicht an wo etwas als Tab hinzugefügt werden soll, wird auch nicht versucht irgendwelche Hooks aufzurufen, ergo kann auch keine Exception auftreten.

Hier noch ein Tutorial, wo man die Implementation eines Tabs sehen kann: https://www.neteye-blog.com/2016/12/tutorial-erstellen-eines-glpi-plugins/
Ist alt, aber das Prinzip hat sich wohl nicht geändert.
 
  • Gefällt mir
Reaktionen: Testa2014
Erstmal vielen Dank @lokked !

Klingt aufjedenfall schlüssig... Stehe leider noch auf dem Schlauch...
Ich hab jetzt eben mal versucht mit einem kleineren "Test Plugin" das mal nachzuvollziehen aber das trägt leider immer noch keine Früchte.

Ich habe jetzt den Klassennamen registriert, und das addtabon hinzugefügt. Als auch die Methoden in der Klasse eingefügt und bisschen bearbeitet...

Ich vermute ich mache immer noch was falsch... Debug hab ich an, gibt mir leider nur nichts passendes aus...

setup.php
PHP:
<?php
// Definiere Variablen mit Plugin Informationen
define("PLUGIN_NAME", "Spiele");
define("VERSION_NUMBER", "1.0.0");


// Erstelle Initialisierungsfunktion des Plugins
function plugin_init_spiele()
{
    global $PLUGIN_HOOKS;
    $PLUGIN_HOOKS['csrf_compliant']['spiele'] = true;

    Plugin::registerClass('SpieleClass', array('addtabon' => 'Computer'));
}

// Definiere Plugin Informationen
function plugin_version_spiele()
{
    return array(
        "name"  =>  PLUGIN_NAME,
        "version" => VERSION_NUMBER,
        "author"=>  "Phil",
        "license" => "LIZENZ",
        "homepage" => "google.de",
        "minGlpiVersion" => "10.0.0"
    );
}

//Überprüfe ob Anforderungen für das Plugin erfüllt sind
function plugin_spiele_check_prerequisites()
{
    if(version_compare(GLPI_VERSION, '10', 'eq') || version_compare(GLPI_VERSION, '10', 'gt'))
    {
        return true;
    } else {
        echo "Das Plugin benötigt die Version 10.0.0 | Installiert ist Version: " . GLPI_VERSION;
        return false;
    }
}

//Überprüfe ob die Konfiguration übereinstimmt
function plugin_spiele_check_config()
{
    return true;
}

hook.php
PHP:
<?php
function plugin_spiele_install()
{
    return true;
}

function plugin_spiele_uninstall()
{
    return true;
}

Spiele.class.php
Code:
<?php
class SpieleClass extends CommonDBTM
{
    function getTabNameForItem(CommonGLPI $item, $withtemplate=0)
    {
        return self::createTabEntry('Spiele');
    }

    static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0)
    {
        ?>
        <form action="../plugins/spiele/front/clone.form.php" method="post">
            <? echo Html::hidden('id', array('value' => $item->getID())); ?>
            <? echo Html::hidden('_glpi_csrf_token', array('value' => Session::getNewCSRFToken())); ?>
            <div class="spaced" id="tabsbody">
                <table class="tab_cadre_fixe">
                    <tr class="tab_bg_1">
                        <td>
                            Welches Spiel: &nbsp;&nbsp;&nbsp;
                            <input type="text" name="name" size="40" class="ui-autocomplete-input" autocomplete="off"> &nbsp;&nbsp;&nbsp;
                            <input type="submit" class="submit" value="CLONE" name="clone"/>
                        </td>
                    </tr>
                </table>
            </div>
        </form>
        <?
        return true;
    }

}
 
Zurück
Oben