1<?php
2/**
3 * Jira-links action plugin for DokuWiki
4 *
5 * This action adds Jira remote issue links when saving a page.
6 *
7 * @author christian studer <christian.studer@meteotest.ch>
8 * @license GPL2 http://www.gnu.org/licenses/gpl-2.0.html
9 */
10
11// Must be run within DokuWiki
12if (!defined('DOKU_INC')) die();
13
14/**
15 * The Jira-links action plugin itself
16 *
17 * @author christian studer <christian.studer@meteotest.ch>
18 */
19class action_plugin_jiralinks extends DokuWiki_Action_Plugin {
20	/**
21	 * Flag to detect double triggering of the event
22	 *
23	 * @var bool
24	 */
25	protected $alreadyTriggered = FALSE;
26
27	/**
28	 * Register the IO_WIKIPAGE_WRITE AFTER event handler, if required
29	 *
30	 * @param Doku_Event_Handler $controller
31	 */
32	public function register(Doku_Event_Handler &$controller) {
33		if($this->getConf('enable_adding_urls_to_issues') and function_exists('curl_version')) {
34			$controller->register_hook('IO_WIKIPAGE_WRITE', 'AFTER', $this, 'addRemoteIssueLinks');
35		}
36
37	}
38
39	/**
40	 * Add remote issue links
41	 *
42	 * @param Doku_Event $event
43	 * @param mixed $param
44	 */
45	public function addRemoteIssueLinks(Doku_Event &$event, $param) {
46		if($this->alreadyTriggered) return;
47
48		global $ID, $INFO, $conf;
49
50		// Look for issue keys
51		if(preg_match_all('/[A-Z]+?-[0-9]+/', $event->data[0][1], $keys)) {
52			// Keys found, prepare data for the remote issue link
53			$keys = array_unique($keys[0]);
54			$url = wl($ID, '', TRUE);
55			$globalId = md5($url); // MD5 hash is used because the global id max length is 255 characters. An effective page URL might be longer.
56			$applicationName =  $conf['title'];
57			$applicationType = 'org.dokuwiki';
58			$title = $applicationName . ' - ' . (empty($INFO['meta']['title']) ? $event->data[2] : $INFO['meta']['title']);
59			$relationship = $this->getConf('url_relationship');
60			$favicon = tpl_getMediaFile(array(':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico'), TRUE);
61
62			foreach($keys as $key) {
63				// Prepare final data array
64				$data = array(
65					'globalId' => $globalId,
66					'application' => array(
67							'type' => $applicationType,
68							'name' => $applicationName,
69							),
70					'relationship' => $relationship,
71					'object' => array(
72							'url' => $url,
73							'title' => $title,
74							'icon' => array(
75									'url16x16' => $favicon),
76							),
77				);
78
79				$this->executeRequest("issue/{$key}/remotelink", 'POST', $data);
80			}
81
82			$this->alreadyTriggered = TRUE;
83		}
84	}
85
86	/*
87	 * Execute request
88	 *
89	 * @param string $request
90	 * @param string $method
91	 * @param array $data
92	 * @return StdClass
93	 */
94	protected function executeRequest($request, $method = 'GET', $data = NULL) {
95		$curl = curl_init($this->getConf('jira_api_url') . $request);
96
97		// Additional curl setup
98		switch(strtoupper($method)) {
99			default:
100			case 'GET':
101				// Do nothing
102				break;
103			case 'POST':
104				curl_setopt($curl, CURLOPT_POST, TRUE);
105
106				// Send data
107				curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
108				break;
109		}
110
111		// Basic curl setup
112		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
113		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
114		curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC) ;
115		curl_setopt($curl, CURLOPT_USERPWD, $this->getConf('jira_api_username') . ':' . $this->getConf('jira_api_password'));
116		curl_setopt($curl, CURLOPT_TIMEOUT, 10);
117		curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
118		curl_setopt($curl, CURLOPT_HEADER, FALSE);
119		curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json"));
120
121		// Execution
122		$response = curl_exec($curl);
123		curl_close($curl);
124
125		return json_decode($response);
126	}
127}
128