Compare commits

...

7 commits

Author SHA1 Message Date
f8e945bacd 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.
2023-11-06 12:43:17 -06:00
15052790c5 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.
2022-04-05 18:02:30 -05:00
95bba75265 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.
2021-06-14 18:01:47 -05:00
peter279k
c12f512f8a Add assertRegExp assertion checking 2021-06-10 23:01:28 -05:00
peter279k
b398ba5013 Add PHP8.0 and JSON & cURL extension checking 2020-12-29 16:26:42 -06:00
peter279k
b15f862193 Using PHPUnit ^4.8.36 and some PHPUnit stuffs 2020-12-22 16:17:12 -06:00
49d20e06a8 docs: fix build and coverage badges
Had the wrong URL in there, whoops.
2020-06-19 19:12:30 -05:00
8 changed files with 166 additions and 375 deletions

View file

@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: 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: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -23,7 +23,7 @@ jobs:
- name: Run Tests - name: Run Tests
run: vendor/bin/phpunit --coverage-clover ./coverage.xml run: vendor/bin/phpunit --coverage-clover ./coverage.xml
- name: Upload Coverage - name: Upload Coverage
if: ${{ matrix.php-version == '7.4' }} if: ${{ matrix.php-version == '8.2' }}
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v1
with: with:
file: ./coverage.xml file: ./coverage.xml

View file

@ -1,6 +1,6 @@
MIT License 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -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) [![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) ![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/holidayapi/holidayapi-php?style=for-the-badge)](https://codecov.io/gh/holidayapi/holidayapi-php)
[![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 Official PHP library for [Holiday API](https://holidayapi.com) providing quick
and easy access to holiday information from applications written in PHP. 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 ## Documentation
Full documentation of the Holiday API endpoints is available Full documentation of the Holiday API endpoints is available
@ -265,3 +251,16 @@ $holiday_api->workday([
'days' => 7, 'days' => 7,
]); ]);
``` ```
### Workdays
#### Fetch number of workdays between two dates
```php
<?php
$holiday_api->workdays([
'country' => 'US',
'start' => '2019-07-01',
'end' => '2019-07-10',
]);
```

View file

@ -1,7 +1,7 @@
{ {
"name": "holidayapi/holidayapi-php", "name": "holidayapi/holidayapi-php",
"description": "Official PHP library for Holiday API", "description": "Official PHP library for Holiday API",
"version": "2.3.0", "version": "4.0.0",
"type": "library", "type": "library",
"keywords": [ "keywords": [
"calendar", "calendar",
@ -17,14 +17,21 @@
"homepage": "https://holidayapi.com" "homepage": "https://holidayapi.com"
}], }],
"require": { "require": {
"php": ">=5.3" "php": ">=8.0",
"ext-json": "*",
"ext-curl": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": ">=4" "phpunit/phpunit": "^9.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"HolidayAPI\\": "src/" "HolidayAPI\\": "src/"
} }
},
"autoload-dev": {
"psr-4": {
"HolidayAPI\\Tests\\": "tests/"
}
} }
} }

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit <phpunit
colors="true" colors="true"
bootstrap="./vendor/autoload.php"
convertErrorsToExceptions="true" convertErrorsToExceptions="true"
convertNoticesToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" convertWarningsToExceptions="true"

View file

@ -64,17 +64,6 @@ class Client
public function holidays($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); return $this->request('holidays', $request);
} }
@ -85,17 +74,12 @@ class Client
public function workday($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); return $this->request('workday', $request);
} }
public function workdays($request)
{
return $this->request('workdays', $request);
}
} }

View file

@ -2,56 +2,72 @@
namespace HolidayAPI\Tests; namespace HolidayAPI\Tests;
use HolidayAPI\Client; use HolidayAPI\Client;
use HolidayAPI\Request; use HolidayAPI\Request;
use PHPUnit\Framework\TestCase;
require __DIR__ . '/../vendor/autoload.php'; class ClientTest extends TestCase
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
{ {
const BASE_URL = 'https://holidayapi.com/v1/'; const BASE_URL = 'https://holidayapi.com/v1/';
const KEY = '8e4de28c-4b18-49f0-9aba-0bd6b424fc38'; const KEY = '8e4de28c-4b18-49f0-9aba-0bd6b424fc38';
public function testMissingKey() public function testMissingKey()
{ {
if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
$assertRegExp = 'assertMatchesRegularExpression';
} else {
$assertRegExp = 'assertRegExp';
}
try { try {
$client = new Client(array()); new Client(array());
} catch (\Exception $e) { } catch (\Exception $e) {
$this->assertRegExp('/missing api key/i', $e->getMessage()); $this->$assertRegExp('/missing api key/i', $e->getMessage());
} }
} }
public function testInvalidKey() public function testInvalidKey()
{ {
if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
$assertRegExp = 'assertMatchesRegularExpression';
} else {
$assertRegExp = 'assertRegExp';
}
try { try {
$client = new Client(array( new Client(array(
'key' => 'zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz', 'key' => 'zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz',
)); ));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->assertRegExp('/invalid api key/i', $e->getMessage()); $this->$assertRegExp('/invalid api key/i', $e->getMessage());
} }
} }
public function testVersionTooLow() public function testVersionTooLow()
{ {
if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
$assertRegExp = 'assertMatchesRegularExpression';
} else {
$assertRegExp = 'assertRegExp';
}
try { try {
$client = new Client(array('key' => self::KEY, 'version' => 0)); new Client(array('key' => self::KEY, 'version' => 0));
} catch (\Exception $e) { } catch (\Exception $e) {
$this->assertRegExp('/invalid version/i', $e->getMessage()); $this->$assertRegExp('/invalid version/i', $e->getMessage());
} }
} }
public function testVersionTooHigh() public function testVersionTooHigh()
{ {
if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
$assertRegExp = 'assertMatchesRegularExpression';
} else {
$assertRegExp = 'assertRegExp';
}
try { try {
$client = new Client(array('key' => self::KEY, 'version' => 2)); new Client(array('key' => self::KEY, 'version' => 2));
} catch (\Exception $e) { } 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()); ), $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() public function testCountriesRaise4xxErrors()
{ {
$url = self::BASE_URL . 'countries?key=' . self::KEY; $url = self::BASE_URL . 'countries?key=' . self::KEY;
@ -296,88 +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 testHolidaysCountryMissing()
{
$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()
{
$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()
{
$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() public function testHolidaysRaise4xxErrors()
{ {
$url = self::BASE_URL . 'holidays?key=' . self::KEY . '&country=US&year=2019'; $url = self::BASE_URL . 'holidays?key=' . self::KEY . '&country=US&year=2019';
@ -466,74 +298,6 @@ class ClientTest extends \PHPUnit_Framework_TestCase
), $client->languages()); ), $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() public function testLanguagesRaise4xxErrors()
{ {
$url = self::BASE_URL . 'languages?key=' . self::KEY; $url = self::BASE_URL . 'languages?key=' . self::KEY;
@ -620,57 +384,6 @@ class ClientTest extends \PHPUnit_Framework_TestCase
))); )));
} }
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() public function testWorkdayRaise4xxErrors()
{ {
$url = self::BASE_URL . 'workday?key=' . self::KEY . '&country=US&start=2019-07-01&days=10'; $url = self::BASE_URL . 'workday?key=' . self::KEY . '&country=US&start=2019-07-01&days=10';
@ -732,5 +445,95 @@ class ClientTest extends \PHPUnit_Framework_TestCase
$this->assertSame('Internal server error', $e->getMessage()); $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());
}
}
} }

View file

@ -1,18 +1,9 @@
<?php <?php
namespace HolidayAPI\Tests; namespace HolidayAPI\Tests;
use HolidayAPI\Client;
use HolidayAPI\Request; use HolidayAPI\Request;
use PHPUnit\Framework\TestCase;
require __DIR__ . '/../vendor/autoload.php'; class RequestTest extends TestCase
if (
!class_exists('\PHPUnit_Framework_TestCase')
&& class_exists('\PHPUnit\Framework\TestCase')
) {
class_alias('\PHPUnit\Framework\TestCase', '\PHPUnit_Framework_TestCase');
}
class RequestTest extends \PHPUnit_Framework_TestCase
{ {
public function testExecute() public function testExecute()
{ {
@ -24,6 +15,12 @@ class RequestTest extends \PHPUnit_Framework_TestCase
public function testGet() public function testGet()
{ {
if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
$assertRegExp = 'assertMatchesRegularExpression';
} else {
$assertRegExp = 'assertRegExp';
}
$url = 'https://holidayapi.com'; $url = 'https://holidayapi.com';
$request = new Request(array( $request = new Request(array(
@ -38,7 +35,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase
try { try {
$request->get($url); $request->get($url);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->assertRegExp('/empty response/i', $e->getMessage()); $this->$assertRegExp('/empty response/i', $e->getMessage());
} }
} }
} }