From c3ff15afad3a9375176deae076167604d72618dc Mon Sep 17 00:00:00 2001 From: Andrew McIntosh Date: Sun, 24 Jul 2022 12:27:20 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20builder=20for=20sorting=20lis?= =?UTF-8?q?t=20calls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #36 --- CHANGELOG.md | 2 + docs/source/api-calls/builders.rst | 34 +++++++++-- src/Builder/SortBuilder.php | 94 ++++++++++++++++++++++++++++++ tests/Builder/SortBuilderTest.php | 76 ++++++++++++++++++++++++ 4 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 src/Builder/SortBuilder.php create mode 100644 tests/Builder/SortBuilderTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index b74c59c..a3a3ec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/docs/source/api-calls/builders.rst b/docs/source/api-calls/builders.rst index 58c486d..86a9d2c 100644 --- a/docs/source/api-calls/builders.rst +++ b/docs/source/api-calls/builders.rst @@ -1,8 +1,8 @@ -Pagination, Filters, and Includes -================================= +Pagination, Filters, Includes, and Sorting +========================================== -:doc:`list` calls take a list of builder objects that can be used to paginate, filter, and include +:doc:`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 `_ documentation. @@ -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. diff --git a/src/Builder/SortBuilder.php b/src/Builder/SortBuilder.php new file mode 100644 index 0000000..2fe3c44 --- /dev/null +++ b/src/Builder/SortBuilder.php @@ -0,0 +1,94 @@ +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; + } +} diff --git a/tests/Builder/SortBuilderTest.php b/tests/Builder/SortBuilderTest.php new file mode 100644 index 0000000..6ea4bc8 --- /dev/null +++ b/tests/Builder/SortBuilderTest.php @@ -0,0 +1,76 @@ +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')); + } +}