1<?php 2/** 3 * GitLab Api Plugin 4 * 5 * @license : BSD-3 Clause 6 * @author : Mehmet Ozgan <mozgan@gmail.com> 7 */ 8 9if (!defined('DOKU_INC')) { die(); } 10 11require_once __DIR__.'/gitlab/gitlabapi.php'; 12 13class syntax_plugin_gitlabapi extends DokuWiki_Syntax_Plugin { 14 /** 15 * Syntax Plugins 16 * 17 * The class needs to implement at least the following functions: 18 * -) getType() 19 * -) getSort() 20 * -) connectTo($mode) 21 * -) handle($match, $state, $pos, Doku_Handler $handler) 22 * -) render($mode, Doku_Renderer $renderer, $data) 23 * 24 * More information: https://www.dokuwiki.org/devel:syntax_plugins#syntax_types 25 */ 26 27 public function getType() { return 'substition'; } 28 29 public function getPType() { return 'normal'; } 30 31 public function getSort() { return 196; } 32 33 public function connectTo($mode) { 34 $this->Lexer->addSpecialPattern('<gitlab-api[^>]*/>', $mode, 'plugin_gitlabapi'); 35 } 36 37 function getServerFromJson($server) { 38 $json_file = file_get_contents(__DIR__.'/server.json'); 39 $json_data = json_decode($json_file, true); 40 if (isset($json_data[$server])) { 41 return $json_data[$server]; 42 } else { 43 return null; 44 } 45 } 46 47 48 function handle($match, $state, $pos, Doku_Handler $handler) { 49 switch ($state) { 50 case DOKU_LEXER_SPECIAL: 51 $data = array( 52 'state' => $state 53 ); 54 55 // match @server and @token 56 preg_match("/server *= *(['\"])(.*?)\\1/", $match, $server); 57 if (!empty($server)) { 58 $server_data = $this->getServerFromJson($server[2]); 59 if (!is_null($server_data)) { 60 $data['server'] = $server_data['url']; 61 $data['token'] = $server_data['api_token']; 62 } 63 } 64 if (!isset($data['server'])) { 65 $data['server'] = $this->getConf('server.default'); 66 } 67 68 if (!isset($data['token'])) { 69 $data['token'] = $this->getConf('token.default'); 70 } 71 72 // match @project-path 73 preg_match("/project-path *= *(['\"])(.*?)\\1/", $match, $project_path); 74 if (!empty($project_path)) { 75 $data['project-path'] = $project_path[2]; 76 } 77 78 // match @milestones 79 preg_match("/milestones *= *(['\"])(.*?)\\1/", $match, $milestones); 80 if(!empty($milestones)) { 81 $data['milestones'] = $milestones[2]; 82 } 83 84 // match @commits 85 preg_match("/commits *= *(['\"])(.*?)\\1/", $match, $commits); 86 if(!empty($commits)) { 87 $data['commits'] = $commits[2]; 88 } 89 90 // match @issues 91 preg_match("/issues *= *(['\"])(.*?)\\1/", $match, $issues); 92 if(!empty($issues)) { 93 $data['issues'] = $issues[2]; 94 } 95 96 // match @pipelines 97 preg_match("/pipelines *= *(['\"])(.*?)\\1/", $match, $pipelines); 98 if(!empty($pipelines)) { 99 $data['pipelines'] = $pipelines[2]; 100 } 101 102 return $data; 103 104 case DOKU_LEXER_UNMATCHED: 105 return array('state' => $state, 'text' => $match); 106 107 default: 108 return array('state' => $state, 'bytepos_end' => $pos + strlen($match)); 109 } 110 } 111 112 function render($mode, Doku_Renderer $renderer, $data) { 113 if ($mode !== 'xhtml') { return false; } 114 if ($mode != 'xhtml') { return false; } 115 116 if (isset($data['error'])) { 117 $renderer->doc .= $data['text']; 118 return true; 119 } 120 121 $renderer->info['cache'] = false; 122 switch ($data['state']) { 123 case DOKU_LEXER_SPECIAL: 124 $this->renderGitLab($renderer, $data); 125 break; 126 127 case DOKU_LEXER_ENTER: 128 case DOKU_LEXER_EXIT: 129 case DOKU_LEXER_UNMATCHED: 130 $renderer->doc .= $renderer->_xmlEntities($data['text']); 131 break; 132 } 133 134 return true; 135 } 136 137 function renderGitLab($renderer, $data) { 138 // create GitLabApi object 139 $gitlab = new GitLabApi($data); 140 141 // get project 142 $project = $gitlab->getProject(); 143 //dbg($project); 144 145 if (empty($project)) { 146 $this->renderProjectError($renderer, $data); 147 return array('state' => $state, 'bytepos_end' => $pos + strlen($match)); 148 } 149 150 $project_id = $project['id']; 151 152 $project_url = $project['web_url']; 153 $project_name = $project['name']; 154 $date_time = $this->getDateTime($project['last_activity_at']); 155 $namespace = $project['namespace']['full_path']; 156 157 $img_url = DOKU_URL . 'lib/plugins/gitlabapi/images/gitlab.png'; 158 159 $renderer->doc .= '<div class="gitlab">'; 160 $renderer->doc .= '<span><img src="'.$img_url.'" class="gitlab"></span>'; 161 $renderer->doc .= '<b class="gitlab">'.$this->getLang('gitlab.project').'</b><br>'; 162 $renderer->doc .= '<hr class="gitlab">'; 163 $renderer->doc .= '<a href="'.$project_url.'" class="gitlab">'.$project_name.'</a>'; 164 $renderer->doc .= ' - <b>Namespace:</b> <a href="'.$data['server'].'/'.$namespace.'"> '.$namespace.'</a>'; 165 $renderer->doc .= '<p><b>'.$this->getLang('gitlab.activity').':</b> '.$date_time['date'].' - '.$date_time['time'].'</p>'; 166 167 if (!empty($data['milestones'])) { 168 $this->renderProjectMilestones($renderer, $gitlab, $project_id, $data['milestones']); 169 } 170 if (!empty($data['commits'])) { 171 $this->renderProjectCommits($renderer, $gitlab, $project_id, $data['commits']); 172 } 173 if (!empty($data['issues'])) { 174 $this->renderProjectIssues($renderer, $gitlab, $project_id, $data['issues']); 175 } 176 if (!empty($data['pipelines'])) { 177 $this->renderProjectPipelines($renderer, $gitlab, $project_id, $data['pipelines']); 178 } 179 180 $renderer->doc .= '</p>'; 181 $renderer->doc .= '</div>'; 182 183 $gitlab->closeClient(); 184 } 185 186 function renderProjectCommits($renderer, $gitlab, $project_id, $number) { 187 $commits = $gitlab->getCommits($project_id); 188 189 $renderer->doc .= '<b class="gitlab">'.$this->getLang('gitlab.commits').'</b><br>'; 190 $renderer->doc .= '<table border="1"> 191 <thread> 192 <tr> 193 <th>Committer Name</th> 194 <th>Title</th> 195 <th>Message</th> 196 <th>Date</th> 197 <th>URL</th> 198 <tr> 199 </thread> 200 <tbody>'; 201 202 $total = count($commits) < $number ? count($commits) : $number; 203 for ($i = 0; $i < $total; $i++) { 204 $renderer->doc .= '<tr>'; 205 $renderer->doc .= '<td>'.$commits[$i]['committer_name'].'</td>'; 206 $renderer->doc .= '<td>'.$commits[$i]['title'].'</td>'; 207 $renderer->doc .= '<td>'.$commits[$i]['message'].'</td>'; 208 $renderer->doc .= '<td>'.$commits[$i]['committed_date'].'</td>'; 209 $renderer->doc .= '<td><a href='.$commits[$i]['web_url'].'>Commit link</a></td>'; 210 $renderer->doc .= '</tr>'; 211 } 212 $renderer->doc .= '</tbody></table>'; 213 } 214 215 function renderProjectIssues($renderer, $gitlab, $project_id, $number) { 216 $issues = $gitlab->getIssues($project_id); 217 218 $renderer->doc .= '<b class="gitlab">'.$this->getLang('gitlab.issues').'</b><br>'; 219 $renderer->doc .= '<table border="1"> 220 <thread> 221 <tr> 222 <th>Author</th> 223 <th>Title</th> 224 <th>Labels</th> 225 <th>Assignees</th> 226 <th>State</th> 227 <th>URL</th> 228 <tr> 229 </thread> 230 <tbody>'; 231 232 $total = count($issues) < $number ? count($issues) : $number; 233 for ($i = 0; $i < $total; $i++) { 234 if ($issues[$i]['state'] == 'closed') { 235 continue; 236 } 237 $renderer->doc .= '<tr>'; 238 $renderer->doc .= '<td>'.$issues[$i]['author']['name'].'</td>'; 239 $renderer->doc .= '<td>'.$issues[$i]['title'].'</td>'; 240 $labels = $issues[$i]['labels']; 241 $l_list = ''; 242 foreach ($labels as $l) { 243 $l_list .= $l.', '; 244 } 245 $renderer->doc .= '<td>'.rtrim($l_list,', ').'</td>'; 246 $assignees = $issues[$i]['assignees']; 247 $a_list = ''; 248 foreach ($assignees as $a) { 249 $a_list .= $a['name'].', '; 250 } 251 $renderer->doc .= '<td>'.rtrim($a_list, ', ').'</td>'; 252 $renderer->doc .= '<td>'.$issues[$i]['state'].'</td>'; 253 $renderer->doc .= '<td><a href='.$issues[$i]['web_url'].'>Issue link</a></td>'; 254 $renderer->doc .= '</tr>'; 255 } 256 $renderer->doc .= '</tbody></table>'; 257 258 } 259 260 function renderProjectMilestones($renderer, $gitlab, $project_id, $number) { 261 $milestones = $gitlab->getMilestones($project_id); 262 263 $renderer->doc .= '<b class="gitlab">'.$this->getLang('gitlab.milestones').'</b><br>'; 264 $renderer->doc .= '<table border="1"> 265 <thread> 266 <tr> 267 <th>Title</th> 268 <th>Description</th> 269 <th>State</th> 270 <th>Created</th> 271 <th>URL</th> 272 <tr> 273 </thread> 274 <tbody>'; 275 276 $total = count($milestones) < $number ? count($milestones) : $number; 277 for ($i = 0; $i < $total; $i++) { 278 $renderer->doc .= '<tr>'; 279 $renderer->doc .= '<td>'.$milestones[$i]['title'].'</td>'; 280 $renderer->doc .= '<td>'.$milestones[$i]['description'].'</td>'; 281 $renderer->doc .= '<td>'.$milestones[$i]['state'].'</td>'; 282 $renderer->doc .= '<td>'.$milestones[$i]['created_at'].'</td>'; 283 $renderer->doc .= '<td><a href='.$milestones[$i]['web_url'].'>Milestone link</a></td>'; 284 $renderer->doc .= '</tr>'; 285 } 286 287 $renderer->doc .= '</tbody></table>'; 288 } 289 290 function renderProjectPipelines($renderer, $gitlab, $project_id, $number) { 291 $pipelines = $gitlab->getPipelines($project_id); 292 293 $renderer->doc .= '<b class="gitlab">'.$this->getLang('gitlab.pipelines').'</b><br>'; 294 $renderer->doc .= '<table border="1"> 295 <thread> 296 <tr> 297 <th>Ref</th> 298 <th>Status</th> 299 <th>Source</th> 300 <th>URL</th> 301 <tr> 302 </thread> 303 <tbody>'; 304 305 $total = count($pipelines) < $number ? count($pipelines) : $number; 306 for ($i = 0; $i < $total; $i++) { 307 $renderer->doc .= '<tr>'; 308 $renderer->doc .= '<td>'.$pipelines[$i]['ref'].'</td>'; 309 $renderer->doc .= '<td>'.$pipelines[$i]['status'].'</td>'; 310 $renderer->doc .= '<td>'.$pipelines[$i]['source'].'</td>'; 311 $renderer->doc .= '<td><a href='.$pipelines[$i]['web_url'].'>Pipeline link</a></td>'; 312 $renderer->doc .= '</tr>'; 313 } 314 315 $renderer->doc .= '</tbody></table>'; 316 317 } 318 319 function renderProjectError($renderer, $data) { 320 $img_url = DOKU_URL . 'lib/plugins/gitlabapi/images/gitlab.png'; 321 322 $renderer->doc .= '<div class="gitlab">'; 323 $renderer->doc .= '<span><img src="'.$img_url.'" class="gitlab"></span>'; 324 $renderer->doc .= '<b class="gitlab">'.$this->getLang('gitlab.project').'</b><br>'; 325 $renderer->doc .= '<hr class="gitlab">'; 326 $renderer->doc .= '<p>'.$this->getLang('gitlab.error').'</p>'; 327 $renderer->doc .= '</div>'; 328 } 329 330 function getDateTime($activity_time) { 331 $date_exploded = explode('T', $activity_time); 332 $time_exploded = explode('Z', $date_exploded[1]); 333 334 return array('date' => $date_exploded[0], 'time' => substr($time_exploded[0], 0, -4)); 335 } 336 337} 338 339 340 341