diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..31c5f8e --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,21 @@ +name: PHPStan + +on: [push, pull_request] + +jobs: + phpstan: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@2.26.0 + with: + php-version: '8.1' + + - name: Install composer dependencies + uses: ramsey/composer-install@v2 + + - name: Run PHPStan + run: vendor/bin/phpstan --error-format=github diff --git a/.gitignore b/.gitignore index 4a6e97a..067c442 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,6 @@ npm-debug.log /log package-lock.json -yarn.lock \ No newline at end of file +yarn.lock + +build diff --git a/README.md b/README.md index d67a58c..80fd7c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Telegram Git Notifier -This package provides the ability to integrate the Telegram messaging service and GitHub/GitLab. +This package provides the ability to integrate the Telegram messaging service and GitHub and GitLab. With this package, you can create a Telegram bot to receive notifications from GitHub or GitLab events and manage customization through messages and buttons on Telegram. @@ -18,7 +18,7 @@ and manage customization through messages and buttons on Telegram. ## 📋 Requirements -- PHP ^8.0 +- PHP ^8.1 - Composer - Telegram Bot diff --git a/common/helpers.php b/common/helpers.php index 90119f6..ba9a497 100755 --- a/common/helpers.php +++ b/common/helpers.php @@ -124,10 +124,11 @@ function config(string $string): mixed * @param string $partialPath * @param array $data * - * @return bool|string + * @return null|string */ - function view(string $partialPath, array $data = []): bool|string + function view(string $partialPath, array $data = []): null|string { - return (new ConfigHelper())->getTemplateData($partialPath, $data); + $content = (new ConfigHelper())->getTemplateData($partialPath, $data); + return $content ?: null; } } diff --git a/composer.json b/composer.json index 3de2514..1577599 100644 --- a/composer.json +++ b/composer.json @@ -34,12 +34,18 @@ ] }, "require": { - "php": "^8.0", + "php": "^8.1", "eleirbag89/telegrambotphp": "^1.4", "guzzlehttp/guzzle": "^7.8", "symfony/http-foundation": "^6.3", "vlucas/phpdotenv": "^5.5" }, + "require-dev": { + "phpstan/phpstan": "^1.10.39" + }, + "scripts": { + "analyse": "vendor/bin/phpstan" + }, "support": { "issues": "https://github.com/lbiltech/telegram-git-notifier/issues" }, diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..2e837cd --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,6 @@ +parameters: + level: 8 + paths: + - src + tmpDir: build/phpstan + checkMissingIterableValueType: false diff --git a/src/Exceptions/EntryNotFoundException.php b/src/Exceptions/EntryNotFoundException.php index 2e20763..04b3bf6 100644 --- a/src/Exceptions/EntryNotFoundException.php +++ b/src/Exceptions/EntryNotFoundException.php @@ -9,12 +9,12 @@ public static function fileNotFound(): self return new self('File not found'); } - public static function configNotFound($config): self + public static function configNotFound(string $config): self { return new self("Config {$config} not found"); } - public static function viewNotFound($view): self + public static function viewNotFound(string $view): self { return new self("View {$view} not found"); } diff --git a/src/Exceptions/TelegramGitNotifierException.php b/src/Exceptions/TelegramGitNotifierException.php index e9e0337..3d201ea 100644 --- a/src/Exceptions/TelegramGitNotifierException.php +++ b/src/Exceptions/TelegramGitNotifierException.php @@ -8,11 +8,11 @@ class TelegramGitNotifierException extends Exception { public static function isEmpty(): self { - return new static('Telegram Git Notifier is empty'); + return new self('Telegram Git Notifier is empty'); } public static function invalid(): self { - return new static('Telegram Git Notifier is invalid'); + return new self('Telegram Git Notifier is invalid'); } } diff --git a/src/Helpers/ConfigHelper.php b/src/Helpers/ConfigHelper.php index 7626aba..d345474 100644 --- a/src/Helpers/ConfigHelper.php +++ b/src/Helpers/ConfigHelper.php @@ -8,6 +8,9 @@ class ConfigHelper { + /** + * @var array + */ public array $config; public function __construct() @@ -39,12 +42,12 @@ public function execConfig(string $string): mixed /** * Return template data * - * @param $partialPath + * @param string $partialPath * @param array $data * * @return bool|string */ - public function getTemplateData($partialPath, array $data = []): bool|string + public function getTemplateData(string $partialPath, array $data = []): bool|string { $viewPathFile = $this->execConfig('telegram-git-notifier.view.path') . '/' . str_replace('.', '/', $partialPath) . '.php'; @@ -53,6 +56,7 @@ public function getTemplateData($partialPath, array $data = []): bool|string return ''; } + $content = ''; ob_start(); try { extract($data, EXTR_SKIP); diff --git a/src/Interfaces/EventInterface.php b/src/Interfaces/EventInterface.php index 846a260..a2de979 100644 --- a/src/Interfaces/EventInterface.php +++ b/src/Interfaces/EventInterface.php @@ -2,6 +2,7 @@ namespace LbilTech\TelegramGitNotifier\Interfaces; +use LbilTech\TelegramGitNotifier\Constants\EventConstant; use LbilTech\TelegramGitNotifier\Trait\ActionEventTrait; use Symfony\Component\HttpFoundation\Request; @@ -10,23 +11,23 @@ interface EventInterface /** * Get action name of event from payload data * - * @param $payload + * @param object $payload * * @return string * @see ActionEventTrait::getActionOfEvent() */ - public function getActionOfEvent($payload): string; + public function getActionOfEvent(object $payload): string; /** * Set platform and platform file for event * - * @param string $platform + * @param string|null $platform * @param string|null $platformFile * * @return void * @see EventTrait::setPlatFormForEvent() */ - public function setPlatFormForEvent(string $platform, string $platformFile = null): void; + public function setPlatFormForEvent(?string $platform = EventConstant::DEFAULT_PLATFORM, string $platformFile = null): void; /** * Set event config and get event name diff --git a/src/Interfaces/SettingInterface.php b/src/Interfaces/SettingInterface.php index c08a6f7..b5833ae 100644 --- a/src/Interfaces/SettingInterface.php +++ b/src/Interfaces/SettingInterface.php @@ -38,12 +38,12 @@ public function getCallbackData(string $event, string $platform, array|bool $val * Get event name for markup * * @param string $event - * @param $value + * @param bool|array $value * * @return string * @see EventSettingTrait::getEventName() */ - public function getEventName(string $event, $value): string; + public function getEventName(string $event, bool|array $value): string; /** * Get end keyboard buttons diff --git a/src/Interfaces/Structures/AppInterface.php b/src/Interfaces/Structures/AppInterface.php index 9395f2e..2bc4867 100644 --- a/src/Interfaces/Structures/AppInterface.php +++ b/src/Interfaces/Structures/AppInterface.php @@ -10,17 +10,14 @@ interface AppInterface /** * Send a message to telegram * - * @param string $message + * @param string|null $message * @param array $options * * @return void * @throws MessageIsEmptyException * @see App::sendMessage() */ - public function sendMessage( - string $message = '', - array $options = [] - ): void; + public function sendMessage(?string $message = '', array $options = []): void; /** * Send a photo to telegram @@ -54,10 +51,7 @@ public function answerCallbackQuery(string $text = null): void; * @return void * @see App::editMessageText() */ - public function editMessageText( - ?string $text = null, - array $options = [] - ): void; + public function editMessageText(string $text = null, array $options = []): void; /** * Edit message reply markup from a telegram diff --git a/src/Interfaces/Structures/NotificationInterface.php b/src/Interfaces/Structures/NotificationInterface.php index 863f01f..1e65546 100644 --- a/src/Interfaces/Structures/NotificationInterface.php +++ b/src/Interfaces/Structures/NotificationInterface.php @@ -50,12 +50,12 @@ public function sendNotify(string $message = null, array $options = []): bool; /** * Get action name of event from payload data * - * @param $payload + * @param object $payload * * @return string * @see EventTrait::getActionOfEvent() */ - public function getActionOfEvent($payload): string; + public function getActionOfEvent(object $payload): string; /** * Convert chat and thread ids to array diff --git a/src/Models/Event.php b/src/Models/Event.php index a6a8287..d3a12b2 100644 --- a/src/Models/Event.php +++ b/src/Models/Event.php @@ -41,17 +41,20 @@ public function getEventConfig(): array /** * Set event config * - * @param string $platform + * @param string|null $platform * * @return void */ public function setEventConfig( - string $platform = EventConstant::DEFAULT_PLATFORM + string $platform = null ): void { - $this->platform = $platform; + $this->platform = $platform ?? EventConstant::DEFAULT_PLATFORM; $json = file_get_contents($this->platformFile); - $this->eventConfig = json_decode($json, true); + + if (!empty($json)) { + $this->eventConfig = json_decode($json, true); + } } /** diff --git a/src/Models/Setting.php b/src/Models/Setting.php index 6c07913..f7b6d8c 100644 --- a/src/Models/Setting.php +++ b/src/Models/Setting.php @@ -44,7 +44,10 @@ public function getSettingFile(): string public function setSettingConfig(): void { $json = file_get_contents($this->settingFile); - $this->settings = json_decode($json, true); + + if (!empty($json)) { + $this->settings = json_decode($json, true); + } } /** @@ -81,13 +84,13 @@ public function isNotified(): bool * Update setting item value and save to file * * @param string $settingName - * @param $settingValue + * @param array|string|bool|int|null $settingValue * * @return bool */ public function updateSetting( string $settingName, - $settingValue = null + mixed $settingValue = null ): bool { $settingKeys = explode('.', $settingName); $lastKey = array_pop($settingKeys); diff --git a/src/Objects/Validator.php b/src/Objects/Validator.php index 944529d..6c2b4b8 100644 --- a/src/Objects/Validator.php +++ b/src/Objects/Validator.php @@ -25,14 +25,14 @@ public function __construct(Setting $setting, Event $event) * * @param string $platform Source code platform (GitHub, GitLab) * @param string $event Event name (push, pull_request) - * @param $payload + * @param object $payload * * @return bool */ public function isAccessEvent( string $platform, string $event, - $payload + object $payload ): bool { if (!$this->setting->isNotified()) { return false; diff --git a/src/Structures/App.php b/src/Structures/App.php index 907df5d..f3465d3 100644 --- a/src/Structures/App.php +++ b/src/Structures/App.php @@ -27,7 +27,7 @@ private function createTelegramBaseContent(): array ]; } - public function sendMessage(string $message = '', array $options = []): void + public function sendMessage(?string $message = '', array $options = []): void { if (empty($message)) { throw MessageIsEmptyException::create(); diff --git a/src/Structures/Notification.php b/src/Structures/Notification.php index cfdbef3..9426436 100644 --- a/src/Structures/Notification.php +++ b/src/Structures/Notification.php @@ -4,12 +4,13 @@ use GuzzleHttp\Exception\GuzzleException; use LbilTech\TelegramGitNotifier\Constants\EventConstant; +use LbilTech\TelegramGitNotifier\Exceptions\MessageIsEmptyException; use LbilTech\TelegramGitNotifier\Exceptions\SendNotificationException; use Symfony\Component\HttpFoundation\Request; trait Notification { - public mixed $payload; + public object $payload; public string $message = ''; @@ -30,11 +31,18 @@ public function accessDenied( public function setPayload(Request $request, string $event) { + $content = null; + if ($this->event->platform === 'gitlab') { - $this->payload = json_decode($request->getContent()); + $content = $request->getContent(); } elseif ($this->event->platform === EventConstant::DEFAULT_PLATFORM) { - $this->payload = json_decode($request->request->get('payload')); + $content = $request->request->get('payload'); + } + + if (is_string($content)) { + $this->payload = json_decode($content); } + $this->setMessage($event); return $this->payload; @@ -46,6 +54,7 @@ public function setPayload(Request $request, string $event) * @param string $typeEvent * * @return void + * @throws MessageIsEmptyException */ private function setMessage(string $typeEvent): void { @@ -56,10 +65,16 @@ private function setMessage(string $typeEvent): void ? "events.{$this->event->platform}.{$event}.default" : "events.{$this->event->platform}.{$event}.{$action}"; - $this->message = view($viewTemplate, [ + $viewResult = view($viewTemplate, [ 'payload' => $this->payload, 'event' => tgn_convert_event_name($typeEvent), ]); + + if ($viewResult === null) { + throw MessageIsEmptyException::create(); + } + + $this->message = $viewResult; } public function sendNotify(string $message = null, array $options = []): bool diff --git a/src/Trait/ActionEventTrait.php b/src/Trait/ActionEventTrait.php index 7c05b68..5161e0a 100644 --- a/src/Trait/ActionEventTrait.php +++ b/src/Trait/ActionEventTrait.php @@ -4,11 +4,11 @@ trait ActionEventTrait { - public function getActionOfEvent($payload): string + public function getActionOfEvent(object $payload): string { - $action = $payload?->action - ?? $payload?->object_attributes?->action - ?? $payload?->object_attributes?->noteable_type + $action = $payload->action + ?? $payload->object_attributes?->action + ?? $payload->object_attributes?->noteable_type ?? ''; if (!empty($action)) { diff --git a/src/Trait/EventSettingTrait.php b/src/Trait/EventSettingTrait.php index 87c1532..51f98ad 100644 --- a/src/Trait/EventSettingTrait.php +++ b/src/Trait/EventSettingTrait.php @@ -65,7 +65,7 @@ public function getCallbackData( return $prefix . $event . EventConstant::EVENT_UPDATE_SEPARATOR; } - public function getEventName(string $event, $value): string + public function getEventName(string $event, bool|array $value = false): string { if (is_array($value)) { return '⚙ ' . $event; @@ -124,9 +124,9 @@ public function getPlatformFromCallback( return $platform; } - if (str_contains($callback, EventConstant::GITHUB_EVENT_SEPARATOR)) { + if ($callback && str_contains($callback, EventConstant::GITHUB_EVENT_SEPARATOR)) { return 'github'; - } elseif (str_contains($callback, EventConstant::GITLAB_EVENT_SEPARATOR)) { + } elseif ($callback && str_contains($callback, EventConstant::GITLAB_EVENT_SEPARATOR)) { return 'gitlab'; } @@ -157,6 +157,10 @@ public function sendSettingEventMessage( public function getEventFromCallback(?string $callback): string { + if (!$callback) { + return ''; + } + return str_replace([ EventConstant::EVENT_PREFIX, EventConstant::GITHUB_EVENT_SEPARATOR, diff --git a/src/Trait/EventTrait.php b/src/Trait/EventTrait.php index 98ec7d9..2175b0d 100644 --- a/src/Trait/EventTrait.php +++ b/src/Trait/EventTrait.php @@ -9,9 +9,9 @@ trait EventTrait { use ActionEventTrait; - public function setPlatFormForEvent(string $platform, string $platformFile = null): void + public function setPlatFormForEvent(?string $platform = EventConstant::DEFAULT_PLATFORM, string $platformFile = null): void { - /** @var array $platformFileDefaults */ + /** @var array $platformFileDefaults */ $platformFileDefaults = config('telegram-git-notifier.data_file.platform'); $this->event->setPlatformFile($platformFile ?? $platformFileDefaults[$platform]); $this->event->setEventConfig($platform);