In an implementation of PdfBundle, adding a stylesheet to the Pdf() annotation neither throws an error or is used. The page rendered is a default 8.5 x 11, not the expected 5 x 8. Replacing the stylesheet file name with random characters does not elicit an error. Is other configuration required to take advantage of a stylesheet?
Controller:
/**
* #Pdf(stylesheet="ManaClientBundle:Test:pdfstyle.xml.twig",
* #Route("/card")
*/
public function cardAction() {
$em = $this->getDoctrine()->getManager();
$household = $em->getRepository('ManaClientBundle:Household')->find(8607);
$facade = $this->get('ps_pdf.facade');
$response = new Response();
$this->render('ManaClientBundle:Test:card.pdf.twig', array(
'household' => $household,
'date' => date_create(),
), $response);
$xml = $response->getContent();
$content = $facade->render($xml);
return new Response($content, 200, array('content-type' => 'application/pdf'));
}
Template (in .../Resources/views/Test/)
<pdf>
<page id="card">
...
</page>
</pdf>
Stylesheet in .../Resources/views/Test/pdfstyle.xml.twig
<stylesheet>
<page id="card" page-size="8in:5in" margin=".5in" font-size="12">
</page>
</stylesheet>
From the author of the bundle:
If you use $facade object directly, Pdf annotation is unnecessary. You should use Pdf annotation when you want to use pdf rendering in implicit way. In you code you should pass stylesheet xml as second argument of $facade->render(...) method.
Controller now reads:
/**
* #Route("/card")
*/
public function cardAction() {
$em = $this->getDoctrine()->getManager();
$household = $em->getRepository('ManaClientBundle:Household')->find(8607);
$stylesheetXml = $this->renderView('ManaClientBundle:Test:pdfstyle.xml.twig', array());
$facade = $this->get('ps_pdf.facade');
$response = new Response();
$this->render('ManaClientBundle:Test:card.pdf.twig', array(
'household' => $household,
'date' => date_create(),
), $response);
$xml = $response->getContent();
$content = $facade->render($xml, $stylesheetXml);
return new Response($content, 200, array('content-type' => 'application/pdf'));
}
Related
I would like to do this in Symfony 3 :
public function styleAction()
{
// Fetch it from service or whatever strategy you have
$backgroundColor = '#ff0000';
return $this->render(
'AcmeMyBundle::somefile.css.twig',
['backgroundColor' => $backgroundColor],
['Content-Type' => 'text/css']
);
}
But infortunately I still get a problem with the third argument of the render method.
Here is my error message :
Catchable Fatal Error: Argument 3 passed to Symfony\Bundle\FrameworkBundle\Controller\Controller::render() must be an instance of Symfony\Component\HttpFoundation\Response, array given
EDIT :
This is how to solve it :
public function styleAction()
{
$response = new Response();
$response->headers->set('Content-Type', 'text/css');
// replace this example code with whatever you need
return $this->render('main.css.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
],
$response
);
}
I'm in the process of creating a REST API with Symfony and the FOSRestBundle and am pretty much new to the both.
Now I wonder how to generate an URL to a resource I just created. Routes are setup like this:
# app/config/routing.yml
characters:
type: rest
prefix: /api
resource: "#Optc/Resources/config/routing/characters_routing.yml"
NelmioApiDocBundle:
prefix: /api/doc
resource: "#NelmioApiDocBundle/Resources/config/routing.yml"
# Resources/Optc/Resources/config/routing/characters_routing.yml
characters:
type: rest
resource: Optc\Controller\CharactersController
The part of the Characters controller that creates the resource:
$character = new Character();
$form = $this->createForm(new CharacterType(), $character);
$form->bind($data);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($character);
$em->flush();
$response->headers->set('Location', $this->generateUrl('get_characters', array('id' => $user->getId()), true));
$view = $this->view($character, 200);
return $this->handleView($view);
}
Update: Full controller code:
<?php
namespace Optc\Controller;
use FOS\RestBundle\Controller\Annotations\QueryParam;
use FOS\RestBundle\Controller\FOSRestController;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Optc\Entity\Character;
use Optc\Form\CharacterType;
use Optc\HttpFoundation\File\Base64File;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Characters Controller
*/
class CharactersController extends FOSRestController
{
/**
* Get the list of characters.
*
* #param string $page integer with the page number (requires param_fetcher_listener: force)
*
* #return array data
*
* #QueryParam(name="page", requirements="\d+", default="1", description="Page number of the overview.")
* #ApiDoc()
*/
public function getCharactersAction($page)
{
$characters = $this
->getDoctrine()
->getRepository('Optc:Character')
->findAll();
$view = $this->view($characters, 200);
return $this->handleView($view);
}
public function getCharacterAction($id)
{
$character = $this
->getDoctrine()
->getRepository('Optc:Character')
->findOneById($id);
if (!$character) {
throw new HttpException(404, sprintf('Character with id %d not found!', $id));
}
$view = $this->view($character, 200);
return $this->handleView($view);
}
/**
* Create a new character.
*
* #param Request $request
*
* #return View view instance
*
* #ApiDoc()
*/
public function postCharacterAction(Request $request)
{
$data = $request->request->all();
// If the request contains image date, first convert it from its base64 enconding to a real file
if ($request->request->has('image') && $request->request->get('id')) {
$imagePath = realpath($this->get('kernel')->getRootDir() . '/../web'.$this->container->getParameter('upload_path_characters')).'/'.$request->request->get('id');
$file = Base64File::create($imagePath, $request->request->get('image'));
$data['image'] = $file;
}
$character = new Character();
$form = $this->createForm(new CharacterType(), $character);
$form->bind($data);
var_dump($form->isValid());
var_dump($form->getErrorsAsString());
var_dump($this->generateUrl('get_characters', array('id' => $character->getId()), true));
die();
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($character);
$em->flush();
$response->headers->set('Location', $this->generateUrl('acme_demo_user_get', array('id' => $user->getId()), true));
$view = $this->view($character, 200);
return $this->handleView($view);
}
else {
}
}
}
The thing that isn't quite working like I expected is the generateUrl part to set the Location header. It spits out http://optc.local/api/characters?id=2. This will of course only list all resources instead. But what I want is http://optc.local/api/characters/2.
How would I do that? Seems like I'm missing something simple.
(By the way, the PHP part about returning the Location header is from http://williamdurand.fr/2012/08/02/rest-apis-with-symfony2-the-right-way/, so I expected this to be the "right" way.)
you should check app/console debug:router in terminal to see what name symfony has named the route
in my case it used a minus instead of an underscore
i.e get-character
You must use get_character route instead of get_characters route,
I suggest to you whether implement ClassResourceInterface or use RouteResource annotation, that can use method name as getAction, cgetAction(this is only a suggestion)
I want to be able to pass a node id to a path and generate an RTF file. I am having problems loading the library. I am using the Libraries 2 method. The error is:
PHP Fatal error: Class 'PHPRtfLite' not found in [redacted]/sites/all/modules/custom/ain_export/ain_export.module on line 22 request_id="245a0131-9519-4fa9-a512-3b60d0b91ad8"
So I've been making sure the files are where they should be. In my /sites/all/libraries directory I have a folder called 'phprtflite', set up like this:
-- phprtflite
----PHPRtfLite.php
Below is my code, now edited per the comment below to load the library inside my callback. I am still getting the error, except now on line 41. It seems to not be loading the library?
<?php
/**
* Implements hook_libraries_info().
*/
function ain_export_libraries_info() {
$libraries['phprtflite'] = array(
'name' => 'PHPRtfLite',
'vendor url' => 'http://sourceforge.net/projects/phprtf/',
'download url' => 'http://sourceforge.net/projects/phprtf/',
'files' => array(
'php' => array('PHPRtfLite.php'),
),
);
return $libraries;
}
/**
* Implements hook_menu().
*/
function ain_export_menu() {
$items = array();
$items['admin/ain_export/%'] = array(
'title' => 'Export Node',
'page callback' => 'ain_export_page',
'page arguments' => array(2),
'access arguments' => array('access administration pages'),
);
return $items;
}
// spit out node
function ain_export_page($nid) {
// load library
libraries_load('phprtflite');
// register PHPRtfLite class loader
PHPRtfLite::registerAutoloader();
if (isset($nid) ) {
try {
$rtf = new PHPRtfLite();
// set page properties
$rtf->setMargins(2.54, 2.54, 2.54, 2.54);
$rtf->setPaperFormat(PHPRtfLite::PAPER_LETTER);
// define fonts
$fontH1 = new PHPRtfLite_Font(16, 'Arial', '#000000');
$fontH2 = new PHPRtfLite_Font(14, 'Arial', '#000000');
$fontP = new PHPRtfLite_Font(12, 'Arial', '#000000');
// vertical space
$formatH1 = new PHPRtfLite_ParFormat();
$formatH1->setSpaceAfter(8);
$formatH2 = new PHPRtfLite_ParFormat();
$formatH2->setSpaceAfter(6);
$formatP = new PHPRtfLite_ParFormat();
$formatP->setSpaceAfter(3);
// page content
$node = node_load($nid); // load the node
// headline
$section = $rtf->AddSection();
$section->writeText($node->title, $fontH1, $formatH1);
// output file
$rtf->SendRtf( $nid . '.rtf' );
} catch (Exception $e) {
$error = $e->getMessage();
}
}
}
Using the example from http://twig.sensiolabs.org/doc/advanced.html#creating-an-extension: within my main Slim file that creates the view:
$filter = new Twig_SimpleFilter( 'stripslashes', function ( $string ) {
return stripslashes( $string );
});
$loader = new \Twig_Loader_String();
$twig = new Twig_Environment($loader);
$twig->addFilter($filter);
$app->view($twig);
$app->view()->setData( array(
'nav' => $nav,
'sidenav' => $sidenav,
));
Results in: Call to undefined method Twig_Environment::appendData().
Tried in various ways such as this:
$app->view(new \Slim\Views\Twig());
$app->view->parserExtensions = array(
new \Slim\Views\TwigExtension(),
);
$app->view->addFilter($filter);
but I'm just not understanding how it's supposed to work.
For Slim 3, things have changed. It can be done in one line:
$view->getEnvironment()->addFilter($filter);
But that isn't particularly useful without context, so here is a full sample, based on the example provided at the Slim Framework Website: http://www.slimframework.com/docs/features/templates.html
This code demonstrates adding a filter to encode text with rot13
<?php
// Create app
$app = new \Slim\App();
// Get container
$container = $app->getContainer();
// Register component on container
$container['view'] = function ($container) {
$view = new \Slim\Views\Twig('path/to/templates', [
'cache' => 'path/to/cache'
]);
$view->addExtension(new \Slim\Views\TwigExtension(
$container['router'],
$container['request']->getUri()
));
$filter = new Twig_SimpleFilter('rot13', function ($string) {
return str_rot13($string);
});
$view->getEnvironment()->addFilter($filter);
return $view;
};
// Render Twig template in route
$app->get('/rot13/{text}', function ($request, $response, $args) {
return $this->view->render($response, 'rot13.html', [
'name' => $args['text']
]);
})->setName('rot13');
// Run app
$app->run();
And the html file rot13.html contains:
{{text|rot13}}
Point your browser at yourservername/rot13/pineapple and you should see
cvarnccyr
Ah. Just needed this two liner:
$twig = $app->view->getInstance();
$twig->addFilter($filter);
I want to return in my RandomController::indexAction() an XML Response:
return new Response($this->renderView(
'AcmeRandomBundle:Random:index.xml.twig',
array(
'randomParameter' => $randomParameter
)
));
where index.xml.twig is like that:
<?xml version="1.0" encoding="UTF-8"?>
<randomTag>
{{ randomParameter }}
</randomTag>
When I want to open this action in firefox, I get in firebug:
<html>
<body>
<randomTag>
randomValue
</randomTag>
</body>
</html>
How to return correct XML response?
Try adding correct header on the Response Object like:
$response->headers->set('Content-Type', 'text/xml');
Otherwise add the correct annotation (defaults) on your Controller method like this example:
/**
* #Route("/hello/{name}", defaults={"_format"="xml"}, name="_demo_hello")
* #Template()
*/
public function helloAction($name)
{
return array('name' => $name);
}
Look at the guide for further explaination
If you have many XmlResponse to return, consider creating your own Response object:
<?php
namespace App\Component\HttpFoundation;
use Symfony\Component\HttpFoundation\Response;
class XmlResponse extends Response
{
public function __construct(?string $content = '', int $status = 200, array $headers = [])
{
parent::__construct($content, $status, array_merge($headers, [
'Content-Type' => 'text/xml',
]));
}
}
You can then return new XmlResponse($xmlBody); in your controllers.