2121 */
2222class Expression
2323{
24+ /** @var Expression */
25+ protected static $ instance ;
26+
27+ /** @var SegmentChecker */
28+ protected $ checker ;
29+
2430 protected static $ expressions = [
2531 '@yearly ' => '0 0 1 1 * ' ,
2632 '@annually ' => '0 0 1 1 * ' ,
@@ -57,6 +63,24 @@ class Expression
5763 'dec ' => 12 ,
5864 ];
5965
66+ public function __construct (SegmentChecker $ checker = null )
67+ {
68+ $ this ->checker = $ checker ?: new SegmentChecker ;
69+
70+ if (null === static ::$ instance ) {
71+ static ::$ instance = $ this ;
72+ }
73+ }
74+
75+ public static function instance ()
76+ {
77+ if (null === static ::$ instance ) {
78+ static ::$ instance = new static ;
79+ }
80+
81+ return static ::$ instance ;
82+ }
83+
6084 /**
6185 * Parse cron expression to decide if it can be run on given time (or default now).
6286 *
@@ -67,13 +91,20 @@ class Expression
6791 */
6892 public static function isDue ($ expr , $ time = null )
6993 {
70- static $ instance ;
71-
72- if (!$ instance ) {
73- $ instance = new static ;
74- }
94+ return static ::instance ()->isCronDue ($ expr , $ time );
95+ }
7596
76- return $ instance ->isCronDue ($ expr , $ time );
97+ /**
98+ * Filter only the jobs that are due.
99+ *
100+ * @param array $jobs Jobs with cron exprs. [job1 => cron-expr1, job2 => cron-expr2, ...]
101+ * @param mixed $time The timestamp to validate the cron expr against. Defaults to now.
102+ *
103+ * @return array Due job names: [job1name, ...];
104+ */
105+ public static function getDues (array $ jobs , $ time = null )
106+ {
107+ return static ::instance ()->filter ($ jobs , $ time );
77108 }
78109
79110 /**
@@ -82,28 +113,55 @@ public static function isDue($expr, $time = null)
82113 * Parse cron expression to decide if it can be run on given time (or default now).
83114 *
84115 * @param string $expr The cron expression.
85- * @param int $time The timestamp to validate the cron expr against. Defaults to now.
116+ * @param mixed $time The timestamp to validate the cron expr against. Defaults to now.
86117 *
87118 * @return bool
88119 */
89120 public function isCronDue ($ expr , $ time = null )
90121 {
91- list ($ expr , $ time ) = $ this ->process ($ expr , $ time );
122+ list ($ expr , $ times ) = $ this ->process ($ expr , $ time );
92123
93- $ checker = new SegmentChecker ;
94124 foreach ($ expr as $ pos => $ segment ) {
95125 if ($ segment === '* ' || $ segment === '? ' ) {
96126 continue ;
97127 }
98128
99- if (!$ checker ->checkDue ($ segment , $ pos , $ time )) {
129+ if (!$ this -> checker ->checkDue ($ segment , $ pos , $ times )) {
100130 return false ;
101131 }
102132 }
103133
104134 return true ;
105135 }
106136
137+ /**
138+ * Filter only the jobs that are due.
139+ *
140+ * @param array $jobs Jobs with cron exprs. [job1 => cron-expr1, job2 => cron-expr2, ...]
141+ * @param mixed $time The timestamp to validate the cron expr against. Defaults to now.
142+ *
143+ * @return array Due job names: [job1name, ...];
144+ */
145+ public function filter (array $ jobs , $ time = null )
146+ {
147+ $ dues = $ cache = [];
148+ $ time = $ this ->normalizeTime ($ time );
149+
150+ foreach ($ jobs as $ name => $ expr ) {
151+ $ expr = $ this ->normalizeExpr ($ expr );
152+
153+ if (!isset ($ cache [$ expr ])) {
154+ $ cache [$ expr ] = $ this ->isCronDue ($ expr , $ time );
155+ }
156+
157+ if ($ cache [$ expr ]) {
158+ $ dues [] = $ name ;
159+ }
160+ }
161+
162+ return $ dues ;
163+ }
164+
107165 /**
108166 * Process and prepare input.
109167 *
@@ -114,10 +172,7 @@ public function isCronDue($expr, $time = null)
114172 */
115173 protected function process ($ expr , $ time )
116174 {
117- if (isset (static ::$ expressions [$ expr ])) {
118- $ expr = static ::$ expressions [$ expr ];
119- }
120-
175+ $ expr = $ this ->normalizeExpr ($ expr );
121176 $ expr = \str_ireplace (\array_keys (static ::$ literals ), \array_values (static ::$ literals ), $ expr );
122177 $ expr = \explode (' ' , $ expr );
123178
@@ -127,11 +182,10 @@ protected function process($expr, $time)
127182 );
128183 }
129184
130- $ time = static ::normalizeTime ($ time );
185+ $ time = static ::normalizeTime ($ time );
186+ $ times = \array_map ('intval ' , \explode (' ' , \date ('i G j n w Y t d m N ' , $ time )));
131187
132- $ time = \array_map ('intval ' , \explode (' ' , \date ('i G j n w Y t d m N ' , $ time )));
133-
134- return [$ expr , $ time ];
188+ return [$ expr , $ times ];
135189 }
136190
137191 protected function normalizeTime ($ time )
@@ -146,4 +200,13 @@ protected function normalizeTime($time)
146200
147201 return $ time ;
148202 }
203+
204+ protected function normalizeExpr ($ expr )
205+ {
206+ if (isset (static ::$ expressions [$ expr ])) {
207+ $ expr = static ::$ expressions [$ expr ];
208+ }
209+
210+ return $ expr ;
211+ }
149212}
0 commit comments