Skip to content

Commit 183d2bc

Browse files
committed
Additional *Array() convenience methods; emulate searchRead for Odoo <8.0
1 parent a7b48bb commit 183d2bc

File tree

2 files changed

+162
-24
lines changed

2 files changed

+162
-24
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,26 @@ $client->searchCount('res.partner', $criteria);
7171
$client->read('res.partner', [17858, 17852])->value()->me['array']
7272
```
7373

74+
# Query methods
75+
76+
The following methods are supported and will return an XML-RPC response:
77+
78+
* search()
79+
* searchRead()
80+
* read()
81+
82+
The following helper functions return a native PHp type insead:
83+
84+
* searchArray - array
85+
* searchReadArray - array
86+
* readArray - array
87+
* searchCount - integer
88+
* getResourceId - integer
89+
90+
Note that `searchRead` will emulate the server's `search_read` for
91+
Odoo versions less than 8.0 (OpenERP) but use the native `search_read`
92+
for Odoo 8.0 upwards.
93+
7494
# TODO
7595

7696
* An elegant way to parse the results, as the `Value` objects can be

src/OdooClient.php

Lines changed: 142 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)