commit 3f10e5d9341d700ebc6c989759bb72b448461ee4 Author: Giuseppe Nucifora Date: Fri Jul 26 23:59:32 2019 +0200 First Commit diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..f3451cf --- /dev/null +++ b/composer.json @@ -0,0 +1,31 @@ +{ + "name": "giuseppenuc/uptimerobot-bundle", + "description": "Uptime Robot SF4 Bundle", + "type": "symfony-bundle", + "license": "MIT", + "authors": [ + { + "name": "Giuseppe Nucifora", + "email": "me@giuseppenucifora.com" + } + ], + "minimum-stability": "stable", + "require": { + "php": ">=7.1", + "symfony/framework-bundle": "~4.3", + "symfony/flex": "^1.2", + "vdhicts/uptimerobot-api-client": "^1.1", + "symfony/dependency-injection": "~4.0", + "symfony/config": "~4.0", + "symfony/serializer": "~4.0", + "ext-json": "*" + }, + "require-dev": { + "roave/security-advisories": "dev-master" + }, + "autoload": { + "psr-4": { + "Pn\\UptimeRobotBundle\\": "src/" + } + } +} diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php new file mode 100644 index 0000000..110901d --- /dev/null +++ b/src/DependencyInjection/Configuration.php @@ -0,0 +1,44 @@ +getRootNode(); + + $rootNode + ->children() + ->arrayNode('credentials') + ->children() + ->variableNode('api_key')->end() + ->end() + ->end() + ->arrayNode('configurations') + ->children() + ->variableNode('interval')->end() + ->variableNode('alert_contacts')->end() + ->end() + ->end() + ->end() + ->end(); + + return $treeBuilder; + } +} diff --git a/src/DependencyInjection/UptimeRobotExtension.php b/src/DependencyInjection/UptimeRobotExtension.php new file mode 100644 index 0000000..eff5ff1 --- /dev/null +++ b/src/DependencyInjection/UptimeRobotExtension.php @@ -0,0 +1,51 @@ +processConfiguration($configuration, $configs); + + $loader = new YamlFileLoader($container, new FileLocator(dirname(__DIR__) . '/Resources/config')); + $loader->load('services.yaml'); + + //$container->setParameter('uptime_robot.credentials', $config['credentials']); + if (isset($config['credentials'])) { + if (\array_key_exists('api_key', $config['credentials'])) { + $container->setParameter('uptime_robot.credentials.api_key', $config['credentials']['api_key']); + } + } + //$container->setParameter('uptime_robot.configurations', $config['configurations']); + if (isset($config['configurations'])) { + if (\array_key_exists('interval', $config['configurations'])) { + $container->setParameter('uptime_robot.configurations.interval', $config['configurations']['interval']); + } + + if (\array_key_exists('alert_contacts', $config['configurations'])) { + $container->setParameter('uptime_robot.configurations.alert_contacts', $config['configurations']['alert_contacts']); + } + } + + $this->addAnnotatedClassesToCompile([ + 'Pn\\UptimeRobotBundle\\Service\\UptimeRobotApiService' + ]); + } +} diff --git a/src/Model/AlertContact.php b/src/Model/AlertContact.php new file mode 100644 index 0000000..1737384 --- /dev/null +++ b/src/Model/AlertContact.php @@ -0,0 +1,195 @@ +type = 2; + $this->errors = []; + } + + /** + * @param $alertContactObj + * @return AlertContact + */ + public static function getAlertContactFromResponse($alertContactObj) + { + $alertContact = new AlertContact(); + + $alertContact->setId($alertContactObj->id); + $alertContact->setFriendlyName($alertContactObj->friendly_name); + $alertContact->setType($alertContactObj->type); + $alertContact->setStatus($alertContactObj->status); + $alertContact->setValue($alertContactObj->value); + + return $alertContact; + } + + /** + * @return bool + */ + public function isValidObjectForCreate() + { + $result = true; + $this->errors = []; + if (!in_array($this->getType(), self::ALLOWED_FOR_CREATE)) { + $this->errors[] = 'Type not valid for create alert contact'; + $result = false; + } + + switch ($this->getType()) { + case self::TYPE_SMS: + $checkValue = $this->getValue(); + + if (!is_numeric(str_replace(' ', '', str_replace('+', '', $checkValue)))) { + $this->errors[] = 'Invalid number format'; + $result = false; + } + + break; + case self::TYPE_EMAIL: + if (!filter_var($this->getValue(), FILTER_VALIDATE_EMAIL)) { + $this->errors[] = 'Invalid email format'; + $result = false; + } + break; + } + return $result; + } + + /** + * @return mixed + */ + public function getErrors() + { + return $this->errors; + } + + /** + * @return mixed + */ + public function getId() + { + return $this->id; + } + + /** + * @param mixed $id + * @return AlertContact + */ + public function setId($id) + { + $this->id = $id; + return $this; + } + + /** + * @return mixed + */ + public function getFriendlyName() + { + return $this->friendlyName; + } + + /** + * @param mixed $friendlyName + * @return AlertContact + */ + public function setFriendlyName($friendlyName) + { + $this->friendlyName = $friendlyName; + return $this; + } + + /** + * @return mixed + */ + public function getType() + { + return $this->type; + } + + /** + * @param mixed $type + * @return AlertContact + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * @return mixed + */ + public function getStatus() + { + return $this->status; + } + + /** + * @param mixed $status + * @return AlertContact + */ + public function setStatus($status) + { + $this->status = $status; + return $this; + } + + /** + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * @param mixed $value + * @return AlertContact + */ + public function setValue($value) + { + $this->value = $value; + return $this; + } + + public function getIdForMonitorRequest($threshold = 0, $recurrence = 0) + { + return sprintf('%u_%u_%u', $this->id, $threshold, $recurrence); + } +} \ No newline at end of file diff --git a/src/Model/Monitor.php b/src/Model/Monitor.php new file mode 100644 index 0000000..d049185 --- /dev/null +++ b/src/Model/Monitor.php @@ -0,0 +1,344 @@ +setId($monitorObj->id); + $monitor->setFriendlyName($monitorObj->friendly_name); + $monitor->setUrl($monitorObj->url); + $monitor->setType($monitorObj->type); + $monitor->setSubType($monitorObj->sub_type); + $monitor->setKeywordType($monitorObj->keyword_type); + $monitor->setKeywordValue($monitorObj->keyword_value); + $monitor->setHttpUsername($monitorObj->http_username); + $monitor->setHttpPassword($monitorObj->http_password); + $monitor->setPort($monitorObj->port); + $monitor->setInterval($monitorObj->interval); + $monitor->setStatus($monitorObj->status); + + $date = new \DateTime(); + $date->setTimestamp($monitorObj->create_datetime); + $monitor->setCreateDatetime($date); + + return $monitor; + } + + public function __construct() + { + $this->type = self::TYPE_HTTP; + } + + /** + * @return bool + */ + public function isValidObjectForCreate() + { + $result = true; + + return $result; + } + + /** + * @return int + */ + public function getId(): ?int + { + return $this->id; + } + + /** + * @param int $id + * @return Monitor + */ + public function setId(int $id): Monitor + { + $this->id = $id; + return $this; + } + + /** + * @return string + */ + public function getFriendlyName(): ?string + { + return $this->friendlyName; + } + + /** + * @param string $friendlyName + * @return Monitor + */ + public function setFriendlyName(string $friendlyName): Monitor + { + $this->friendlyName = $friendlyName; + return $this; + } + + /** + * @return string + */ + public function getUrl(): ?string + { + return $this->url; + } + + /** + * @param string $url + * @return Monitor + */ + public function setUrl(string $url): Monitor + { + $this->url = $url; + return $this; + } + + /** + * @return int + */ + public function getType(): ?int + { + return $this->type; + } + + /** + * @param int $type + * @return Monitor + */ + public function setType(?int $type): Monitor + { + $this->type = $type; + return $this; + } + + /** + * @return string + */ + public function getSubType(): ?string + { + return $this->subType; + } + + /** + * @param string $subType + * @return Monitor + */ + public function setSubType(?string $subType): Monitor + { + $this->subType = $subType; + return $this; + } + + /** + * @return string + */ + public function getKeywordType(): ?string + { + return $this->keywordType; + } + + /** + * @param string $keywordType + * @return Monitor + */ + public function setKeywordType(?string $keywordType): Monitor + { + $this->keywordType = $keywordType; + return $this; + } + + /** + * @return string + */ + public function getKeywordValue(): ?string + { + return $this->keywordValue; + } + + /** + * @param string $keywordValue + * @return Monitor + */ + public function setKeywordValue(?string $keywordValue): Monitor + { + $this->keywordValue = $keywordValue; + return $this; + } + + /** + * @return string + */ + public function getHttpUsername(): ?string + { + return $this->httpUsername; + } + + /** + * @param string $httpUsername + * @return Monitor + */ + public function setHttpUsername(?string $httpUsername): Monitor + { + $this->httpUsername = $httpUsername; + return $this; + } + + /** + * @return string + */ + public function getHttpPassword(): ?string + { + return $this->httpPassword; + } + + /** + * @param string $httpPassword + * @return Monitor + */ + public function setHttpPassword(?string $httpPassword): Monitor + { + $this->httpPassword = $httpPassword; + return $this; + } + + /** + * @return string + */ + public function getPort(): ?string + { + return $this->port; + } + + /** + * @param string $port + * @return Monitor + */ + public function setPort(?string $port): Monitor + { + $this->port = $port; + return $this; + } + + /** + * @return int + */ + public function getInterval(): ?int + { + return $this->interval; + } + + /** + * @param int $interval + * @return Monitor + */ + public function setInterval(?int $interval): Monitor + { + $this->interval = $interval; + return $this; + } + + /** + * @return int + */ + public function getStatus(): ?int + { + return $this->status; + } + + /** + * @param int $status + * @return Monitor + */ + public function setStatus(?int $status): Monitor + { + $this->status = $status; + return $this; + } + + /** + * @return \DateTime + */ + public function getCreateDatetime(): ?\DateTime + { + return $this->createDatetime; + } + + /** + * @param \DateTime $createDatetime + * @return Monitor + */ + public function setCreateDatetime(\DateTime $createDatetime): Monitor + { + $this->createDatetime = $createDatetime; + return $this; + } +} \ No newline at end of file diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml new file mode 100644 index 0000000..9341d92 --- /dev/null +++ b/src/Resources/config/services.yaml @@ -0,0 +1,13 @@ +parameters: + uptime_robot.credentials.api_key: '' + uptime_robot.configurations.interval: '' + uptime_robot.configurations.alert_contacts: '' + + +services: + Pn\UptimeRobotBundle\Service\UptimeRobotApiService: + class: Pn\UptimeRobotBundle\Service\UptimeRobotApiService + public: true + arguments: + - '%uptime_robot.credentials.api_key%' + - '@Symfony\Component\Serializer\SerializerInterface' diff --git a/src/Resources/doc/index.rst b/src/Resources/doc/index.rst new file mode 100644 index 0000000..e69de29 diff --git a/src/Response/MonitorResponse.php b/src/Response/MonitorResponse.php new file mode 100644 index 0000000..5daf962 --- /dev/null +++ b/src/Response/MonitorResponse.php @@ -0,0 +1,8 @@ +client->perform(self::GET_ALERT_CONTACTS); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + + foreach ($response->alert_contacts as $alert_contact) { + + $alertContact = AlertContact::getAlertContactFromResponse($alert_contact); + + $this->cachedAlertContacts[] = $alertContact; + } + + break; + default: + break; + } + + + return $this->cachedAlertContacts; + } + + + /** + * @param AlertContact $alertContact + * @return bool|AlertContact + */ + public function create(AlertContact $alertContact) + { + try { + $jsonResponse = $this->client->perform( + self::NEW_ALERT_CONTACT, + [ + 'type' => $alertContact->getType(), + 'value' => $alertContact->getValue(), + 'friendly_name' => $alertContact->getFriendlyName() + ] + ); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + $alertContact->setId($response->alertcontact->id); + return $alertContact; + break; + default: + return false; + break; + } + + } + + /** + * @param AlertContact $oldAlertContact + * @param AlertContact $alertContact + * @return bool|AlertContact + */ + public function update(AlertContact $oldAlertContact, AlertContact $alertContact) + { + try { + $jsonResponse = $this->client->perform( + self::EDIT_ALERT_CONTACT, + [ + 'id' => $oldAlertContact->getId(), + 'type' => $alertContact->getType(), + 'value' => $alertContact->getValue(), + 'friendly_name' => $alertContact->getFriendlyName() + ] + ); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + $alertContact->setId($response->alert_contact->id); + return $alertContact; + break; + default: + return false; + break; + } + } + + /** + * @param AlertContact $alertContact + * @return bool|AlertContact + */ + public function delete(AlertContact $alertContact) + { + try { + $jsonResponse = $this->client->perform(self::DELETE_ALERT_CONTACT, [ + 'id' => $alertContact->getId() + ]); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + return $alertContact; + break; + default: + return false; + break; + } + } + + /** + * @param $id + * @param bool $forceRefresh + * @return mixed|AlertContact|null + */ + public function find($id, $forceRefresh = false) + { + if (empty($this->cachedAlertContacts) || $forceRefresh) { + $this->getAlertContacts(); + } + + /** @var AlertContact $alertContact */ + foreach ($this->cachedAlertContacts as $alertContact) { + if ($alertContact->getId() === $id) { + return $alertContact; + } + } + + return null; + } + + + /** + * @param $value + * @param int $type + * @param bool $forceRefresh + * @return mixed|AlertContact|null + */ + public function findOneByValueAndType($value, $type = AlertContact::TYPE_EMAIL, $forceRefresh = false) + { + if (empty($this->cachedAlertContacts) || $forceRefresh) { + $this->getAlertContacts(); + } + + /** @var AlertContact $alertContact */ + foreach ($this->cachedAlertContacts as $alertContact) { + if ($alertContact->getValue() === $value && $alertContact->getType() === $type) { + return $alertContact; + } + } + + return null; + } + + /** + * @param AlertContact $alertContact + * @return bool|mixed|AlertContact + */ + public function createOrUpdate(AlertContact $alertContact) + { + if ($alertContact->isValidObjectForCreate()) { + + $foundAlertContact = $this->findOneByValueAndType($alertContact->getValue(), $alertContact->getType(), true); + + if ($foundAlertContact instanceof AlertContact) { + return $this->update($foundAlertContact, $alertContact); + } else { + return $this->create($alertContact); + } + } else { + return $alertContact->getErrors(); + } + } +} \ No newline at end of file diff --git a/src/Service/UptimeRobotApiService.php b/src/Service/UptimeRobotApiService.php new file mode 100644 index 0000000..7013146 --- /dev/null +++ b/src/Service/UptimeRobotApiService.php @@ -0,0 +1,84 @@ +client = new Client($configuration); + $this->serializer = $serializer; + } + + /** + * @return SymfonyStyle + */ + public function getIo(): SymfonyStyle + { + return $this->io; + } + + /** + * @param SymfonyStyle $io + * @return UptimeRobotApiService + */ + public function setIo(SymfonyStyle $io): UptimeRobotApiService + { + $this->io = $io; + return $this; + } + + /** + * @return UptimeRobotMonitorService + */ + public function getMonitorService(): UptimeRobotMonitorService + { + if (null === $this->monitorService) { + $this->monitorService = New UptimeRobotMonitorService($this->client); + if ($this->io instanceof SymfonyStyle) { + $this->monitorService->setIo($this->io); + } + } + return $this->monitorService; + } + + /** + * @return UptimeRobotAlertContacsService + */ + public function getAlertContactService(): UptimeRobotAlertContacsService + { + if (null === $this->alertContactService) { + $this->alertContactService = New UptimeRobotAlertContacsService($this->client); + if ($this->io instanceof SymfonyStyle) { + $this->alertContactService->setIo($this->io); + } + } + return $this->alertContactService; + } + + +} \ No newline at end of file diff --git a/src/Service/UptimeRobotMonitorService.php b/src/Service/UptimeRobotMonitorService.php new file mode 100644 index 0000000..f099749 --- /dev/null +++ b/src/Service/UptimeRobotMonitorService.php @@ -0,0 +1,279 @@ +getMonitors(); + } + + /** + * @param array $params + * @return array|bool + */ + public function getMonitors($params = []) + { + $this->cachedMonitors = []; + + try { + $jsonResponse = $this->client->perform(self::GET_MONITORS, $params); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + foreach ($response->monitors as $monitorObj) { + $monitor = Monitor::getMonitorFromResponse($monitorObj); + + $this->cachedMonitors[] = $monitor; + } + break; + default: + return false; + break; + } + + return $this->cachedMonitors; + } + + /** + * @param Monitor $monitor + * @return bool|Monitor + */ + public function create(Monitor $monitor, array $alertContacts, $threshold = 0, $recurrence = 0) + { + try { + $alertContactsString = ''; + + /** @var AlertContact $alertContact */ + foreach ($alertContacts as $alertContact) { + if ($alertContactsString !== '') { + $alertContactsString .= '-'; + } + $alertContactsString .= $alertContact->getIdForMonitorRequest($threshold, $recurrence); + } + + $jsonResponse = $this->client->perform( + self::NEW_MONITOR, + [ + 'friendly_name' => $monitor->getFriendlyName(), + 'url' => $monitor->getUrl(), + 'type' => $monitor->getType(), + 'sub_type' => $monitor->getSubType(), + 'port' => $monitor->getPort(), + 'keyword_type' => $monitor->getKeywordType(), + 'keyword_value' => $monitor->getKeywordValue(), + 'interval' => $monitor->getInterval(), + 'http_username' => $monitor->getHttpUsername(), + 'http_password' => $monitor->getHttpPassword(), + 'alert_contacts' => $alertContactsString, + 'mwindows' => '' + ] + ); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + + switch ($response->stat) { + case 'ok': + $monitor->setId($response->monitor->id); + return $monitor; + break; + default: + return false; + break; + } + + } + + /** + * @param Monitor $oldMonitor + * @param Monitor $monitor + * @return bool|Monitor + */ + public function update(Monitor $oldMonitor, Monitor $monitor, array $alertContacts, $threshold = 0, $recurrence = 0) + { + try { + $alertContactsString = ''; + + /** @var AlertContact $alertContact */ + foreach ($alertContacts as $alertContact) { + if ($alertContactsString !== '') { + $alertContactsString .= '-'; + } + $alertContactsString .= $alertContact->getIdForMonitorRequest($threshold, $recurrence); + } + + $jsonResponse = $this->client->perform( + self::EDIT_MONITOR, + [ + 'id' => $oldMonitor->getId(), + 'friendly_name' => $monitor->getFriendlyName(), + 'url' => $monitor->getUrl(), + 'type' => $monitor->getType(), + 'sub_type' => $monitor->getSubType(), + 'port' => $monitor->getPort(), + 'keyword_type' => $monitor->getKeywordType(), + 'keyword_value' => $monitor->getKeywordValue(), + 'interval' => $monitor->getInterval(), + 'http_username' => $monitor->getHttpUsername(), + 'http_password' => $monitor->getHttpPassword(), + 'alert_contacts' => $alertContactsString, + 'mwindows' => '' + ] + ); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + $monitor->setId($response->monitor->id); + return $monitor; + break; + default: + return false; + break; + } + } + + /** + * @param Monitor $monitor + * @return bool|Monitor + */ + public function delete(Monitor $monitor) + { + try { + $jsonResponse = $this->client->perform(self::DELETE_MONITOR, [ + 'id' => $monitor->getId() + ]); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + return $monitor; + break; + default: + return false; + break; + } + } + + /** + * @param Monitor $monitor + * @return bool|Monitor + */ + public function reset(Monitor $monitor) + { + try { + $jsonResponse = $this->client->perform(self::RESET_MONITOR, [ + 'id' => $monitor->getId() + ]); + } catch (\Vdhicts\UptimeRobot\Client\Exceptions\FailedRequestException $exception) { + $this->logError($exception); + } + + $response = json_decode($jsonResponse); + + switch ($response->stat) { + case 'ok': + return $monitor; + break; + default: + return false; + break; + } + } + + /** + * @param $id + * @param bool $forceRefresh + * @return mixed|Monitor|null + */ + public function find($id, $forceRefresh = false) + { + if (empty($this->cachedMonitors) || $forceRefresh) { + $this->getMonitors(); + } + + /** @var Monitor $monitor */ + foreach ($this->cachedMonitors as $monitor) { + if ($monitor->getId() === $id) { + return $monitor; + } + } + + return null; + } + + + /** + * @param $url + * @param int $type + * @param bool $forceRefresh + * @return mixed|Monitor|null + */ + public function findOneByURLAndType($url, $type = Monitor::TYPE_HTTP, $forceRefresh = false) + { + if (empty($this->cachedMonitors) || $forceRefresh) { + $this->getMonitors(); + } + + /** @var Monitor $monitor */ + foreach ($this->cachedMonitors as $monitor) { + if ($monitor->getUrl() === $url && $monitor->getType() === $type) { + return $monitor; + } + } + + return null; + } + + /** + * @param Monitor $monitor + * @return bool|mixed|Monitor + */ + public function createOrUpdate(Monitor $monitor, array $alertContacts, $threshold = 0, $recurrence = 0) + { + if ($monitor->isValidObjectForCreate()) { + + $foundMonitor = $this->findOneByURLAndType($monitor->getUrl(), $monitor->getType(), true); + + if ($foundMonitor instanceof Monitor) { + return $this->update($foundMonitor, $monitor, $alertContacts, $threshold, $recurrence); + } else { + return $this->create($monitor, $alertContacts, $threshold, $recurrence); + } + } else { + return $monitor->getErrors(); + } + } +} \ No newline at end of file diff --git a/src/Service/UptimeRobotService.php b/src/Service/UptimeRobotService.php new file mode 100644 index 0000000..606a572 --- /dev/null +++ b/src/Service/UptimeRobotService.php @@ -0,0 +1,67 @@ +client = $client; + + $encoders = [new XmlEncoder(), new JsonEncoder()]; + $normalizers = [new ObjectNormalizer()]; + + $this->serializer = new Serializer($normalizers, $encoders); + } + + /** + * @return SymfonyStyle + */ + public function getIo(): SymfonyStyle + { + return $this->io; + } + + /** + * @param SymfonyStyle $io + * @return UptimeRobotService + */ + public function setIo(SymfonyStyle $io): UptimeRobotService + { + $this->io = $io; + return $this; + } + + /** + * @return Client + */ + public function getClient(): Client + { + return $this->client; + } + + protected function logError(\Exception $exception) + { + if ($this->getIo()) { + $this->getIo()->error($exception->getMessage()); + } + } +} \ No newline at end of file diff --git a/src/UptimeRobotBundle.php b/src/UptimeRobotBundle.php new file mode 100644 index 0000000..25a18b4 --- /dev/null +++ b/src/UptimeRobotBundle.php @@ -0,0 +1,10 @@ +