Benutzer-Werkzeuge

Webseiten-Werkzeuge


redmine:api

Redmine Rest-API

Die meisten Funktionen von Redmine lassen sich auch über eine Rest-API ansprechen. Hierbei wurden Funktionen für die wichtigsten Bereiche Tickets, Projekte, Benutzer und Zeiterfassung aktuell in einer stabilen Version eingestuft. Funktionen in anderen Bereichen wie z. B. News, Wiki, Gruppen usw. befinden sich derzeit noch in Beta, Alpha oder sogar Prototype-Status. Eine vollständige Auflistung gibt es hier.

Beispiel: Tickets

In diesem Beispiel wird der wohl wichtigste Bereich für die API beschrieben: Die Tickets. Durch die Ressource „Issue“ können Ticktes angelegt, gelesen, geändert und auch gelöscht werden. Ein typisches Anwendungsbeispiel ist die Integration in die Webseite, um Kundenanfragen vom Typ „Fehler“ und „Verbesserungsvorschlag“ automatisch direkt in ein Ticket umzuwanden.

Es ist empfehlenswert für die API einen eigenen Benutzer in Redmine anzulegen und diesem neuen Benutzer auch die Projekte zuzuordnen, auf die mit der API zugegriffen werden sollen, da der vorinstallierte admin Berechtigungen über alle Projekte hat.

Die Variable „key“ muss durch den API-Zugriffsschlüssel ersetzt werden der in Redmine unter „Mein Konto“ auf der rechten Seite angezeigt wird.

Redmine-Ticket-Klasse

class.Redmine.php
class Redmine
{
    private $service_url    = 'http://meine-domain.de:3000/';
    private $key            = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
 
    public function createIssue( redmineIssueModel $issueModel )
    {
        $issue = array('issue' => $issueModel );
        $curl_post_data = json_encode( $issue );
 
        $curl = curl_init( $this->service_url . 'issues.json?key=' . $this->key );
        curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
        curl_setopt( $curl, CURLOPT_POST, true );
        curl_setopt( $curl, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json') );
        curl_setopt( $curl, CURLOPT_POSTFIELDS, $curl_post_data );
        $result = $this->execute( $curl );
        return $result->issue->id;
    }
 
    /**
     * @param integer $id
     * @return models\redmineIssueModel
     * @throws Exception
     */
    public function getIssue( $id )
    {
        $curl = curl_init( $this->service_url . 'issues/' . $id . '.json?key=' . $this->key );
        curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
        curl_setopt( $curl, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json') );
        curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, "GET");
        $result = $this->execute( $curl );
 
        if( $result === null )
        {
            return null;
        }
 
        $issueModel                 = new models\redmineIssueModel();
        $issueModel->subject        = $result->issue->subject;
        $issueModel->description    = $result->issue->description;
        $issueModel->done_ratio     = $result->done_ratio;
        $issueModel->assigned_to_id = $result->issue->assigned_to->id;
        $issueModel->priority_id    = $result->issue->priority->id;
        $issueModel->status_id      = $result->issue->status->id;
        $issueModel->tracker_id     = $result->issue->tracker->id;
        return $issueModel;
    }
 
    /**
     * @param redmineIssueModel $issueModel
     * @param integer $id
     * @return bool
     * @throws Exception
     */
    public function updateIssue( redmineIssueModel $issueModel, $id )
    {
        $issue = array('issue' => $issueModel );
        $curl_post_data = json_encode( $issue );
 
        $curl = curl_init( $this->service_url . 'issues/' . $id . '.json?key=' . $this->key );
        curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
        curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt( $curl, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json') );
        curl_setopt( $curl, CURLOPT_POSTFIELDS, $curl_post_data );
        $result = $this->execute( $curl );
 
        if( $result === '' )
        {
            return true;
        }
 
        return false;
    }
 
    /**
     * @param integer $id
     * @return bool
     * @throws Exception
     */
    public function deleteIssue( $id )
    {
        $curl = curl_init( $this->service_url . 'issues/' . $id . '.json?key=' . $this->key );
        curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
        curl_setopt( $curl, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json') );
        curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, "DELETE");
        $result = $this->execute( $curl );
 
        if( $result === '' )
        {
            return true;
        }
 
        return false;
    }
 
    /**
     * @param  $curl
     * @return mixed
     * @throws Exception
     */
    private function execute( $curl )
    {
        $curl_response = curl_exec( $curl );
 
        if( $curl_response === false )
        {
            curl_close( $curl );
            throw new \Exception( 'Service Unavailable', 503 );
        }
 
        curl_close( $curl );
        $decoded = json_decode( $curl_response );
 
        if( isset( $decoded->error ) )
        {
            throw new \Exception( $decoded->error, $decoded->status );
        }
 
        return $decoded;
    }
}

Redmine-Ticket-Model

RedmineIssue.php
class RedmineIssue
{
    const TRACKER_BUG=1, TRACKER_FEATURE=2, TRACKER_SUPPORT=3;
    const PRIO_NIEDRIG=1, PRIO_NORMAL=2, PRIO_HOCH=3, PRIO_DRINGEND=4, PRIO_SOFORT=5;
    const STATUS_NEU=1, STATUS_ZUGEWIESEN=2, STATUS_GELOEST=3;
    const STATUS_RUECKFRAGE=4, STATUS_ERLEDIGT=5, STATUS_ABGEWIESEN=6;
 
    public $project_id      = 1;
    public $subject         = '';
    public $description     = '';
    public $category_id     = NULL;
    public $done_ratio      = 0;    // % erledigt
    public $tracker_id      = 2;
    public $priority_id     = 2;
    public $status_id       = 1;
    public $assigned_to_id  = NULL;
    public $is_private      = false;
    public $notes           = '';
    public $private_notes   = false;
}

Für die nachfolgenden Beispiele müssen die beiden Dateien oben eingebunden werden und eine Instanz der Klasse „Redmine“ erstellt werden:

include 'class.Redmine.php';
include 'redmineIssueModel.php';
 
$rm = new Redmine();

Neues Ticket anlegen

$issue = new redmineIssueModel();
$issue->description = 'Redmine Rest-API in das Support-Formular integrieren';
$issue->subject = 'Redmine Rest-API';
$issue->tracker_id = $issue::TRACKER_FEATURE;
$issue->assigned_to_id = 1;
 
$id = $rm->createIssue( $issue );
echo "Ticket mit der ID " . $id . " angelegt.";

Vorhandenes Ticket auslesen und ändern

$issue = $rm->getIssue( $id );
$issue->done_ratio  = 50; // 50 % erledigt
$issue->status_id   = $issue::STATUS_ZUGEWIESEN;
$issue->priority_id = $issue::PRIO_HOCH;
$issue->notes       = 'Die hälfte schon umgesetzt';
 
$rm->updateIssue( $issue, $id );

Vorhandenes Ticket löschen

if( $rm->deleteIssue( $id ) )
{
    echo "Ticket " . $id . " gelöscht";
}
redmine/api.txt · Zuletzt geändert: 2020/10/21 16:47 von webproducer