Skip to content

Commit

Permalink
Merge 01bef73 into cf8aeef
Browse files Browse the repository at this point in the history
  • Loading branch information
OndraM committed Nov 27, 2017
2 parents cf8aeef + 01bef73 commit f3fcf8d
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
### Added
- `UserMerge` command and `addUserMerge` & `addUserMerges` method for `EventsRequestBuilder`. (Accessible via `$matej->events()->...`).
- `Interaction` command and `addInteraction` & `addInteractions` method for `EventsRequestBuilder`. (Accessible via `$matej->events()->...`).
- `CampaignRequestBuilder` to request batch of recommendations and item sortings for multiple users. (Accessible via `$matej->campaign()->...`).

### Fixed
- Return types of methods in `RequestBuilderFactory` were not defined (and were not guessable by an IDE) for PHP 5 version.
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ $response = $matej->request()
->send();
```

### Request batch of recommendations/item sortings

Use `campaign()` builder to request batch of recommendations or item sorting for multiple users.
Typical use case for this is generating emailing campaigns.

```php
$matej = new Matej('accountId', 'apikey');

$response = $matej->request()
->campaign()
// Request item sortings
->addSorting(Sorting::create('user-id', ['item-id-1', 'item-id-2', 'item-id-3']))
->addSortings([/* array of Sorting objects */])
// Request user-based recommendations
->addRecommendation(UserRecommendation::create('user-id', 10, 'emailing', 1.0, 3600))
->addRecommendations([/* array of UserRecommendation objects */])
->send();
```

## Changelog
For latest changes see [CHANGELOG.md](CHANGELOG.md) file. We follow [Semantic Versioning](http://semver.org/).

Expand Down
67 changes: 67 additions & 0 deletions src/RequestBuilder/CampaignRequestBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php declare(strict_types=1);

namespace Lmc\Matej\RequestBuilder;

use Fig\Http\Message\RequestMethodInterface;
use Lmc\Matej\Exception\LogicException;
use Lmc\Matej\Model\Command\AbstractCommand;
use Lmc\Matej\Model\Command\Sorting;
use Lmc\Matej\Model\Command\UserRecommendation;
use Lmc\Matej\Model\Request;

class CampaignRequestBuilder extends AbstractRequestBuilder
{
protected const ENDPOINT_PATH = '/campaign';

/** @var AbstractCommand[] */
protected $commands = [];

public function addRecommendation(UserRecommendation $recommendation): self
{
$this->commands[] = $recommendation;

return $this;
}

/**
* @param UserRecommendation[] $recommendations
* @return self
*/
public function addRecommendations(array $recommendations): self
{
foreach ($recommendations as $recommendation) {
$this->addRecommendation($recommendation);
}

return $this;
}

public function addSorting(Sorting $sorting): self
{
$this->commands[] = $sorting;

return $this;
}

/**
* @param Sorting[] $sortings
* @return self
*/
public function addSortings(array $sortings): self
{
foreach ($sortings as $sorting) {
$this->addSorting($sorting);
}

return $this;
}

public function build(): Request
{
if (empty($this->commands)) {
throw new LogicException('At least one command must be added to the builder before sending the request');
}

return new Request(self::ENDPOINT_PATH, RequestMethodInterface::METHOD_POST, $this->commands);
}
}
8 changes: 8 additions & 0 deletions src/RequestBuilder/RequestBuilderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ public function events(): EventsRequestBuilder
return $this->createConfiguredBuilder(EventsRequestBuilder::class);
}

/**
* @return CampaignRequestBuilder
*/
public function campaign(): CampaignRequestBuilder
{
return $this->createConfiguredBuilder(CampaignRequestBuilder::class);
}

// TODO: builders for other endpoints

/**
Expand Down
93 changes: 93 additions & 0 deletions tests/RequestBuilder/CampaignRequestBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php declare(strict_types=1);

namespace Lmc\Matej\RequestBuilder;

use Fig\Http\Message\RequestMethodInterface;
use Lmc\Matej\Exception\LogicException;
use Lmc\Matej\Http\RequestManager;
use Lmc\Matej\Model\Command\Sorting;
use Lmc\Matej\Model\Command\UserRecommendation;
use Lmc\Matej\Model\Request;
use Lmc\Matej\Model\Response;
use PHPUnit\Framework\TestCase;

/**
* @covers \Lmc\Matej\RequestBuilder\CampaignRequestBuilder
* @covers \Lmc\Matej\RequestBuilder\AbstractRequestBuilder
*/
class CampaignRequestBuilderTest extends TestCase
{
/** @test */
public function shouldThrowExceptionWhenBuildingEmptyCommands(): void
{
$builder = new CampaignRequestBuilder();

$this->expectException(LogicException::class);
$this->expectExceptionMessage('At least one command must be added to the builder');
$builder->build();
}

/** @test */
public function shouldBuildRequestWithCommands(): void
{
$builder = new CampaignRequestBuilder();

$recommendationCommand1 = UserRecommendation::create('userId1', 1, 'scenario1', 1.0, 600);
$recommendationCommand2 = UserRecommendation::create('userId2', 2, 'scenario2', 0.5, 700);
$recommendationCommand3 = UserRecommendation::create('userId3', 3, 'scenario3', 0.0, 800);
$builder->addRecommendation($recommendationCommand1);
$builder->addRecommendations([$recommendationCommand2, $recommendationCommand3]);

$sortingCommand1 = Sorting::create('userId1', ['itemId1', 'itemId2']);
$sortingCommand2 = Sorting::create('userId2', ['itemId2', 'itemId3']);
$sortingCommand3 = Sorting::create('userId3', ['itemId3', 'itemId4']);

$builder->addSorting($sortingCommand1);
$builder->addSortings([$sortingCommand2, $sortingCommand3]);

$request = $builder->build();

$this->assertInstanceOf(Request::class, $request);
$this->assertSame(RequestMethodInterface::METHOD_POST, $request->getMethod());
$this->assertSame('/campaign', $request->getPath());

$requestData = $request->getData();
$this->assertCount(6, $requestData);
$this->assertContains($recommendationCommand1, $requestData);
$this->assertContains($recommendationCommand2, $requestData);
$this->assertContains($recommendationCommand3, $requestData);
$this->assertContains($sortingCommand1, $requestData);
$this->assertContains($sortingCommand2, $requestData);
$this->assertContains($sortingCommand3, $requestData);
}

/** @test */
public function shouldThrowExceptionWhenSendingCommandsWithoutRequestManager(): void
{
$builder = new CampaignRequestBuilder();

$builder->addSorting(Sorting::create('userId1', ['itemId1', 'itemId2']));

$this->expectException(LogicException::class);
$this->expectExceptionMessage('Instance of RequestManager must be set to request builder');
$builder->send();
}

/** @test */
public function shouldSendRequestViaRequestManager(): void
{
$requestManagerMock = $this->createMock(RequestManager::class);
$requestManagerMock->expects($this->once())
->method('sendRequest')
->with($this->isInstanceOf(Request::class))
->willReturn(new Response(0, 0, 0, 0));

$builder = new CampaignRequestBuilder();
$builder->setRequestManager($requestManagerMock);

$builder->addRecommendation(UserRecommendation::create('userId1', 1, 'scenario1', 1.0, 3600));
$builder->addSorting(Sorting::create('userId1', ['itemId1', 'itemId2']));

$builder->send();
}
}
6 changes: 6 additions & 0 deletions tests/RequestBuilder/RequestBuilderFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Lmc\Matej\Http\RequestManager;
use Lmc\Matej\Model\Command\ItemProperty;
use Lmc\Matej\Model\Command\ItemPropertySetup;
use Lmc\Matej\Model\Command\Sorting;
use Lmc\Matej\Model\Request;
use Lmc\Matej\Model\Response;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -57,10 +58,15 @@ public function provideBuilderMethods(): array
$builder->addItemProperty(ItemProperty::create('item-id', []));
};

$campaignInit = function (CampaignRequestBuilder $builder): void {
$builder->addSorting(Sorting::create('item-id', ['item1', 'item2']));
};

return [
['setupItemProperties', ItemPropertiesSetupRequestBuilder::class, $itemPropertiesSetupInit],
['deleteItemProperties', ItemPropertiesSetupRequestBuilder::class, $itemPropertiesSetupInit],
['events', EventsRequestBuilder::class, $eventInit],
['campaign', CampaignRequestBuilder::class, $campaignInit],
];
}
}

0 comments on commit f3fcf8d

Please sign in to comment.