Skip to content

Commit

Permalink
Code refactoring
Browse files Browse the repository at this point in the history
Fixes unit tests
  • Loading branch information
butschster committed Apr 27, 2024
1 parent 181d865 commit 75bfbe0
Show file tree
Hide file tree
Showing 37 changed files with 759 additions and 407 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ protoc-gen-php-grpc*
.phpunit.result.cache
.php-cs-fixer.cache
.deptrac.cache
.phpunit.cache
8 changes: 5 additions & 3 deletions app/config/queue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
use Spiral\RoadRunner\Jobs\Queue\MemoryCreateInfo;
use Spiral\RoadRunnerBridge\Queue\Queue;

$defaultConnection = env('QUEUE_DEFAULT_CONNECTION', 'roadrunner');

return [
'default' => env('QUEUE_CONNECTION', 'sync'),
'default' => env('QUEUE_CONNECTION', 'memory'),
'aliases' => [
'webhook' => 'roadrunner',
'events' => 'roadrunner',
'webhook' => $defaultConnection,
'events' => $defaultConnection,
],
'pipelines' => [
'memory' => [
Expand Down
3 changes: 3 additions & 0 deletions app/modules/Events/Domain/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
use App\Application\Domain\ValueObjects\Uuid;
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\Annotated\Annotation\Table\Index;

#[Entity(
repository: EventRepositoryInterface::class
)]
#[Index(columns: ['type'])]
#[Index(columns: ['project'])]
class Event
{
/** @internal */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private function listenEvent(ServerRequestInterface $request): ?EventType
|| $request->hasHeader('X-Inspector-Version')
|| \str_ends_with((string)$request->getUri(), 'inspector')
) {
return new EventType(type: 'profiler');
return new EventType(type: 'inspector');
}

return null;
Expand Down
15 changes: 2 additions & 13 deletions app/modules/Projects/Application/ProjectFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,12 @@

use Modules\Projects\Domain\Project;
use Modules\Projects\Domain\ProjectFactoryInterface;
use Modules\Projects\Exception\InvalidKeyFormatException;
use Modules\Projects\Domain\ValueObject\Key;

final readonly class ProjectFactory implements ProjectFactoryInterface
{
public function __construct(
private string $allowedKeyCharacters = 'a-z0-9-_',
) {
}

public function create(string $key, string $name): Project
public function create(Key $key, string $name): Project
{
if (\preg_match('/^[' . $this->allowedKeyCharacters . ']+$/', $key) !== 1) {
throw new InvalidKeyFormatException(
'Invalid project key. Key must contain only lowercase letters, numbers, hyphens and underscores.',
);
}

return new Project($key, $name);
}
}
3 changes: 2 additions & 1 deletion app/modules/Projects/Application/YamlFileProjectLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Modules\Projects\Domain\ProjectFactoryInterface;
use Modules\Projects\Domain\ProjectLocatorInterface;
use Modules\Projects\Domain\ValueObject\Key;
use Psr\Log\LoggerInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Yaml\Yaml;
Expand Down Expand Up @@ -36,7 +37,7 @@ public function findAll(): iterable
$this->validateData($data);

$project = $this->projectFactory->create(
key: $data['project']['key'],
key: Key::create($data['project']['key']),
name: $data['project']['name'],
);

Expand Down
8 changes: 4 additions & 4 deletions app/modules/Projects/Domain/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace Modules\Projects\Domain;

use App\Application\Domain\ValueObjects\Uuid;
use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Modules\Projects\Domain\ValueObject\Key;

#[Entity(
repository: ProjectRepositoryInterface::class
Expand All @@ -15,15 +15,15 @@ class Project
{
/** @internal */
public function __construct(
#[Column(type: 'string(36)', primary: true)]
private string $key,
#[Column(type: 'string(36)', primary: true, typecast: Key::class)]
private Key $key,

#[Column(type: 'string')]
private string $name,
) {
}

public function getKey(): string
public function getKey(): Key
{
return $this->key;
}
Expand Down
4 changes: 3 additions & 1 deletion app/modules/Projects/Domain/ProjectFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Modules\Projects\Domain;

use Modules\Projects\Domain\ValueObject\Key;

interface ProjectFactoryInterface
{
public function create(string $key, string $name): Project;
public function create(Key $key, string $name): Project;
}
69 changes: 69 additions & 0 deletions app/modules/Projects/Domain/ValueObject/Key.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types=1);

namespace Modules\Projects\Domain\ValueObject;

use App\Application\Domain\Assert;

final readonly class Key implements \JsonSerializable, \Stringable
{
public const MIN_LENGTH = 3;
public const MAX_LENGTH = 36;
public const ALLOWED_CHARACTERS = 'a-z0-9-_';

public static function create(string $key): self
{
Assert::notEmpty(
value: $key,
message: 'Project key is required.',
);

Assert::minLength(
value: $key,
min: self::MIN_LENGTH,
message: 'Invalid project key. Key must be at least 3 characters long.',
);

Assert::maxLength(
value: $key,
max: self::MAX_LENGTH,
message: 'Invalid project key. Key must be less than 36 characters long.',
);

Assert::regex(
value: $key,
pattern: '/^[' . self::ALLOWED_CHARACTERS . ']+$/',
message: 'Invalid project key. Key must contain only lowercase letters, numbers, hyphens and underscores.',
);

return new self($key);
}

/**
* @internal
* @private
*/
public function __construct(
public string $value,
) {
}

/**
* Create from data storage raw value
*/
final public static function typecast(mixed $value): self
{
return new self($value);
}

public function jsonSerialize(): string
{
return $this->value;
}

public function __toString(): string
{
return $this->value;
}
}
16 changes: 7 additions & 9 deletions app/modules/Sentry/Application/SecretKeyValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function __construct(

public function validateRequest(ServerRequestInterface $request): bool
{
if ($this->secret === null) {
if (empty($this->secret)) {
return true;
}

Expand All @@ -29,14 +29,12 @@ public function validateRequest(ServerRequestInterface $request): bool
return false;
}

$key = null;
$parts = \explode(',', $request->getHeaderLine('X-Sentry-Auth'));
foreach ($parts as $part) {
if (\str_starts_with($part, 'sentry_key=')) {
$key = \substr($part, 11);
break;
}
}
// Header: Sentry sentry_version=7, sentry_client=raven-php/0.15.0, sentry_key=1234567890
$key = \preg_match(
'/sentry_key=(\w+)/',
$request->getHeaderLine('X-Sentry-Auth'),
$matches,
) ? $matches[1] : null;

return $this->secret === $key;
}
Expand Down
20 changes: 14 additions & 6 deletions app/modules/Sentry/Interfaces/Http/JavascriptAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,22 @@
use Spiral\Boot\EnvironmentInterface;
use Spiral\Router\Annotation\Route;

final class JavascriptAction
final readonly class JavascriptAction
{
#[Route(route: '/sentry/<id>.js', name: 'sentry.js', methods: 'GET', group: 'api')]
public function __invoke(EnvironmentInterface $env, mixed $id): ResponseInterface
#[Route(route: '/sentry/<project>.js', name: 'sentry.js', methods: 'GET', group: 'api')]
public function __invoke(EnvironmentInterface $env, string $project): ResponseInterface
{
$jsSdkUrl = $env->get('SENTRY_JS_SDK_URL', 'https://browser.sentry-cdn.com/7.69.0/bundle.tracing.replay.min.js');
$host = $env->get('SENTRY_DSN_HOST', 'http://[email protected]:8000');
$url = \rtrim($host, '/') . '/' . $id;
$jsSdkUrl = $env->get(
'SENTRY_JS_SDK_URL',
'https://browser.sentry-cdn.com/7.69.0/bundle.tracing.replay.min.js',
);

$host = $env->get(
'SENTRY_JS_DSN_HOST',
'http://[email protected]:8000',
);

$url = \rtrim($host, '/') . '/' . $project;

return new Response(
status: 200,
Expand Down
11 changes: 6 additions & 5 deletions app/modules/Smtp/Application/Mail/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use ZBateson\MailMimeParser\Header\AddressHeader;
use ZBateson\MailMimeParser\Header\Part\AddressPart;
use ZBateson\MailMimeParser\Message as ParseMessage;
use ZBateson\MailMimeParser\Message\IMessagePart;

final readonly class Parser
{
Expand Down Expand Up @@ -51,20 +52,20 @@ public function parse(string $body, array $allRecipients = []): Message
$this->storage->bucket('attachments'),
$message->getHeader('Message - Id')?->getValue(),
$body, $from, $recipients, $ccs, $subject,
$html, $text, $replyTo, $allRecipients, $attachments
$html, $text, $replyTo, $allRecipients, $attachments,
);
}

/**
* @param MessagePart[] $attachments
* @param ParseMessage\IMessagePart[] $attachments
* @return Attachment[]
*/
private function buildAttachmentFrom(array $attachments): array
{
return \array_map(fn(MessagePart|ParseMessage\MimePart $part) => new Attachment(
return \array_map(fn(ParseMessage\IMessagePart $part) => new Attachment(
$part->getFilename(),
$part->getContent(),
$part->getContentType()
$part->getContentType(),
), $attachments);
}

Expand All @@ -74,7 +75,7 @@ private function buildAttachmentFrom(array $attachments): array
*/
private function joinNameAndEmail(array $addresses): array
{
return array_map(function (AddressPart $addressPart) {
return \array_map(function (AddressPart $addressPart) {
$name = $addressPart->getName();
$email = $addressPart->getValue();

Expand Down
9 changes: 5 additions & 4 deletions app/modules/VarDumper/Application/Dump/MessageParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Modules\VarDumper\Application\Dump;

use Modules\VarDumper\Exception\InvalidPayloadException;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Cloner\Stub;

Expand All @@ -12,13 +13,13 @@ final class MessageParser
/**
* @throws \RuntimeException
*/
public function parse(string $message): array
public function parse(string $message): ParsedPayload
{
$payload = @\unserialize(\base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]);

// Impossible to decode the message, give up.
if (false === $payload) {
throw new \RuntimeException("Unable to decode a message from var-dumper client.");
throw new InvalidPayloadException("Unable to decode the message.");
}

if (
Expand All @@ -27,9 +28,9 @@ public function parse(string $message): array
|| !$payload[0] instanceof Data
|| !\is_array($payload[1])
) {
throw new \RuntimeException("Invalid var-dumper payload.");
throw new InvalidPayloadException("Invalid payload structure.");
}

return $payload;
return new ParsedPayload(data: $payload[0], context: $payload[1]);
}
}
16 changes: 16 additions & 0 deletions app/modules/VarDumper/Application/Dump/ParsedPayload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Modules\VarDumper\Application\Dump;

use Symfony\Component\VarDumper\Cloner\Data;

final readonly class ParsedPayload
{
public function __construct(
public Data $data,
public array $context,
) {
}
}
10 changes: 10 additions & 0 deletions app/modules/VarDumper/Exception/InvalidPayloadException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Modules\VarDumper\Exception;

final class InvalidPayloadException extends VarDumperException
{

}
10 changes: 10 additions & 0 deletions app/modules/VarDumper/Exception/VarDumperException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Modules\VarDumper\Exception;

class VarDumperException extends \DomainException
{

}
Loading

0 comments on commit 75bfbe0

Please sign in to comment.