src/Cmixin/BusinessDay/Holiday.php
<?php
namespace Cmixin\BusinessDay;
use Carbon\Carbon;
use Cmixin\BusinessDay;
use Cmixin\BusinessDay\Calculator\MixinConfigPropagator;
use SplObjectStorage;
class Holiday extends YearCrawler
{
use HolidayData;
const DEFAULT_HOLIDAY_LOCALE = 'en';
/**
* @var array
*/
public $holidayNames = [];
/**
* @var callable|null
*/
public $holidayGetter = null;
/**
* @var SplObjectStorage<object,callable>|null
*/
public $holidayGetters = null;
/**
* @var callable|null
*/
public $workdayGetter = null;
/**
* @var SplObjectStorage<object,callable>|null
*/
public $workdayGetters = null;
/**
* Set the strategy to get the holiday ID from a date object.
*
* @return \Closure
*/
public function setHolidayGetter()
{
$mixin = $this;
/**
* Set the strategy to get the holiday ID from a date object.
*
* @param callable|null $holidayGetter
*
* @return $this|null
*/
return static function (?callable $holidayGetter) use ($mixin) {
return MixinConfigPropagator::setHolidayGetter(
$mixin,
end(static::$macroContextStack) ?: null,
$holidayGetter
);
};
}
/**
* Set the strategy to get the extra workday ID from a date object.
*
* @return \Closure
*/
public function setExtraWorkdayGetter()
{
$mixin = $this;
/**
* Set the strategy to get the extra workday ID from a date object.
*
* @param callable|null $workdayGetter
*
* @return $this|null
*/
return static function (?callable $workdayGetter) use ($mixin) {
return MixinConfigPropagator::setExtraWorkdayGetter(
$mixin,
end(static::$macroContextStack) ?: null,
$workdayGetter
);
};
}
/**
* Get the identifier of the current holiday or false if it's not a holiday.
*
* @return \Closure
*/
public function getDBDayId()
{
/**
* Get the identifier of the current holiday or false if it's not a holiday.
*
* @return string|false
*/
return static function (string $getDays = 'getHolidays') {
/** @var Carbon|BusinessDay $self */
$self = static::this();
$date = $self->format('d/m');
$year = $self->year;
$next = $self->getYearHolidaysNextFunction($year, 'string', $getDays);
while ($data = $next()) {
[$holidayId, $holiday] = $data;
if ($holiday && $date.(strlen($holiday) > 5 ? "/$year" : '') === $holiday) {
return $holidayId;
}
}
return false;
};
}
/**
* Get the identifier of the current holiday or false if it's not a holiday.
*
* @return \Closure
*/
public function getHolidayId()
{
$mixin = $this;
/**
* Get the identifier of the current holiday or false if it's not a holiday.
*
* @return string|false
*/
return static function () use ($mixin) {
/** @var Carbon|BusinessDay $self */
$self = static::this();
$fallback = function () use ($self) {
return $self->getDBDayId();
};
$holidayGetter = MixinConfigPropagator::getHolidayGetter($mixin, $self);
return $holidayGetter
? $holidayGetter($mixin->holidaysRegion, $self, $fallback)
: $fallback();
};
}
/**
* Checks the date to see if it is a holiday.
*
* @return \Closure
*/
public function isHoliday()
{
/**
* Checks the date to see if it is a holiday.
*
* @return bool
*/
return static function () {
/** @var Carbon|BusinessDay $self */
$self = static::this();
return $self->getHolidayId() !== false;
};
}
/**
* Get the identifier of the current special workday or false if it's not a special workday.
*
* @return \Closure
*/
public function getExtraWorkdayId()
{
$mixin = $this;
/**
* Get the identifier of the current special workday or false if it's not a special workday.
*
* @return string|false
*/
return static function () use ($mixin) {
/** @var Carbon|BusinessDay $self */
$self = static::this();
$fallback = function () use ($self) {
return $self->getDBDayId('getExtraWorkdays');
};
$workdayGetter = MixinConfigPropagator::getExtraWorkdayGetter($mixin, $self);
return $workdayGetter
? $workdayGetter($mixin->holidaysRegion, $self, $fallback)
: $fallback();
};
}
/**
* Checks the date to see if it is a holiday.
*
* @return \Closure
*/
public function isExtraWorkday()
{
/**
* Checks the date to see if it is a holiday.
*
* @return bool
*/
return static function () {
/** @var Carbon|BusinessDay $self */
$self = static::this();
return $self->getExtraWorkdayId() !== false;
};
}
/**
* Get the holidays in the given language.
*
* @return \Closure
*/
public function getHolidayNamesDictionary()
{
$mixin = $this;
$defaultLocale = static::DEFAULT_HOLIDAY_LOCALE;
/**
* Get the holidays in the given language.
*
* @param string $locale language
*
* @return array
*/
return static function ($locale) use ($mixin, $defaultLocale) {
if (isset($mixin->holidayNames[$locale])) {
return $mixin->holidayNames[$locale] ?: $mixin->holidayNames[$defaultLocale];
}
$file = __DIR__."/../HolidayNames/$locale.php";
if (!file_exists($file)) {
$mixin->holidayNames[$locale] = false;
$locale = $defaultLocale;
$file = __DIR__."/../HolidayNames/$locale.php";
if (isset($mixin->holidayNames[$locale])) {
return $mixin->holidayNames[$locale];
}
}
return $mixin->holidayNames[$locale] = include $file;
};
}
/**
* Get the name of the current holiday (using the locale given in parameter or the current date locale)
* or false if it's not a holiday.
*
* @return \Closure
*/
public function getHolidayName()
{
$dictionary = $this->getHolidayNamesDictionary();
/**
* Get the name of the current holiday (using the locale given in parameter or the current date locale)
* or false if it's not a holiday.
*
* @param string $locale language ("en" by default)
*
* @return string|false
*/
return static function ($date = null, $locale = null) use ($dictionary) {
/** @var Carbon|BusinessDay $self */
$self = static::this();
/** @var Carbon|BusinessDay $date */
[$locale, $date] = $self->swapDateTimeParam($locale, $date, null);
$locale = $locale ?? (is_string($date) ? $date : null);
$date = is_object($date) ? $self->resolveCarbon($date) : $self;
$holidayId = $date->getHolidayId();
if ($holidayId === false) {
return false;
}
if (!$locale) {
$locale = ($date->locale ?? get_class($date)::getLocale()) ?: 'en';
}
/* @var string $holidayId */
$names = $dictionary(preg_replace('/^([^_-]+)([_-].*)$/', '$1', $locale));
return isset($names[$holidayId]) ? $names[$holidayId] : 'Unknown';
};
}
}