diff --git a/.github/workflows/laravel.yml b/.github/workflows/laravel.yml index 9823892b..f157d659 100644 --- a/.github/workflows/laravel.yml +++ b/.github/workflows/laravel.yml @@ -4,9 +4,27 @@ on: [push, pull_request] jobs: laravel-tests: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + os: [ ubuntu-latest ] + php: [ 8.0, 8.1 ] + laravel: [ 9.* ] + stability: [ prefer-stable ] + include: + - laravel: 9.* + testbench: ^7.0 + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} + steps: - uses: actions/checkout@v2 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo + coverage: none - name: Cache dependencies uses: actions/cache@v2 with: @@ -14,7 +32,9 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: | ${{ runner.os }}-composer- - - name: Install Dependencies - run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist + - name: Install dependencies + run: | + composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update + composer update --${{ matrix.stability }} --prefer-dist --no-interaction - name: Execute tests (Unit and Feature tests) via PHPUnit run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index f169040a..5b112725 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ _ide_helper.php .DS_Store .idea *.sketch +.phpunit.result.cache diff --git a/composer.json b/composer.json index 602ba577..d817732b 100644 --- a/composer.json +++ b/composer.json @@ -16,21 +16,21 @@ } ], "require": { - "php": ">=7.3", + "php": "^8.0.0|^8.1.0", "ext-json": "*", "doctrine/dbal": "^3.1", - "illuminate/bus": "^8.11", - "illuminate/console": "^8.11", - "illuminate/contracts": "^8.11", - "illuminate/database": "^8.11", - "illuminate/events": "^8.11", - "illuminate/notifications": "^8.11", + "illuminate/bus": "^8.11|^9.0", + "illuminate/console": "^8.11|^9.0", + "illuminate/contracts": "^8.11|^9.0", + "illuminate/database": "^8.11|^9.0", + "illuminate/events": "^8.11|^9.0", + "illuminate/notifications": "^8.11|^9.0", "laravelcollective/html": "^6.0" }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/database": "^6.0", - "orchestra/testbench" : "^6.0", + "orchestra/database": "^6.0|^7.0", + "orchestra/testbench" : "^6.0|^7.0", "phpunit/phpunit": "^9.0" }, "suggest": { diff --git a/docker-compose.yml b/docker-compose.yml index 49be20af..e3a25cb5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,7 @@ services: - totem db: - image: mysql:8.0.20 + image: mysql/mysql-server:8.0.27 container_name: totem-db restart: unless-stopped environment: diff --git a/docker/Dockerfile b/docker/Dockerfile index e13022e3..3c63c8c0 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7.3.29-fpm +FROM arm64v8/php:8.1.0-fpm # Install system dependencies RUN apt-get update && apt-get install -y \ diff --git a/src/Contracts/TaskInterface.php b/src/Contracts/TaskInterface.php index e85cb72a..c955de24 100644 --- a/src/Contracts/TaskInterface.php +++ b/src/Contracts/TaskInterface.php @@ -2,67 +2,71 @@ namespace Studio\Totem\Contracts; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; +use Studio\Totem\Task; + interface TaskInterface { /** * Returns Eloquent Builder. * - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ - public function builder(); + public function builder(): Builder; /** * Returns a task by its primary key. * - * @param int|\Studio\Totem\Task $id - * @return \Studio\Totem\Task + * @param int|Task $id + * @return Task */ - public function find($id); + public function find(Task|int $id); /** * Returns all tasks. * - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ - public function findAll(); + public function findAll(): Collection; /** * Returns all active tasks. * - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ - public function findAllActive(); + public function findAllActive(): Collection; /** * Creates a new task with the given data. * * @param array $input - * @return \Studio\Totem\Task + * @return Task|bool */ - public function store(array $input); + public function store(array $input): Task|bool; /** * Updates the given task with the given data. * * @param array $input - * @param \Studio\Totem\Task $task - * @return \Studio\Totem\Task + * @param Task $task + * @return Task */ - public function update(array $input, $task); + public function update(array $input, Task $task): Task; /** * Deletes the given task. * - * @param int|\Studio\Totem\Task $id + * @param int|Task $id * @return bool */ - public function destroy($id); + public function destroy(Task|int $id): bool; /** * Executes the given task. * - * @param int|\Studio\Totem\Task $id - * @return bool + * @param int|Task $id + * @return Task */ - public function execute($id); + public function execute(Task|int $id): Task; } diff --git a/src/Events/BroadcastingEvent.php b/src/Events/BroadcastingEvent.php index bd4c9d2a..226d7aa3 100644 --- a/src/Events/BroadcastingEvent.php +++ b/src/Events/BroadcastingEvent.php @@ -13,9 +13,9 @@ class BroadcastingEvent extends TaskEvent implements ShouldBroadcast /** * Get the channels the event should broadcast on. * - * @return \Illuminate\Broadcasting\Channel|\Illuminate\Broadcasting\Channel[]|PrivateChannel + * @return PrivateChannel */ - public function broadcastOn() + public function broadcastOn(): PrivateChannel { return new PrivateChannel(config('totem.broadcasting.channel')); } @@ -25,7 +25,7 @@ public function broadcastOn() * * @return bool */ - public function broadcastWhen() + public function broadcastWhen(): bool { return config('totem.broadcasting.enabled'); } diff --git a/src/Events/Creating.php b/src/Events/Creating.php index 53d0b6f8..27aacb37 100644 --- a/src/Events/Creating.php +++ b/src/Events/Creating.php @@ -2,7 +2,6 @@ namespace Studio\Totem\Events; -use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; @@ -16,7 +15,7 @@ class Creating implements ShouldBroadcast /** * @var array */ - private $input; + private array $input; /** * Create a new event instance. @@ -31,9 +30,9 @@ public function __construct(array $input) /** * Get the channels the event should broadcast on. * - * @return Channel|array + * @return PrivateChannel */ - public function broadcastOn() + public function broadcastOn(): PrivateChannel { return new PrivateChannel('channel-name'); } diff --git a/src/Events/Deleted.php b/src/Events/Deleted.php index 51eefd5f..1d9d308e 100644 --- a/src/Events/Deleted.php +++ b/src/Events/Deleted.php @@ -6,9 +6,6 @@ class Deleted extends Event { /** * Create a new event instance. - * - * @param array $input - * @param Task $task */ public function __construct() { diff --git a/src/Events/Executed.php b/src/Events/Executed.php index a0eec41e..b5dc6d69 100644 --- a/src/Events/Executed.php +++ b/src/Events/Executed.php @@ -11,7 +11,8 @@ class Executed extends BroadcastingEvent * Executed constructor. * * @param Task $task - * @param string $started + * @param string|float|int $started + * @param $output */ public function __construct(Task $task, $started, $output) { diff --git a/src/Events/TaskEvent.php b/src/Events/TaskEvent.php index 4b88cdd0..a952eaed 100644 --- a/src/Events/TaskEvent.php +++ b/src/Events/TaskEvent.php @@ -13,7 +13,7 @@ class TaskEvent extends Event /** * @var Task */ - public $task; + public Task $task; /** * Constructor. diff --git a/src/Events/Updating.php b/src/Events/Updating.php index d53c9e8c..ee75f6ab 100644 --- a/src/Events/Updating.php +++ b/src/Events/Updating.php @@ -2,7 +2,6 @@ namespace Studio\Totem\Events; -use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\PrivateChannel; use Studio\Totem\Task; @@ -11,7 +10,7 @@ class Updating extends BroadcastingEvent /** * @var array */ - private $input; + private array $input; /** * Create a new event instance. @@ -28,9 +27,9 @@ public function __construct(array $input, Task $task) /** * Get the channels the event should broadcast on. * - * @return Channel|array + * @return PrivateChannel */ - public function broadcastOn() + public function broadcastOn(): PrivateChannel { return new PrivateChannel('channel-name'); } diff --git a/src/Frequency.php b/src/Frequency.php index 39755df3..f85eccc0 100644 --- a/src/Frequency.php +++ b/src/Frequency.php @@ -2,6 +2,7 @@ namespace Studio\Totem; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Studio\Totem\Traits\HasParameters; class Frequency extends TotemModel @@ -17,9 +18,9 @@ class Frequency extends TotemModel ]; /** - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return BelongsTo */ - public function task() + public function task(): BelongsTo { return $this->belongsTo(Task::class); } diff --git a/src/Http/Controllers/ActiveTasksController.php b/src/Http/Controllers/ActiveTasksController.php index 779c181e..c5174b89 100644 --- a/src/Http/Controllers/ActiveTasksController.php +++ b/src/Http/Controllers/ActiveTasksController.php @@ -2,6 +2,7 @@ namespace Studio\Totem\Http\Controllers; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Studio\Totem\Contracts\TaskInterface; @@ -10,7 +11,7 @@ class ActiveTasksController extends Controller /** * @var TaskInterface */ - private $tasks; + private TaskInterface $tasks; /** * @param TaskInterface $tasks @@ -25,10 +26,10 @@ public function __construct(TaskInterface $tasks) /** * Store a newly active task in storage. * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response + * @param Request $request + * @return JsonResponse */ - public function store(Request $request) + public function store(Request $request): JsonResponse { $task = $this->tasks->activate($request->all()); @@ -39,9 +40,9 @@ public function store(Request $request) * Remove the specified resource from storage. * * @param int $id - * @return \Illuminate\Http\Response + * @return JsonResponse */ - public function destroy($id) + public function destroy(int $id): JsonResponse { $task = $this->tasks->deactivate($id); diff --git a/src/Http/Controllers/DashboardController.php b/src/Http/Controllers/DashboardController.php index 435bfe42..9f05db89 100644 --- a/src/Http/Controllers/DashboardController.php +++ b/src/Http/Controllers/DashboardController.php @@ -2,14 +2,16 @@ namespace Studio\Totem\Http\Controllers; +use Illuminate\Http\RedirectResponse; + class DashboardController extends Controller { /** * Single page application catch-all route. * - * @return \Illuminate\Http\Response + * @return RedirectResponse */ - public function index() + public function index(): RedirectResponse { return redirect()->route('totem.tasks.all'); } diff --git a/src/Http/Controllers/ExecuteTasksController.php b/src/Http/Controllers/ExecuteTasksController.php index 1b97e456..f353a78f 100644 --- a/src/Http/Controllers/ExecuteTasksController.php +++ b/src/Http/Controllers/ExecuteTasksController.php @@ -10,13 +10,15 @@ class ExecuteTasksController extends Controller /** * @var TaskInterface */ - private $tasks; + private TaskInterface $tasks; /** * @param TaskInterface $tasks */ public function __construct(TaskInterface $tasks) { + parent::__construct(); + $this->tasks = $tasks; } diff --git a/src/Http/Controllers/ExportTasksController.php b/src/Http/Controllers/ExportTasksController.php index b9e22972..4600c537 100644 --- a/src/Http/Controllers/ExportTasksController.php +++ b/src/Http/Controllers/ExportTasksController.php @@ -3,13 +3,14 @@ namespace Studio\Totem\Http\Controllers; use Studio\Totem\Contracts\TaskInterface; +use Symfony\Component\HttpFoundation\StreamedResponse; class ExportTasksController extends Controller { /** * @var TaskInterface */ - private $tasks; + private TaskInterface $tasks; /** * ExportTasksController constructor. @@ -26,9 +27,9 @@ public function __construct(TaskInterface $tasks) /** * Export all tasks to a json file. * - * @return \Symfony\Component\HttpFoundation\StreamedResponse + * @return StreamedResponse */ - public function index() + public function index(): StreamedResponse { $headers = [ 'Content-Type' => 'text/json', diff --git a/src/Http/Controllers/ImportTasksController.php b/src/Http/Controllers/ImportTasksController.php index 6bfa813b..7ba764f7 100644 --- a/src/Http/Controllers/ImportTasksController.php +++ b/src/Http/Controllers/ImportTasksController.php @@ -2,6 +2,7 @@ namespace Studio\Totem\Http\Controllers; +use Illuminate\Contracts\Filesystem\FileNotFoundException; use Studio\Totem\Contracts\TaskInterface; use Studio\Totem\Http\Requests\ImportRequest; @@ -10,7 +11,7 @@ class ImportTasksController extends Controller /** * @var TaskInterface */ - private $tasks; + private TaskInterface $tasks; /** * ImportTasksController constructor. @@ -27,9 +28,9 @@ public function __construct(TaskInterface $tasks) /** * Import tasks from a json file. * - * @param \Studio\Totem\Http\Requests\ImportRequest $request + * @param ImportRequest $request * - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * @throws FileNotFoundException */ public function index(ImportRequest $request) { diff --git a/src/Http/Controllers/TasksController.php b/src/Http/Controllers/TasksController.php index 960d1208..d6ab3057 100644 --- a/src/Http/Controllers/TasksController.php +++ b/src/Http/Controllers/TasksController.php @@ -2,7 +2,10 @@ namespace Studio\Totem\Http\Controllers; +use Illuminate\Contracts\View\Factory; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Http\RedirectResponse; +use Illuminate\View\View; use Studio\Totem\Contracts\TaskInterface; use Studio\Totem\Http\Requests\TaskRequest; use Studio\Totem\Task; @@ -13,7 +16,7 @@ class TasksController extends Controller /** * @var TaskInterface */ - private $tasks; + private TaskInterface $tasks; /** * TasksController constructor. @@ -30,9 +33,9 @@ public function __construct(TaskInterface $tasks) /** * Display a listing of the tasks. * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @return View */ - public function index() + public function index(): View { return view('totem::tasks.index', [ 'tasks' => $this->tasks @@ -53,9 +56,9 @@ public function index() /** * Show the form for creating a new task. * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @return View */ - public function create() + public function create(): View { $commands = Totem::getCommands()->map(function ($command) { return ['name' => $command->getName(), 'description' => $command->getDescription()]; @@ -73,9 +76,9 @@ public function create() * Store a newly created task in storage. * * @param TaskRequest $request - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function store(TaskRequest $request) + public function store(TaskRequest $request): RedirectResponse { $this->tasks->store($request->all()); @@ -87,8 +90,8 @@ public function store(TaskRequest $request) /** * Display the specified task. * - * @param $task - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @param Task $task + * @return Factory|View */ public function view(Task $task) { @@ -100,10 +103,10 @@ public function view(Task $task) /** * Show the form for editing the specified task. * - * @param $task - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @param Task $task + * @return View */ - public function edit(Task $task) + public function edit(Task $task): View { $commands = Totem::getCommands()->map(function ($command) { return ['name' => $command->getName(), 'description' => $command->getDescription()]; @@ -122,9 +125,9 @@ public function edit(Task $task) * * @param TaskRequest $request * @param $task - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function update(TaskRequest $request, Task $task) + public function update(TaskRequest $request, Task $task): RedirectResponse { $task = $this->tasks->update($request->all(), $task); @@ -136,8 +139,8 @@ public function update(TaskRequest $request, Task $task) /** * Remove the specified task from storage. * - * @param $task - * @return \Illuminate\Http\RedirectResponse + * @param Task $task + * @return RedirectResponse */ public function destroy(Task $task) { diff --git a/src/Http/Middleware/Authenticate.php b/src/Http/Middleware/Authenticate.php index 945221dc..2da5c375 100644 --- a/src/Http/Middleware/Authenticate.php +++ b/src/Http/Middleware/Authenticate.php @@ -2,6 +2,9 @@ namespace Studio\Totem\Http\Middleware; +use Closure; +use Illuminate\Http\Request; +use Illuminate\Http\Response; use Studio\Totem\Totem; class Authenticate @@ -9,9 +12,9 @@ class Authenticate /** * Handle the incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @return \Illuminate\Http\Response + * @param Request $request + * @param Closure $next + * @return Response */ public function handle($request, $next) { diff --git a/src/Http/Requests/ImportRequest.php b/src/Http/Requests/ImportRequest.php index c5ffd34d..3c9632d6 100644 --- a/src/Http/Requests/ImportRequest.php +++ b/src/Http/Requests/ImportRequest.php @@ -72,7 +72,7 @@ public function all($keys = null) * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ - public function validated() + public function validated($key = null, $default = null) { $content = ''; diff --git a/src/Listeners/BuildCache.php b/src/Listeners/BuildCache.php index 5ba060d3..6554733d 100644 --- a/src/Listeners/BuildCache.php +++ b/src/Listeners/BuildCache.php @@ -9,7 +9,7 @@ class BuildCache extends Listener /** * Handle the event. * - * @param \Studio\Totem\Events\Event $event + * @param Event $event */ public function handle(Event $event) { diff --git a/src/Listeners/BustCache.php b/src/Listeners/BustCache.php index 13abf5e0..1ec930a4 100644 --- a/src/Listeners/BustCache.php +++ b/src/Listeners/BustCache.php @@ -9,7 +9,7 @@ class BustCache extends Listener /** * Handle the event. * - * @param \Studio\Totem\Events\Event $event + * @param Event $event */ public function handle(Event $event) { diff --git a/src/Listeners/BustCacheImmediately.php b/src/Listeners/BustCacheImmediately.php index 79652a67..1cd63fd4 100644 --- a/src/Listeners/BustCacheImmediately.php +++ b/src/Listeners/BustCacheImmediately.php @@ -10,7 +10,7 @@ class BustCacheImmediately /** * @var Container */ - protected $app; + protected Container $app; /** * Create the event listener. @@ -25,7 +25,7 @@ public function __construct(Container $app) /** * Handle the event. * - * @param \Studio\Totem\Events\Event $event + * @param Event $event */ public function handle(Event $event) { diff --git a/src/Listeners/Listener.php b/src/Listeners/Listener.php index 52e685f4..6c899b20 100644 --- a/src/Listeners/Listener.php +++ b/src/Listeners/Listener.php @@ -11,12 +11,12 @@ class Listener implements ShouldQueue /** * @var TaskInterface. */ - protected $tasks; + protected TaskInterface $tasks; /** * @var Container */ - protected $app; + protected Container $app; /** * Create the event listener. diff --git a/src/Notifications/TaskCompleted.php b/src/Notifications/TaskCompleted.php index 84e2782a..1c244548 100644 --- a/src/Notifications/TaskCompleted.php +++ b/src/Notifications/TaskCompleted.php @@ -33,7 +33,7 @@ public function __construct($output) * @param mixed $notifiable * @return array */ - public function via($notifiable) + public function via(mixed $notifiable): array { $channels = []; if ($notifiable->notification_email_address) { @@ -53,9 +53,9 @@ public function via($notifiable) * Get the mail representation of the notification. * * @param mixed $notifiable - * @return \Illuminate\Notifications\Messages\MailMessage + * @return MailMessage */ - public function toMail($notifiable) + public function toMail(mixed $notifiable): MailMessage { return (new MailMessage) ->subject($notifiable->description) @@ -70,7 +70,7 @@ public function toMail($notifiable) * @param mixed $notifiable * @return NexmoMessage */ - public function toNexmo($notifiable) + public function toNexmo(mixed $notifiable): NexmoMessage { return (new NexmoMessage) ->content($notifiable->description.' just finished running.'); @@ -82,7 +82,7 @@ public function toNexmo($notifiable) * @param mixed $notifiable * @return SlackMessage */ - public function toSlack($notifiable) + public function toSlack(mixed $notifiable): SlackMessage { return (new SlackMessage) ->content(config('app.name')) diff --git a/src/Parameter.php b/src/Parameter.php index 87b30392..03d6511a 100644 --- a/src/Parameter.php +++ b/src/Parameter.php @@ -2,6 +2,8 @@ namespace Studio\Totem; +use Illuminate\Database\Eloquent\Relations\BelongsTo; + class Parameter extends TotemModel { protected $table = 'frequency_parameters'; @@ -12,7 +14,7 @@ class Parameter extends TotemModel 'value', ]; - public function task() + public function task(): BelongsTo { return $this->belongsTo(Frequency::class); } diff --git a/src/Repositories/EloquentTaskRepository.php b/src/Repositories/EloquentTaskRepository.php index bca6af65..bf2b3d82 100644 --- a/src/Repositories/EloquentTaskRepository.php +++ b/src/Repositories/EloquentTaskRepository.php @@ -3,6 +3,7 @@ namespace Studio\Totem\Repositories; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Cache; @@ -24,7 +25,7 @@ class EloquentTaskRepository implements TaskInterface /** * Return task eloquent builder. * - * @return Task + * @return Builder */ public function builder(): Builder { @@ -45,9 +46,9 @@ public function builder(): Builder * Find a task by id. * * @param int|Task $id - * @return int|Task + * @return Task|null */ - public function find($id) + public function find(Task|int $id) { if ($id instanceof Task) { return $id; @@ -61,9 +62,9 @@ public function find($id) /** * Find all tasks. * - * @return mixed + * @return Collection */ - public function findAll() + public function findAll(): Collection { return Cache::rememberForever('totem.tasks.all', function () { return Task::query()->with('frequencies')->get(); @@ -73,9 +74,9 @@ public function findAll() /** * Find all active tasks. * - * @return mixed + * @return Collection */ - public function findAllActive() + public function findAllActive(): Collection { return Cache::rememberForever('totem.tasks.active', function () { return $this->findAll()->filter(function ($task) { @@ -90,13 +91,11 @@ public function findAllActive() * @param array $input * @return bool|Task */ - public function store(array $input) + public function store(array $input): bool|Task { $task = new Task; - if (Creating::dispatch($input) === false) { - return false; - } + Creating::dispatch($input); $task->fill(Arr::only($input, $task->getFillable()))->save(); @@ -110,15 +109,13 @@ public function store(array $input) * * @param array $input * @param Task $task - * @return bool|int|Task + * @return Task */ - public function update(array $input, $task) + public function update(array $input, $task): Task { $task = $this->find($task); - if (Updating::dispatch($input, $task) === false) { - return false; - } + Updating::dispatch($input, $task); $task->fill(Arr::only($input, $task->getFillable()))->save(); @@ -133,7 +130,7 @@ public function update(array $input, $task) * @param int|Task $id * @return bool */ - public function destroy($id) + public function destroy(Task|int $id): bool { $task = $this->find($id); @@ -152,9 +149,9 @@ public function destroy($id) * Activate the given task. * * @param $input - * @return int|Task + * @return Task */ - public function activate($input) + public function activate($input): Task { $task = $this->find($input['task_id']); @@ -166,12 +163,12 @@ public function activate($input) } /** - * Deactive the given task. + * Deactivate the given task. * * @param $id - * @return int|Task + * @return Task */ - public function deactivate($id) + public function deactivate($id): Task { $task = $this->find($id); @@ -185,10 +182,10 @@ public function deactivate($id) /** * Execute a given task. * - * @param $id - * @return int|Task + * @param int|Task $id + * @return Task */ - public function execute($id) + public function execute(Task|int $id): Task { $task = $this->find($id); $start = microtime(true); @@ -208,9 +205,9 @@ public function execute($id) * Import tasks. * * @param $input - * @return bool|int|Task|void + * @return void */ - public function import($input) + public function import($input): void { Cache::forget('totem.tasks.all'); Cache::forget('totem.tasks.active'); diff --git a/src/Result.php b/src/Result.php index a163dbb4..ba39872d 100644 --- a/src/Result.php +++ b/src/Result.php @@ -4,6 +4,7 @@ use Database\Factories\TotemResultFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Query\Builder; use Illuminate\Support\Facades\DB; @@ -18,11 +19,11 @@ class Result extends TotemModel 'result', ]; - protected $dates = [ - 'ran_at', + protected $casts = [ + 'ran_at' => 'datetime', ]; - public function task() + public function task(): BelongsTo { return $this->belongsTo(Task::class); } @@ -50,11 +51,9 @@ public function getAverageRunTime(): Builder } /** - * Create a new factory instance for the model. - * - * @return \Illuminate\Database\Eloquent\Factories\Factory + * @return TotemResultFactory */ - protected static function newFactory() + protected static function newFactory(): TotemResultFactory { return TotemResultFactory::new(); } diff --git a/src/Task.php b/src/Task.php index 79bc536f..08eff582 100644 --- a/src/Task.php +++ b/src/Task.php @@ -5,7 +5,9 @@ use Carbon\Carbon; use Cron\CronExpression; use Database\Factories\TotemTaskFactory; +use Exception; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Str; use Studio\Totem\Traits\FrontendSortable; @@ -56,17 +58,19 @@ class Task extends TotemModel * * @return bool */ - public function getActivatedAttribute() + public function getActivatedAttribute(): bool { - return $this->is_active; + return $this->is_active ?? true; } /** * Upcoming Accessor. * * @return string + * + * @throws Exception */ - public function getUpcomingAttribute() + public function getUpcomingAttribute(): string { return CronExpression::factory($this->getCronExpression())->getNextRunDate()->format('Y-m-d H:i:s'); } @@ -77,7 +81,7 @@ public function getUpcomingAttribute() * @param bool $console if true will convert arguments to non associative array * @return array */ - public function compileParameters($console = false) + public function compileParameters(bool $console = false): array { if ($this->parameters) { $regex = '/(?=\S)[^\'"\s]*(?:\'[^\']*\'[^\'"\s]*|"[^"]*"[^\'"\s]*)*/'; @@ -130,9 +134,9 @@ public function compileParameters($console = false) /** * Results Relation. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function results() + public function results(): HasMany { return $this->hasMany(Result::class, 'task_id', 'id'); } @@ -140,9 +144,9 @@ public function results() /** * Returns the most recent result entry for this task. * - * @return Model|null + * @return Result|null */ - public function getLastResultAttribute() + public function getLastResultAttribute(): Result|null { return $this->results()->orderBy('id', 'desc')->first(); } @@ -150,7 +154,7 @@ public function getLastResultAttribute() /** * @return float */ - public function getAverageRuntimeAttribute() + public function getAverageRuntimeAttribute(): float { return $this->results()->avg('duration') ?? 0.00; } @@ -160,7 +164,7 @@ public function getAverageRuntimeAttribute() * * @return string */ - public function routeNotificationForMail() + public function routeNotificationForMail(): string { return $this->notification_email_address; } @@ -170,7 +174,7 @@ public function routeNotificationForMail() * * @return string */ - public function routeNotificationForNexmo() + public function routeNotificationForNexmo(): string { return $this->notification_phone_number; } @@ -180,7 +184,7 @@ public function routeNotificationForNexmo() * * @return string */ - public function routeNotificationForSlack() + public function routeNotificationForSlack(): string { return $this->notification_slack_webhook; } @@ -229,9 +233,9 @@ public function autoCleanup() /** * Create a new factory instance for the model. * - * @return \Illuminate\Database\Eloquent\Factories\Factory + * @return TotemTaskFactory */ - protected static function newFactory() + protected static function newFactory(): TotemTaskFactory { return TotemTaskFactory::new(); } diff --git a/src/Totem.php b/src/Totem.php index d03d3662..ab7fb709 100644 --- a/src/Totem.php +++ b/src/Totem.php @@ -3,6 +3,8 @@ namespace Studio\Totem; use Closure; +use Illuminate\Http\Request; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Schema; @@ -14,17 +16,17 @@ class Totem /** * The callback that should be used to authenticate Totem users. * - * @var \Closure + * @var Closure */ - public static $authUsing; + public static Closure $authUsing; /** * Determine if the given request can access the Totem dashboard. * - * @param \Illuminate\Http\Request $request + * @param Request|string|null $request * @return bool */ - public static function check($request) + public static function check($request): bool { return (static::$authUsing ?: function () { return app()->environment('local'); @@ -34,7 +36,7 @@ public static function check($request) /** * Set the callback that should be used to authenticate Totem users. * - * @param \Closure $callback + * @param Closure $callback * @return static */ public static function auth(Closure $callback) @@ -49,7 +51,7 @@ public static function auth(Closure $callback) * * @return array */ - public static function frequencies() + public static function frequencies(): array { return config('totem.frequencies'); } @@ -57,9 +59,9 @@ public static function frequencies() /** * Return collection of Artisan commands filtered if needed. * - * @return \Illuminate\Support\Collection + * @return Collection */ - public static function getCommands() + public static function getCommands(): Collection { $command_filter = config('totem.artisan.command_filter'); $whitelist = config('totem.artisan.whitelist', true); diff --git a/src/TotemModel.php b/src/TotemModel.php index dddd7ef2..1a285975 100644 --- a/src/TotemModel.php +++ b/src/TotemModel.php @@ -10,9 +10,9 @@ class TotemModel extends Model protected $connection = TOTEM_DATABASE_CONNECTION; /** - * @return mixed + * @return string */ - public function getTable() + public function getTable(): string { if (Str::contains(parent::getTable(), TOTEM_TABLE_PREFIX)) { return parent::getTable(); diff --git a/src/Traits/FrontendSortable.php b/src/Traits/FrontendSortable.php index 59823cf5..01339318 100644 --- a/src/Traits/FrontendSortable.php +++ b/src/Traits/FrontendSortable.php @@ -7,10 +7,10 @@ trait FrontendSortable { /** - * @param \Illuminate\Database\Eloquent\Builder $builder + * @param Builder $builder * @param array $sortableColumns * @param array $defaultSort - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ public function scopeSortableBy(Builder $builder, array $sortableColumns, array $defaultSort = ['name' => 'asc']): Builder { diff --git a/src/Traits/HasFrequencies.php b/src/Traits/HasFrequencies.php index 5cc6be43..a4f5b631 100644 --- a/src/Traits/HasFrequencies.php +++ b/src/Traits/HasFrequencies.php @@ -4,6 +4,9 @@ use Closure; use Illuminate\Console\Scheduling\ManagesFrequencies; +use Illuminate\Contracts\Filesystem\FileNotFoundException; +use Illuminate\Contracts\Foundation\Application; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Arr; use function json_decode; use function request; @@ -19,14 +22,14 @@ trait HasFrequencies * * @var array */ - protected $filters = []; + protected array $filters = []; /** * The array of reject callbacks. * * @var array */ - protected $rejects = []; + protected array $rejects = []; /** * Boot HasFrequencies Trait. @@ -85,9 +88,9 @@ public function beforeDelete() /** * Frequencies Relation. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function frequencies() + public function frequencies(): HasMany { return $this->hasMany(Frequency::class, 'task_id', 'id')->with('parameters'); } @@ -97,7 +100,7 @@ public function frequencies() * * @return string */ - public function getCronExpression() + public function getCronExpression(): string { if (! $this->expression) { $this->expression = '* * * * *'; @@ -119,10 +122,10 @@ public function getCronExpression() /** * Determine if the filters pass for the event. * - * @param \Illuminate\Contracts\Foundation\Application $app + * @param Application $app * @return bool */ - public function filtersPass($app) + public function filtersPass(Application $app): bool { foreach ($this->filters as $callback) { if (! $app->call($callback)) { @@ -142,10 +145,10 @@ public function filtersPass($app) /** * Register a callback to further filter the schedule. * - * @param \Closure $callback + * @param Closure $callback * @return $this */ - public function when(Closure $callback) + public function when(Closure $callback): static { $this->filters[] = $callback; @@ -159,7 +162,7 @@ public function when(Closure $callback) * @param string $endTime * @return $this */ - public function between($startTime, $endTime) + public function between($startTime, $endTime): static { return $this->when($this->inTimeInterval($startTime, $endTime)); } @@ -168,9 +171,9 @@ public function between($startTime, $endTime) * Process input data. If its an import action we must find out if the imported json has frequencies or not and * prepare data accordingly. * - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * @throws FileNotFoundException */ - private function processData() + private function processData(): array { $data = request()->all(); diff --git a/src/Traits/HasParameters.php b/src/Traits/HasParameters.php index bd0ee60e..682488e0 100644 --- a/src/Traits/HasParameters.php +++ b/src/Traits/HasParameters.php @@ -2,6 +2,8 @@ namespace Studio\Totem\Traits; +use Illuminate\Contracts\Filesystem\FileNotFoundException; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Arr; use Studio\Totem\Parameter; @@ -21,6 +23,9 @@ public static function bootHasParameters() }); } + /** + * @throws FileNotFoundException + */ public function afterSave() { $data = $this->processData(); @@ -42,9 +47,9 @@ public function beforeDelete() } /** - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return HasMany */ - public function parameters() + public function parameters(): HasMany { return $this->hasMany(Parameter::class); } @@ -53,9 +58,9 @@ public function parameters() * Process input data. If its an import action we must find out if the imported json has frequencies or not and * prepare data accordingly. * - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * @throws FileNotFoundException */ - private function processData() + private function processData(): array { $data = request()->all(); diff --git a/src/User.php b/src/User.php index 96f8f146..904b9a61 100644 --- a/src/User.php +++ b/src/User.php @@ -32,9 +32,9 @@ class User extends Authenticatable /** * Create a new factory instance for the model. * - * @return \Illuminate\Database\Eloquent\Factories\Factory + * @return TotemUserFactory */ - protected static function newFactory() + protected static function newFactory(): TotemUserFactory { return TotemUserFactory::new(); } diff --git a/tests/Feature/TaskExecutionTest.php b/tests/Feature/TaskExecutionTest.php index 7ea97aae..186a37ec 100644 --- a/tests/Feature/TaskExecutionTest.php +++ b/tests/Feature/TaskExecutionTest.php @@ -43,7 +43,8 @@ public function it_executes_a_scheduled_task() Event::fake(); - $this->get(route('totem.task.execute', $task->id)) + $this->signIn() + ->get(route('totem.task.execute', $task->id)) ->assertSuccessful(); $this->assertEquals(1, Result::count());