6
6
class Quandl {
7
7
8
8
public $ api_key ;
9
- public $ default_format = " csv " ;
9
+ public $ format ;
10
10
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
+ ];
17
20
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 " ) {
25
22
$ this ->api_key = $ api_key ;
26
- $ this ->params = $ params ;
23
+ $ this ->format = $ format ;
27
24
}
28
25
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 ));
37
31
38
- // Magic getter, for completeness
39
- public function __get ($ key ) {
40
- return $ this ->params [$ key ];
32
+ return $ this ->getData ($ url );
41
33
}
42
34
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 ));
47
43
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 );
51
45
}
52
46
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 ));
57
59
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 );
61
61
}
62
62
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 ));
70
74
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 );
75
76
}
76
77
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 ;
83
88
}
84
89
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 ;
115
98
}
116
99
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 ;
131
105
}
132
106
133
- // executeDownload gets a URL, and returns the downloaded document
107
+ // executeDownload gets a URL, and returns the downloaded document.
134
108
// If a cache_handler is set, it will call it to get a document
135
109
// from it, and ask it to store the downloaded object where applicable.
136
110
private function executeDownload ($ url ) {
@@ -152,16 +126,31 @@ private function executeDownload($url) {
152
126
return $ data ;
153
127
}
154
128
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
+
155
146
// convertToQuandlDate converts any time string supported by
156
147
// PHP (e.g. "today-30 days") to the format needed by Quandl
157
148
private static function convertToQuandlDate ($ time_str ) {
158
149
return date ("Y-m-d " , strtotime ($ time_str ));
159
150
}
160
151
161
152
// 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.
165
154
private static function convertSymbolsToMulti ($ symbols_array ) {
166
155
$ result = [];
167
156
foreach ($ symbols_array as $ symbol ) {
0 commit comments