Basic scheduler completed

This commit is contained in:
2022-03-16 12:01:55 +00:00
parent 5e67853951
commit c542721982
10 changed files with 737 additions and 0 deletions

215
src/Scheduler/Scheduler.php Normal file
View File

@@ -0,0 +1,215 @@
<?php
/*
* AVSDev UF Scheduler (https://avsdev.uk)
*
* @link https://git.avsdev.uk/avsdev/sprinkle-scheduler
* @license https://git.avsdev.uk/avsdev/sprinkle-scheduler/blob/master/LICENSE.md (LGPL-3.0 License)
*/
namespace UserFrosting\Sprinkle\Scheduler\Scheduler;
use Illuminate\Support\Str;
use Psr\Container\ContainerInterface;
use UserFrosting\UniformResourceLocator\Resource as ResourceInstance;
/**
* Scheduler Class.
*
* Finds all tasks class across sprinkles
*
* @author Craig Williams (https://avsdev.uk)
*/
class Scheduler
{
/**
* @var ContainerInterface
*/
protected $ci;
/**
* @var string The resource locator scheme
*/
protected $scheme = 'tasks://';
/**
* Class Constructor.
*
* @param ContainerInterface $ci
*/
public function __construct(ContainerInterface $ci)
{
$this->ci = $ci;
}
/**
* Loop all the available sprinkles and return a list of their tasks.
*
* @return array An array of all the task classes found for every sprinkle
*/
public function getTasks()
{
$tasks = $this->ci->locator->listResources($this->scheme, false, false);
return $this->loadTasks($tasks);
}
/**
* Get a single task info.
*
* @param string $name The task name
*
* @throws \Exception If task not found
*
* @return array The details about a task file [name, class, sprinkle]
*/
public function getTask($name)
{
// Get task resource
$taskResource = $this->ci->locator->getResource($this->scheme . $name . '.php');
// Make sure we found something
if (!$taskResource) {
throw new \Exception("Task $name not found");
}
// Return the task info
return $this->getTaskDetails($taskResource);
}
/**
* Return the class instance of a task.
*
* @param string $name The task name
*
* @throws \Exception If class doesn't exist or is not right interface
*
* @return TaskInterface The task class instance
*/
public function getTaskClass($name)
{
// Try to get task info
$task = $this->getTask($name);
// Make sure class exist
$classPath = $task['class'];
if (!class_exists($classPath)) {
throw new \Exception("Task class `$classPath` not found. Make sure the class has the correct namespace.");
}
// Create a new class instance
$taskClass = new $classPath($this->ci);
// Class must be an instance of `TaskerInterface`
if (!$taskClass instanceof TaskInterface) {
throw new \Exception('Task class must be an instance of `TaskerInterface`');
}
return $taskClass;
}
/**
* Run a task class.
*
* @param TaskInterface $task The task to run
*/
public function runTask(TaskInterface $task)
{
$task->run();
}
/**
* Run a task based on it's name.
*
* @param string $taskName
*/
public function run($taskName)
{
$task = $this->getTaskClass($taskName);
$this->runTask($task);
}
/**
* Return a list of tasks due to be run
*/
public function dueTasks()
{
$tasks = $this->getTasks();
return array_filter($tasks, function($task) {
// Get the task's class
$classPath = $task['class'];
// Create a new class instance
$taskClass = new $classPath($this->ci);
// Class must be an instance of `TaskerInterface`
if (!$taskClass instanceof TaskInterface) {
throw new \Exception('Task class must be an instance of `TaskerInterface`');
}
return $taskClass->isDue();
});
}
/**
* Process tasks Resource into info.
*
* @param array $taskFiles List of tasks files
*
* @return array
*/
protected function loadTasks(array $taskFiles)
{
$tasks = [];
foreach ($taskFiles as $taskFile) {
$tasks[] = $this->getTaskDetails($taskFile);
}
return $tasks;
}
/**
* Return an array of task details including the class name and the sprinkle name.
*
* @param ResourceInstance $file The task file
*
* @return array The details about a task file [name, class, sprinkle]
*/
protected function getTaskDetails(ResourceInstance $file)
{
// Format the sprinkle name for the namespace
$sprinkleName = $file->getLocation()->getName();
$sprinkleName = Str::studly($sprinkleName);
// Getting base path, name and class name
$basePath = str_replace($file->getBasename(), '', $file->getBasePath());
$name = $basePath . $file->getFilename();
$className = str_replace('/', '\\', $basePath) . $file->getFilename();
$classPath = "\\UserFrosting\\Sprinkle\\$sprinkleName\\Scheduler\\Tasks\\$className";
if (!class_exists($classPath)) {
throw new \Exception("Task class `$className` not found. Make sure the class has the correct namespace.");
}
// Create a new class instance
$taskClass = new $classPath($this->ci);
// Class must be an instance of `TaskerInterface`
if (!$taskClass instanceof TaskInterface) {
throw new \Exception('Task class must be an instance of `TaskerInterface`');
}
$schedule = $taskClass->cronExpression();
// Build the class name and namespace
return [
'schedule' => $schedule,
'sprinkle' => $sprinkleName,
'name' => $name,
'class' => $classPath,
'instance' => $taskClass,
];
}
}