src/EventSubscriber/EasyAdminSubscriber.php line 528
<?php
# src/EventSubscriber/EasyAdminSubscriber.php
namespace App\EventSubscriber;
use App\Entity\ExportExcel;
use App\Entity\FrontTheme;
use App\Entity\Settings;
use App\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Persistence\ManagerRegistry;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use ReflectionClass;
use ReflectionMethod;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Yaml\Yaml;
use ZipArchive;
use Symfony\Contracts\Translation\TranslatorInterface;
class EasyAdminSubscriber implements EventSubscriberInterface
{
public function __construct(
private readonly Security $security,
private readonly UserPasswordHasherInterface $passwordEncoder,
private readonly ManagerRegistry $doctrine,
private readonly TranslatorInterface $translatorInterface
)
{
}
public static function getSubscribedEvents()
{
return [
BeforeEntityPersistedEvent::class => ['beforePersist'],
BeforeEntityUpdatedEvent::class => ['beforeUpdated'],
BeforeEntityDeletedEvent::class => ['beforeDelete']
];
}
public function beforePersist(BeforeEntityPersistedEvent $event)
{
$entity = $event->getEntityInstance();
if($entity instanceof FrontTheme){
$filesystem = new Filesystem();
$finder = new Finder();
$path = __DIR__."/../../public/uploads/".$entity->getName();
if(!$filesystem->exists($path) )
{
$filesystem->mkdir($path,0777);
$filesystem->mkdir($path."/pages",0777);
$filesystem->mkdir($path."/shop",0777);
}
$pathFrontBundle = __DIR__."/../Flexy/FrontBundle";
$themePath = $pathFrontBundle."/Themes";
$filesystem->mirror($themePath."/Default",$themePath."/".ucfirst($entity->getName()));
//$filesystem->mkdir(__DIR__."/../../public/themes/".strtolower($entity->getName()),0777);
$filesystem->symlink($themePath."/".$entity->getName()."/assets", __DIR__."/../../public/themes/".strtolower($entity->getName()));
//Step 1 : Copy Controllers
$finder->in($themePath."/".ucfirst($entity->getName())."/Controller");
$finder->files()->contains("Default");
foreach ($finder as $file) {
$file_contents = file_get_contents($file->getPathname());
$file_contents = str_replace("Default\Controller", ucfirst($entity->getName())."\Controller", $file_contents);
$file_contents = str_replace("Default\Form", ucfirst($entity->getName())."\Form", $file_contents);
file_put_contents($file->getPathname(), $file_contents);
}
//Step 2 : Copy Forms
$finder->in($themePath."/".ucfirst($entity->getName())."/Form");
$finder->files()->contains("Default");
//dd($finder->hasResults());
foreach ($finder as $file) {
$file_contents = file_get_contents($file->getPathname());
$file_contents = str_replace("Default\Form", ucfirst($entity->getName())."\Form", $file_contents);
file_put_contents($file->getPathname(), $file_contents);
}
//Step 3 : Copy assets
//$assetsPath = $pathFrontBundle."/Resources/public/assets";
//$filesystem->mirror($assetsPath."/default",$assetsPath."/".strtolower($entity->getName()));
//Step 4 : Copy Templates
$finder->in($themePath."/".ucfirst($entity->getName())."/templates");
$finder->files()->contains("default");
//dd($finder->hasResults());
foreach ($finder as $file) {
$file_contents = file_get_contents($file->getPathname());
$file_contents = str_replace("default/", strtolower($entity->getName())."/", $file_contents);
file_put_contents($file->getPathname(), $file_contents);
}
}
if($entity instanceof Settings){
if($entity->getFrontTheme()){
$entity->setAssetFolderName(strtolower($entity->getFrontTheme()->getName()));
}
$filesystem = new Filesystem();
$path = __DIR__."/../../public/uploads/".$entity->getAssetFolderName();
if(!$filesystem->exists($path) )
{
$filesystem->mkdir($path,0777);
$filesystem->mkdir($path."/pages",0777);
$filesystem->mkdir($path."/shop",0777);
}
$pathFrontBundleRoutes = __DIR__."/../Flexy/FrontBundle/Resources/config/routes.yaml";
if($filesystem->exists($pathFrontBundleRoutes)){
$configArray = Yaml::parseFile($pathFrontBundleRoutes);
$configArray["controllers"]["resource"] = "../../Controller/".ucfirst($entity->getAssetFolderName());
$yamlConfig = Yaml::dump($configArray);
file_put_contents($pathFrontBundleRoutes, $yamlConfig);
}
}
if ($entity instanceof ExportExcel) {
$entityNameSpace = $entity->getEntityNameSpace();
$directFields = $this->doctrine->getManager()->getClassMetadata($entityNameSpace)->getColumnNames();
$associationFields = $this->doctrine->getManager()->getClassMetadata($entityNameSpace)->getAssociationMappings();
$entityRepository = $this->doctrine->getRepository($entityNameSpace);
$repositoryMethods = $this->getAllRepositoryMethods($entityRepository);
$reflectionClass = $this->doctrine->getManager()->getClassMetadata($entityNameSpace)->reflClass->getMethods();// All methods detailled
//-------------
//dd($reflectionClass[0]->name);
$fields = [];
$translatedFields = [];
foreach($reflectionClass as $singleRefClass){
if(count($entity->getFields()) > 0 ){
if($entity->isExcludeFields()){
if(in_array($singleRefClass->name,$entity->getFields())){
continue;
}
}else{
if(!in_array($singleRefClass->name,$entity->getFields())){
continue;
}
}
}
if (substr($singleRefClass->name, 0, 3) === "get") {
$fields[]=$singleRefClass->name;
} else {
continue;
}
}
foreach($repositoryMethods as $singleMethod){
$fields[]=$singleMethod;
}
//dd($fields);
//$selectedFieldsToExport = ["name","categoryProduct","subCategoryProduct","price"];
$selectedFieldsToExport = [];
$selectedFieldsToExport = array_merge($selectedFieldsToExport,$fields);
//$selectedFieldsToExport = array_merge($selectedFieldsToExport,$reflectionClass);
if(count($entity->getFindBy())>0){
$queryBuilder = $this->doctrine->getManager()->createQueryBuilder();
$queryBuilder
->select('e')
->from($entityNameSpace, 'e');
//->join('e.relatedEntity', 'r')
foreach($entity->getFindBy() as $key => $value){
$queryBuilder
->where('e.'.$key.' '.$value);
}
if(count($entity->getOrderBy())>0){
foreach($entity->getOrderBy() as $key => $value){
if(gettype($key)=="integer"){
$queryBuilder->orderBy("e.".$value);
}else{
$queryBuilder->orderBy("e.".$key,$value);
}
}
}
$entityFetchAll = $queryBuilder->getQuery()->getResult();
}else{
$entityFetchAll = $this->doctrine->getManager()->getRepository($entityNameSpace)->findAll();
}
$arrayToExport = [];
//$arrayToExport[]=$selectedFieldsToExport;
$correctedFieldsName =[];
foreach($fields as $field){
$name = $this->getAbsoluteNameMethod($field);
$correctedFieldsName[]= $this->translatorInterface->trans($name);
}
$arrayToExport[]=$correctedFieldsName;
foreach($entityFetchAll as $singleEntityInstance){
$singleRow =[];
foreach($fields as $singleField){
$value=null;
$valueSub=null;
$valueParent=null;
if(method_exists($singleEntityInstance,$singleField)){
$value = $singleEntityInstance->{$singleField}();
if($value instanceof Collection){
$value = implode("\n", $value->toArray());
//dd($value);
}elseif(is_array($value)){
$value = implode("\n", $value);
//dd($value);
}elseif(gettype($value) == "string"){
$value = $this->translatorInterface->trans($value);
}
}elseif(method_exists($entityRepository,$singleField)){
$value = $entityRepository->{$singleField}($singleEntityInstance->getId());
if(is_array($value)){
// find the index of the value 'orange'
$field = $this->getAbsoluteNameMethod($singleField);
$translatedField = $this->translatorInterface->trans($field);
$index = array_search($translatedField, $arrayToExport[0]);
// if the value exists in the array, remove it
if ($index !== false) {
unset($arrayToExport[0][$index]);
}
// re-index the array
//$arrayToExport = array_values($arrayToExport[0]);
// dd($value);
foreach($value as $singleData){
$translatedKey = $this->translatorInterface->trans($singleData["key"]);
if(!in_array($translatedKey,$arrayToExport[0])){
$arrayToExport[0][] = $this->translatorInterface->trans($translatedKey);
}
$singleRow[]=$singleData["value"];
}
continue;
}else{
$value = $this->translatorInterface->trans($value);
}
}
$singleRow[]=$value;
}
$arrayToExport[]=$singleRow;
}
$mySpreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$mySpreadsheet->removeSheetByIndex(0);
$worksheet1 = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($mySpreadsheet, "List Produits");
$mySpreadsheet->addSheet($worksheet1, 0);
$worksheet1->fromArray($arrayToExport,null,"A1");
// Set the auto filter to cover all the data
$lastColumn = $worksheet1->getHighestColumn();
$lastRow = $worksheet1->getHighestDataRow();
$range = "A1:$lastColumn$lastRow";
$worksheet1->setAutoFilter($range);
foreach ($worksheet1->getColumnIterator() as $column)
{
$worksheet1->getColumnDimension($column->getColumnIndex())->setAutoSize(true);
}
foreach ($worksheet1->getRowIterator() as $row) {
foreach ($row->getCellIterator() as $cell) {
$cell->getStyle()->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP);
}
}
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($mySpreadsheet);
$parts = explode("\\", $entityNameSpace);
$nameOfFile = end($parts);
$nameOfFile = strtolower($nameOfFile)."-".$entity->getCreatedAt()->format("Y-m-d-H-i");
//echo $lastWord; // output: CategoryProduct
$settings = $this->doctrine->getManager()->getRepository(Settings::class)->findOneBy(["code"=>"main"]);
$assetFolderName = $settings->getAssetFolderName();
$assetFolderName = strtolower($assetFolderName);
$writer->save("uploads/".$assetFolderName."/exports/".$nameOfFile.".xlsx");
$entity->setGeneratedFilePath("uploads/".$assetFolderName."/exports/".$nameOfFile.".xlsx");
$entity->setEntityNameSpace($entityNameSpace);
}
if ($entity instanceof User) {
$entity->setPassword(
$this->passwordEncoder->hashPassword(
$entity,
$entity->getPassword()
));
}
}
public function beforeUpdated(BeforeEntityUpdatedEvent $event)
{
$entity = $event->getEntityInstance();
if($entity instanceof Settings){
$filesystem = new Filesystem();
$pathFrontBundle = __DIR__."/../Flexy/FrontBundle";
$themePath = $pathFrontBundle."/Themes";
if($entity->getFrontTheme()){
$entity->setAssetFolderName($entity->getFrontTheme()->getName());
if(!$filesystem->exists(__DIR__."/../../public/themes/".strtolower($entity->getFrontTheme()->getName()))){
$filesystem->symlink($themePath."/".$entity->getFrontTheme()->getName()."/assets", __DIR__."/../../public/themes/".strtolower($entity->getFrontTheme()->getName()));
}
}
$path = __DIR__."/../../public/uploads/".$entity->getAssetFolderName();
if(!$filesystem->exists($path) )
{
$filesystem->mkdir($path,0777);
$filesystem->mkdir($path."/pages",0777);
$filesystem->mkdir($path."/shop",0777);
}
$pathFrontBundleRoutes = __DIR__."/../Flexy/FrontBundle/Resources/config/routes.yaml";
if($filesystem->exists($pathFrontBundleRoutes)){
$configArray = Yaml::parseFile($pathFrontBundleRoutes);
$configArray["controllers"]["resource"] = "../../Themes/".ucfirst($entity->getAssetFolderName())."/Controller";
$yamlConfig = Yaml::dump($configArray);
file_put_contents($pathFrontBundleRoutes, $yamlConfig);
}
}
}
public function beforeDelete(BeforeEntityDeletedEvent $event){
$entity = $event->getEntityInstance();
if($entity instanceof FrontTheme){
//$entity->getSettings()->setFrontTheme(null);
$filesystem = new Filesystem();
//dd(__DIR__."/../../");
$pathFrontBundle = __DIR__."/../Flexy/FrontBundle";
$themePath = $pathFrontBundle."/Themes";
if($filesystem->exists($themePath."/".ucfirst($entity->getName()) ) ){
$this->zipDirectory($themePath."/".ucfirst($entity->getName()),__DIR__."/../../public/archive-themes/".strtolower($entity->getName()).".zip" );
$filesystem->remove($themePath."/".ucfirst($entity->getName()));
}
//$filesystem->remove($pathFrontBundle."/Resources/public/assets/".strtolower($entity->getName()));
$settings = $this->doctrine->getManager()->getRepository(Settings::class)->findOneBy(["code"=>"main"]);
$currentTheme = $settings->getAssetFolderName();
$entity->removeSetting($settings);
$settings->setAssetFolderName("Default");
$this->doctrine->getManager()->persist($settings);
if(strtolower($entity->getName()) == strtolower($currentTheme) ){
$pathFrontBundleRoutes = __DIR__."/../Flexy/FrontBundle/Resources/config/routes.yaml";
if($filesystem->exists($pathFrontBundleRoutes)){
$configArray = Yaml::parseFile($pathFrontBundleRoutes);
$configArray["controllers"]["resource"] = "../../Themes/Default/Controller";
$yamlConfig = Yaml::dump($configArray);
file_put_contents($pathFrontBundleRoutes, $yamlConfig);
}
}
}
}
public function exportFile($records) {
$heading = false;
if(!empty($records))
foreach($records as $row) {
if(!$heading) {
// display field/column names as a first row
echo implode("\t", array_keys($row)) . "\n";
$heading = true;
}
echo implode("\t", array_values($row)) . "\n";
}
}
public static function zipDirectory($directory, $zipName)
{
// Get real path for our folder
$rootPath = realpath($directory);
// Initialize archive object
$zip = new ZipArchive();
$zip->open($zipName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
// Initialize empty "delete list"
$filesToDelete = array();
// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file)
{
// Skip directories (they would be added automatically)
if (!$file->isDir())
{
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
// Add current file to archive
$zip->addFile($filePath, $relativePath);
// Add current file to "delete list"
// delete it later cause ZipArchive create archive only after calling close function and ZipArchive lock files until archive created)
if ($file->getFilename() != 'important.txt')
{
$filesToDelete[] = $filePath;
}
}
}
// Zip archive will be created only after closing object
$zip->close();
return $zip;
}
function getAbsoluteNameMethod($input) {
// Remove the "get" prefix from the input string
$input = preg_replace('/^get/', '', $input);
// Replace all capital letters with a space followed by the letter
$output = preg_replace('/([A-Z])/', ' $1', $input);
// Remove any leading or trailing spaces
$output = trim($output);
// Convert the first character to uppercase
$output = ucfirst($output);
// Return the final result
return $output;
}
public function getAllRepositoryMethods($repository)
{
$reflectionClass = new ReflectionClass(get_class($repository));
$methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC);
$findMethods = [];
foreach ($methods as $method) {
$methodName = $method->getName();
if (strpos($methodName, 'export') === 0) {
$findMethods[] = $methodName;
}
}
return $findMethods;
}
}