From 27b0f2961530a2f2c37609979908f9a568532e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Fri, 3 May 2024 19:32:35 +0200 Subject: [PATCH 1/2] Fix jolinotif executable in verbose mode when no driver is available --- CHANGELOG.md | 2 ++ jolinotif | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1af3ad6..2ab5c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Not released yet +* Fixed jolinotif executable in verbose mode when no driver is available + ## 2.7.0 (2024-05-03) * Added a new NotifierInterface and DefaultNotifier as the main public API of this package diff --git a/jolinotif b/jolinotif index 070a3ea..fcd9d81 100755 --- a/jolinotif +++ b/jolinotif @@ -199,7 +199,11 @@ $result = $notifier->send($notification); $driver = $notifier->getDriver(); if ($cli->hasOption('verbose')) { - $cli->log(sprintf('Notification %s with %s. ', $result ? 'successfully sent' : 'failed', str_replace('Joli\\JoliNotif\\Driver\\', '', $driver::class))); + if (!$driver) { + $cli->log('No driver available to display a notification on your system.'); + } else { + $cli->log(sprintf('Notification %s with %s. ', $result ? 'successfully sent' : 'failed', str_replace('Joli\\JoliNotif\\Driver\\', '', $driver::class))); + } } exit($result ? 0 : 1); From bd90f09f9173f4f82299a8f713079845e5c681e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Fri, 3 May 2024 19:51:53 +0200 Subject: [PATCH 2/2] Configure PHPStan to analyse executable and prevent passing option many times --- CHANGELOG.md | 1 + jolinotif | 54 +++++++++++++++++++++++++++++++++++++--------------- phpstan.neon | 1 + 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ab5c69..2f74319 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Not released yet * Fixed jolinotif executable in verbose mode when no driver is available +* Changed jolinotif executable to better handle option passed several times ## 2.7.0 (2024-05-03) diff --git a/jolinotif b/jolinotif index fcd9d81..6357443 100755 --- a/jolinotif +++ b/jolinotif @@ -61,15 +61,17 @@ final class Cli ], ]; - private $arguments = []; - private $command = []; + /** @var array */ + private array $arguments = []; + + private readonly string $command; public function __construct() { $this->command = $_SERVER['argv'][0]; } - public function parse() + public function parse(): void { $options = ''; $longOptions = array_map(function ($rule) { @@ -81,17 +83,33 @@ final class Cli $this->arguments = getopt($options, $longOptions) ?: []; } - public function getOption(string $name) + public function getOption(string $name): mixed { return $this->arguments[$name] ?: false; } - public function hasOption(string $name) + public function getStringOption(string $name): string + { + $option = $this->getOption($name); + + if (is_array($option)) { + throw new Exception("Option --{$name} can be specified only once."); + } + + if (!is_string($option) && !is_numeric($option)) { + // Probably not possible to reach this point + throw new Exception("Invalid type given for option --{$name}."); + } + + return (string) $option; + } + + public function hasOption(string $name): bool { return isset($this->arguments[$name]); } - public function validate() + public function validate(): bool { $valid = true; @@ -100,12 +118,17 @@ final class Cli $this->log("Please specify notification {$rule['name']} with the option --{$rule['name']}"); $valid = false; } + + if ($this->hasOption($rule['name']) && is_array($this->getOption($rule['name']))) { + $this->log("Option --{$rule['name']} can be specified only once."); + $valid = false; + } } return $valid; } - public function showUsage() + public function showUsage(): void { $required = []; $optional = []; @@ -141,12 +164,13 @@ final class Cli } } - public function log(string $message) + public function log(string $message): void { echo $message . PHP_EOL; } - private function formatUsage($name, $rule) + /** @param array{name: string, info: string, required: bool, flag?: bool} $rule */ + private function formatUsage(string $name, array $rule): string { $example = $rule['required'] ? " {$name}" : "=\"{$name}\""; $value = isset($rule['flag']) && $rule['flag'] ? '' : $example; @@ -176,23 +200,23 @@ if (!$cli->validate()) { $notifier = new DefaultNotifier(); $notification = (new Notification()) - ->setTitle($cli->getOption('title')) - ->setBody($cli->getOption('body')); + ->setTitle($cli->getStringOption('title')) + ->setBody($cli->getStringOption('body')); if ($cli->hasOption('icon')) { - $notification->setIcon($cli->getOption('icon')); + $notification->setIcon($cli->getStringOption('icon')); } if ($cli->hasOption('subtitle')) { - $notification->addOption('subtitle', $cli->getOption('subtitle')); + $notification->addOption('subtitle', $cli->getStringOption('subtitle')); } if ($cli->hasOption('sound')) { - $notification->addOption('sound', $cli->getOption('sound')); + $notification->addOption('sound', $cli->getStringOption('sound')); } if ($cli->hasOption('url')) { - $notification->addOption('url', $cli->getOption('url')); + $notification->addOption('url', $cli->getStringOption('url')); } $result = $notifier->send($notification); diff --git a/phpstan.neon b/phpstan.neon index aff038d..2f37c8a 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,6 +5,7 @@ parameters: level: 9 paths: - src + - jolinotif tmpDir: 'var/phpstan/tmp' inferPrivatePropertyTypeFromConstructor: true checkGenericClassInNonGenericObjectType: false