module = Module::getInstanceByName('qlocrontaskmanager'); } public function getCronExpressionTranslation($expression) { $parts = preg_split('/\s+/', trim($expression)); if (count($parts) !== 5) { return $this->module->l('Invalid cron expression'); } list($minute, $hour, $day, $month, $weekday) = $parts; $hasFixedTime = $this->isNumeric($hour) && $this->isNumeric($minute); $dayMonthWildcard = ($day == '*' && $month == '*'); $monthWeekdayWildcard = ($month == '*' && $weekday == '*'); $everyMinuteWildcard = ($minute == '*' && $hour == '*'); if ($expression === '* * * * *') { return $this->module->l('Every minute'); } if (preg_match('/^\*\/(\d+)$/', $minute, $m) && $hour == '*' && $dayMonthWildcard && $weekday == '*') { return ((int) $m[1] === 1) ? $this->module->l('Every minute') : vsprintf($this->module->l('Every %d minutes'), array((int) $m[1])); } if ($minute == '0' && $hour == '*' && $dayMonthWildcard && $weekday == '*') { return $this->module->l('Every hour'); } if ($minute == '0' && preg_match('/^\*\/(\d+)$/', $hour, $m) && $dayMonthWildcard && $weekday == '*') { return ((int) $m[1] === 1) ? $this->module->l('Every hour') : vsprintf($this->module->l('Every %d hours'), array((int) $m[1])); } if ($hasFixedTime && $dayMonthWildcard && $weekday == '*') { return vsprintf($this->module->l('Every day at %s'), array($this->hourLabel($hour, $minute))); } if ($hasFixedTime && $day == '*' && $weekday == '*' && preg_match('/^\*\/(\d+)$/', $month, $mm)) { return ((int) $mm[1] === 1) ? vsprintf($this->module->l('Every day every month at %s'), array($this->hourLabel($hour, $minute))) : vsprintf( $this->module->l('Every day every %1$d months at %2$s'), array((int) $mm[1], $this->hourLabel($hour, $minute)) ); } if ($hasFixedTime && $dayMonthWildcard && $weekday == '1-5') { return vsprintf($this->module->l('Every weekday at %s'), array($this->hourLabel($hour, $minute))); } if ($hasFixedTime && $dayMonthWildcard && $weekday == '0,6') { return vsprintf($this->module->l('Every weekend at %s'), array($this->hourLabel($hour, $minute))); } if ($hasFixedTime && $dayMonthWildcard && $this->isNumeric($weekday)) { return vsprintf( $this->module->l('Every %1$s at %2$s'), array($this->weekdayName($weekday), $this->hourLabel($hour, $minute)) ); } if (strpos($weekday, ',') !== false && $hasFixedTime && $dayMonthWildcard) { return vsprintf( $this->module->l('Every %1$s at %2$s'), array($this->joinNames($weekday, 'weekdayName'), $this->hourLabel($hour, $minute)) ); } if ($this->isNumeric($day) && $hasFixedTime && $monthWeekdayWildcard) { return vsprintf( $this->module->l('On the %1$s of every month at %2$s'), array($this->ordinal($day), $this->hourLabel($hour, $minute)) ); } if (preg_match('/^(\d+)-(\d+)$/', $day, $dm) && $hasFixedTime && $monthWeekdayWildcard) { return vsprintf( $this->module->l('Every day from the %1$s to the %2$s of each month at %3$s'), array($this->ordinal($dm[1]), $this->ordinal($dm[2]), $this->hourLabel($hour, $minute)) ); } if (strpos($day, ',') !== false && $hasFixedTime && $monthWeekdayWildcard) { return vsprintf( $this->module->l('On the %1$s of each month at %2$s'), array($this->joinOrdinals($day), $this->hourLabel($hour, $minute)) ); } if ($this->isNumeric($day) && $this->isNumeric($month) && $hasFixedTime && $weekday == '*') { return vsprintf( $this->module->l('Every %1$s %2$s at %3$s'), array($this->monthName($month), $this->ordinal($day), $this->hourLabel($hour, $minute)) ); } if ($everyMinuteWildcard && $dayMonthWildcard && $this->isNumeric($weekday)) { return vsprintf($this->module->l('Every minute on %s'), array($this->weekdayName($weekday))); } if ($everyMinuteWildcard && $dayMonthWildcard && $weekday == '1-5') { return $this->module->l('Every minute on weekdays'); } if ($everyMinuteWildcard && $dayMonthWildcard && $weekday == '0,6') { return $this->module->l('Every minute on weekends'); } if ($hasFixedTime) { $when = vsprintf($this->module->l('At %s'), array($this->hourLabel($hour, $minute))); } else { $minuteFreq = null; if ($minute === '*') { $minuteFreq = $this->module->l('Every minute'); } elseif (preg_match('/^\*\/(\d+)$/', $minute, $m)) { $minuteFreq = ((int) $m[1] === 1) ? $this->module->l('Every minute') : vsprintf($this->module->l('Every %d minutes'), array((int) $m[1])); } if (preg_match('/^(\d+)-(\d+)\/(\d+)$/', $hour, $hs) && $this->isNumeric($minute)) { $when = ((int) $hs[3] === 1) ? vsprintf( $this->module->l('Every hour between %1$s and %2$s'), array($this->hourLabel($hs[1], $minute), $this->hourLabel($hs[2], $minute)) ) : vsprintf( $this->module->l('Every %1$d hours between %2$s and %3$s'), array((int) $hs[3], $this->hourLabel($hs[1], $minute), $this->hourLabel($hs[2], $minute)) ); } elseif ($minuteFreq !== null) { if ($hour === '*') { $when = $minuteFreq; } elseif ($this->isNumeric($hour)) { $when = vsprintf($this->module->l('%1$s, during hour %2$s'), array($minuteFreq, $hour)); } elseif (preg_match('/^(\d+)-(\d+)$/', $hour, $hm)) { $when = vsprintf( $this->module->l('%1$s between %2$s and %3$s'), array($minuteFreq, $this->hourLabel($hm[1], 0), $this->hourLabel($hm[2], 59)) ); } else { $when = vsprintf($this->module->l('%1$s, during hour %2$s'), array($minuteFreq, $hour)); } } elseif ($this->isNumeric($minute) && $hour === '*') { $when = vsprintf($this->module->l('Every hour, at minute %s'), array($minute)); } elseif ($this->isNumeric($minute) && preg_match('/^(\d+)-(\d+)$/', $hour, $hm)) { $when = vsprintf( $this->module->l('At minute %1$s, between %2$s and %3$s'), array($minute, $this->hourLabel($hm[1], $minute), $this->hourLabel($hm[2], $minute)) ); } else { $when = vsprintf($this->module->l('At minute %1$s, hour %2$s'), array($minute, $hour)); } } $conditions = array(); if ($day !== '*') { if (preg_match('/^(\d+)-(\d+)$/', $day, $dm)) { $conditions[] = vsprintf( $this->module->l('from the %1$s to the %2$s of the month'), array($this->ordinal($dm[1]), $this->ordinal($dm[2])) ); } elseif (strpos($day, ',') !== false) { $conditions[] = vsprintf($this->module->l('on the %s of the month'), array($this->joinOrdinals($day))); } elseif ($this->isNumeric($day)) { $conditions[] = vsprintf($this->module->l('on the %s of the month'), array($this->ordinal($day))); } else { $conditions[] = vsprintf($this->module->l('on day %s of the month'), array($day)); } } if ($month !== '*') { if (preg_match('/^\*\/(\d+)$/', $month, $mf)) { $conditions[] = ((int) $mf[1] === 1) ? $this->module->l('every month') : vsprintf($this->module->l('every %d months'), array((int) $mf[1])); } else { if (preg_match('/^(\d+)-(\d+)$/', $month, $mm)) { $monthDesc = vsprintf( $this->module->l('%1$s through %2$s'), array($this->monthName($mm[1]), $this->monthName($mm[2])) ); } elseif (strpos($month, ',') !== false) { $monthDesc = $this->joinNames($month, 'monthName'); } else { $monthDesc = $this->monthName($month); } $conditions[] = vsprintf($this->module->l('in %s'), array($monthDesc)); } } if ($weekday !== '*') { if ($weekday === '1-5') { $weekdayDesc = $this->module->l('weekdays'); } elseif ($weekday === '0,6' || $weekday === '6,0') { $weekdayDesc = $this->module->l('weekends'); } elseif (preg_match('/^(\d+)-(\d+)$/', $weekday, $wm)) { $weekdayDesc = vsprintf( $this->module->l('%1$s through %2$s'), array($this->weekdayName($wm[1]), $this->weekdayName($wm[2])) ); } elseif (strpos($weekday, ',') !== false) { $weekdayDesc = $this->joinNames($weekday, 'weekdayName'); } else { $weekdayDesc = $this->weekdayName($weekday); } $conditions[] = vsprintf($this->module->l('on %s'), array($weekdayDesc)); } if (empty($conditions)) { return $when; } return $when . ' ' . implode(', ', $conditions); } public function isNumeric($value) { return preg_match('/^\d+$/', $value) === 1; } public function weekdayName($weekday) { $weekdays = array( 0 => $this->module->l('Sunday'), 1 => $this->module->l('Monday'), 2 => $this->module->l('Tuesday'), 3 => $this->module->l('Wednesday'), 4 => $this->module->l('Thursday'), 5 => $this->module->l('Friday'), 6 => $this->module->l('Saturday'), 7 => $this->module->l('Sunday'), ); return ($this->isNumeric($weekday) && isset($weekdays[(int) $weekday])) ? $weekdays[(int) $weekday] : $weekday; } public function monthName($month) { $months = array( 1 => $this->module->l('January'), 2 => $this->module->l('February'), 3 => $this->module->l('March'), 4 => $this->module->l('April'), 5 => $this->module->l('May'), 6 => $this->module->l('June'), 7 => $this->module->l('July'), 8 => $this->module->l('August'), 9 => $this->module->l('September'), 10 => $this->module->l('October'), 11 => $this->module->l('November'), 12 => $this->module->l('December'), ); return ($this->isNumeric($month) && isset($months[(int) $month])) ? $months[(int) $month] : $month; } public function hourLabel($hour, $minute = null) { $h = (int) $hour; $suffix = $h >= 12 ? $this->module->l('PM') : $this->module->l('AM'); $h12 = $h % 12; if ($h12 === 0) { $h12 = 12; } return $minute === null ? sprintf('%d %s', $h12, $suffix) : sprintf('%d:%02d %s', $h12, (int) $minute, $suffix); } public function joinNames($csv, $nameMethod) { $names = array(); foreach (explode(',', $csv) as $token) { $names[] = $this->$nameMethod($token); } if (count($names) === 1) { return $names[0]; } $last = array_pop($names); return implode(', ', $names) . ' ' . $this->module->l('and') . ' ' . $last; } public function ordinal($number) { $number = (int) $number; if ($number % 100 >= 11 && $number % 100 <= 13) { $suffix = 'th'; } else { switch ($number % 10) { case 1: $suffix = 'st'; break; case 2: $suffix = 'nd'; break; case 3: $suffix = 'rd'; break; default: $suffix = 'th'; } } return $number . $suffix; } public function joinOrdinals($csv) { $ordinals = array(); foreach (explode(',', $csv) as $token) { $ordinals[] = $this->isNumeric($token) ? $this->ordinal($token) : $token; } if (count($ordinals) === 1) { return $ordinals[0]; } $last = array_pop($ordinals); return implode(', ', $ordinals) . ' ' . $this->module->l('and') . ' ' . $last; } }