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