← Back
Editing: AgencyImporter.php
<?php namespace App\Import; use App\Entity\Adresse; use App\Entity\Agency; use App\Entity\AgencyPrestataire; use App\Entity\Item; use App\Entity\Prestataire; use App\Entity\User; use App\Entity\UserAddress; use App\Service\SolutionService; use App\Service\UserService; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\ORMException; use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Shared\Date; use PhpOffice\PhpSpreadsheet\Spreadsheet; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\Validator\Validator\ValidatorInterface; class AgencyImporter { protected Spreadsheet $spreadsheet; protected PhpDocExtractor $phpDocExtractor; protected Agency $agency; protected AgencyImportSummary $summary; protected array $errors = []; protected array $prestataires = []; /** @var Item[] */ private array $defaultItems = []; private bool $commit = false; public function __construct( private readonly EntityManagerInterface $entityManager, private readonly ValidatorInterface $validator, private readonly SolutionService $solutionService, private readonly UserService $userService, private readonly AgencyImportTransformer $transformer, private readonly AgencyImportMapper $mapper ) { $this->summary = new AgencyImportSummary(); $this->phpDocExtractor = new PhpDocExtractor(); } public function importFile($file, Agency $agency): void { $this->agency = $agency; $this->updateSummary($agency); $this->spreadsheet = IOFactory::load($file); } /** * @param Item[] $defaultItems * * @throws ORMException * @throws Exception * @throws AgencyImportException */ public function run(bool $commit, array $defaultItems): void { $this->commit = $commit; $this->defaultItems = $defaultItems; $this->importSupervisors(); $this->importManagers(); $this->importAgents(); $this->importPresta(); $this->importAgencyPresta(); $this->importAddresses(); $this->doAffectations(); if (true === $this->commit) { $this->process(); $this->userService->setColorsToNewManagers(); } } public function process(): void { $this->entityManager->flush(); } /** * @throws AgencyImportException * @throws Exception * @throws ORMException */ protected function importModelFromSheet( int $sheetIndex, array $cols, string $modelClass, array $extraFields = [], int $colOffset = 2 ): void { $this->spreadsheet->setActiveSheetIndex($sheetIndex); $rowOffset = 2; $position = 0; $nbRows = $this->countRowsFromSheet($sheetIndex); for ($currentRowIdx = $rowOffset; $currentRowIdx < ($nbRows + $rowOffset); ++$currentRowIdx) { $values = []; for ($currentColIdx = $colOffset; $currentColIdx < (count($cols) + $colOffset); ++$currentColIdx) { $val = $this->spreadsheet->getActiveSheet()->getCellByColumnAndRow( $currentColIdx, $currentRowIdx )->getValue(); $colIndex = $currentColIdx - $colOffset; $keyName = $cols[$colIndex]; $values[$keyName] = $val; } $values = array_merge($values, $extraFields); $this->importFromRawData($modelClass, $values, $position); ++$position; } } /** * @throws Exception */ protected function countRowsFromSheet(int $sheetIndex): int { $i = 2; $cnt = 0; $this->spreadsheet->setActiveSheetIndex($sheetIndex); while ($val = $this->spreadsheet->getActiveSheet()->getCellByColumnAndRow(2, $i)->getFormattedValue()) { ++$i; ++$cnt; } return $cnt; } /** * @throws AgencyImportException * @throws ORMException * @throws Exception */ private function importSupervisors(): void { $rows = ExcelMapping::ADMINS; $this->importModelFromSheet(1, $rows, User::class, ['roles' => ['ROLE_SUPERVISOR']]); } /** * @throws AgencyImportException * @throws Exception * @throws ORMException */ private function importManagers(): void { $rows = ExcelMapping::MANAGERS; $this->importModelFromSheet(2, $rows, User::class, ['roles' => ['ROLE_MANAGER']]); } /** * @throws AgencyImportException * @throws Exception * @throws ORMException */ private function importAddresses(): void { $rows = ExcelMapping::ADDRESSES; $this->importModelFromSheet(3, $rows, Adresse::class); if (!$this->agency) { throw new \Exception('Pas d\'agence renseigné'); } } /** * @throws ORMException * @throws Exception * @throws AgencyImportException */ private function importAgents(): void { $rows = ExcelMapping::AGENTS; $this->importModelFromSheet(4, $rows, User::class, ['roles' => ['ROLE_AGENT']]); } /** * @throws ORMException * @throws Exception * @throws AgencyImportException */ private function importPresta(): void { $rows = ExcelMapping::PRESTAS; $this->importModelFromSheet(5, $rows, Prestataire::class); } /** * @throws ORMException * @throws Exception * @throws AgencyImportException */ private function importAgencyPresta(): void { $rows = ExcelMapping::AGENCY_PRESTAS; $this->importModelFromSheet(5, $rows, AgencyPrestataire::class, [], 4); } /** * @param class-string $modelClass * * @throws AgencyImportException * @throws ORMException * @throws \Exception */ protected function importFromRawData(string $modelClass, array $values, int $position): void { $obj = ($this->mapper)($modelClass, $values); ($this->transformer)($obj, $values, $position, $this->agency, $this->prestataires); foreach ($values as $key => $value) { $method = 'set'.ucfirst($key); $this->transformValue($obj, $key, $value); $obj->$method($value); } $errors = $this->validator->validate($obj); if (count($errors) > 0) { throw new AgencyImportException($modelClass, $errors, $position, $values); } if (Agency::class === $modelClass) { $this->agency = $obj; /* @var Agency $obj */ $obj->addSolution($this->solutionService->getCurrent()); } $this->entityManager->persist($obj); $this->postPersist($obj); $this->updateSummary($obj); } protected function postPersist(object $obj): void { if ($obj instanceof Prestataire) { $this->prestataires[] = $obj; } if ($obj instanceof User) { if (true === $this->commit && null === $obj->getId()) { $this->userService->sendNewAccountEmail($obj); } } } protected function updateSummary(object $obj): void { if ($obj instanceof Agency) { $this->summary->setAgency($obj); } if ($obj instanceof User) { if (in_array('ROLE_MANAGER', $obj->getRoles())) { $this->summary->addManager($obj); } if (in_array('ROLE_AGENT', $obj->getRoles())) { $this->summary->addAgent($obj); } } if ($obj instanceof Adresse) { $this->summary->addAddress($obj); } if ($obj instanceof Prestataire) { $this->summary->addPresta($obj); } } /** * @throws \Exception */ protected function transformValue(object $obj, $key, &$value): void { $types = $this->phpDocExtractor->getTypes(get_class($obj), $key); if (is_string($value)) { $value = trim($value); } if ($types) { foreach ($types as $type) { if (\DateTime::class === $type->getClassName()) { $value = Date::excelToDateTimeObject($value); } } } } /** * Handle affectations. * * @throws Exception * @throws ORMException */ private function doAffectations(): void { $this->doManagerAffectations(); $this->doAddressesAffectations(); } /** * @throws ORMException * @throws Exception * @throws \Exception */ protected function doManagerAffectations(): void { $this->spreadsheet->setActiveSheetIndex(4); $rowOffset = 2; $i = 0; foreach ($this->summary->getAgents() as $agent) { $managerStr = $this->spreadsheet->getActiveSheet()->getCellByColumnAndRow( 8, $i + $rowOffset )->getFormattedValue(); if ($managerStr) { $tmp = explode(' ', $managerStr); $managerIdx = $tmp[1] - 1; $managers = $this->summary->getManagers(); if (isset($managers[$managerIdx])) { $managerObj = $managers[$managerIdx]; } else { throw new \Exception("Le manager $managerStr n'existe pas"); } $agent->setManager($managerObj); } $this->entityManager->persist($agent); ++$i; } } /** * @throws ORMException * @throws Exception * @throws \Exception */ protected function doAddressesAffectations(): void { $this->spreadsheet->setActiveSheetIndex(3); $rowOffset = 2; $i = 0; foreach ($this->summary->getAddresses() as $adresse) { $prestaStr = $this->spreadsheet->getActiveSheet()->getCellByColumnAndRow( 10, $i + $rowOffset )->getFormattedValue(); if ($prestaStr) { $tmp = explode(' ', $prestaStr); $prestaIdx = $tmp[1] - 1; $prestas = $this->summary->getPresta(); if (isset($prestas[$prestaIdx])) { $prestaObj = $prestas[$prestaIdx]; } else { throw new \Exception("Le prestataire $prestaStr n'existe pas"); } $adresse->addPrestataire($prestaObj); } $agentStr = $this->spreadsheet->getActiveSheet()->getCellByColumnAndRow( 11, $i + $rowOffset )->getFormattedValue(); if ($agentStr) { $tmp = explode(' ', $agentStr); $agentIdx = $tmp[1] - 1; try { $agentObj = $this->summary->getAgents()[$agentIdx]; } catch (\Exception $e) { throw new \Exception('L\'agent '.$agentStr.' n\'existe pas'); } $userAddress = new UserAddress(); $userAddress->setUser($agentObj); $userAddress->setAddress($adresse); $adresse->addUserAddress($userAddress); $adresse->setManager($agentObj->getManager()); } foreach ($this->defaultItems as $item) { $adresse->addItem($item); } $this->entityManager->persist($adresse); ++$i; } } public function getSummary(): AgencyImportSummary { return $this->summary; } public function hasErrors(): bool { return boolval(count($this->errors)); } }
Save File
Cancel