Initial commit

This commit is contained in:
Chris 2017-12-30 00:49:06 +01:00
commit 26942cdbde
9 changed files with 420 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/vendor/
/composer.lock

26
composer.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "noccylabs/pdf-bundle",
"description": "Generate PDFs in Symfony",
"type": "bundle",
"require": {
"dompdf/dompdf": "^0.8.1"
},
"license": "GPL-3.0",
"authors": [
{
"name": "Christopher Vagnetoft",
"email": "cvagnetoft@gmail.com"
}
],
"repositories": [
{
"type": "composer",
"url": "https://packages.noccylabs.info/composer/"
}
],
"autoload": {
"psr-4": {
"NoccyLabs\\Bundle\\PdfBundle\\": "src/"
}
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace NoccyLabs\Bundle\PdfBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('noccy_labs_pdf_converter');
// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.
return $treeBuilder;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace NoccyLabs\Bundle\PdfBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration.
*
* @link http://symfony.com/doc/current/cookbook/bundles/extension.html
*/
class NoccyLabsPdfExtension extends Extension
{
/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace NoccyLabs\Bundle\PdfBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class NoccyLabsPdfBundle extends Bundle
{
}

49
src/Pdf/PdfGenerator.php Normal file
View File

@ -0,0 +1,49 @@
<?php
namespace NoccyLabs\Bundle\PdfBundle\Pdf;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Dompdf\Dompdf;
class PdfGenerator
{
protected $tempDir;
public function __construct($tempDir)
{
$this->tempDir = $tempDir;
}
public function generate($html, array $options=[])
{
$pdf = new Dompdf();
$pdf->loadHtml($html);
$pdf->render();
$output = $pdf->output();
return $output;
}
public function generateResponseFromHtml($html, array $options=[])
{
$tempFile = $this->tempDir . "/" . "pdf_" . md5(uniqid()) . ".pdf";
// Call on generate with the options provided
$output = $this->generate($html, $options);
file_put_contents($tempFile, $output);
// Prepare the response
$response = new BinaryFileResponse($tempFile);
if (array_key_exists('filename', $options)) {
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $options['filename']);
} else {
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE);
}
$response->deleteFileAfterSend(true);
return $response;
}
}

View File

@ -0,0 +1,14 @@
services:
_defaults:
autowire: true
autoconfigure: true
NoccyLabs\Bundle\PdfBundle\Controller\DefaultController:
public: true
calls:
- [ setGenerator, [ "@noccylabs.pdf.generator" ]]
noccylabs.pdf.generator:
class: NoccyLabs\Bundle\PdfBundle\Pdf\PdfGenerator
arguments: [ "%kernel.cache_dir%" ]
public: true

View File

@ -0,0 +1,164 @@
{% extends "NoccyLabsPdfBundle:Pdf:document.html.twig" %}
{% import "NoccyLabsPdfBundle:Pdf:document.html.twig" as page %}
{% import _self as helpers %}
{% block footer %}
<table class="full-width">
<tr>
<td>
<div class="small">Postal address:</div>
<div>Some Company Name<br>1234 Address St.<br>12345 Somewhere</div>
</td>
<td>
<div class="small">Postal address:</div>
<div>Some Company Name<br>1234 Address St.<br>12345 Somewhere</div>
</td>
<td>
<div class="small">Postal address:</div>
<div>Some Company Name<br>1234 Address St.<br>12345 Somewhere</div>
</td>
</tr>
</table>
{% endblock %}
{% block styles %}
body {
font-family: sans-serif;
font-size: 9pt;
}
.small {
font-size: 7pt;
}
table.full-width {
width: 100%;
}
table.bordered {
border: solid 1px #666;
border-collapse: collapse;
}
table.bordered td,
table.bordered th {
padding: 3px;
vertical-align: top;
}
table.bordered thead {
background: #cde;
border-bottom: solid 1px #666;
}
.page-footer {
border-top: solid 1px #000;
padding-top: 5px;
}
.monospaced {
font-family: monospace;
}
.align-right {
text-align: right;
}
{% endblock %}
{% block body %}
<div class="row">
<div class="col-2"><div class="small">Client No.</div>123456</div>
<div class="col-2"><div class="small">Date</div>2017-12-01</div>
<div class="col-2">Third</div>
<div class="col-5"></div>
<div class="col-1"><div class="small">Page</div>1 (2)</div>
</div>
<div class="row">
</div>
<table class="full-width bordered monospaced">
{{ helpers.thead() }}
<tbody>
<tr>
<td>12345</td>
<td>Abcd<br>multi-line!</td>
<td class="align-right" style="background:#def;">199.99</td>
</tr>
<tr>
<td>12345</td>
<td>Abcd<br>multi-line!</td>
<td class="align-right" style="background:#def;">199.99</td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
</tbody>
</table>
{{ page.break() }}
<div class="row">
<div class="col-11">&nbsp;</div>
<div class="col-1"><div class="small">Page</div>2 (2)</div>
</div>
<table class="full-width bordered monospaced">
{{ helpers.thead }}
<tbody>
<tr>
<td>12345</td>
<td>Abcd<br>multi-line!</td>
<td class="align-right" style="background:#def;">199.99</td>
</tr>
<tr>
<td>12345</td>
<td>Abcd<br>multi-line!</td>
<td class="align-right" style="background:#def;">199.99</td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
<tr>
<td colspan="2">&nbsp;<br>&nbsp;</td>
<td style="background:#def;"></td>
</tr>
</tbody>
</table>
{% endblock %}
{% macro thead() %}
<thead>
<tr>
<th width="15%">SKU</th>
<th>Description</th>
<th width="10%">Price</th>
</tr>
</thead>
{% endmacro %}

View File

@ -0,0 +1,99 @@
{#
# This is the base document template for PdfBundle. You should construct your
# views by extending from this template.
#
# (c) 2017, NoccyLabs. Licensed under GPL v3
#}
{# -- break macro -- #}
{% macro break() %}
</div><div class="new-page">
{% if block("footer") is defined %}
<div class="page-footer">{{ block("footer") }}</div>
{% endif %}
{% endmacro %}
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@media all {
div.page-footer {
position: fixed;
bottom: 2cm;
}
div.new-page {
page-break-before: always;
}
div.row {
display: block;
margin: 5px 0px;
width: 100%;
}
div.row:before,
div.row:after {
content: "";
display: table;
clear: both;
}
div.row > div {
float: left;
min-height: 1px;
}
div.col-1 {
width: 8.333%;
}
div.col-2 {
width: 16.667%;
}
div.col-3 {
width: 25.000%;
}
div.col-4 {
width: 33.333%;
}
div.col-5 {
width: 41.667%;
}
div.col-6 {
width: 50.000%;
}
div.col-7 {
width: 58.333%;
}
div.col-8 {
width: 66.667%;
}
div.col-9 {
width: 75.000%;
}
div.col-10 {
width: 83.333%;
}
div.col-11 {
width: 91.667%;
}
div.col-12 {
width: 100.000%;
}
{% block styles %}
{% endblock %}
}
</style>
</head>
<body>
{% if block("footer") is defined %}
<div class="page-footer">{{ block("footer") }}</div>
{% endif %}
<div>
{% block body %}
{% endblock %}
</div>
</body>
</html>