223 lines
5.9 KiB
PHP
223 lines
5.9 KiB
PHP
<?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)
|
|
{
|
|
/** @var \UserFrosting\System\Sprinkle\SprinkleManager */
|
|
$sprinkleManager = $this->ci->sprinkleManager;
|
|
|
|
// Format the sprinkle name for the namespace
|
|
$sprinkleName = $file->getLocation()->getName();
|
|
$sprinkleNS = $sprinkleManager->getSprinkleClassNamespace($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 = "\\$sprinkleNS\\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();
|
|
|
|
$nextRun = $taskClass->nextRunDate();
|
|
|
|
// Build the class name and namespace
|
|
return [
|
|
'schedule' => $schedule,
|
|
'sprinkle' => $sprinkleName,
|
|
'name' => $name,
|
|
'class' => $classPath,
|
|
'instance' => $taskClass,
|
|
'next_run' => $nextRun,
|
|
];
|
|
}
|
|
}
|