Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge 1.next => 1.x #20

Merged
merged 11 commits into from
Nov 17, 2024
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- 'main'
- '1.x'
- '1.next'
pull_request:
branches:
- '*'
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
"type": "cakephp-plugin",
"require": {
"php": "^8.1",
"cakephp/cakephp": "^5.0.0",
"cakephp/cakephp": "^5.0",
"dragonmantank/cron-expression": "^3.3"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^5.0",
"phpunit/phpunit": "^10.1"
"mockery/mockery": "^1.6",
"phpunit/phpunit": "^10.5.5 || ^11.1.3"
},
"license": "MIT",
"autoload": {
Expand Down
19 changes: 19 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
parameters:
ignoreErrors:
-
message: '#^Call to an undefined method CakeScheduler\\Scheduler\\Scheduler\|Mockery\\LegacyMockInterface\:\:getEventManager\(\)\.$#'
identifier: method.notFound
count: 2
path: tests/TestCase/Command/ScheduleRunCommandTest.php

-
message: '#^Call to an undefined method CakeScheduler\\Scheduler\\Scheduler\|Mockery\\LegacyMockInterface\:\:shouldReceive\(\)\.$#'
identifier: method.notFound
count: 8
path: tests/TestCase/Command/ScheduleRunCommandTest.php

-
message: '#^Call to an undefined method Mockery\\ExpectationInterface\|Mockery\\HigherOrderMessage\:\:andReturn\(\)\.$#'
identifier: method.notFound
count: 8
path: tests/TestCase/Command/ScheduleRunCommandTest.php
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
includes:
- phpstan-baseline.neon

parameters:
paths:
- src
Expand Down
23 changes: 20 additions & 3 deletions src/Command/ScheduleRunCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
use Cake\Command\Command;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use CakeScheduler\Error\SchedulerStoppedException;
use CakeScheduler\Scheduler\Event;
use CakeScheduler\Scheduler\Scheduler;
use Throwable;

class ScheduleRunCommand extends Command
{
Expand All @@ -34,7 +36,13 @@ public function execute(Arguments $args, ConsoleIo $io): int
}

$events->each(function (Event $event) use ($io): void {
$this->runEvent($event, $io);
$returnCode = $this->runEvent($event, $io);

if ($returnCode === Scheduler::SHOULD_STOP_EXECUTION) {
$io->error('Error while executing command: ' . get_class($event->getCommand()));

throw new SchedulerStoppedException('Scheduler was stopped by event listener');
}
});

return self::CODE_SUCCESS;
Expand All @@ -48,8 +56,17 @@ public function execute(Arguments $args, ConsoleIo $io): int
protected function runEvent(Event $event, ConsoleIo $io): ?int
{
$this->scheduler->dispatchEvent('CakeScheduler.beforeExecute', ['event' => $event]);
$result = $event->run($io);
$this->scheduler->dispatchEvent('CakeScheduler.afterExecute', ['event' => $event, 'result' => $result]);
try {
$result = $event->run($io);
$this->scheduler->dispatchEvent('CakeScheduler.afterExecute', ['event' => $event, 'result' => $result]);
} catch (Throwable $exception) {
$io->error($exception->getMessage());
$event = $this->scheduler->dispatchEvent('CakeScheduler.errorExecute', [
'event' => $event,
'exception' => $exception,
]);
$result = $event->getResult();
}

return $result;
}
Expand Down
10 changes: 10 additions & 0 deletions src/Error/SchedulerStoppedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace CakeScheduler\Error;

use RuntimeException;

class SchedulerStoppedException extends RuntimeException
{
}
52 changes: 50 additions & 2 deletions src/Scheduler/Scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

use Cake\Collection\Collection;
use Cake\Collection\CollectionInterface;
use Cake\Command\Command;
use Cake\Console\Arguments;
use Cake\Console\CommandInterface;
use Cake\Console\ConsoleIo;
use Cake\Core\Container;
use Cake\Core\ContainerInterface;
use Cake\Event\EventDispatcherInterface;
Expand Down Expand Up @@ -33,6 +36,11 @@ class Scheduler implements EventDispatcherInterface
*/
protected CollectionInterface $events;

/**
* The event code if execution should be stopped
*/
public const SHOULD_STOP_EXECUTION = 1;

/**
* @param \Cake\Core\Container|null $container The DI container instance from the app
*/
Expand All @@ -43,12 +51,16 @@ public function __construct(?Container $container = null)
}

/**
* @param string $command The FQCN of the command to be executed
* @param callable|string $command The FQCN of the command to be executed or a callable function
* @param array $args Args which should be passed on to the command
* @return \CakeScheduler\Scheduler\Event
*/
public function execute(string $command, array $args = []): Event
public function execute(string|callable $command, array $args = []): Event
{
if (is_callable($command)) {
return $this->addCallable($command, $args);
}

try {
if ($this->container !== null) {
$commandObj = $this->container->get($command);
Expand Down Expand Up @@ -81,6 +93,42 @@ protected function addCommand(CommandInterface $command, array $args = []): Even
return $event;
}

/**
* @param callable $callable
* @param array $args
* @return \CakeScheduler\Scheduler\Event
*/
protected function addCallable(callable $callable, array $args = []): Event
{
$command = new class ($callable, $args) extends Command {
/**
* @param callable $callable
* @param array $args
*/
public function __construct(
protected $callable,
protected array $args = []
) {
}

/**
* @param \Cake\Console\Arguments $args
* @param \Cake\Console\ConsoleIo $io
* @return int|null
*/
public function execute(Arguments $args, ConsoleIo $io): ?int
{
array_push($this->args, $io);

return call_user_func_array($this->callable, $this->args);
}
};
$event = new Event($command, $args);
$this->events = $this->events->appendItem($event);

return $event;
}

/**
* @return \Cake\Collection\CollectionInterface
*/
Expand Down
Loading