PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/Temesky/resource-management-system-backend
PHP | 635 lines | 522 code | 21 blank | 92 comment | 1 complexity | 084068e31690d0bc3d3bb4ba4f2969c8 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. namespace Illuminate\Console\Scheduling;
  3. use Closure;
  4. use Carbon\Carbon;
  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\Support\Traits\Macroable;
  10. use Illuminate\Contracts\Container\Container;
  11. use Illuminate\Contracts\Cache\Repository as Cache;
  12. class Event
  13. {
  14. use Macroable, ManagesFrequencies;
  15. /**
  16. * The cache store implementation.
  17. *
  18. * @var \Illuminate\Contracts\Cache\Repository
  19. */
  20. protected $cache;
  21. /**
  22. * The command string.
  23. *
  24. * @var string
  25. */
  26. public $command;
  27. /**
  28. * The cron expression representing the event's frequency.
  29. *
  30. * @var string
  31. */
  32. public $expression = '* * * * * *';
  33. /**
  34. * The timezone the date should be evaluated on.
  35. *
  36. * @var \DateTimeZone|string
  37. */
  38. public $timezone;
  39. /**
  40. * The user the command should run as.
  41. *
  42. * @var string
  43. */
  44. public $user;
  45. /**
  46. * The list of environments the command should run under.
  47. *
  48. * @var array
  49. */
  50. public $environments = [];
  51. /**
  52. * Indicates if the command should run in maintenance mode.
  53. *
  54. * @var bool
  55. */
  56. public $evenInMaintenanceMode = false;
  57. /**
  58. * Indicates if the command should not overlap itself.
  59. *
  60. * @var bool
  61. */
  62. public $withoutOverlapping = false;
  63. /**
  64. * Indicates if the command should run in background.
  65. *
  66. * @var bool
  67. */
  68. public $runInBackground = false;
  69. /**
  70. * The array of filter callbacks.
  71. *
  72. * @var array
  73. */
  74. protected $filters = [];
  75. /**
  76. * The array of reject callbacks.
  77. *
  78. * @var array
  79. */
  80. protected $rejects = [];
  81. /**
  82. * The location that output should be sent to.
  83. *
  84. * @var string
  85. */
  86. public $output = '/dev/null';
  87. /**
  88. * Indicates whether output should be appended.
  89. *
  90. * @var bool
  91. */
  92. public $shouldAppendOutput = false;
  93. /**
  94. * The array of callbacks to be run before the event is started.
  95. *
  96. * @var array
  97. */
  98. protected $beforeCallbacks = [];
  99. /**
  100. * The array of callbacks to be run after the event is finished.
  101. *
  102. * @var array
  103. */
  104. protected $afterCallbacks = [];
  105. /**
  106. * The human readable description of the event.
  107. *
  108. * @var string
  109. */
  110. public $description;
  111. /**
  112. * Create a new event instance.
  113. *
  114. * @param \Illuminate\Contracts\Cache\Repository $cache
  115. * @param string $command
  116. * @return void
  117. */
  118. public function __construct(Cache $cache, $command)
  119. {
  120. $this->cache = $cache;
  121. $this->command = $command;
  122. $this->output = $this->getDefaultOutput();
  123. }
  124. /**
  125. * Get the default output depending on the OS.
  126. *
  127. * @return string
  128. */
  129. public function getDefaultOutput()
  130. {
  131. return (DIRECTORY_SEPARATOR == '\\') ? 'NUL' : '/dev/null';
  132. }
  133. /**
  134. * Run the given event.
  135. *
  136. * @param \Illuminate\Contracts\Container\Container $container
  137. * @return void
  138. */
  139. public function run(Container $container)
  140. {
  141. if ($this->withoutOverlapping) {
  142. $this->cache->put($this->mutexName(), true, 1440);
  143. }
  144. $this->runInBackground
  145. ? $this->runCommandInBackground($container)
  146. : $this->runCommandInForeground($container);
  147. }
  148. /**
  149. * Get the mutex name for the scheduled command.
  150. *
  151. * @return string
  152. */
  153. public function mutexName()
  154. {
  155. return 'framework'.DIRECTORY_SEPARATOR.'schedule-'.sha1($this->expression.$this->command);
  156. }
  157. /**
  158. * Run the command in the foreground.
  159. *
  160. * @param \Illuminate\Contracts\Container\Container $container
  161. * @return void
  162. */
  163. protected function runCommandInForeground(Container $container)
  164. {
  165. $this->callBeforeCallbacks($container);
  166. (new Process(
  167. $this->buildCommand(), base_path(), null, null, null
  168. ))->run();
  169. $this->callAfterCallbacks($container);
  170. }
  171. /**
  172. * Run the command in the background.
  173. *
  174. * @param \Illuminate\Contracts\Container\Container $container
  175. * @return void
  176. */
  177. protected function runCommandInBackground(Container $container)
  178. {
  179. $this->callBeforeCallbacks($container);
  180. (new Process(
  181. $this->buildCommand(), base_path(), null, null, null
  182. ))->run();
  183. }
  184. /**
  185. * Call all of the "before" callbacks for the event.
  186. *
  187. * @param \Illuminate\Contracts\Container\Container $container
  188. * @return void
  189. */
  190. public function callBeforeCallbacks(Container $container)
  191. {
  192. foreach ($this->beforeCallbacks as $callback) {
  193. $container->call($callback);
  194. }
  195. }
  196. /**
  197. * Call all of the "after" callbacks for the event.
  198. *
  199. * @param \Illuminate\Contracts\Container\Container $container
  200. * @return void
  201. */
  202. public function callAfterCallbacks(Container $container)
  203. {
  204. foreach ($this->afterCallbacks as $callback) {
  205. $container->call($callback);
  206. }
  207. }
  208. /**
  209. * Build the command string.
  210. *
  211. * @return string
  212. */
  213. public function buildCommand()
  214. {
  215. return (new CommandBuilder)->buildCommand($this);
  216. }
  217. /**
  218. * Determine if the given event should run based on the Cron expression.
  219. *
  220. * @param \Illuminate\Contracts\Foundation\Application $app
  221. * @return bool
  222. */
  223. public function isDue($app)
  224. {
  225. if (! $this->runsInMaintenanceMode() && $app->isDownForMaintenance()) {
  226. return false;
  227. }
  228. return $this->expressionPasses() &&
  229. $this->runsInEnvironment($app->environment());
  230. }
  231. /**
  232. * Determine if the event runs in maintenance mode.
  233. *
  234. * @return bool
  235. */
  236. public function runsInMaintenanceMode()
  237. {
  238. return $this->evenInMaintenanceMode;
  239. }
  240. /**
  241. * Determine if the Cron expression passes.
  242. *
  243. * @return bool
  244. */
  245. protected function expressionPasses()
  246. {
  247. $date = Carbon::now();
  248. if ($this->timezone) {
  249. $date->setTimezone($this->timezone);
  250. }
  251. return CronExpression::factory($this->expression)->isDue($date->toDateTimeString());
  252. }
  253. /**
  254. * Determine if the event runs in the given environment.
  255. *
  256. * @param string $environment
  257. * @return bool
  258. */
  259. public function runsInEnvironment($environment)
  260. {
  261. return empty($this->environments) || in_array($environment, $this->environments);
  262. }
  263. /**
  264. * Determine if the filters pass for the event.
  265. *
  266. * @param \Illuminate\Contracts\Foundation\Application $app
  267. * @return bool
  268. */
  269. public function filtersPass($app)
  270. {
  271. foreach ($this->filters as $callback) {
  272. if (! $app->call($callback)) {
  273. return false;
  274. }
  275. }
  276. foreach ($this->rejects as $callback) {
  277. if ($app->call($callback)) {
  278. return false;
  279. }
  280. }
  281. return true;
  282. }
  283. /**
  284. * Send the output of the command to a given location.
  285. *
  286. * @param string $location
  287. * @param bool $append
  288. * @return $this
  289. */
  290. public function sendOutputTo($location, $append = false)
  291. {
  292. $this->output = $location;
  293. $this->shouldAppendOutput = $append;
  294. return $this;
  295. }
  296. /**
  297. * Append the output of the command to a given location.
  298. *
  299. * @param string $location
  300. * @return $this
  301. */
  302. public function appendOutputTo($location)
  303. {
  304. return $this->sendOutputTo($location, true);
  305. }
  306. /**
  307. * E-mail the results of the scheduled operation.
  308. *
  309. * @param array|mixed $addresses
  310. * @param bool $onlyIfOutputExists
  311. * @return $this
  312. *
  313. * @throws \LogicException
  314. */
  315. public function emailOutputTo($addresses, $onlyIfOutputExists = false)
  316. {
  317. $this->ensureOutputIsBeingCapturedForEmail();
  318. $addresses = is_array($addresses) ? $addresses : func_get_args();
  319. return $this->then(function (Mailer $mailer) use ($addresses, $onlyIfOutputExists) {
  320. $this->emailOutput($mailer, $addresses, $onlyIfOutputExists);
  321. });
  322. }
  323. /**
  324. * E-mail the results of the scheduled operation if it produces output.
  325. *
  326. * @param array|mixed $addresses
  327. * @return $this
  328. *
  329. * @throws \LogicException
  330. */
  331. public function emailWrittenOutputTo($addresses)
  332. {
  333. return $this->emailOutputTo($addresses, true);
  334. }
  335. /**
  336. * Ensure that output is being captured for email.
  337. *
  338. * @return void
  339. */
  340. protected function ensureOutputIsBeingCapturedForEmail()
  341. {
  342. if (is_null($this->output) || $this->output == $this->getDefaultOutput()) {
  343. $this->sendOutputTo(storage_path('logs/schedule-'.sha1($this->mutexName()).'.log'));
  344. }
  345. }
  346. /**
  347. * E-mail the output of the event to the recipients.
  348. *
  349. * @param \Illuminate\Contracts\Mail\Mailer $mailer
  350. * @param array $addresses
  351. * @param bool $onlyIfOutputExists
  352. * @return void
  353. */
  354. protected function emailOutput(Mailer $mailer, $addresses, $onlyIfOutputExists = false)
  355. {
  356. $text = file_get_contents($this->output);
  357. if ($onlyIfOutputExists && empty($text)) {
  358. return;
  359. }
  360. $mailer->raw($text, function ($m) use ($addresses) {
  361. $m->to($addresses)->subject($this->getEmailSubject());
  362. });
  363. }
  364. /**
  365. * Get the e-mail subject line for output results.
  366. *
  367. * @return string
  368. */
  369. protected function getEmailSubject()
  370. {
  371. if ($this->description) {
  372. return $this->description;
  373. }
  374. return 'Scheduled Job Output';
  375. }
  376. /**
  377. * Register a callback to ping a given URL before the job runs.
  378. *
  379. * @param string $url
  380. * @return $this
  381. */
  382. public function pingBefore($url)
  383. {
  384. return $this->before(function () use ($url) {
  385. (new HttpClient)->get($url);
  386. });
  387. }
  388. /**
  389. * Register a callback to ping a given URL after the job runs.
  390. *
  391. * @param string $url
  392. * @return $this
  393. */
  394. public function thenPing($url)
  395. {
  396. return $this->then(function () use ($url) {
  397. (new HttpClient)->get($url);
  398. });
  399. }
  400. /**
  401. * State that the command should run in background.
  402. *
  403. * @return $this
  404. */
  405. public function runInBackground()
  406. {
  407. $this->runInBackground = true;
  408. return $this;
  409. }
  410. /**
  411. * Set which user the command should run as.
  412. *
  413. * @param string $user
  414. * @return $this
  415. */
  416. public function user($user)
  417. {
  418. $this->user = $user;
  419. return $this;
  420. }
  421. /**
  422. * Limit the environments the command should run in.
  423. *
  424. * @param array|mixed $environments
  425. * @return $this
  426. */
  427. public function environments($environments)
  428. {
  429. $this->environments = is_array($environments) ? $environments : func_get_args();
  430. return $this;
  431. }
  432. /**
  433. * State that the command should run even in maintenance mode.
  434. *
  435. * @return $this
  436. */
  437. public function evenInMaintenanceMode()
  438. {
  439. $this->evenInMaintenanceMode = true;
  440. return $this;
  441. }
  442. /**
  443. * Do not allow the event to overlap each other.
  444. *
  445. * @return $this
  446. */
  447. public function withoutOverlapping()
  448. {
  449. $this->withoutOverlapping = true;
  450. return $this->then(function () {
  451. $this->cache->forget($this->mutexName());
  452. })->skip(function () {
  453. return $this->cache->has($this->mutexName());
  454. });
  455. }
  456. /**
  457. * Register a callback to further filter the schedule.
  458. *
  459. * @param \Closure $callback
  460. * @return $this
  461. */
  462. public function when(Closure $callback)
  463. {
  464. $this->filters[] = $callback;
  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 skip(Closure $callback)
  474. {
  475. $this->rejects[] = $callback;
  476. return $this;
  477. }
  478. /**
  479. * Register a callback to be called before the operation.
  480. *
  481. * @param \Closure $callback
  482. * @return $this
  483. */
  484. public function before(Closure $callback)
  485. {
  486. $this->beforeCallbacks[] = $callback;
  487. return $this;
  488. }
  489. /**
  490. * Register a callback to be called after the operation.
  491. *
  492. * @param \Closure $callback
  493. * @return $this
  494. */
  495. public function after(Closure $callback)
  496. {
  497. return $this->then($callback);
  498. }
  499. /**
  500. * Register a callback to be called after the operation.
  501. *
  502. * @param \Closure $callback
  503. * @return $this
  504. */
  505. public function then(Closure $callback)
  506. {
  507. $this->afterCallbacks[] = $callback;
  508. return $this;
  509. }
  510. /**
  511. * Set the human-friendly description of the event.
  512. *
  513. * @param string $description
  514. * @return $this
  515. */
  516. public function name($description)
  517. {
  518. return $this->description($description);
  519. }
  520. /**
  521. * Set the human-friendly description of the event.
  522. *
  523. * @param string $description
  524. * @return $this
  525. */
  526. public function description($description)
  527. {
  528. $this->description = $description;
  529. return $this;
  530. }
  531. /**
  532. * Get the summary of the event for display.
  533. *
  534. * @return string
  535. */
  536. public function getSummaryForDisplay()
  537. {
  538. if (is_string($this->description)) {
  539. return $this->description;
  540. }
  541. return $this->buildCommand();
  542. }
  543. /**
  544. * Get the Cron expression for the event.
  545. *
  546. * @return string
  547. */
  548. public function getExpression()
  549. {
  550. return $this->expression;
  551. }
  552. }