Initial commit
This commit is contained in:
commit
26942cdbde
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/vendor/
|
||||
/composer.lock
|
26
composer.json
Normal file
26
composer.json
Normal 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/"
|
||||
}
|
||||
}
|
||||
}
|
29
src/DependencyInjection/Configuration.php
Normal file
29
src/DependencyInjection/Configuration.php
Normal 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;
|
||||
}
|
||||
}
|
28
src/DependencyInjection/NoccyLabsPdfExtension.php
Normal file
28
src/DependencyInjection/NoccyLabsPdfExtension.php
Normal 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');
|
||||
}
|
||||
}
|
9
src/NoccyLabsPdfBundle.php
Normal file
9
src/NoccyLabsPdfBundle.php
Normal 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
49
src/Pdf/PdfGenerator.php
Normal 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;
|
||||
}
|
||||
}
|
14
src/Resources/config/services.yml
Normal file
14
src/Resources/config/services.yml
Normal 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
|
164
src/Resources/views/Example/example.html.twig
Normal file
164
src/Resources/views/Example/example.html.twig
Normal 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"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ page.break() }}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-11"> </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"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </td>
|
||||
<td style="background:#def;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> <br> </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 %}
|
99
src/Resources/views/Pdf/document.html.twig
Normal file
99
src/Resources/views/Pdf/document.html.twig
Normal 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>
|
Loading…
Reference in New Issue
Block a user