Overview

Packages

  • Scheduler

Classes

  • Horde_Scheduler
  • Horde_Scheduler_Cron
  • Horde_Scheduler_Cron_Date
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * @author  Ryan Flynn <ryan@ryanflynn.com>
  4:  * @author  Chuck Hagenbuch <chuck@horde.org>
  5:  * @package Scheduler
  6:  */
  7: class Horde_Scheduler_Cron_Date
  8: {
  9:     public $legalDays = array('MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN');
 10: 
 11:     public $sec;
 12:     public $min;
 13:     public $hour;
 14:     public $day;
 15:     public $month;
 16: 
 17:     public function __construct($raw)
 18:     {
 19:         $this->parse(Horde_String::upper($raw));
 20:     }
 21: 
 22:     public function nowMatches()
 23:     {
 24:         return $this->scheduledAt(time());
 25:     }
 26: 
 27:     public function scheduledAt($ts = null)
 28:     {
 29:         if ($ts === null) {
 30:             $ts = time();
 31:         }
 32:         return ($this->monthMatches($ts) &&
 33:                 $this->monthMatches($ts) &&
 34:                 $this->dayMatches($ts) &&
 35:                 $this->hourMatches($ts) &&
 36:                 $this->minMatches($ts) &&
 37:                 $this->secMatches($ts));
 38:     }
 39: 
 40:     public function monthMatches($ts)
 41:     {
 42:         if ($this->month == '*') {
 43:             return true;
 44:         }
 45: 
 46:         $currentmonth = '-' . date('n', $ts) . '-';
 47: 
 48:         return (bool)strpos($this->month, $currentmonth);
 49:     }
 50: 
 51:     public function dayMatches($ts)
 52:     {
 53:         if (!empty($this->day['value']) && $this->day['value'] == '*') {
 54:             return true;
 55:         }
 56: 
 57:         $currentdaynum = '-' . date('j', $ts) . '-';
 58:         $currentdaytxt = Horde_String::upper(date('D'));
 59: 
 60:         foreach ($this->day as $day) {
 61:             if (@strpos($day['not'], $currentdaytxt) === false) {
 62:                 $v1 = (@strpos($day['value'], $currentdaynum) !== false);
 63:                 $v2 = (@strpos($day['and'], $currentdaytxt) !== false);
 64: 
 65:                 if (!empty($day['and']) && ($v1 && $v2)) {
 66:                     return true;
 67:                 } elseif (empty($day['and']) && $v1) {
 68:                     return true;
 69:                 }
 70:             }
 71:         }
 72: 
 73:         return false;
 74:     }
 75: 
 76:     public function hourMatches($ts)
 77:     {
 78:         if ($this->hour == '*') {
 79:             return true;
 80:         }
 81: 
 82:         $currenthour = '-' . date('G', $ts) . '-';
 83: 
 84:         return (strpos($this->hour, $currenthour) !== false);
 85:     }
 86: 
 87:     public function minMatches($ts)
 88:     {
 89:         if ($this->min == '*') {
 90:             return true;
 91:         }
 92: 
 93:         $currentmin = '-' . intval(date('i', $ts)) . '-';
 94: 
 95:         return (strpos($this->min, $currentmin) !== false);
 96:     }
 97: 
 98:     public function secMatches($ts)
 99:     {
100:         if ($this->sec == '*') {
101:             return true;
102:         }
103: 
104:         $currentsec = '-' . intval(date('s', $ts)) . '-';
105: 
106:         return (strpos($this->sec, $currentsec) !== false);
107:     }
108: 
109:     public function parse($str)
110:     {
111:         $s = array();
112: 
113:         list($s['sec'], $s['min'], $s['hour'], $s['day'], $s['month']) = preg_split('|[\n\t ]+|', $str);
114: 
115:         foreach ($s as $k => $v) {
116:             if (strpos($v, '*') !== false) {
117:                 $s[$k] = array('*');
118:             } elseif (!$this->generallyDecentSyntax($v)) {
119:                 die("Illegal syntax in '$v'\n");
120:             } else {
121:                 $s[$k] = explode(',', $s[$k]);
122:             }
123:         }
124: 
125:         if ($s['sec'][0] == '*') {
126:             $this->sec = '*';
127:         } else {
128:             for ($i = 0; $i < sizeof($s['sec']); $i++) {
129:                 if ($this->isRange($s['sec'][$i])) {
130:                     $s['sec'][$i] = $this->expandRange($this->rangeVals($s['sec'][$i]));
131:                 }
132:             }
133:             $this->sec = '-' . join('-', $s['sec']) . '-';
134:         }
135: 
136:         if ($s['min'][0] == '*') {
137:             $this->min = '*';
138:         } else {
139:             for ($i = 0; $i < sizeof($s['min']); $i++) {
140:                 if ($this->isRange($s['min'][$i])) {
141:                     $s['min'][$i] = $this->expandRange($this->rangeVals($s['min'][$i]));
142:                 }
143:             }
144:             $this->min = '-' . join('-', $s['min']) . '-';
145:         }
146: 
147:         if ($s['hour'][0] == '*') {
148:             $this->hour = '*';
149:         } else {
150:             for ($i = 0; $i < sizeof($s['hour']); $i++) {
151:                 if ($this->isRange($s['hour'][$i])) {
152:                     $s['hour'][$i] = $this->expandRange($this->rangeVals($s['hour'][$i]));
153:                 }
154:             }
155:             $this->hour = '-' . join('-', $s['hour']) . '-';
156:         }
157: 
158:         if ($s['day'][0] == '*') {
159:             $this->day = '*';
160:         } else {
161:             for ($i = 0; $i < sizeof($s['day']); $i++) {
162:                 $tmp = array();
163:                 if (($char = $this->isCond($s['day'][$i])) !== false) {
164:                     if ($char == '&') {
165:                         list($tmp['value'], $tmp['and']) = explode($char, $s['day'][$i]);
166:                         if ($this->isRange($tmp['and'])) {
167:                             $tmp['and'] = $this->expandRange($this->rangeVals($tmp['and']));
168:                         }
169:                     } else {
170:                         list($tmp['value'], $tmp['not']) = explode($char, $s['day'][$i]);
171:                         if ($this->isRange($tmp['not'])) {
172:                             $tmp['not'] = $this->expandRange($this->rangeVals($tmp['not']));
173:                         }
174:                     }
175:                 } else {
176:                     $tmp = array('value' => $s['day'][$i]);
177:                 }
178: 
179:                 $s['day'][$i] = $tmp;
180: 
181:                 if ($this->isRange($s['day'][$i]['value'])) {
182:                     $s['day'][$i]['value'] = $this->expandRange($this->rangeVals($s['day'][$i]['value']));
183:                 }
184:             }
185: 
186:             $this->day = $s['day'];
187:         }
188: 
189:         if ($s['month'][0] == '*') {
190:             $this->month = '*';
191:         } else {
192:             for ($i = 0; $i < sizeof($s['month']); $i++) {
193:                 if ($this->isRange($s['month'][$i])) {
194:                     $s['month'][$i] = $this->expandRange($this->rangeVals($s['month'][$i]));
195:                 }
196:             }
197:             $this->month = '-' . join('-', $s['month']) . '-';
198:         }
199:     }
200: 
201:     public function isCond($s)
202:     {
203:         if (strpos($s, '&') !== false) {
204:             return '&';
205:         } elseif (strpos($s, '!') !== false) {
206:             return '!';
207:         } else {
208:             return false;
209:         }
210:     }
211: 
212:     public function isRange($s)
213:     {
214:         return preg_match('/^\w+\-\w+/', $s);
215:     }
216: 
217:     public function isCondRange($s)
218:     {
219:         return ($this->isCond($s) && $this->isRange($s));
220:     }
221: 
222:     public function isCondVal($s)
223:     {
224:         return ($this->isCond($s) && !$this->isRange($s));
225:     }
226: 
227:     public function rangeVals($s)
228:     {
229:         return explode('-', $s);
230:     }
231: 
232:     public function expandRange($l, $h = '')
233:     {
234:         // Expand range from 1-5 -> '-1-2-3-4-5-'.
235:         if (is_array($l)) {
236:             $h = $l[1];
237:             $l = $l[0];
238:         }
239: 
240:         if ($this->isDigit($l)) {
241:             if (!$this->isDigit($h)) {
242:                 die("Invalid value '$h' in range '$l-$h'");
243:             }
244: 
245:             // Currently there is no possible reason to need to do a
246:             // range beyond 0-59 for anything.
247:             if ($l < 0) {
248:                 $l = 0;
249:             } elseif ($l > 59) {
250:                 $l = 59;
251:             }
252: 
253:             if ($h < 0) {
254:                 $h = 0;
255:             } elseif ($h > 59) {
256:                 $h = 59;
257:             }
258: 
259:             if ($l > $h) {
260:                 $tmp = $l;
261:                 $l = $h;
262:                 $h = $tmp;
263:                 unset($tmp);
264:             }
265: 
266:             // For some reason range() doesn't work w/o the explicit
267:             // intval() calls.
268:             return '-' . join('-', range(intval($l), intval($h))) . '-';
269:         } else {
270:             // Invalid.
271:             die("Invalid value '$l' in range '$l-$h'");
272:         }
273:     }
274: 
275:     public function dayValue($s)
276:     {
277:         for ($i = 0; $i < count($this->legalDays); $i++) {
278:             if ($this->legalDays[$i] == $s) {
279:                 return $i;
280:             }
281:         }
282: 
283:         return -1;
284:     }
285: 
286:     public function isDigit($s)
287:     {
288:         return preg_match('/^\d+$/', $s);
289:     }
290: 
291:     public function isAlpha($s)
292:     {
293:         return $this->isLegalDay($s);
294:     }
295: 
296:     public function isLegalDay($s)
297:     {
298:         return in_array($s, $this->legalDays);
299:     }
300: 
301:     public function generallyDecentSyntax($s)
302:     {
303:         return ($s == '*' ||
304:                 preg_match('/^\d+(-\d+)?([!&][A-Z\*]+(-[A-Z\*]+)?)?(,\d+(-\d+)?([!&][A-Z\*]+(-[A-Z\*]+)?)?)*$/', $s));
305:     }
306: 
307: }
308: 
API documentation generated by ApiGen