Skip to content

Commit

Permalink
Added back-offcie UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Franck Allimant committed Nov 14, 2024
1 parent 7acb206 commit c8b5c1e
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 47 deletions.
42 changes: 3 additions & 39 deletions Command/ImportProducts.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,45 +29,9 @@ protected function configure(): void
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->initRequest();
$baseDir = $input->getArgument(self::DIR_PATH);

$finder = Finder::create()
->files()
->in($baseDir)
->depth(0)
->name('*.csv')
;

$output->writeln("<info>Fetching directory $baseDir</info>");

$return = Command::SUCCESS;

$count = $errors = 0;

foreach ($finder->getIterator() as $file) {
$output->writeln("<info>Starting to import : ".$file->getBasename()."</info>");

$count++;

try {
$this->csvProductImporterService->importProductsFromCsv($file->getPathname(), $baseDir);

$output->writeln('<info>Import is a success !</info>');
} catch (\Exception $e) {
Tlog::getInstance()->addError("Erreur lors de l'importation : ".$e->getMessage());
$output->writeln('<error>Error : '.$e->getMessage().'</error>');
if ($e->getPrevious()) {
$output->writeln('<error>Caused by : '.$e->getPrevious()->getMessage().'</error>');
}

$return = Command::FAILURE;

$errors++;
}
}

$output->writeln("<info>$count file(s) processed, $errors error(s).</info>");

return $return;
return $this->csvProductImporterService->importFromDirectory($input->getArgument(self::DIR_PATH)) ?
Command::SUCCESS :
Command::FAILURE;
}
}
7 changes: 7 additions & 0 deletions Config/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,11 @@
<config xmlns="http://thelia.net/schema/dic/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">

<hooks>
<hook id="CsvImporter\Hook\HookManager" class="CsvImporter\Hook\HookManager">
<tag name="hook.event_listener" event="module.configuration" type="back" method="onModuleConfiguration" />
<tag name="hook.event_listener" event="main.top-menu-tools" type="back" method="onMainTopMenuTools" />
</hook>
</hooks>
</config>
2 changes: 1 addition & 1 deletion Config/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<descriptive locale="fr_FR">
<title>CSV Importer</title>
</descriptive>
<version>1.0.4</version>
<version>1.0.5</version>
<author>
<name>Thelia</name>
<email>info@thelia.net</email>
Expand Down
83 changes: 83 additions & 0 deletions Controller/ConfigurationController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php
/*************************************************************************************/
/* Copyright (c) Open Studio */
/* web : https://open.studio */
/* */
/* For the full copyright and license information, please view the LICENSE */
/* file that was distributed with this source code. */
/*************************************************************************************/

/**
* Created by Franck Allimant, OpenStudio <fallimant@openstudio.fr>
* Date: 14/11/2024 09:23
*/
namespace CsvImporter\Controller;

use CsvImporter\Service\CsvProductImporterService;
use Propel\Runtime\Propel;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Thelia\Controller\Admin\BaseAdminController;
use Thelia\Log\Destination\TlogDestinationFile;
use Thelia\Log\Destination\TlogDestinationRotatingFile;
use Thelia\Log\Tlog;
use Thelia\Tools\URL;

/**
* @Route("/admin/module/csvimporter")
*/
class ConfigurationController extends BaseAdminController
{
protected string $logFile = THELIA_LOG_DIR . 'catalog-import-log.txt';

/**
* Import manuel du catalogue
*
* @Route("/import", methods="GET")
*/
public function import(CsvProductImporterService $csvProductImporterService): Response
{
@unlink($this->logFile);

Tlog::getInstance()
->setLevel(Tlog::INFO)
->setDestinations(TlogDestinationFile::class)
->setConfig(TlogDestinationFile::class, TlogDestinationFile::VAR_PATH_FILE, $this->logFile)

->setFiles('*')
->setPrefix('[#LEVEL] #DATE #HOUR:');

// Pas de log des requetes SQL
Propel::getConnection('TheliaMain')->useDebug(false);

$catalogDir = THELIA_LOCAL_DIR . 'Catalogue';

if (! is_dir($catalogDir)) {
return $this->generateRedirect(URL::getInstance()?->absoluteUrl(
'/admin/module/CsvImporter',
[ 'error' => 'Répertoire ' . $catalogDir . ' non trouvé.' ])
);
}

$csvProductImporterService->importFromDirectory($catalogDir);

return $this->generateRedirect(URL::getInstance()?->absoluteUrl('/admin/module/CsvImporter', [ 'done' => 1 ]));
}

/**
* Import manuel du catalogue
*
* @Route("/log", methods="GET")
*/
public function getLogFile(): Response
{
return new Response(
@file_get_contents($this->logFile),
200,
array(
'Content-type' => "text/plain",
'Content-Disposition' => 'Attachment;filename=csv-import-log.txt'
)
);
}
}
64 changes: 64 additions & 0 deletions Hook/HookManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
/*************************************************************************************/
/* Copyright (c) Open Studio */
/* web : https://open.studio */
/* */
/* For the full copyright and license information, please view the LICENSE */
/* file that was distributed with this source code. */
/*************************************************************************************/

/**
* Created by Franck Allimant, OpenStudio <fallimant@openstudio.fr>
* Date: 14/11/2024 09:27
*/
namespace CsvImporter\Hook;

use BestSellers\BestSellers;
use Thelia\Core\Event\Hook\HookRenderBlockEvent;
use Thelia\Core\Event\Hook\HookRenderEvent;
use Thelia\Core\Hook\BaseHook;
use Thelia\Tools\URL;

/**
*
*/
class HookManager extends BaseHook
{
protected const MAX_TRACE_SIZE_IN_BYTES = 40000;

public function onModuleConfiguration(HookRenderEvent $event)
{
$logFilePath = THELIA_LOG_DIR . 'catalog-import-log.txt';

$traces = @file_get_contents($logFilePath);

// Limiter la taille des traces à 1MO
if (strlen($traces) > self::MAX_TRACE_SIZE_IN_BYTES) {
$traces = substr($traces, strlen($traces) - self::MAX_TRACE_SIZE_IN_BYTES);

// Cut a first line break;
if (false !== $lineBreakPos = strpos($traces, "\n")) {
$traces = substr($traces, $lineBreakPos+1);
}
}

$event->add(
$this->render(
'module-configuration.html',
[ 'trace_content' => nl2br($traces) ]
)
);
}

public function onMainTopMenuTools(HookRenderBlockEvent $event)
{
$event->add(
[
'id' => 'csvimporter_menu',
'class' => '',
'url' => URL::getInstance()->absoluteUrl('/admin/module/CsvImporter'),
'title' =>"Import catalogue CSV"
]
);
}
}
71 changes: 64 additions & 7 deletions Service/CsvProductImporterService.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

use Propel\Runtime\Exception\PropelException;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Thelia\Core\Event\Attribute\AttributeAvCreateEvent;
use Thelia\Core\Event\Attribute\AttributeCreateEvent;
Expand Down Expand Up @@ -97,6 +99,56 @@ public function __construct(
{
}

public function importFromDirectory(string $path, ?OutputInterface $output = null): bool
{
$finder = Finder::create()
->files()
->in($path)
->ignoreDotFiles(true)
->depth(0)
->name('*.csv')
;

$output?->writeln("<info>Fetching directory $path</info>");

$count = $errors = 0;

$success = true;

foreach ($finder->getIterator() as $file) {
Tlog::getInstance()->info("Importation du fichier $file");

$output?->writeln("<info>Starting to import : ".$file->getBasename()."</info>");

$count++;

try {
$this->importProductsFromCsv($file->getPathname(), $path);

$output?->writeln('<info>Import is a success !</info>');

Tlog::getInstance()->info("Fichier $file importé.");
} catch (\Exception $e) {
Tlog::getInstance()->addError("Erreur lors de l'importation de $file : ".$e->getMessage());
$output?->writeln('<error>Error : '.$e->getMessage().'</error>');

if ($e->getPrevious()) {
$output?->writeln('<error>Caused by : '.$e->getPrevious()->getMessage().'</error>');
}

$success = false;

$errors++;
}
}

Tlog::getInstance()->info("$count fichiers(s) traités, $errors erreur(s).");

$output?->writeln("<info>$count file(s) processed, $errors error(s).</info>");

return $success;
}

/**
* @throws PropelException
* @throws \Exception
Expand All @@ -115,31 +167,35 @@ public function importProductsFromCsv(string $filePath, string $basedir, Country
throw new \RuntimeException("Cannot open file: $filePath");
}

$line = 0;

$headers = fgetcsv($handle);
while (($data = fgetcsv($handle)) !== false) {
$line++;

if (!$productData = array_combine($headers, $data)) {
throw new \RuntimeException('Problem while combining headers and data.');
}
$productData = $this->csvParser->mapToArray($productData);

if (!$productData[self::REF_COLUMN]) {
Tlog::getInstance()->addWarning('Missing Product reference');
Tlog::getInstance()->addWarning("Line $line: Missing Product reference");
continue;
}
if (!$productData[self::TITLE_COLUMN]) {
Tlog::getInstance()->addWarning('Missing Product title');
Tlog::getInstance()->addWarning("Line $line: Missing Product title");
continue;
}
if (!$productData[self::LEVEL1_COLUMN]) {
Tlog::getInstance()->addWarning('Missing Product category');
Tlog::getInstance()->addWarning("Line $line: Missing Product category");
continue;
}
if (!$productData[self::TAX_RULE_COLUMN]) {
Tlog::getInstance()->addWarning('Missing Product tax rule');
Tlog::getInstance()->addWarning("Line $line: Missing Product tax rule");
continue;
}
if (!$productData[self::PRICE_EXCL_TAX_COLUMN]) {
Tlog::getInstance()->addWarning('Missing Product price for:' . $productData[self::REF_COLUMN]);
Tlog::getInstance()->addWarning("Line $line: Missing Product price for:" . $productData[self::REF_COLUMN]);
continue;
}
$product = $this->findOrCreateProduct(
Expand All @@ -153,7 +209,6 @@ public function importProductsFromCsv(string $filePath, string $basedir, Country
}

fclose($handle);
Tlog::getInstance()->addInfo('End of products import.');
}

/**
Expand Down Expand Up @@ -271,6 +326,8 @@ private function findOrCreateCategory(array $productData, string $locale, Catego
->setVisible(1);
$this->dispatcher->dispatch($createEvent, TheliaEvents::CATEGORY_CREATE);
$category = $createEvent->getCategory();

Tlog::getInstance()->info('Created catégory ' . $productData[$level]);
}
$this->findOrCreateCategory($productData, $locale, $category, $this->incrementLevel($level));

Expand Down Expand Up @@ -304,7 +361,7 @@ private function findOrCreateProduct(array $productData, Country $country, strin
}

$newProduct = $this->dispatchProductEvent(new ProductCreateEvent(), $productData, $locale, $category, $country, true);
Tlog::getInstance()->addInfo('Produit créé : ' . $productData[self::TITLE_COLUMN]);
Tlog::getInstance()->addInfo('Created product ' . $productData[self::TITLE_COLUMN]);

return $this->dispatchProductEvent(new ProductUpdateEvent($newProduct->getId()), $productData, $locale, $category, $country);
}
Expand Down
Loading

0 comments on commit c8b5c1e

Please sign in to comment.