Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applied fixes from StyleCI #85

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [1.x]
### Added
- Add `KnpSnappyWriter` that introduces PDF export format.

## [1.4.0](https://github.com/sonata-project/exporter/compare/1.3.4...1.4.0) - 2015-06-09
### Added
Expand Down
16 changes: 10 additions & 6 deletions composer.json
Expand Up @@ -16,18 +16,22 @@
"php": "^5.3 || ^7.0"
},
"require-dev": {
"symfony/routing": "^2.3 || ^3.0",
"symfony/property-access": "^2.3 || ^3.0",
"symfony/phpunit-bridge": "^2.7 || ^3.0",
"propel/propel1": "^1.6",
"fabpot/php-cs-fixer": "~0.1 || ^1.0",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
"h4cc/wkhtmltopdf-amd64": "^0.12",
"knplabs/knp-snappy": "^0.4",
"mikey179/vfsStream": "^1.6",
"propel/propel1": "^1.6",
"sllh/php-cs-fixer-styleci-bridge": "^2.0",
"symfony/phpunit-bridge": "^2.7 || ^3.0",
"symfony/property-access": "^2.3 || ^3.0",
"symfony/routing": "^2.3 || ^3.0"
},
"suggest": {
"ext-curl": "*",
"symfony/routing": "^2.3 || ^3.0",
"symfony/property-access": "^2.3 || ^3.0",
"propel/propel1": "^1.6"
"propel/propel1": "^1.6",
"knplabs/knp-snappy": "For using the KnpSnappyWriter to export data in PDF format"
},
"autoload": {
"psr-0": {
Expand Down
30 changes: 29 additions & 1 deletion docs/reference/outputs.rst
Expand Up @@ -12,5 +12,33 @@ Several output formatters are supported:
* XML
* Excel XML
* XLS (MS Excel)
* PDF

You may also create your own. To do so, simply create a class that implements the ``Exporter\Writer\WriterInterface``.
You may also create your own. To do so, simply create a class that implements the ``Exporter\Writer\WriterInterface``.

The knplabs/knp-snappy writer
=============================

If you want to generate a pdf output, you can use the ``knplabs/knp-snappy`` writer.
You will have to `install the library and its dependencies <https://github.com/KnpLabs/snappy>`_
(including ``wkhtmltopdf``).

The instanciation of the writer goes like this:

.. code-block:: php

<?php

use Exporter\Writer\KnpSnappyWriter;
use Knp\Snappy\Pdf;

$writer = new KnpSnappyWriter(
new Pdf(),
'output.pdf',
'/absolute/path/to/the/wkhtmltopdf/binary',
true, // include a header
true, // add borders
array(
'any_supported_snappy_option' => 'and its value',
)
);
245 changes: 245 additions & 0 deletions lib/Exporter/Writer/KnpSnappyWriter.php
@@ -0,0 +1,245 @@
<?php

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Exporter\Writer;

use Knp\Snappy\Pdf;

/**
* Export data in PDF format.
*
* @author Robin Chalas <robin.chalas@gmail.com>
*/
final class KnpSnappyWriter implements WriterInterface
{
/**
* @var Pdf
*/
private $pdfGenerator;

/**
* @var string
*/
private $filename;

/**
* @var string
*/
private $wkhtmltopdf;

/**
* @var bool
*/
private $showHeaders;

/**
* @var bool
*/
private $showBorders;

/**
* @var array
*
* @see http://wkhtmltopdf.org/usage/wkhtmltopdf.txt
*/
private $snappyOptions;

/**
* @var resource
*/
private $file;

/**
* @var string
*/
private $html = '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name=ProgId content=Pdf.Document>
<meta name=Generator content="https://github.com/sonata-project/exporter">
<style></style>
</head>
<body>
[header-html]
<table>[content]</table>
[footer-html]
</body>
</html>';

/**
* @throws \RuntimeException
* @throws \InvalidArgumentException
*
* @param Pdf $pdfGenerator
* @param string $filename
* @param bool $showHeaders
* @param bool $showBorders
* @param array $snappyOptions KnpSnappy options (wkhtmltopdf)
* @param string $wkhtmltopdf Path of the wkhtmltopdf binary
*/
public function __construct(
Pdf $pdfGenerator,
$filename,
$wkhtmltopdf,
$showHeaders = true,
$showBorders = true,
array $snappyOptions = array()
) {
if (!is_bool($showHeaders)) {
throw new \InvalidArgumentException(sprintf(
'The second argument of "%s::__construct()" must be of type boolean, %s given',
__CLASS__,
gettype($showHeaders)
));
}

if (!is_bool($showBorders)) {
throw new \InvalidArgumentException(sprintf(
'The third argument of "%s::__construct()" must be of type boolean, %s given',
__CLASS__,
gettype($showBorders)
));
}

if (is_file($filename)) {
throw new \RuntimeException(sprintf('The file "%s" already exists', $filename));
}

if (!is_executable($wkhtmltopdf)) {
throw new \RuntimeException(sprintf('The file "%s" does not exist or is not executable', $wkhtmltopdf));
}

$this->pdfGenerator = $pdfGenerator;
$this->filename = $filename;
$this->showHeaders = $showHeaders;
$this->showBorders = $showBorders;
$this->snappyOptions = $snappyOptions;
$this->wkhtmltopdf = $wkhtmltopdf;
}

/**
* {@inheritdoc}
*/
public function open()
{
$this->file = fopen($this->filename, 'w', false);
}

/**
* {@inheritdoc}
*/
public function write(array $data)
{
$tmpFile = tmpfile();

if ($this->showBorders) {
$this->addBorders();
}

$this->addMarkupFromOptions();

if ($this->showHeaders) {
fwrite($tmpFile, $this->getHeaders(array_keys($data)));
}

fwrite($tmpFile, '<tr>');

foreach ($data as $value) {
fwrite($tmpFile, sprintf('<td>%s</td>', $value));
}

fwrite($tmpFile, '</tr>');

$tmpFileMetaData = stream_get_meta_data($tmpFile);
$tmpFilePath = $tmpFileMetaData['uri'];

fwrite($this->file, $this->generatePdf($tmpFilePath));

fclose($tmpFile);
}

/**
* {@inheritdoc}
*/
public function close()
{
fclose($this->file);
}

/**
* Generates a PDF using KnpSnappy.
*
* @param string $htmlFilename.
*
* @return string The generated PDF content.
*/
private function generatePdf($htmlFilename)
{
$this->pdfGenerator->setBinary($this->wkhtmltopdf);

foreach ($this->snappyOptions as $key => $value) {
$this->pdfGenerator->setOption($key, $value);
}

$this->html = str_replace('[content]', file_get_contents($htmlFilename), $this->html);

return $this->pdfGenerator->getOutputFromHtml($this->html);
}

/**
* Add style for bordered table.
*/
private function addBorders()
{
$borderedStyle = '<style>table{border-collapse:collapse;width:90%;}th,td{border:1px solid black;}</style>';

$this->html = str_replace('<style></style>', $borderedStyle, $this->html);
}

/**
* @param array $columnNames
*
* @return string
*/
private function getHeaders(array $columnNames)
{
$row = '';

foreach ($columnNames as $name) {
$row .= sprintf('<th>%s</th>', $name);
}

return sprintf('<tr>%s</tr>', $row);
}

/**
* Handles header-html/footer-html wkhtmltopdf options.
*/
private function addMarkupFromOptions()
{
$markupOptions = array('header-html', 'footer-html');

foreach ($markupOptions as $key) {
if (!isset($this->snappyOptions[$key])) {
$this->snappyOptions[$key] = '';
}

$this->html = str_replace(
sprintf('[%s]', $key),
$this->snappyOptions[$key],
$this->html
);

unset($this->snappyOptions[$key]);
}
}
}