diff options
Diffstat (limited to 'bridges/GitlabIssueBridge.php')
-rw-r--r-- | bridges/GitlabIssueBridge.php | 415 |
1 files changed, 212 insertions, 203 deletions
diff --git a/bridges/GitlabIssueBridge.php b/bridges/GitlabIssueBridge.php index ce3ab08b..ebcdbb4c 100644 --- a/bridges/GitlabIssueBridge.php +++ b/bridges/GitlabIssueBridge.php @@ -1,205 +1,214 @@ <?php -class GitlabIssueBridge extends BridgeAbstract { - - const MAINTAINER = 'Mynacol'; - const NAME = 'Gitlab Issue/Merge Request'; - const URI = 'https://gitlab.com/'; - const CACHE_TIMEOUT = 1800; // 30min - const DESCRIPTION = 'Returns comments of an issue/MR of a gitlab project'; - - const PARAMETERS = array( - 'global' => array( - 'h' => array( - 'name' => 'Gitlab instance host name', - 'exampleValue' => 'gitlab.com', - 'defaultValue' => 'gitlab.com', - 'required' => true - ), - 'u' => array( - 'name' => 'User/Organization name', - 'exampleValue' => 'fdroid', - 'required' => true - ), - 'p' => array( - 'name' => 'Project name', - 'exampleValue' => 'fdroidclient', - 'required' => true - ) - - ), - 'Issue comments' => array( - 'i' => array( - 'name' => 'Issue number', - 'type' => 'number', - 'exampleValue' => '2099', - 'required' => true - ) - ), - 'Merge Request comments' => array( - 'i' => array( - 'name' => 'Merge Request number', - 'type' => 'number', - 'exampleValue' => '2099', - 'required' => true - ) - ) - ); - - public function getName(){ - $name = $this->getInput('h') . '/' . $this->getInput('u') . '/' . $this->getInput('p'); - switch ($this->queriedContext) { - case 'Issue comments': - $name .= ' Issue #' . $this->getInput('i'); - break; - case 'Merge Request comments': - $name .= ' MR !' . $this->getInput('i'); - break; - default: - return parent::getName(); - } - return $name; - } - - public function getURI() { - $host = $this->getInput('h') ?? 'gitlab.com'; - $uri = 'https://' . $host . '/' . $this->getInput('u') . '/' - . $this->getInput('p') . '/'; - switch ($this->queriedContext) { - case 'Issue comments': - $uri .= '-/issues'; - break; - case 'Merge Request comments': - $uri .= '-/merge_requests'; - break; - default: - return $uri; - } - $uri .= '/' . $this->getInput('i'); - return $uri; - } - - public function getIcon() { - return 'https://' . $this->getInput('h') . '/favicon.ico'; - } - - public function collectData() { - switch ($this->queriedContext) { - case 'Issue comments': - $this->items[] = $this->parseIssueDescription(); - break; - case 'Merge Request comments': - $this->items[] = $this->parseMergeRequestDescription(); - break; - default: - break; - } - - /* parse issue/MR comments */ - $comments_uri = $this->getURI() . '/discussions.json'; - $comments = getContents($comments_uri); - $comments = json_decode($comments, false); - - foreach ($comments as $value) { - foreach ($value->notes as $comment) { - $item = array(); - $item['uri'] = $comment->noteable_note_url; - $item['uid'] = $item['uri']; - - // TODO fix invalid timestamps (fdroid bot) - $item['timestamp'] = $comment->created_at ?? $comment->updated_at ?? $comment->last_edited_at; - $author = $comment->author ?? $comment->last_edited_by; - $item['author'] = '<img src="' . $author->avatar_url . '" width=24></img> <a href="https://' . - $this->getInput('h') . $author->path . '">' . $author->name . ' @' . $author->username . '</a>'; - - $content = ''; - if ($comment->system) { - $content = $comment->note_html; - if ($comment->type === 'StateNote') { - $content .= ' the issue'; - } elseif ($comment->type === null) { - // e.g. "added 900 commits\n800 from master\n175h4d - commit message\n..." - $content = str_get_html($comment->note_html)->find('p', 0); - } - } else { - // no switch-case to do strict comparison - if ($comment->type === null || $comment->type === 'DiscussionNote') { - $content = 'commented'; - } elseif ($comment->type === 'DiffNote') { - $content = 'commented on a thread'; - } else { - $content = $comment->note_html; - } - } - $item['title'] = $author->name . " $content"; - - $content = $this->fixImgSrc($comment->note_html); - $item['content'] = defaultLinkTo($content, 'https://' . $this->getInput('h') . '/'); - - $this->items[] = $item; - } - } - } - - private function parseIssueDescription() { - $description_uri = $this->getURI() . '.json'; - $description = getContents($description_uri); - $description = json_decode($description, false); - $description_html = getSimpleHtmlDomCached($this->getURI()); - - $item = array(); - $item['uri'] = $this->getURI(); - $item['uid'] = $item['uri']; - - $item['timestamp'] = $description->created_at ?? $description->updated_at; - - $item['author'] = $this->parseAuthor($description_html); - - $item['title'] = $description->title; - $item['content'] = markdownToHtml($description->description); - - return $item; - } - - private function parseMergeRequestDescription() { - $description_uri = $this->getURI() . '/cached_widget.json'; - $description = getContents($description_uri); - $description = json_decode($description, false); - $description_html = getSimpleHtmlDomCached($this->getURI()); - - $item = array(); - $item['uri'] = $this->getURI(); - $item['uid'] = $item['uri']; - - $item['timestamp'] = $description_html->find('.merge-request-details time', 0)->datetime; - - $item['author'] = $this->parseAuthor($description_html); - - $item['title'] = 'Merge Request ' . $description->title; - $item['content'] = markdownToHtml($description->description); - - return $item; - } - - private function fixImgSrc($html) { - if (is_string($html)) { - $html = str_get_html($html); - } - - foreach ($html->find('img') as $img) { - $img->src = $img->getAttribute('data-src'); - } - return $html; - } - - private function parseAuthor($description_html) { - $description_html = $this->fixImgSrc($description_html); - - $authors = $description_html->find('.issuable-meta a.author-link, .merge-request a.author-link'); - $editors = $description_html->find('.edited-text a.author-link'); - $author_str = implode(' ', $authors); - if ($editors) { - $author_str .= ', ' . implode(' ', $editors); - } - return defaultLinkTo($author_str, 'https://' . $this->getInput('h') . '/'); - } + +class GitlabIssueBridge extends BridgeAbstract +{ + const MAINTAINER = 'Mynacol'; + const NAME = 'Gitlab Issue/Merge Request'; + const URI = 'https://gitlab.com/'; + const CACHE_TIMEOUT = 1800; // 30min + const DESCRIPTION = 'Returns comments of an issue/MR of a gitlab project'; + + const PARAMETERS = [ + 'global' => [ + 'h' => [ + 'name' => 'Gitlab instance host name', + 'exampleValue' => 'gitlab.com', + 'defaultValue' => 'gitlab.com', + 'required' => true + ], + 'u' => [ + 'name' => 'User/Organization name', + 'exampleValue' => 'fdroid', + 'required' => true + ], + 'p' => [ + 'name' => 'Project name', + 'exampleValue' => 'fdroidclient', + 'required' => true + ] + + ], + 'Issue comments' => [ + 'i' => [ + 'name' => 'Issue number', + 'type' => 'number', + 'exampleValue' => '2099', + 'required' => true + ] + ], + 'Merge Request comments' => [ + 'i' => [ + 'name' => 'Merge Request number', + 'type' => 'number', + 'exampleValue' => '2099', + 'required' => true + ] + ] + ]; + + public function getName() + { + $name = $this->getInput('h') . '/' . $this->getInput('u') . '/' . $this->getInput('p'); + switch ($this->queriedContext) { + case 'Issue comments': + $name .= ' Issue #' . $this->getInput('i'); + break; + case 'Merge Request comments': + $name .= ' MR !' . $this->getInput('i'); + break; + default: + return parent::getName(); + } + return $name; + } + + public function getURI() + { + $host = $this->getInput('h') ?? 'gitlab.com'; + $uri = 'https://' . $host . '/' . $this->getInput('u') . '/' + . $this->getInput('p') . '/'; + switch ($this->queriedContext) { + case 'Issue comments': + $uri .= '-/issues'; + break; + case 'Merge Request comments': + $uri .= '-/merge_requests'; + break; + default: + return $uri; + } + $uri .= '/' . $this->getInput('i'); + return $uri; + } + + public function getIcon() + { + return 'https://' . $this->getInput('h') . '/favicon.ico'; + } + + public function collectData() + { + switch ($this->queriedContext) { + case 'Issue comments': + $this->items[] = $this->parseIssueDescription(); + break; + case 'Merge Request comments': + $this->items[] = $this->parseMergeRequestDescription(); + break; + default: + break; + } + + /* parse issue/MR comments */ + $comments_uri = $this->getURI() . '/discussions.json'; + $comments = getContents($comments_uri); + $comments = json_decode($comments, false); + + foreach ($comments as $value) { + foreach ($value->notes as $comment) { + $item = []; + $item['uri'] = $comment->noteable_note_url; + $item['uid'] = $item['uri']; + + // TODO fix invalid timestamps (fdroid bot) + $item['timestamp'] = $comment->created_at ?? $comment->updated_at ?? $comment->last_edited_at; + $author = $comment->author ?? $comment->last_edited_by; + $item['author'] = '<img src="' . $author->avatar_url . '" width=24></img> <a href="https://' . + $this->getInput('h') . $author->path . '">' . $author->name . ' @' . $author->username . '</a>'; + + $content = ''; + if ($comment->system) { + $content = $comment->note_html; + if ($comment->type === 'StateNote') { + $content .= ' the issue'; + } elseif ($comment->type === null) { + // e.g. "added 900 commits\n800 from master\n175h4d - commit message\n..." + $content = str_get_html($comment->note_html)->find('p', 0); + } + } else { + // no switch-case to do strict comparison + if ($comment->type === null || $comment->type === 'DiscussionNote') { + $content = 'commented'; + } elseif ($comment->type === 'DiffNote') { + $content = 'commented on a thread'; + } else { + $content = $comment->note_html; + } + } + $item['title'] = $author->name . " $content"; + + $content = $this->fixImgSrc($comment->note_html); + $item['content'] = defaultLinkTo($content, 'https://' . $this->getInput('h') . '/'); + + $this->items[] = $item; + } + } + } + + private function parseIssueDescription() + { + $description_uri = $this->getURI() . '.json'; + $description = getContents($description_uri); + $description = json_decode($description, false); + $description_html = getSimpleHtmlDomCached($this->getURI()); + + $item = []; + $item['uri'] = $this->getURI(); + $item['uid'] = $item['uri']; + + $item['timestamp'] = $description->created_at ?? $description->updated_at; + + $item['author'] = $this->parseAuthor($description_html); + + $item['title'] = $description->title; + $item['content'] = markdownToHtml($description->description); + + return $item; + } + + private function parseMergeRequestDescription() + { + $description_uri = $this->getURI() . '/cached_widget.json'; + $description = getContents($description_uri); + $description = json_decode($description, false); + $description_html = getSimpleHtmlDomCached($this->getURI()); + + $item = []; + $item['uri'] = $this->getURI(); + $item['uid'] = $item['uri']; + + $item['timestamp'] = $description_html->find('.merge-request-details time', 0)->datetime; + + $item['author'] = $this->parseAuthor($description_html); + + $item['title'] = 'Merge Request ' . $description->title; + $item['content'] = markdownToHtml($description->description); + + return $item; + } + + private function fixImgSrc($html) + { + if (is_string($html)) { + $html = str_get_html($html); + } + + foreach ($html->find('img') as $img) { + $img->src = $img->getAttribute('data-src'); + } + return $html; + } + + private function parseAuthor($description_html) + { + $description_html = $this->fixImgSrc($description_html); + + $authors = $description_html->find('.issuable-meta a.author-link, .merge-request a.author-link'); + $editors = $description_html->find('.edited-text a.author-link'); + $author_str = implode(' ', $authors); + if ($editors) { + $author_str .= ', ' . implode(' ', $editors); + } + return defaultLinkTo($author_str, 'https://' . $this->getInput('h') . '/'); + } } |