PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/Console/Scheduling/Event.php

https://gitlab.com/PragmaticLinux/Laravel
PHP | 705 lines | 286 code | 90 blank | 329 comment | 14 complexity | 340d7c1a8076bf32a489384ed7d3bd41 MD5 | raw file
  1. <?php namespace Illuminate\Console\Scheduling;
  2. use Closure;
  3. use Carbon\Carbon;
  4. use LogicException;
  5. use Cron\CronExpression;
  6. use GuzzleHttp\Client as HttpClient;
  7. use Illuminate\Contracts\Mail\Mailer;
  8. use Symfony\Component\Process\Process;
  9. use Illuminate\Contracts\Container\Container;
  10. use Illuminate\Contracts\Foundation\Application;
  11. class Event {
  12. /**
  13. * The command string.
  14. *
  15. * @var string
  16. */
  17. protected $command;
  18. /**
  19. * The cron expression representing the event's frequency.
  20. *
  21. * @var string
  22. */
  23. protected $expression = '* * * * * *';
  24. /**
  25. * The timezone the date should be evaluated on.
  26. *
  27. * @var \DateTimeZone|string
  28. */
  29. protected $timezone;
  30. /**
  31. * The user the command should run as.
  32. *
  33. * @var string
  34. */
  35. protected $user;
  36. /**
  37. * The list of environments the command should run under.
  38. *
  39. * @var array
  40. */
  41. protected $environments = [];
  42. /**
  43. * Indicates if the command should run in maintenance mode.
  44. *
  45. * @var bool
  46. */
  47. protected $evenInMaintenanceMode = false;
  48. /**
  49. * The filter callback.
  50. *
  51. * @var \Closure
  52. */
  53. protected $filter;
  54. /**
  55. * The reject callback.
  56. *
  57. * @var \Closure
  58. */
  59. protected $reject;
  60. /**
  61. * The location that output should be sent to.
  62. *
  63. * @var string
  64. */
  65. protected $output = '/dev/null';
  66. /**
  67. * The array of callbacks to be run after the event is finished.
  68. *
  69. * @var array
  70. */
  71. protected $afterCallbacks = [];
  72. /**
  73. * The human readable description of the event.
  74. *
  75. * @var string
  76. */
  77. protected $description;
  78. /**
  79. * Create a new event instance.
  80. *
  81. * @param string $command
  82. * @return void
  83. */
  84. public function __construct($command)
  85. {
  86. $this->command = $command;
  87. }
  88. /**
  89. * Run the given event.
  90. *
  91. * @param \Illuminate\Contracts\Container\Container $container
  92. * @return void
  93. */
  94. public function run(Container $container)
  95. {
  96. if (count($this->afterCallbacks) > 0)
  97. {
  98. $this->runCommandInForeground($container);
  99. }
  100. else
  101. {
  102. $this->runCommandInBackground();
  103. }
  104. }
  105. /**
  106. * Run the command in the background using exec.
  107. *
  108. * @return void
  109. */
  110. protected function runCommandInBackground()
  111. {
  112. chdir(base_path());
  113. exec($this->buildCommand());
  114. }
  115. /**
  116. * Run the command in the foreground.
  117. *
  118. * @param \Illuminate\Contracts\Container\Container $container
  119. * @return void
  120. */
  121. protected function runCommandInForeground(Container $container)
  122. {
  123. (new Process(
  124. trim($this->buildCommand(), '& '), base_path(), null, null, null
  125. ))->run();
  126. $this->callAfterCallbacks($container);
  127. }
  128. /**
  129. * Call all of the "after" callbacks for the event.
  130. *
  131. * @param \Illuminate\Contracts\Container\Container $container
  132. * @return void
  133. */
  134. protected function callAfterCallbacks(Container $container)
  135. {
  136. foreach ($this->afterCallbacks as $callback)
  137. {
  138. $container->call($callback);
  139. }
  140. }
  141. /**
  142. * Build the comand string.
  143. *
  144. * @return string
  145. */
  146. public function buildCommand()
  147. {
  148. $command = $this->command.' > '.$this->output.' 2>&1 &';
  149. return $this->user ? 'sudo -u '.$this->user.' '.$command : $command;
  150. }
  151. /**
  152. * Determine if the given event should run based on the Cron expression.
  153. *
  154. * @param \Illuminate\Contracts\Foundation\Application $app
  155. * @return bool
  156. */
  157. public function isDue(Application $app)
  158. {
  159. if ( ! $this->runsInMaintenanceMode() && $app->isDownForMaintenance())
  160. {
  161. return false;
  162. }
  163. return $this->expressionPasses() &&
  164. $this->filtersPass($app) &&
  165. $this->runsInEnvironment($app->environment());
  166. }
  167. /**
  168. * Determine if the Cron expression passes.
  169. *
  170. * @return bool
  171. */
  172. protected function expressionPasses()
  173. {
  174. $date = Carbon::now();
  175. if ($this->timezone)
  176. {
  177. $date->setTimezone($this->timezone);
  178. }
  179. return CronExpression::factory($this->expression)->isDue($date);
  180. }
  181. /**
  182. * Determine if the filters pass for the event.
  183. *
  184. * @param \Illuminate\Contracts\Foundation\Application $app
  185. * @return bool
  186. */
  187. protected function filtersPass(Application $app)
  188. {
  189. if (($this->filter && ! $app->call($this->filter)) ||
  190. $this->reject && $app->call($this->reject))
  191. {
  192. return false;
  193. }
  194. return true;
  195. }
  196. /**
  197. * Determine if the event runs in the given environment.
  198. *
  199. * @param string $environment
  200. * @return bool
  201. */
  202. public function runsInEnvironment($environment)
  203. {
  204. return empty($this->environments) || in_array($environment, $this->environments);
  205. }
  206. /**
  207. * Determine if the event runs in maintenance mode.
  208. *
  209. * @return bool
  210. */
  211. public function runsInMaintenanceMode()
  212. {
  213. return $this->evenInMaintenanceMode;
  214. }
  215. /**
  216. * The Cron expression representing the event's frequency.
  217. *
  218. * @param string $expression
  219. * @return $this
  220. */
  221. public function cron($expression)
  222. {
  223. $this->expression = $expression;
  224. return $this;
  225. }
  226. /**
  227. * Schedule the event to run hourly.
  228. *
  229. * @return $this
  230. */
  231. public function hourly()
  232. {
  233. return $this->cron('0 * * * * *');
  234. }
  235. /**
  236. * Schedule the event to run daily.
  237. *
  238. * @return $this
  239. */
  240. public function daily()
  241. {
  242. return $this->cron('0 0 * * * *');
  243. }
  244. /**
  245. * Schedule the command at a given time.
  246. *
  247. * @param string $time
  248. * @return $this
  249. */
  250. public function at($time)
  251. {
  252. return $this->dailyAt($time);
  253. }
  254. /**
  255. * Schedule the event to run daily at a given time (10:00, 19:30, etc).
  256. *
  257. * @param string $time
  258. * @return $this
  259. */
  260. public function dailyAt($time)
  261. {
  262. $segments = explode(':', $time);
  263. return $this->spliceIntoPosition(2, (int) $segments[0])
  264. ->spliceIntoPosition(1, count($segments) == 2 ? (int) $segments[1] : '0');
  265. }
  266. /**
  267. * Schedule the event to run twice daily.
  268. *
  269. * @return $this
  270. */
  271. public function twiceDaily()
  272. {
  273. return $this->cron('0 1,13 * * * *');
  274. }
  275. /**
  276. * Schedule the event to run only on weekdays.
  277. *
  278. * @return $this
  279. */
  280. public function weekdays()
  281. {
  282. return $this->spliceIntoPosition(5, '1-5');
  283. }
  284. /**
  285. * Schedule the event to run only on Mondays.
  286. *
  287. * @return $this
  288. */
  289. public function mondays()
  290. {
  291. return $this->days(1);
  292. }
  293. /**
  294. * Schedule the event to run only on Tuesdays.
  295. *
  296. * @return $this
  297. */
  298. public function tuesdays()
  299. {
  300. return $this->days(2);
  301. }
  302. /**
  303. * Schedule the event to run only on Wednesdays.
  304. *
  305. * @return $this
  306. */
  307. public function wednesdays()
  308. {
  309. return $this->days(3);
  310. }
  311. /**
  312. * Schedule the event to run only on Thursdays.
  313. *
  314. * @return $this
  315. */
  316. public function thursdays()
  317. {
  318. return $this->days(4);
  319. }
  320. /**
  321. * Schedule the event to run only on Fridays.
  322. *
  323. * @return $this
  324. */
  325. public function fridays()
  326. {
  327. return $this->days(5);
  328. }
  329. /**
  330. * Schedule the event to run only on Saturdays.
  331. *
  332. * @return $this
  333. */
  334. public function saturdays()
  335. {
  336. return $this->days(6);
  337. }
  338. /**
  339. * Schedule the event to run only on Sundays.
  340. *
  341. * @return $this
  342. */
  343. public function sundays()
  344. {
  345. return $this->days(0);
  346. }
  347. /**
  348. * Schedule the event to run weekly.
  349. *
  350. * @return $this
  351. */
  352. public function weekly()
  353. {
  354. return $this->cron('0 0 * * 0 *');
  355. }
  356. /**
  357. * Schedule the event to run weekly on a given day and time.
  358. *
  359. * @param int $day
  360. * @param string $time
  361. * @return $this
  362. */
  363. public function weeklyOn($day, $time = '0:0')
  364. {
  365. $this->dailyAt($time);
  366. return $this->spliceIntoPosition(5, $day);
  367. }
  368. /**
  369. * Schedule the event to run monthly.
  370. *
  371. * @return $this
  372. */
  373. public function monthly()
  374. {
  375. return $this->cron('0 0 1 * * *');
  376. }
  377. /**
  378. * Schedule the event to run yearly.
  379. *
  380. * @return $this
  381. */
  382. public function yearly()
  383. {
  384. return $this->cron('0 0 1 1 * *');
  385. }
  386. /**
  387. * Schedule the event to run every five minutes.
  388. *
  389. * @return $this
  390. */
  391. public function everyFiveMinutes()
  392. {
  393. return $this->cron('*/5 * * * * *');
  394. }
  395. /**
  396. * Schedule the event to run every ten minutes.
  397. *
  398. * @return $this
  399. */
  400. public function everyTenMinutes()
  401. {
  402. return $this->cron('*/10 * * * * *');
  403. }
  404. /**
  405. * Schedule the event to run every thirty minutes.
  406. *
  407. * @return $this
  408. */
  409. public function everyThirtyMinutes()
  410. {
  411. return $this->cron('0,30 * * * * *');
  412. }
  413. /**
  414. * Set the days of the week the command should run on.
  415. *
  416. * @param array|dynamic $days
  417. * @return $this
  418. */
  419. public function days($days)
  420. {
  421. $days = is_array($days) ? $days : func_get_args();
  422. return $this->spliceIntoPosition(5, implode(',', $days));
  423. }
  424. /**
  425. * Set the timezone the date should be evaluated on.
  426. *
  427. * @param \DateTimeZone|string $timezone
  428. * @return $this
  429. */
  430. public function timezone($timezone)
  431. {
  432. $this->timezone = $timezone;
  433. return $this;
  434. }
  435. /**
  436. * Set which user the command should run as.
  437. *
  438. * @param string $user
  439. * @return $this
  440. */
  441. public function user($user)
  442. {
  443. $this->user = $user;
  444. return $this;
  445. }
  446. /**
  447. * Limit the environments the command should run in.
  448. *
  449. * @param array|dynamic $environments
  450. * @return $this
  451. */
  452. public function environments($environments)
  453. {
  454. $this->environments = is_array($environments) ? $environments : func_get_args();
  455. return $this;
  456. }
  457. /**
  458. * State that the command should run even in maintenance mode.
  459. *
  460. * @return $this
  461. */
  462. public function evenInMaintenanceMode()
  463. {
  464. $this->evenInMaintenanceMode = true;
  465. return $this;
  466. }
  467. /**
  468. * Register a callback to further filter the schedule.
  469. *
  470. * @param \Closure $callback
  471. * @return $this
  472. */
  473. public function when(Closure $callback)
  474. {
  475. $this->filter = $callback;
  476. return $this;
  477. }
  478. /**
  479. * Register a callback to further filter the schedule.
  480. *
  481. * @param \Closure $callback
  482. * @return $this
  483. */
  484. public function skip(Closure $callback)
  485. {
  486. $this->reject = $callback;
  487. return $this;
  488. }
  489. /**
  490. * Send the output of the command to a given location.
  491. *
  492. * @param string $location
  493. * @return $this
  494. */
  495. public function sendOutputTo($location)
  496. {
  497. $this->output = $location;
  498. return $this;
  499. }
  500. /**
  501. * E-mail the results of the scheduled operation.
  502. *
  503. * @param array|dynamic $addresses
  504. * @return $this
  505. *
  506. * @throws \LogicException
  507. */
  508. public function emailOutputTo($addresses)
  509. {
  510. if (is_null($this->output) || $this->output == '/dev/null')
  511. {
  512. throw new LogicException("Must direct output to a file in order to e-mail results.");
  513. }
  514. $addresses = is_array($addresses) ? $addresses : func_get_args();
  515. return $this->then(function(Mailer $mailer) use ($addresses)
  516. {
  517. $this->emailOutput($mailer, $addresses);
  518. });
  519. }
  520. /**
  521. * E-mail the output of the event to the recipients.
  522. *
  523. * @param \Illuminate\Contracts\Mail\Mailer $mailer
  524. * @param array $addresses
  525. * @return void
  526. */
  527. protected function emailOutput(Mailer $mailer, $addresses)
  528. {
  529. $mailer->raw(file_get_contents($this->output), function($m) use ($addresses)
  530. {
  531. $m->subject($this->getEmailSubject());
  532. foreach ($addresses as $address)
  533. {
  534. $m->to($address);
  535. }
  536. });
  537. }
  538. /**
  539. * Get the e-mail subject line for output results.
  540. *
  541. * @return string
  542. */
  543. protected function getEmailSubject()
  544. {
  545. if ($this->description)
  546. {
  547. return 'Scheduled Job Output ('.$this->description.')';
  548. }
  549. return 'Scheduled Job Output';
  550. }
  551. /**
  552. * Register a callback to the ping a given URL after the job runs.
  553. *
  554. * @param string $url
  555. * @return $this
  556. */
  557. public function thenPing($url)
  558. {
  559. return $this->then(function() use ($url) { (new HttpClient)->get($url); });
  560. }
  561. /**
  562. * Register a callback to be called after the operation.
  563. *
  564. * @param \Closure $callback
  565. * @return $this
  566. */
  567. public function then(Closure $callback)
  568. {
  569. $this->afterCallbacks[] = $callback;
  570. return $this;
  571. }
  572. /**
  573. * Set the human-friendly description of the event.
  574. *
  575. * @param string $description
  576. * @return $this
  577. */
  578. public function description($description)
  579. {
  580. $this->description = $description;
  581. return $this;
  582. }
  583. /**
  584. * Splice the given value into the given position of the expression.
  585. *
  586. * @param int $position
  587. * @param string $value
  588. * @return void
  589. */
  590. protected function spliceIntoPosition($position, $value)
  591. {
  592. $segments = explode(' ', $this->expression);
  593. $segments[$position - 1] = $value;
  594. return $this->cron(implode(' ', $segments));
  595. }
  596. /**
  597. * Get the summary of the event for display.
  598. *
  599. * @return string
  600. */
  601. public function getSummaryForDisplay()
  602. {
  603. if (is_string($this->description)) return $this->description;
  604. return $this->buildCommand();
  605. }
  606. /**
  607. * Get the Cron expression for the event.
  608. *
  609. * @return string
  610. */
  611. public function getExpression()
  612. {
  613. return $this->expression;
  614. }
  615. }