<?php
namespace App\Controller;
use App\Entity\{Category, Department};
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Service\{CardsService, DepartmentService, SpecialCharService};
class HomeController extends CoreController
{
/**
* @Route("/", name="app_home")
*/
public function display(SpecialCharService $specialCharService, CardsService $cards): Response
{
// We get back the session to see if the user is logged in
// And to check if they have clearance to see the homepage
$session = $this->requestStack->getSession();
$session->remove('sector');
$session->remove('service');
$response = $this->getAuthorizationResponse($session);
if ($response instanceof Response) {
return $this->render('errors.html.twig', $session->get('error'), $response);
}
// Defining the titles of the homepage
extract($cards->getTitles($specialCharService, 0));
// We create an associative array of the departments in order to get only the properties we need
$departmentsArray = $cards->setDepartmentsArray($specialCharService);
$departmentsArray = $cards->addImagesOnDepartments($departmentsArray);
dump($departmentsArray);
// TODO : delete line when DEVE okay
array_pop($departmentsArray);
// dump($departmentsArray);
return $this->render('home.html.twig', [
'categories' => $departmentsArray,
"sector" => $sector,
"service" => $serviceArray,
"headerLink" => 'app_home',
"department" => 0
]);
}
/**
* @Route("/deve", name="app_department_5")
* @Route("/snap", name="app_department_4")
* @Route("/service-de-la-documentation", name="app_department_3")
* @Route("/direction-des-affaires-financieres-et-comptables", name="app_department_2")
* @Route("/direction-du-patrimoine", name="app_department_1")
*/
public function displayDepartment(Request $request, SpecialCharService $specialCharService, CardsService $cards)
{
$currentPath = substr($request->getPathInfo(), 1); // the URI path being requested
$id = $cards->getDepartmentId($currentPath);
$session = $this->requestStack->getSession();
$response = $this->getAuthorizationResponse($session);
if ($response instanceof Response) {
return $this->render('errors.html.twig', $session->get('error'), $response);
}
extract($cards->getTitles($specialCharService, $id));
// We create an associative array of the departments in order to get only the properties we need
$departmentsArray = $cards->setDepartmentsArray($specialCharService, $id);
// Sets the categories into the $departmentsArray, with their properties, image and route.
$cardsArray = $cards->setCategories($departmentsArray, $id);
return $this->render('patrimoine/home.html.twig', [
'categories' => $cardsArray,
"sector" => $sector,
"service" => $serviceArray,
"id" => $id,
"headerLink" => 'app_home'
]);
}
/**
* @Route("/deve/ticket/success", name="app_success_5")
* @Route("/snap/ticket/success", name="app_success_4")
* @Route("/service-de-la-documentation/ticket/succes", name="app_success_3")
* @Route("/direction-des-affaires-financieres-et-comptables/ticket/succes", name="app_success__2")
* @Route("/direction-du-patrimoine/ticket/succes", name="app_success__1")
*/
public function showSuccess(): Response
{
$session = $this->requestStack->getSession();
$ticketId = $session->get('ticketId');
extract($this->handleUrlParams($session));
$messages = ["Votre demande a été envoyée avec succès."];
if ($sector === '3') {
$target = "le site de l'Université";
$messages = [...$messages, "Elle sera traitée sous 72 heures ouvrées."];
}
else {
$target = "la page d'Accueil";
}
return $this->render('form-success.html.twig', [
'messages' => $messages,
'sector' => $department,
'sectorId' => $sector,
'service' => $service,
'ticketId' => $ticketId,
'target' => $target,
"headerLink" => 'app_department_' . $sector
]);
}
/**
* Transforms the $departments array of objects into an array of associative arrays
* And filters the data so as to keep the only needed properties
*
* @param array $departments
* @return array
*/
private function setDepartmentsArray(ManagerRegistry $doctrine, SpecialCharService $specialCharService) {
$departments = $doctrine->getRepository(Department::class)->findAll();
$newDepartmentArray = [];
foreach ($departments as $currentDepartment) {
$newDep = [];
$newDep['id'] = $currentDepartment->getId();
$newDep['label'] = $currentDepartment->getXlab();
// $newDep['label'] = $specialCharService->setHomeCardsSpecialChars($currentDepartment);
$newDep['visibility'] = $currentDepartment->getVisi();
$newDep['categories'] = [];
array_push($newDepartmentArray, $newDep);
}
return $newDepartmentArray;
}
/**
* Method that gathers many functions to create the array that will receives all categories, sorted by department, with the needed properties, route and image.
*
* @param ManagerRegistry $doctrine
* @param array $departments
* @return array
*/
private function setCategories(ManagerRegistry $doctrine, $departments, $service) {
// We get all the categories from the database
$categories = $doctrine->getRepository(Category::class)->findAll();
// Adds the property route to each $categories, whether they do or don't have a matching route
// route can be an empty array or an array containing the route name and the department and category IDs
$categoriesWihRoutes = $this->setRoutesOnAllCategories($categories);
// Now we fetch the parent categories
$parents = array_filter($categoriesWihRoutes, function($cat) {
return $cat->getParentId() === null;
});
// And them we assign them their children and grand-children
$children = $service->setChildren($parents, $categoriesWihRoutes, $doctrine);
// Now we put all the matching categories into their parent array
$sortedArray = $this->sortByDepartmentAndAddImage($children, $departments);
// And finally, we replace empty sub-categories with they parent category.
$finalCardsArray = $this->replaceEmptySubCategories($sortedArray);
$finalCardsArray = $this->setOrderFirstDepartment($finalCardsArray);
return $finalCardsArray;
}
/**
* To each category, the functions adds a route if there is a match.
* It also sets the the rigth title/name for the category
*
* @param array $categories
* @return array
*/
private function setRoutesOnAllCategories($categories) {
$newCardsArray = array_map(function($cat) {
require __DIR__ . '/../Data/cardsData.php';
// Retrieves the keys of the array
$arrayKeys = array_keys($routes);
// To each category, we assgin an empty array as default route name
$cat->setRouteName([]);
// We change the label of the category so as to the client can read the special characters
$cat->setXlab(SpecialCharService::setHomeCardsSpecialChars($cat));
// Now we check the $arrayKeys
foreach ($arrayKeys as $key) {
// If the current key is contained in the category label
if (str_contains(strtolower($cat->getXlab()), $key)) {
// We set the matching route with the value associated to the key
// TODO : find a solution to keep the 34th category to ignore the reprographie route because of the "format" part of the name
if ($cat->getId() !== '34') {
$cat->setRouteName($routes[$key]);
}
}
}
return $cat;
}, $categories);
return $newCardsArray;
}
/**
* Complex function that identifies a category's children and stores into a sub-category roperty all of its children/grand-children
*
* @param array $parents
* @param array $children array of categories with routes
* @return array
*/
private function setChildren($parents, $categories, ManagerRegistry $doctrine) {
// DISCLAIMER : we are dealing with three different levels of categories, all stored in the same table of the database.
// Some of the categories are actually more like ticket subjects, we need to identify them
$subjectsIds = ['34', '35', '36'];
// For each parent category, we need to find if there are any children
foreach ($parents as $parent) {
// We create a new property, an array, that will welcome all of the sub-categories
$parent->subCategories = [];
// And a new array to welcome the current parent's children
$children = [];
// For each category
foreach($categories as $category) {
// If the current $category has a parentId property that matches the current $parent id
if ($category->getParentId() === $parent->getId()) {
// We push the category into the children array.
array_push($children, $category);
}
}
// if there is a least one child, meaning the current category's parentId matches the current parent id
if (count($children) > 0) {
foreach($children as $child) {
// We now check if there are any grandchildren to the current child
$grandChildren = $doctrine->getRepository(Category::class)->findByParentId($child->getId());
// If the current child id is in the $subjectsIds
if (array_search($child->getId(), $subjectsIds) !== false) {
// We retrieve its index so as to unset it
$childIndex = array_search($child, $children);
unset($children[$childIndex]);
}
// Then we push the grandchildren into the children array
// That way, we put them at the same level
foreach ($grandChildren as $grandChild) {
array_push($children, $grandChild) ;
}
// Finally, if there are any grandchildren
if (count($grandChildren) > 0) {
// We retrieve the index of the child in the children array so as to delete it
// Meaning the grandchildren actually replace the child
$childIndex = array_search($child, $children);
unset($children[$childIndex]);
}
};
// Finally, we push the children into the subCategories array we created at the beginning
array_push($parent->subCategories,...$children) ;
}
}
return $parents;
}
/**
* Stores the parent categories into the departments array
* In the process, adds the image matching the department
*
* @param array $categories
* @param array $departments
* @return array
*/
private function sortByDepartmentAndAddImage($categories, $departments) {
include __DIR__ . '/../Data/cardsData.php';
// Retrieves the keys of the array
$imagesArrayKeys = array_keys($images);
$newDepArray = [];
foreach ($departments as $department) {
foreach ($categories as $category) {
// if the current category's departmentId matches the current department's id
if ($category->getDepaId() === $department['id']) {
// We push the category into the categories property of the department
array_push($department['categories'], $category);
}
}
foreach ($imagesArrayKeys as $imageKey) {
// If the department's label contains the image key
if (str_contains($department['label'], $imageKey)) {
// We add the image property to the department
$department['image'] = $images[$imageKey];
}
}
array_push($newDepArray, $department);
}
return $newDepArray;
}
/**
* Functions that checks if the sub-categories array is empty
*
* @param array $cards
* @return array
*/
private function replaceEmptySubCategories ($cards) {
$newCardsArray = array_map(function($card) { // department level
$categories = array_map(function($cat) { // categories level
// If there are no subcategories
if (count($cat->subCategories) === 0) {
// We create a clone of the current category and we set it as the subcategory
$clone = clone $cat;
$cat->subCategories = [$clone];
}
return $cat;
}, $card['categories']);
$card['categories'] = $categories;
return $card;
}, $cards);
return $newCardsArray;
}
/**
* Rearranges the sub-categories of the Logistique category
* Descending order based on name length
*
* @param array $cards
* @return array
*/
private function setOrderFirstDepartment ($cards) {
$orderedSubcategories = [];
foreach ($cards[0]['categories'][0]->subCategories as $category) {
$orderedSubcategories[strlen($category->getXlab())] = $category;
}
// Sorts the array by key, in ascending order
ksort($orderedSubcategories);
$cards[0]['categories'][0]->subCategories = $orderedSubcategories;
return $cards;
}
}