Example #1
0
 /**
  * Parse parameters and set internal properties
  *
  * @since 1.9
  *
  * @param $params
  */
 protected function parse($parameters)
 {
     // Initialize variables.
     $all_date_strings = array();
     $unused_params = array();
     $property_name = $start_date = $end_date = $unit = $period = $week_num = null;
     $included_dates = array();
     $excluded_dates = array();
     $excluded_dates_jd = array();
     // Parse parameters and assign values
     foreach ($parameters as $name => $values) {
         foreach ($values as $value) {
             switch ($name) {
                 case 'property':
                     $this->property = $value;
                     break;
                 case 'start':
                     $start_date = DataValueFactory::getInstance()->newTypeIDValue('_dat', $value);
                     break;
                 case 'end':
                     $end_date = DataValueFactory::getInstance()->newTypeIDValue('_dat', $value);
                     break;
                 case 'limit':
                     // Override default limit with query specific limit
                     $this->settings->set('smwgDefaultNumRecurringEvents', (int) $value);
                     break;
                 case 'unit':
                     $unit = $value;
                     break;
                 case 'period':
                     $period = (int) $value;
                     break;
                 case 'week number':
                     $week_num = (int) $value;
                     break;
                 case 'include':
                     // This is for compatibility only otherwise we break
                     // to much at once. Instead of writing include=...;...
                     // it should be include=...;...|+sep=; because the
                     // ParameterParser class is conditioned to split those
                     // parameter accordingly
                     if (strpos($value, ';')) {
                         $included_dates = explode(';', $value);
                     } else {
                         $included_dates[] = $value;
                     }
                     break;
                 case 'exclude':
                     // Some as above
                     if (strpos($value, ';')) {
                         $excluded_dates = explode(';', $value);
                     } else {
                         $excluded_dates[] = $value;
                     }
                     break;
                 default:
                     $this->parameters[$name][] = $value;
             }
         }
     }
     if ($start_date === null) {
         $this->errors[] = new Message('smw-events-start-date-missing');
         return;
     } else {
         if (!$start_date->getDataItem() instanceof SMWDITime) {
             $this->setError($start_date->getErrors());
             return;
         }
     }
     // Check property
     if (is_null($this->property)) {
         $this->errors[] = new Message('smw-events-property-missing');
         return;
     }
     // Exclude dates
     foreach ($excluded_dates as $date_str) {
         $excluded_dates_jd[] = $this->getJulianDay(DataValueFactory::getInstance()->newTypeIDValue('_dat', $date_str));
     }
     // If the period is null, or outside of normal bounds, set it to 1.
     if (is_null($period) || $period < 1 || $period > 500) {
         $period = 1;
     }
     // Handle 'week number', but only if it's of unit 'month'.
     if ($unit == 'month' && !is_null($week_num)) {
         $unit = 'dayofweekinmonth';
         if ($week_num < -4 || $week_num > 5 || $week_num == 0) {
             $week_num = null;
         }
     }
     if ($unit == 'dayofweekinmonth' && is_null($week_num)) {
         $week_num = ceil($start_date->getDay() / 7);
     }
     // Get the Julian day value for both the start and end date.
     $end_date_jd = $this->getJulianDay($end_date);
     $cur_date = $start_date;
     $cur_date_jd = $this->getJulianDay($cur_date);
     $i = 0;
     do {
         $i++;
         $exclude_date = in_array($cur_date_jd, $excluded_dates_jd);
         if (!$exclude_date) {
             $all_date_strings[] = $cur_date->getLongWikiText();
         }
         // Now get the next date.
         // Handling is different depending on whether it's
         // month/year or week/day since the latter is a set
         // number of days while the former isn't.
         if ($unit === 'year' || $unit == 'month') {
             $cur_year = $cur_date->getYear();
             $cur_month = $cur_date->getMonth();
             $cur_day = $start_date->getDay();
             $cur_time = $cur_date->getTimeString();
             if ($unit == 'year') {
                 $cur_year += $period;
                 $display_month = $cur_month;
             } else {
                 // $unit === 'month'
                 $cur_month += $period;
                 $cur_year += (int) (($cur_month - 1) / 12);
                 $cur_month %= 12;
                 $display_month = $cur_month == 0 ? 12 : $cur_month;
             }
             // If the date is February 29, and this isn't
             // a leap year, change it to February 28.
             if ($cur_month == 2 && $cur_day == 29) {
                 if (!date('L', strtotime("{$cur_year}-1-1"))) {
                     $cur_day = 28;
                 }
             }
             $date_str = "{$cur_year}-{$display_month}-{$cur_day} {$cur_time}";
             $cur_date = DataValueFactory::getInstance()->newTypeIDValue('_dat', $date_str);
             $all_date_strings = array_merge($all_date_strings, $included_dates);
             $cur_date_jd = $cur_date->getDataItem()->getJD();
         } elseif ($unit == 'dayofweekinmonth') {
             // e.g., "3rd Monday of every month"
             $prev_month = $cur_date->getMonth();
             $prev_year = $cur_date->getYear();
             $new_month = ($prev_month + $period) % 12;
             if ($new_month == 0) {
                 $new_month = 12;
             }
             $new_year = $prev_year + floor(($prev_month + $period - 1) / 12);
             $cur_date_jd += 28 * $period - 7;
             // We're sometime before the actual date now -
             // keep incrementing by a week, until we get there.
             do {
                 $cur_date_jd += 7;
                 $cur_date = $this->getJulianDayTimeValue($cur_date_jd);
                 $right_month = $cur_date->getMonth() == $new_month;
                 if ($week_num < 0) {
                     $next_week_jd = $cur_date_jd;
                     do {
                         $next_week_jd += 7;
                         $next_week_date = $this->getJulianDayTimeValue($next_week_jd);
                         $right_week = $next_week_date->getMonth() != $new_month || $next_week_date->getYear() != $new_year;
                     } while (!$right_week);
                     $cur_date_jd = $next_week_jd + 7 * $week_num;
                     $cur_date = $this->getJulianDayTimeValue($cur_date_jd);
                 } else {
                     $cur_week_num = ceil($cur_date->getDay() / 7);
                     $right_week = $cur_week_num == $week_num;
                     if ($week_num == 5 && $cur_date->getMonth() % 12 == ($new_month + 1) % 12) {
                         $cur_date_jd -= 7;
                         $cur_date = $this->getJulianDayTimeValue($cur_date_jd);
                         $right_month = $right_week = true;
                     }
                 }
             } while (!$right_month || !$right_week);
         } else {
             // $unit == 'day' or 'week'
             // Assume 'day' if it's none of the above.
             $cur_date_jd += $unit === 'week' ? 7 * $period : $period;
             $cur_date = $this->getJulianDayTimeValue($cur_date_jd);
         }
         // should we stop?
         if (is_null($end_date)) {
             $reached_end_date = $i > $this->settings->get('smwgDefaultNumRecurringEvents');
         } else {
             $reached_end_date = $cur_date_jd > $end_date_jd || $i > $this->settings->get('smwgMaxNumRecurringEvents');
         }
     } while (!$reached_end_date);
     // Handle the 'include' dates as well.
     $all_date_strings = array_filter(array_merge($all_date_strings, $included_dates));
     // Set dates
     $this->dates = $all_date_strings;
 }