tests and linting
Some checks failed
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in -7s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in -16s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Failing after -3s
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in -4s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Successful in 6s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Successful in -41s

This commit is contained in:
2026-01-29 19:28:57 -05:00
parent e9cb49d942
commit 4ee830327e
20 changed files with 112 additions and 86 deletions

View File

@@ -10,5 +10,6 @@ return new LicenseConfigurationBuilder()
'BSD-2-Clause',
'BSD-3-Clause',
'Apache-2.0',
'LGPL-2.1-only'
)
->build();

View File

@@ -1,6 +1,16 @@
{
"name": "siteworxpro/app",
"type": "project",
"config": {
"optimize-autoloader": true,
"sort-packages": true,
"audit": {
"ignore": {
"PKSA-rkkf-636k-qjb3": "Dev only package",
"PKSA-z3gr-8qht-p93v": "Dev only package"
}
}
},
"autoload": {
"psr-4": {
"Siteworxpro\\App\\": "src/",
@@ -37,12 +47,13 @@
"phpmailer/phpmailer": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "^12.4",
"mockery/mockery": "^1.6",
"squizlabs/php_codesniffer": "^4.0",
"jetbrains/phpstorm-attributes": "^1.2",
"kwn/php-rdkafka-stubs": "^2.2",
"lendable/composer-license-checker": "^1.3.0",
"mockery/mockery": "^1.6",
"phpstan/phpstan": "^2.1.31",
"kwn/php-rdkafka-stubs": "^2.2"
"phpunit/phpunit": "^12.4",
"squizlabs/php_codesniffer": "^4.0"
},
"scripts": {
"tests:all": [

44
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4c2ae64539e4f6a700912cdc7d863493",
"content-hash": "3063e521174c3d0c51a4b8143aee7e85",
"packages": [
{
"name": "brick/math",
@@ -5739,6 +5739,48 @@
},
"time": "2025-04-30T06:54:44+00:00"
},
{
"name": "jetbrains/phpstorm-attributes",
"version": "1.2",
"source": {
"type": "git",
"url": "https://github.com/JetBrains/phpstorm-attributes.git",
"reference": "64de815a4509c29e00d5e3474087fd24c171afc2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JetBrains/phpstorm-attributes/zipball/64de815a4509c29e00d5e3474087fd24c171afc2",
"reference": "64de815a4509c29e00d5e3474087fd24c171afc2",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-4": {
"JetBrains\\PhpStorm\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "JetBrains",
"homepage": "https://www.jetbrains.com"
}
],
"description": "PhpStorm specific attributes",
"keywords": [
"attributes",
"jetbrains",
"phpstorm"
],
"support": {
"issues": "https://youtrack.jetbrains.com/newIssue?project=WI",
"source": "https://github.com/JetBrains/phpstorm-attributes/tree/1.2"
},
"time": "2024-10-11T10:46:19+00:00"
},
{
"name": "kwn/php-rdkafka-stubs",
"version": "v2.2.1",

View File

@@ -28,11 +28,11 @@ abstract class Command extends \Symfony\Component\Console\Command\Command implem
}
/**
* @param ClimateOutput|OutputInterface $output
* @param ArgvInput|InputInterface $input
* @param ClimateOutput $output
* @param ClimateOutput|ArgvInput $input
* @return Client | null
*/
protected function askForClient(ClimateOutput|OutputInterface $output, ArgvInput|InputInterface $input): ?Client
protected function askForClient(ClimateOutput $output, ClimateOutput|ArgvInput $input): ?Client
{
/** @var Collection<Client> $clients */
$clients = Client::whereJsonContains('grant_types', 'authorization_code')
@@ -60,8 +60,8 @@ abstract class Command extends \Symfony\Component\Console\Command\Command implem
protected function askForUser(
Client $client,
ClimateOutput|OutputInterface $output,
ArgvInput|InputInterface $input
ClimateOutput $output,
ClimateOutput|ArgvInput $input
): ?User {
$users = $client->users;

View File

@@ -14,7 +14,12 @@ interface CommandInterface
/**
* Execute the command.
*
* @param ArgvInput|ClimateOutput $input
* @param ClimateOutput $output
* @return int
*/
public function __invoke(InputInterface | ArgvInput $input, OutputInterface | ClimateOutput $output): int;
public function __invoke(
ClimateOutput|ArgvInput $input,
ClimateOutput $output
): int;
}

View File

@@ -9,6 +9,7 @@ use Siteworxpro\App\Cli\ClimateOutput;
use Siteworxpro\App\Cli\Commands\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
#[AsCommand('crypt:generate-key', 'Generate a new encryption key for the application')]
class GenerateKey extends Command

View File

@@ -11,6 +11,7 @@ use Siteworxpro\App\OAuth\Entities\Client;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Question\Question;
#[AsCommand(name: 'oauth:redirect-uri:create', description: 'Add a redirect URI to an existing OAuth client.')]

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Siteworxpro\App\Cli\Commands\OAuth;
use Siteworxpro\App\Cli\ClimateOutput;
use Siteworxpro\App\Cli\Commands\Command;
use Siteworxpro\App\OAuth\Entities\Scope;
use Symfony\Component\Console\Attribute\AsCommand;
@@ -22,7 +23,7 @@ class AddScope extends Command
->addArgument('description', InputArgument::OPTIONAL, 'The description of the scope');
}
public function __invoke(ArgvInput | InputInterface $input, $output): int
public function __invoke($input, $output): int
{
$name = $input->getArgument('name');
$description = $input->getArgument('description') ?? '';

View File

@@ -7,15 +7,13 @@ namespace Siteworxpro\App\Cli\Commands\OAuth;
use Siteworxpro\App\Cli\ClimateOutput;
use Siteworxpro\App\Cli\Commands\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
#[AsCommand(name: 'oauth:client:edit', description: 'Edit an OAuth client.')]
class ClientCapabilities extends Command
{
public function __invoke(ArgvInput|InputInterface $input, ClimateOutput|OutputInterface $output): int
public function __invoke($input, ClimateOutput|OutputInterface $output): int
{
$client = $this->askForClient($output, $input);

View File

@@ -22,11 +22,11 @@ class ListClients extends Command
}
/**
* @param ArgvInput|InputInterface $input
* @param ArgvInput|ClimateOutput|InputInterface $input
* @param ClimateOutput $output
* @return int
*/
public function __invoke(ArgvInput|InputInterface $input, $output): int
public function __invoke(ClimateOutput|ArgvInput|InputInterface $input, $output): int
{
if ($input->getArgument('client-id')) {
$client = Client::find($input->getArgument('client-id'));

View File

@@ -5,10 +5,13 @@ declare(strict_types=1);
namespace Siteworxpro\App\Cli\Commands\Queue;
use Siteworxpro\App\Async\Consumer;
use Siteworxpro\App\Cli\ClimateOutput;
use Siteworxpro\App\Cli\Commands\Command;
use Siteworxpro\App\Cli\Commands\CommandInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
#[AsCommand('queue:start', 'Start the queue consumer')]
class Start extends Command implements CommandInterface
@@ -23,7 +26,7 @@ class Start extends Command implements CommandInterface
);
}
public function __invoke($input, $output): int
public function __invoke(ClimateOutput|ArgvInput|InputInterface $input, $output): int
{
$queues = $input->getArgument('queues');

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Siteworxpro\App\Cli\Commands\User;
use Siteworxpro\App\Cli\ClimateOutput;
use Siteworxpro\App\Cli\Commands\Command;
use Siteworxpro\App\CommandBus\Commands\CreateUser;
use Siteworxpro\App\Models\ClientUser;
@@ -12,12 +13,14 @@ use Siteworxpro\App\Services\Facades\CommandBus;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command as SCommand;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Question\Question as QuestionInput;
#[AsCommand('user:add', 'Add a new user associated with an OAuth client')]
class Add extends Command
{
public function __invoke($input, $output): int
public function __invoke(ClimateOutput|ArgvInput|InputInterface $input, ClimateOutput $output): int
{
$client = $this->askForClient($output, $input);
if (!$client) {

View File

@@ -11,9 +11,7 @@ use Siteworxpro\App\Services\Facades\CommandBus;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question as QuestionInput;
#[AsCommand('user:reset-password', 'Reset a user\'s password')]
@@ -29,7 +27,12 @@ class ResetPassword extends Command
);
}
public function __invoke(ArgvInput|InputInterface $input, ClimateOutput|OutputInterface $output): int
/**
* @param ArgvInput|ClimateOutput $input
* @param ClimateOutput $output
* @return int
*/
public function __invoke(ClimateOutput|ArgvInput $input, ClimateOutput $output): int
{
$client = $this->askForClient($output, $input);

View File

@@ -8,7 +8,7 @@ readonly class CreateClient extends Command
{
/**
* @param string $clientName
* @param array<ClientGrant> $clientGrants
* @param array<ClientGrant | mixed> $clientGrants
* @param string $clientDescription
*/
public function __construct(

View File

@@ -14,7 +14,7 @@ class LoginFailed extends Listener
/**
* Handle the event.
*
* @param \Siteworxpro\App\Events\Login\LoginFailed $event
* @param string | \Siteworxpro\App\Events\Login\LoginFailed $event
* @param array $payload
* @return AuditLog|null
*/

View File

@@ -193,7 +193,7 @@ class Dispatcher implements DispatcherContract, Arrayable
/**
* Push an event to be dispatched later.
*
* @param $event
* @param mixed $event
* @param array $payload
* @return void
*/

View File

@@ -13,15 +13,19 @@ class Log implements DriverInterface
public function send(Message $message): bool
{
$logMessage = <<<'MSG'
===============================================
From: {$this->fromAddress}
To: {$message->getTo()}
Subject: {$message->getSubject()}
Body:
{$this->formatBodyForLog($message->getBody())}
===============================================
MSG;
$logMessage = sprintf(
"=================================" . PHP_EOL .
"Email sent via Log Driver" . PHP_EOL .
"From: %s" . PHP_EOL .
"To: %s" . PHP_EOL .
"Subject: %s" . PHP_EOL .
"Body: " . PHP_EOL . "%s" . PHP_EOL .
"=================================",
$this->fromAddress,
$message->getTo(),
$message->getSubject(),
$this->formatBodyForLog($message->getBody())
);
Logger::info($logMessage);

View File

@@ -13,12 +13,9 @@ class Smtp implements DriverInterface
{
private PHPMailer $mailer;
/**
* @throws Exception
*/
public function __construct()
{
$config = Config::get('mailer.smtp', []);
$config = Config::get('mailer.smtp');
if (empty($config['host']) || empty($config['port'])) {
throw new \InvalidArgumentException(
@@ -46,6 +43,9 @@ class Smtp implements DriverInterface
return true;
}
/**
* @throws Exception
*/
public function setFrom(string $address, string $name): void
{
$this->mailer->setFrom($address, $name, false);

View File

@@ -38,7 +38,7 @@ use Siteworxpro\App\OAuth\ScopeRepository;
* @property Collection $grant_types
* @property bool $confidential
*
* @property ClientCapabilities $capabilities
* @property ClientCapabilities | array $capabilities
* @property-read Collection<ClientRedirectUri> $clientRedirectUris
* @property-read Scope[]|Collection $scopes
* @property-read Collection<User> $users

View File

@@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Events\Listeners;
use Illuminate\Database\Events\ConnectionEstablished;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LogLevel;
use Siteworxpro\App\Events\EventListeners\Database\Connected;
use Siteworxpro\App\Log\Logger;
use Siteworxpro\Tests\Unit;
class ConnectedTest extends Unit
{
/**
* @throws ContainerExceptionInterface
* @throws \ReflectionException
* @throws NotFoundExceptionInterface
*/
protected function setUp(): void
{
parent::setUp();
$inputBuffer = fopen('php://memory', 'r+');
$logger = new Logger(LogLevel::DEBUG, $inputBuffer);
\Siteworxpro\App\Services\Facades\Logger::getFacadeContainer()->bind(Logger::class, fn() => $logger);
}
public function testHandlesEvent()
{
$this->expectNotToPerformAssertions();
$connectedEvent = $this->createMock(ConnectionEstablished::class);
$listener = new Connected();
$listener->__invoke($connectedEvent);
}
public function testThrowsException()
{
$this->expectException(\TypeError::class);
$listener = new Connected();
$listener->__invoke(new \stdClass());
}
}