<?php
namespace App\Twig;
use DateTime;
use Twig\TwigTest;
use App\Entity\Club;
use App\Entity\User;
use Twig\TwigFilter;
use App\Entity\Coach;
use App\Entity\Course;
use Twig\TwigFunction;
use App\Entity\Category;
use App\Entity\ClubInfo;
use App\Entity\Operator;
use App\Entity\CoachInfo;
use App\Entity\Partnership;
use App\Service\CourseService;
use App\Entity\CourseAvailability;
use App\Repository\NoteRepository;
use App\Repository\CourseRepository;
use App\Service\InternationalService;
use Symfony\Component\Intl\Countries;
use Twig\Extension\AbstractExtension;
use App\Repository\CategoryRepository;
use App\Repository\PartnershipRepository;
use App\Repository\ConversationRepository;
use App\Repository\WebsiteLanguageRepository;
use App\Repository\CourseAvailabilityRepository;
use App\Repository\NoteRequestRepository;
use App\Repository\TraineeRepository;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class AppExtension extends AbstractExtension
{
private $googleApiKeyBack;
public function __construct(
private ConversationRepository $conversationRepository,
private InternationalService $internationalService,
private CourseRepository $courseRepository,
private CourseAvailabilityRepository $courseAvailabilityRepository,
private RequestStack $requestStack,
private ParameterBagInterface $params,
private CategoryRepository $categoryRepository,
private WebsiteLanguageRepository $websiteLanguageRepository,
private UrlGeneratorInterface $router,
private CourseService $courseService,
private PartnershipRepository $partnershipRepository,
private NoteRepository $noteRepository,
private NoteRequestRepository $noteRequestRepository,
private TraineeRepository $traineeRepository
) {
$this->googleApiKeyBack = $this->params->get('api_key_google_back');
}
public function getTests()
{
return [
new TwigTest('instanceof', [$this, 'isInstanceof']),
new TwigTest('hasseveralavailabilities', [$this, 'hasSeveralAvailabilities']),
new TwigTest('fileexists', [$this, 'fileExists']),
];
}
public function getFunctions()
{
return [
new TwigFunction('conversationBetween', [$this, 'conversationBetween']),
new TwigFunction('countunreadmessages', [$this, 'countUnreadMessages']),
new TwigFunction('haveCommonIntership', [$this, 'haveCommonIntership']),
new TwigFunction('articleCategoryInfos', [$this, 'articleCategoryInfos']),
new TwigFunction('getOtherPartner', [$this, 'getOtherPartner']),
new TwigFunction('getNotes', [$this, 'getNotes']),
new TwigFunction('getAverageNotes', [$this, 'getAverageNotes']),
];
}
public function getFilters()
{
return [
new TwigFilter('nextdate', [$this, 'getNextDate']),
new TwigFilter('cheapestavailability', [$this, 'getCheapestAvailability']),
new TwigFilter('countryName', [$this, 'getCountryName']),
new TwigFilter('nextcalendarweek', [$this, 'getNextWeek']),
new TwigFilter('lastcalendarweek', [$this, 'getLastWeek']),
new TwigFilter('nextcalendarmonth', [$this, 'getNextMonth']),
new TwigFilter('lastcalendarmonth', [$this, 'getLastMonth']),
new TwigFilter('stringToDate', [$this, 'stringToDate']),
new TwigFilter('placeName', [$this, 'getPlaceName']),
new TwigFilter('getDifferenceDate', [$this, 'getDifferenceDate']),
new TwigFilter('courseTitleFromToken', [$this, 'courseTitleFromToken']),
new TwigFilter('proActiveCourses', [$this, 'proActiveCourses']),
new TwigFilter('countryPhoneCode', [$this, 'countryPhoneCode']),
new TwigFilter('userType', [$this, 'userType']),
new TwigFilter('statusReuqested', [$this, 'statusReuqested']),
];
}
public function statusReuqested($email)
{
$user = $this->traineeRepository->findOneBy(['email' => $email]);
if ($user) {
return 'registered';
}
return 'not-registered';
}
public function getNotes($pro)
{
$notes = $this->noteRepository->getProNotes($pro);
return $notes;
}
public function getAverageNotes($pro)
{
$total = 0;
$education = 0;
$organization = 0;
$count = 0;
$notes = $this->getNotes($pro);
foreach ($notes as $note) {
$organization += $note->getOrganization();
$education += $note->getEducation();
$count++;
}
$educationAverage = $count != 0 ? number_format((float)($education / $count), 1, '.', '') : 0;
$organizationAverage = $count != 0 ? number_format((float)($organization / $count), 1, '.', '') : 0;
$totalAverage = $count != 0 ? number_format((float)(($education + $organization) / ($count * 2)), 1, '.', '') : 0;
$average = [
'education' => $count != 0 ? $educationAverage : 0,
'organization' => $count != 0 ? $organizationAverage : 0,
'total' => $count != 0 ? $totalAverage : 0,
'count' => $count
];
return $average;
}
public function getOtherPartner(Partnership $partnership, $pro)
{
// Vérifie si le pro est un Coach et trouve l'autre professionnel
if ($partnership->getCoach() === $pro) {
return $partnership->getClub() ?? $partnership->getOperator();
}
// Vérifie si le pro est un Club et trouve l'autre professionnel
if ($partnership->getClub() === $pro) {
return $partnership->getCoach() ?? $partnership->getOperator();
}
// Vérifie si le pro est un Opérateur et trouve l'autre professionnel
if ($partnership->getOperator() === $pro) {
return $partnership->getCoach() ?? $partnership->getClub();
}
// Si le pro est le demandeur du partenariat, retourne l'autre professionnel
if ($partnership->getRequestedBy() !== $pro) {
if ($partnership->getCoach() !== $pro) {
return $partnership->getCoach();
} elseif ($partnership->getClub() !== $pro) {
return $partnership->getClub();
} elseif ($partnership->getOperator() !== $pro) {
return $partnership->getOperator();
}
}
return null; // Si le pro n'est pas impliqué ou aucune condition ne correspond
}
function countryPhoneCode($countryCode)
{
return $this->internationalService->countryPhoneCode($countryCode);
}
public function articleCategoryInfos(Category $category, $locale)
{
$language = $this->websiteLanguageRepository->findOneBy(['slug' => $locale]);
$categoryTranslated = $this->categoryRepository->findOneBy(['unit' => $category->getUnit(), 'websiteLanguage' => $language]);
return [
'title' => $categoryTranslated->getTitle(),
'link' => $this->router->generate('article_category', ['slug' => $categoryTranslated->getSlug()])
];
}
public function haveCommonIntership(User $owner, $partner)
{
return $this->courseRepository->areProTogetherOnActiveCourse($owner, $partner);
if ($partner instanceof Club) {
$clubInfo = $partner->getClubInfo();
$courses = $this->courseRepository->count(['owner' => $owner, 'club' => $clubInfo, 'status' => 'active']);
} else if ($partner instanceof Coach) {
$coachInfo = $partner->getCoachInfo();
$courses = $this->courseRepository->countActiveCourseBetween($owner, $coachInfo);
} else if ($partner instanceof Operator) {
$operatorInfo = $partner->getOperatorInfo();
$courses = $this->courseRepository->countActiveCourseBetween($partner, $operatorInfo);
}
if ($courses == 0) {
return false;
}
return true;
}
public function isInstanceof($var, $instance)
{
$reflexionClass = new \ReflectionClass($instance);
return $reflexionClass->isInstance($var);
}
function userType(User $user)
{
if ($user instanceof Coach) {
$type = 'coach';
} elseif ($user instanceof Club) {
$type = 'club';
} elseif ($user instanceof Operator) {
$type = 'operator';
}
return $type;
}
public function getNextDate(Course $course, $startingDate = null)
{
$nextAvailability = $this->courseService->getAvailabilities($course, 'single', $startingDate);
return $nextAvailability;
/*
if ($startingDate == null) {
$fromDate = new DateTime();
$fromDate->setTimestamp(strtotime('today midnight'));
}
else {
$fromDate = date_create_from_format('d/m/Y', $startingDate);
}
$date = null;
$nextAvailability = new CourseAvailability();
$frequency = $course->getFrequency();
if ($frequency == 'punctual') {
foreach ($course->getAvailabilities() as $availability) {
$begin = date_create_from_format('d/m/Y', $availability->getBegin());
if ($begin > $fromDate && ($date == null || $date > $begin)) {
$date = $begin;
$nextAvailability->setDuration($availability->getDuration())
->setPrice($availability->getPrice())
->setBegin($begin->format('d.m.y'))
->setEnd(date_create_from_format('d/m/Y', $availability->getEnd())->format('d.m.y'));
}
}
}
else {
foreach ($course->getAvailabilities() as $availability) {
$begin = date_create_from_format('d/m/Y', $availability->getBegin());
$endDate = null;
if ($availability->getEnd() != null) {
$endDate = date_create_from_format('d/m/Y', $availability->getEnd());
}
if ($endDate == null || $endDate > $fromDate) {
$startDay = $availability->getStartDate();
$recurrence = $availability->getRecurrence();
$currentDate = $begin;
switch ($startDay) {
case 'mon':
$startDay = 'monday';
break;
case 'tue':
$startDay = 'tuesday';
break;
case 'wed':
$startDay = 'wednesday';
break;
case 'thu':
$startDay = 'thursday';
break;
case 'fri':
$startDay = 'friday';
break;
case 'sat':
$startDay = 'saturday';
break;
case 'sun':
$startDay = 'sunday';
break;
}
if($startDay) {
if (strtolower($begin->format('l')) != $startDay) {
$currentDate->modify("next {$startDay}");
}
}
switch ($recurrence) {
case 'weekly':
$nextRecurrence = "next {$startDay}";
break;
case 'monthly':
$dayPosition = $availability->getDayPosition();
if ($dayPosition == '1') {
$nextRecurrence = "first {$startDay} of next month";
} else if ($dayPosition == '2') {
$nextRecurrence = "second {$startDay} of next month";
} else if ($dayPosition == '3') {
$nextRecurrence = "third {$startDay} of next month";
} else if ($dayPosition == '4') {
$nextRecurrence = "fourth {$startDay} of next month";
}
else if ($dayPosition == 'last') {
$nextRecurrence = "last {$startDay} of next month";
}
break;
}
while ($currentDate < $fromDate) {
$currentDate->modify($nextRecurrence);
}
if ($date == null || $date > ($currentDate && ($endDate == null || $endDate > $date))) {
$end = clone ($currentDate);
$end->modify("+{$availability->getDuration()} days");
$date = $currentDate;
$nextAvailability->setDuration($availability->getDuration())
->setPrice($availability->getPrice())
->setBegin($begin->format('d.m.y'))
->setEnd($end->format('d.m.y'));
}
}
}
}
return $nextAvailability;
*/
}
public function getCheapestAvailability(Course $course)
{
$cheapestAvailability = null;
foreach ($course->getAvailabilities() as $availability) {
if ($cheapestAvailability == null || $cheapestAvailability->getPrice() > $availability->getPrice()) {
$cheapestAvailability = $availability;
}
}
return $cheapestAvailability;
}
public function getNextWeek($date)
{
$dateTime = new \DateTime($date);
$dateTime->modify('+1 week');
return $dateTime->format('Y-m-d');
}
public function getLastWeek($date)
{
$dateTime = new \DateTime($date);
$dateTime->modify('-1 week');
return $dateTime->format('Y-m-d');
}
public function getNextMonth($date)
{
$dateTime = new \DateTime($date);
$dateTime->modify('+1 month');
$dateTime->modify('first monday of this month');
return $dateTime->format('Y-m-d');
}
public function getLastMonth($date)
{
$dateTime = new \DateTime($date);
$dateTime->modify('-1 month');
$dateTime->modify('first monday of this month');
return $dateTime->format('Y-m-d');
}
public function stringToDate($string)
{
$date = date_create_from_format('d.m.y', $string);
return ($date);
}
public function getPlaceName($place, $locale)
{
$response = file_get_contents("https://maps.googleapis.com/maps/api/place/details/json?place_id={$place}&key={$this->googleApiKeyBack}&language={$locale}");
$resultJson = json_decode($response);
return $resultJson->result->formatted_address;
}
public function getCountryName($countryCode, $locale)
{
return Countries::getName($countryCode, $locale);
}
public function getDifferenceDate($created)
{
$now = date("Y-m-d");
$diff = $now - $created;
return $diff;
}
public function conversationBetween($pro, $trainee)
{
$conversation = $this->conversationRepository->findOneBy(['pro' => $pro, 'trainee' => $trainee]);
return $conversation ? $conversation->getToken() : null;
}
public function courseTitleFromToken($token)
{
$course = $this->courseRepository->findOneBy(['token' => $token]);
$request = $this->requestStack->getCurrentRequest();
try {
$courseName = $course->getTranslatedContent($request->getLocale())->getName();
} catch (\Throwable $th) {
$courseName = '';
}
return $courseName;
}
public function hasSeveralAvailabilities(Course $course, $startingDate = null)
{
if ($startingDate == null) {
$fromDate = new DateTime();
$fromDate->setTimestamp(strtotime('today midnight'));
} else {
$fromDate = date_create_from_format('d/m/Y', $startingDate);
}
$nextAvailabilities = [];
$allAvailabilities = $this->courseAvailabilityRepository->findAvailabilities($course);
$frequency = $course->getFrequency();
if ($frequency == 'punctual') {
foreach ($allAvailabilities as $availability) {
$begin = date_create_from_format('d/m/Y', $availability->getBegin());
if ($begin > $fromDate) {
$currentAvailability = new CourseAvailability();
$currentAvailability->setDuration($availability->getDuration())
->setPrice($availability->getPrice())
->setBegin($begin->format('d.m.y'))
->setEnd(date_create_from_format('d/m/Y', $availability->getEnd())->format('d.m.y'));
$nextAvailabilities[] = $currentAvailability;
}
}
} else {
foreach ($allAvailabilities as $availability) {
$begin = date_create_from_format('d/m/Y', $availability->getBegin());
$endDate = null;
if ($availability->getEnd() != null) {
$endDate = date_create_from_format('d/m/Y', $availability->getEnd());
}
if ($endDate == null || $endDate > $fromDate) {
$startDay = $availability->getStartDate();
$recurrence = $availability->getRecurrence();
$duration = $availability->getDuration();
$currentDate = clone ($begin);
/*
switch ($startDay) {
case 'mon':
$startDay = 'monday';
break;
case 'tue':
$startDay = 'tuesday';
break;
case 'wed':
$startDay = 'wednesday';
break;
case 'thu':
$startDay = 'thursday';
break;
case 'fri':
$startDay = 'friday';
break;
case 'sat':
$startDay = 'saturday';
break;
case 'sun':
$startDay = 'sunday';
break;
}
*/
$currentDate->modify("next {$startDay}");
switch ($recurrence) {
case 'weekly':
$nextRecurrence = "next {$startDay}";
break;
case 'monthly':
$dayPosition = $availability->getDayPosition();
if ($dayPosition == '1') {
$nextRecurrence = "first {$startDay} of next month";
} else if ($dayPosition == '2') {
$nextRecurrence = "second {$startDay} of next month";
} else if ($dayPosition == '3') {
$nextRecurrence = "third {$startDay} of next month";
} else if ($dayPosition == '4') {
$nextRecurrence = "fourth {$startDay} of next month";
} else if ($dayPosition == 'last') {
$nextRecurrence = "last {$startDay} of next month";
}
break;
}
while ($currentDate < $fromDate) {
$currentDate->modify($nextRecurrence);
}
for ($i = 0; $i < 10; $i++) {
$end = clone ($currentDate);
$end->modify("+{$duration} days");
$currentAvailability = new CourseAvailability();
$currentAvailability->setDuration($duration)
->setPrice($availability->getPrice())
->setBegin($currentDate->format('d.m.y'))
->setEnd($end->format('d.m.y'));
if ($endDate == null || $endDate > $currentDate) {
array_push($nextAvailabilities, $currentAvailability);
}
$currentDate->modify($nextRecurrence);
}
}
}
}
if (count($nextAvailabilities) > 1) {
return true;
}
return false;
}
public function fileExists($file, $directory)
{
if (file_exists($this->params->get($directory) . '/' . $file)) {
return true;
}
return false;
}
public function countUnreadMessages($user)
{
$number = 0;
$conversations = $this->conversationRepository->getMessages($user);
foreach ($conversations as $conversation) {
$lastMessage = $conversation->getLastMessage();
if ($lastMessage->getSender() != $user && $lastMessage->getIsReaded() == false) {
$number++;
}
}
return $number;
}
public function proActiveCourses(User $pro)
{
return $this->courseRepository->countProActiveCourses($pro);
}
}