Skip to content

Commit a085e5c

Browse files
committed
Support returnProperties and includedProperties parameters of ListItems and ListUsers. Send User-Agent HTTP header. Use POST for recomm requests.
1 parent 0bca53a commit a085e5c

29 files changed

Lines changed: 413 additions & 113 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ or
1717
```
1818
{
1919
"require": {
20-
"recombee/php-api-client": "^1.3.2"
20+
"recombee/php-api-client": "^1.4.0"
2121
}
2222
}
2323
```

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
}
1111
],
1212
"require": {
13-
"php": ">=5.4.0",
13+
"php": ">=5.3.0",
1414
"rmccue/requests": "^1.7.0"
1515
},
1616
"require-dev": {
17-
"phpunit/phpunit": ">=4",
17+
"phpunit/phpunit": "^6.1.0",
1818
"phpdocumentor/phpdocumentor": "2.*"
1919
},
2020
"autoload": {

src/RecommApi/Client.php

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Client{
2121
protected $request;
2222
protected $protocol;
2323
protected $base_uri;
24+
protected $options;
2425

2526
/**
2627
* @ignore
@@ -37,14 +38,16 @@ class Client{
3738
* @param string $account Name of your account at Recombee
3839
* @param string $token Secret token
3940
* @param string $protocol Default protocol for sending requests. Possible values: 'http', 'https'.
41+
* @param array $options Other custom options
4042
*/
41-
public function __construct($account, $token, $protocol = 'http') {
43+
public function __construct($account, $token, $protocol = 'http', $options= array()) {
4244
$this->account = $account;
4345
$this->token = $token;
4446
$this->protocol = $protocol;
4547
$this->base_uri = Client::BASE_URI;
4648
if(getenv("RAPI_URI") !== false)
4749
$this->base_uri = getenv("RAPI_URI");
50+
$this->options = $options;
4851
}
4952

5053
/**
@@ -74,7 +77,8 @@ public function send(Requests\Request $request) {
7477
break;
7578

7679
case Requests\Request::HTTP_PUT:
77-
$result = $this->put($uri, $timeout);
80+
$json = json_encode($request->getBodyParameters(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
81+
$result = $this->put($uri, $timeout, $json);
7882
break;
7983

8084
case Requests\Request::HTTP_DELETE:
@@ -101,27 +105,53 @@ public function send(Requests\Request $request) {
101105
}
102106

103107
/* ----------------------- Send requests ----------------------- */
104-
protected function put($uri, $timeout) {
105-
$response = \Requests::put($uri, array(), ['timeout' => $timeout]);
108+
protected function getOptionalHttpHeaders() {
109+
if (isset($this->options['requestsHeaders']))
110+
return $this->options['requestsHeaders'];
111+
return array();
112+
}
113+
114+
protected function getHttpHeaders() {
115+
return array_merge(array('User-Agent' => 'recombee-php-api-client/1.4.0'), $this->getOptionalHttpHeaders());
116+
}
117+
118+
protected function getOptionalRequestOptions() {
119+
if (isset($this->options['requestsOptions']))
120+
return $this->options['requestsOptions'];
121+
return array();
122+
}
123+
124+
protected function put($uri, $timeout, $body) {
125+
$options = array_merge(array('timeout' => $timeout), $this->getOptionalRequestOptions());
126+
$headers = array_merge(array('Content-Type' => 'application/json'), $this->getHttpHeaders());
127+
128+
$response = \Requests::put($uri, $headers, $body, $options);
106129
$this->checkErrors($response);
107130
return $response->body;
108131
}
109132

110133
protected function get($uri, $timeout) {
111-
$response = \Requests::get($uri, array(), ['timeout' => $timeout]);
134+
$options = array_merge(array('timeout' => $timeout), $this->getOptionalRequestOptions());
135+
$headers = $this->getHttpHeaders();
136+
137+
$response = \Requests::get($uri, $headers, $options);
112138
$this->checkErrors($response);
113139
return json_decode($response->body, true);
114140
}
115141

116142
protected function delete($uri, $timeout) {
117-
$response = \Requests::delete($uri, array(), ['timeout' => $timeout]);
143+
$options = array_merge(array('timeout' => $timeout), $this->getOptionalRequestOptions());
144+
$headers = $this->getHttpHeaders();
145+
146+
$response = \Requests::delete($uri, $headers, $options);
118147
$this->checkErrors($response);
119148
return $response->body;
120149
}
121150

122151
protected function post($uri, $timeout, $body) {
123-
$headers = array('Content-Type' => 'application/json');
124-
$response = \Requests::post($uri, $headers, $body, ['timeout' => $timeout]);
152+
$options = array_merge(array('timeout' => $timeout), $this->getOptionalRequestOptions());
153+
$headers = array_merge(array('Content-Type' => 'application/json'), $this->getHttpHeaders());
154+
$response = \Requests::post($uri, $headers, $body, $options);
125155
$this->checkErrors($response);
126156

127157
$json = json_decode($response->body, true);

src/RecommApi/Requests/ItemBasedRecommendation.php

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111

1212
/**
1313
* Recommends set of items that are somehow related to one given item, *X*. Typical scenario for using item-based recommendation is when user *A* is viewing *X*. Then you may display items to the user that he might be also interested in. Item-recommendation request gives you Top-N such items, optionally taking the target user *A* into account.
14+
* It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters.
1415
*/
1516
class ItemBasedRecommendation extends Request {
1617

1718
/**
18-
* @var string $item_id ID of the item recommendations for which are to be generated.
19+
* @var string $item_id ID of the item for which the recommendations are to be generated.
1920
*/
2021
protected $item_id;
2122
/**
@@ -32,7 +33,7 @@ class ItemBasedRecommendation extends Request {
3233
*/
3334
protected $target_user_id;
3435
/**
35-
* @var float $user_impact If *targetUserId* parameter is present, the recommendations are biased towards the user given. Using *userImpact*, you may control this bias. For an extreme case of `userImpact=0.0`, the interactions made by the user are not taken into account at all (with the exception of history-based blacklisting), for `userImpact=1.0`, you'll get user-based recommendation. The default value is `0.1`
36+
* @var float $user_impact If *targetUserId* parameter is present, the recommendations are biased towards the user given. Using *userImpact*, you may control this bias. For an extreme case of `userImpact=0.0`, the interactions made by the user are not taken into account at all (with the exception of history-based blacklisting), for `userImpact=1.0`, you'll get user-based recommendation. The default value is `0`.
3637
*/
3738
protected $user_impact;
3839
/**
@@ -110,17 +111,21 @@ class ItemBasedRecommendation extends Request {
110111
*/
111112
protected $rotation_rate;
112113
/**
113-
* @var float $rotation_time **Expert option** If the *targetUserId* is provided: Taking *rotationRate* into account, specifies how long time it takes to an item to fully recover from the penalization. For example, `rotationTime=7200.0` means that items recommended more than 2 hours ago are definitely not penalized anymore. Currently, the penalization is linear, so for `rotationTime=7200.0`, an item is still penalized by `0.5` to the user after 1 hour.
114+
* @var float $rotation_time **Expert option** If the *targetUserId* is provided: Taking *rotationRate* into account, specifies how long time it takes to an item to recover from the penalization. For example, `rotationTime=7200.0` means that items recommended less than 2 hours ago are penalized.
114115
*/
115116
protected $rotation_time;
117+
/**
118+
* @var $expert_settings Dictionary of custom options.
119+
*/
120+
protected $expert_settings;
116121
/**
117122
* @var array Array containing values of optional parameters
118123
*/
119124
protected $optional;
120125

121126
/**
122127
* Construct the request
123-
* @param string $item_id ID of the item recommendations for which are to be generated.
128+
* @param string $item_id ID of the item for which the recommendations are to be generated.
124129
* @param int $count Number of items to be recommended (N for the top-N recommendation).
125130
* @param array $optional Optional parameters given as an array containing pairs name of the parameter => value
126131
* - Allowed parameters:
@@ -134,7 +139,7 @@ class ItemBasedRecommendation extends Request {
134139
* For the above reasons, we encourage you to set the *targetUserId* even for anonymous/unregistered users (i.e. use their session ID).
135140
* - *userImpact*
136141
* - Type: float
137-
* - Description: If *targetUserId* parameter is present, the recommendations are biased towards the user given. Using *userImpact*, you may control this bias. For an extreme case of `userImpact=0.0`, the interactions made by the user are not taken into account at all (with the exception of history-based blacklisting), for `userImpact=1.0`, you'll get user-based recommendation. The default value is `0.1`
142+
* - Description: If *targetUserId* parameter is present, the recommendations are biased towards the user given. Using *userImpact*, you may control this bias. For an extreme case of `userImpact=0.0`, the interactions made by the user are not taken into account at all (with the exception of history-based blacklisting), for `userImpact=1.0`, you'll get user-based recommendation. The default value is `0`.
138143
* - *filter*
139144
* - Type: string
140145
* - Description: Boolean-returning [ReQL](https://docs.recombee.com/reql.html) expression which allows you to filter recommended items based on the values of their attributes.
@@ -201,7 +206,10 @@ class ItemBasedRecommendation extends Request {
201206
* - Description: **Expert option** If the *targetUserId* is provided: If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per-request in backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example `rotationRate=0.2` for only slight rotation of recommended items.
202207
* - *rotationTime*
203208
* - Type: float
204-
* - Description: **Expert option** If the *targetUserId* is provided: Taking *rotationRate* into account, specifies how long time it takes to an item to fully recover from the penalization. For example, `rotationTime=7200.0` means that items recommended more than 2 hours ago are definitely not penalized anymore. Currently, the penalization is linear, so for `rotationTime=7200.0`, an item is still penalized by `0.5` to the user after 1 hour.
209+
* - Description: **Expert option** If the *targetUserId* is provided: Taking *rotationRate* into account, specifies how long time it takes to an item to recover from the penalization. For example, `rotationTime=7200.0` means that items recommended less than 2 hours ago are penalized.
210+
* - *expertSettings*
211+
* - Type:
212+
* - Description: Dictionary of custom options.
205213
* @throws Exceptions\UnknownOptionalParameterException UnknownOptionalParameterException if an unknown optional parameter is given in $optional
206214
*/
207215
public function __construct($item_id, $count, $optional = array()) {
@@ -220,9 +228,10 @@ public function __construct($item_id, $count, $optional = array()) {
220228
$this->min_relevance = isset($optional['minRelevance']) ? $optional['minRelevance'] : null;
221229
$this->rotation_rate = isset($optional['rotationRate']) ? $optional['rotationRate'] : null;
222230
$this->rotation_time = isset($optional['rotationTime']) ? $optional['rotationTime'] : null;
231+
$this->expert_settings = isset($optional['expertSettings']) ? $optional['expertSettings'] : null;
223232
$this->optional = $optional;
224233

225-
$existing_optional = array('targetUserId','userImpact','filter','booster','allowNonexistent','cascadeCreate','scenario','returnProperties','includedProperties','diversity','minRelevance','rotationRate','rotationTime');
234+
$existing_optional = array('targetUserId','userImpact','filter','booster','allowNonexistent','cascadeCreate','scenario','returnProperties','includedProperties','diversity','minRelevance','rotationRate','rotationTime','expertSettings');
226235
foreach ($this->optional as $key => $value) {
227236
if (!in_array($key, $existing_optional))
228237
throw new UnknownOptionalParameterException($key);
@@ -236,7 +245,7 @@ public function __construct($item_id, $count, $optional = array()) {
236245
* @return static Used HTTP method
237246
*/
238247
public function getMethod() {
239-
return Request::HTTP_GET;
248+
return Request::HTTP_POST;
240249
}
241250

242251
/**
@@ -253,42 +262,44 @@ public function getPath() {
253262
*/
254263
public function getQueryParameters() {
255264
$params = array();
256-
$params['count'] = $this->count;
265+
return $params;
266+
}
267+
268+
/**
269+
* Get body parameters
270+
* @return array Values of body parameters (name of parameter => value of the parameter)
271+
*/
272+
public function getBodyParameters() {
273+
$p = array();
274+
$p['count'] = $this->count;
257275
if (isset($this->optional['targetUserId']))
258-
$params['targetUserId'] = $this->optional['targetUserId'];
276+
$p['targetUserId'] = $this-> optional['targetUserId'];
259277
if (isset($this->optional['userImpact']))
260-
$params['userImpact'] = $this->optional['userImpact'];
278+
$p['userImpact'] = $this-> optional['userImpact'];
261279
if (isset($this->optional['filter']))
262-
$params['filter'] = $this->optional['filter'];
280+
$p['filter'] = $this-> optional['filter'];
263281
if (isset($this->optional['booster']))
264-
$params['booster'] = $this->optional['booster'];
282+
$p['booster'] = $this-> optional['booster'];
265283
if (isset($this->optional['allowNonexistent']))
266-
$params['allowNonexistent'] = $this->optional['allowNonexistent'];
284+
$p['allowNonexistent'] = $this-> optional['allowNonexistent'];
267285
if (isset($this->optional['cascadeCreate']))
268-
$params['cascadeCreate'] = $this->optional['cascadeCreate'];
286+
$p['cascadeCreate'] = $this-> optional['cascadeCreate'];
269287
if (isset($this->optional['scenario']))
270-
$params['scenario'] = $this->optional['scenario'];
288+
$p['scenario'] = $this-> optional['scenario'];
271289
if (isset($this->optional['returnProperties']))
272-
$params['returnProperties'] = $this->optional['returnProperties'];
290+
$p['returnProperties'] = $this-> optional['returnProperties'];
273291
if (isset($this->optional['includedProperties']))
274-
$params['includedProperties'] = $this->optional['includedProperties'];
292+
$p['includedProperties'] = $this-> optional['includedProperties'];
275293
if (isset($this->optional['diversity']))
276-
$params['diversity'] = $this->optional['diversity'];
294+
$p['diversity'] = $this-> optional['diversity'];
277295
if (isset($this->optional['minRelevance']))
278-
$params['minRelevance'] = $this->optional['minRelevance'];
296+
$p['minRelevance'] = $this-> optional['minRelevance'];
279297
if (isset($this->optional['rotationRate']))
280-
$params['rotationRate'] = $this->optional['rotationRate'];
298+
$p['rotationRate'] = $this-> optional['rotationRate'];
281299
if (isset($this->optional['rotationTime']))
282-
$params['rotationTime'] = $this->optional['rotationTime'];
283-
return $params;
284-
}
285-
286-
/**
287-
* Get body parameters
288-
* @return array Values of body parameters (name of parameter => value of the parameter)
289-
*/
290-
public function getBodyParameters() {
291-
$p = array();
300+
$p['rotationTime'] = $this-> optional['rotationTime'];
301+
if (isset($this->optional['expertSettings']))
302+
$p['expertSettings'] = $this-> optional['expertSettings'];
292303
return $p;
293304
}
294305

src/RecommApi/Requests/ListGroups.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ListGroups extends Request {
1919
* Construct the request
2020
*/
2121
public function __construct() {
22-
$this->timeout = 30000;
22+
$this->timeout = 239000;
2323
$this->ensure_https = false;
2424
}
2525

src/RecommApi/Requests/ListItemBookmarks.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ListItemBookmarks extends Request {
2525
*/
2626
public function __construct($item_id) {
2727
$this->item_id = $item_id;
28-
$this->timeout = 1000;
28+
$this->timeout = 100000;
2929
$this->ensure_https = false;
3030
}
3131

src/RecommApi/Requests/ListItemCartAdditions.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ListItemCartAdditions extends Request {
2525
*/
2626
public function __construct($item_id) {
2727
$this->item_id = $item_id;
28-
$this->timeout = 1000;
28+
$this->timeout = 100000;
2929
$this->ensure_https = false;
3030
}
3131

src/RecommApi/Requests/ListItemDetailViews.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ListItemDetailViews extends Request {
2525
*/
2626
public function __construct($item_id) {
2727
$this->item_id = $item_id;
28-
$this->timeout = 1000;
28+
$this->timeout = 100000;
2929
$this->ensure_https = false;
3030
}
3131

src/RecommApi/Requests/ListItemPurchases.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ListItemPurchases extends Request {
2525
*/
2626
public function __construct($item_id) {
2727
$this->item_id = $item_id;
28-
$this->timeout = 1000;
28+
$this->timeout = 100000;
2929
$this->ensure_https = false;
3030
}
3131

src/RecommApi/Requests/ListItemRatings.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ListItemRatings extends Request {
2525
*/
2626
public function __construct($item_id) {
2727
$this->item_id = $item_id;
28-
$this->timeout = 1000;
28+
$this->timeout = 100000;
2929
$this->ensure_https = false;
3030
}
3131

0 commit comments

Comments
 (0)