1<?php
2
3include_once(dirname(__FILE__) . join(DIRECTORY_SEPARATOR, array('idoit', 'php', 'apiclient.php')));
4
5use idoit\Api\Client as ApiClient;
6use idoit\Api\Request as Request;
7use idoit\Api\CMDB\Object as CMDBObject;
8use idoit\Api\CMDB\Category;
9use idoit\Api\Connection as ApiConnection;
10
11class syntax_plugin_idoit extends DokuWiki_Syntax_Plugin {
12
13	public function getType(){ return 'disabled'; }
14	public function getPType() { return 'block'; }
15	public function getAllowedTypes() { return array(); }
16	public function getSort(){ return 100; }
17	public function connectTo($mode) { $this->Lexer->addEntryPattern('<idoitAPI>(?=.*?</idoitAPI>)','base','plugin_idoit'); }
18	public function postConnect() { $this->Lexer->addExitPattern('</idoitAPI>','plugin_idoit'); }
19
20
21	function getInfo(){
22	  return array(
23		'author' => 'Oliver Günther',
24		'email'  => 'mail@oliverguenther.de',
25		'date'   => '2014-11-19',
26		'name'   => 'i-doit API client plugin',
27		'desc'   => 'Call i-doit API with JSON requests directly from DokuWiki',
28		'url'    => 'https://github.com/oliverguenther/dokuwiki-idoit-syntax'
29	  );
30	}
31
32
33	/**
34	* Filter results with a given set of arrays, each containing
35	* one hierarchy element to access.
36	*/
37	function filterResults($request, $response) {
38		$results = array();
39
40		foreach ($request['filter'] as $filter) {
41			// Every filter is an array of items
42			$obj = $response;
43
44			$path = $filter['path'];
45			$name = $filter['desc'];
46			foreach ($path as $elem) {
47				if (array_key_exists($elem, $obj)) {
48					// descend
49					$obj = $obj[$elem];
50				} else {
51					// continue with next filter
52					$results[$name] = "Filter '$name' (path " . join('/', $path) . ") does not match response";
53					continue 2;
54				}
55			}
56			$results[$name] = $obj;
57		}
58
59		return $results;
60	}
61
62
63	/**
64	* Execute the request on the JSON RPC apai
65	* and process the results.
66	*/
67	function callAPI($request) {
68		try {
69
70			// Init connection to api endpoint
71			$api_conn = new ApiClient(new ApiConnection(
72				$this->getConf('api_endpoint'),
73				$this->getConf('api_key'),
74				$this->getConf('api_user'),
75				$this->getConf('api_pass')
76			));
77
78			$apiRequest = new Request($api_conn, $request['method'], $request['params']);
79			$response = $apiRequest->send();
80
81			if ($request['filter']) {
82				return $this->filterResults($request, $response);
83			} else {
84				return $response;
85			}
86
87
88
89		} catch (Exception $e) {
90			return "API error: " . $e->getMessage();
91		}
92	}
93
94	/**
95	* Parse the JSON request from the syntax environment
96	* and call the API with it.
97	*
98	* Returns a string error for JSON decode errors.
99	*/
100	function decodeAndRunQuery($request) {
101
102		$json = json_decode(trim($request), 1);
103
104		switch (json_last_error()) {
105			case JSON_ERROR_NONE:
106				return $this->callAPI($json);
107			case JSON_ERROR_DEPTH:
108				return 'JSON decode error: Maximum stack depth exceeded';
109			case JSON_ERROR_STATE_MISMATCH:
110				return 'JSON decode error: Underflow or the modes mismatch';
111			case JSON_ERROR_CTRL_CHAR:
112				return 'JSON decode error: Unexpected control character found';
113			case JSON_ERROR_SYNTAX:
114				return 'JSON decode error: Syntax error, malformed JSON';
115			case JSON_ERROR_UTF8:
116				return 'JSON decode error: Malformed UTF-8 characters, possibly incorrectly encoded';
117			default:
118				return 'JSON decode error: unknown';
119		}
120	}
121
122
123	public function handle($match, $state, $pos, Doku_Handler &$handler){
124		switch ($state) {
125			case DOKU_LEXER_EXIT :
126			case DOKU_LEXER_ENTER :
127				break;
128
129			case DOKU_LEXER_UNMATCHED :
130				$result = $this->decodeAndRunQuery($match);
131				return array($state, $result);
132		}
133
134		return array($state, null);
135	}
136
137	public function render($mode, &$renderer, $data) {
138		if ($mode == 'xhtml') {
139			list($state, $match) = $data;
140			switch ($state) {
141				case DOKU_LEXER_ENTER :
142					$renderer->doc .= "<pre>";
143					break;
144
145				case DOKU_LEXER_UNMATCHED :
146					if (is_array($match)) {
147						foreach ($match as $k => $v) {
148							if (!is_array($v)) {
149								// Print literal
150								$renderer->doc .= str_pad($k, 30) . "$v\n";
151							} else {
152								// Print complex as print_r
153								$renderer->doc .= "--- $k ---\n";
154								$renderer->doc .= print_r($v, true);
155								$renderer->doc .= "end $k end\n";
156							}
157						}
158					} else {
159						$renderer->doc .= print_r($match, true);
160					}
161
162					break;
163
164				case DOKU_LEXER_EXIT :
165					$renderer->doc .= "</pre>";
166					break;
167			}
168			return true;
169		}
170		return false;
171	}
172}
173