Skip to content

Commit

Permalink
Merged PR 41388: Use do-while loop to fetch more than 1000 API items …
Browse files Browse the repository at this point in the history
…(address books)

## What's being changed

Dotdigital API calls fetch at most 1000 items per call. As currently our API endpoints are implemented we can't exceed that limit. So we added a do-while loop in our addressBooks controller in order to continuously fetch all the api items (addressBooks) for merchants that have more than 1000 address books.

## Why it's being changed

In order to list all the available address books even if those are more than 1000.

## How to review / test this change

- Confirm that you get all the address books
- If you don't have more than 1000 address books in your dotdigital account change the SKIP_LIMIT const in AbstractClient to e.g 100. So if you have 300 address books you should still get all the address books in contact flow modal. Additionally you can put a breakpoint to the do-while loop and to see that process works as expected.

Related work items: #192199
  • Loading branch information
sertlab committed Nov 14, 2022
1 parent b8d5559 commit e9cc34f
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 5 deletions.
15 changes: 13 additions & 2 deletions src/Api/Controller/AddressBooksController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Dotdigital\Flow\Api\Controller;

use Dotdigital\Flow\Core\Framework\Traits\InteractsWithResponseTrait;
use Dotdigital\Flow\Service\Client\AbstractClient;
use Dotdigital\Flow\Service\Client\DotdigitalClientFactory;
use Shopware\Core\Framework\Routing\Annotation\Acl;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
Expand Down Expand Up @@ -35,8 +36,18 @@ public function __construct(
*/
public function showAddressBooks(): JsonResponse
{
$addressBooks = $this->dotdigitalClientFactory->createClient()->getAddressBooks();
$addressBooks = [];
do {
$addressBooksCollection = $this->dotdigitalClientFactory
->createClient()
->getAddressBooks(\count($addressBooks));

return new JsonResponse($this->dotdigitalCollectionToArray($addressBooks));
$addressBooks = [
...$addressBooks,
...$this->dotdigitalCollectionToArray($addressBooksCollection),
];
} while (\count($addressBooksCollection) === AbstractClient::SELECT_LIMIT);

return new JsonResponse($addressBooks);
}
}
2 changes: 2 additions & 0 deletions src/Service/Client/AbstractClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

class AbstractClient
{
public const SELECT_LIMIT = 1000;

protected LoggerInterface $logger;

private ClientInterface $client;
Expand Down
14 changes: 11 additions & 3 deletions src/Service/Client/DotdigitalClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,21 @@ public function addContact(
}

/**
* Get Collection of address books
* Get Collection of address books.
*
* @throws GuzzleException
*/
public function getAddressBooks(): AddressBookCollection
public function getAddressBooks(int $skipLimit = 0): AddressBookCollection
{
$addressBooksResponse = $this->get(self::GET_ADDRESS_BOOKS_ENDPOINT, []);
$addressBooksResponse = $this->get(
sprintf(
'%s?select=%s&skip=%s',
self::GET_ADDRESS_BOOKS_ENDPOINT,
self::SELECT_LIMIT,
$skipLimit
),
[]
);
$addressBooks = new AddressBookCollection();
foreach ($addressBooksResponse as $addressBook) {
$struct = new AddressBookStruct(
Expand Down
66 changes: 66 additions & 0 deletions tests/PHPUnit/Controller/AddressBooksControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php declare(strict_types=1);

namespace Dotdigital\Tests\Controller;

use DG\BypassFinals;
use Dotdigital\Flow\Api\Controller\AddressBooksController;
use Dotdigital\Flow\Service\Client\DotdigitalClient;
use Dotdigital\Flow\Service\Client\DotdigitalClientFactory;
use Dotdigital\Tests\Traits\InteractWithAddressBooksTrait;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\JsonResponse;

class AddressBooksControllerTest extends TestCase
{
use InteractWithAddressBooksTrait;

private const LIMIT_NOT_EXCEEDED = 900;
private const LIMIT_EXCEEDED = 2500;

private $dotdigitalClientMock;

private $dotdigitalClientFactoryMock;

protected function setUp(): void
{
BypassFinals::enable();
$this->dotdigitalClientFactoryMock = $this->createMock(DotdigitalClientFactory::class);
$this->dotdigitalClientMock = $this->createMock(DotdigitalClient::class);

$this->dotdigitalClientFactoryMock->expects(static::any())
->method('createClient')
->willReturn($this->dotdigitalClientMock);

$this->addressBooksController = new AddressBooksController(
$this->dotdigitalClientFactoryMock
);
}

public function testControllerForLessItemsThanTheApiLimit(): void
{
$this->dotdigitalClientMock->expects(static::any())
->method('getAddressBooks')
->willReturn($this->generateAddressBookCollection(self::LIMIT_NOT_EXCEEDED));

$response = $this->addressBooksController->showAddressBooks();

static::assertInstanceOf(JsonResponse::class, $response);
static::assertEquals(\count(json_decode($response->getContent())), self::LIMIT_NOT_EXCEEDED);
}

public function testControllerForMoreItemsThanTheApiLimit(): void
{
$this->dotdigitalClientMock->expects(static::any())
->method('getAddressBooks')
->willReturnOnConsecutiveCalls(
$this->generateAddressBookCollection(1000),
$this->generateAddressBookCollection(1000),
$this->generateAddressBookCollection(500)
);

$response = $this->addressBooksController->showAddressBooks();

static::assertInstanceOf(JsonResponse::class, $response);
static::assertEquals(\count(json_decode($response->getContent())), self::LIMIT_EXCEEDED);
}
}

0 comments on commit e9cc34f

Please sign in to comment.