From e97edee50842da41761ed874d5b6f887f430bf5d Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Thu, 19 Sep 2019 23:20:15 -0500 Subject: [PATCH 01/14] feat: include all endpoints * Reworked interfacing to drop the versioning in the class name. * Refactored / cleaned up existing code. * Stuck with support for PHP 5.3+ since PHP 5.x still seems to hold majority. * Abstracted request logic to another class for mocking. * Added test suite and hit full code coverage. * Updated readme, included migration guide and the full gamut of examples. * Wired up travis-ci and coveralls for testing and coverage. --- .coveralls.yml | 1 + .gitignore | 6 +- .travis.yml | 46 ++++ LICENSE | 2 +- README.md | 215 ++++++++++++++++-- composer.json | 47 ++-- phpunit.xml | 23 ++ src/Client.php | 112 ++++++++++ src/Request.php | 79 +++++++ src/v1.php | 51 ----- tests/ClientTest.php | 491 ++++++++++++++++++++++++++++++++++++++++++ tests/RequestTest.php | 45 ++++ 12 files changed, 1024 insertions(+), 94 deletions(-) create mode 100644 .coveralls.yml create mode 100644 .travis.yml create mode 100644 phpunit.xml create mode 100644 src/Client.php create mode 100644 src/Request.php delete mode 100644 src/v1.php create mode 100644 tests/ClientTest.php create mode 100644 tests/RequestTest.php diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..9160059 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +service_name: travis-ci diff --git a/.gitignore b/.gitignore index c422267..a2144a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ +composer.lock composer.phar +.phpunit.result.cache /vendor/ - -# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file -# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file -# composer.lock diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..eb67138 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,46 @@ +language: php +dist: bionic +sudo: required + +matrix: + include: + - php: 5.3 + dist: precise + - php: 5.4 + dist: trusty + - php: 5.5 + dist: trusty + - php: 5.6 + dist: trusty + - php: 7.0 + dist: xenial + env: PHPUNIT=5.7 + - php: 7.1 + env: PHPUNIT=7.5 + - php: 7.2 + - php: 7.3 + env: COVERAGE=true + +install: + - composer install + - | + if [[ $PHPUNIT ]]; then + composer require "phpunit/phpunit:$PHPUNIT" + fi + +before_script: + - mkdir -p build/logs + +script: + - | + if [[ $PHPUNIT ]]; then + vendor/bin/phpunit --coverage-clover build/logs/clover.xml + else + phpunit --coverage-clover build/logs/clover.xml + fi + +after_success: + - | + if [[ $COVERAGE ]]; then + php vendor/bin/coveralls --config .coveralls.yml -v + fi diff --git a/LICENSE b/LICENSE index 9ccb0e7..7dcf161 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 Josh Sherman +Copyright (c) 2016, 2017, 2018, 2019 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 6a07365..302867a 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,211 @@ -# php-holidayapi -Official PHP library for [Holiday API](https://holidayapi.com) +# Holiday API PHP Library + +[![License](https://img.shields.io/npm/l/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) +![Build Status](https://img.shields.io/travis/holidayapi/holidayapi-php/master?style=for-the-badge) +[![Coverage Status](https://img.shields.io/coveralls/github/holidayapi/holidayapi-php/master?style=for-the-badge)](https://coveralls.io/github/holidayapi/holidayapi-php?branch=master) + +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 +[here](https://holidayapi.com/docs). ## Installation ```shell -composer require "joshtronic/php-holidayapi:dev-master" +composer require holidayapi/holidayapi-php ``` ## Usage ```php -$hapi = new HolidayAPI\v1('_YOUR_API_KEY_'); +$key = 'Insert your API key here'; +$holiday_api = new \HolidayAPI\Client(['key' => $key]); -$parameters = array( - // Required - 'country' => 'US', - 'year' => 2016, - // Optional - // 'month' => 7, - // 'day' => 4, - // 'previous' => true, - // 'upcoming' => true, - // 'public' => true, - // 'pretty' => true, -); +try { + // Fetch supported countries and subdivisions + $countries = $holiday_api->countries(); -$response = $hapi->holidays($parameters); + // Fetch supported languages + $languages = $holiday_api->languages(); + + // Fetch holidays with minimum parameters + $holidays = $holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + ]); + + var_dump($countries, $languages, $holidays); +} catch (Exception $e) { + var_dump($e); +} ``` +## Examples + +### Countries + +#### Fetch all supported countries + +```php +$holiday_api->countries(); +``` + +#### Search for a country by code or name + +```php +$holiday_api->countries([ + 'search' => 'united', +]); +``` + +### Languages + +#### Fetch all supported languages + +```php +$holiday_api->languages(); +``` + +#### Search for a language by code or name + +```php +$holiday_api->languages([ + 'search' => 'Chinese', +]); +``` + +### Holidays + +#### Fetch holidays for a specific year + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, +]); +``` + +#### Fetch holidays for a specific month + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'month' => 7, +]); +``` + +#### Fetch holidays for a specific day + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'month' => 7, + 'day' => 4, +]); +``` + +#### Fetch upcoming holidays based on a specific date + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'month' => 7, + 'day' => 4, + 'upcoming' => true, +]); +``` + +#### Fetch previous holidays based on a specific date + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'month' => 7, + 'day' => 4, + 'previous' => true, +]); +``` + +#### Fetch only public holidays + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'public' => true, +]); +``` + +#### Fetch holidays for a specific subdivision + +```php +$holiday_api->holidays([ + 'country' => 'GB-ENG', + 'year' => 2019, +]); +``` + +#### Include subdivision holidays with countrywide holidays + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'subdivisions' => true, +]); +``` + +#### Search for a holiday by name + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'search' => 'New Year', +]); +``` + +#### Translate holidays to another language + +```php +$holiday_api->holidays([ + 'country' => 'US', + 'year' => 2019, + 'language' => 'zh', // Chinese (Simplified) +]); +``` + +#### Fetch holidays for multiple countries + +```php +$holiday_api->holidays([ + 'country' => 'US,GB,NZ', + 'year' => 2019, +]); + +$holiday_api->holidays([ + 'country' => ['US', 'GB', 'NZ'], + 'year' => 2019, +]); +``` diff --git a/composer.json b/composer.json index 78f9a03..c6fa09f 100644 --- a/composer.json +++ b/composer.json @@ -1,23 +1,28 @@ { - "name": "joshtronic/php-holidayapi", - "description": "Official PHP library for Holiday API", - "version": "1.0.0", - "type": "library", - "keywords": [ "holiday", "holidays", "holidayapi" ], - "homepage": "https://github.com/joshtronic/php-holidayapi", - "license": "MIT", - "authors": [{ - "name": "Josh Sherman", - "email": "hello@holidayapi.com", - "homepage": "https://holidayapi.com," - }], - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "satooshi/php-coveralls": "~1.0" - }, - "autoload": { - "psr-4": { "HolidayAPI\\": "src/" } - } + "name": "holidayapi/holidayapi-php", + "description": "Official PHP library for Holiday API", + "version": "2.0.0", + "type": "library", + "keywords": [ + "calendar", + "holiday", + "holidays", + "holidayapi" + ], + "homepage": "https://github.com/holidayapi/holidayapi-php", + "license": "MIT", + "authors": [{ + "name": "Josh Sherman", + "email": "hello@holidayapi.com", + "homepage": "https://holidayapi.com" + }], + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "satooshi/php-coveralls": "~1.0" + }, + "autoload": { + "psr-4": { "HolidayAPI\\": "src/" } + } } diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..fa05f6b --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,23 @@ + + + + + tests + + + + + ./src + + + diff --git a/src/Client.php b/src/Client.php new file mode 100644 index 0000000..058f1d6 --- /dev/null +++ b/src/Client.php @@ -0,0 +1,112 @@ +baseUrl = "https://holidayapi.com/v{$version}/"; + $this->key = $options['key']; + + if (isset($options['handler'])) { + $this->handler = $options['handler']; + } else { + $this->handler = new Request(); + } + } + + private function createUrl($endpoint, $request = array()) + { + $parameters = array_merge(array('key' => $this->key), $request); + $parameters = http_build_query($parameters); + + return "{$this->baseUrl}{$endpoint}?{$parameters}"; + } + + private function request($endpoint, $request) + { + return $this->handler->get($this->createUrl($endpoint, $request)); + + /* + $curl = curl_init(); + + curl_setopt_array($curl, array( + CURLOPT_URL => $this->createUrl($endpoint, $request), + CURLOPT_HEADER => false, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_RETURNTRANSFER => true, + )); + + $response = curl_exec($curl); + + if ($error = curl_error($curl)) { + throw new \Exception($error); + } + + curl_close($curl); + $response = json_decode($response, true); + + if (!$response) { + throw new \Exception('Empty response received'); + } + + return $response; + */ + } + + public function countries($request = array()) + { + return $this->request('countries', $request); + } + + public function holidays($request) + { + if (!isset($request['country'])) { + throw new \Exception('Missing country'); + } elseif (!isset($request['year'])) { + throw new \Exception('Missing year'); + } elseif ( + isset($request['previous'], $request['upcoming']) + && $request['previous'] && $request['upcoming'] + ) { + throw new \Exception('Previous and upcoming are mutually exclusive'); + } + + return $this->request('holidays', $request); + } + + public function languages($request = array()) + { + return $this->request('languages', $request); + } +} + diff --git a/src/Request.php b/src/Request.php new file mode 100644 index 0000000..355e69a --- /dev/null +++ b/src/Request.php @@ -0,0 +1,79 @@ +handlers = $handlers; + } + + public function execute($curl) + { + if (isset($this->handlers['execute'])) { + $info = curl_getinfo($curl); + $url = $info['url']; + + if (isset($this->handlers['execute'][$url])) { + return $this->handlers['execute'][$url]($curl); + } + } + + return curl_exec($curl); + } + + public function error($curl) + { + if (isset($this->handlers['error'])) { + $info = curl_getinfo($curl); + $url = $info['url']; + + if (isset($this->handlers['error'][$url])) { + return $this->handlers['error'][$url]($curl); + } + } + + return curl_error($curl); + } + + public function get($url) + { + $curl = curl_init(); + + curl_setopt_array($curl, array( + CURLOPT_URL => $url, + CURLOPT_HEADER => false, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_RETURNTRANSFER => true, + )); + + $response = $this->execute($curl); + + if ($error = $this->error($curl)) { + throw new \Exception($error); + } + + curl_close($curl); + $response = json_decode($response, true); + + if (!$response) { + throw new \Exception('Empty response received'); + } + + if (isset($response['error'])) { + throw new \Exception($response['error'], $response['status']); + } + + return $response; + } +} + diff --git a/src/v1.php b/src/v1.php deleted file mode 100644 index 472bd62..0000000 --- a/src/v1.php +++ /dev/null @@ -1,51 +0,0 @@ -parameters[$variable] = $value; - } - - public function __construct($key = null) - { - if ($key) { - $this->key = $key; - } - } - - public function holidays($parameters = array()) - { - $parameters = array_merge($this->parameters, $parameters); - $parameters = http_build_query($parameters); - - $url = 'https://holidayapi.com/v1/holidays?' . $parameters; - $curl = curl_init(); - - curl_setopt_array($curl, array( - CURLOPT_URL => $url, - CURLOPT_HEADER => false, - CURLOPT_SSL_VERIFYPEER => true, - CURLOPT_RETURNTRANSFER => true, - )); - - $response = curl_exec($curl); - - if ($error = curl_error($curl)) { - return false; - } - - curl_close($curl); - $response = json_decode($response, true); - - if (!$response) { - return false; - } - - return $response; - } -} - diff --git a/tests/ClientTest.php b/tests/ClientTest.php new file mode 100644 index 0000000..c77611a --- /dev/null +++ b/tests/ClientTest.php @@ -0,0 +1,491 @@ +assertRegExp('/missing api key/i', $e->getMessage()); + } + } + + public function testInvalidKey() + { + try { + $client = new Client(array( + 'key' => 'zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz', + )); + } catch (\Exception $e) { + $this->assertRegExp('/invalid api key/i', $e->getMessage()); + } + } + + public function testVersionTooLow() + { + try { + $client = new Client(array('key' => self::KEY, 'version' => 0)); + } catch (\Exception $e) { + $this->assertRegExp('/invalid version/i', $e->getMessage()); + } + } + + public function testVersionTooHigh() + { + try { + $client = new Client(array('key' => self::KEY, 'version' => 2)); + } catch (\Exception $e) { + $this->assertRegExp('/invalid version/i', $e->getMessage()); + } + } + + public function testAssignClassMembers() + { + $client = new Client(array('key' => self::KEY)); + + $this->assertSame(self::BASE_URL, $client->baseUrl); + $this->assertSame(self::KEY, $client->key); + } + + public function testReturnCountries() + { + $url = self::BASE_URL . 'countries?key=' . self::KEY; + + $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()); + } + + 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 testCountriesRaise4xxErrors() + { + $url = self::BASE_URL . 'countries?key=' . self::KEY; + + $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->countries(); + } catch (\Exception $e) { + $this->assertSame(429, $e->getCode()); + $this->assertSame('Rate limit exceeded', $e->getMessage()); + } + } + + public function testCountriesRaise5xxErrors() + { + $url = self::BASE_URL . 'countries?key=' . self::KEY; + + $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->countries(); + } catch (\Exception $e) { + $this->assertSame('Internal server error', $e->getMessage()); + } + } + + public function testReturnHolidays() + { + $url = self::BASE_URL . 'holidays?key=' . self::KEY + . '&country=US&year=2015&month=7&day=4'; + + $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, + 'month' => 7, + 'day' => 4, + ))); + } + + 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'; + + $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->holidays(array('country' => 'US', 'year' => 2019)); + } catch (\Exception $e) { + $this->assertSame(429, $e->getCode()); + $this->assertSame('Rate limit exceeded', $e->getMessage()); + } + } + + public function testHolidaysRaise5xxErrors() + { + $url = self::BASE_URL . 'holidays?key=' . self::KEY . '&country=US&year=2019'; + + $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->holidays(array('country' => 'US', 'year' => 2019)); + } catch (\Exception $e) { + $this->assertSame('Internal server error', $e->getMessage()); + } + } + + public function testReturnLanguages() + { + $url = self::BASE_URL . 'languages?key=' . self::KEY; + + $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()); + } + + 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 testLanguagesRaise4xxErrors() + { + $url = self::BASE_URL . 'languages?key=' . self::KEY; + + $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->languages(); + } catch (\Exception $e) { + $this->assertSame(429, $e->getCode()); + $this->assertSame('Rate limit exceeded', $e->getMessage()); + } + } + + public function testLanguagesRaise5xxErrors() + { + $url = self::BASE_URL . 'languages?key=' . self::KEY; + + $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->languages(); + } catch (\Exception $e) { + $this->assertSame('Internal server error', $e->getMessage()); + } + } +} + diff --git a/tests/RequestTest.php b/tests/RequestTest.php new file mode 100644 index 0000000..31594f3 --- /dev/null +++ b/tests/RequestTest.php @@ -0,0 +1,45 @@ +assertFalse($request->execute($curl)); + } + + public function testGet() + { + $url = 'https://holidayapi.com'; + + $request = new Request(array( + 'execute' => array( + $url => function () + { + return ''; + }, + ), + )); + + try { + $request->get($url); + } catch (\Exception $e) { + $this->assertRegExp('/empty response/i', $e->getMessage()); + } + } +} + From 0f45ca781a92ae0d2f5242b40fdaeb6fef00a169 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Sat, 19 Oct 2019 15:14:23 -0500 Subject: [PATCH 02/14] chore(ci): include 7.4 and nightly * chore(ci): Added 7.4 (just released) and nightly (as an allowed failure). * chore(composer): Swap out abandoned coveralls package for maintained version. * chore(composer): Added PHPUnit as a dev dependency. * chore(ci): Dropped a ton of the juggling in favor of version juggling in Composer. * fix(readme): Corrected the badge for the license. * chore(composer): Bumped the package's version number. --- .travis.yml | 20 +++++++------------- README.md | 2 +- composer.json | 7 ++++--- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index eb67138..36d3649 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,33 +14,27 @@ matrix: dist: trusty - php: 7.0 dist: xenial - env: PHPUNIT=5.7 - php: 7.1 - env: PHPUNIT=7.5 - php: 7.2 - php: 7.3 + - php: 7.4 env: COVERAGE=true + - php: nightly + allow_failures: + - php: nightly install: + - php --version - composer install - - | - if [[ $PHPUNIT ]]; then - composer require "phpunit/phpunit:$PHPUNIT" - fi before_script: - mkdir -p build/logs script: - - | - if [[ $PHPUNIT ]]; then - vendor/bin/phpunit --coverage-clover build/logs/clover.xml - else - phpunit --coverage-clover build/logs/clover.xml - fi + - vendor/bin/phpunit --coverage-clover build/logs/clover.xml after_success: - | if [[ $COVERAGE ]]; then - php vendor/bin/coveralls --config .coveralls.yml -v + travis_retry php vendor/bin/php-coveralls --config .coveralls.yml -v fi diff --git a/README.md b/README.md index 302867a..f1dd8cf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Holiday API PHP Library -[![License](https://img.shields.io/npm/l/holidayapi-php?style=for-the-badge)](https://github.com/holidayapi/holidayapi-php/blob/master/LICENSE) +[![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) ![Build Status](https://img.shields.io/travis/holidayapi/holidayapi-php/master?style=for-the-badge) [![Coverage Status](https://img.shields.io/coveralls/github/holidayapi/holidayapi-php/master?style=for-the-badge)](https://coveralls.io/github/holidayapi/holidayapi-php?branch=master) diff --git a/composer.json b/composer.json index c6fa09f..8eae454 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "holidayapi/holidayapi-php", "description": "Official PHP library for Holiday API", - "version": "2.0.0", + "version": "2.1.0", "type": "library", "keywords": [ "calendar", @@ -17,10 +17,11 @@ "homepage": "https://holidayapi.com" }], "require": { - "php": ">=5.3.0" + "php": ">=5.3" }, "require-dev": { - "satooshi/php-coveralls": "~1.0" + "php-coveralls/php-coveralls": ">=1", + "phpunit/phpunit": ">=4" }, "autoload": { "psr-4": { "HolidayAPI\\": "src/" } From 054eab9c0278a6662b7274ee6d96647e3d290187 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Tue, 11 Feb 2020 18:00:37 -0600 Subject: [PATCH 03/14] feat: pull country or language by code * feat: pull country or language by code. This differs from the existing `search` functionality in that it allows you to explicitly pull back a single country or language instead of anything that matches (which could result in more items returned than expected). * docs(readme): update to include examples for new functionality. * test: expand tests to include new parameters. * fix(client): dropped some commented out code that wasn't in use. * docs(license): bump the year of the license. --- LICENSE | 2 +- README.md | 20 +++++++++++-- composer.json | 2 +- src/Client.php | 26 ----------------- tests/ClientTest.php | 68 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 30 deletions(-) diff --git a/LICENSE b/LICENSE index 7dcf161..f9f0c99 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016, 2017, 2018, 2019 Gravity Boulevard, LLC +Copyright (c) 2016, 2017, 2018, 2019, 2020 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 f1dd8cf..5712dd2 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,15 @@ try { $holiday_api->countries(); ``` -#### Search for a country by code or name +#### Fetch a supported country by code + +```php +$holiday_api->countries([ + 'country' => 'NO', +]); +``` + +#### Search for countries by code or name ```php $holiday_api->countries([ @@ -83,7 +91,15 @@ $holiday_api->countries([ $holiday_api->languages(); ``` -#### Search for a language by code or name +#### Fetch a supported language by code + +```php +$holiday_api->languages([ + 'language' => 'es', +]); +``` + +#### Search for languages by code or name ```php $holiday_api->languages([ diff --git a/composer.json b/composer.json index 8eae454..cefa821 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "holidayapi/holidayapi-php", "description": "Official PHP library for Holiday API", - "version": "2.1.0", + "version": "2.2.0", "type": "library", "keywords": [ "calendar", diff --git a/src/Client.php b/src/Client.php index 058f1d6..c482865 100644 --- a/src/Client.php +++ b/src/Client.php @@ -55,32 +55,6 @@ class Client private function request($endpoint, $request) { return $this->handler->get($this->createUrl($endpoint, $request)); - - /* - $curl = curl_init(); - - curl_setopt_array($curl, array( - CURLOPT_URL => $this->createUrl($endpoint, $request), - CURLOPT_HEADER => false, - CURLOPT_SSL_VERIFYPEER => true, - CURLOPT_RETURNTRANSFER => true, - )); - - $response = curl_exec($curl); - - if ($error = curl_error($curl)) { - throw new \Exception($error); - } - - curl_close($curl); - $response = json_decode($response, true); - - if (!$response) { - throw new \Exception('Empty response received'); - } - - return $response; - */ } public function countries($request = array()) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index c77611a..267d572 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -131,6 +131,40 @@ class ClientTest extends \PHPUnit_Framework_TestCase ), $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 testCountriesRaise4xxErrors() { $url = self::BASE_URL . 'countries?key=' . self::KEY; @@ -434,6 +468,40 @@ class ClientTest extends \PHPUnit_Framework_TestCase ), $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; From 12f1ea69f8c395e0bf3c623aeb2be3fe897d329d Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Tue, 3 Mar 2020 21:51:57 -0600 Subject: [PATCH 04/14] feat: filter out countries without public holidays Fairly minor update, no code change, just added a new test to cover the flag that was recently added to the API and expanded the documentation to also include it. --- README.md | 8 ++++++++ composer.json | 2 +- tests/ClientTest.php | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5712dd2..e3e827e 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,14 @@ try { $holiday_api->countries(); ``` +#### Fetch only countries with public holidays + +```php +$holiday_api->countries([ + 'public' => true, +]); +``` + #### Fetch a supported country by code ```php diff --git a/composer.json b/composer.json index cefa821..93d9423 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.0", + "version": "2.2.1", "type": "library", "keywords": [ "calendar", diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 267d572..30a96b3 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -165,6 +165,40 @@ class ClientTest extends \PHPUnit_Framework_TestCase ), $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; From b9ceb5947c861de64cb2bf762097a156bf7147b4 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Sun, 17 May 2020 14:34:09 -0500 Subject: [PATCH 05/14] docs: improve syntax highlighting of code snippets * Seems PHP snippets require the delimiter to function properly. * Updated a bunch of dependencies. --- README.md | 19 +++++++++++++++++++ composer.json | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e3e827e..bb4dece 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ composer require holidayapi/holidayapi-php ## Usage ```php + $key]); @@ -64,12 +65,14 @@ try { #### Fetch all supported countries ```php +countries(); ``` #### Fetch only countries with public holidays ```php +countries([ 'public' => true, ]); @@ -78,6 +81,7 @@ $holiday_api->countries([ #### Fetch a supported country by code ```php +countries([ 'country' => 'NO', ]); @@ -86,6 +90,7 @@ $holiday_api->countries([ #### Search for countries by code or name ```php +countries([ 'search' => 'united', ]); @@ -96,12 +101,14 @@ $holiday_api->countries([ #### Fetch all supported languages ```php +languages(); ``` #### Fetch a supported language by code ```php +languages([ 'language' => 'es', ]); @@ -110,6 +117,7 @@ $holiday_api->languages([ #### Search for languages by code or name ```php +languages([ 'search' => 'Chinese', ]); @@ -120,6 +128,7 @@ $holiday_api->languages([ #### Fetch holidays for a specific year ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -129,6 +138,7 @@ $holiday_api->holidays([ #### Fetch holidays for a specific month ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -139,6 +149,7 @@ $holiday_api->holidays([ #### Fetch holidays for a specific day ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -150,6 +161,7 @@ $holiday_api->holidays([ #### Fetch upcoming holidays based on a specific date ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -162,6 +174,7 @@ $holiday_api->holidays([ #### Fetch previous holidays based on a specific date ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -174,6 +187,7 @@ $holiday_api->holidays([ #### Fetch only public holidays ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -184,6 +198,7 @@ $holiday_api->holidays([ #### Fetch holidays for a specific subdivision ```php +holidays([ 'country' => 'GB-ENG', 'year' => 2019, @@ -193,6 +208,7 @@ $holiday_api->holidays([ #### Include subdivision holidays with countrywide holidays ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -203,6 +219,7 @@ $holiday_api->holidays([ #### Search for a holiday by name ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -213,6 +230,7 @@ $holiday_api->holidays([ #### Translate holidays to another language ```php +holidays([ 'country' => 'US', 'year' => 2019, @@ -223,6 +241,7 @@ $holiday_api->holidays([ #### Fetch holidays for multiple countries ```php +holidays([ 'country' => 'US,GB,NZ', 'year' => 2019, diff --git a/composer.json b/composer.json index 93d9423..53a6924 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.1", + "version": "2.2.2", "type": "library", "keywords": [ "calendar", From b6fad34f1909fbf5b859b625202610e57cefd3d8 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Sat, 13 Jun 2020 10:10:45 -0500 Subject: [PATCH 06/14] build: swap travis for github actions --- .coveralls.yml | 1 - .github/workflows/test.yml | 29 +++++++++++++++++++++++++++ .travis.yml | 40 -------------------------------------- README.md | 4 ++-- codecov.yml | 20 +++++++++++++++++++ composer.json | 5 +++-- 6 files changed, 54 insertions(+), 45 deletions(-) delete mode 100644 .coveralls.yml create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml create mode 100644 codecov.yml diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index 9160059..0000000 --- a/.coveralls.yml +++ /dev/null @@ -1 +0,0 @@ -service_name: travis-ci diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..41cef6c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,29 @@ +name: Test +on: [push, pull_request] +jobs: + test: + name: Test PHP ${{ matrix.php-version }} + 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'] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + - name: PHP Version + run: php --version + - name: Composer Version + run: composer --version + - name: Install Dependencies + run: COMPOSER_MEMORY_LIMIT=-1 composer install + - name: Run Tests + run: vendor/bin/phpunit --coverage-clover ./coverage.xml + - name: Upload Coverage + if: ${{ matrix.php-version == '7.4' }} + uses: codecov/codecov-action@v1 + with: + file: ./coverage.xml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 36d3649..0000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -language: php -dist: bionic -sudo: required - -matrix: - include: - - php: 5.3 - dist: precise - - php: 5.4 - dist: trusty - - php: 5.5 - dist: trusty - - php: 5.6 - dist: trusty - - php: 7.0 - dist: xenial - - php: 7.1 - - php: 7.2 - - php: 7.3 - - php: 7.4 - env: COVERAGE=true - - php: nightly - allow_failures: - - php: nightly - -install: - - php --version - - composer install - -before_script: - - mkdir -p build/logs - -script: - - vendor/bin/phpunit --coverage-clover build/logs/clover.xml - -after_success: - - | - if [[ $COVERAGE ]]; then - travis_retry php vendor/bin/php-coveralls --config .coveralls.yml -v - fi diff --git a/README.md b/README.md index bb4dece..f587bf7 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [![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) -![Build Status](https://img.shields.io/travis/holidayapi/holidayapi-php/master?style=for-the-badge) -[![Coverage Status](https://img.shields.io/coveralls/github/holidayapi/holidayapi-php/master?style=for-the-badge)](https://coveralls.io/github/holidayapi/holidayapi-php?branch=master) +[![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) Official PHP library for [Holiday API](https://holidayapi.com) providing quick and easy access to holiday information from applications written in PHP. diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..657d8f7 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,20 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 2 + round: down + range: "70...100" + +parsers: + gcov: + branch_detection: + conditional: yes + loop: yes + method: no + macro: no + +comment: + layout: "reach,diff,flags,tree" + behavior: default + require_changes: no diff --git a/composer.json b/composer.json index 53a6924..c1c0886 100644 --- a/composer.json +++ b/composer.json @@ -20,10 +20,11 @@ "php": ">=5.3" }, "require-dev": { - "php-coveralls/php-coveralls": ">=1", "phpunit/phpunit": ">=4" }, "autoload": { - "psr-4": { "HolidayAPI\\": "src/" } + "psr-4": { + "HolidayAPI\\": "src/" + } } } From 45ca80d8462b95855bca45bbb1dfe89d596a5409 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Fri, 19 Jun 2020 18:39:13 -0500 Subject: [PATCH 07/14] feat: add workday endpoint Added support for our latest endpoint, which calculates the workday a given number of business days into the future from the given date for the given country. --- README.md | 13 ++++ composer.json | 2 +- src/Client.php | 15 +++++ tests/ClientTest.php | 157 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 179 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f587bf7..9d33b02 100644 --- a/README.md +++ b/README.md @@ -252,3 +252,16 @@ $holiday_api->holidays([ 'year' => 2019, ]); ``` + +### Workday + +#### Fetch workday 7 business days after a date + +```php +workday([ + 'country' => 'US', + 'start' => '2019-07-01', + 'days' => 7, +]); +``` diff --git a/composer.json b/composer.json index c1c0886..b5e0b93 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": "2.3.0", "type": "library", "keywords": [ "calendar", diff --git a/src/Client.php b/src/Client.php index c482865..f855d06 100644 --- a/src/Client.php +++ b/src/Client.php @@ -82,5 +82,20 @@ class Client { return $this->request('languages', $request); } + + public function workday($request) + { + if (!isset($request['country'])) { + throw new \Exception('Missing country'); + } elseif (!isset($request['start'])) { + throw new \Exception('Missing start date'); + } elseif (!isset($request['days'])) { + throw new \Exception('Missing days'); + } elseif ($request['days'] < 1) { + throw new \Exception('Days must be 1 or more'); + } + + return $this->request('workday', $request); + } } diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 30a96b3..08d07da 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -255,8 +255,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( @@ -299,8 +298,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase public function testSearchHolidays() { - $url = self::BASE_URL . 'holidays?key=' . self::KEY - . '&country=US&year=2015&search=Independence'; + $url = self::BASE_URL . 'holidays?key=' . self::KEY . '&country=US&year=2015&search=Independence'; $request = new Request(array( 'execute' => array( @@ -340,7 +338,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase ))); } - public function testCountryMissing() + public function testHolidaysCountryMissing() { $client = new Client(array('key' => self::KEY)); @@ -351,7 +349,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase } } - public function testYearMissing() + public function testHolidaysYearMissing() { $client = new Client(array('key' => self::KEY)); @@ -362,7 +360,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase } } - public function testBothPreviousAndUpcoming() + public function testHolidaysBothPreviousAndUpcoming() { $client = new Client(array('key' => self::KEY)); @@ -589,5 +587,150 @@ 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 testWorkdayCountryMissing() + { + $client = new Client(array('key' => self::KEY)); + + try { + $client->workday(array()); + } catch (\Exception $e) { + $this->assertRegExp('/missing country/i', $e->getMessage()); + } + } + + public function testWorkdayStartMissing() + { + $client = new Client(array('key' => self::KEY)); + + try { + $client->workday(array('country' => 'US')); + } catch (\Exception $e) { + $this->assertRegExp('/missing start date/i', $e->getMessage()); + } + } + + public function testWorkdayDaysMissing() + { + $client = new Client(array('key' => self::KEY)); + + try { + $client->workday(array( + 'country' => 'US', + 'start' => '2019-07-01', + )); + } catch (\Exception $e) { + $this->assertRegExp('/missing days/i', $e->getMessage()); + } + } + + public function testWorkdayDaysNegative() + { + $client = new Client(array('key' => self::KEY)); + + try { + $client->workday(array( + 'country' => 'US', + 'start' => '2019-07-01', + 'days' => -10, + )); + } catch (\Exception $e) { + $this->assertRegExp('/days must be 1 or more/i', $e->getMessage()); + } + } + + 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()); + } + } } From 49d20e06a8473572c7ae4c569403968308515fa0 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Fri, 19 Jun 2020 18:58:49 -0500 Subject: [PATCH 08/14] docs: fix build and coverage badges Had the wrong URL in there, whoops. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d33b02..e03b325 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [![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) +[![Test Status](https://img.shields.io/github/workflow/status/holidayapi/holidayapi-php/Test?style=for-the-badge)](https://github.com/holidayapi/holidayapi-php/actions) +[![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. From b15f862193c4fb44d8765dcdf589cb0c4e5e8a58 Mon Sep 17 00:00:00 2001 From: peter279k Date: Sun, 13 Dec 2020 10:58:45 +0800 Subject: [PATCH 09/14] Using PHPUnit ^4.8.36 and some PHPUnit stuffs --- composer.json | 7 ++++++- phpunit.xml | 1 + tests/ClientTest.php | 12 ++---------- tests/RequestTest.php | 13 ++----------- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index b5e0b93..405b4e2 100644 --- a/composer.json +++ b/composer.json @@ -20,11 +20,16 @@ "php": ">=5.3" }, "require-dev": { - "phpunit/phpunit": ">=4" + "phpunit/phpunit": "^4.8.36" }, "autoload": { "psr-4": { "HolidayAPI\\": "src/" } + }, + "autoload-dev": { + "psr-4": { + "HolidayAPI\\Tests\\": "tests/" + } } } diff --git a/phpunit.xml b/phpunit.xml index fa05f6b..fa15f4b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,6 +1,7 @@ Date: Fri, 25 Dec 2020 03:07:16 +0800 Subject: [PATCH 10/14] Add PHP8.0 and JSON & cURL extension checking --- .github/workflows/test.yml | 2 +- composer.json | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 41cef6c..ddf8b8d 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: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/composer.json b/composer.json index 405b4e2..4b004bc 100644 --- a/composer.json +++ b/composer.json @@ -17,10 +17,12 @@ "homepage": "https://holidayapi.com" }], "require": { - "php": ">=5.3" + "php": ">=5.3", + "ext-json": "*", + "ext-curl": "*" }, "require-dev": { - "phpunit/phpunit": "^4.8.36" + "phpunit/phpunit": "^4.8.36 || ^9.0" }, "autoload": { "psr-4": { From c12f512f8a84f0c2c0024045b47f620642fe2744 Mon Sep 17 00:00:00 2001 From: peter279k Date: Sat, 2 Jan 2021 00:04:30 +0800 Subject: [PATCH 11/14] Add assertRegExp assertion checking --- phpunit.xml | 2 +- tests/ClientTest.php | 96 ++++++++++++++++++++++++++++++++++++------- tests/RequestTest.php | 8 +++- 3 files changed, 89 insertions(+), 17 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index fa15f4b..92f2230 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,7 +1,7 @@ =')) { + $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()); } } @@ -332,28 +356,46 @@ class ClientTest extends TestCase public function testHolidaysCountryMissing() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $client = new Client(array('key' => self::KEY)); try { $client->holidays(array('year' => 2015)); } catch (\Exception $e) { - $this->assertRegExp('/missing country/i', $e->getMessage()); + $this->$assertRegExp('/missing country/i', $e->getMessage()); } } public function testHolidaysYearMissing() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $client = new Client(array('key' => self::KEY)); try { $client->holidays(array('country' => 'US')); } catch (\Exception $e) { - $this->assertRegExp('/missing year/i', $e->getMessage()); + $this->$assertRegExp('/missing year/i', $e->getMessage()); } } public function testHolidaysBothPreviousAndUpcoming() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $client = new Client(array('key' => self::KEY)); try { @@ -366,7 +408,7 @@ class ClientTest extends TestCase 'previous' => true, )); } catch (\Exception $e) { - $this->assertRegExp('/previous and upcoming/i', $e->getMessage()); + $this->$assertRegExp('/previous and upcoming/i', $e->getMessage()); } } @@ -614,28 +656,46 @@ class ClientTest extends TestCase public function testWorkdayCountryMissing() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $client = new Client(array('key' => self::KEY)); try { $client->workday(array()); } catch (\Exception $e) { - $this->assertRegExp('/missing country/i', $e->getMessage()); + $this->$assertRegExp('/missing country/i', $e->getMessage()); } } public function testWorkdayStartMissing() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $client = new Client(array('key' => self::KEY)); try { $client->workday(array('country' => 'US')); } catch (\Exception $e) { - $this->assertRegExp('/missing start date/i', $e->getMessage()); + $this->$assertRegExp('/missing start date/i', $e->getMessage()); } } public function testWorkdayDaysMissing() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $client = new Client(array('key' => self::KEY)); try { @@ -644,12 +704,18 @@ class ClientTest extends TestCase 'start' => '2019-07-01', )); } catch (\Exception $e) { - $this->assertRegExp('/missing days/i', $e->getMessage()); + $this->$assertRegExp('/missing days/i', $e->getMessage()); } } public function testWorkdayDaysNegative() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $client = new Client(array('key' => self::KEY)); try { @@ -659,7 +725,7 @@ class ClientTest extends TestCase 'days' => -10, )); } catch (\Exception $e) { - $this->assertRegExp('/days must be 1 or more/i', $e->getMessage()); + $this->$assertRegExp('/days must be 1 or more/i', $e->getMessage()); } } diff --git a/tests/RequestTest.php b/tests/RequestTest.php index 97c15d4..f42776d 100644 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -15,6 +15,12 @@ class RequestTest extends TestCase public function testGet() { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + $url = 'https://holidayapi.com'; $request = new Request(array( @@ -29,7 +35,7 @@ class RequestTest extends TestCase try { $request->get($url); } catch (\Exception $e) { - $this->assertRegExp('/empty response/i', $e->getMessage()); + $this->$assertRegExp('/empty response/i', $e->getMessage()); } } } From 95bba752652cd112649aa2403c21ea0c032a66bc Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Thu, 10 Jun 2021 23:11:35 -0500 Subject: [PATCH 12/14] feat: add workdays endpoint Added support for our new workdays endpoint that allows you to get the number of working days for a country between two dates. --- .github/workflows/test.yml | 2 +- README.md | 26 +++---- composer.json | 2 +- src/Client.php | 13 ++++ tests/ClientTest.php | 144 +++++++++++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ddf8b8d..19263c5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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.0' }} uses: codecov/codecov-action@v1 with: file: ./coverage.xml diff --git a/README.md b/README.md index e03b325..c74f9d1 100644 --- a/README.md +++ b/README.md @@ -8,19 +8,6 @@ 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 @@ -265,3 +252,16 @@ $holiday_api->workday([ '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 4b004bc..0cd3dee 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "holidayapi/holidayapi-php", "description": "Official PHP library for Holiday API", - "version": "2.3.0", + "version": "2.4.0", "type": "library", "keywords": [ "calendar", diff --git a/src/Client.php b/src/Client.php index f855d06..b3e295e 100644 --- a/src/Client.php +++ b/src/Client.php @@ -97,5 +97,18 @@ class Client return $this->request('workday', $request); } + + public function workdays($request) + { + if (!isset($request['country'])) { + throw new \Exception('Missing country'); + } elseif (!isset($request['start'])) { + throw new \Exception('Missing start date'); + } elseif (!isset($request['end'])) { + throw new \Exception('Missing end date'); + } + + return $this->request('workdays', $request); + } } diff --git a/tests/ClientTest.php b/tests/ClientTest.php index fd368c6..e999192 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -790,5 +790,149 @@ class ClientTest extends TestCase $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 testWorkdaysCountryMissing() + { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + + $client = new Client(array('key' => self::KEY)); + + try { + $client->workdays(array()); + } catch (\Exception $e) { + $this->$assertRegExp('/missing country/i', $e->getMessage()); + } + } + + public function testWorkdaysStartMissing() + { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + + $client = new Client(array('key' => self::KEY)); + + try { + $client->workdays(array('country' => 'US')); + } catch (\Exception $e) { + $this->$assertRegExp('/missing start date/i', $e->getMessage()); + } + } + + public function testWorkdaysEndMissing() + { + if (version_compare(PHP_VERSION, '7.3.0', '>=')) { + $assertRegExp = 'assertMatchesRegularExpression'; + } else { + $assertRegExp = 'assertRegExp'; + } + + $client = new Client(array('key' => self::KEY)); + + try { + $client->workdays(array( + 'country' => 'US', + 'start' => '2019-07-01', + )); + } catch (\Exception $e) { + $this->$assertRegExp('/missing end date/i', $e->getMessage()); + } + } + + 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()); + } + } } From 15052790c5ef0138347907cb2ae449ecf1988d95 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Tue, 5 Apr 2022 17:56:44 -0500 Subject: [PATCH 13/14] feat: get previous workday Added the ability to get the previous workday by passing in a negative number of days along with the date to start from. This update also includes some overhauling to allow for the library to be more resilient to changes in the upstream API. --- .github/workflows/test.yml | 4 +- LICENSE | 2 +- composer.json | 2 +- src/Client.php | 29 --- tests/ClientTest.php | 399 ------------------------------------- 5 files changed, 4 insertions(+), 432 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 19263c5..c492e7a 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', '8.0'] + php-version: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1'] 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 == '8.0' }} + if: ${{ matrix.php-version == '8.1' }} uses: codecov/codecov-action@v1 with: file: ./coverage.xml diff --git a/LICENSE b/LICENSE index f9f0c99..d7dcfb3 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 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/composer.json b/composer.json index 0cd3dee..2170ae6 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "holidayapi/holidayapi-php", "description": "Official PHP library for Holiday API", - "version": "2.4.0", + "version": "3.0.0", "type": "library", "keywords": [ "calendar", diff --git a/src/Client.php b/src/Client.php index b3e295e..0793c97 100644 --- a/src/Client.php +++ b/src/Client.php @@ -64,17 +64,6 @@ class Client public function holidays($request) { - if (!isset($request['country'])) { - throw new \Exception('Missing country'); - } elseif (!isset($request['year'])) { - throw new \Exception('Missing year'); - } elseif ( - isset($request['previous'], $request['upcoming']) - && $request['previous'] && $request['upcoming'] - ) { - throw new \Exception('Previous and upcoming are mutually exclusive'); - } - return $this->request('holidays', $request); } @@ -85,29 +74,11 @@ class Client public function workday($request) { - if (!isset($request['country'])) { - throw new \Exception('Missing country'); - } elseif (!isset($request['start'])) { - throw new \Exception('Missing start date'); - } elseif (!isset($request['days'])) { - throw new \Exception('Missing days'); - } elseif ($request['days'] < 1) { - throw new \Exception('Days must be 1 or more'); - } - return $this->request('workday', $request); } public function workdays($request) { - if (!isset($request['country'])) { - throw new \Exception('Missing country'); - } elseif (!isset($request['start'])) { - throw new \Exception('Missing start date'); - } elseif (!isset($request['end'])) { - throw new \Exception('Missing end date'); - } - return $this->request('workdays', $request); } } diff --git a/tests/ClientTest.php b/tests/ClientTest.php index e999192..14f83c7 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -113,108 +113,6 @@ class ClientTest extends 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; @@ -312,106 +210,6 @@ class ClientTest extends 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 testHolidaysCountryMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $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 testHolidaysYearMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $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 testHolidaysBothPreviousAndUpcoming() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $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'; @@ -500,74 +298,6 @@ class ClientTest extends 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; @@ -654,81 +384,6 @@ class ClientTest extends TestCase ))); } - public function testWorkdayCountryMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $client = new Client(array('key' => self::KEY)); - - try { - $client->workday(array()); - } catch (\Exception $e) { - $this->$assertRegExp('/missing country/i', $e->getMessage()); - } - } - - public function testWorkdayStartMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $client = new Client(array('key' => self::KEY)); - - try { - $client->workday(array('country' => 'US')); - } catch (\Exception $e) { - $this->$assertRegExp('/missing start date/i', $e->getMessage()); - } - } - - public function testWorkdayDaysMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $client = new Client(array('key' => self::KEY)); - - try { - $client->workday(array( - 'country' => 'US', - 'start' => '2019-07-01', - )); - } catch (\Exception $e) { - $this->$assertRegExp('/missing days/i', $e->getMessage()); - } - } - - public function testWorkdayDaysNegative() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $client = new Client(array('key' => self::KEY)); - - try { - $client->workday(array( - 'country' => 'US', - 'start' => '2019-07-01', - 'days' => -10, - )); - } catch (\Exception $e) { - $this->$assertRegExp('/days must be 1 or more/i', $e->getMessage()); - } - } - public function testWorkdayRaise4xxErrors() { $url = self::BASE_URL . 'workday?key=' . self::KEY . '&country=US&start=2019-07-01&days=10'; @@ -819,60 +474,6 @@ class ClientTest extends TestCase ))); } - public function testWorkdaysCountryMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $client = new Client(array('key' => self::KEY)); - - try { - $client->workdays(array()); - } catch (\Exception $e) { - $this->$assertRegExp('/missing country/i', $e->getMessage()); - } - } - - public function testWorkdaysStartMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $client = new Client(array('key' => self::KEY)); - - try { - $client->workdays(array('country' => 'US')); - } catch (\Exception $e) { - $this->$assertRegExp('/missing start date/i', $e->getMessage()); - } - } - - public function testWorkdaysEndMissing() - { - if (version_compare(PHP_VERSION, '7.3.0', '>=')) { - $assertRegExp = 'assertMatchesRegularExpression'; - } else { - $assertRegExp = 'assertRegExp'; - } - - $client = new Client(array('key' => self::KEY)); - - try { - $client->workdays(array( - 'country' => 'US', - 'start' => '2019-07-01', - )); - } catch (\Exception $e) { - $this->$assertRegExp('/missing end date/i', $e->getMessage()); - } - } - public function testWorkdaysRaise4xxErrors() { $url = self::BASE_URL . 'workdays?key=' . self::KEY . '&country=US&start=2019-07-01&end=2019-07-10'; From f8e945bacd8a81524babc80741a04d3b24723221 Mon Sep 17 00:00:00 2001 From: Josh Sherman Date: Mon, 6 Nov 2023 12:29:43 -0600 Subject: [PATCH 14/14] chore: drop EOL PHP versions Seemed overdue to finally drop support for PHP 5.x, as well as 7.x as the 7 series has also reached end of life. Expanded testing to include both the soon to be released 8.3 and the next development version 8.4. --- .github/workflows/test.yml | 4 ++-- LICENSE | 2 +- README.md | 1 - composer.json | 6 +++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c492e7a..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', '8.0', '8.1'] + 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 == '8.1' }} + if: ${{ matrix.php-version == '8.2' }} uses: codecov/codecov-action@v1 with: file: ./coverage.xml diff --git a/LICENSE b/LICENSE index d7dcfb3..ab5ad02 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022 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 c74f9d1..81a1456 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![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/holidayapi/holidayapi-php/Test?style=for-the-badge)](https://github.com/holidayapi/holidayapi-php/actions) [![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 diff --git a/composer.json b/composer.json index 2170ae6..3129ca8 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "holidayapi/holidayapi-php", "description": "Official PHP library for Holiday API", - "version": "3.0.0", + "version": "4.0.0", "type": "library", "keywords": [ "calendar", @@ -17,12 +17,12 @@ "homepage": "https://holidayapi.com" }], "require": { - "php": ">=5.3", + "php": ">=8.0", "ext-json": "*", "ext-curl": "*" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^9.0" + "phpunit/phpunit": "^9.0" }, "autoload": { "psr-4": {