How to check if a certain file already exists in symfony2? - php

I am working on symfony2 and currently I want to check if a file does exist. My scenario look something like this,, I have two files excel file and the docx file. If a person have an excel file for her/his transaction then it is automatically that the docx file is not applicable for her or him.And vice versa. How can I possibly do it in symfony2? A lot in the net but I don't know how to do it in my case,, thanks a lot :)
UPDATE
Controller:
public function documentType ($doc_type) {
$em = $this->getDoctrine()->getEntityManager();
$result = $em->getRepository('SupplierBundle:SupplierTransactionDetails')->findDocumentType('xlsx');
$result1 = $em->getRepository('SupplierBundle:SupplierTransactionDetails')->findDocumentType('docx');
// statement that will know if the file exists for that certain user if so the other document type will be not applicable for that user. Example: that user have docx file already then the xlsx will be N/A and vice versa
}
Repository :
public function findDocumentType ($doc_type) {
$em = $this->getEntityManager();
$query = $em->createQuery(
'SELECT a, b, c FROM SupplierBundle:SupplierTransaction Details a
JOIN a.supplierTransaction b
JOIN b.supplierDocType c
WHERE c.docType LIKE :doc_type'
)->setParameter('doc_type', $doc_type);
return $query->getResult();
}

You can just use plain PHP for this. For example:
$xls = 'sheet.xlsx';
$doc = 'document.docx';
if (file_exists($xls)) {
// User has an XLSX file
echo 'Download your sheet here.';
} elseif (file_exists($doc)) {
// User has a DOCX file
echo 'Download your document here.';
}

If you want to do it the Symfony2 way, you can use the Filesystem class, it has an exists() function. In a controller an instance is automatically available in the service container:
$em = $this->getDoctrine()->getManager();
$xlsx = $em->getRepository('SupplierBundle:SupplierTransactionDetail')->findDocumentType‌('xlsx');
$docx = $em->getRepository('SupplierBundle:SupplierTransactionDetail')->findDocumnetType‌('docx');
return [
'xlsx' => $xlsx instanceof SupplierTransactionDetail && $this->get('filesystem')->exists($xlsx->getFile()) ? $xlsx->getFile() : null,
'docx' => $docx instanceof SupplierTransactionDetail && $this->get('filesystem')->exists($docx->getFile()) ? $docx->getFile() : null,
];
In your twig template:
{% if xlsx is not empty %}
{{ xlsx }}
{% endif %}
{% if docx is not empty %}
{{ docx }}
{% endif %}

Related

Symfony 3 - Serve image within twig extension

I want to serve several images which are not avaible in public folder (web) using php for example path/to/myphp/script.php?image=imagereference&some=parameter
To improve performances and not using this approach I made a twig extension to do that.
<?php
#src/MyBundle/Service/DisplayImage.php
namespace MyBundle\Service;
#https://symfony.com/blog/new-in-symfony-2-4-the-request-stack
use Symfony\Component\HttpFoundation\RequestStack;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;
class DisplayImage
{
private $entityManagerInterface;
private $requestStack;
public function __construct(EntityManagerInterface $entityManagerInterface, RequestStack $requestStack)
{
$this->entityManagerInterface = $entityManagerInterface;
$this->requestStack = $requestStack;
}
public function show(int $ref)
{
$photoPath = __DIR__ ."/../photoFolder/".$ref.".jpg";
$file = file_get_contents($photoPath);
$response = new Response();
$response->headers->set('Content-Type', 'image/jpeg');
$response->setContent($file);
return $response;
}
}
And into my twig template
{# src/MyBundle/Ressources/views/DisplayImage.html.twig #}
{% for ref in refs %}
<img src="{{ show(ref) }}"/>
{% endfor %}
But it doesn't work because the response returned is not a valid src path.
The only way I found is to base 64 encode the response returned
<?php
return "data:image/jpeg;base64," . base64_encode($file);
So my question is how generate URL that target my twig extension?
Something like path/to/twigExtension.php?ref=ref calls show(ref)
Maybe it's not the good way to achieve that.
This is a two step process.
you need to create to a valid link to each image (which will be a route to some kind of ImageController::show(id) controller-action)
The ImageController that takes the id (or imagename) and shouts out the binary content of the image file (or throws an error if a user is not granted to download the image). You can return a BinaryFileResponse here. Take a look here.

symfony 4 - dompdf loop when display image

I try for several days to display images in my PDF generated with domPDF on symfony 4.
In the pdf, I would like to insert an image from an entity, which I manage with VichUploader.
So I proceeded like this:
In my controller, I added :
// Configure Dompdf according to your needs
$pdfOptions = new Options();
$pdfOptions->set('isRemoteEnabled', true);
In my Twig, I display my image like this :
<img style="width:90px;" src="{{absolute_url(vich_uploader_asset(parametresAdmin, 'logoFile'))}}">
But when I start the action, there is a loop and I end up having the following error:
Error: Maximum execution time of 120 seconds exceeded
However, if I cancel adding the image, the PDF loads well (but without the image since I do not display it)
I checked on the url of the image was well an absolute way and that it was correct, doing this in my Twig:
{% set var = absolute_url(vich_uploader_asset(parametresAdmin, 'logoFile')) %}
<pre>
{{ dump(var) }}
And it is !
And the path is good, because I can open the file in a new tab.
I tried to display my image with a split in my twig :
{% set var = absolute_url(vich_uploader_asset(parametresAdmin, 'logoFile')) %}
<img style="width:90px;" src="{{var}}">
Or pass my url from my controller to my view in parameter :
Controller:
$html = $this->renderView('absence/pdf.html.twig', [
'title' => "Welcome to our PDF Test",
'parametresAdmin' => $parametresAdmin,
'url' => "http://127.0.0.1:8000/admin/logo/avatar2.jpg",
]);
Twig :
<img style="width:90px;" src="{{url}}">
But same problem. Looping for 120 seconds and error :
Error: Maximum execution time of 120 seconds exceeded
So I really do not understand why he does not want to post it in the PDF and that it loops. The path is correct, and works on normal views.
Here is my whole code for an overview:
Controller:
/* Uses */
use Dompdf\Dompdf;
use Dompdf\Options;
/*Fonction*/
/**
* Générer un PDF
* #Route("/absence/pdf", name="absence_pdf")
*
* #return void
*/
public function createPDF(ParametresAdminRepository $repoParametres)
{
$parametresAdmin = $repoParametres->findAll();
if (isset($parametresAdmin[0])) {
$parametresAdmin = $parametresAdmin[0];
} else {
$parametresAdmin = new ParametresAdmin();
}
// Configure Dompdf according to your needs
$pdfOptions = new Options();
$pdfOptions->set('isRemoteEnabled', true);
// Instantiate Dompdf with our options
$dompdf = new Dompdf($pdfOptions);
$dompdf->set_option('isHtml5ParserEnabled', true);
// Retrieve the HTML generated in our twig file
$html = $this->renderView('absence/pdf.html.twig', [
'title' => "Welcome to our PDF Test",
'parametresAdmin' => $parametresAdmin
]);
// Load HTML to Dompdf
$dompdf->loadHtml($html);
// (Optional) Setup the paper size and orientation 'portrait' or 'portrait'
$dompdf->setPaper('A4', 'portrait');
// Render the HTML as PDF
$dompdf->render();
// Output the generated PDF to Browser (inline view)
$dompdf->stream("mypdf.pdf", [
"Attachment" => false,
]);
}
And my Twig:
<html>
<head>
<meta charset="UTF-8">
<title>Title of the PDF</title>
</head>
<body>
<h4>{{ title }}</h4>
<p>Lorem Ipsum</p>
{% if parametresAdmin.logoName %}
<img style="width:90px;" src="{{absolute_url(vich_uploader_asset(parametresAdmin, 'logoFile'))}}">
{% endif %}
</body>
</html>
EDIT: When I use an absolute path directly from my files, like :
"C:\Users\user\Desktop\congesTest2\public\admin\logo\avatar2.jpg"
It works.
But it seems that if the absolute path is :
http://........
In this case:
http://127.0.0.1:8000/admin/logo/avatar2.jpg
It doesn't work. But I need this path
Thanks for your help !

Symfony2 translation in twig using CsvFileLoader

I want to implement translation in Symfony2 using csvFileLoader. In config.yml translation field is enabled and locale set to fr.
I have written following code in controller.
$file = //file path eg: messages.fr.csv;
$loader = new CsvFileLoader($file);
$loader->setCsvControl(',');
$x = $loader->load($file, 'fr');
$translator = new Translator('fr',new MessageSelector());
$translator->addLoader('csv', $loader);
$translator->addResource('csv', $file, 'fr','messages');
$translator->trans('Symfony is great');
Above code works fine. If I use trans tag in twig then text is not translated. Even I add twig extentions:-
$loader = new \Twig_Loader_Filesystem("path to twig template file");
$twig = new \Twig_Environment($loader);
$twig->addExtension(new TranslationExtension($translator));
And Code in witten in twig file
{% trans %}Symfony2 is great{% endtrans %}
Above text is not translated in twig. I tried it using .xlf file then it works but for .csv file translation is not working.
Need solution for above mentioned issue.
Controller :
/**
* #Route("{_locale}/translate1")
*/
public function showTwoAction(Request $request)
{
$delimiter = ";";
$enclosure = '"';
$escape = '\\';
$file = __DIR__.'/file_'.$request->getLocale().'.csv';
$translator = new Translator($request->getLocale(), new MessageSelector());
$translator->addLoader('csv', new CsvFileLoader());
$translator->addResource('csv', $file, $request->getLocale());
$catalogue = $translator->getCatalogue($request->getLocale());
$messages = $catalogue->all();
while ($catalogue = $catalogue->getFallbackCatalogue())
{
$messages = array_replace_recursive($catalogue->all(), $messages);
}
return $this->render("PRIYACoreTranslateBundle:Default:translate.html.twig",$messages);
}
Twig :
{{ messages.Hi }}
{{ messages.Hello }}
Translation CSV Files
=> file_en.csv
"Hi";"Hi"
"Hello";"Hello"
=> file_fr.csv
"Hi";"salut"
"Hello";"Bonjour"
Hope it helps.

Upload multiple files in PHP form

I am currently uploading single image file at a time to mysql database, However I need to upload 800 images, so I want to select all images and upload them by one click. This is my PHP controller
/**
* #Route("/insert", name="satellite_images_create")
*/
public function insertAction(Request $request)
{
$satelliteImage=new satelliteImage;
$form=$this->createFormBuilder($satelliteImage)
->add('file')
->add('save',SubmitType::class,array('label'=>'Insert Image','attr'=>array('class'=>'btn btn-primary','style'=>'margin-bottom:15px')))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em=$this->getDoctrine()->getManager();
$satelliteImage->upload();
$em->persist($satelliteImage);
$em->flush();
$this->addFlash(
'notice',
'Image inserted successfully'
);
return $this->redirectToRoute('satellite_images');
}
return $this->render('satelliteImages/insert.html.twig',array(
'form'=>$form->createView()));
}
SatelliteImage ENTITY has a function to handle the upload
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
$imgFile=$this->getFile();
$this->setImage(file_get_contents($imgFile));
$this->getFile()->move(
$this->getUploadRootDir(),
$this->getFile()->getClientOriginalName()
);
// set the path property to the filename where you've saved the file
$this->path = $this->getFile()->getClientOriginalName();
// clean up the file property as you won't need it anymore
$this->file = null;
}
And here is my twig file
{% extends 'base.html.twig' %}
{% block body %}
<h2 class="page-header">Insert Image</h2>
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
{% endblock %}
How I modify the form and the upload function so that I can select all the image files to be uploaded?Thanks.
I would recommend checking out DropzoneJS http://www.dropzonejs.com/
It is a javascript front end for handling multiple file uploads. It works by passing the files to a PHP backend for storage / processing.
EDIT - ADDITION
If you need info on how to use DropzoneJS with symfony2 then check out Multi upload Symfony 2.3 with Dropzone
Also, this question is basically a duplicate of Problems With Multiple File Upload In Symfony2

PHPUnit test a function that write in file and check the content into created file

I am contributing to sonata/exporter, a library used for export data in many formats (CSV, JSON, XML, XLS, ...).
I work on a Writer that converts boolean values into strings (e.g. yes/no) by encapsulating another Writer (like CsvWriter or XlsWriter).
It's my first experience with phpunit.
All unit tests made on the existing Writers use this logic :
- Create a file.
- Write data in file using the corresponding format.
- Make an assertEquals on file_get_contents(filename).
So, I've written this test :
public function setUp()
{
$this->filename = 'formatedbool.xls';
$this->sampleWriter = new XlsWriter($this->filename, false);
$this->trueLabel = 'oui';
$this->falseLabel = 'non';
if (is_file($this->filename)) {
unlink($this->filename);
}
}
public function testValidDataFormat()
{
$writer = new FormatedBoolWriter($this->sampleWriter, $this->trueLabel, $this->falseLabel);
$writer->open();
$writer->write(array('john', 'doe', false, true));
$writer->close();
$expected = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name=ProgId content=Excel.Sheet><meta name=Generator content="https://github.com/sonata-project/exporter"></head><body><table><tr><td>john</td><td>doe</td><td>non</td><td>oui</td></tr></table></body></html>';
$this->assertEquals($expected, trim(file_get_contents($this->filename)));
}
When submitting my PR, the owner says me :
just use a mock with expected method call and check calling argument, this will avoid creating the file. see https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects.examples.with-consecutive.php
I have begin to rewrite tests using a Mock but I have an error on file_get_contents because file is not created.
The "write" method just write in a file and return nothing.
I think he want I test the data after converting bools, but before writing in file.
How can I check the result of the file content without really create it ?
Or simply access to my $data during the method call ?
EDIT Thanks to #Cerad, the code I've submitted :
public function testValidDataFormat()
{
$data = array('john', 'doe', false, true);
$expected = array('john', 'doe', 'no', 'yes');
$mock = $this->getMockBuilder('Exporter\Writer\XlsWriter')
->setConstructorArgs(array('formattedbool.xls', false))
->getMock();
$mock->expects($this->any())
->method('write')
->with($this->equalTo($expected));
$writer = new FormattedBoolWriter($mock, $this->trueLabel, $this->falseLabel);
$writer->open();
$writer->write($data);
$writer->close();
}
I'm waiting for answer of the project owner.
EDIT PR merged at https://github.com/sonata-project/exporter/pull/56
This question has been answered by #Cerad by commenting on the question.
The PR has been accepted and merged, see https://github.com/sonata-project/exporter/pull/56

Categories