/php-pear-Date-Holidays-0.21.6/Date_Holidays-0.21.6/Date/Holidays/Driver.php
PHP | 1417 lines | 678 code | 110 blank | 629 comment | 120 complexity | da0e7c55200556b0f273ca4d4d97f52c MD5 | raw file
- <?php
- /* vim: set expandtab tabstop=4 shiftwidth=4: */
- /**
- * Driver.php
- *
- * PHP Version 4
- *
- * Copyright (c) 1997-2008 The PHP Group
- *
- * This source file is subject to version 2.0 of the PHP license,
- * that is bundled with this package in the file LICENSE, and is
- * available at through the world-wide-web at
- * http://www.php.net/license/2_02.txt.
- * If you did not receive a copy of the PHP license and are unable to
- * obtain it through the world-wide-web, please send a note to
- * license@php.net so we can mail you a copy immediately.
- *
- * Authors: Carsten Lucke <luckec@tool-garage.de>
- *
- * CVS file id: $Id: Driver.php 321620 2011-12-31 20:59:14Z danielc $
- *
- * @category Date
- * @package Date_Holidays
- * @author Carsten Lucke <luckec@tool-garage.de>
- * @license http://www.php.net/license/3_01.txt PHP License 3.0.1
- * @version CVS: $Id: Driver.php 321620 2011-12-31 20:59:14Z danielc $
- * @link http://pear.php.net/package/Date_Holidays
- */
- /**
- * DriverClass and associated defines.
- *
- * @abstract
- * @category Date
- * @package Date_Holidays
- * @author Carsten Lucke <luckec@tool-garage.de>
- * @license http://www.php.net/license/3_01.txt PHP License 3.0.1
- * @version CVS: $Id: Driver.php 321620 2011-12-31 20:59:14Z danielc $
- * @link http://pear.php.net/package/Date_Holidays
- */
- /**
- * uses PEAR_Errorstack
- */
- require_once 'PEAR/ErrorStack.php';
- require_once 'Date/Holidays/Filter.php';
- require_once 'Date/Holidays/Filter/Whitelist.php';
- require_once 'Date/Holidays/Filter/Blacklist.php';
- /**
- * invalid internal name
- *
- * @access public
- */
- define('DATE_HOLIDAYS_INVALID_INTERNAL_NAME', 51);
- /**
- * title for a holiday is not available
- *
- * @access public
- */
- define('DATE_HOLIDAYS_TITLE_UNAVAILABLE', 52);
- /**
- * date could not be converted into a PEAR::Date object
- *
- * date was neither a timestamp nor a string
- *
- * @access public
- * @deprecated will certainly be removed
- */
- define('DATE_HOLIDAYS_INVALID_DATE', 53);
- /**
- * string that represents a date has wrong format
- *
- * format must be YYYY-MM-DD
- *
- * @access public
- * @deprecated will certainly be removed
- */
- define('DATE_HOLIDAYS_INVALID_DATE_FORMAT', 54);
- /**
- * date for a holiday is not available
- *
- * @access public
- */
- define('DATE_HOLIDAYS_DATE_UNAVAILABLE', 55);
- /**
- * language-file doesn't exist
- *
- * @access public
- */
- define('DATE_HOLIDAYS_LANGUAGEFILE_NOT_FOUND', 56);
- /**
- * unable to read language-file
- *
- * @access public
- */
- define('DATE_HOLIDAYS_UNABLE_TO_READ_TRANSLATIONDATA', 57);
- /**
- * Name of the static {@link Date_Holidays_Driver} method returning
- * a array of possible ISO3166 codes that identify itself.
- *
- * @access public
- */
- define('DATE_HOLIDAYS_DRIVER_IDENTIFY_ISO3166_METHOD', 'getISO3166Codes');
- /**
- * class that helps you to locate holidays for a year
- *
- * @abstract
- * @category Date
- * @package Date_Holidays
- * @subpackage Driver
- * @author Carsten Lucke <luckec@tool-garage.de>
- * @license http://www.php.net/license/3_01.txt PHP License 3.0.1
- * @version CVS: $Id: Driver.php 321620 2011-12-31 20:59:14Z danielc $
- * @link http://pear.php.net/package/Date_Holidays
- */
- class Date_Holidays_Driver
- {
- /**
- * this driver's name
- *
- * @access protected
- * @var string
- */
- var $_driverName;
- /**
- * locale setting for output
- *
- * @access protected
- * @var string
- */
- var $_locale;
- /**
- * locales for which translations of holiday titles are available
- *
- * @access private
- * @var array
- */
- var $_availableLocales = array('C');
- /**
- * object's current year
- *
- * @access protected
- * @var int
- */
- var $_year;
- /**
- * internal names for the available holidays
- *
- * @access protected
- * @var array
- */
- var $_internalNames = array();
- /**
- * dates of the available holidays
- *
- * @access protected
- * @var array
- */
- var $_dates = array();
- /**
- * array of the available holidays indexed by date
- *
- * @access protected
- * @var array
- */
- var $_holidays = array();
- /**
- * localized names of the available holidays
- *
- * @access protected
- * @var array
- */
- var $_titles = array();
- /**
- * Array of holiday-properties indexed by internal-names and
- * furthermore by locales.
- *
- * <code>
- * $_holidayProperties = array(
- * 'internalName1' => array(
- * 'de_DE' => array(),
- * 'en_US' => array(),
- * 'fr_FR' => array()
- * )
- * 'internalName2' => array(
- * 'de_DE' => array(),
- * 'en_US' => array(),
- * 'fr_FR' => array()
- * )
- * );
- * </code>
- */
- var $_holidayProperties = array();
- /**
- * Constructor
- *
- * Use the Date_Holidays::factory() method to construct an object of a
- * certain driver
- *
- * @access protected
- */
- function Date_Holidays_Driver()
- {
- }
- /**
- * Method that returns an array containing the ISO3166 codes that may possibly
- * identify a driver.
- *
- * @static
- * @access public
- * @return array possible ISO3166 codes
- */
- function getISO3166Codes()
- {
- return array();
- }
- /**
- * Sets the driver's current year
- *
- * Calling this method forces the object to rebuild the holidays
- *
- * @param int $year year
- *
- * @access public
- * @return boolean true on success, otherwise a PEAR_ErrorStack object
- * @throws object PEAR_ErrorStack
- * @uses _buildHolidays()
- */
- function setYear($year)
- {
- $this->_year = $year;
- return $this->_buildHolidays();
- }
- /**
- * Returns the driver's current year
- *
- * @access public
- * @return int current year
- */
- function getYear()
- {
- return $this->_year;
- }
- /**
- * Build the internal arrays that contain data about the calculated holidays
- *
- * @abstract
- * @access protected
- * @return boolean true on success, otherwise a PEAR_ErrorStack object
- * @throws object PEAR_ErrorStack
- */
- function _buildHolidays()
- {
- }
- /**
- * Add a driver component
- *
- * @param object $driver Date_Holidays_Driver object
- *
- * @abstract
- * @access public
- * @return void
- */
- function addDriver($driver)
- {
- }
- /**
- * addTranslation
- *
- * Search for installed language files appropriate for the specified
- * locale and add them to the driver
- *
- * @param string $locale locale setting to be used
- *
- * @access public
- * @return boolean true on success, otherwise false
- */
- function addTranslation($locale)
- {
- $data_dir = "@DATA-DIR@";
- $bestLocale = $this->_findBestLocale($locale);
- $matches = array();
- $loaded = false;
- if ($data_dir == '@'.'DATA-DIR'.'@') {
- $data_dir = dirname(dirname(dirname(__FILE__)));
- $stubdirs = array(
- "$data_dir/lang/{$this->_driverName}/",
- "$data_dir/lang/Christian/");
- } else {
- //Christian driver is exceptional...
- if ($this->_driverName == 'Christian') {
- $stubdir = "$data_dir/Date_Holidays/lang/Christian/";
- } else {
- $stubdir = "$data_dir/Date_Holidays_{$this->_driverName}/lang/{$this->_driverName}/";
- if (! is_dir($stubdir)) {
- $stubdir = $data_dir . "/Date_Holidays/lang/";
- }
- }
- $stubdirs = array(
- $stubdir,
- "$data_dir/Date_Holidays_{$this->_driverName}/lang/Christian/");
- }
- foreach ($stubdirs as $stubdir) {
- if (is_dir($stubdir)) {
- if ($dh = opendir($stubdir)) {
- while (($file = readdir($dh)) !== false) {
- if (strlen($locale) == 5) {
- if (((strncasecmp($file, $bestLocale, 5) == 0))
- || (strncasecmp($file, $locale, 5) == 0)
- ) {
- array_push($matches, $file);
- }
- }
- if (strlen($locale) == 2) {
- if (((strncasecmp($file, $bestLocale, 2) == 0))
- || (strncasecmp($file, $locale, 2) == 0)
- ) {
- array_push($matches, $file);
- }
- }
- }
- closedir($dh);
- $forget = array();
- sort($matches);
- foreach ($matches as $am) {
- if (strpos($am, ".ser") !== false) {
- $this->addCompiledTranslationFile($stubdir.$am, $locale);
- $loaded = true;
- array_push($forget, basename($am, ".ser") . ".xml");
- } else {
- if (!in_array($am, $forget)) {
- $this->addTranslationFile(
- $stubdir . $am,
- str_replace(".xml", "", $am)
- );
- $loaded = true;
- }
- }
- }
- }
- }
- }
- return $loaded;
- }
- /**
- * Remove a driver component
- *
- * @param object $driver Date_Holidays_Driver driver-object
- *
- * @abstract
- * @access public
- * @return boolean true on success, otherwise a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_DRIVER_NOT_FOUND
- */
- function removeDriver($driver)
- {
- }
- /**
- * Returns the internal names of holidays that were calculated
- *
- * @access public
- * @return array
- */
- function getInternalHolidayNames()
- {
- return $this->_internalNames;
- }
- /**
- * Returns localized titles of all holidays or those accepted by the filter
- *
- * @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
- * @param string $locale locale setting that shall be used
- * by this method
- *
- * @access public
- * @return array $filter array with localized holiday titles on success,
- * otherwise a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- * @uses getHolidayTitle()
- */
- function getHolidayTitles($filter = null, $locale = null)
- {
- if (is_null($filter)) {
- $filter = new Date_Holidays_Filter_Blacklist(array());
- } elseif (is_array($filter)) {
- $filter = new Date_Holidays_Filter_Whitelist($filter);
- }
- $titles = array();
- foreach ($this->_internalNames as $internalName) {
- if ($filter->accept($internalName)) {
- $title = $this->getHolidayTitle($internalName, $locale);
- if (Date_Holidays::isError($title)) {
- return $title;
- }
- $titles[$internalName] = $title;
- }
- }
- return $titles;
- }
- /**
- * Returns localized title for a holiday
- *
- * @param string $internalName internal name for holiday
- * @param string $locale locale setting to be used by this method
- *
- * @access public
- * @return string title on success, otherwise a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- * @throws object PEAR_Error DATE_HOLIDAYS_TITLE_UNAVAILABLE
- */
- function getHolidayTitle($internalName, $locale = null)
- {
- if (! in_array($internalName, $this->_internalNames)) {
- $msg = 'Invalid internal name: ' . $internalName;
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_INTERNAL_NAME,
- $msg);
- }
- if (is_null($locale)) {
- $locale = $this->_findBestLocale($this->_locale);
- } else {
- $locale = $this->_findBestLocale($locale);
- }
- if (! isset($this->_titles[$locale][$internalName])) {
- if (Date_Holidays::staticGetProperty('DIE_ON_MISSING_LOCALE')) {
- $err = DATE_HOLIDAYS_TITLE_UNAVAILABLE;
- $msg = 'The internal name (' . $internalName . ') ' .
- 'for the holiday was correct but no ' .
- 'localized title could be found';
- return Date_Holidays::raiseError($err, $msg);
- }
- }
- if (isset($this->_titles[$locale][$internalName])) {
- return $this->_titles[$locale][$internalName];
- } else {
- return $this->_titles['C'][$internalName];
- }
- }
- /**
- * Returns the localized properties of a holiday. If no properties have
- * been stored an empty array will be returned.
- *
- * @param string $internalName internal name for holiday
- * @param string $locale locale setting that shall be used by this method
- *
- * @access public
- * @return array array of properties on success, otherwise
- * a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- */
- function getHolidayProperties($internalName, $locale = null)
- {
- if (! in_array($internalName, $this->_internalNames)) {
- $msg = 'Invalid internal name: ' . $internalName;
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_INTERNAL_NAME,
- $msg);
- }
- if (is_null($locale)) {
- $locale = $this->_findBestLocale($this->_locale);
- } else {
- $locale = $this->_findBestLocale($locale);
- }
- $properties = array();
- if (isset($this->_holidayProperties[$internalName][$locale])) {
- $properties = $this->_holidayProperties[$internalName][$locale];
- }
- return $properties;
- }
- /**
- * Returns all holidays that the driver knows.
- *
- * You can limit the holidays by passing a filter, then only those
- * holidays accepted by the filter will be returned.
- *
- * Return format:
- * <pre>
- * array(
- * 'easter' => object of type Date_Holidays_Holiday,
- * 'eastermonday' => object of type Date_Holidays_Holiday,
- * ...
- * )
- * </pre>
- *
- * @param Date_Holidays_Filter $filter filter-object
- * (or an array !DEPRECATED!)
- * @param string $locale locale setting that shall be used
- * by this method
- *
- * @access public
- * @return array numeric array containing objects of
- * Date_Holidays_Holiday on success, otherwise a
- * PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- * @see getHoliday()
- */
- function getHolidays($filter = null, $locale = null)
- {
- if (is_null($filter)) {
- $filter = new Date_Holidays_Filter_Blacklist(array());
- } elseif (is_array($filter)) {
- $filter = new Date_Holidays_Filter_Whitelist($filter);
- }
- if (is_null($locale)) {
- $locale = $this->_locale;
- }
- $holidays = array();
- foreach ($this->_internalNames as $internalName) {
- if ($filter->accept($internalName)) {
- // no need to check for valid internal-name, will be
- // done by #getHoliday()
- $holidays[$internalName] = $this->getHoliday($internalName,
- $locale);
- }
- }
- return $holidays;
- }
- /**
- * Returns the specified holiday
- *
- * Return format:
- * <pre>
- * array(
- * 'title' => 'Easter Sunday'
- * 'date' => '2004-04-11'
- * )
- * </pre>
- *
- * @param string $internalName internal name of the holiday
- * @param string $locale locale setting that shall be used
- * by this method
- *
- * @access public
- * @return object Date_Holidays_Holiday holiday's information on
- * success, otherwise a PEAR_Error
- * object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- * @uses getHolidayTitle()
- * @uses getHolidayDate()
- */
- function getHoliday($internalName, $locale = null)
- {
- if (! in_array($internalName, $this->_internalNames)) {
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_INTERNAL_NAME,
- 'Invalid internal name: ' . $internalName);
- }
- if (is_null($locale)) {
- $locale = $this->_locale;
- }
- $title = $this->getHolidayTitle($internalName, $locale);
- if (Date_Holidays::isError($title)) {
- return $title;
- }
- $date = $this->getHolidayDate($internalName);
- if (Date_Holidays::isError($date)) {
- return $date;
- }
- $properties = $this->getHolidayProperties($internalName, $locale);
- if (Date_Holidays::isError($properties)) {
- return $properties;
- }
- $holiday = new Date_Holidays_Holiday($internalName,
- $title,
- $date,
- $properties);
- return $holiday;
- }
- /**
- * Determines whether a date represents a holiday or not
- *
- * @param mixed $date a timestamp, string or PEAR::Date object
- * @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
- *
- * @access public
- * @return boolean true if date represents a holiday, otherwise false
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE_FORMAT
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE
- */
- function isHoliday($date, $filter = null)
- {
- if (! is_a($date, 'Date')) {
- $date = $this->_convertDate($date);
- if (Date_Holidays::isError($date)) {
- return $date;
- }
- }
- //rebuild internal array of holidays if required.
- $compare_year = $date->getYear();
- $this_year = $this->getYear();
- if ($this_year !== $compare_year) {
- $this->setYear($compare_year);
- }
- if (is_null($filter)) {
- $filter = new Date_Holidays_Filter_Blacklist(array());
- } elseif (is_array($filter)) {
- $filter = new Date_Holidays_Filter_Whitelist($filter);
- }
- foreach (array_keys($this->_dates) as $internalName) {
- if ($filter->accept($internalName)) {
- if (Date_Holidays_Driver::dateSloppyCompare($date,
- $this->_dates[$internalName]) != 0) {
- continue;
- }
- $this->setYear($this_year);
- return true;
- }
- }
- $this->setYear($this_year);
- return false;
- }
- /**
- * Returns a <code>Date_Holidays_Holiday</code> object, if any was found,
- * matching the specified date.
- *
- * Normally the method will return the object of the first holiday matching
- * the date. If you want the method to continue searching holidays for the
- * specified date, set the 4th param to true.
- *
- * If multiple holidays match your date, the return value will be an array
- * containing a number of <code>Date_Holidays_Holiday</code> items.
- *
- * @param mixed $date date (timestamp | string | PEAR::Date object)
- * @param string $locale locale setting that shall be used by this method
- * @param boolean $multiple if true, continue searching holidays for
- * specified date
- *
- * @access public
- * @return object object of type Date_Holidays_Holiday on success
- * (numeric array of those on multiple search),
- * if no holiday was found, matching this date,
- * null is returned
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE_FORMAT
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE
- * @uses getHoliday()
- * @uses getHolidayTitle()
- * @see getHoliday()
- **/
- function getHolidayForDate($date, $locale = null, $multiple = false)
- {
- if (!is_a($date, 'Date')) {
- $date = $this->_convertDate($date);
- if (Date_Holidays::isError($date)) {
- return $date;
- }
- }
- if ($date->getYear() != $this->_year) {
- return null;
- }
- $isodate = mktime(0,
- 0,
- 0,
- $date->getMonth(),
- $date->getDay(),
- $date->getYear());
- unset($date);
- if (is_null($locale)) {
- $locale = $this->_locale;
- }
- if (array_key_exists($isodate, $this->_holidays)) {
- if (!$multiple) {
- //get only the first feast for this day
- $internalName = $this->_holidays[$isodate][0];
- $result = $this->getHoliday($internalName, $locale);
- return Date_Holidays::isError($result) ? null : $result;
- }
- // array that collects data, if multiple searching is done
- $data = array();
- foreach ($this->_holidays[$isodate] as $internalName) {
- $result = $this->getHoliday($internalName, $locale);
- if (Date_Holidays::isError($result)) {
- continue;
- }
- $data[] = $result;
- }
- return $data;
- }
- return null;
- }
- /**
- * Returns an array containing a number of
- * <code>Date_Holidays_Holiday</code> items.
- *
- * If no items have been found the returned array will be empty.
- *
- * @param mixed $start date: timestamp, string or PEAR::Date
- * @param mixed $end date: timestamp, string or PEAR::Date
- * @param Date_Holidays_Filter $filter filter-object (or
- * an array !DEPRECATED!)
- * @param string $locale locale setting that shall be used
- * by this method
- *
- * @access public
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE_FORMAT
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE
- * @return array an array containing a number
- * of <code>Date_Holidays_Holiday</code> items
- */
- function getHolidaysForDatespan($start, $end, $filter = null, $locale = null)
- {
- if (is_null($filter)) {
- $filter = new Date_Holidays_Filter_Blacklist(array());
- } elseif (is_array($filter)) {
- $filter = new Date_Holidays_Filter_Whitelist($filter);
- }
- if (!is_a($start, 'Date')) {
- $start = $this->_convertDate($start);
- if (Date_Holidays::isError($start)) {
- return $start;
- }
- }
- if (!is_a($end, 'Date')) {
- $end = $this->_convertDate($end);
- if (Date_Holidays::isError($end)) {
- return $end;
- }
- }
- $isodateStart = mktime(0,
- 0,
- 0,
- $start->getMonth(),
- $start->getDay(),
- $start->getYear());
- unset($start);
- $isodateEnd = mktime(0,
- 0,
- 0,
- $end->getMonth(),
- $end->getDay(),
- $end->getYear());
- unset($end);
- if (is_null($locale)) {
- $locale = $this->_locale;
- }
- $internalNames = array();
- foreach ($this->_holidays as $isoDateTS => $arHolidays) {
- if ($isoDateTS >= $isodateStart && $isoDateTS <= $isodateEnd) {
- $internalNames = array_merge($internalNames, $arHolidays);
- }
- }
- $retval = array();
- foreach ($internalNames as $internalName) {
- if ($filter->accept($internalName)) {
- $retval[] = $this->getHoliday($internalName, $locale);
- }
- }
- return $retval;
- }
- /**
- * Converts timestamp or date-string into da PEAR::Date object
- *
- * @param mixed $date date
- *
- * @static
- * @access private
- * @return object PEAR_Date
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE_FORMAT
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_DATE
- */
- function _convertDate($date)
- {
- if (is_string($date)) {
- if (! preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}/', $date)) {
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_DATE_FORMAT,
- 'Date-string has wrong format (must be YYYY-MM-DD)');
- }
- $date = new Date($date);
- return $date;
- }
- if (is_int($date)) {
- $date = new Date(date('Y-m-d', $date));
- return $date;
- }
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_DATE,
- 'The date you specified is invalid');
- }
- /**
- * Adds all holidays in the array to the driver's internal list of holidays.
- *
- * Format of the array:
- * <pre>
- * array(
- * 'newYearsDay' => array(
- * 'date' => '01-01',
- * 'title' => 'New Year\'s Day',
- * 'translations' => array(
- * 'de_DE' => 'Neujahr',
- * 'en_EN' => 'New Year\'s Day'
- * )
- * ),
- * 'valentinesDay' => array(
- * ...
- * )
- * );
- * </pre>
- *
- * @param array $holidays static holidays' data
- *
- * @access protected
- * @uses _addHoliday()
- * @return void
- */
- function _addStaticHolidays($holidays)
- {
- foreach ($holidays as $internalName => $holiday) {
- // add the holiday's basic data
- $this->_addHoliday($internalName,
- $this->_year . '-' . $holiday['date'],
- $holiday['title']);
- }
- }
- /**
- * Adds a holiday to the driver's holidays
- *
- * @param string $internalName internal name - must not contain characters
- * that aren't allowed as variable-names
- * @param mixed $date date (timestamp | string | PEAR::Date object)
- * @param string $title holiday title
- *
- * @access protected
- * @return void
- */
- function _addHoliday($internalName, $date, $title)
- {
- if (! is_a($date, 'Date')) {
- $date = new Date($date);
- }
- $this->_dates[$internalName] = $date;
- $this->_titles['C'][$internalName] = $title;
- $isodate = mktime(0, 0, 0,
- $date->getMonth(),
- $date->getDay(),
- $date->getYear());
- if (!isset($this->_holidays[$isodate])) {
- $this->_holidays[$isodate] = array();
- }
- array_push($this->_holidays[$isodate], $internalName);
- array_push($this->_internalNames, $internalName);
- }
- /**
- * Add a localized translation for a holiday's title. Overwrites existing data.
- *
- * @param string $internalName internal name of an existing holiday
- * @param string $locale locale setting that shall be used by this method
- * @param string $title title
- *
- * @access protected
- * @return true on success, otherwise a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- */
- function _addTranslationForHoliday($internalName, $locale, $title)
- {
- if (! in_array($internalName, $this->_internalNames)) {
- $msg = 'Couldn\'t add translation (' . $locale . ') ' .
- 'for holiday with this internal name: ' . $internalName;
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_INTERNAL_NAME,
- $msg);
- }
- if (! in_array($locale, $this->_availableLocales)) {
- array_push($this->_availableLocales, $locale);
- }
- $this->_titles[$locale][$internalName] = $title;
- return true;
- }
- /**
- * Adds a localized (regrading translation etc.) string-property for a holiday.
- * Overwrites existing data.
- *
- * @param string $internalName internal-name
- * @param string $locale locale-setting
- * @param string $propId property-identifier
- * @param mixed $propVal property-value
- *
- * @access public
- * @return boolean true on success, false otherwise
- * @throws PEAR_ErrorStack if internal-name does not exist
- */
- function _addStringPropertyForHoliday($internalName, $locale, $propId, $propVal)
- {
- if (! in_array($internalName, $this->_internalNames)) {
- $msg = 'Couldn\'t add property (locale: ' . $locale . ') '.
- 'for holiday with this internal name: ' . $internalName;
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_INTERNAL_NAME,
- $msg);
- }
- if (!isset($this->_holidayProperties[$internalName]) ||
- !is_array($this->_holidayProperties[$internalName])) {
- $this->_holidayProperties[$internalName] = array();
- }
- if (! isset($this->_holidayProperties[$internalName][$locale]) ||
- !is_array($this->_holidayProperties[$internalName][$locale])) {
- $this->_holidayProperties[$internalName][$locale] = array();
- }
- $this->_holidayProperties[$internalName][$locale][$propId] = $propVal;
- return true;
- }
- /**
- * Adds a arbitrary number of localized string-properties for the
- * specified holiday.
- *
- * @param string $internalName internal-name
- * @param string $locale locale-setting
- * @param array $properties associative array: array(propId1 => val1,...)
- *
- * @access public
- * @return boolean true on success, false otherwise
- * @throws PEAR_ErrorStack if internal-name does not exist
- */
- function _addStringPropertiesForHoliday($internalName, $locale, $properties)
- {
- foreach ($properties as $propId => $propValue) {
- return $this->_addStringPropertyForHoliday($internalName,
- $locale,
- $propId,
- $propValue);
- }
- return true;
- }
- /**
- * Add a language-file's content
- *
- * The language-file's content will be parsed and translations,
- * properties, etc. for holidays will be made available with the specified
- * locale.
- *
- * @param string $file filename of the language file
- * @param string $locale locale-code of the translation
- *
- * @access public
- * @return boolean true on success, otherwise a PEAR_ErrorStack object
- * @throws object PEAR_Errorstack
- */
- function addTranslationFile($file, $locale)
- {
- if (! file_exists($file)) {
- Date_Holidays::raiseError(DATE_HOLIDAYS_LANGUAGEFILE_NOT_FOUND,
- 'Language-file not found: ' . $file);
- return Date_Holidays::getErrorStack();
- }
- include_once 'XML/Unserializer.php';
- $options = array('parseAttributes' => false,
- 'attributesArray' => false,
- 'keyAttribute' => array('property' => 'id'),
- 'forceEnum' => array('holiday'));
- // unserialize the document
- $unserializer = new XML_Unserializer($options);
- $status = $unserializer->unserialize($file, true);
- if (PEAR::isError($status)) {
- return Date_Holidays::raiseError($status->getCode(),
- $status->getMessage());
- }
- $content = $unserializer->getUnserializedData();
- if (PEAR::isError($content)) {
- return Date_Holidays::raiseError($content->getCode(),
- $content->getMessage());
- }
- return $this->_addTranslationData($content, $locale);
- }
- /**
- * Add a compiled language-file's content
- *
- * The language-file's content will be unserialized and translations,
- * properties, etc. for holidays will be made available with the
- * specified locale.
- *
- * @param string $file filename of the compiled language file
- * @param string $locale locale-code of the translation
- *
- * @access public
- * @return boolean true on success, otherwise a PEAR_ErrorStack object
- * @throws object PEAR_Errorstack
- */
- function addCompiledTranslationFile($file, $locale)
- {
- if (! file_exists($file)) {
- Date_Holidays::raiseError(DATE_HOLIDAYS_LANGUAGEFILE_NOT_FOUND,
- 'Language-file not found: ' . $file);
- return Date_Holidays::getErrorStack();
- }
- $content = file_get_contents($file);
- if ($content === false) {
- return false;
- }
- $data = unserialize($content);
- if ($data === false) {
- $e = DATE_HOLIDAYS_UNABLE_TO_READ_TRANSLATIONDATA;
- $msg = "Unable to read translation-data - file maybe damaged: $file";
- return Date_Holidays::raiseError($e, $msg);
- }
- return $this->_addTranslationData($data, $locale);
- }
- /**
- * Add a language-file's content. Translations, properties, etc. for
- * holidays will be made available with the specified locale.
- *
- * @param array $data translated data
- * @param string $locale locale-code of the translation
- *
- * @access public
- * @return boolean true on success, otherwise a PEAR_ErrorStack object
- * @throws object PEAR_Errorstack
- */
- function _addTranslationData($data, $locale)
- {
- foreach ($data['holidays']['holiday'] as $holiday) {
- $this->_addTranslationForHoliday($holiday['internal-name'],
- $locale,
- $holiday['translation']);
- if (isset($holiday['properties']) && is_array($holiday['properties'])) {
- foreach ($holiday['properties'] as $propId => $propVal) {
- $this->_addStringPropertyForHoliday($holiday['internal-name'],
- $locale,
- $propId,
- $propVal);
- }
- }
- }
- if (Date_Holidays::errorsOccurred()) {
- return Date_Holidays::getErrorStack();
- }
- return true;
- }
- /**
- * Remove a holiday from internal storage
- *
- * This method should be used within driver classes to unset holidays that
- * were inherited from parent-drivers
- *
- * @param $string $internalName internal name
- *
- * @access protected
- * @return boolean true on success, otherwise a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- */
- function _removeHoliday($internalName)
- {
- if (! in_array($internalName, $this->_internalNames)) {
- $msg = "Couldn't remove holiday with this internal name: $internalName";
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_INTERNAL_NAME,
- $msg);
- }
- if (isset($this->_dates[$internalName])) {
- unset($this->_dates[$internalName]);
- }
- $locales = array_keys($this->_titles);
- foreach ($locales as $locale) {
- if (isset($this->_titles[$locale][$internalName])) {
- unset($this->_titles[$locale][$internalName]);
- }
- }
- $index = array_search($internalName, $this->_internalNames);
- if (! is_null($index)) {
- unset($this->_internalNames[$index]);
- }
- return true;
- }
- /**
- * Finds the best internally available locale for the specified one
- *
- * @param string $locale locale
- *
- * @access protected
- * @return string best locale available
- */
- function _findBestLocale($locale)
- {
- /* exact locale is available */
- if (in_array($locale, $this->_availableLocales)) {
- return $locale;
- }
- /* first two letter are equal */
- foreach ($this->_availableLocales as $aLocale) {
- if (strncasecmp($aLocale, $locale, 2) == 0) {
- return $aLocale;
- }
- }
- /* no appropriate locale available, will use driver's internal locale */
- return 'C';
- }
- /**
- * Returns date of a holiday
- *
- * @param string $internalName internal name for holiday
- *
- * @access public
- * @return object Date date of holiday as PEAR::Date object
- * on success, otherwise a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_DATE_UNAVAILABLE
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- */
- function getHolidayDate($internalName)
- {
- if (! in_array($internalName, $this->_internalNames)) {
- $msg = 'Invalid internal name: ' . $internalName;
- return Date_Holidays::raiseError(DATE_HOLIDAYS_INVALID_INTERNAL_NAME,
- $msg);
- }
- if (! isset($this->_dates[$internalName])) {
- $msg = 'Date for holiday with internal name ' .
- $internalName . ' is not available';
- return Date_Holidays::raiseError(DATE_HOLIDAYS_DATE_UNAVAILABLE, $msg);
- }
- return $this->_dates[$internalName];
- }
- /**
- * Returns dates of all holidays or those accepted by the applied filter.
- *
- * Structure of the returned array:
- * <pre>
- * array(
- * 'internalNameFoo' => object of type date,
- * 'internalNameBar' => object of type date
- * )
- * </pre>
- *
- * @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
- *
- * @access public
- * @return array with holidays' dates on success, otherwise a PEAR_Error object
- * @throws object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
- * @uses getHolidayDate()
- */
- function getHolidayDates($filter = null)
- {
- if (is_null($filter)) {
- $filter = new Date_Holidays_Filter_Blacklist(array());
- } elseif (is_array($filter)) {
- $filter = new Date_Holidays_Filter_Whitelist($filter);
- }
- $dates = array();
- foreach ($this->_internalNames as $internalName) {
- if ($filter->accept($internalName)) {
- $date = $this->getHolidayDate($internalName);
- if (Date_Holidays::isError($date)) {
- return $date;
- }
- $dates[$internalName] = $this->getHolidayDate($internalName);
- }
- }
- return $dates;
- }
- /**
- * Sets the driver's locale
- *
- * @param string $locale locale
- *
- * @access public
- * @return void
- */
- function setLocale($locale)
- {
- $this->_locale = $locale;
- //if possible, load the translation files for this locale
- $this->addTranslation($locale);
- }
- /**
- * Sloppily compares two date objects (only year, month and day are compared).
- * Does not take the date's timezone into account.
- *
- * @param Date $d1 a date object
- * @param Date $d2 another date object
- *
- * @static
- * @access private
- * @return int 0 if the dates are equal,
- * -1 if d1 is before d2,
- * 1 if d1 is after d2
- */
- function dateSloppyCompare($d1, $d2)
- {
- $d1->setTZ(new Date_TimeZone('UTC'));
- $d2->setTZ(new Date_TimeZone('UTC'));
- $days1 = Date_Calc::dateToDays($d1->day, $d1->month, $d1->year);
- $days2 = Date_Calc::dateToDays($d2->day, $d2->month, $d2->year);
- if ($days1 < $days2) return -1;
- if ($days1 > $days2) return 1;
- return 0;
- }
- /**
- * Find the date of the first monday in the specified year of the current year.
- *
- * @param integer $month month
- *
- * @access private
- * @return object Date date of first monday in specified month.
- */
- function _calcFirstMonday($month)
- {
- $month = sprintf("%02d", $month);
- $date = new Date($this->_year . "-$month-01");
- while ($date->getDayOfWeek() != 1) {
- $date = $date->getNextDay();
- }
- return ($date);
- }
- /**
- * Find the date of the last monday in the specified year of the current year.
- *
- * @param integer $month month
- *
- * @access private
- * @return object Date date of last monday in specified month.
- */
- function _calcLastMonday($month)
- {
- //work backwards from the first day of the next month.
- $month = sprintf("%02d", $month);
- $nm = ((int) $month ) + 1;
- if ($nm > 12) {
- $nm = 1;
- }
- $nm = sprintf("%02d", $nm);
- $date = new Date($this->_year . "-$nm-01");
- $date = $date->getPrevDay();
- while ($date->getDayOfWeek() != 1) {
- $date = $date->getPrevDay();
- }
- return ($date);
- }
- /**
- * Calculate Nth monday in a month
- *
- * @param int $month month
- * @param int $position position
- *
- * @access private
- * @return object Date date
- */
- function _calcNthMondayInMonth($month, $position)
- {
- if ($position == 1) {
- $startday = '01';
- } elseif ($position == 2) {
- $startday = '08';
- } elseif ($position == 3) {
- $startday = '15';
- } elseif ($position == 4) {
- $startday = '22';
- } elseif ($position == 5) {
- $startday = '29';
- }
- $month = sprintf("%02d", $month);
- $date = new Date($this->_year . '-' . $month . '-' . $startday);
- while ($date->getDayOfWeek() != 1) {
- $date = $date->getNextDay();
- }
- return $date;
- }
- /**
- * Calculate Nth day of the week in a month
- *
- * @param int $position position
- * @param int $weekday day of the week starting from 1 == sunday
- * @param int $month month
- *
- * @access private
- * @return object Date date
- */
- function _calcNthWeekDayInMonth($position, $weekday, $month)
- {
- if ($position == 1) {
- $startday = '01';
- } elseif ($position == 2) {
- $startday = '08';
- } elseif ($position == 3) {
- $startday = '15';
- } elseif ($position == 4) {
- $startday = '22';
- } elseif ($position == 5) {
- $startday = '29';
- }
- $month = sprintf("%02d", $month);
- $date = new Date($this->_year . '-' . $month . '-' . $startday);
- while ($date->getDayOfWeek() != $weekday) {
- $date = $date->getNextDay();
- }
- return $date;
- }
- /**
- * Converts the date to the specified no of days from the given date
- *
- * To subtract days use a negative value for the '$pn_days' parameter
- *
- * @param Date $date Date object
- * @param int $pn_days days to add
- *
- * @return Date
- * @access protected
- */
- function _addDays($date, $pn_days)
- {
- $new_date = new Date($date);
- list($new_date->year, $new_date->month, $new_date->day) =
- explode(' ',
- Date_Calc::daysToDate(Date_Calc::dateToDays($date->day,
- $date->month,
- $date->year) +
- $pn_days,
- '%Y %m %d'));
- if (isset($new_date->on_standardyear)) {
- $new_date->on_standardyear = $new_date->year;
- $new_date->on_standardmonth = $new_date->month;
- $new_date->on_standardday = $new_date->day;
- }
- return $new_date;
- }
- }
- ?>