Skip to content

Commit

Permalink
added code for installation tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
Ayush Raj Srivastava committed Aug 26, 2024
1 parent 650d4dd commit a32210a
Show file tree
Hide file tree
Showing 8 changed files with 295 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG-1.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
},
Expand Down
96 changes: 95 additions & 1 deletion src/Console/Wizard/ConfigureHelpdesk.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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(" <comment>[!]</comment> No active user account found with super admin privileges.");
$interactiveQuestion = new Question("\n <comment>Create a new user account with super admin privileges? [Y/N]</comment> ", 'Y');
Expand All @@ -258,6 +276,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
do {
$u_email = $this->askInteractiveQuestion("<info>Email</info>: ", 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]);
Expand All @@ -272,6 +291,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$u_name = $this->askInteractiveQuestion("<info>Name</info>: ", null, 6, false, false, "Please enter your name");

$warningFlag = false;
$this->userName = $u_name;

do {
$u_password = $this->askInteractiveQuestion("<info>Password</info>: ", null, 6, false, true, "Please enter your password");
Expand Down Expand Up @@ -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.
*
Expand Down
10 changes: 10 additions & 0 deletions src/Controller/ConfigureHelpdesk.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
53 changes: 53 additions & 0 deletions src/Controller/ImageCache/ImageCacheController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace App\Controller\ImageCache;

use App\Service\UrlImageCacheService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ImageCacheController extends AbstractController
{
/**
* Logo URL
*/
const UVDESK_LOGO = 'https://updates.uvdesk.com/uvdesk-logo.png';

protected $urlImageCacheService;
protected $urlGenerator;

public function __construct(
UrlImageCacheService $urlImageCacheService
) {
$this->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);
}
}
71 changes: 71 additions & 0 deletions src/Controller/ImageCache/ImageManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace App\Controller\ImageCache;

use Intervention\Image\Exception\NotReadableException;
use Intervention\Image\ImageManager as BaseImageManager;
use Symfony\Component\DependencyInjection\ContainerInterface;

class ImageManager extends BaseImageManager
{
protected $container;

public function __construct(ContainerInterface $container)
{
$this->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.");
}
}
6 changes: 6 additions & 0 deletions src/Resources/config/routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
53 changes: 53 additions & 0 deletions src/Service/UrlImageCacheService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace App\Service;

use App\Controller\ImageCache\ImageManager;
use Symfony\Component\DependencyInjection\ContainerInterface;

class UrlImageCacheService
{
protected $cacheDir;
protected $container;
private $imageManager;

public function __construct(ContainerInterface $container)
{
$this->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);
}
}

0 comments on commit a32210a

Please sign in to comment.