@@ -26,6 +26,8 @@ class OdooClient
2626 const TYPE_DOUBLE = 'double ' ;
2727 const TYPE_NULL = 'null ' ;
2828
29+ const DEFAULT_LIMIT = 100 ;
30+
2931 /**
3032 *
3133 */
@@ -41,6 +43,11 @@ class OdooClient
4143 */
4244 protected $ userId ;
4345
46+ /**
47+ * The version of the server, fetched when logging in.
48+ */
49+ protected $ serverVersion ;
50+
4451 /**
4552 * Config data.
4653 */
@@ -131,10 +138,16 @@ public function getUserId()
131138
132139 // Grab the User ID.
133140
134- $ userId = $ response ->value ()-> me [ ' int ' ] ;
141+ $ this -> userId = $ this -> valueToNative ( $ response ->value ()) ;
135142
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 ;
138151 }
139152
140153 throw new Exception (sprintf (
@@ -201,7 +214,7 @@ public function search(
201214 string $ modelName ,
202215 array $ criteria = [],
203216 $ offset = 0 ,
204- $ limit = 100 ,
217+ $ limit = self :: DEFAULT_LIMIT ,
205218 $ order = ''
206219 ) {
207220 $ msg = $ this ->getBaseObjectRequest ($ modelName , 'search ' );
@@ -217,9 +230,42 @@ public function search(
217230 return $ response ;
218231 }
219232
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+
220266 /**
221267 * Example:
222- * OdooApi::getClient()->search_count ('res.partner', $criteria)
268+ * OdooApi::getClient()->searchCount ('res.partner', $criteria)
223269 *
224270 * @return integer
225271 */
@@ -233,7 +279,7 @@ public function searchCount(
233279
234280 $ response = $ this ->getXmlRpcClient ('object ' )->send ($ msg );
235281
236- return $ response ->value ()-> me [ ' int ' ] ;
282+ return $ this -> valueToNative ( $ response ->value ()) ;
237283 }
238284
239285 /**
@@ -244,45 +290,117 @@ public function searchRead(
244290 string $ modelName ,
245291 array $ criteria = [],
246292 $ offset = 0 ,
247- $ limit = 100 ,
293+ $ limit = self :: DEFAULT_LIMIT ,
248294 $ order = ''
249295 ) {
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 ' );
251311
252- $ msg ->addParam ($ this ->nativeToValue ($ criteria ));
312+ $ msg ->addParam ($ this ->nativeToValue ($ criteria ));
253313
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 ));
255317
256- //$msg->addParam($this->stringValue('id'));
318+ $ response = $ this ->getXmlRpcClient ('object ' )->send ($ msg );
319+ }
257320
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+ }
262323
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+ );
264341
265- return $ response ;
342+ return $ this -> valueToNative ( $ response-> value ()) ;
266343 }
267344
268345 /**
269- * $criteria is an array of IDs.
346+ * @param array $instanceIds list of model instance IDs to read and return
347+ * @return Response
270348 */
271349 public function read (
272350 string $ modelName ,
273- array $ criteria = []
351+ array $ instanceIds = []
274352 ) {
275353 $ msg = $ this ->getBaseObjectRequest ($ modelName , 'read ' );
276354
277- $ msg ->addParam ($ this ->nativeToValue ($ criteria ));
355+ $ msg ->addParam ($ this ->nativeToValue ($ instanceIds ));
278356
279357 $ response = $ this ->getXmlRpcClient ('object ' )->send ($ msg );
280358
281359 return $ response ;
282360 }
283361
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+
284401 //
285402 // TODO: actions to implement = create write unlink
403+ // Also: fields_get, version
286404 //
287405
288406 /**
@@ -310,8 +428,7 @@ public function getResourceId(string $externalId, string $model = null)
310428
311429 $ criteria [] = ['name ' , '= ' , $ name ];
312430
313- $ result = $ this ->search ('ir.model.data ' , $ criteria );
314- $ irModelDataIds = $ this ->valueToNative ($ result ->value ());
431+ $ irModelDataIds = $ this ->searchArray ('ir.model.data ' , $ criteria );
315432 $ irModelDataId = collect ($ irModelDataIds )->first ();
316433
317434 if ($ irModelDataId === null ) {
@@ -321,8 +438,9 @@ public function getResourceId(string $externalId, string $model = null)
321438
322439 // Now read the full record to get the resource ID.
323440
324- $ irModelDataArray = $ this ->valueToNative (
325- $ this ->read ('ir.model.data ' , [$ irModelDataId ])->value ()
441+ $ irModelDataArray = $ this ->readArray (
442+ 'ir.model.data ' ,
443+ [$ irModelDataId ]
326444 );
327445 $ irModelData = collect ($ irModelDataArray )->first ();
328446
0 commit comments