Date_Holidays
[ class tree: Date_Holidays ] [ index: Date_Holidays ] [ all elements ]

Source for file Driver.php

Documentation is available at Driver.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. /**
  4.  * Driver.php
  5.  *
  6.  * PHP Version 4
  7.  *
  8.  * Copyright (c) 1997-2008 The PHP Group
  9.  *
  10.  * This source file is subject to version 2.0 of the PHP license,
  11.  * that is bundled with this package in the file LICENSE, and is
  12.  * available at through the world-wide-web at
  13.  * http://www.php.net/license/2_02.txt.
  14.  * If you did not receive a copy of the PHP license and are unable to
  15.  * obtain it through the world-wide-web, please send a note to
  16.  * license@php.net so we can mail you a copy immediately.
  17.  *
  18.  * Authors:   Carsten Lucke <luckec@tool-garage.de>
  19.  *
  20.  * CVS file id: $Id: Driver.php,v 1.31 2008/03/17 11:13:36 kguest Exp $
  21.  *
  22.  * @category Date
  23.  * @package  Date_Holidays
  24.  * @author   Carsten Lucke <luckec@tool-garage.de>
  25.  * @license  http://www.php.net/license/3_01.txt PHP License 3.0.1
  26.  * @version  CVS: $Id: Driver.php,v 1.31 2008/03/17 11:13:36 kguest Exp $
  27.  * @link     http://pear.php.net/package/Date_Holidays
  28.  */
  29.  
  30. /**
  31.  * DriverClass and associated defines.
  32.  *
  33.  * @abstract
  34.  * @category Date
  35.  * @package  Date_Holidays
  36.  * @author   Carsten Lucke <luckec@tool-garage.de>
  37.  * @license  http://www.php.net/license/3_01.txt PHP License 3.0.1
  38.  * @version  CVS: $Id: Driver.php,v 1.31 2008/03/17 11:13:36 kguest Exp $
  39.  * @link     http://pear.php.net/package/Date_Holidays
  40.  */
  41.  
  42. /**
  43.  * uses PEAR_Errorstack
  44.  */
  45. require_once 'PEAR/ErrorStack.php';
  46. require_once 'Date/Holidays/Filter.php';
  47. require_once 'Date/Holidays/Filter/Whitelist.php';
  48. require_once 'Date/Holidays/Filter/Blacklist.php';
  49.  
  50. /**
  51.  * invalid internal name
  52.  *
  53.  * @access  public
  54.  */
  55. define('DATE_HOLIDAYS_INVALID_INTERNAL_NAME'51);
  56.  
  57. /**
  58.  * title for a holiday is not available
  59.  *
  60.  * @access  public
  61.  */
  62. define('DATE_HOLIDAYS_TITLE_UNAVAILABLE'52);
  63.  
  64. /**
  65.  * date could not be converted into a PEAR::Date object
  66.  *
  67.  * date was neither a timestamp nor a string
  68.  *
  69.  * @access  public
  70.  * @deprecated   will certainly be removed
  71.  */
  72. define('DATE_HOLIDAYS_INVALID_DATE'53);
  73.  
  74. /**
  75.  * string that represents a date has wrong format
  76.  *
  77.  * format must be YYYY-MM-DD
  78.  *
  79.  * @access  public
  80.  * @deprecated   will certainly be removed
  81.  */
  82. define('DATE_HOLIDAYS_INVALID_DATE_FORMAT'54);
  83.  
  84. /**
  85.  * date for a holiday is not available
  86.  *
  87.  * @access  public
  88.  */
  89. define('DATE_HOLIDAYS_DATE_UNAVAILABLE'55);
  90.  
  91. /**
  92.  * language-file doesn't exist
  93.  *
  94.  * @access  public
  95.  */
  96. define('DATE_HOLIDAYS_LANGUAGEFILE_NOT_FOUND'56);
  97.  
  98. /**
  99.  * unable to read language-file
  100.  *
  101.  * @access  public
  102.  */
  103. define('DATE_HOLIDAYS_UNABLE_TO_READ_TRANSLATIONDATA'57);
  104.  
  105. /**
  106.  * Name of the static {@link Date_Holidays_Driver} method returning
  107.  * a array of possible ISO3166 codes that identify itself.
  108.  *
  109.  * @access  public
  110.  */
  111. define('DATE_HOLIDAYS_DRIVER_IDENTIFY_ISO3166_METHOD''getISO3166Codes');
  112.  
  113. /**
  114.  * class that helps you to locate holidays for a year
  115.  *
  116.  * @abstract
  117.  * @category   Date
  118.  * @package    Date_Holidays
  119.  * @subpackage Driver
  120.  * @author     Carsten Lucke <luckec@tool-garage.de>
  121.  * @license    http://www.php.net/license/3_01.txt PHP License 3.0.1
  122.  * @version    CVS: $Id: Driver.php,v 1.31 2008/03/17 11:13:36 kguest Exp $
  123.  * @link       http://pear.php.net/package/Date_Holidays
  124.  */
  125. {
  126.  
  127.     /**
  128.      * locale setting for output
  129.      *
  130.      * @access   protected
  131.      * @var      string 
  132.      */
  133.     var $_locale;
  134.  
  135.     /**
  136.      * locales for which translations of holiday titles are available
  137.      *
  138.      * @access   private
  139.      * @var      array 
  140.      */
  141.     var $_availableLocales = array('C');
  142.  
  143.     /**
  144.      * object's current year
  145.      *
  146.      * @access   protected
  147.      * @var      int 
  148.      */
  149.     var $_year;
  150.  
  151.     /**
  152.      * internal names for the available holidays
  153.      *
  154.      * @access   protected
  155.      * @var      array 
  156.      */
  157.     var $_internalNames = array();
  158.  
  159.     /**
  160.      * dates of the available holidays
  161.      *
  162.      * @access   protected
  163.      * @var      array 
  164.      */
  165.     var $_dates = array();
  166.  
  167.     /**
  168.      * array of the available holidays indexed by date
  169.      *
  170.      * @access   protected
  171.      * @var      array 
  172.      */
  173.     var $_holidays = array();
  174.  
  175.     /**
  176.      * localized names of the available holidays
  177.      *
  178.      * @access   protected
  179.      * @var      array 
  180.      */
  181.     var $_titles = array();
  182.  
  183.     /**
  184.      * Array of holiday-properties indexed by internal-names and
  185.      * furthermore by locales.
  186.      *
  187.      * <code>
  188.      * $_holidayProperties = array(
  189.      *       'internalName1' =>  array(
  190.      *                               'de_DE' => array(),
  191.      *                               'en_US' => array(),
  192.      *                               'fr_FR' => array()
  193.      *                           )
  194.      *       'internalName2' =>  array(
  195.      *                               'de_DE' => array(),
  196.      *                               'en_US' => array(),
  197.      *                               'fr_FR' => array()
  198.      *                           )
  199.      * );
  200.      * </code>
  201.      */
  202.     var $_holidayProperties = array();
  203.  
  204.     /**
  205.      * Constructor
  206.      *
  207.      * Use the Date_Holidays::factory() method to construct an object of a
  208.      * certain driver
  209.      *
  210.      * @access   protected
  211.      */
  212.     function Date_Holidays_Driver()
  213.     {
  214.     }
  215.  
  216.     /**
  217.      * Method that returns an array containing the ISO3166 codes that may possibly
  218.      * identify a driver.
  219.      *
  220.      * @static
  221.      * @access public
  222.      * @return array possible ISO3166 codes
  223.      */
  224.     function getISO3166Codes()
  225.     {
  226.         return array();
  227.     }
  228.  
  229.     /**
  230.      * Sets the driver's current year
  231.      *
  232.      * Calling this method forces the object to rebuild the holidays
  233.      *
  234.      * @param int $year year
  235.      *
  236.      * @access   public
  237.      * @return   boolean true on success, otherwise a PEAR_ErrorStack object
  238.      * @throws   object PEAR_ErrorStack
  239.      * @uses     _buildHolidays()
  240.      */
  241.     function setYear($year)
  242.     {
  243.         $this->_year = $year;
  244.         return $this->_buildHolidays();
  245.     }
  246.  
  247.     /**
  248.      * Returns the driver's current year
  249.      *
  250.      * @access   public
  251.      * @return   int     current year
  252.      */
  253.     function getYear()
  254.     {
  255.         return $this->_year;
  256.     }
  257.  
  258.     /**
  259.      * Build the internal arrays that contain data about the calculated holidays
  260.      *
  261.      * @abstract
  262.      * @access   protected
  263.      * @return   boolean true on success, otherwise a PEAR_ErrorStack object
  264.      * @throws   object PEAR_ErrorStack
  265.      */
  266.     function _buildHolidays()
  267.     {
  268.     }
  269.  
  270.     /**
  271.      * Add a driver component
  272.      *
  273.      * @param object $driver Date_Holidays_Driver object
  274.      *
  275.      * @abstract
  276.      * @access public
  277.      * @return void 
  278.      */
  279.     function addDriver($driver)
  280.     {
  281.     }
  282.  
  283.     /**
  284.      * Remove a driver component
  285.      *
  286.      * @param object $driver Date_Holidays_Driver driver-object
  287.      *
  288.      * @abstract
  289.      * @access   public
  290.      * @return   boolean true on success, otherwise a PEAR_Error object
  291.      * @throws   object PEAR_Error   DATE_HOLIDAYS_DRIVER_NOT_FOUND
  292.      */
  293.     function removeDriver($driver)
  294.     {
  295.     }
  296.  
  297.     /**
  298.      * Returns the internal names of holidays that were calculated
  299.      *
  300.      * @access   public
  301.      * @return   array 
  302.      */
  303.     function getInternalHolidayNames()
  304.     {
  305.         return $this->_internalNames;
  306.     }
  307.  
  308.     /**
  309.      * Returns localized titles of all holidays or those accepted by the filter
  310.      *
  311.      * @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
  312.      * @param string               $locale locale setting that shall be used
  313.      *                                      by this method
  314.      *
  315.      * @access   public
  316.      * @return   array   $filter array with localized holiday titles on success,
  317.      *                            otherwise a PEAR_Error object
  318.      * @throws   object PEAR_Error   DATE_HOLIDAYS_INVALID_INTERNAL_NAME
  319.      * @uses     getHolidayTitle()
  320.      */
  321.     function getHolidayTitles($filter = null$locale = null)
  322.     {
  323.         if (is_null($filter)) {
  324.             $filter = new Date_Holidays_Filter_Blacklist(array());
  325.         elseif (is_array($filter)) {
  326.             $filter = new Date_Holidays_Filter_Whitelist($filter);
  327.         }
  328.  
  329.         $titles =   array();
  330.  
  331.         foreach ($this->_internalNames as $internalName{
  332.             if ($filter->accept($internalName)) {
  333.                 $title $this->getHolidayTitle($internalName$locale);
  334.                 if (Date_Holidays::isError($title)) {
  335.                     return $title;
  336.                 }
  337.                 $titles[$internalName$title;
  338.             }
  339.         }
  340.  
  341.         return $titles;
  342.     }
  343.  
  344.     /**
  345.      * Returns localized title for a holiday
  346.      *
  347.      * @param string $internalName internal name for holiday
  348.      * @param string $locale       locale setting to be used by this method
  349.      *
  350.      * @access   public
  351.      * @return   string  title on success, otherwise a PEAR_Error object
  352.      * @throws   object PEAR_Error DATE_HOLIDAYS_INVALID_INTERNAL_NAME
  353.      * @throws   object PEAR_Error DATE_HOLIDAYS_TITLE_UNAVAILABLE
  354.      */
  355.     function getHolidayTitle($internalName$locale = null)
  356.     {
  357.         if (in_array($internalName$this->_internalNames)) {
  358.             $msg 'Invalid internal name: ' $internalName;
  359.                                              $msg);
  360.  
  361.         }
  362.  
  363.         if (is_null($locale)) {
  364.             $locale $this->_findBestLocale($this->_locale);
  365.         else {
  366.             $locale $this->_findBestLocale($locale);
  367.         }
  368.  
  369.         if (isset($this->_titles[$locale][$internalName])) {
  370.             if (Date_Holidays::staticGetProperty('DIE_ON_MISSING_LOCALE')) {
  371.                 $err DATE_HOLIDAYS_TITLE_UNAVAILABLE;
  372.                 $msg 'The internal name (' $internalName ') ' .
  373.                        'for the holiday was correct but no ' .
  374.                        'localized title could be found';
  375.                 return Date_Holidays::raiseError($err$msg);
  376.             }
  377.         }
  378.  
  379.         if (isset($this->_titles[$locale][$internalName])) {
  380.             return $this->_titles[$locale][$internalName];
  381.         else {
  382.             return $this->_titles['C'][$internalName];
  383.         }
  384.     }
  385.  
  386.  
  387.     /**
  388.      * Returns the localized properties of a holiday. If no properties have
  389.      * been stored an empty array will be returned.
  390.      *
  391.      * @param string $internalName internal name for holiday
  392.      * @param string $locale       locale setting that shall be used by this method
  393.      *
  394.      * @access   public
  395.      * @return   array   array of properties on success, otherwise
  396.      *                    a PEAR_Error object
  397.      * @throws   object PEAR_Error   DATE_HOLIDAYS_INVALID_INTERNAL_NAME
  398.      */
  399.     function getHolidayProperties($internalName$locale = null)
  400.     {
  401.         if (in_array($internalName$this->_internalNames)) {
  402.             $msg 'Invalid internal name: ' $internalName;
  403.                                              $msg);
  404.         }
  405.  
  406.         if (is_null($locale)) {
  407.             $locale =   $this->_findBestLocale($this->_locale);
  408.         else {
  409.             $locale =   $this->_findBestLocale($locale);
  410.         }
  411.  
  412.  
  413.         $properties = array();
  414.         if (isset($this->_holidayProperties[$internalName][$locale])) {
  415.             $properties $this->_holidayProperties[$internalName][$locale];
  416.         }
  417.         return $properties;
  418.     }
  419.  
  420.  
  421.     /**
  422.      * Returns all holidays that the driver knows.
  423.      *
  424.      * You can limit the holidays by passing a filter, then only those
  425.      * holidays accepted by the filter will be returned.
  426.      *
  427.      * Return format:
  428.      * <pre>
  429.      *   array(
  430.      *       'easter'        =>  object of type Date_Holidays_Holiday,
  431.      *       'eastermonday'  =>  object of type Date_Holidays_Holiday,
  432.      *       ...
  433.      *   )
  434.      * </pre>
  435.      *
  436.      * @param Date_Holidays_Filter $filter filter-object
  437.      *                                      (or an array !DEPRECATED!)
  438.      * @param string               $locale locale setting that shall be used
  439.      *                                       by this method
  440.      *
  441.      * @access   public
  442.      * @return   array   numeric array containing objects of
  443.      *                    Date_Holidays_Holiday on success, otherwise a
  444.      *                    PEAR_Error object
  445.      * @throws   object PEAR_Error   DATE_HOLIDAYS_INVALID_INTERNAL_NAME
  446.      * @see      getHoliday()
  447.      */
  448.     function getHolidays($filter = null$locale = null)
  449.     {
  450.         if (is_null($filter)) {
  451.             $filter = new Date_Holidays_Filter_Blacklist(array());
  452.         elseif (is_array($filter)) {
  453.             $filter = new Date_Holidays_Filter_Whitelist($filter);
  454.         }
  455.  
  456.         if (is_null($locale)) {
  457.             $locale $this->_locale;
  458.         }
  459.  
  460.         $holidays = array();
  461.  
  462.         foreach ($this->_internalNames as $internalName{
  463.             if ($filter->accept($internalName)) {
  464.                 // no need to check for valid internal-name, will be
  465.                 // done by #getHoliday()
  466.                 $holidays[$internalName$this->getHoliday($internalName,
  467.                                                              $locale);
  468.             }
  469.         }
  470.  
  471.         return $holidays;
  472.     }
  473.  
  474.     /**
  475.      * Returns the specified holiday
  476.      *
  477.      * Return format:
  478.      * <pre>
  479.      *   array(
  480.      *       'title' =>  'Easter Sunday'
  481.      *       'date'  =>  '2004-04-11'
  482.      *   )
  483.      * </pre>
  484.      *
  485.      * @param string $internalName internal name of the holiday
  486.      * @param string $locale       locale setting that shall be used
  487.      *                               by this method
  488.      *
  489.      * @access   public
  490.      * @return   object Date_Holidays_Holiday holiday's information on
  491.      *                                          success, otherwise a PEAR_Error
  492.      *                                          object
  493.      * @throws   object PEAR_Error       DATE_HOLIDAYS_INVALID_INTERNAL_NAME
  494.      * @uses     getHolidayTitle()
  495.      * @uses     getHolidayDate()
  496.      */
  497.     function getHoliday($internalName$locale = null)
  498.     {
  499.         if (in_array($internalName$this->_internalNames)) {
  500.                 'Invalid internal name: ' $internalName);
  501.         }
  502.         if (is_null($locale)) {
  503.             $locale $this->_locale;
  504.         }
  505.  
  506.         $title $this->getHolidayTitle($internalName$locale);
  507.         if (Date_Holidays::isError($title)) {
  508.             return $title;
  509.         }
  510.         $date $this->getHolidayDate($internalName);
  511.         if (Date_Holidays::isError($date)) {
  512.             return $date;
  513.         }
  514.         $properties $this->getHolidayProperties($internalName$locale);
  515.         if (Date_Holidays::isError($properties)) {
  516.             return $properties;
  517.         }
  518.  
  519.         $holiday = new Date_Holidays_Holiday($internalName,
  520.                                              $title,
  521.                                              $date,
  522.                                              $properties);
  523.         return $holiday;
  524.     }
  525.  
  526.     /**
  527.      * Determines whether a date represents a holiday or not
  528.      *
  529.      * @param mixed                $date   a timestamp, string or PEAR::Date object
  530.      * @param Date_Holidays_Filter $filter filter-object (or an array !DEPRECATED!)
  531.      *
  532.      * @access   public
  533.      * @return   boolean true if date represents a holiday, otherwise false
  534.      * @throws   object PEAR_Error   DATE_HOLIDAYS_INVALID_DATE_FORMAT
  535.      * @throws   object PEAR_Error   DATE_HOLIDAYS_INVALID_DATE
  536.      */
  537.     function isHoliday($date$filter = null)
  538.     {
  539.         if (is_a($date'Date')) {
  540.             $date $this->_convertDate($date);
  541.             if (Date_Holidays::isError($date)) {
  542.                 return $date;
  543.             }
  544.         }
  545.  
  546.         //rebuild internal array of holidays if required.
  547.         $compare_year $date->getYear();
  548.         $this_year $this->getYear();
  549.         if ($this_year !== $compare_year{
  550.             $this->setYear($compare_year);
  551.         }
  552.  
  553.         if (is_null($filter)) {
  554.             $filter = new Date_Holidays_Filter_Blacklist(array());
  555.         elseif (is_array($filter)) {
  556.             $filter = new Date_Holidays_Filter_Whitelist($filter);
  557.         }
  558.  
  559.         foreach (array_keys($this->_datesas $internalName{
  560.             if ($filter->accept($internalName)) {
  561.                 if (Date_Holidays_Driver::dateSloppyCompare($date,
  562.                                           $this->_dates[$internalName]!= 0{
  563.                     continue;
  564.                 }
  565.                 $this->setYear($this_year);
  566.                 return true;
  567.             }
  568.         }
  569.         $this->setYear($this_year);
  570.         return false;
  571.     }
  572.  
  573.     /**
  574.      * Returns a <code>Date_Holidays_Holiday</code> object, if any was found,
  575.      * matching the specified date.
  576.      *
  577.      * Normally the method will return the object of the first holiday matching
  578.      * the date. If you want the method to continue searching holidays for the
  579.      * specified date, set the 4th param to true.
  580.      *
  581.      * If multiple holidays match your date, the return value will be an array
  582.      * containing a number of <code>Date_Holidays_Holiday</code> items.
  583.      *
  584.      * @param mixed   $date     date (timestamp | string | PEAR::Date object)
  585.      * @param string  $locale   locale setting that shall be used by this method
  586.      * @param boolean $multiple if true, continue searching holidays for
  587.      *                            specified date
  588.      *
  589.      * @access   public
  590.      * @return   object  object of type Date_Holidays_Holiday on success
  591.      *                    (numeric array of those on multiple search),
  592.      *                    if no holiday was found, matching this date,
  593.      *                    null is returned
  594.      * @throws   object PEAR_Error   DATE_HOLIDAYS_INVALID_DATE_FORMAT
  595.      * @throws   object PEAR_Error   DATE_HOLIDAYS_INVALID_DATE
  596.      * @uses     getHoliday()
  597.      * @uses     getHolidayTitle()
  598.      * @see      getHoliday()
  599.      ***/
  600.     function getHolidayForDate($date$locale = null$multiple = false)
  601.     {
  602.         if (!is_a($date'Date')) {
  603.             $date $this->_convertDate($date);
  604.             if (Date_Holidays::isError($date)) {
  605.                 return $date;
  606.             }
  607.         }
  608.         $isodate mktime(0,
  609.                           0,
  610.                           0,
  611.                           $date->getMonth(),
  612.                           $date->getDay(),
  613.                           $date->getYear());
  614.         unset($date);
  615.         if (is_null($locale)) {
  616.             $locale $this->_locale;
  617.         }
  618.         if (array_key_exists($isodate$this->_holidays)) {
  619.             if (!$multiple{
  620.                 //get only the first feast for this day
  621.                 $internalName $this->_holidays[$isodate][0];
  622.                 $result       $this->getHoliday($internalName$locale);
  623.                 return Date_Holidays::isError($result? null : $result;
  624.             }
  625.             // array that collects data, if multiple searching is done
  626.             $data = array();
  627.             foreach ($this->_holidays[$isodateas $internalName{
  628.                 $result $this->getHoliday($internalName$locale);
  629.                 if (Date_Holidays::