src/Controller/ClinicsController.php line 54
<?php
namespace App\Controller;
use App\Entity\Addresses;
use App\Entity\AiSpecies;
use App\Entity\Baskets;
use App\Entity\ClinicCommunicationMethods;
use App\Entity\Clinics;
use App\Entity\ClinicUserPermissions;
use App\Entity\ClinicUsers;
use App\Entity\CommunicationMethods;
use App\Entity\Countries;
use App\Entity\Distributors;
use App\Entity\DistributorUsers;
use App\Entity\Lists;
use App\Entity\RestrictedDomains;
use App\Entity\Species;
use App\Entity\UserPermissions;
use App\Form\AddressesFormType;
use App\Form\ClinicCommunicationMethodsFormType;
use App\Form\ClinicFormType;
use App\Form\ClinicUsersFormType;
use App\Services\PaginationManager;
use Doctrine\ORM\EntityManagerInterface;
use Nzo\UrlEncryptorBundle\Encryptor\Encryptor;
use phpDocumentor\Reflection\Types\This;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
class ClinicsController extends AbstractController
{
const ITEMS_PER_PAGE = 12;
private $em;
private $plainPassword;
private $encryptor;
private $mailer;
private $pageManager;
public function __construct(EntityManagerInterface $em, Encryptor $encryptor, MailerInterface $mailer, PaginationManager $pageManager)
{
$this->em = $em;
$this->encryptor = $encryptor;
$this->mailer = $mailer;
$this->pageManager = $pageManager;
}
#[Route('/clinics/register', name: 'clinic_reg')]
public function clinicReg(Request $request): Response
{
$clinics = new Clinics();
$clinicUsers = new ClinicUsers();
$clinics->getClinicUsers()->add($clinicUsers);
$form = $this->createForm(ClinicFormType::class, $clinics)->createView();
$countries = $this->em->getRepository(Countries::class)->findBy([
'isActive' => 1,
]);
return $this->render('frontend/clinics/register.html.twig', [
'form' => $form,
'countries' => $countries,
]);
}
#[Route('/clinics/register/check-email', name: 'clinic_check_email')]
public function clinicsCheckEmailAction(Request $request): Response
{
$email = $request->request->get('email');
$domainName = explode('@', $email);
$response['response'] = true;
$restrictedDomains = $this->em->getRepository(RestrictedDomains::class)->arrayFindAll();
$firstName = '';
foreach($restrictedDomains as $restrictedDomain)
{
if(md5($domainName[1]) == md5($restrictedDomain->getName()))
{
$response['response'] = false;
$response['restricted'] = true;
return new JsonResponse($response);
}
}
$distributor = $this->em->getRepository(Distributors::class)->findOneBy([
'hashedEmail' => md5($email),
]);
$distributorDomain = $this->em->getRepository(Distributors::class)->findOneBy([
'domainName' => md5($domainName[1]),
]);
$distributorUsers = $this->em->getRepository(DistributorUsers::class)->findOneBy([
'hashedEmail' => md5($email),
]);
$clinic = $this->em->getRepository(Clinics::class)->findOneBy([
'hashedEmail' => md5($email),
]);
$clinicDomain = $this->em->getRepository(Clinics::class)->findOneBy([
'domainName' => md5($domainName[1]),
]);
$clinicUsers = $this->em->getRepository(ClinicUsers::class)->findOneBy([
'hashedEmail' => md5($email),
]);
if($clinicDomain != null)
{
$user = $this->em->getRepository(ClinicUsers::class)->findOneBy([
'clinic' => $clinicDomain->getId(),
'isPrimary' => 1
]);
if($user != null)
{
$firstName = $this->encryptor->decrypt($user->getFirstName());
}
}
if($distributorDomain != null)
{
$user = $this->em->getRepository(DistributorUsers::class)->findOneBy([
'distributor' => $distributorDomain->getId(),
'isPrimary' => 1
]);
if($user != null)
{
$firstName = $this->encryptor->decrypt($user->getFirstName());
}
}
$response['firstName'] = $firstName;
if($distributor != null || $distributorUsers != null || $clinic != null || $clinicUsers != null || $clinicDomain != null || $distributorDomain != null){
$response['response'] = false;
}
return new JsonResponse($response);
}
#[Route('/clinics/register/create', name: 'clinic_create')]
public function clinicsCreateAction(Request $request, UserPasswordHasherInterface $passwordHasher, MailerInterface $mailer): Response
{
$data = $request->request;
$clinics = $this->em->getRepository(Clinics::class)->findOneBy(['hashedEmail' => md5($data->get('email'))]);
if($clinics == null) {
$clinics = new Clinics();
$plainTextPwd = $this->generatePassword();
if (!empty($plainTextPwd)) {
$domainName = explode('@', $data->get('email'));
$country = $this->em->getRepository(Countries::class)->find($data->get('country'));
$clinics->setClinicName($this->encryptor->encrypt($data->get('clinicName')));
$clinics->setEmail($this->encryptor->encrypt($data->get('email')));
$clinics->setHashedEmail(md5($data->get('email')));
$clinics->setDomainName(md5($domainName[1]));
$clinics->setTelephone($this->encryptor->encrypt($data->get('telephone')));
$clinics->setIntlCode($this->encryptor->encrypt($data->get('business-intl-code')));
$clinics->setIsoCode($this->encryptor->encrypt($data->get('business-iso-code')));
$clinics->setCountry($country);
$clinics->setIsApproved(0);
$this->em->persist($clinics);
$this->em->flush();
// Create user
$clinic = $this->em->getRepository(Clinics::class)->findOneBy([
'hashedEmail' => md5($data->get('email')),
]);
$clinicUsers = new ClinicUsers();
$hashedPwd = $passwordHasher->hashPassword($clinicUsers, $plainTextPwd);
$clinicUsers->setClinic($clinic);
$clinicUsers->setFirstName($this->encryptor->encrypt($data->get('firstName')));
$clinicUsers->setLastName($this->encryptor->encrypt($data->get('lastName')));
$clinicUsers->setPosition($this->encryptor->encrypt($data->get('position')));
$clinicUsers->setEmail($this->encryptor->encrypt($data->get('email')));
$clinicUsers->setHashedEmail(md5($data->get('email')));
$clinicUsers->setTelephone($this->encryptor->encrypt($data->get('mobile-telephone')));
$clinicUsers->setIntlCode($this->encryptor->encrypt($data->get('mobile-intl-code')));
$clinicUsers->setIsoCode($this->encryptor->encrypt($data->get('mobile-iso-code')));
$clinicUsers->setRoles(['ROLE_CLINIC']);
$clinicUsers->setPassword($hashedPwd);
$clinicUsers->setIsPrimary(1);
$this->em->persist($clinicUsers);
// Assign Full Permissions
$userPermissions = $this->em->getRepository(UserPermissions::class)->findBy([
'isClinic' => 1,
]);
foreach($userPermissions as $userPermission){
$clinicUserPermissions = new ClinicUserPermissions();
$clinicUserPermissions->setClinic($clinic);
$clinicUserPermissions->setUser($clinicUsers);
$clinicUserPermissions->setPermission($userPermission);
$this->em->persist($clinicUserPermissions);
}
// Create Default Basket
$basket = new Baskets();
$firstName = $this->encryptor->decrypt($clinicUsers->getFirstName());
$lastName = $this->encryptor->decrypt($clinicUsers->getLastName());
$basket->setClinic($clinic);
$basket->setName('Fluid Commerce');
$basket->setTotal(0);
$basket->setStatus('active');
$basket->setIsDefault(1);
$basket->setSavedBy($this->encryptor->encrypt($firstName .' '. $lastName));
$this->em->persist($basket);
// Create In App Communication Method
$clinicCommunicationMethod = new ClinicCommunicationMethods();
$communicationMethod = $this->em->getRepository(CommunicationMethods::class)->find(1);
$clinicCommunicationMethod->setClinic($clinic);
$clinicCommunicationMethod->setCommunicationMethod($communicationMethod);
$clinicCommunicationMethod->setSendTo($this->encryptor->encrypt($data->get('email')));
$clinicCommunicationMethod->setIsDefault(1);
$clinicCommunicationMethod->setIsActive(1);
$this->em->persist($clinicCommunicationMethod);
// Create Favourites List
$favourite = new Lists();
$favourite->setClinic($clinic);
$favourite->setListType('favourite');
$favourite->setName('Favourite Items');
$favourite->setItemCount(0);
$favourite->setIsProtected(1);
$this->em->persist($favourite);
$this->em->flush();
// Send Email
$body = $this->render('frontend/clinics/emails/login_credentials.html.twig', [
'user' => $clinicUsers,
'password' => $plainTextPwd,
])->getContent();
$subject = 'Fluid Login Credentials';
$to = $data->get('email');
exec(__DIR__ . '/../../bin/console app:send-email "'. $subject .'" "'. addslashes($body) .'" "'. $to .'" "" "" "'. true .'" > /dev/null 2>&1 &');
}
$response = 'Your Fluid account was successfully created, an email with your login credentials has been sent to your inbox.';
} else {
$response = false;
}
return new JsonResponse($response);
}
#[Route('/clinics/get-company-information', name: 'get_clinic_company_information')]
public function clinicsGetCompanyInformationAction(Request $request): Response
{
$response = json_decode($this->forward('App\Controller\AiProductsController::isAuthenticated')->getContent(), true);
if(!$response['isAuthenticated'])
{
return $this->redirectToRoute('clinics_login');
}
$species = $this->em->getRepository(AiSpecies::class)->findByNameAsc();
$permissions = json_decode($request->request->get('permissions'), true);
$countries = $this->em->getRepository(Countries::class)->findBy([
'isActive' => 1,
]);
$clinic = $this->em->getRepository(Clinics::class)->find($this->getUser()->getClinic()->getId());
$response = $this->render('frontend/clinics/company_information.html.twig', [
'permissions' => $permissions,
'species' => $species,
'countries' => $countries,
'clinic' => $clinic,
])->getContent();
return new JsonResponse($response);
}
#[Route('/clinics/update/company-information', name: 'clinic_update_company_information')]
public function clinicsUpdateCompanyInformationAction(Request $request): Response
{
$response = json_decode($this->forward('App\Controller\AiProductsController::isAuthenticated')->getContent(), true);
if(!$response['isAuthenticated'])
{
$response = [
'isAuthenticated' => false,
];
return new JsonResponse($response);
}
$data = $request->request->all('clinic_form');
$clinicId = $this->getUser()->getClinic()->getId();
$clinics = $this->em->getRepository(Clinics::class)->find($clinicId);
$isApproved = (bool) $clinics->getIsApproved() ?? false;
$tradeLicense = $_FILES['clinic_form']['name']['trade-license-file'];
$tradeLicenseNo = $data['trade-license-no'];
$tradeLicenseExpDate = $data['trade-license-exp-date'];
// Account approval required if reg docs change
if(
!empty($tradeLicense) || $tradeLicenseNo != $this->encryptor->decrypt($clinics->getTradeLicenseNo()) ||
$tradeLicenseExpDate != $clinics->getTradeLicenseExpDate()->format('Y-m-d')
)
{
$clinics->setIsApproved(0);
$isApproved = false;
}
if($clinics != null)
{
$domainName = explode('@', $data['email']);
$clinics->setClinicName($this->encryptor->encrypt($data['clinic-name']));
$clinics->setEmail($this->encryptor->encrypt($data['email']));
$clinics->setDomainName(md5($domainName[1]));
$clinics->setTelephone($this->encryptor->encrypt($data['telephone']));
$clinics->setIsoCode($this->encryptor->encrypt($data['iso-code']));
$clinics->setIntlCode($this->encryptor->encrypt($data['intl-code']));
$clinics->setManagerFirstName($this->encryptor->encrypt($data['manager-first-name']));
$clinics->setManagerLastName($this->encryptor->encrypt($data['manager-last-name']));
$clinics->setManagerIdNo($this->encryptor->encrypt($data['manager-id-no']));
$clinics->setManagerIdExpDate(new \DateTime($data['manager-id-exp-date']));
$clinics->setTradeLicenseNo($this->encryptor->encrypt($data['trade-license-no']));
$clinics->setTradeLicenseExpDate(new \DateTime($data['trade-license-exp-date']));
// Trade License
if(!empty($_FILES['clinic_form']['name']['trade-license-file']))
{
$extension = pathinfo($_FILES['clinic_form']['name']['trade-license-file'], PATHINFO_EXTENSION);
$file = $clinics->getId() . '-' . uniqid() . '.' . $extension;
$targetFile = __DIR__ . '/../../public/documents/' . $file;
if(move_uploaded_file($_FILES['clinic_form']['tmp_name']['trade-license-file'], $targetFile)) {
$clinics->setTradeLicense($file);
}
}
// Logo
if(!empty($_FILES['clinic_form']['name']['logo']))
{
$extension = pathinfo($_FILES['clinic_form']['name']['logo'], PATHINFO_EXTENSION);
$file = $clinics->getId() . '-' . uniqid() . '.' . $extension;
$targetFile = __DIR__ . '/../../public/images/logos/' . $file;
if(move_uploaded_file($_FILES['clinic_form']['tmp_name']['logo'], $targetFile)) {
$clinics->setLogo($file);
}
}
$this->em->persist($clinics);
$this->em->flush();
// Send Approval Email
if(!$isApproved)
{
$orderUrl = $this->getParameter('app.base_url') . '/admin/clinic/'. $clinics->getId();
$html = '<p>Please <a href="'. $orderUrl .'">click here</a> the clinics details.</p><br>';
$html = $this->forward('App\Controller\ResetPasswordController::emailFooter', [
'html' => $html,
])->getContent();
$subject = 'Fluid - Account Approval Request';
$to = $this->getParameter('app.email_admin');
exec(__DIR__ . '/../../bin/console app:send-email "'. $subject .'" "'. addslashes($html) .'" "'. $to .'" "" "" "'. true .'" > /dev/null 2>&1 &');
}
$response = [
'flash' => '<b><i class="fa-solid fa-circle-check"></i></i></b> Company details successfully updated.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>',
'isAuthenticated' => true,
];
}
else
{
$response = [
'flash' => '<b><i class="fas fa-check-circle"></i> An error occurred.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>',
'isAuthenticated' => true,
];
}
return new JsonResponse($response);
}
#[Route('/clinics/download/trade-license/{tradeLicense}', name: 'clinics_download_trade_license')]
public function downloadTradeLicenseAction(Request $request)
{
$path = __DIR__ . '/../../public/documents/';
$tradeLicense = $path . $request->get('tradeLicense');
$response = new BinaryFileResponse($tradeLicense);
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
basename($tradeLicense)
);
return $response;
}
#[Route('/clinics/update/copy', name: 'clinic_update_copy')]
public function clinicsUpdateCopyAction(Request $request): Response
{
$response = json_decode($this->forward('App\Controller\AiProductsController::isAuthenticated')->getContent(), true);
if(!$response['isAuthenticated'])
{
$response = [
'isAuthenticated' => false,
];
return new JsonResponse($response);
}
$response = [];
if($this->getUser() == null)
{
return new JsonResponse('Please login..');
}
$clinic = $this->getUser()->getClinic();
$copy = $request->request->get('copy');
$method = $request->request->get('method');
$clinic->$method($copy);
$this->em->persist($clinic);
$this->em->flush();
$response['flash'] = '<b><i class="fa-solid fa-circle-check"></i></i></b> Successfully saved.<div class="flash-close"><i class="fa-solid fa-xmark"></i></div>';
$response['isAuthenticated'] = true;
return new JsonResponse($response);
}
#[Route('/admin/get/clinics-list', name: 'get_clinics_list')]
public function getClinicsList(Request $request): Response
{
$isApproved = $request->request->get('status') ?? 1;
$searchString = $request->request->get('search-string') ?? '';
$pageId = $request->request->get('page-id') ?? 1;
$clinics = $this->em->getRepository(Clinics::class)->adminFindAll($isApproved, $searchString);
$results = $this->pageManager->paginate($clinics[0], $request, self::ITEMS_PER_PAGE, $pageId);
$dataAction = 'data-action="click->admin--clinics#onClickGetList"';
$pagination = $this->getPagination($pageId, $results, $dataAction, self::ITEMS_PER_PAGE);
$isStatusChange = $request->request->get('is-status-change') ?? 0;
$html = $this->render('Admin/clinics/clinics_list.html.twig', [
'clinics' => $results,
'pagination' => $pagination,
'isStatusChange' => $isStatusChange,
])->getContent();
return new JsonResponse($html);
}
#[Route('/admin/get/clinic-form', name: 'get_clinic_form')]
public function getClinicForm(Request $request): Response
{
$clinicId = $request->request->get('clinic-id') ?? 0;
$clinic = $this->em->getRepository(Clinics::class)->find($clinicId);
$clinicUsers = $this->em->getRepository(ClinicUsers::class)->findBy([
'clinic' => $clinicId,
'isApproved' => true
]);
$userPermissions = $this->em->getRepository(UserPermissions::class)->findBy([
'isClinic' => 1
]);
if($clinic == null){
$clinic = new Clinics();
}
$html = $this->render('Admin/clinics/clinics.html.twig',[
'clinic' => $clinic,
'clinicUsers' => $clinicUsers,
'userPermissions' => $userPermissions
])->getContent();
return new JsonResponse($html);
}
private function generatePassword()
{
$sets = [];
$sets[] = 'abcdefghjkmnpqrstuvwxyz';
$sets[] = 'ABCDEFGHJKMNPQRSTUVWXYZ';
$sets[] = '23456789';
$sets[] = '!@$%*?';
$all = '';
$password = '';
foreach ($sets as $set) {
$password .= $set[array_rand(str_split($set))];
$all .= $set;
}
$all = str_split($all);
for ($i = 0; $i < 16 - count($sets); $i++) {
$password .= $all[array_rand($all)];
}
$this->plainPassword = str_shuffle($password);
return $this->plainPassword;
}
#[Route('/clinics/error', name: 'clinic_error_500')]
public function clinic500ErrorAction(Request $request): Response
{
$username = $this->getUser();
$id = '';
if($username != null) {
$id = $this->getUser()->getClinic()->getId();
}
return $this->render('bundles/TwigBundle/Exception/error500.html.twig', [
'type' => 'clinics',
'id' => $id,
]);
}
#[Route('/admin/submit/clinic/crud', name: 'admin_submit_clinic_crud')]
public function submitClinicCrud(Request $request): Response
{
$data = $request->request;
$clinicId = $request->get('clinic-id') ?? $data->get('delete');
$clinic = $this->em->getRepository(Clinics::class)->find($clinicId);
$response['clinicUsers'] = $this->em->getRepository(ClinicUsers::class)->findBy([
'clinic' => $clinicId,
]);
if($data->get('delete') != null)
{
$response = $this->deleteUser($data->get('delete'));
return new JsonResponse($response);
}
$response['flash'] = '';
if(!empty($data))
{
// Clinic Details
$this->saveClinic($data, $clinic);
// Clinic Users
$this->saveClinicUsers($data, $clinic);
$response['flash'] = 'Clinic Successfully Updated.';
$response['clinicName'] = $data->get('clinic_name');
}
return new JsonResponse($response);
}
public function deleteUser($userId): array
{
$user = $this->em->getRepository(ClinicUsers::class)->find($userId);
$response['flash'] = 'User Not Found!';
$response['type'] = 'danger';
if($user != null)
{
$user->setIsApproved(false);
$this->em->persist($user);
$this->em->flush();
$response['flash'] = 'User Successfully Deleted.';
$response['type'] = 'success';
}
return $response;
}
public function saveClinic($data, Clinics $clinic)
{
$clinic->setIsApproved($data->get('is-approved'));
$clinic->setClinicName($this->encryptor->encrypt($data->get('clinic_name')));
$clinic->setEmail($this->encryptor->encrypt($data->get('email')));
$clinic->setTelephone($this->encryptor->encrypt($data->get('telephone')));
$clinic->setManagerFirstName($this->encryptor->encrypt($data->get('manager-first-name')));
$clinic->setManagerLastName($this->encryptor->encrypt($data->get('manager-last-name')));
$clinic->setManagerIdNo($this->encryptor->encrypt($data->get('manager-id-no')));
$clinic->setManagerIdExpDate(new \DateTime($data->get('manager-id-exp-date')));
$this->em->persist($clinic);
$this->em->flush();
}
public function saveClinicUsers($data, $clinic)
{
if(count($data->all('user_id')) > 0)
{
// Loop users
for($i = 0; $i < count($data->all('user_id')); $i++)
{
$userId = $data->all('user_id')[$i];
// Save user
$clinicUser = $this->saveUser($data, $i, $userId);
// User Permissions
$userPermissions = $this->em->getRepository(ClinicUserPermissions::class)->findBy([
'user' => $userId
]);
// Remove currently saved
$this->deleteUserPermissions($userPermissions);
// Save new permissions
$this->createUserPermissions($data, $clinic, $clinicUser);
}
$this->em->flush();
}
}
public function saveUser($data, $i, $userId): object
{
$firstName = $data->all('user_first_name')[$i];
$lastName = $data->all('user_last_name')[$i];
$userEmail = $data->all('user_email')[$i];
$userTelephone = $data->all('user_telephone')[$i];
$clinicUser = $this->em->getRepository(ClinicUsers::class)->find($userId);
$clinicUser->setFirstName($this->encryptor->encrypt($firstName));
$clinicUser->setLastName($this->encryptor->encrypt($lastName));
$clinicUser->setEmail($this->encryptor->encrypt($userEmail));
$clinicUser->setTelephone($this->encryptor->encrypt($userTelephone));
$this->em->persist($clinicUser);
$this->em->flush();
return $clinicUser;
}
public function deleteUserPermissions($userPermissions)
{
foreach($userPermissions as $userPermission)
{
$this->em->remove($userPermission);
}
$this->em->flush();
}
public function createUserPermissions($data, $clinic, $clinicUsers)
{
if($data->all('user_permissions') != null)
{
foreach ($data->all('user_permissions') as $permissionId)
{
$pieces = explode('_', $permissionId);
if ($pieces[1] == $clinicUsers->getId())
{
$userPermission = new ClinicUserPermissions();
$permission = $this->em->getRepository(UserPermissions::class)->find($permissionId);
$userPermission->setPermission($permission);
$userPermission->setClinic($clinic);
$userPermission->setUser($clinicUsers);
$this->em->persist($userPermission);
}
}
$this->em->flush();
}
}
public function getPagination($currentPage, $results, $dataAction = '', $itemsPerPage = 10): string
{
return $this->render('pagination.html.twig', [
'currentPage' => $currentPage,
'results' => $results,
'dataAction' => $dataAction,
'itemsPerPage' => $itemsPerPage,
'lastPage' => $this->pageManager->lastPage($results),
'totalPages' => ceil(count($results) / $itemsPerPage),
'i' => max(1, $currentPage - 5),
'forLimit' => min($currentPage + 5, ceil(count($results) / $itemsPerPage)),
])->getContent();
}
}