diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 41cef6c..7e0764d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-version: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4'] + php-version: ['8.0', '8.1', '8.2', '8.3', '8.4'] steps: - name: Checkout uses: actions/checkout@v2 @@ -23,7 +23,7 @@ jobs: - name: Run Tests run: vendor/bin/phpunit --coverage-clover ./coverage.xml - name: Upload Coverage - if: ${{ matrix.php-version == '7.4' }} + if: ${{ matrix.php-version == '8.2' }} uses: codecov/codecov-action@v1 with: file: ./coverage.xml diff --git a/LICENSE b/LICENSE index f9f0c99..ab5ad02 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016, 2017, 2018, 2019, 2020 Gravity Boulevard, LLC +Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Gravity Boulevard, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index f587bf7..81a1456 100644 --- a/README.md +++ b/README.md @@ -2,25 +2,11 @@ [![License](https://img.shields.io/packagist/l/holidayapi/holidayapi-php?style=for-the-badge)](https://github.com/holidayapi/holidayapi-php/blob/master/LICENSE) ![PHP Version](https://img.shields.io/packagist/php-v/holidayapi/holidayapi-php?style=for-the-badge) -[![Test Status](https://img.shields.io/github/workflow/status/joshtronic/holidayapi-php/Test?style=for-the-badge)](https://github.com/joshtronic/holidayapi-php/actions) -[![Code Coverage](https://img.shields.io/codecov/c/github/joshtronic/holidayapi-php?style=for-the-badge)](https://codecov.io/gh/joshtronic/holidayapi-php) +[![Code Coverage](https://img.shields.io/codecov/c/github/holidayapi/holidayapi-php?style=for-the-badge)](https://codecov.io/gh/holidayapi/holidayapi-php) Official PHP library for [Holiday API](https://holidayapi.com) providing quick and easy access to holiday information from applications written in PHP. -## Migrating from 1.x - -Please note, version 2.x of this library is a full rewrite of the 1.x series. -The interfacing to the library has been simplified and existing applications -upgrading to 2.x will need to be updated. - -| Version 1.x Syntax (Old) | Version 2.x Syntax (New) | -|--------------------------------------------|-----------------------------------------------------------| -| `$holiday_api = new \HolidayAPI\v1($key);` | `$holiday_api = new \HolidayAPI\Client(['key' => $key]);` | - -Version 1.x of the library can still be found -[here](https://github.com/joshtronic/php-holidayapi). - ## Documentation Full documentation of the Holiday API endpoints is available @@ -252,3 +238,29 @@ $holiday_api->holidays([ 'year' => 2019, ]); ``` + +### Workday + +#### Fetch workday 7 business days after a date + +```php +workday([ + 'country' => 'US', + 'start' => '2019-07-01', + 'days' => 7, +]); +``` + +### Workdays + +#### Fetch number of workdays between two dates + +```php +workdays([ + 'country' => 'US', + 'start' => '2019-07-01', + 'end' => '2019-07-10', +]); +``` diff --git a/composer.json b/composer.json index c1c0886..3129ca8 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "holidayapi/holidayapi-php", "description": "Official PHP library for Holiday API", - "version": "2.2.2", + "version": "4.0.0", "type": "library", "keywords": [ "calendar", @@ -17,14 +17,21 @@ "homepage": "https://holidayapi.com" }], "require": { - "php": ">=5.3" + "php": ">=8.0", + "ext-json": "*", + "ext-curl": "*" }, "require-dev": { - "phpunit/phpunit": ">=4" + "phpunit/phpunit": "^9.0" }, "autoload": { "psr-4": { "HolidayAPI\\": "src/" } + }, + "autoload-dev": { + "psr-4": { + "HolidayAPI\\Tests\\": "tests/" + } } } diff --git a/phpunit.xml b/phpunit.xml index fa05f6b..92f2230 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,6 +1,7 @@ request('holidays', $request); } @@ -82,5 +71,15 @@ class Client { return $this->request('languages', $request); } + + public function workday($request) + { + return $this->request('workday', $request); + } + + public function workdays($request) + { + return $this->request('workdays', $request); + } } diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 30a96b3..14f83c7 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,56 +2,72 @@ namespace HolidayAPI\Tests; use HolidayAPI\Client; use HolidayAPI\Request; +use PHPUnit\Framework\TestCase; -require __DIR__ . '/../vendor/autoload.php'; - -if ( - !class_exists('\PHPUnit_Framework_TestCase') - && class_exists('\PHPUnit\Framework\TestCase') -) { - class_alias('\PHPUnit\Framework\TestCase', '\PHPUnit_Framework_TestCase'); -} - -class ClientTest extends \PHPUnit_Framework_TestCase +class ClientTest extends TestCase { const BASE_URL = 'https://holidayapi.com/v1/'; const KEY = '8e4de28c-4b18-49f0-9aba-0bd6b424fc38'; public function testMissingKey() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + try { - $client = new Client(array()); + new Client(array()); } catch (\Exception $e) { - $this->assertRegExp('/missing api key/i', $e->getMessage()); + $this->$assertRegExp('/missing api key/i', $e->getMessage()); } } public function testInvalidKey() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + try { - $client = new Client(array( + new Client(array( 'key' => 'zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz', )); } catch (\Exception $e) { - $this->assertRegExp('/invalid api key/i', $e->getMessage()); + $this->$assertRegExp('/invalid api key/i', $e->getMessage()); } } public function testVersionTooLow() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + try { - $client = new Client(array('key' => self::KEY, 'version' => 0)); + new Client(array('key' => self::KEY, 'version' => 0)); } catch (\Exception $e) { - $this->assertRegExp('/invalid version/i', $e->getMessage()); + $this->$assertRegExp('/invalid version/i', $e->getMessage()); } } public function testVersionTooHigh() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + try { - $client = new Client(array('key' => self::KEY, 'version' => 2)); + new Client(array('key' => self::KEY, 'version' => 2)); } catch (\Exception $e) { - $this->assertRegExp('/invalid version/i', $e->getMessage()); + $this->$assertRegExp('/invalid version/i', $e->getMessage()); } } @@ -97,108 +113,6 @@ class ClientTest extends \PHPUnit_Framework_TestCase ), $client->countries()); } - public function testSearchCountries() - { - $url = self::BASE_URL . 'countries?key=' . self::KEY . '&search=Sao'; - - $request = new Request(array( - 'execute' => array( - $url => function () - { - return json_encode(array( - 'status' => 200, - 'countries' => array( - array( - 'code' => 'ST', - 'name' => 'Sao Tome and Principle', - ), - ), - )); - }, - ), - )); - - $client = new Client(array('key' => self::KEY, 'handler' => $request)); - - $this->assertEquals(array( - 'status' => 200, - 'countries' => array( - array( - 'code' => 'ST', - 'name' => 'Sao Tome and Principle', - ), - ), - ), $client->countries(array('search' => 'Sao'))); - } - - public function testReturnCountryByCode() - { - $url = self::BASE_URL . 'countries?key=' . self::KEY . '&country=ST'; - - $request = new Request(array( - 'execute' => array( - $url => function () - { - return json_encode(array( - 'status' => 200, - 'countries' => array( - array( - 'code' => 'ST', - 'name' => 'Sao Tome and Principle', - ), - ), - )); - }, - ), - )); - - $client = new Client(array('key' => self::KEY, 'handler' => $request)); - - $this->assertEquals(array( - 'status' => 200, - 'countries' => array( - array( - 'code' => 'ST', - 'name' => 'Sao Tome and Principle', - ), - ), - ), $client->countries(array('country' => 'ST'))); - } - - public function testReturnCountryWithPublic() - { - $url = self::BASE_URL . 'countries?key=' . self::KEY . '&public=1'; - - $request = new Request(array( - 'execute' => array( - $url => function () - { - return json_encode(array( - 'status' => 200, - 'countries' => array( - array( - 'code' => 'ST', - 'name' => 'Sao Tome and Principle', - ), - ), - )); - }, - ), - )); - - $client = new Client(array('key' => self::KEY, 'handler' => $request)); - - $this->assertEquals(array( - 'status' => 200, - 'countries' => array( - array( - 'code' => 'ST', - 'name' => 'Sao Tome and Principle', - ), - ), - ), $client->countries(array('public' => true))); - } - public function testCountriesRaise4xxErrors() { $url = self::BASE_URL . 'countries?key=' . self::KEY; @@ -255,8 +169,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase public function testReturnHolidays() { - $url = self::BASE_URL . 'holidays?key=' . self::KEY - . '&country=US&year=2015&month=7&day=4'; + $url = self::BASE_URL . 'holidays?key=' . self::KEY . '&country=US&year=2015&month=7&day=4'; $request = new Request(array( 'execute' => array( @@ -297,89 +210,6 @@ class ClientTest extends \PHPUnit_Framework_TestCase ))); } - public function testSearchHolidays() - { - $url = self::BASE_URL . 'holidays?key=' . self::KEY - . '&country=US&year=2015&search=Independence'; - - $request = new Request(array( - 'execute' => array( - $url => function () - { - return json_encode(array( - 'status' => 200, - 'holidays' => array( - array( - 'name' => 'Independence Day', - 'date' => '2015-07-04', - 'observed' => '2015-07-03', - 'public' => true, - ), - ), - )); - }, - ), - )); - - $client = new Client(array('key' => self::KEY, 'handler' => $request)); - - $this->assertEquals(array( - 'status' => 200, - 'holidays' => array( - array( - 'name' => 'Independence Day', - 'date' => '2015-07-04', - 'observed' => '2015-07-03', - 'public' => true, - ), - ), - ), $client->holidays(array( - 'country' => 'US', - 'year' => 2015, - 'search' => 'Independence', - ))); - } - - public function testCountryMissing() - { - $client = new Client(array('key' => self::KEY)); - - try { - $client->holidays(array('year' => 2015)); - } catch (\Exception $e) { - $this->assertRegExp('/missing country/i', $e->getMessage()); - } - } - - public function testYearMissing() - { - $client = new Client(array('key' => self::KEY)); - - try { - $client->holidays(array('country' => 'US')); - } catch (\Exception $e) { - $this->assertRegExp('/missing year/i', $e->getMessage()); - } - } - - public function testBothPreviousAndUpcoming() - { - $client = new Client(array('key' => self::KEY)); - - try { - $client->holidays(array( - 'country' => 'US', - 'year' => 2015, - 'month' => 7, - 'day' => 4, - 'upcoming' => true, - 'previous' => true, - )); - } catch (\Exception $e) { - $this->assertRegExp('/previous and upcoming/i', $e->getMessage()); - } - } - public function testHolidaysRaise4xxErrors() { $url = self::BASE_URL . 'holidays?key=' . self::KEY . '&country=US&year=2019'; @@ -468,74 +298,6 @@ class ClientTest extends \PHPUnit_Framework_TestCase ), $client->languages()); } - public function testSearchLanguages() - { - $url = self::BASE_URL . 'languages?key=' . self::KEY . '&search=Eng'; - - $request = new Request(array( - 'execute' => array( - $url => function () - { - return json_encode(array( - 'status' => 200, - 'languages' => array( - array( - 'code' => 'en', - 'name' => 'English', - ), - ), - )); - }, - ), - )); - - $client = new Client(array('key' => self::KEY, 'handler' => $request)); - - $this->assertEquals(array( - 'status' => 200, - 'languages' => array( - array( - 'code' => 'en', - 'name' => 'English', - ), - ), - ), $client->languages(array('search' => 'Eng'))); - } - - public function testReturnLanguageByCode() - { - $url = self::BASE_URL . 'languages?key=' . self::KEY . '&language=en'; - - $request = new Request(array( - 'execute' => array( - $url => function () - { - return json_encode(array( - 'status' => 200, - 'languages' => array( - array( - 'code' => 'en', - 'name' => 'English', - ), - ), - )); - }, - ), - )); - - $client = new Client(array('key' => self::KEY, 'handler' => $request)); - - $this->assertEquals(array( - 'status' => 200, - 'languages' => array( - array( - 'code' => 'en', - 'name' => 'English', - ), - ), - ), $client->languages(array('language' => 'en'))); - } - public function testLanguagesRaise4xxErrors() { $url = self::BASE_URL . 'languages?key=' . self::KEY; @@ -589,5 +351,189 @@ class ClientTest extends \PHPUnit_Framework_TestCase $this->assertSame('Internal server error', $e->getMessage()); } } + + public function testReturnWorkday() + { + $url = self::BASE_URL . 'workday?key=' . self::KEY . '&country=US&start=2019-07-01&days=10'; + + $request = new Request(array( + 'execute' => array( + $url => function () + { + return json_encode(array( + 'status' => 200, + 'workday' => array( + 'date' => '2019-07-16', + ), + )); + }, + ), + )); + + $client = new Client(array('key' => self::KEY, 'handler' => $request)); + + $this->assertEquals(array( + 'status' => 200, + 'workday' => array( + 'date' => '2019-07-16', + ), + ), $client->workday(array( + 'country' => 'US', + 'start' => '2019-07-01', + 'days' => 10, + ))); + } + + public function testWorkdayRaise4xxErrors() + { + $url = self::BASE_URL . 'workday?key=' . self::KEY . '&country=US&start=2019-07-01&days=10'; + + $request = new Request(array( + 'execute' => array( + $url => function () + { + return json_encode(array( + 'status' => 429, + 'error' => 'Rate limit exceeded', + )); + }, + ), + )); + + $client = new Client(array('key' => self::KEY, 'handler' => $request)); + + try { + $client->workday(array( + 'country' => 'US', + 'start' => '2019-07-01', + 'days' => 10, + )); + } catch (\Exception $e) { + $this->assertSame(429, $e->getCode()); + $this->assertSame('Rate limit exceeded', $e->getMessage()); + } + } + + public function testWorkdayRaise5xxErrors() + { + $url = self::BASE_URL . 'workday?key=' . self::KEY . '&country=US&start=2019-07-01&days=10'; + + $request = new Request(array( + 'execute' => array( + $url => function () + { + return false; + }, + ), + 'error' => array( + $url => function () + { + return 'Internal server error'; + }, + ), + )); + + $client = new Client(array('key' => self::KEY, 'handler' => $request)); + + try { + $client->workday(array( + 'country' => 'US', + 'start' => '2019-07-01', + 'days' => 10, + )); + } catch (\Exception $e) { + $this->assertSame('Internal server error', $e->getMessage()); + } + } + + public function testReturnWorkdays() + { + $url = self::BASE_URL . 'workdays?key=' . self::KEY . '&country=US&start=2019-07-01&end=2019-07-10'; + + $request = new Request(array( + 'execute' => array( + $url => function () + { + return json_encode(array( + 'status' => 200, + 'workdays' => 7, + )); + }, + ), + )); + + $client = new Client(array('key' => self::KEY, 'handler' => $request)); + + $this->assertEquals(array( + 'status' => 200, + 'workdays' => 7, + ), $client->workdays(array( + 'country' => 'US', + 'start' => '2019-07-01', + 'end' => '2019-07-10', + ))); + } + + public function testWorkdaysRaise4xxErrors() + { + $url = self::BASE_URL . 'workdays?key=' . self::KEY . '&country=US&start=2019-07-01&end=2019-07-10'; + + $request = new Request(array( + 'execute' => array( + $url => function () + { + return json_encode(array( + 'status' => 429, + 'error' => 'Rate limit exceeded', + )); + }, + ), + )); + + $client = new Client(array('key' => self::KEY, 'handler' => $request)); + + try { + $client->workdays(array( + 'country' => 'US', + 'start' => '2019-07-01', + 'end' => '2019-07-10', + )); + } catch (\Exception $e) { + $this->assertSame(429, $e->getCode()); + $this->assertSame('Rate limit exceeded', $e->getMessage()); + } + } + + public function testWorkdaysRaise5xxErrors() + { + $url = self::BASE_URL . 'workdays?key=' . self::KEY . '&country=US&start=2019-07-01&end=2019-07-10'; + + $request = new Request(array( + 'execute' => array( + $url => function () + { + return false; + }, + ), + 'error' => array( + $url => function () + { + return 'Internal server error'; + }, + ), + )); + + $client = new Client(array('key' => self::KEY, 'handler' => $request)); + + try { + $client->workdays(array( + 'country' => 'US', + 'start' => '2019-07-01', + 'end' => '2019-07-10', + )); + } catch (\Exception $e) { + $this->assertSame('Internal server error', $e->getMessage()); + } + } } diff --git a/tests/RequestTest.php b/tests/RequestTest.php index 31594f3..f42776d 100644 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -1,18 +1,9 @@ =')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $url = 'https://holidayapi.com'; $request = new Request(array( @@ -38,7 +35,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase try { $request->get($url); } catch (\Exception $e) { - $this->assertRegExp('/empty response/i', $e->getMessage()); + $this->$assertRegExp('/empty response/i', $e->getMessage()); } } }