diff --git a/.travis.yml b/.travis.yml index c9591bd..f6df0a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ php: - '7.1' - '7.2' - '7.3' + - '7.4' - nightly env: diff --git a/README.md b/README.md index 9e101d6..f136ce2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ We assume you have a minimum knowledge of how Push Notifications work, otherwise * You have an eCommerce app: * Notify your customer their order has been shipped * Notify your category manager they sell a product - + ## Summary @@ -43,7 +43,7 @@ This bundle is just the back-end part of the subscription process. For the front PHP7.1+ is required. ```bash -composer require bentools/webpush-bundle 0.5.* +composer require bentools/webpush-bundle 0.6.* ``` If you're using Symfony 3, add the bundle to your kernel. With Symfony Flex, this should be done automatically. diff --git a/composer.json b/composer.json index bdbac33..ac4610d 100644 --- a/composer.json +++ b/composer.json @@ -16,22 +16,22 @@ "ext-mbstring": "*", "ext-openssl": "*", "guzzlehttp/guzzle": "~6.0", - "minishlink/web-push": "^4.0|^5.0", - "symfony/http-kernel": "^3.0|^4.0" + "minishlink/web-push": "~4.0|~5.0", + "symfony/http-kernel": "~3.0|~4.0|~5.0" }, "require-dev": { "bentools/doctrine-static": "1.0.x-dev", "doctrine/dbal": "~2.5", - "nyholm/symfony-bundle-test": "^1.4", - "phpunit/phpunit": "^5.0|^6.0|^7.0", - "symfony/config": "^4.0", - "symfony/dependency-injection": "^3.0|^4.0", - "symfony/framework-bundle": "^3.0|^4.0", - "symfony/http-foundation": "^3.0|^4.0", - "symfony/routing": "^3.0|^4.0", - "symfony/security": "^3.0|^4.0", - "symfony/var-dumper": "^3.0|^4.0", - "symfony/yaml": "^3.0|^4.0", + "nyholm/symfony-bundle-test": "~1.4", + "phpunit/phpunit": "~5.0|~6.0|~7.0", + "symfony/config": "~4.0", + "symfony/dependency-injection": "~3.0|~4.0|~5.0", + "symfony/framework-bundle": "~3.0|~4.0|~5.0", + "symfony/http-foundation": "~3.0|~4.0|~5.0", + "symfony/routing": "~3.0|~4.0|~5.0", + "symfony/security": "~3.0|~4.0|~5.0", + "symfony/var-dumper": "~3.0|~4.0|~5.0", + "symfony/yaml": "~3.0|~4.0|~5.0", "twig/twig": "~1.0|~2.0" }, "autoload": { diff --git a/src/Action/RegisterSubscriptionAction.php b/src/Action/RegisterSubscriptionAction.php index f64b240..2e132f7 100644 --- a/src/Action/RegisterSubscriptionAction.php +++ b/src/Action/RegisterSubscriptionAction.php @@ -5,6 +5,7 @@ use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionManagerRegistry; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\Security\Core\User\UserInterface; @@ -18,7 +19,6 @@ final class RegisterSubscriptionAction /** * RegisterSubscriptionAction constructor. - * @param UserSubscriptionManagerRegistry $registry */ public function __construct(UserSubscriptionManagerRegistry $registry) { @@ -26,10 +26,6 @@ public function __construct(UserSubscriptionManagerRegistry $registry) } /** - * @param UserInterface $user - * @param string $subscriptionHash - * @param array $subscription - * @param array $options * @throws \InvalidArgumentException * @throws \RuntimeException * @throws \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException @@ -44,8 +40,6 @@ private function subscribe(UserInterface $user, string $subscriptionHash, array } /** - * @param UserInterface $user - * @param string $subscriptionHash * @throws BadRequestHttpException * @throws \RuntimeException */ @@ -54,18 +48,16 @@ private function unsubscribe(UserInterface $user, string $subscriptionHash) $manager = $this->registry->getManager($user); $subscription = $manager->getUserSubscription($user, $subscriptionHash); if (null === $subscription) { - throw new BadRequestHttpException("Subscription hash not found"); + throw new BadRequestHttpException('Subscription hash not found'); } $manager->delete($subscription); } - /** - * @param Request $request - * @param UserInterface $user - * @return Response - */ - public function __invoke(Request $request, UserInterface $user): Response + public function __invoke(Request $request, UserInterface $user = null): Response { + if (null === $user) { + throw new AccessDeniedHttpException('Not authenticated.'); + } if (!in_array($request->getMethod(), ['POST', 'DELETE'])) { throw new MethodNotAllowedHttpException(['POST', 'DELETE']); diff --git a/src/Command/WebPushGenerateKeysCommand.php b/src/Command/WebPushGenerateKeysCommand.php index 433faaa..3a3ceeb 100644 --- a/src/Command/WebPushGenerateKeysCommand.php +++ b/src/Command/WebPushGenerateKeysCommand.php @@ -3,14 +3,16 @@ namespace BenTools\WebPushBundle\Command; use Minishlink\WebPush\VAPID; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\HttpKernel\Kernel; -final class WebPushGenerateKeysCommand extends ContainerAwareCommand +final class WebPushGenerateKeysCommand extends Command { + protected static $defaultName = 'webpush:generate:keys'; + /** * {@inheritdoc} */ @@ -24,7 +26,7 @@ protected function configure() /** * {@inheritdoc} */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); $keys = VAPID::createVapidKeys(); @@ -50,5 +52,7 @@ protected function execute(InputInterface $input, OutputInterface $output) private_key: '{$keys['privateKey']}' EOF ); + + return 0; } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 01802fd..65ad5c5 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -4,13 +4,19 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\HttpKernel\Kernel; class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder() { - $treeBuilder = new TreeBuilder(); - $rootNode = $treeBuilder->root('bentools_webpush'); + if (Kernel::MAJOR_VERSION < 4) { + $treeBuilder = new TreeBuilder(); + $rootNode = $treeBuilder->root('bentools_webpush'); + } else { + $treeBuilder = new TreeBuilder('bentools_webpush'); + $rootNode = $treeBuilder->getRootNode(); + } $rootNode ->children() diff --git a/src/DependencyInjection/WebPushCompilerPass.php b/src/DependencyInjection/WebPushCompilerPass.php index 8bb1c88..f10264f 100644 --- a/src/DependencyInjection/WebPushCompilerPass.php +++ b/src/DependencyInjection/WebPushCompilerPass.php @@ -9,7 +9,6 @@ final class WebPushCompilerPass implements CompilerPassInterface { - public function process(ContainerBuilder $container) { $registry = $container->getDefinition(UserSubscriptionManagerRegistry::class); diff --git a/src/DependencyInjection/WebPushExtension.php b/src/DependencyInjection/WebPushExtension.php index 45f13af..aa8189d 100644 --- a/src/DependencyInjection/WebPushExtension.php +++ b/src/DependencyInjection/WebPushExtension.php @@ -10,7 +10,7 @@ /** * This is the class that loads and manages your bundle configuration. * - * @link http://symfony.com/doc/current/cookbook/bundles/extension.html + * @see http://symfony.com/doc/current/cookbook/bundles/extension.html */ class WebPushExtension extends Extension { @@ -25,12 +25,12 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('bentools_webpush.vapid_subject', $config['settings']['subject'] ?? $container->getParameter('router.request_context.host')); $container->setParameter('bentools_webpush.vapid_public_key', $config['settings']['public_key'] ?? null); $container->setParameter('bentools_webpush.vapid_private_key', $config['settings']['private_key'] ?? null); - $loader = new XmlFileLoader($container, new FileLocator([__DIR__ . '/../Resources/config/'])); + $loader = new XmlFileLoader($container, new FileLocator([__DIR__.'/../Resources/config/'])); $loader->load('services.xml'); } /** - * @inheritDoc + * {@inheritdoc} */ public function getAlias() { diff --git a/src/Model/Message/PushMessage.php b/src/Model/Message/PushMessage.php index bb61403..f6126ca 100644 --- a/src/Model/Message/PushMessage.php +++ b/src/Model/Message/PushMessage.php @@ -6,18 +6,16 @@ * A message is an enveloppe that contain: * - An optional payload * - An optional array of options (like TTL, Topic, etc) - * - An optional array of authentication data (if different from the client) + * - An optional array of authentication data (if different from the client). */ final class PushMessage { - - private $payload, $options, $auth; + private $payload; + private $options; + private $auth; /** * PushMessage constructor. - * @param null|string $payload - * @param array $options - * @param array $auth */ public function __construct(?string $payload = null, array $options = [], array $auth = []) { @@ -26,46 +24,34 @@ public function __construct(?string $payload = null, array $options = [], array $this->auth = $auth; } - /** - * @param null|string $payload - */ public function setPayload(?string $payload): void { $this->payload = $payload; } - /** - * @return null|string - */ public function getPayload(): ?string { return $this->payload; } - /** - * @param int $ttl - */ public function setTTL(int $ttl): void { $this->options['TTL'] = $ttl; } - /** - * @param null|string $topic - */ public function setTopic(?string $topic): void { $this->options['topic'] = $topic; } /** - * @param null|string $urgency * @throws \InvalidArgumentException */ public function setUrgency(?string $urgency): void { if (null === $urgency) { unset($this->options['urgency']); + return; } @@ -76,9 +62,6 @@ public function setUrgency(?string $urgency): void $this->options['urgency'] = $urgency; } - /** - * @return array - */ public function getOptions(): array { return array_diff($this->options, array_filter($this->options, 'is_null')); @@ -89,9 +72,6 @@ public function getOption(string $key) return $this->options[$key] ?? null; } - /** - * @return array - */ public function getAuth(): array { return $this->auth; diff --git a/src/Model/Message/PushNotification.php b/src/Model/Message/PushNotification.php index 06bf8a9..b87ab76 100644 --- a/src/Model/Message/PushNotification.php +++ b/src/Model/Message/PushNotification.php @@ -7,7 +7,6 @@ final class PushNotification implements JsonSerializable, ArrayAccess { - const BODY = 'body'; const ICON = 'icon'; const IMAGE = 'image'; @@ -24,7 +23,7 @@ final class PushNotification implements JsonSerializable, ArrayAccess const TIMESTAMP = 'timestamp'; /** - * @var null|string + * @var string|null */ private $title; @@ -35,8 +34,6 @@ final class PushNotification implements JsonSerializable, ArrayAccess /** * PushNotification constructor. - * @param null|string $title - * @param array $options */ public function __construct(?string $title, array $options = []) { @@ -44,47 +41,34 @@ public function __construct(?string $title, array $options = []) $this->options = $options; } - /** - * @return null|string - */ public function getTitle(): ?string { return $this->title; } - - /** - * @param null|string $title - */ public function setTitle(?string $title): void { $this->title = $title; } - /** - * @return array - */ public function getOptions(): array { return $this->options; } - /** - * @param array $options - */ public function setOptions(array $options): void { $this->options = $options; } /** - * @param string $key * @param mixed $value */ public function setOption(string $key, $value): void { if (null === $value) { unset($this->options[$key]); + return; } @@ -96,45 +80,38 @@ public function getOption($key) return $this->options[$key] ?? null; } - /** - * @param array $options - * @param array $auth - * @return PushMessage - */ public function createMessage(array $options = [], array $auth = []): PushMessage { return new PushMessage((string) $this, $options, $auth); } - /** - * @return array - */ public function jsonSerialize(): array { return [ - 'title' => $this->title, + 'title' => $this->title, 'options' => array_diff($this->options, array_filter($this->options, 'is_null')), ]; } - /** - * @return string - */ public function __toString(): string { return (string) json_encode($this); } /** - * Whether a offset exists - * @link https://php.net/manual/en/arrayaccess.offsetexists.php + * Whether a offset exists. + * + * @see https://php.net/manual/en/arrayaccess.offsetexists.php + * * @param mixed $offset

- * An offset to check for. - *

- * @return boolean true on success or false on failure. - *

- *

- * The return value will be casted to boolean if non-boolean was returned. + * An offset to check for. + *

+ * + * @return bool true on success or false on failure. + *

+ *

+ * The return value will be casted to boolean if non-boolean was returned. + * * @since 5.0.0 */ public function offsetExists($offset) @@ -143,12 +120,16 @@ public function offsetExists($offset) } /** - * Offset to retrieve - * @link https://php.net/manual/en/arrayaccess.offsetget.php + * Offset to retrieve. + * + * @see https://php.net/manual/en/arrayaccess.offsetget.php + * * @param mixed $offset

- * The offset to retrieve. - *

- * @return mixed Can return all value types. + * The offset to retrieve. + *

+ * + * @return mixed can return all value types + * * @since 5.0.0 */ public function offsetGet($offset) @@ -157,15 +138,19 @@ public function offsetGet($offset) } /** - * Offset to set - * @link https://php.net/manual/en/arrayaccess.offsetset.php + * Offset to set. + * + * @see https://php.net/manual/en/arrayaccess.offsetset.php + * * @param mixed $offset

- * The offset to assign the value to. - *

- * @param mixed $value

- * The value to set. - *

+ * The offset to assign the value to. + *

+ * @param mixed $value

+ * The value to set. + *

+ * * @return void + * * @since 5.0.0 */ public function offsetSet($offset, $value) @@ -174,12 +159,16 @@ public function offsetSet($offset, $value) } /** - * Offset to unset - * @link https://php.net/manual/en/arrayaccess.offsetunset.php + * Offset to unset. + * + * @see https://php.net/manual/en/arrayaccess.offsetunset.php + * * @param mixed $offset

- * The offset to unset. - *

+ * The offset to unset. + *

+ * * @return void + * * @since 5.0.0 */ public function offsetUnset($offset) diff --git a/src/Model/Response/PushResponse.php b/src/Model/Response/PushResponse.php index 09dc499..a3aeb26 100644 --- a/src/Model/Response/PushResponse.php +++ b/src/Model/Response/PushResponse.php @@ -25,8 +25,6 @@ final class PushResponse /** * WebPushResponse constructor. - * @param UserSubscriptionInterface $subscription - * @param int $statusCode */ public function __construct(UserSubscriptionInterface $subscription, int $statusCode) { @@ -34,33 +32,21 @@ public function __construct(UserSubscriptionInterface $subscription, int $status $this->statusCode = $statusCode; } - /** - * @return UserSubscriptionInterface - */ public function getSubscription(): UserSubscriptionInterface { return $this->subscription; } - /** - * @return int - */ public function getStatusCode(): int { return $this->statusCode; } - /** - * @return bool - */ public function isExpired(): bool { return in_array($this->statusCode, [self::NOT_FOUND, self::GONE]); } - /** - * @return bool - */ public function isSuccessFul(): bool { return self::SUCCESS === $this->statusCode; diff --git a/src/Model/Subscription/UserSubscriptionInterface.php b/src/Model/Subscription/UserSubscriptionInterface.php index 92c449e..77ef6dd 100644 --- a/src/Model/Subscription/UserSubscriptionInterface.php +++ b/src/Model/Subscription/UserSubscriptionInterface.php @@ -6,46 +6,33 @@ interface UserSubscriptionInterface { - /** * Return the user associated to this subscription. - * - * @return UserInterface */ public function getUser(): UserInterface; /** * Return the hash of this subscription. Can be a fingerprint or a cookie. - * - * @return string */ public function getSubscriptionHash(): string; /** * Return the subscriber's HTTP endpoint. - * - * @return string */ public function getEndpoint(): string; /** * Return the subscriber's public key. - * - * @return string */ public function getPublicKey(): string; /** * Return the subscriber auth token. - * - * @return string */ public function getAuthToken(): string; /** * Content-encoding (default: aesgcm). - * - * @return string */ public function getContentEncoding(): string; } diff --git a/src/Model/Subscription/UserSubscriptionManagerInterface.php b/src/Model/Subscription/UserSubscriptionManagerInterface.php index 66a6156..307e457 100644 --- a/src/Model/Subscription/UserSubscriptionManagerInterface.php +++ b/src/Model/Subscription/UserSubscriptionManagerInterface.php @@ -6,42 +6,26 @@ interface UserSubscriptionManagerInterface { - /** * Create a user/subscription association. - * - * @param UserInterface $user - * @param string $subscriptionHash - * @param array $subscription - * @param array $options - * @return UserSubscriptionInterface */ public function factory(UserInterface $user, string $subscriptionHash, array $subscription, array $options = []): UserSubscriptionInterface; /** * Return a string representation of the subscription's endpoint. * Example: md5($endpoint). - * - * @param string $endpoint - * @param UserInterface $user - * @return string */ public function hash(string $endpoint, UserInterface $user): string; /** * Return the subscription attached to this user. - * - * @param UserInterface $user - * @param string $subscriptionHash - * @return UserSubscriptionInterface|null */ public function getUserSubscription(UserInterface $user, string $subscriptionHash): ?UserSubscriptionInterface; /** * Return the list of known subscriptions for this user. - * A user can have several subscriptions (on chrome, firefox, etc.) + * A user can have several subscriptions (on chrome, firefox, etc.). * - * @param UserInterface $user * @return iterable|UserSubscriptionInterface[] */ public function findByUser(UserInterface $user): iterable; @@ -49,23 +33,16 @@ public function findByUser(UserInterface $user): iterable; /** * Return the list of known subscriptions for this hash. * Several users can share the same hash. - * - * @param string $subscriptionHash - * @return iterable */ public function findByHash(string $subscriptionHash): iterable; /** * Store the user/subscription association. - * - * @param UserSubscriptionInterface $userSubscription */ public function save(UserSubscriptionInterface $userSubscription): void; /** * Remove the user/subscription association. - * - * @param UserSubscriptionInterface $userSubscription */ public function delete(UserSubscriptionInterface $userSubscription): void; } diff --git a/src/Model/Subscription/UserSubscriptionManagerRegistry.php b/src/Model/Subscription/UserSubscriptionManagerRegistry.php index d4f174e..b507c9f 100644 --- a/src/Model/Subscription/UserSubscriptionManagerRegistry.php +++ b/src/Model/Subscription/UserSubscriptionManagerRegistry.php @@ -15,8 +15,6 @@ final class UserSubscriptionManagerRegistry implements UserSubscriptionManagerIn private $registry = []; /** - * @param string $userClass - * @param UserSubscriptionManagerInterface $userSubscriptionManager * @throws \InvalidArgumentException */ public function register(string $userClass, UserSubscriptionManagerInterface $userSubscriptionManager) @@ -38,7 +36,7 @@ public function register(string $userClass, UserSubscriptionManagerInterface $us /** * @param UserInterface|string $userClass - * @return UserSubscriptionManagerInterface + * * @throws RuntimeException * @throws ServiceNotFoundException * @throws \InvalidArgumentException @@ -47,13 +45,7 @@ public function register(string $userClass, UserSubscriptionManagerInterface $us public function getManager($userClass): UserSubscriptionManagerInterface { if (!is_a($userClass, UserInterface::class, true)) { - throw new \InvalidArgumentException( - sprintf( - 'Expected class or object that implements %s, %s given', - UserInterface::class, - is_object($userClass) ? get_class($userClass) : gettype($userClass) - ) - ); + throw new \InvalidArgumentException(sprintf('Expected class or object that implements %s, %s given', UserInterface::class, is_object($userClass) ? get_class($userClass) : gettype($userClass))); } if (is_object($userClass)) { @@ -73,7 +65,7 @@ public function getManager($userClass): UserSubscriptionManagerInterface } /** - * @inheritDoc + * {@inheritdoc} */ public function factory(UserInterface $user, string $subscriptionHash, array $subscription, array $options = []): UserSubscriptionInterface { @@ -81,7 +73,7 @@ public function factory(UserInterface $user, string $subscriptionHash, array $su } /** - * @inheritDoc + * {@inheritdoc} */ public function hash(string $endpoint, UserInterface $user): string { @@ -89,7 +81,7 @@ public function hash(string $endpoint, UserInterface $user): string } /** - * @inheritDoc + * {@inheritdoc} */ public function getUserSubscription(UserInterface $user, string $subscriptionHash): ?UserSubscriptionInterface { @@ -97,7 +89,7 @@ public function getUserSubscription(UserInterface $user, string $subscriptionHas } /** - * @inheritDoc + * {@inheritdoc} */ public function findByUser(UserInterface $user): iterable { @@ -105,7 +97,7 @@ public function findByUser(UserInterface $user): iterable } /** - * @inheritDoc + * {@inheritdoc} */ public function findByHash(string $subscriptionHash): iterable { @@ -117,7 +109,7 @@ public function findByHash(string $subscriptionHash): iterable } /** - * @inheritDoc + * {@inheritdoc} */ public function save(UserSubscriptionInterface $userSubscription): void { @@ -125,7 +117,7 @@ public function save(UserSubscriptionInterface $userSubscription): void } /** - * @inheritDoc + * {@inheritdoc} */ public function delete(UserSubscriptionInterface $userSubscription): void { diff --git a/src/Sender/NullPushMessageSender.php b/src/Sender/NullPushMessageSender.php index 2e04418..5d17afe 100644 --- a/src/Sender/NullPushMessageSender.php +++ b/src/Sender/NullPushMessageSender.php @@ -9,7 +9,7 @@ final class NullPushMessageSender implements PushMessagerSenderInterface /** * Does nothing. * - * @inheritDoc + * {@inheritdoc} */ public function push(PushMessage $message, iterable $subscriptions): iterable { diff --git a/src/Sender/PushMessageSender.php b/src/Sender/PushMessageSender.php index 7c0e66d..c98478b 100644 --- a/src/Sender/PushMessageSender.php +++ b/src/Sender/PushMessageSender.php @@ -3,8 +3,8 @@ namespace BenTools\WebPushBundle\Sender; use BenTools\WebPushBundle\Model\Message\PushMessage; -use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface; use BenTools\WebPushBundle\Model\Response\PushResponse; +use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface; use GuzzleHttp\Client; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\RequestException; @@ -42,16 +42,12 @@ class PushMessageSender implements PushMessagerSenderInterface /** * PushMessageSender constructor. - * @param array $auth - * @param array $defaultOptions - * @param ClientInterface|null $client */ public function __construct( array $auth = [], array $defaultOptions = [], ClientInterface $client = null ) { - if (isset($auth['VAPID'])) { $auth['VAPID']['validated'] = false; } @@ -62,9 +58,8 @@ public function __construct( } /** - * @param PushMessage $message - * @param iterable $subscriptions * @return PushResponse[] + * * @throws \ErrorException * @throws \InvalidArgumentException * @throws \LogicException @@ -100,7 +95,6 @@ public function push(PushMessage $message, iterable $subscriptions): iterable return new PushResponse($subscription, $response->getStatusCode()); }) ->otherwise(function (\Throwable $reason) use ($subscription) { - if ($reason instanceof RequestException && $reason->hasResponse()) { return new PushResponse($subscription, $reason->getResponse()->getStatusCode()); } @@ -121,12 +115,9 @@ public function push(PushMessage $message, iterable $subscriptions): iterable return $promise->wait(); } - /** - * @return bool - */ public function isAutomaticPadding(): bool { - return $this->maxPaddingLength !== 0; + return 0 !== $this->maxPaddingLength; } /** @@ -140,8 +131,6 @@ public function getMaxPaddingLength() /** * @param int|bool $maxPaddingLength Max padding length * - * @return self - * * @throws \Exception */ public function setMaxPaddingLength($maxPaddingLength): self @@ -150,9 +139,9 @@ public function setMaxPaddingLength($maxPaddingLength): self throw new \Exception('Automatic padding is too large. Max is '.Encryption::MAX_PAYLOAD_LENGTH.'. Recommended max is '.Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH.' for compatibility reasons (see README).'); } elseif ($maxPaddingLength < 0) { throw new \Exception('Padding length should be positive or zero.'); - } elseif ($maxPaddingLength === true) { + } elseif (true === $maxPaddingLength) { $this->maxPaddingLength = Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH; - } elseif ($maxPaddingLength === false) { + } elseif (false === $maxPaddingLength) { $this->maxPaddingLength = 0; } else { $this->maxPaddingLength = $maxPaddingLength; @@ -161,9 +150,6 @@ public function setMaxPaddingLength($maxPaddingLength): self return $this; } - /** - * @return array - */ public function getDefaultOptions(): array { return $this->defaultOptions; diff --git a/src/Sender/PushMessagerSenderInterface.php b/src/Sender/PushMessagerSenderInterface.php index e3d268c..de3adc6 100644 --- a/src/Sender/PushMessagerSenderInterface.php +++ b/src/Sender/PushMessagerSenderInterface.php @@ -3,8 +3,8 @@ namespace BenTools\WebPushBundle\Sender; use BenTools\WebPushBundle\Model\Message\PushMessage; -use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface; use BenTools\WebPushBundle\Model\Response\PushResponse; +use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface; interface PushMessagerSenderInterface { @@ -12,8 +12,8 @@ interface PushMessagerSenderInterface * Push a notification. * The implementation MUST adapt the payload with proper padding, etc. * - * @param PushMessage $message * @param UserSubscriptionInterface[] $subscriptions + * * @return PushResponse[] */ public function push(PushMessage $message, iterable $subscriptions): iterable; diff --git a/src/Sender/RequestBuilder.php b/src/Sender/RequestBuilder.php index cedfb73..3ff45ae 100644 --- a/src/Sender/RequestBuilder.php +++ b/src/Sender/RequestBuilder.php @@ -6,23 +6,20 @@ use BenTools\WebPushBundle\Model\Message\PushMessage; use BenTools\WebPushBundle\Model\Subscription\UserSubscriptionInterface; use GuzzleHttp\Psr7\Request; +use function GuzzleHttp\Psr7\stream_for; use GuzzleHttp\Psr7\Uri; use Minishlink\WebPush\Encryption; use Minishlink\WebPush\Utils; use Minishlink\WebPush\VAPID; use Psr\Http\Message\RequestInterface; -use function GuzzleHttp\Psr7\stream_for; final class RequestBuilder { private const FCM_BASE_URL = 'https://fcm.googleapis.com'; /** - * @param PushMessage $message - * @param UserSubscriptionInterface $subscription - * @param int $ttl - * @param int $maxPaddingLength - * @return RequestInterface + * @param int $maxPaddingLength + * * @throws \ErrorException * @throws \InvalidArgumentException */ @@ -36,13 +33,11 @@ public function createRequest( $request = $this->withOptionalHeaders($request, $message); $request = $request->withHeader('TTL', $ttl); - if (null !== $message->getPayload() && null !== $subscription->getPublicKey() && null !== $subscription->getAuthToken()) { $request = $request ->withHeader('Content-Type', 'application/octet-stream') ->withHeader('Content-Encoding', $subscription->getContentEncoding()); - $payload = $this->getNormalizedPayload($message->getPayload(), $subscription->getContentEncoding(), $maxPaddingLength); $encrypted = Encryption::encrypt( @@ -53,39 +48,33 @@ public function createRequest( ); if ('aesgcm' === $subscription->getContentEncoding()) { - $request = $request->withHeader('Encryption', 'salt=' . Base64Url::encode($encrypted['salt'])) - ->withHeader('Crypto-Key', 'dh=' . Base64Url::encode($encrypted['localPublicKey'])); + $request = $request->withHeader('Encryption', 'salt='.Base64Url::encode($encrypted['salt'])) + ->withHeader('Crypto-Key', 'dh='.Base64Url::encode($encrypted['localPublicKey'])); } $encryptionContentCodingHeader = Encryption::getContentCodingHeader($encrypted['salt'], $encrypted['localPublicKey'], $subscription->getContentEncoding()); - $content = $encryptionContentCodingHeader . $encrypted['cipherText']; + $content = $encryptionContentCodingHeader.$encrypted['cipherText']; return $request ->withBody(stream_for($content)) ->withHeader('Content-Length', Utils::safeStrlen($content)); } - return $request ->withHeader('Content-Length', 0); } /** - * @param RequestInterface $request - * @param array $vapid - * @param UserSubscriptionInterface $subscription - * @return RequestInterface * @throws \ErrorException * @throws \InvalidArgumentException */ public function withVAPIDAuthentication(RequestInterface $request, array $vapid, UserSubscriptionInterface $subscription): RequestInterface { - $endpoint = $subscription->getEndpoint(); - $audience = parse_url($endpoint, PHP_URL_SCHEME) . '://' . parse_url($endpoint, PHP_URL_HOST); + $audience = parse_url($endpoint, PHP_URL_SCHEME).'://'.parse_url($endpoint, PHP_URL_HOST); if (!parse_url($audience)) { - throw new \ErrorException('Audience "' . $audience . '"" could not be generated.'); + throw new \ErrorException('Audience "'.$audience.'"" could not be generated.'); } $vapidHeaders = VAPID::getVapidHeaders($audience, $vapid['subject'], $vapid['publicKey'], $vapid['privateKey'], $subscription->getContentEncoding()); @@ -94,12 +83,12 @@ public function withVAPIDAuthentication(RequestInterface $request, array $vapid, if ('aesgcm' === $subscription->getContentEncoding()) { if ($request->hasHeader('Crypto-Key')) { - $request = $request->withHeader('Crypto-Key', $request->getHeaderLine('Crypto-Key') . ';' . $vapidHeaders['Crypto-Key']); + $request = $request->withHeader('Crypto-Key', $request->getHeaderLine('Crypto-Key').';'.$vapidHeaders['Crypto-Key']); } else { $headers['Crypto-Key'] = $vapidHeaders['Crypto-Key']; $request->withHeader('Crypto-Key', $vapidHeaders['Crypto-Key']); } - } else if ('aes128gcm' === $subscription->getContentEncoding() && substr($endpoint, 0, strlen(self::FCM_BASE_URL)) === self::FCM_BASE_URL) { + } elseif ('aes128gcm' === $subscription->getContentEncoding() && self::FCM_BASE_URL === substr($endpoint, 0, strlen(self::FCM_BASE_URL))) { $request = $request->withUri(new Uri(str_replace('fcm/send', 'wp', $endpoint))); } @@ -107,20 +96,14 @@ public function withVAPIDAuthentication(RequestInterface $request, array $vapid, } /** - * @param RequestInterface $request - * @param string $apiKey - * @return RequestInterface * @throws \InvalidArgumentException */ public function withGCMAuthentication(RequestInterface $request, string $apiKey): RequestInterface { - return $request->withHeader('Authorization', 'key=' . $apiKey); + return $request->withHeader('Authorization', 'key='.$apiKey); } /** - * @param RequestInterface $request - * @param PushMessage $message - * @return RequestInterface * @throws \InvalidArgumentException */ private function withOptionalHeaders(RequestInterface $request, PushMessage $message): RequestInterface @@ -135,10 +118,8 @@ private function withOptionalHeaders(RequestInterface $request, PushMessage $mes } /** - * @param null|string $payload - * @param string $contentEncoding - * @param mixed $automaticPadding - * @return null|string + * @param mixed $automaticPadding + * * @throws \ErrorException */ private function getNormalizedPayload(?string $payload, string $contentEncoding, $automaticPadding): ?string @@ -147,7 +128,7 @@ private function getNormalizedPayload(?string $payload, string $contentEncoding, return null; } if (Utils::safeStrlen($payload) > Encryption::MAX_PAYLOAD_LENGTH) { - throw new \ErrorException('Size of payload must not be greater than ' . Encryption::MAX_PAYLOAD_LENGTH . ' bytes.'); + throw new \ErrorException('Size of payload must not be greater than '.Encryption::MAX_PAYLOAD_LENGTH.' bytes.'); } return Encryption::padPayload($payload, $automaticPadding, $contentEncoding); diff --git a/src/Twig/WebPushTwigExtension.php b/src/Twig/WebPushTwigExtension.php index 019d294..65957ab 100644 --- a/src/Twig/WebPushTwigExtension.php +++ b/src/Twig/WebPushTwigExtension.php @@ -18,9 +18,9 @@ public function __construct(?string $publicKey) } /** - * @inheritDoc + * {@inheritdoc} */ - public function getGlobals() + public function getGlobals(): array { return [ 'bentools_webpush' => [ diff --git a/src/WebPushBundle.php b/src/WebPushBundle.php index efc59df..70147e6 100644 --- a/src/WebPushBundle.php +++ b/src/WebPushBundle.php @@ -10,7 +10,7 @@ class WebPushBundle extends Bundle { /** - * @inheritDoc + * {@inheritdoc} */ public function getContainerExtension() {