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

releases, fixes #39

parent c61ca5cb
No related branches found
No related tags found
1 merge request!8releases, fixes #39
<?php
require_once __DIR__ . '/bootstrap.php';
final class StudipReleasesPlugin extends TracToGitlab\Plugin implements SystemPlugin
{
public function __construct()
{
parent::__construct();
$navigation = new Navigation(
_('Stud.IP Releases (Beta)'),
PluginEngine::getURL($this, [], 'releases')
);
$navigation->setImage(Icon::create('download', Icon::ROLE_NAVIGATION));
Navigation::addItem('/studip-releases', $navigation);
}
public function perform($unconsumed_path)
{
$this->addStylesheet('assets/releases.scss');
parent::perform($unconsumed_path);
}
}
<?php <?php
require_once __DIR__ . '/bootstrap.php'; require_once __DIR__ . '/bootstrap.php';
final class TracToGitlabPlugin extends StudIPPlugin implements StandardPlugin, SystemPlugin final class TracToGitlabPlugin extends TracToGitlab\Plugin implements StandardPlugin, SystemPlugin
{ {
private $container = null;
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
...@@ -23,48 +21,6 @@ final class TracToGitlabPlugin extends StudIPPlugin implements StandardPlugin, S ...@@ -23,48 +21,6 @@ final class TracToGitlabPlugin extends StudIPPlugin implements StandardPlugin, S
$this->buildNavigation(); $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) public function getIconNavigation($course_id, $last_visit, $user_id)
{ {
return null; return null;
......
.release-filesize {
white-space: nowrap;
}
tr:not(:last-child) td.table-divider {
border-bottom-color: var(--light-gray-color-80);
}
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"http-interop/http-factory-guzzle": "^1.0", "http-interop/http-factory-guzzle": "^1.0",
"erusev/parsedown": "^1.7", "erusev/parsedown": "^1.7",
"ext-json": "*", "ext-json": "*",
"pimple/pimple": "^3.4" "pimple/pimple": "^3.4",
"ext-curl": "*"
} }
} }
...@@ -459,32 +459,32 @@ ...@@ -459,32 +459,32 @@
}, },
{ {
"name": "m4tthumphrey/php-gitlab-api", "name": "m4tthumphrey/php-gitlab-api",
"version": "11.4.0", "version": "11.5.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/GitLabPHP/Client.git", "url": "https://github.com/GitLabPHP/Client.git",
"reference": "4aa7d2af5614bca3f3473dae59fe930dbe73b496" "reference": "d3364fd373f1ec8588dbd65afb527ea4cdcad8b4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/GitLabPHP/Client/zipball/4aa7d2af5614bca3f3473dae59fe930dbe73b496", "url": "https://api.github.com/repos/GitLabPHP/Client/zipball/d3364fd373f1ec8588dbd65afb527ea4cdcad8b4",
"reference": "4aa7d2af5614bca3f3473dae59fe930dbe73b496", "reference": "d3364fd373f1ec8588dbd65afb527ea4cdcad8b4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"ext-xml": "*", "ext-xml": "*",
"php": "^7.2.5 || ^8.0", "php": "^7.2.5 || ^8.0",
"php-http/cache-plugin": "^1.7.1", "php-http/cache-plugin": "^1.7.2",
"php-http/client-common": "^2.3", "php-http/client-common": "^2.3",
"php-http/discovery": "^1.12", "php-http/discovery": "^1.12",
"php-http/httplug": "^2.2", "php-http/httplug": "^2.2",
"php-http/multipart-stream-builder": "^1.1.2", "php-http/multipart-stream-builder": "^1.1.2",
"psr/cache": "^1.0", "psr/cache": "^1.0 || ^2.0",
"psr/http-client-implementation": "^1.0", "psr/http-client-implementation": "^1.0",
"psr/http-factory-implementation": "^1.0", "psr/http-factory-implementation": "^1.0",
"psr/http-message": "^1.0", "psr/http-message": "^1.0",
"symfony/options-resolver": "^3.4 || ^4.0 || ^5.0", "symfony/options-resolver": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"symfony/polyfill-php80": "^1.17" "symfony/polyfill-php80": "^1.17"
}, },
"require-dev": { "require-dev": {
...@@ -505,19 +505,23 @@ ...@@ -505,19 +505,23 @@
"authors": [ "authors": [
{ {
"name": "Fabien Bourigault", "name": "Fabien Bourigault",
"email": "bourigaultfabien@gmail.com" "email": "bourigaultfabien@gmail.com",
"homepage": "https://github.com/fbourigault"
}, },
{ {
"name": "Graham Campbell", "name": "Graham Campbell",
"email": "graham@alt-three.com" "email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
}, },
{ {
"name": "Matt Humphrey", "name": "Matt Humphrey",
"email": "matth@windsor-telecom.co.uk" "email": "matth@windsor-telecom.co.uk",
"homepage": "https://github.com/m4tthumphrey"
}, },
{ {
"name": "Miguel Piedrafita", "name": "Miguel Piedrafita",
"email": "github@miguelpiedrafita.com" "email": "github@miguelpiedrafita.com",
"homepage": "https://github.com/m1guelpf"
} }
], ],
"description": "GitLab API v4 client for PHP", "description": "GitLab API v4 client for PHP",
...@@ -527,7 +531,7 @@ ...@@ -527,7 +531,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/GitLabPHP/Client/issues", "issues": "https://github.com/GitLabPHP/Client/issues",
"source": "https://github.com/GitLabPHP/Client/tree/11.4.0" "source": "https://github.com/GitLabPHP/Client/tree/11.5.1"
}, },
"funding": [ "funding": [
{ {
...@@ -535,7 +539,7 @@ ...@@ -535,7 +539,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-03-27T23:40:20+00:00" "time": "2022-01-23T18:43:46+00:00"
}, },
{ {
"name": "php-http/cache-plugin", "name": "php-http/cache-plugin",
...@@ -1711,5 +1715,5 @@ ...@@ -1711,5 +1715,5 @@
"ext-json": "*" "ext-json": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.1.0" "plugin-api-version": "2.3.0"
} }
<?php
final class ReleasesController extends \TracToGitlab\Controller
{
const CACHE_KEY = 'studip-releases';
private static $curl_handle = null;
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
Navigation::activateItem('/studip-releases');
PageLayout::setTitle(_('Stud.IP Releases'));
$widget = new LinksWidget();
$widget->setTitle(_('Weiterführende Links'));
$widget->addLink(
_('Releases auf gitlab.studip.de'),
'https://gitlab.studip.de/studip/studip/-/releases',
Icon::create('link2'),
['target' => '_blank']
);
$widget->addLink(
_('Ältere Releases bei SourceForge'),
'https://sourceforge.net/projects/studip/files/Stud.IP/',
Icon::create('link2'),
['target' => '_blank']
);
Sidebar::get()->addWidget($widget);
}
public function after_filter($action, $args)
{
if (self::$curl_handle !== null) {
curl_close(self::$curl_handle);
}
parent::after_filter($action, $args);
}
public function index_action()
{
$version = Request::get('version');
$this->releases = $this->getReleases();
$this->addVersionFilter($this->releases, $version);
$this->addResetAction();
if ($version && isset($this->releases[$version])) {
$this->releases = [
$version => $this->releases[$version],
];
}
}
public function reset_action()
{
if ($this->isAdmin()) {
StudipCacheFactory::getCache()->expire(self::CACHE_KEY);
}
$this->relocate($this->indexURL());
}
private function getReleases(): array
{
$cache = StudipCacheFactory::getCache();
$releases = $cache->read(self::CACHE_KEY);
if ($releases === false) {
$temp = array_map(
function (array $release): array {
$links = array_filter(
$release['assets']['links'] ?? [],
function (array $asset): bool {
return $asset['link_type'] === 'package';
}
);
$links = array_map(
function (array $link): array {
return [
'name' => $link['name'],
'url' => $link['url'],
'size' => $this->getFileSize($link['url']),
];
},
$links
);
usort($links, function ($a, $b) {
return strcmp($a['name'], $b['name']);
});
$sources = array_map(
function (array $asset): array {
$asset['size'] = $this->getFileSize($asset['url']);
return $asset;
},
$release['assets']['sources'] ?? []
);
$changelog = sprintf(
'https://gitlab.studip.de/studip/studip/-/blob/%s/ChangeLog',
$release['tag_name']
);
return [
'name' => $release['name'],
'description' => $release['description'],
'url' => $release['_links']['self'],
'changelog' => $changelog,
'released' => strtotime($release['released_at']),
'sources' => $release['assets']['sources'],
'links' => $links
];
},
$this->gitlab->repositories()->releases($this->gitlabProjectId)
);
$releases = [];
foreach ($temp as $release) {
$version = $release['name'];
if (preg_match('/^v?(\d+(\.\d+)+)$/', $release['name'], $match)) {
$version = $match[1];
}
$major_version = implode('.', array_slice(explode('.', $version), 0, 2));
if (!isset($releases[$major_version])) {
$releases[$major_version] = [];
}
$releases[$major_version][$version] = $release;
}
uksort($releases, function ($a, $b) {
return version_compare($b, $a);
});
foreach ($releases as $version => $subversions) {
uksort($subversions, function ($a, $b) {
return version_compare($b, $a);
});
$releases[$version] = $subversions;
}
$cache->write(self::CACHE_KEY, $releases);
}
return $releases;
}
private function getFileSize(string $url): int
{
// Init curl if necessary
if (self::$curl_handle === null) {
self::$curl_handle = curl_init(null);
curl_setopt(self::$curl_handle, CURLOPT_HEADER, true);
curl_setopt(self::$curl_handle, CURLOPT_NOBODY, true);
curl_setopt(self::$curl_handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt(self::$curl_handle, CURLOPT_FOLLOWLOCATION, true);
}
// Set url and send request
curl_setopt(self::$curl_handle, CURLOPT_URL, $url);
$response = curl_exec(self::$curl_handle);
// Get status
$line = strtok($response, "\r\n");
$status = trim($line);
// Parse headers
$headers = [];
while (($line = strtok("\r\n")) !== false) {
$chunks = explode(':', $line, 2);
if ($chunks !== false) {
$headers[$chunks[0]] = $chunks[1];
}
}
// TODO: Check status
// Get filesize by Content-Length header
return (int) ($headers['Content-Length'] ?? -1);
}
private function addVersionFilter(array $releases, ?string $version): void
{
if (count($releases) > 1) {
$widget = new SelectWidget(
_('Nur Releases einer Version anzeigen'),
$this->indexURL(),
'version'
);
$widget->addElement(new SelectElement(
null,
_('Alle Versionen anzeigen'),
!isset($releases[$version])
));
foreach (array_keys($releases) as $v) {
$widget->addElement(new SelectElement(
$v,
$v,
$v === $version
));
}
Sidebar::get()->addWidget($widget);
}
}
private function addResetAction(): void
{
if (!$this->isAdmin()) {
return;
}
Sidebar::get()->addWidget(new ActionsWidget())->addLink(
_('Cache leeren'),
$this->resetURL(),
Icon::create('refresh')
);
}
private function isAdmin(): bool
{
$user = User::findCurrent();
return $user && $user->perms === 'root';
}
}
<?php
namespace TracToGitlab;
use Gitlab;
use GuzzleHttp;
use Http;
use Parsedown;
use Pimple;
abstract class Plugin extends \StudIPPlugin
{
private $container = null;
public function getDIContainer()
{
if ($this->container === null) {
require_once $this->getPluginPath() . '/vendor/autoload.php';
$this->container = new Pimple\Container();
$this->container['trac'] = function () {
return new 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;
}
}
pluginname=Trac to gitlab converter pluginname=Trac to gitlab converter
pluginclassname=TracToGitlabPlugin pluginclassname=TracToGitlabPlugin
pluginclassname=StudipReleasesPlugin
origin=UOL origin=UOL
version=1.4 version=1.4.1
studipMinVersion=5.0 studipMinVersion=5.0
<?php
/**
* @var array<string, array> $releases
*/
?>
<table class="default">
<colgroup>
<col>
<col class="hidden-tiny-down">
<col>
<col>
<col>
</colgroup>
<? foreach ($releases as $major_version => $versions): ?>
<tbody>
<tr>
<th colspan="5"><?= htmlReady($major_version) ?></th>
</tr>
<? foreach ($versions as $version => $release): ?>
<tr>
<td>
<a href="<?= URLHelper::getLink($release['url']) ?>" target="_blank" rel="noreferrer noopener">
<?= htmlReady($release['name']) ?>
</a>
</td>
<td class="hidden-tiny-down"><?= strftime('%x', $release['released']) ?></td>
<? foreach ($release['links'] as $link): ?>
<td>
<a href="<?= URLHelper::getLink($link['url']) ?>" target="_blank" rel="noreferrer noopener">
<?= htmlReady($link['name']) ?>
</a>
<span class="release-filesize hidden-tiny-down">
(<?= relsize($link['size'], false) ?>)
</span>
</td>
<? endforeach; ?>
<td class="hidden-small-down">
<a href="<?= URLHelper::getLink($release['changelog']) ?>" target="_blank" rel="noopener noreferrer">
ChangeLog
</a>
</td>
</tr>
<tr class="hidden-medium-up">
<td colspan="5" class="table-divider">
<a href="<?= URLHelper::getLink($release['changelog']) ?>" target="_blank" rel="noopener noreferrer">
ChangeLog
</a>
</td>
</tr>
<? endforeach; ?>
</tbody>
<? endforeach; ?>
</table>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment