Skip to content

Commit 2d76ddc

Browse files
committed
Complete revision of the API
1 parent 781169f commit 2d76ddc

File tree

4 files changed

+243
-219
lines changed

4 files changed

+243
-219
lines changed

Quandl.php

Lines changed: 94 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -6,131 +6,105 @@
66
class Quandl {
77

88
public $api_key;
9-
public $default_format = "csv";
9+
public $format;
1010
public $cache_handler = null;
11-
public $was_cached = false;
12-
private $params;
13-
14-
private static $base = "https://www.quandl.com/api/v1/datasets";
15-
private static $base_multi = "https://quandl.com/api/v1/multisets";
16-
private static $base_lists = "http://www.quandl.com/api/v2/datasets";
11+
public $was_cached = false;
12+
public $last_url;
13+
14+
private static $url_templates = [
15+
"symbol" => 'https://www.quandl.com/api/v1/datasets/%s.%s?%s',
16+
"symbols" => 'https://www.quandl.com/api/v1/multisets.%s?columns=%s&%s',
17+
"search" => 'https://www.quandl.com/api/v1/datasets.%s?%s',
18+
"list" => 'http://www.quandl.com/api/v2/datasets.%s?%s',
19+
];
1720

18-
// The constructor accepts an optional api_key and an
19-
// array of params. The params array may contain any key=>value
20-
// pair that is supported by Quandl. All params will be appended
21-
// to the request URL.
22-
// If you prefer, you may add the params later, see __set below.
23-
// Example: $quandl = new Quandl("asd123", ["trim_end"=>"yesterday"])
24-
public function __construct($api_key=null, $params=[]) {
21+
public function __construct($api_key=null, $format="object") {
2522
$this->api_key = $api_key;
26-
$this->params = $params;
23+
$this->format = $format;
2724
}
2825

29-
// Magic setter handles all calls to $quandl->unknown_var
30-
// This is used to set params outside of the constructor.
31-
// Example: $quandl->trim_start = "today-300 days";
32-
public function __set($key, $value) {
33-
if($key == "trim_start" or $key == "trim_end")
34-
$value = self::convertToQuandlDate($value);
35-
$this->params[$key] = $value;
36-
}
26+
// getSymbol returns data for a given symbol.
27+
public function getSymbol($symbol, $params=null) {
28+
$url = $this->getUrl("symbol",
29+
$symbol, $this->getFormat(),
30+
$this->arrangeParams($params));
3731

38-
// Magic getter, for completeness
39-
public function __get($key) {
40-
return $this->params[$key];
32+
return $this->getData($url);
4133
}
4234

43-
// getCsv returns CSV data for a quandl symbol
44-
public function getCsv($symbol=null) {
45-
return $this->getData($symbol, "csv");
46-
}
35+
// getSymbols returns data for an array of symbols.
36+
// Symbols may be in slash or dot notation and may include
37+
// column specifier.
38+
public function getSymbols($symbols, $params=null) {
39+
$url = $this->getUrl("symbols",
40+
$this->getFormat(),
41+
self::convertSymbolsToMulti($symbols),
42+
$this->arrangeParams($params));
4743

48-
// getJson returns JSON data for a quandl symbol
49-
public function getJson($symbol=null) {
50-
return $this->getData($symbol, "json");
44+
return $this->getData($url);
5145
}
5246

53-
// getObject returns a PHP object data for a quandl symbol
54-
public function getObject($symbol=null) {
55-
return json_decode($this->getJson($symbol));
56-
}
47+
// getSearch returns results for a search query.
48+
// CSV output is not supported with this node so if format
49+
// is set to CSV, the result will fall back to object mode.
50+
public function getSearch($query, $page=1, $per_page=300) {
51+
$params = [
52+
"per_page" => $per_page,
53+
"page" => $page,
54+
"query" => $query,
55+
];
56+
$url = $this->getUrl("search",
57+
$this->getFormat(true),
58+
$this->arrangeParams($params));
5759

58-
// getXml returns XML data for a quandl symbol
59-
public function getXml($symbol=null) {
60-
return $this->getData($symbol, "xml");
60+
return $this->getData($url);
6161
}
6262

63-
// search returns a data object with Quandle document results
64-
public function search($query, $per_page=null, $page=null) {
65-
$this->query = $query;
66-
$per_page and $this->per_page = $per_page;
67-
$page and $this->page = $page;
68-
return $this->getObject();
69-
}
63+
// getList returns the list of symbols for a given source.
64+
public function getList($source, $page=1, $per_page=300) {
65+
$params = [
66+
"query" => "*",
67+
"source_code" => $source,
68+
"per_page" => $per_page,
69+
"page" => $page,
70+
];
71+
$url = $this->getUrl("list",
72+
$this->getFormat(),
73+
$this->arrangeParams($params));
7074

71-
//
72-
public function getList($source, $per_page=300, $page=1, $format=null) {
73-
$url = $this->getListUrl($source, $per_page, $page, $format);
74-
return $this->executeDownload($url);
75+
return $this->getData($url);
7576
}
7677

77-
// getData returns data in any format for a given symbol.
78-
// Normally, you should use the getCsv, getJson or getXml
79-
// which will call getData.
80-
public function getData($symbol=null, $format=null) {
81-
$url = $this->getUrl($symbol, $format);
82-
return $this->executeDownload($url);
78+
// getFormat returns one of the three formats supported by Quandl.
79+
// It is here for two reasons:
80+
// 1) we also allow "object" format. this will be sent to Quandl
81+
// as "json" but the getData method will return a json_decoded
82+
// output.
83+
// 2) some Quandl nodes do not support CSV (namely search).
84+
private function getFormat($omit_csv=false) {
85+
if(($this->format == "csv" and $omit_csv) or $this->format == "object")
86+
return "json";
87+
return $this->format;
8388
}
8489

85-
// getUrl returns the complete URL for making a request to Quandl.
86-
// Normally, you would not need to use it but it is publicly exposed
87-
// for convenience.
88-
// Note that $symbol may be an array of symbols and in this case,
89-
// may be either the slash notation or dot notation, and may include
90-
// the column selector.
91-
public function getUrl($symbol=null, $format=null) {
92-
$is_multi = is_array($symbol);
93-
$format or $format = $this->default_format;
94-
$params = [];
95-
96-
if($is_multi) {
97-
$base = self::$base_multi;
98-
$result = "$base.$format";
99-
$params["columns"] = self::convertSymbolsToMulti($symbol);
100-
}
101-
else {
102-
$base = self::$base;
103-
$result = $symbol === null
104-
? "$base.$format"
105-
: "$base/$symbol.$format";
106-
}
107-
108-
foreach($this->params as $k=>$v)
109-
$params[$k] = $v;
110-
111-
$this->api_key and $params['auth_token'] = $this->api_key;
112-
$params and $result .= "?" . http_build_query($params);
113-
114-
return $result;
90+
// getUrl receives a kind that points to a URL template and
91+
// a variable number of parameters, which will be replaced
92+
// in the template.
93+
private function getUrl($kind) {
94+
$template = self::$url_templates[$kind];
95+
$args = array_slice(func_get_args(), 1);
96+
$this->last_url = trim(vsprintf($template, $args), "?&");
97+
return $this->last_url;
11598
}
11699

117-
// getListUrl returns a URL to the list of symbols in a
118-
// given source
119-
public function getListUrl($source, $per_page=300, $page=1, $format=null) {
120-
$format or $format = $this->default_format;
121-
$base = self::$base_lists;
122-
$params = [
123-
"query" => "*",
124-
"source_code" => $source,
125-
"per_page" => $per_page,
126-
"page" => $page,
127-
];
128-
$this->api_key and $params['auth_token'] = $this->api_key;
129-
$params = http_build_query($params);
130-
return "$base.$format?$params";
100+
// getData executes the download operation and returns the result
101+
// as is, or json-decoded if "object" type was requested.
102+
private function getData($url) {
103+
$result = $this->executeDownload($url);
104+
return $this->format == "object" ? json_decode($result) : $result;
131105
}
132106

133-
// executeDownload gets a URL, and returns the downloaded document
107+
// executeDownload gets a URL, and returns the downloaded document.
134108
// If a cache_handler is set, it will call it to get a document
135109
// from it, and ask it to store the downloaded object where applicable.
136110
private function executeDownload($url) {
@@ -152,16 +126,31 @@ private function executeDownload($url) {
152126
return $data;
153127
}
154128

129+
// arrangeParams converts a parameters array to a query string.
130+
// In addition, we add some patches:
131+
// 1) trim_start and trim_end are converted from any plain
132+
// language syntax to Quandle format
133+
// 2) api_key is appended
134+
private function arrangeParams($params) {
135+
$this->api_key and $params['auth_token'] = $this->api_key;
136+
if(!$params) return $params;
137+
138+
foreach(["trim_start", "trim_end"] as $v) {
139+
if(isset($params[$v]) )
140+
$params[$v] = self::convertToQuandlDate($params[$v]);
141+
}
142+
143+
return http_build_query($params);
144+
}
145+
155146
// convertToQuandlDate converts any time string supported by
156147
// PHP (e.g. "today-30 days") to the format needed by Quandl
157148
private static function convertToQuandlDate($time_str) {
158149
return date("Y-m-d", strtotime($time_str));
159150
}
160151

161152
// convertSymbolsToMulti converts an array of symbols to
162-
// the format neede dfor a multiset request. In essence, it
163-
// just replaces slashes with dots and returns the comma
164-
// delimited list.
153+
// the format needed for a multiset request.
165154
private static function convertSymbolsToMulti($symbols_array) {
166155
$result = [];
167156
foreach($symbols_array as $symbol) {

0 commit comments

Comments
 (0)