@@ -26,6 +26,8 @@ class OdooClient
26
26
const TYPE_DOUBLE = 'double ' ;
27
27
const TYPE_NULL = 'null ' ;
28
28
29
+ const DEFAULT_LIMIT = 100 ;
30
+
29
31
/**
30
32
*
31
33
*/
@@ -41,6 +43,11 @@ class OdooClient
41
43
*/
42
44
protected $ userId ;
43
45
46
+ /**
47
+ * The version of the server, fetched when logging in.
48
+ */
49
+ protected $ serverVersion ;
50
+
44
51
/**
45
52
* Config data.
46
53
*/
@@ -131,10 +138,16 @@ public function getUserId()
131
138
132
139
// Grab the User ID.
133
140
134
- $ userId = $ response ->value ()-> me [ ' int ' ] ;
141
+ $ this -> userId = $ this -> valueToNative ( $ response ->value ()) ;
135
142
136
- if ($ userId > 0 ) {
137
- return $ userId ;
143
+ // Get the server version for capabilities.
144
+
145
+ $ version = $ this ->version ();
146
+
147
+ $ this ->serverVersion = $ version ['server_version ' ] ?? '' ;
148
+
149
+ if ($ this ->userId > 0 ) {
150
+ return $ this ->userId ;
138
151
}
139
152
140
153
throw new Exception (sprintf (
@@ -201,7 +214,7 @@ public function search(
201
214
string $ modelName ,
202
215
array $ criteria = [],
203
216
$ offset = 0 ,
204
- $ limit = 100 ,
217
+ $ limit = self :: DEFAULT_LIMIT ,
205
218
$ order = ''
206
219
) {
207
220
$ msg = $ this ->getBaseObjectRequest ($ modelName , 'search ' );
@@ -217,9 +230,42 @@ public function search(
217
230
return $ response ;
218
231
}
219
232
233
+ /**
234
+ * Same as search() but returns a native array.
235
+ *
236
+ * @return array
237
+ */
238
+ public function searchArray (
239
+ string $ modelName ,
240
+ array $ criteria = [],
241
+ $ offset = 0 ,
242
+ $ limit = self ::DEFAULT_LIMIT ,
243
+ $ order = ''
244
+ ) {
245
+ $ response = $ this ->search (
246
+ $ modelName ,
247
+ $ criteria ,
248
+ $ offset ,
249
+ $ limit ,
250
+ $ order
251
+ );
252
+
253
+ if ($ response ->value () instanceof Value) {
254
+ return $ this ->valueToNative ($ response ->value ());
255
+ }
256
+
257
+ // An error in the criteria or model provided.
258
+
259
+ throw new Exception (sprintf (
260
+ 'Failed to search model %s; response was "%s" ' ,
261
+ $ modelName ,
262
+ $ response ->value ()
263
+ ));
264
+ }
265
+
220
266
/**
221
267
* Example:
222
- * OdooApi::getClient()->search_count ('res.partner', $criteria)
268
+ * OdooApi::getClient()->searchCount ('res.partner', $criteria)
223
269
*
224
270
* @return integer
225
271
*/
@@ -233,7 +279,7 @@ public function searchCount(
233
279
234
280
$ response = $ this ->getXmlRpcClient ('object ' )->send ($ msg );
235
281
236
- return $ response ->value ()-> me [ ' int ' ] ;
282
+ return $ this -> valueToNative ( $ response ->value ()) ;
237
283
}
238
284
239
285
/**
@@ -244,45 +290,117 @@ public function searchRead(
244
290
string $ modelName ,
245
291
array $ criteria = [],
246
292
$ offset = 0 ,
247
- $ limit = 100 ,
293
+ $ limit = self :: DEFAULT_LIMIT ,
248
294
$ order = ''
249
295
) {
250
- $ msg = $ this ->getBaseObjectRequest ($ modelName , 'search_read ' );
296
+ if (version_compare ('8.0 ' , $ this ->serverVersion ) === 1 ) {
297
+ // Less than Odoo 8.0, so search_read is not supported.
298
+ // However, we will emulate it.
299
+
300
+ $ ids = $ this ->searchArray (
301
+ $ modelName ,
302
+ $ criteria ,
303
+ $ offset ,
304
+ $ limit ,
305
+ $ order
306
+ );
307
+
308
+ return $ this ->read ($ modelName , $ ids );
309
+ } else {
310
+ $ msg = $ this ->getBaseObjectRequest ($ modelName , 'search_read ' );
251
311
252
- $ msg ->addParam ($ this ->nativeToValue ($ criteria ));
312
+ $ msg ->addParam ($ this ->nativeToValue ($ criteria ));
253
313
254
- // To be fixed when we have Odoo 8 available to develop against.
314
+ $ msg ->addParam ($ this ->intValue ($ offset ));
315
+ $ msg ->addParam ($ this ->intValue ($ limit ));
316
+ $ msg ->addParam ($ this ->stringValue ($ order ));
255
317
256
- //$msg->addParam($this->stringValue('id'));
318
+ $ response = $ this ->getXmlRpcClient ('object ' )->send ($ msg );
319
+ }
257
320
258
- //$msg->addParam($this->stringValue($offset)); // offset
259
- //$msg->addParam($this->intValue($limit)); // limit
260
- //$msg->addParam($this->stringValue($order)); // order, CSV list
261
- //$msg->addParam($this->structValue(['fields' => $this->arrayValue(['id', 'name'])]));
321
+ return $ response ;
322
+ }
262
323
263
- $ response = $ this ->getXmlRpcClient ('object ' )->send ($ msg );
324
+ /**
325
+ * Same as searchRead but returning a native PHP array.
326
+ */
327
+ public function searchReadArray (
328
+ string $ modelName ,
329
+ array $ criteria = [],
330
+ $ offset = 0 ,
331
+ $ limit = self ::DEFAULT_LIMIT ,
332
+ $ order = ''
333
+ ) {
334
+ $ response = $ this ->searchRead (
335
+ $ modelName ,
336
+ $ criteria ,
337
+ $ offset ,
338
+ $ limit ,
339
+ $ order
340
+ );
264
341
265
- return $ response ;
342
+ return $ this -> valueToNative ( $ response-> value ()) ;
266
343
}
267
344
268
345
/**
269
- * $criteria is an array of IDs.
346
+ * @param array $instanceIds list of model instance IDs to read and return
347
+ * @return Response
270
348
*/
271
349
public function read (
272
350
string $ modelName ,
273
- array $ criteria = []
351
+ array $ instanceIds = []
274
352
) {
275
353
$ msg = $ this ->getBaseObjectRequest ($ modelName , 'read ' );
276
354
277
- $ msg ->addParam ($ this ->nativeToValue ($ criteria ));
355
+ $ msg ->addParam ($ this ->nativeToValue ($ instanceIds ));
278
356
279
357
$ response = $ this ->getXmlRpcClient ('object ' )->send ($ msg );
280
358
281
359
return $ response ;
282
360
}
283
361
362
+ /**
363
+ * Same as read() but returns a native array.
364
+ */
365
+ public function readArray (
366
+ string $ modelName ,
367
+ array $ instanceIds = []
368
+ ) {
369
+ $ response = $ this ->read (
370
+ $ modelName ,
371
+ $ instanceIds
372
+ );
373
+
374
+ if ($ response ->value () instanceof Value) {
375
+ return $ this ->valueToNative ($ response ->value ());
376
+ }
377
+
378
+ // An error in the instanceIds or model provided.
379
+
380
+ throw new Exception (sprintf (
381
+ 'Failed to read model %s; response was "%s" ' ,
382
+ $ modelName ,
383
+ $ response ->value ()
384
+ ));
385
+ }
386
+
387
+ /**
388
+ * Get the server version information.
389
+ *
390
+ * @return array
391
+ */
392
+ public function version ()
393
+ {
394
+ $ msg = new Request ('version ' );
395
+
396
+ $ response = $ this ->getXmlRpcClient ('common ' )->send ($ msg );
397
+
398
+ return $ this ->valueToNative ($ response ->value ());
399
+ }
400
+
284
401
//
285
402
// TODO: actions to implement = create write unlink
403
+ // Also: fields_get, version
286
404
//
287
405
288
406
/**
@@ -310,8 +428,7 @@ public function getResourceId(string $externalId, string $model = null)
310
428
311
429
$ criteria [] = ['name ' , '= ' , $ name ];
312
430
313
- $ result = $ this ->search ('ir.model.data ' , $ criteria );
314
- $ irModelDataIds = $ this ->valueToNative ($ result ->value ());
431
+ $ irModelDataIds = $ this ->searchArray ('ir.model.data ' , $ criteria );
315
432
$ irModelDataId = collect ($ irModelDataIds )->first ();
316
433
317
434
if ($ irModelDataId === null ) {
@@ -321,8 +438,9 @@ public function getResourceId(string $externalId, string $model = null)
321
438
322
439
// Now read the full record to get the resource ID.
323
440
324
- $ irModelDataArray = $ this ->valueToNative (
325
- $ this ->read ('ir.model.data ' , [$ irModelDataId ])->value ()
441
+ $ irModelDataArray = $ this ->readArray (
442
+ 'ir.model.data ' ,
443
+ [$ irModelDataId ]
326
444
);
327
445
$ irModelData = collect ($ irModelDataArray )->first ();
328
446
0 commit comments