From a32210a561df339c6f24599aaf3d3eaa4868b122 Mon Sep 17 00:00:00 2001 From: Ayush Raj Srivastava Date: Mon, 26 Aug 2024 10:18:30 +0530 Subject: [PATCH] added code for installation tracker --- CHANGELOG-1.1.md | 3 + composer.json | 6 +- src/Console/Wizard/ConfigureHelpdesk.php | 96 ++++++++++++++++++- src/Controller/ConfigureHelpdesk.php | 10 ++ .../ImageCache/ImageCacheController.php | 53 ++++++++++ src/Controller/ImageCache/ImageManager.php | 71 ++++++++++++++ src/Resources/config/routes.yaml | 6 ++ src/Service/UrlImageCacheService.php | 53 ++++++++++ 8 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 src/Controller/ImageCache/ImageCacheController.php create mode 100644 src/Controller/ImageCache/ImageManager.php create mode 100644 src/Service/UrlImageCacheService.php diff --git a/CHANGELOG-1.1.md b/CHANGELOG-1.1.md index 022d260d3..00d55f783 100644 --- a/CHANGELOG-1.1.md +++ b/CHANGELOG-1.1.md @@ -3,6 +3,9 @@ CHANGELOG for 1.1.x This changelog references any relevant changes introduced in 1.1 minor versions. +* 1.1.4 (2024-08-26) + * Feature: Add functionality for tracking the installation count and count of active users (ars128) + * 1.1.3 (2023-06-13) * Update: Render project version number dynamically diff --git a/composer.json b/composer.json index 62e565f63..462d287f5 100644 --- a/composer.json +++ b/composer.json @@ -50,10 +50,12 @@ "twig/twig": "^2.12|^3.0", "uvdesk/api-bundle": "^1.1", "uvdesk/automation-bundle": "^1.1.2", - "uvdesk/core-framework": "^1.1.3", + "uvdesk/core-framework": "^1.1.5", "uvdesk/extension-framework": "^1.1", "uvdesk/mailbox-component": "^1.1", - "uvdesk/support-center-bundle": "^1.1.3" + "uvdesk/support-center-bundle": "^1.1.3", + "intervention/image": "^2.4", + "intervention/imagecache": "^2.5.2" }, "require-dev": { }, diff --git a/src/Console/Wizard/ConfigureHelpdesk.php b/src/Console/Wizard/ConfigureHelpdesk.php index 16042c4d1..d0466b7ba 100644 --- a/src/Console/Wizard/ConfigureHelpdesk.php +++ b/src/Console/Wizard/ConfigureHelpdesk.php @@ -17,6 +17,13 @@ class ConfigureHelpdesk extends Command { + /** + * Api endpoint + * + * @var string + */ + protected const API_ENDPOINT = 'https://updates.uvdesk.com/api/updates'; + CONST CLS = "\033[H"; // Clear screen CONST CLL = "\033[K"; // Clear line CONST MCH = "\033[2J"; // Move cursor home @@ -26,6 +33,10 @@ class ConfigureHelpdesk extends Command private $entityManager; private $questionHelper; + private $userName; + private $userEmail; + private $userInstance; + public function __construct(ContainerInterface $container) { $this->container = $container; @@ -244,7 +255,14 @@ protected function execute(InputInterface $input, OutputInterface $output) $userInstanceQuery = $database->query("SELECT * FROM uv_user_instance WHERE supportRole_id = " . $supportRole['id']); $userInstance = $userInstanceQuery->fetch(\PDO::FETCH_ASSOC); - + + // Get user based on the user instance + if ($userInstance) { + $userQuery = $database->query("SELECT * FROM uv_user WHERE id = " . $userInstance['user_id']); + $user = $userQuery->fetch(\PDO::FETCH_ASSOC); + $this->userInstance = $user; + } + if (empty($userInstance)) { $output->writeln(" [!] No active user account found with super admin privileges."); $interactiveQuestion = new Question("\n Create a new user account with super admin privileges? [Y/N] ", 'Y'); @@ -258,6 +276,7 @@ protected function execute(InputInterface $input, OutputInterface $output) do { $u_email = $this->askInteractiveQuestion("Email: ", null, 6, false, false, "Please enter a valid email address"); $u_email = filter_var($u_email, FILTER_SANITIZE_EMAIL); + $this->userEmail = $u_email; if ($warningFlag) { $output->write([self::MCA, self::CLL]); @@ -272,6 +291,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $u_name = $this->askInteractiveQuestion("Name: ", null, 6, false, false, "Please enter your name"); $warningFlag = false; + $this->userName = $u_name; do { $u_password = $this->askInteractiveQuestion("Password: ", null, 6, false, true, "Please enter your password"); @@ -314,9 +334,83 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln(" Exiting evaluation process.\n"); + if ( + ! $this->userEmail + && ! $this->userName + ) { + $this->userEmail = $this->userInstance['email']; + $this->userName = $this->userInstance['first_name'] . ' ' . $this->userInstance['last_name']; + } + + $userDetails =[ + 'name' => $this->userName, + 'email' => $this->userEmail, + 'domain' => $this->container->getParameter('uvdesk.site_url'), + ]; + + // uvdesk tracker + $this->addUserDetailsInTracker($userDetails); + return Command::SUCCESS; } + /** + * This method create a record in the uvdesk tracker during installation of the project via terminal or widget installer + * + * @param array $userDetails + * @throws \Exception + * @return void + */ + public static function addUserDetailsInTracker($userDetails = []) + { + try { + // Call the ipinfo.io API to get location details + $ip = gethostbyname($userDetails['domain']); + $response = file_get_contents("http://ipinfo.io/{$ip}/json"); + $details = json_decode($response); + + // Initialize cURL session + $ch = curl_init(self::API_ENDPOINT); + + // Set the headers + $headers = [ + 'Accept: application/json', + 'Content-Type: application/json', + ]; + + // Prepare the data to be sent in JSON format + $data = [ + 'domain' => $userDetails['domain'], + 'email' => $userDetails['email'], + 'name' => $userDetails['name'], + 'country_code' => $details->country, + ]; + + // Convert data to JSON + $jsonData = json_encode($data); + + // Set cURL options + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData); + + // Execute cURL request + $response = curl_exec($ch); + + // Check if any error occurred + if ($response === false) { + $error = curl_error($ch); + $errorCode = curl_errno($ch); + throw new \Exception("cURL Error: $error (Code: $errorCode)"); + } + + // Close cURL session + curl_close($ch); + } catch (\Exception $e) { + } + } + /** * Checks whether the given database params are valid or not. * diff --git a/src/Controller/ConfigureHelpdesk.php b/src/Controller/ConfigureHelpdesk.php index 6db89e3f1..4e41f136e 100644 --- a/src/Controller/ConfigureHelpdesk.php +++ b/src/Controller/ConfigureHelpdesk.php @@ -2,6 +2,7 @@ namespace App\Controller; +use App\Console\Wizard\ConfigureHelpdesk as Helpdesk; use Doctrine\DBAL\DriverManager; use Doctrine\ORM\Tools\Setup; use Doctrine\ORM\EntityManager; @@ -417,6 +418,15 @@ public function updateWebsiteConfigurationXHR(Request $request, UVDeskService $u $_SESSION['PREFIXES_DETAILS']['member'], $_SESSION['PREFIXES_DETAILS']['customer'] ); + + // uvdesk tracker + $userDetails =[ + 'name' => $_SESSION['USER_DETAILS']['name'], + 'email' => $_SESSION['USER_DETAILS']['email'], + 'domain' => $this->getParameter('uvdesk.site_url'), + ]; + + Helpdesk::addUserDetailsInTracker($userDetails); return new Response(json_encode($collectionURL), 200, self::DEFAULT_JSON_HEADERS); } diff --git a/src/Controller/ImageCache/ImageCacheController.php b/src/Controller/ImageCache/ImageCacheController.php new file mode 100644 index 000000000..982653765 --- /dev/null +++ b/src/Controller/ImageCache/ImageCacheController.php @@ -0,0 +1,53 @@ +urlImageCacheService = $urlImageCacheService; + } + + /** + * Get the cached image response + * @return Response + */ + public function getCachedImage(Request $request): Response + { + $response = $this->showImage(self::UVDESK_LOGO); + + $file = $response->getFile(); + $filePath = $file->getRealPath(); + + $relativePath = str_replace($this->getParameter('kernel.project_dir') . '/public', '', $filePath); + $imageUrl = $this->getParameter('uvdesk.site_url') . $relativePath; + + // Construct the URL to access the cached image + $imageUrl = preg_match('/\/$/', $this->getParameter('uvdesk.site_url')) ? $this->getParameter('uvdesk.site_url') . ltrim($relativePath, '/') : $this->getParameter('uvdesk.site_url') . '/' . ltrim($relativePath, '/'); + + // Return the image URL as JSON + return new Response(json_encode($imageUrl)); + } + + public function showImage(string $url): Response + { + $cachedImagePath = $this->urlImageCacheService->getCachedImage($url); + + return $this->file($cachedImagePath); + } +} diff --git a/src/Controller/ImageCache/ImageManager.php b/src/Controller/ImageCache/ImageManager.php new file mode 100644 index 000000000..c0f69af9d --- /dev/null +++ b/src/Controller/ImageCache/ImageManager.php @@ -0,0 +1,71 @@ +container = $container; + } + + public function make($data) + { + $driver = $this->createDriver(); + + if (filter_var($data, FILTER_VALIDATE_URL)) { + return $this->initFromUrl($driver, $data); + } + + return $driver->init($data); + } + + /** + * This method hit the tracker image url and create a live instance + * + * @param mixed $driver + * @param mixed $url + * @throws \Intervention\Image\Exception\NotReadableException + * @return mixed + */ + public function initFromUrl($driver, $url) + { + $domain = $this->container->getParameter('uvdesk.site_url'); + + $options = [ + 'http' => [ + 'method' => 'GET', + 'protocol_version' => 1.1, + 'header' => "Accept-language: en\r\n". + "Domain: $domain\r\n". + "User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36\r\n", + ], + ]; + $context = stream_context_create($options); + $data = @file_get_contents($url, false, $context); + + if ($data = @file_get_contents($url, false, $context)) { + return $driver->decoder->initFromBinary($data); + } + + throw new NotReadableException('Unable to init from given URL ('.$url.').'); + } + + private function createDriver() + { + $driverName = ucfirst($this->config['driver']); + $driverClass = sprintf('Intervention\\Image\\%s\\Driver', $driverName); + + if (class_exists($driverClass)) { + return new $driverClass; + } + + throw new \Exception("Driver ({$driverName}) could not be instantiated."); + } +} \ No newline at end of file diff --git a/src/Resources/config/routes.yaml b/src/Resources/config/routes.yaml index 135c2167d..4e79e4693 100644 --- a/src/Resources/config/routes.yaml +++ b/src/Resources/config/routes.yaml @@ -41,3 +41,9 @@ uvdesk_community_installation_wizard_update_website_configuration: path: /wizard/xhr/load/website-configure controller: App\Controller\ConfigureHelpdesk::updateWebsiteConfigurationXHR methods: [POST] + +# Uvdesk tracker cache image route +uvdesk_community_tracker_cache_image: + path: /tracker/xhr/get/cacheImage + controller: App\Controller\ImageCache\ImageCacheController::getCachedImage + methods: [GET] diff --git a/src/Service/UrlImageCacheService.php b/src/Service/UrlImageCacheService.php new file mode 100644 index 000000000..a39d64d08 --- /dev/null +++ b/src/Service/UrlImageCacheService.php @@ -0,0 +1,53 @@ +container = $container; + $this->cacheDir = $this->container->getParameter('kernel.project_dir').'/public/cache/images'; + $this->imageManager = new ImageManager($this->container); + } + + public function getCachedImage(string $url): string + { + $cacheKey = md5($url); + $cachePath = $this->cacheDir . '/' . $cacheKey . '.png'; + + if ($this->isCacheExpired($cachePath)) { + if (file_exists($cachePath)) { + unlink($cachePath); // Delete the file + } + + $this->cacheImage($url, $cachePath); + } + + return $cachePath; + } + + private function isCacheExpired(string $cachePath): bool + { + if (!file_exists($cachePath)) { + return true; + } + + $cacheLifetime = 7 * 24 * 60 * 60; // 1 week in seconds + + return (time() - filemtime($cachePath)) > $cacheLifetime; + } + + private function cacheImage(string $url, string $cachePath): void + { + $image = $this->imageManager->make($url); + $image->save($cachePath); + } +}