<?php
namespace App\Controller;
use App\Entity\File;
use App\Entity\PSA;
use App\Repository\FileRepository;
use App\Repository\LangRepository;
use App\Repository\PSARepository;
use App\Repository\SiteRepository;
use App\Services\WebserviceUtils;
use CURLFile;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use PrestaShopWebservice;
use PrestaShopWebserviceException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use SimpleXMLElement;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\String\Slugger\SluggerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
#[Route('/file', name: 'app_file')]
#[IsGranted("ROLE_USER")]
class FileController extends AbstractController
{
public function __construct(Security $security, TranslatorInterface $translator)
{
$this->twigData = [];
$this->translator = $translator;
$this->security = $security;
$this->twigData = [
'user' => $security->getUser(),
];
}
#[Route('/', name: '_index')]
public function index(FileRepository $fileRepository, LangRepository $langRepository): Response
{
$this->breadcrumb[0]['name'] = $this->translator->trans('page.catalog.Catalog');
$this->breadcrumb[0]['link'] = $this->generateUrl('app_catalog_index');
$this->breadcrumb[0]['last'] = false;
$this->breadcrumb[1]['name'] = $this->translator->trans('page.files.Files');
$this->breadcrumb[1]['last'] = true;
$this->twigData['breadcrumb'] = $this->breadcrumb;
$langs = $langRepository->findAll();
$this->twigData['langs'] = $langs;
$this->twigData['files'] = $fileRepository->findAll();
return $this->render('files/index.html.twig', $this->twigData);
}
#[Route('/new', name: '_new', methods: ['GET', 'POST'])]
public function new(LangRepository $langRepository,SluggerInterface $slugger, FileRepository $fileRepository, Request $request, EntityManagerInterface $entityManager, PSARepository $PSARepository): Response
{
$this->breadcrumb[0]['name'] = $this->translator->trans('page.catalog.Catalog');
$this->breadcrumb[0]['link'] = $this->generateUrl('app_catalog_index');
$this->breadcrumb[0]['last'] = false;
$this->breadcrumb[1]['name'] = $this->translator->trans('page.files.Files');
$this->breadcrumb[1]['link'] = $this->generateUrl('app_file_index');
$this->breadcrumb[1]['last'] = false;
$this->breadcrumb[2]['name'] = $this->translator->trans('page.files.new');
$this->breadcrumb[2]['last'] = true;
$this->twigData['breadcrumb'] = $this->breadcrumb;
$langs = $langRepository->findAll();
$this->twigData['langs'] = $langs;
$submit = $request->get("submit");
if ($submit == 1) {
$file = $request->files->get('file');
$langId = $request->request->get('lang');
$lang = $langRepository->find($langId);
if ($file) {
$originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
// this is needed to safely include the file name as part of the URL
$safeFilename = $slugger->slug($originalFilename);
$newFilename = $safeFilename.'-'.uniqid().'_'.$lang->getICU().'.'.$file->guessExtension();
// Move the file to the directory where product file are stored
try {
$file->move(
$this->getParameter('file_directory'),
$newFilename
);
$fileNameDisplay = $request->request->get('name');
$fileDescription = $request->request->get('description');
$file = new File();
$file->setName($newFilename);
$file->setDescription($fileDescription);
$file->setDisplayName($fileNameDisplay);
$file->setLang($lang);
$fileRepository->add($file, true);
} catch (FileException $e) {
return new Response($e, Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
return $this->redirectToRoute('app_file_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('files/new.html.twig', $this->twigData);
}
#[Route('/{id}/edit', name: '_edit', methods: ['GET', 'POST'])]
public function edit(File $file,LangRepository $langRepository,SluggerInterface $slugger, FileRepository $fileRepository, Request $request, EntityManagerInterface $entityManager, PSARepository $PSARepository): Response
{
$this->breadcrumb[0]['name'] = $this->translator->trans('page.catalog.Catalog');
$this->breadcrumb[0]['link'] = $this->generateUrl('app_catalog_index');
$this->breadcrumb[0]['last'] = false;
$this->breadcrumb[1]['name'] = $this->translator->trans('page.files.Files');
$this->breadcrumb[1]['link'] = $this->generateUrl('app_file_index');
$this->breadcrumb[1]['last'] = false;
$this->breadcrumb[2]['name'] = $this->translator->trans('page.files.edit');
$this->breadcrumb[2]['last'] = true;
$this->twigData['breadcrumb'] = $this->breadcrumb;
$langs = $langRepository->findAll();
$this->twigData['langs'] = $langs;
$this->twigData['file'] = $file;
$submit = $request->get("submit");
if ($submit == 1) {
$fileFile = $request->files->get('file');
$langId = $request->request->get('lang');
$lang = $langRepository->find($langId);
if ($fileFile) {
$originalFilename = pathinfo($fileFile->getClientOriginalName(), PATHINFO_FILENAME);
// this is needed to safely include the file name as part of the URL
$safeFilename = $slugger->slug($originalFilename);
$newFilename = $safeFilename.'-'.uniqid().'_'.$lang->getICU().'.'.$fileFile->guessExtension();
// Move the file to the directory where product file are stored
try {
$fileFile->move(
$this->getParameter('file_directory'),
$newFilename
);
$file->setName($newFilename);
} catch (FileException $e) {
return new Response($e, Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
$fileNameDisplay = $request->request->get('name');
$fileDescription = $request->request->get('description');
$file->setDescription($fileDescription);
$file->setDisplayName($fileNameDisplay);
$file->setLang($lang);
$fileRepository->add($file, true);
return $this->redirectToRoute('app_file_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('files/edit.html.twig', $this->twigData);
}
#[Route('/{id}', name: '_delete', methods: ['POST'], requirements: ['id' => '\d+'])]
public function delete(Request $request, File $file, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('delete'.$file->getId(), $request->request->get('_token'))) {
$pathToFile = $this->getParameter('file_directory').'/'.$file->getName();
if (file_exists($pathToFile)) {
unlink($pathToFile);
}
$entityManager->remove($file);
$entityManager->flush();
}
return $this->redirectToRoute('app_file_index', [], Response::HTTP_SEE_OTHER);
}
#[Route('/{id}/sync', name: '_sync', methods: ['GET', 'POST'], requirements: ['id' => '\d+'])]
public function sync(File $file, EntityManagerInterface $entityManager, PSARepository $PSARepository, SiteRepository $siteRepository): Response
{
$debug = false;
$sites = $siteRepository->findAll();
foreach ($sites as $key => $site) {
if ($site->getId() == 3 ) continue;
$url = $site->getUrl();
$apiKey = $site->getApiKey();
$webService = new PrestaShopWebservice($url, $apiKey, $debug);
$webServiceUtils = new WebserviceUtils($webService, $url);
$langs = $webServiceUtils->getSiteLangs();
$psaAttachment = $PSARepository->findOneBy(['entityId'=> $file->getId(), "entityName"=>'attachments', "siteId"=>$site->getId()]);
if($psaAttachment != null){
$file_path = $this->getParameter('file_directory').'/'.$file->getName();
$file_mime = mime_content_type($file_path);
// dd(filesize($file_path));
$args['file'] = new CURLFile($file_path, $file_mime, $file->getDisplayName().'_'.$file->getLang()->getICU());
try {
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_URL, $url."/api/attachments/file/".$psaAttachment->getInSiteId());
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_USERPWD, $apiKey);
curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$returnFile = curl_exec($ch);
if ($returnFile === false) {
echo "cURL Error: " . curl_error($ch);
} else {
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$body = substr($returnFile, $header_size);
// Check HTTP status code
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200) {
// Handle successful response
$response = json_decode($body, true); // Or use simplexml_load_string() for XML
if (isset($response['attachment'])) {
// Process the attachment data
echo "Attachment uploaded successfully.";
} else {
echo "Error: 'attachment' property not found in response.";
}
} else {
dd($site, $http_code);
}
}
curl_close($ch);
$returnFile = $body;
$returnFile = simplexml_load_string($returnFile);
// dump($returnFile);
$returnFileId = intval($returnFile->attachment[0]->id);
$xmlAttachmentsResponse = $webService->get(['url' => $url . '/api/attachments/'.$returnFileId]);
$attachmentsXml = $xmlAttachmentsResponse->attachment[0];
foreach ($langs as $keyLang => $lang) {
$attachmentsXml->description->language[$keyLang] = $file->getDescription();
}
$optAttachment = ['resource' => 'attachments'];
$optAttachment['putXml'] = $xmlAttachmentsResponse->asXML();
$optAttachment['id'] = $returnFileId;
} catch (\Throwable $th) {
// dump($site);
// dd($th);
$errors[] = [
'site' => $site->getName(),
'error' => $th
];
}
if (isset($optAttachment)) {
try {
$returnAttachment = $webService->edit($optAttachment);
} catch (PrestaShopWebserviceException $th) {
// dd($th);
$errors[] = [
'site' => $site->getName(),
'error' => $th
];
}
}
if (isset($returnFileId)) {
$returnAttachmentId = $returnFileId;
$psaAttachment = new PSA();
$psaAttachment->setEntityId($file->getId());
$psaAttachment->setEntityName('attachments');
$psaAttachment->setInSiteId($returnAttachmentId);
$psaAttachment->setSiteId($site->getId());
$PSARepository->add($psaAttachment, true);
}
}else{
$psaAttachment = $PSARepository->findOneBy(['entityName' => "attachments", 'entityId'=> $file->getId(), 'siteId'=> $site->getId()]);
if ($psaAttachment == null) {
$file_path = $this->getParameter('file_directory').'/'.$file->getName();
$file_mime = mime_content_type($file_path);
$file_name = $file->getDisplayName().'_'.$file->getLang()->getICU();
$file_name = str_replace(' ', '_', $file_name);
// dd(filesize($file_path));
//make file name length less than 32 by removing first characters
if(strlen($file_name) > 32){
$file_name = substr($file_name, -32, 32);
}
$args['file'] = new CURLFile($file_path, $file_mime, $file_name);
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_URL, $url."/api/attachments/file/");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_USERPWD, $apiKey);
curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$returnFile = curl_exec($ch);
if ($returnFile === false) {
echo "cURL Error: " . curl_error($ch);
} else {
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$body = substr($returnFile, $header_size);
// Check HTTP status code
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($http_code == 200) {
// Handle successful response
$response = json_decode($body, true); // Or use simplexml_load_string() for XML
if (isset($response['attachment'])) {
// Process the attachment data
echo "Attachment uploaded successfully.";
} else {
echo "Error: 'attachment' property not found in response.";
}
} else {
dd($site, $http_code);
}
}
curl_close($ch);
$returnFile = $body;
$returnFile = simplexml_load_string($returnFile);
$returnFileId = intval($returnFile->attachment[0]->id);
$xmlAttachmentsResponse = $webService->get(['url' => $url . '/api/attachments/'.$returnFileId]);
$attachmentsXml = $xmlAttachmentsResponse->attachment[0];
foreach ($langs as $keyLang => $lang) {
$attachmentsXml->description->language[$keyLang] = $file->getDescription();
}
$optAttachment = ['resource' => 'attachments'];
$optAttachment['putXml'] = $xmlAttachmentsResponse->asXML();
$optAttachment['id'] = $returnFileId;
try {
$returnAttachment = $webService->edit($optAttachment);
} catch (PrestaShopWebserviceException $th) {
dd($th);
}
$returnAttachmentId = $returnFileId;
$psaAttachment = new PSA();
$psaAttachment->setEntityId($file->getId());
$psaAttachment->setEntityName('attachments');
$psaAttachment->setInSiteId($returnAttachmentId);
$psaAttachment->setSiteId($site->getId());
$PSARepository->add($psaAttachment, true);
} else {
$xmlAttachmentsResponse = $webService->get(['url' => $url . '/api/attachments/'.$psaAttachment->getInSiteId()]);
}
}
}
return $this->redirectToRoute('app_file_index', [], Response::HTTP_SEE_OTHER);
}
#[Route('/{fileName}', name: '_display', methods:['GET'])]
public function display($fileName, Request $request, SluggerInterface $slugger, FileRepository $fileRepository): Response
{
$file = $fileRepository->findOneBy(['name'=>$fileName]);
$filename = $this->getParameter('file_directory') . '/' . $fileName;
if (file_exists($filename)) {
//return a new BinaryFileResponse with the file name
return new BinaryFileResponse($filename);
} else {
return new JsonResponse(null, 404);
}
}
}