Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add builder for sorting list calls #37

Merged
merged 1 commit into from
Jul 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Added list sort builder

## 0.5.0

- Fixed issue with sending invoice models fields that are only write-on-create
Expand Down
34 changes: 30 additions & 4 deletions docs/source/api-calls/builders.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

Pagination, Filters, and Includes
=================================
Pagination, Filters, Includes, and Sorting
==========================================

:doc:`list<get-list>` calls take a list of builder objects that can be used to paginate, filter, and include
:doc:`list<get-list>` calls take a list of builder objects that can be used to paginate, filter, sort, and include
optional data in the response. See `FreshBooks API - Parameters <https://www.freshbooks.com/api/parameters>`_
documentation.

Expand Down Expand Up @@ -109,6 +109,32 @@ o include the data in the response of the updated resource:
'email' => 'john.doe@abcorp.com'
);

$newClient = $freshBooksClient->clients()->create($accountId, data: $clientData);
$newClient = $freshBooksClient->clients()->create($accountId, data: $clientData, includes: $includes);

echo $client->outstanding_balance->amount; // null, new client has no balance

Sorting
-------

To sort the results of a list call by supported fields (see the documentation for that resource) a
``SortBuilder` can be used.

.. code-block:: php
use amcintosh\FreshBooks\Builder\SortBuilder;

$sort = new SortBuilder();
$sort->ascending("invoice_date");

$invoices = $freshBooksClient->invoices()->list($accountId, builders: [$sort]);

to sort by the invoice date in ascending order, or:

.. code-block:: php
use amcintosh\FreshBooks\Builder\SortBuilder;

$sort = new SortBuilder();
$sort->descending("invoice_date");

$invoices = $freshBooksClient->invoices()->list($accountId, builders: [$sort]);

for descending order.
94 changes: 94 additions & 0 deletions src/Builder/SortBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

declare(strict_types=1);

namespace amcintosh\FreshBooks\Builder;

use amcintosh\FreshBooks\Builder\BuilderInterface;

/**
* Builder for making sorted list queries.
*
* @package amcintosh\FreshBooks\Builder
* @link https://www.freshbooks.com/api/parameters
*/
class SortBuilder implements BuilderInterface
{
/**
* Builder for including sort by field data in a list request.
*
* @return void
*/
public function __construct()
{
$this->sortKey = null;
$this->isAscending = true;
}

/**
* Alias for ascending().
*
* @param string $key The field for the resource list to be sorted by.
* @return void
*/
public function asc(string $key): void
{
$this->ascending($key);
}

/**
* Add a sort by the field in ascending order.
*
* @param string $key The field for the resource list to be sorted by.
* @return void
*/
public function ascending(string $key): void
{
$this->sortKey = $key;
$this->isAscending = true;
}

/**
* Alias for descending().
*
* @param string $key The field for the resource list to be sorted by.
* @return void
*/
public function desc(string $key): void
{
$this->descending($key);
}

/**
* Add a sort by the field in descending order.
*
* @param string $key The field for the resource list to be sorted by.
* @return void
*/
public function descending(string $key): void
{
$this->sortKey = $key;
$this->isAscending = false;
}

/**
* Builds the query string parameters from the Builder.
*
* @param string $resourceName The type of resource to generate the query string for.
* Eg. AccountingResource, ProjectsResource
* @return string The built query string
*/
public function build(string $resourceName = null): string
{
if (is_null($this->sortKey)) {
return '';
}

if (is_null($resourceName) or in_array($resourceName, ['AccountingResource', 'EventsResource'], true)) {
$suffix = $this->isAscending ? '_asc' : '_desc';
return '&sort=' . $this->sortKey . $suffix;
}
$negate = $this->isAscending ? '' : '-';
return '&sort=' . $negate . $this->sortKey;
}
}
76 changes: 76 additions & 0 deletions tests/Builder/SortBuilderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

namespace amcintosh\FreshBooks\Tests\Builder;

use DateTime;
use PHPUnit\Framework\TestCase;
use amcintosh\FreshBooks\Builder\SortBuilder;

final class SortBuilderTest extends TestCase
{
public function testSortBuildAccountingAscending(): void
{
$builder = new SortBuilder();
$builder->ascending("invoice_date");

$this->assertSame('&sort=invoice_date_asc', $builder->build('AccountingResource'));
}

public function testSortBuildAccountingAsc(): void
{
$builder = new SortBuilder();
$builder->asc("invoice_date");

$this->assertSame('&sort=invoice_date_asc', $builder->build('AccountingResource'));
}

public function testSortBuildAccountingDescending(): void
{
$builder = new SortBuilder();
$builder->descending("invoice_date");

$this->assertSame('&sort=invoice_date_desc', $builder->build('AccountingResource'));
}

public function testSortBuildAccountingDesc(): void
{
$builder = new SortBuilder();
$builder->desc("invoice_date");

$this->assertSame('&sort=invoice_date_desc', $builder->build('AccountingResource'));
}

public function testSortBuildProjectAscending(): void
{
$builder = new SortBuilder();
$builder->ascending("due_date");

$this->assertSame('&sort=due_date', $builder->build('ProjectsResource'));
}

public function testSortBuildProjectAsc(): void
{
$builder = new SortBuilder();
$builder->asc("due_date");

$this->assertSame('&sort=due_date', $builder->build('ProjectsResource'));
}

public function testSortBuildProjectDescending(): void
{
$builder = new SortBuilder();
$builder->descending("due_date");

$this->assertSame('&sort=-due_date', $builder->build('ProjectsResource'));
}

public function testSortBuildProjectDesc(): void
{
$builder = new SortBuilder();
$builder->desc("due_date");

$this->assertSame('&sort=-due_date', $builder->build('ProjectsResource'));
}
}