Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Console\Scheduling;
4
 
5
use Closure;
6
use DateTimeInterface;
7
use Illuminate\Bus\UniqueLock;
8
use Illuminate\Console\Application;
9
use Illuminate\Container\Container;
10
use Illuminate\Contracts\Bus\Dispatcher;
11
use Illuminate\Contracts\Cache\Repository as Cache;
12
use Illuminate\Contracts\Container\BindingResolutionException;
13
use Illuminate\Contracts\Queue\ShouldBeUnique;
14
use Illuminate\Contracts\Queue\ShouldQueue;
15
use Illuminate\Queue\CallQueuedClosure;
16
use Illuminate\Support\ProcessUtils;
17
use Illuminate\Support\Traits\Macroable;
18
use RuntimeException;
19
 
20
class Schedule
21
{
22
    use Macroable;
23
 
24
    const SUNDAY = 0;
25
 
26
    const MONDAY = 1;
27
 
28
    const TUESDAY = 2;
29
 
30
    const WEDNESDAY = 3;
31
 
32
    const THURSDAY = 4;
33
 
34
    const FRIDAY = 5;
35
 
36
    const SATURDAY = 6;
37
 
38
    /**
39
     * All of the events on the schedule.
40
     *
41
     * @var \Illuminate\Console\Scheduling\Event[]
42
     */
43
    protected $events = [];
44
 
45
    /**
46
     * The event mutex implementation.
47
     *
48
     * @var \Illuminate\Console\Scheduling\EventMutex
49
     */
50
    protected $eventMutex;
51
 
52
    /**
53
     * The scheduling mutex implementation.
54
     *
55
     * @var \Illuminate\Console\Scheduling\SchedulingMutex
56
     */
57
    protected $schedulingMutex;
58
 
59
    /**
60
     * The timezone the date should be evaluated on.
61
     *
62
     * @var \DateTimeZone|string
63
     */
64
    protected $timezone;
65
 
66
    /**
67
     * The job dispatcher implementation.
68
     *
69
     * @var \Illuminate\Contracts\Bus\Dispatcher
70
     */
71
    protected $dispatcher;
72
 
73
    /**
74
     * Create a new schedule instance.
75
     *
76
     * @param  \DateTimeZone|string|null  $timezone
77
     * @return void
78
     *
79
     * @throws \RuntimeException
80
     */
81
    public function __construct($timezone = null)
82
    {
83
        $this->timezone = $timezone;
84
 
85
        if (! class_exists(Container::class)) {
86
            throw new RuntimeException(
87
                'A container implementation is required to use the scheduler. Please install the illuminate/container package.'
88
            );
89
        }
90
 
91
        $container = Container::getInstance();
92
 
93
        $this->eventMutex = $container->bound(EventMutex::class)
94
                                ? $container->make(EventMutex::class)
95
                                : $container->make(CacheEventMutex::class);
96
 
97
        $this->schedulingMutex = $container->bound(SchedulingMutex::class)
98
                                ? $container->make(SchedulingMutex::class)
99
                                : $container->make(CacheSchedulingMutex::class);
100
    }
101
 
102
    /**
103
     * Add a new callback event to the schedule.
104
     *
105
     * @param  string|callable  $callback
106
     * @param  array  $parameters
107
     * @return \Illuminate\Console\Scheduling\CallbackEvent
108
     */
109
    public function call($callback, array $parameters = [])
110
    {
111
        $this->events[] = $event = new CallbackEvent(
112
            $this->eventMutex, $callback, $parameters, $this->timezone
113
        );
114
 
115
        return $event;
116
    }
117
 
118
    /**
119
     * Add a new Artisan command event to the schedule.
120
     *
121
     * @param  string  $command
122
     * @param  array  $parameters
123
     * @return \Illuminate\Console\Scheduling\Event
124
     */
125
    public function command($command, array $parameters = [])
126
    {
127
        if (class_exists($command)) {
128
            $command = Container::getInstance()->make($command);
129
 
130
            return $this->exec(
131
                Application::formatCommandString($command->getName()), $parameters,
132
            )->description($command->getDescription());
133
        }
134
 
135
        return $this->exec(
136
            Application::formatCommandString($command), $parameters
137
        );
138
    }
139
 
140
    /**
141
     * Add a new job callback event to the schedule.
142
     *
143
     * @param  object|string  $job
144
     * @param  string|null  $queue
145
     * @param  string|null  $connection
146
     * @return \Illuminate\Console\Scheduling\CallbackEvent
147
     */
148
    public function job($job, $queue = null, $connection = null)
149
    {
150
        return $this->call(function () use ($job, $queue, $connection) {
151
            $job = is_string($job) ? Container::getInstance()->make($job) : $job;
152
 
153
            if ($job instanceof ShouldQueue) {
154
                $this->dispatchToQueue($job, $queue ?? $job->queue, $connection ?? $job->connection);
155
            } else {
156
                $this->dispatchNow($job);
157
            }
158
        })->name(is_string($job) ? $job : get_class($job));
159
    }
160
 
161
    /**
162
     * Dispatch the given job to the queue.
163
     *
164
     * @param  object  $job
165
     * @param  string|null  $queue
166
     * @param  string|null  $connection
167
     * @return void
168
     *
169
     * @throws \RuntimeException
170
     */
171
    protected function dispatchToQueue($job, $queue, $connection)
172
    {
173
        if ($job instanceof Closure) {
174
            if (! class_exists(CallQueuedClosure::class)) {
175
                throw new RuntimeException(
176
                    'To enable support for closure jobs, please install the illuminate/queue package.'
177
                );
178
            }
179
 
180
            $job = CallQueuedClosure::create($job);
181
        }
182
 
183
        if ($job instanceof ShouldBeUnique) {
184
            return $this->dispatchUniqueJobToQueue($job, $queue, $connection);
185
        }
186
 
187
        $this->getDispatcher()->dispatch(
188
            $job->onConnection($connection)->onQueue($queue)
189
        );
190
    }
191
 
192
    /**
193
     * Dispatch the given unique job to the queue.
194
     *
195
     * @param  object  $job
196
     * @param  string|null  $queue
197
     * @param  string|null  $connection
198
     * @return void
199
     *
200
     * @throws \RuntimeException
201
     */
202
    protected function dispatchUniqueJobToQueue($job, $queue, $connection)
203
    {
204
        if (! Container::getInstance()->bound(Cache::class)) {
205
            throw new RuntimeException('Cache driver not available. Scheduling unique jobs not supported.');
206
        }
207
 
208
        if (! (new UniqueLock(Container::getInstance()->make(Cache::class)))->acquire($job)) {
209
            return;
210
        }
211
 
212
        $this->getDispatcher()->dispatch(
213
            $job->onConnection($connection)->onQueue($queue)
214
        );
215
    }
216
 
217
    /**
218
     * Dispatch the given job right now.
219
     *
220
     * @param  object  $job
221
     * @return void
222
     */
223
    protected function dispatchNow($job)
224
    {
225
        $this->getDispatcher()->dispatchNow($job);
226
    }
227
 
228
    /**
229
     * Add a new command event to the schedule.
230
     *
231
     * @param  string  $command
232
     * @param  array  $parameters
233
     * @return \Illuminate\Console\Scheduling\Event
234
     */
235
    public function exec($command, array $parameters = [])
236
    {
237
        if (count($parameters)) {
238
            $command .= ' '.$this->compileParameters($parameters);
239
        }
240
 
241
        $this->events[] = $event = new Event($this->eventMutex, $command, $this->timezone);
242
 
243
        return $event;
244
    }
245
 
246
    /**
247
     * Compile parameters for a command.
248
     *
249
     * @param  array  $parameters
250
     * @return string
251
     */
252
    protected function compileParameters(array $parameters)
253
    {
254
        return collect($parameters)->map(function ($value, $key) {
255
            if (is_array($value)) {
256
                return $this->compileArrayInput($key, $value);
257
            }
258
 
259
            if (! is_numeric($value) && ! preg_match('/^(-.$|--.*)/i', $value)) {
260
                $value = ProcessUtils::escapeArgument($value);
261
            }
262
 
263
            return is_numeric($key) ? $value : "{$key}={$value}";
264
        })->implode(' ');
265
    }
266
 
267
    /**
268
     * Compile array input for a command.
269
     *
270
     * @param  string|int  $key
271
     * @param  array  $value
272
     * @return string
273
     */
274
    public function compileArrayInput($key, $value)
275
    {
276
        $value = collect($value)->map(function ($value) {
277
            return ProcessUtils::escapeArgument($value);
278
        });
279
 
280
        if (str_starts_with($key, '--')) {
281
            $value = $value->map(function ($value) use ($key) {
282
                return "{$key}={$value}";
283
            });
284
        } elseif (str_starts_with($key, '-')) {
285
            $value = $value->map(function ($value) use ($key) {
286
                return "{$key} {$value}";
287
            });
288
        }
289
 
290
        return $value->implode(' ');
291
    }
292
 
293
    /**
294
     * Determine if the server is allowed to run this event.
295
     *
296
     * @param  \Illuminate\Console\Scheduling\Event  $event
297
     * @param  \DateTimeInterface  $time
298
     * @return bool
299
     */
300
    public function serverShouldRun(Event $event, DateTimeInterface $time)
301
    {
302
        return $this->schedulingMutex->create($event, $time);
303
    }
304
 
305
    /**
306
     * Get all of the events on the schedule that are due.
307
     *
308
     * @param  \Illuminate\Contracts\Foundation\Application  $app
309
     * @return \Illuminate\Support\Collection
310
     */
311
    public function dueEvents($app)
312
    {
313
        return collect($this->events)->filter->isDue($app);
314
    }
315
 
316
    /**
317
     * Get all of the events on the schedule.
318
     *
319
     * @return \Illuminate\Console\Scheduling\Event[]
320
     */
321
    public function events()
322
    {
323
        return $this->events;
324
    }
325
 
326
    /**
327
     * Specify the cache store that should be used to store mutexes.
328
     *
329
     * @param  string  $store
330
     * @return $this
331
     */
332
    public function useCache($store)
333
    {
334
        if ($this->eventMutex instanceof CacheAware) {
335
            $this->eventMutex->useStore($store);
336
        }
337
 
338
        if ($this->schedulingMutex instanceof CacheAware) {
339
            $this->schedulingMutex->useStore($store);
340
        }
341
 
342
        return $this;
343
    }
344
 
345
    /**
346
     * Get the job dispatcher, if available.
347
     *
348
     * @return \Illuminate\Contracts\Bus\Dispatcher
349
     *
350
     * @throws \RuntimeException
351
     */
352
    protected function getDispatcher()
353
    {
354
        if ($this->dispatcher === null) {
355
            try {
356
                $this->dispatcher = Container::getInstance()->make(Dispatcher::class);
357
            } catch (BindingResolutionException $e) {
358
                throw new RuntimeException(
359
                    'Unable to resolve the dispatcher from the service container. Please bind it or install the illuminate/bus package.',
360
                    is_int($e->getCode()) ? $e->getCode() : 0, $e
361
                );
362
            }
363
        }
364
 
365
        return $this->dispatcher;
366
    }
367
}