Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | // $Id$ | |
3 | ||
4 | /** | |
5 | ||
6 | This class allows to consume the API, either from within a module that knows civicrm already: | |
7 | ||
8 | require_once('api/class/api.php'); | |
9 | $api = new civicrm_api3(); | |
10 | ||
11 | or from any code on the same server as civicrm | |
12 | ||
13 | require_once('/your/civi/folder/api/class.api.php'); | |
14 | // the path to civicrm.settings.php | |
15 | $api = new civicrm_api3 (array('conf_path'=> '/your/path/to/your/civicrm/or/joomla/site)); | |
16 | ||
17 | or to query a remote server via the rest api | |
18 | ||
19 | $api = new civicrm_api3 (array ('server' => 'http://example.org','api_key'=>'theusersecretkey','key'=>'thesitesecretkey')); | |
20 | ||
21 | no matter how initialised and if civicrm is local or remote, you use the class the same way | |
22 | ||
23 | $api->{entity}->{action}($params); | |
24 | ||
25 | so to get the individual contacts | |
26 | ||
27 | if ($api->Contact->Get(array( | |
28 | 'contact_type'=>'Individual','return'=>'sort_name,current_employer')) { | |
29 | // each key of the result array is an attribute of the api | |
30 | echo "\n contacts found " . $api->count; | |
31 | foreach ($api->values as $c) { | |
32 | echo "\n".$c->sort_name. " working for ". $c->current_employer; | |
33 | } | |
34 | // in theory, doesn't append | |
35 | } else { | |
36 | echo $api->errorMsg(); | |
37 | } | |
38 | ||
39 | or to create an event | |
40 | ||
41 | if ($api->Event->Create(array( | |
42 | 'title'=>'Test','event_type_id' => 1,'is_public' => 1,'start_date' => 19430429))) { | |
43 | echo "created event id:". $api->id; | |
44 | } else { | |
45 | echo $api->errorMsg(); | |
46 | } | |
47 | ||
48 | To make it easier, the Actions can either take for input an associative array $params, or simply an id | |
49 | ||
50 | $api->Activity->Get (42); | |
51 | ||
52 | being the same as: | |
53 | ||
54 | $api->Activity->Get (array('id'=>42)); | |
55 | ||
56 | you can too get the result like what civicrm_api does, but as an object instead of an array (eg $entity->attribute instead of $entity['attribute'] | |
57 | ||
58 | $result = $api->result; | |
59 | // is the json encoded result | |
60 | echo $api; | |
61 | ||
62 | */ | |
63 | class civicrm_api3 { | |
64 | function __construct($config = NULL) { | |
65 | $this->local = TRUE; | |
66 | $this->input = array(); | |
67 | $this->lastResult = array(); | |
68 | if (isset($config) && isset($config['server'])) { | |
69 | // we are calling a remote server via REST | |
70 | $this->local = FALSE; | |
71 | $this->uri = $config['server']; | |
72 | if (isset($config['path'])) { | |
73 | $this->uri .= "/" . $config['path']; | |
74 | } | |
75 | else $this->uri .= '/sites/all/modules/civicrm/extern/rest.php'; | |
76 | $this->uri .= '?json=1'; | |
77 | if (isset($config['key'])) { | |
78 | $this->key = $config['key']; | |
79 | } | |
80 | else { | |
81 | die("\nFATAL:param['key] missing\n"); | |
82 | } | |
83 | if (isset($config['api_key'])) { | |
84 | $this->api_key = $config['api_key']; | |
85 | } | |
86 | else { | |
87 | die("\nFATAL:param['api_key] missing\n"); | |
88 | } | |
89 | ||
90 | return; | |
91 | } | |
92 | if (isset($config) && isset($config['conf_path'])) { | |
93 | define('CIVICRM_SETTINGS_PATH', $config['conf_path'] . '/civicrm.settings.php'); | |
94 | require_once CIVICRM_SETTINGS_PATH; | |
95 | require_once 'CRM/Core/Config.php'; | |
96 | require_once 'api/api.php'; | |
97 | require_once "api/v3/utils.php"; | |
98 | $this->cfg = CRM_Core_Config::singleton(); | |
99 | $this->init(); | |
100 | } | |
101 | else { | |
102 | $this->cfg = CRM_Core_Config::singleton(); | |
103 | } | |
104 | } | |
105 | ||
106 | public function __toString() { | |
107 | return json_encode($this->lastResult); | |
108 | } | |
109 | ||
110 | public function __call($action, $params) { | |
111 | // TODO : check if it's a valid action | |
112 | if (isset($params[0])) { | |
113 | return $this->call($this->currentEntity, $action, $params[0]); | |
114 | } | |
115 | else { | |
116 | return $this->call($this->currentEntity, $action, $this->input); | |
117 | } | |
118 | } | |
119 | ||
120 | /** As of PHP 5.3.0 */ | |
121 | public static function __callStatic($name, $arguments) { | |
122 | // Should we implement it ? | |
123 | echo "Calling static method '$name' " . implode(', ', $arguments) . "\n"; | |
124 | } | |
125 | ||
126 | function remoteCall($entity, $action, $params = array( | |
127 | )) { | |
128 | $fields = "key={$this->key}&api_key={$this->api_key}"; | |
129 | $query = $this->uri . "&entity=$entity&action=$action"; | |
130 | foreach ($params as $k => $v) { | |
131 | $fields .= "&$k=" . urlencode($v); | |
132 | } | |
133 | if (function_exists('curl_init')) { | |
134 | //to make it easier to debug but avoid leaking info, entity&action are the url, the rest is in the POST | |
135 | $ch = curl_init(); | |
136 | curl_setopt($ch, CURLOPT_URL, $query); | |
137 | curl_setopt($ch, CURLOPT_POST, count($params) + 2); | |
138 | curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); | |
139 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); | |
140 | ||
141 | //execute post | |
142 | $result = curl_exec($ch); | |
143 | curl_close($ch); | |
144 | return json_decode($result); | |
145 | // not good, all in get when should be in post. | |
146 | } | |
147 | else { | |
148 | $result = file_get_contents($query . '&' . $fields); | |
149 | return json_decode($result); | |
150 | } | |
151 | } | |
152 | ||
153 | function call($entity, $action = 'Get', $params = array( | |
154 | )) { | |
155 | if (is_int($params)) { | |
156 | $params = array('id' => $params); | |
157 | } | |
158 | elseif (is_string($params)) { | |
159 | $params = json_decode($params); | |
160 | } | |
161 | ||
162 | if (!isset($params['version'])) { | |
163 | ||
164 | $params['version'] = 3; | |
165 | } | |
166 | if (!isset($params['sequential'])) { | |
167 | $params['sequential'] = 1; | |
168 | } | |
169 | ||
170 | if (!$this->local) { | |
171 | $this->lastResult = $this->remoteCall($entity, $action, $params); | |
172 | } | |
173 | else { | |
174 | // easiest to convert a multi-dimentional array into an object | |
175 | $this->lastResult = json_decode(json_encode(civicrm_api($entity, $action, $params))); | |
176 | } | |
177 | // reset the input to be ready for a new call | |
178 | $this->input = array(); | |
179 | if (property_exists($this->lastResult, 'is_error')) { | |
180 | return !$this->lastResult->is_error; | |
181 | } | |
182 | // getsingle doesn't have is_error | |
183 | return TRUE; | |
184 | } | |
185 | ||
186 | //* helper method for long running programs (eg bots) | |
187 | function ping() { | |
188 | global $_DB_DATAOBJECT; | |
189 | foreach ($_DB_DATAOBJECT['CONNECTIONS'] as & $c) { | |
190 | if (!$c->connection->ping()) { | |
191 | $c->connect($this->cfg->dsn); | |
192 | if (!$c->connection->ping()) { | |
193 | die("we couldn't connect"); | |
194 | } | |
195 | } | |
196 | } | |
197 | } | |
198 | ||
199 | function errorMsg() { | |
200 | return $this->lastResult->error_message; | |
201 | } | |
202 | ||
203 | function init() { | |
204 | CRM_Core_DAO::init($this->cfg->dsn); | |
205 | } | |
206 | ||
207 | /* | |
208 | // return the id | |
209 | * $api->attr ('id'); | |
210 | * or | |
211 | * $api->attr ('id',42) //set the id | |
212 | */ | |
213 | ||
214 | ||
215 | ||
216 | public function attr($name, $value = NULL) { | |
217 | if ($value === NULL) { | |
218 | if (property_exists($this->lastResult, $name)) { | |
219 | return $this->lastResult->$name; | |
220 | } | |
221 | } | |
222 | else { | |
223 | $this->input[$name] = $value; | |
224 | } | |
225 | return $this; | |
226 | } | |
227 | ||
228 | public function is_error() { | |
229 | return (property_exists($this->lastResult, 'is_error') && $this->lastResult->is_error); | |
230 | } | |
231 | ||
232 | public function is_set($name) { | |
233 | return (isset($this->lastResult->$name)); | |
234 | } | |
235 | ||
236 | /* public function __set($name, $value) { | |
237 | echo "Setting '$name' to '$value'\n"; | |
238 | } | |
239 | */ | |
240 | ||
241 | ||
242 | ||
243 | public function __get($name) { | |
244 | //TODO, test if valid entity | |
245 | if (strtolower($name) !== $name) { | |
246 | //cheap and dumb test to differenciate call to $api->Entity->Action & value retrieval | |
247 | $this->currentEntity = $name; | |
248 | return $this; | |
249 | } | |
250 | ||
251 | if ($name === 'result') { | |
252 | ||
253 | return $this->lastResult; | |
254 | } | |
255 | if ($name === 'values') { | |
256 | return $this->lastResult->values; | |
257 | } | |
258 | ||
259 | if (property_exists($this->lastResult, $name)) { | |
260 | ||
261 | return $this->lastResult->$name; | |
262 | } | |
263 | ||
264 | $this->currentEntity = $name; | |
265 | return $this; | |
266 | } | |
267 | ||
268 | ||
269 | // or use $api->value | |
270 | public function values() { | |
271 | if (is_array($this->lastResult)) { | |
272 | return $this->lastResult['values']; | |
273 | } | |
274 | else return $this->lastResult->values; | |
275 | } | |
276 | ||
277 | // or use $api->result | |
278 | public function result() { | |
279 | return $this->lastResult; | |
280 | } | |
281 | } | |
282 |