[BugzillaBridge] Add new bridge (#2825)

This commit is contained in:
Yaman Qalieh 2022-06-24 05:04:49 -04:00 committed by GitHub
parent 7d31d32750
commit 1cfcacbbeb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 184 additions and 2 deletions

180
bridges/BugzillaBridge.php Normal file
View file

@ -0,0 +1,180 @@
<?php
class BugzillaBridge extends BridgeAbstract {
const NAME = 'Bugzilla Bridge';
const URI = 'https://www.bugzilla.org/';
const DESCRIPTION = 'Bridge for any Bugzilla instance';
const MAINTAINER = 'Yaman Qalieh';
const PARAMETERS = array(
'global' => array(
'instance' => array(
'name' => 'Instance URL',
'required' => true,
'exampleValue' => 'https://bugzilla.mozilla.org'
)
),
'Bug comments' => array(
'id' => array(
'name' => 'Bug tracking ID',
'type' => 'number',
'required' => true,
'title' => 'Insert bug tracking ID',
'exampleValue' => 121241
),
'limit' => array(
'name' => 'Number of comments to return',
'type' => 'number',
'required' => false,
'title' => 'Specify number of comments to return',
'defaultValue' => -1
),
'skiptags' => array(
'name' => 'Skip offtopic comments',
'type' => 'checkbox',
'title' => 'Excludes comments tagged as advocacy, metoo, or offtopic from the feed'
)
)
);
const SKIPPED_ACTIVITY = array(
'cc' => true,
'comment_tag' => true
);
const SKIPPED_TAGS = array('advocacy', 'metoo', 'offtopic');
private $instance;
private $bugid;
private $buguri;
private $title;
public function getName() {
if (!is_null($this->title)) {
return $this->title;
}
return parent::getName();
}
public function getURI() {
return $this->buguri ?? parent::getURI();
}
public function collectData() {
$this->instance = rtrim($this->getInput('instance'), '/');
$this->bugid = $this->getInput('id');
$this->buguri = $this->instance . '/show_bug.cgi?id=' . $this->bugid;
$url = $this->instance . '/rest/bug/' . $this->bugid;
$this->getTitle($url);
$this->collectComments($url . '/comment');
$this->collectUpdates($url . '/history');
usort($this->items, function($a, $b) {
return $b['timestamp'] <=> $a['timestamp'];
});
if ($this->getInput('limit') > 0) {
$this->items = array_slice($this->items, 0, $this->getInput('limit'));
}
}
protected function getTitle($url) {
// Only request the summary for a faster request
$json = json_decode(getContents($url . '?include_fields=summary'), true);
$this->title = 'Bug ' . $this->bugid . ' - ' .
$json['bugs'][0]['summary'] . ' - ' .
// Remove https://
substr($this->instance, 8);
}
protected function collectComments($url) {
$json = json_decode(getContents($url), true);
// Array of comments is here
if (!isset($json['bugs'][$this->bugid]['comments'])) {
returnClientError('Cannot find REST endpoint');
}
foreach($json['bugs'][$this->bugid]['comments'] as $comment) {
$item = array();
if ($this->getInput('skiptags') and
array_intersect(self::SKIPPED_TAGS, $comment['tags'])) {
continue;
}
$item['categories'] = $comment['tags'];
$item['uri'] = $this->buguri . '#c' . $comment['count'];
$item['title'] = 'Comment ' . $comment['count'];
$item['timestamp'] = $comment['creation_time'];
$item['author'] = $this->getUser($comment['creator']);
$item['content'] = $comment['text'];
if (isset($comment['is_markdown']) and $comment['is_markdown']) {
$item['content'] = markdownToHtml($item['content']);
}
if (!is_null($comment['attachment_id'])) {
$item['enclosures'] = array($this->instance . '/attachment.cgi?id=' . $comment['attachment_id']);
}
$this->items[] = $item;
}
}
protected function collectUpdates($url) {
$json = json_decode(getContents($url), true);
// Array of changesets which contain an array of changes
if (!isset($json['bugs']['0']['history'])) {
returnClientError('Cannot find REST endpoint');
}
foreach($json['bugs']['0']['history'] as $changeset) {
$author = $this->getUser($changeset['who']);
$timestamp = $changeset['when'];
foreach($changeset['changes'] as $change) {
// Skip updates to the cc list and comment tagging
if (isset(self::SKIPPED_ACTIVITY[$change['field_name']])) {
continue;
}
$item = array();
$item['uri'] = $this->buguri;
$item['title'] = 'Updated';
$item['timestamp'] = $timestamp;
$item['author'] = $author;
$item['content'] = ucfirst($change['field_name']) . ': ' .
($change['removed'] === '' ? '[nothing]' : $change['removed']) . ' -> ' .
($change['added'] === '' ? '[nothing]' : $change['added']);
$this->items[] = $item;
}
}
}
protected function getUser($user) {
// Check if the user endpoint is available
if ($this->loadCacheValue($this->instance . 'userEndpointClosed')) {
return $user;
}
$cache = $this->loadCacheValue($this->instance . $user);
if (!is_null($cache)) {
return $cache;
}
$url = $this->instance . '/rest/user/' . $user . '?include_fields=real_name';
try {
$json = json_decode(getContents($url), true);
if (isset($json['error']) and $json['error']) {
throw new Exception;
}
} catch (Exception $e) {
$this->saveCacheValue($this->instance . 'userEndpointClosed', true);
return $user;
}
$username = $json['users']['0']['real_name'];
if (empty($username)) {
$username = $user;
}
$this->saveCacheValue($this->instance . $user, $username);
return $username;
}
}

View file

@ -3,7 +3,8 @@ class KernelBugTrackerBridge extends BridgeAbstract {
const NAME = 'Kernel Bug Tracker'; const NAME = 'Kernel Bug Tracker';
const URI = 'https://bugzilla.kernel.org'; const URI = 'https://bugzilla.kernel.org';
const DESCRIPTION = 'Returns feeds for bug comments'; const DESCRIPTION = 'DEPRECATED: Use BugzillaBridge instead.
Returns feeds for bug comments';
const MAINTAINER = 'logmanoriginal'; const MAINTAINER = 'logmanoriginal';
const PARAMETERS = array( const PARAMETERS = array(
'Bug comments' => array( 'Bug comments' => array(

View file

@ -3,7 +3,8 @@ class MozillaBugTrackerBridge extends BridgeAbstract {
const NAME = 'Mozilla Bug Tracker'; const NAME = 'Mozilla Bug Tracker';
const URI = 'https://bugzilla.mozilla.org'; const URI = 'https://bugzilla.mozilla.org';
const DESCRIPTION = 'Returns feeds for bug comments'; const DESCRIPTION = 'DEPRECATED: Use BugzillaBridge instead.
Returns feeds for bug comments';
const MAINTAINER = 'AntoineTurmel'; const MAINTAINER = 'AntoineTurmel';
const PARAMETERS = array( const PARAMETERS = array(
'Bug comments' => array( 'Bug comments' => array(