Skip to content
Snippets Groups Projects
Commit f60319f8 authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms
Browse files

fixes #14

parent c4e1f6f1
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,62 @@ require_once __DIR__ . '/bootstrap.php';
final class TracToGitlabPlugin extends StudIPPlugin implements StandardPlugin, SystemPlugin
{
private $container = null;
public function __construct()
{
parent::__construct();
if (!is_object($GLOBALS['user']) || $GLOBALS['user']->id === 'nobody') {
return;
}
$this->buildNavigation();
}
public function getDIContainer()
{
if ($this->container === null) {
require_once __DIR__ . '/vendor/autoload.php';
$this->container = new Pimple\Container();
$this->container['trac'] = function () {
return new TracToGitlab\TracLookup(Config::get()->TRAC2GITLAB_TRAC_URL);
};
$this->container['gitlab'] = function () {
$builder = new Gitlab\HttpClient\Builder(
new GuzzleHttp\Client(),
new Http\Factory\Guzzle\RequestFactory(),
new Http\Factory\Guzzle\StreamFactory(),
new Http\Factory\Guzzle\UriFactory()
);
$client = new Gitlab\Client($builder);
$client->setUrl(Config::get()->TRAC2GITLAB_GITLAB_URL);
$client->authenticate(Config::get()->TRAC2GITLAB_GITLAB_TOKEN, Gitlab\Client::AUTH_HTTP_TOKEN);
return $client;
};
$this->container['gitlabProjectId'] = function () {
return Config::get()->TRAC2GITLAB_GITLAB_PROJECT_ID;
};
$this->container['gitlabPager'] = function ($c) {
return new Gitlab\ResultPager($c['gitlab']);
};
$this->container['parsedown'] = function () {
$parsedown = new Parsedown();
$parsedown->setSafeMode(true);
return $parsedown;
};
}
return $this->container;
}
public function getIconNavigation($course_id, $last_visit, $user_id)
{
return null;
......@@ -48,8 +104,13 @@ final class TracToGitlabPlugin extends StudIPPlugin implements StandardPlugin, S
$this->addStylesheet('assets/style.scss');
$this->addScript('assets/script.js');
require_once __DIR__ . '/vendor/autoload.php';
parent::perform($unconsumed);
}
private function buildNavigation()
{
$navigation = new Navigation(_('Dashboard'), PluginEngine::getURL($this, [], 'dashboard'));
$navigation->setImage(Icon::create($this->getPluginURL() . '/assets/cardiogram.svg', Icon::ROLE_NAVIGATION));
Navigation::addItem('/gitlab-dashboard', $navigation);
}
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 489.5 489.5" style="enable-background:new 0 0 489.5 489.5" xml:space="preserve" width="512" height="512"><path d="M0 0v489.5h489.5V0H0zm47.4 47.4h394.7v170.1h-90.5c-3.5 0-7 1.9-8.5 5.1l-11.7 20.2-57.2-170.6c-2.8-8.5-16.1-9.7-19 1.6l-40.4 217.5-40.4-136c-1.9-6.9-12.8-11-18.6-1.2l-28.7 63.3H47.4v-170zm47.7 404.3c-15.5 0-28-12.4-28-28 0-15.5 12.4-28 28-28 15.5 0 28 12.4 28 28s-12.4 28-28 28zm297.6 0c-15.5 0-28-12.4-28-28 0-15.5 12.4-28 28-28 15.5 0 28 12.4 28 28s-12.5 28-28 28zm49.7-89.7h-395V237.3h85.8c3.9 0 7.4-2.3 8.9-5.8l20.6-45.1 44.7 150.3c3 10.1 17.5 9.3 19.4-1L267.6 115l52.1 154.6c3.8 9.7 15.3 7.3 18.3 1.6l19.8-34.2h84.7v125h-.1z" fill="#24437c"/></svg>
\ No newline at end of file
......@@ -12,6 +12,7 @@
"guzzlehttp/guzzle": "^7.2",
"http-interop/http-factory-guzzle": "^1.0",
"erusev/parsedown": "^1.7",
"ext-json": "*"
"ext-json": "*",
"pimple/pimple": "^3.4"
}
}
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "02c21ff582a38f5e0c5b84426a4902f7",
"content-hash": "33d70628ad93e6a887d04087b16605cf",
"packages": [
{
"name": "clue/stream-filter",
......@@ -1048,6 +1048,59 @@
},
"time": "2020-07-07T09:29:14+00:00"
},
{
"name": "pimple/pimple",
"version": "v3.4.0",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Pimple.git",
"reference": "86406047271859ffc13424a048541f4531f53601"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/86406047271859ffc13424a048541f4531f53601",
"reference": "86406047271859ffc13424a048541f4531f53601",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1"
},
"require-dev": {
"symfony/phpunit-bridge": "^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.4.x-dev"
}
},
"autoload": {
"psr-0": {
"Pimple": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Pimple, a simple Dependency Injection Container",
"homepage": "https://pimple.symfony.com",
"keywords": [
"container",
"dependency injection"
],
"support": {
"source": "https://github.com/silexphp/Pimple/tree/v3.4.0"
},
"time": "2021-03-06T08:28:00+00:00"
},
{
"name": "psr/cache",
"version": "1.0.1",
......@@ -1097,6 +1150,54 @@
},
"time": "2016-08-06T20:24:11+00:00"
},
{
"name": "psr/container",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
"shasum": ""
},
"require": {
"php": ">=7.2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.1"
},
"time": "2021-03-05T17:36:06+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.1",
......@@ -1606,7 +1707,9 @@
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform": {
"ext-json": "*"
},
"platform-dev": [],
"plugin-api-version": "2.1.0"
}
......@@ -35,7 +35,7 @@ final class ConvertController extends TracToGitlab\Controller
$migrated = TracToGitlab\TicketIssueEntry::findOneByTrac_ticket_id($ticket_id);
if ($migrated) {
$issue = $this->gitlab->issues()->show(
Config::get()->TRAC2GITLAB_GITLAB_PROJECT_ID,
$this->gitlabProjectId,
$migrated['gitlab_issue_id']
);
......
<?php
final class DashboardController extends TracToGitlab\Controller
{
const QM_LABEL_MAPPING = [
'Anwendungs-Doku' => 'userdoc',
'Code-Review' => 'code',
'Entwicklungs-Doku' => 'devdoc',
'Funktionalität' => 'func',
'GUI-Richtlinien' => 'gui',
'Schnittstellen' => 'iface',
'Textstrings' => 'text',
];
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
PageLayout::setTitle(_('Übersicht der Issues in gitlab'));
$this->setupSidebar();
}
private function getSelected(string $what)
{
if (!isset($_SESSION['GITLAB_DASHBOARD_SELECTION'])) {
$_SESSION['GITLAB_DASHBOARD_SELECTION'] = [
'milestone' => array_reverse(array_keys($this->getMilestonesAsSelection()))[0],
'types' => 'TIC,StEP',
];
}
return $_SESSION['GITLAB_DASHBOARD_SELECTION'][$what] ?? null;
}
private function setSelected(string $what, string $value)
{
if ($value !== $this->getSelected($what)) {
$_SESSION['GITLAB_DASHBOARD_SELECTION'][$what] = $value;
}
}
public function index_action()
{
$this->issues = $this->getIssues();
$this->mapping = $this->getQMLabelMapping();
}
public function select_action(string $what, string $value = null)
{
$this->setSelected($what, Request::get($what, $value));
$this->redirect($this->indexURL());
}
private function setupSidebar()
{
$options = Sidebar::get()->addWidget(new OptionsWidget());
$options->addSelect(
_('Meilenstein'),
$this->selectURL('milestone'),
'milestone',
$this->getMilestonesAsSelection(),
$this->getSelected('milestone')
);
$options->addSelect(
_('Typ'),
$this->selectURL('types'),
'types',
[
'TIC,StEP' => 'StEPs und TICs',
'StEP' => 'StEPs',
'TIC' => 'TICs',
],
$this->getSelected('types')
);
}
private function getIssues(): array
{
$issues = [];
foreach (explode(',', $this->getSelected('types')) as $type) {
$issues = array_merge(
$issues,
$this->gitlabPager->fetchAll(
$this->gitlab->issues(),
'all',
[
$this->gitlabProjectId,
[
'sort' => 'asc',
'scope' => 'all',
'milestone' => $this->getSelected('milestone'),
'labels' => $type,
]
]
)
);
}
usort($issues, function ($a, $b) {
return $a['id'] - $b['id'];
});
return array_map(function ($issue) {
return new TracToGitlab\GitlabIssue($issue);
}, $issues);
}
private function getMilestones()
{
$milestones = $this->gitlab->milestones()->all(
$this->gitlabProjectId
);
$milestones = array_filter($milestones, function ($milestone) {
return preg_match('/^Stud\.IP \d+\.\d+$/', $milestone['title']);
});
return $milestones;
}
private function getMilestonesAsSelection()
{
$result = [];
foreach ($this->getMilestones() as $milestone) {
$result[$milestone['title']] = $milestone['title'];
}
return $result;
}
private function getQMLabels()
{
$labels = $this->gitlabPager->fetchAll(
$this->gitlab->projects(),
'labels',
[$this->gitlabProjectId]
);
$labels = array_filter($labels, function ($label) {
return strpos($label['name'], 'QM::') === 0;
});
$labels = array_map(function ($label) {
return substr($label['name'], 4, -3);
}, $labels);
$labels = array_unique($labels);
$labels = array_values($labels);
return $labels;
}
private function getQMLabelMapping()
{
return self::QM_LABEL_MAPPING;
}
}
......@@ -11,17 +11,6 @@ final class IssuesController extends \TracToGitlab\Controller
'StEP' => ['1927f2b86d6b185aa6c6697810ad42f1', '93c84607e687030b249a69cd30ca7bd9', 'StEP%05u: %s'],
];
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
$this->registerGenerator('parsedown', function () {
$parsedown = new Parsedown();
$parsedown->setSafeMode(true);
return $parsedown;
});
}
public function create_action()
{
if (!Request::isPost()) {
......
......@@ -2,50 +2,22 @@
namespace TracToGitlab;
/**
* @property TracToGitlab\TracLookup $trac
* @property \TracToGitlabPlugin $plugin
* @property TracLookup $trac
* @property \Gitlab\Client $gitlab
* @property \Gitlab\ResultPager $gitlabPager
* @property int $gitlabProjectId
*/
abstract class Controller extends \PluginController
{
protected $generators = [];
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
$this->registerGenerator('trac', function () {
return new TracLookup(\Config::get()->TRAC2GITLAB_TRAC_URL);
});
$this->registerGenerator('gitlab', function () {
$builder = new \Gitlab\HttpClient\Builder(
new \GuzzleHttp\Client(),
new \Http\Factory\Guzzle\RequestFactory(),
new \Http\Factory\Guzzle\StreamFactory(),
new \Http\Factory\Guzzle\UriFactory()
);
$client = new \Gitlab\Client($builder);
$client->setUrl(\Config::get()->TRAC2GITLAB_GITLAB_URL);
$client->authenticate(\Config::get()->TRAC2GITLAB_GITLAB_TOKEN, \Gitlab\Client::AUTH_HTTP_TOKEN);
return $client;
});
}
public function __get($offset)
{
if (!isset($this->generators[$offset])) {
return $this->$offset ?? null;
}
if (is_callable($this->generators[$offset])) {
$this->generators[$offset] = $this->generators[$offset]();
}
$container = $this->plugin->getDIContainer();
return $this->generators[$offset];
if (!isset($container[$offset])) {
return $this->$offset ?? null;
}
public function registerGenerator($name, $value)
{
$this->generators[$name] = $value;
return $container[$offset];
}
}
<?php
namespace TracToGitlab;
final class GitlabIssue
{
private $issue;
public function __construct(array $issue)
{
$this->issue = $issue;
}
public function __get($offset)
{
if ($offset === 'assignee') {
return implode(', ', array_map(function ($assignee) {
return $assignee['username'];
}, $this->issue['assignees']));
}
if ($offset === 'type') {
if ($this->isBiest()) {
return 'BIEST';
}
if ($this->isTic()) {
return 'TIC';
}
if ($this->isStep()) {
return 'StEP';
}
return '?';
}
return $this->issue[$offset] ?? null;
}
public function isClosed()
{
return $this->issue['state'] !== 'opened';
}
public function isBiest()
{
return in_array('BIEST', $this->issue['labels']);
}
public function isTic()
{
return in_array('TIC', $this->issue['labels']);
}
public function isStep()
{
return in_array('StEP', $this->issue['labels']);
}
public function getIconForQMLabel(string $label)
{
foreach ($this->issue['labels'] as $l) {
if (preg_match("/^QM::{$label}::(.)$/", $l, $match)) {
$state = $match[1];
if ($state === '+') {
return \Icon::create('accept', \Icon::ROLE_STATUS_GREEN);
}
if ($state === '?') {
return \Icon::create('question', \Icon::ROLE_STATUS_YELLOW);
}
if ($state === '-') {
return \Icon::create('decline', \Icon::ROLE_STATUS_RED);
}
}
}
return '';
}
}
pluginname=Trac to gitlab converter
pluginclassname=TracToGitlabPlugin
origin=UOL
version=1.0.3
version=1.1
studipMinVersion=5.0
<table class="default">
<thead>
<tr>
<th><?= _('Issue') ?></th>
<th><?= _('Typ') ?></th>
<th><?= _('Status') ?></th>
<th><?= _('Titel') ?></th>
<th><?= _('Autor') ?></th>
<th><?= _('Bearbeiter') ?></th>
<? foreach ($mapping as $label => $abbrevation): ?>
<th>
<abbr title="<?= htmlReady($label) ?>">
<?= htmlReady($abbrevation) ?>
</abbr>
</th>
<? endforeach; ?>
</tr>
</thead>
<tbody>
<? if (!$issues): ?>
<tr>
<td colspan="<?= 6 + count($mapping) ?>" style="text-align: center">
<?= _('Keine Issues für diesen Meilenstein und Typ') ?>
</td>
</tr>
<? endif; ?>
<? foreach ($issues as $issue): ?>
<tr>
<td>
<a href="<?= htmlReady($issue->web_url) ?>" target="_blank">
#<?= htmlReady($issue->iid) ?>
</a>
</td>
<td><?= htmlReady($issue->type) ?></td>
<td>
<? if ($issue->isClosed()): ?>
closed
<? else: ?>
open
<? endif; ?>
</td>
<td>
<a href="<?= htmlReady($issue->web_url) ?>" target="_blank">
<?= htmlReady($issue->title) ?>
</a>
</td>
<td><?= htmlReady($issue->author['username']) ?></td>
<td><?= htmlReady($issue->assignee) ?></td>
<? foreach ($mapping as $label => $abbrevation): ?>
<td>
<?= $issue->getIconForQMLabel($label) ?>
</td>
<? endforeach; ?>
</tr>
<? endforeach; ?>
</tbody>
</table>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment