/
api.php
137 lines (112 loc) · 3.46 KB
/
api.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* Anqh API controller
*
* @package Anqh
* @author Antti Qvickström
* @copyright (c) 2010-2012 Antti Qvickström
* @license http://www.opensource.org/licenses/mit-license.php MIT license
*/
class Anqh_Controller_API extends Controller {
const FORMAT_JSON = 'json';
const FORMAT_XML = 'xml';
/**
* @var string Output format
*/
protected $format;
/**
* @var array Available output formats
*/
public static $_formats = array(self::FORMAT_JSON, self::FORMAT_XML);
/**
* @var array Data to be returned
*/
protected $data = array();
/**
* @var string API version
*/
protected $version;
/**
* @var array Available versions
*/
public static $_versions = array('v1');
/**
* Construct controller.
*
* @throws Controller_API_Exception on invalid version, rate limit exceeded, invalid format
*/
public function before() {
// Log request
$api_request = Model_API_Request::factory();
$api_request->ip = Request::$client_ip;
$api_request->request = $this->request->uri() . (empty($_REQUEST) ? '' : '?' . http_build_query($_REQUEST));
$api_request->created = time();
$api_request->save();
// Check version
$this->version = $this->request->param('version');
if (!in_array($this->version, self::$_versions)) {
throw new Controller_API_Exception('Invalid version');
}
$this->data['version'] = $this->version;
// Rate limit
$rate_limit = (int)Kohana::$config->load('api.rate_limit');
$rate_span = (int)Kohana::$config->load('api.rate_span');
if ($rate_limit) {
$requests = Model_API_Request::request_count(time() - $rate_span, Request::$client_ip);
$requests_left = $rate_limit - $requests;
if ($requests_left < 0) {
throw new Controller_API_Exception('Request limit reached');
}
$this->data['requests'] = $requests;
$this->data['requests_left'] = $requests_left;
$this->data['request_window'] = $rate_span;
}
// Check format
$this->format = $this->request->param('format');
!$this->format and $this->format = self::FORMAT_JSON;
if (!in_array($this->format, self::$_formats)) {
throw new Controller_API_Exception('Invalid format');
}
parent::before();
}
/**
* Output response.
*/
public function after() {
switch ($this->format) {
// Support JSON and JSONP
case self::FORMAT_JSON:
$this->response->headers('Content-Type', 'application/json');
// Check and sanitize JSONP
$jsonp = Arr::get($_REQUEST, 'callback');
if ($jsonp && Valid::alpha_dash($jsonp)) {
$this->response->body($jsonp . '(' . json_encode($this->data) . ')');
} else {
$this->response->body(json_encode($this->data));
}
break;
case self::FORMAT_XML:
$this->response->headers('Content-Type', 'application/xml');
$this->response->body(Arr::xml($this->data));
break;
}
}
/**
* Prepare order parameters
*
* @param string $order
* @param array $orderable Orderable fields
* @return array
*/
protected function _prepare_order($order, array $orderable = null) {
$orders = array();
// Build order array, field:order => field => order
foreach (explode(':', $order) as $_order) {
$_order = explode('.', $_order);
if (empty($orderable) || in_array($_order[0], $orderable)) {
$orders[$_order[0]] = isset($_order[1]) && ($_order[1] == 'asc' || $_order[1] == 'desc') ? $_order[1] : 'asc';
}
}
return $orders;
}
}