Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating Broadcasting code with PHP 8.1 features #680

Merged
merged 6 commits into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
.travis.yml export-ignore
phpunit.xml export-ignore
monorepo-builder.php export-ignore
.php-cs-fixer.dist.php export-ignore
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ jobs:

# Execution
- name: Check Coding Standards
run: vendor/bin/phpcs --standard=phpcs.xml
run: vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -vvv --dry-run --using-cache=no

#
# Execute unit tests on all valid PHP versions.
Expand Down
23 changes: 23 additions & 0 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

if (!file_exists(__DIR__.'/src')) {
exit(0);
}

return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
])
->setRiskyAllowed(true)
->setFinder(
(new PhpCsFixer\Finder())
->files()
->name('*.php')
->in(__DIR__ . '/src')
->append([__FILE__])
->notPath(['#/Fixtures/#', '#/tests/#', '#/views/#'])
)
->setCacheFile('.php-cs-fixer.cache')
;
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
"ramsey/uuid": "^4.2.3",
"ramsey/collection": "^1.2",
"rector/rector": "0.12.15",
"spiral/code-style": "^1.0",
"spiral/code-style": "^1.1",
"symfony/var-dumper": "^5.2|^6.0",
"symplify/monorepo-builder": "^10.0",
"vimeo/psalm": "4.21"
Expand Down
2 changes: 1 addition & 1 deletion monorepo-builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
'require-dev' => [
'phpunit/phpunit' => '^8.5|^9.5',
'mockery/mockery' => '^1.5',
'spiral/code-style' => '^1.0',
'spiral/code-style' => '^1.1',
'laminas/laminas-hydrator' => '^3.0|^4.0',
'symplify/monorepo-builder' => '^10.0',
'vimeo/psalm' => '^4.21',
Expand Down
7 changes: 4 additions & 3 deletions src/Broadcasting/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
}
],
"require": {
"php": ">=7.4",
"php": ">=8.1",
"psr/http-message": "^1.0",
"psr/http-server-middleware": "^1.0",
"psr/http-factory": "^1.0",
"psr/log": "1 - 3",
"spiral/core": "^2.14",
"spiral/config": "^2.14"
Expand All @@ -32,9 +33,9 @@
}
},
"require-dev": {
"spiral/boot": "^2.14",
"mockery/mockery": "^1.5",
"phpunit/phpunit": "^8.5|^9.5"
"phpunit/phpunit": "^9.5.5",
"spiral/boot": "^2.14"
},
"autoload-dev": {
"psr-4": {
Expand Down
46 changes: 4 additions & 42 deletions src/Broadcasting/src/AuthorizationStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,12 @@

final class AuthorizationStatus
{
private bool $success;
private array $topics;
private array $attributes;
private ?ResponseInterface $response;

public function __construct(
bool $success,
array $topics,
array $attributes = [],
?ResponseInterface $response = null
public readonly bool $success,
public readonly array $topics,
public readonly array $attributes = [],
public readonly ?ResponseInterface $response = null
) {
$this->success = $success;
$this->topics = $topics;
$this->attributes = $attributes;
$this->response = $response;
}

/**
* Check if authorization status is successful.
*/
public function isSuccessful(): bool
{
return $this->success;
}

/**
* Get list of authorized topics.
*/
public function getTopics(): array
{
return $this->topics;
}

public function getAttributes(): array
{
return $this->attributes;
}

/**
Expand All @@ -53,12 +23,4 @@ public function hasResponse(): bool
{
return $this->response !== null;
}

/**
* Get response object.
*/
public function getResponse(): ?ResponseInterface
{
return $this->response;
}
}
16 changes: 10 additions & 6 deletions src/Broadcasting/src/Bootloader/BroadcastingBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ final class BroadcastingBootloader extends Bootloader
TopicRegistryInterface::class => [self::class, 'initTopicRegistry'],
];

private ConfiguratorInterface $config;

public function __construct(ConfiguratorInterface $config)
{
$this->config = $config;
public function __construct(
private readonly ConfiguratorInterface $config
) {
}

public function registerDriverAlias(string $driverClass, string $alias): void
Expand All @@ -40,7 +38,7 @@ public function registerDriverAlias(string $driverClass, string $alias): void
);
}

public function boot(EnvironmentInterface $env): void
public function init(EnvironmentInterface $env): void
{
$this->initConfig($env);
}
Expand Down Expand Up @@ -69,11 +67,17 @@ private function initConfig(EnvironmentInterface $env): void
);
}

/**
* @noRector RemoveUnusedPrivateMethodRector
*/
private function initDefaultBroadcast(BroadcastManagerInterface $manager): BroadcastInterface
{
return $manager->connection();
}

/**
* @noRector RemoveUnusedPrivateMethodRector
*/
private function initTopicRegistry(BroadcastConfig $config): TopicRegistryInterface
{
return new TopicRegistry($config->getTopics());
Expand Down
2 changes: 1 addition & 1 deletion src/Broadcasting/src/Bootloader/WebsocketsBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class WebsocketsBootloader extends Bootloader implements SingletonInterfac
BroadcastingBootloader::class,
];

public function start(Container $container, HttpBootloader $http, BroadcastConfig $config): void
public function boot(Container $container, HttpBootloader $http, BroadcastConfig $config): void
{
$container->bindSingleton(AuthorizationMiddleware::class, static function (
BroadcastInterface $broadcast,
Expand Down
14 changes: 3 additions & 11 deletions src/Broadcasting/src/BroadcastInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
namespace Spiral\Broadcasting;

use Spiral\Broadcasting\Exception\BroadcastException;
use Stringable;

/**
* @psalm-type TopicsList = non-empty-list<string> | non-empty-list<Stringable> | string | Stringable
* @psalm-type MessagesList = non-empty-list<string> | non-empty-list<Stringable> | string | Stringable
* @psalm-type TopicsList = non-empty-list<string> | non-empty-list<\Stringable> | string | Stringable
* @psalm-type MessagesList = non-empty-list<string> | non-empty-list<\Stringable> | string | Stringable
*/
interface BroadcastInterface
{
Expand All @@ -23,16 +22,9 @@ interface BroadcastInterface
* $broadcast->publish(['topic 1', 'topic 2'], ['message 1', 'message 2']);
* </code>
*
* Note: In future major releases, the signature of this method will be
* changed to include follow type-hints.
*
* <code>
* public function publish(iterable|string|\Stringable $topics, iterable|string $messages): void;
* </code>
*
* @param TopicsList $topics
* @param MessagesList $messages
* @throws BroadcastException
*/
public function publish($topics, $messages): void;
public function publish(iterable|string|\Stringable $topics, iterable|string $messages): void;
}
10 changes: 3 additions & 7 deletions src/Broadcasting/src/BroadcastManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,18 @@

final class BroadcastManager implements BroadcastManagerInterface, SingletonInterface
{
private FactoryInterface $factory;
private BroadcastConfig $config;
/** @var BroadcastInterface[] */
private array $connections = [];

public function __construct(
FactoryInterface $factory,
BroadcastConfig $config
private readonly FactoryInterface $factory,
private readonly BroadcastConfig $config
) {
$this->factory = $factory;
$this->config = $config;
}

public function connection(?string $name = null): BroadcastInterface
{
$name = $name ?: $this->config->getDefaultConnection();
$name ??= $this->config->getDefaultConnection();

// Replaces alias with real storage name
$name = $this->config->getAliases()[$name] ?? $name;
Expand Down
4 changes: 2 additions & 2 deletions src/Broadcasting/src/Config/BroadcastConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ public function getConnectionConfig(string $name): array
{
if (!isset($this->config['connections'][$name])) {
throw new InvalidArgumentException(
sprintf('Config for connection `%s` is not defined.', $name)
\sprintf('Config for connection `%s` is not defined.', $name)
);
}

$config = $this->config['connections'][$name];

if (!isset($config['driver'])) {
throw new InvalidArgumentException(
sprintf('Driver for `%s` connection is not defined.', $name)
\sprintf('Driver for `%s` connection is not defined.', $name)
);
}

Expand Down
21 changes: 7 additions & 14 deletions src/Broadcasting/src/Driver/AbstractBroadcast.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,20 @@ abstract class AbstractBroadcast implements BroadcastInterface
*/
protected function formatTopics(array $topics): array
{
return array_map(function ($topic) {
return (string)$topic;
}, $topics);
return \array_map(fn (string|\Stringable $topic) => (string) $topic, $topics);
}

/**
* @template T of mixed
* @param iterable<T>|T $entries
* @return array<T>
*/
protected function toArray($entries): array
protected function toArray(iterable|string|\Stringable $entries): array
{
switch (true) {
case \is_array($entries):
return $entries;

case $entries instanceof \Traversable:
return \iterator_to_array($entries, false);

default:
return [$entries];
}
return match (true) {
\is_array($entries) => $entries,
$entries instanceof \Traversable => \iterator_to_array($entries, false),
default => [$entries],
};
}
}
17 changes: 7 additions & 10 deletions src/Broadcasting/src/Driver/LogBroadcast.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,19 @@

final class LogBroadcast extends AbstractBroadcast
{
private LoggerInterface $logger;
private string $level;

public function __construct(LoggerInterface $logger, string $level = LogLevel::INFO)
{
$this->logger = $logger;
$this->level = $level;
public function __construct(
private readonly LoggerInterface $logger,
private readonly string $level = LogLevel::INFO
) {
}

public function publish($topics, $messages): void
public function publish(iterable|string|\Stringable $topics, iterable|string $messages): void
{
$topics = implode(', ', $this->formatTopics($this->toArray($topics)));
$topics = \implode(', ', $this->formatTopics($this->toArray($topics)));

/** @var string $message */
foreach ($this->toArray($messages) as $message) {
assert(\is_string($message), 'Message argument must be a type of string');
\assert(\is_string($message), 'Message argument must be a type of string');
$this->logger->log($this->level, 'Broadcasting on channels [' . $topics . '] with payload: ' . $message);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Broadcasting/src/Driver/NullBroadcast.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

final class NullBroadcast implements BroadcastInterface
{
public function publish($topics, $messages): void
public function publish(iterable|string|\Stringable $topics, iterable|string $messages): void
{
// Do nothing
}
Expand Down
17 changes: 5 additions & 12 deletions src/Broadcasting/src/Middleware/AuthorizationMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,11 @@

final class AuthorizationMiddleware implements MiddlewareInterface
{
private ResponseFactoryInterface $responseFactory;
private BroadcastInterface $broadcast;
private ?string $authorizationPath;

public function __construct(
BroadcastInterface $broadcast,
ResponseFactoryInterface $responseFactory,
?string $authorizationPath = null
private readonly BroadcastInterface $broadcast,
private readonly ResponseFactoryInterface $responseFactory,
private readonly ?string $authorizationPath = null
) {
$this->responseFactory = $responseFactory;
$this->broadcast = $broadcast;
$this->authorizationPath = $authorizationPath;
}

public function process(
Expand All @@ -40,10 +33,10 @@ public function process(
$status = $this->broadcast->authorize($request);

if ($status->hasResponse()) {
return $status->getResponse();
return $status->response;
}

if (!$status->isSuccessful()) {
if (!$status->success) {
return $this->responseFactory->createResponse(403);
}
}
Expand Down
Loading