-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 88ecc20
Showing
12 changed files
with
440 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/vendor | ||
composer.phar | ||
composer.lock | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
language: php | ||
|
||
php: | ||
- 5.3 | ||
- 5.4 | ||
|
||
before_script: | ||
- curl -s http://getcomposer.org/installer | php | ||
- php composer.phar install --dev | ||
|
||
script: phpunit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "kodebyraaet/prince", | ||
"description": "Simple prince wrapper for Prince library", | ||
"authors": [ | ||
{ | ||
"name": "Anthoni Giskegjerde", | ||
"email": "[email protected]" | ||
}, | ||
{ | ||
"name": "Jon Myrstad", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"require": { | ||
"php": ">=5.3.0", | ||
"illuminate/support": "4.2.x" | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Kodebyraaet\\Prince\\": "src/" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<phpunit backupGlobals="false" | ||
backupStaticAttributes="false" | ||
bootstrap="vendor/autoload.php" | ||
colors="true" | ||
convertErrorsToExceptions="true" | ||
convertNoticesToExceptions="true" | ||
convertWarningsToExceptions="true" | ||
processIsolation="false" | ||
stopOnFailure="false" | ||
syntaxCheck="false" | ||
> | ||
<testsuites> | ||
<testsuite name="Package Test Suite"> | ||
<directory suffix=".php">./tests/</directory> | ||
</testsuite> | ||
</testsuites> | ||
</phpunit> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Laravel PrinceXML Wrapper | ||
|
||
Laravel PrinceXML Wrapper is a Laravel 4.2 package that wraps around the http://www.princexml.com/ PDF generator. | ||
|
||
## Installation | ||
There's a requirement to have the "prince" executable installed. | ||
``` | ||
Install the "prince" executable from http://www.princexml.com/download/. | ||
``` | ||
Run the following command to add Kodebyraaet/Prince to download and install. | ||
``` | ||
composer require kodebyraaet/prince | ||
``` | ||
Add the following .env variable to your .env.*.php. | ||
``` | ||
PRINCE_EXECUTABLE_PATH=/path/to/prince | ||
``` | ||
Add the following to your app.php file in the service provider and alias sections respectively. The alias/facade is optional. | ||
```` | ||
'Kodebyraaet\Prince\PrinceServiceProvider', | ||
'Prince' => 'Kodebyraaet\Prince\Facades\Prince', | ||
```` | ||
|
||
# Usage | ||
The Kodebyraaet\Prince\Prince class is bound in the Laravel IoC as a Kodebyraaet\Prince\PrinceInterface, so everywhere the IoC automatically resolves dependencies (ie. in controllers) this is the preferred way to use Prince. Optionally you can also use $app->make(...) or App::make(...); You can also use \Prince or Kodebyraaet\Prince\Facades\Prince directly anywhere. | ||
|
||
## Methods | ||
All methods are chainable so you can dynamically add more and more markup as you go to a Prince document. For example: | ||
``` | ||
$prince->html('<html><body>') | ||
->html('<div><h1>Appending more content.</h1></div> | ||
->html('</body></html>'); | ||
``` | ||
|
||
The *html* method takes html as a string and appends it to the internally stored markup. | ||
``` | ||
$prince->html('<div>Some HTML</div>'); | ||
``` | ||
|
||
The *view* method takes a Laravel view that has not yet been rendered and renders is and appends it to the internally stored markup. | ||
``` | ||
$prince->view(View::make('someview',['somevar' => $somevalue])); | ||
``` | ||
|
||
The *download* method returns a Response object that can be returned to the client for view in browser/download. For example, in a Controller you can return this for a direct view of a generated PDF. | ||
``` | ||
return $prince->html('<html>...</html>')->download(); | ||
``` | ||
|
||
The *store* method required a path and returns the same path if successful. | ||
``` | ||
$pdfPath = $prince->html('<html>...</html>')->store(public_path('/pdf/example.pdf')); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php namespace Kodebyraaet\Prince\Exceptions; | ||
|
||
use Exception; | ||
|
||
class PrinceError extends Exception | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php namespace Kodebyraaet\Prince\Exceptions; | ||
|
||
use Exception; | ||
|
||
class UnableToExecute extends Exception | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php namespace Kodebyraaet\Prince\Facades; | ||
|
||
use Illuminate\Support\Facades\Facade; | ||
use Kodebyraaet\Prince\PrinceInterface; | ||
|
||
class Prince extends Facade | ||
{ | ||
|
||
/** | ||
* Get the registered name of the component. | ||
* | ||
* @return string | ||
* | ||
* @throws \RuntimeException | ||
*/ | ||
protected static function getFacadeAccessor() | ||
{ | ||
return PrinceInterface::class; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
<?php namespace Kodebyraaet\Prince; | ||
|
||
use File; | ||
use Illuminate\View\View; | ||
use Illuminate\Http\Response; | ||
use Response as ResponseFacade; | ||
use Illuminate\Foundation\Application; | ||
use Kodebyraaet\Prince\Exceptions\PrinceError; | ||
use Kodebyraaet\Prince\Exceptions\UnableToExecute; | ||
|
||
class Prince implements PrinceInterface | ||
{ | ||
|
||
/** | ||
* App Instance. | ||
* | ||
* @var Application | ||
*/ | ||
private $app; | ||
|
||
/** | ||
* Path to the Prince executable. | ||
* | ||
* @var string | ||
*/ | ||
private $executable; | ||
|
||
/** | ||
* Commandline arguments to send to the executable. | ||
* | ||
* @var string | ||
*/ | ||
private $arguments; | ||
|
||
/** | ||
* Echo out error messages. | ||
* | ||
* @var bool | ||
*/ | ||
private $displayErrors; | ||
|
||
/** | ||
* Enable UTF8 | ||
* | ||
* @var bool | ||
*/ | ||
private $useUtf8; | ||
|
||
/** | ||
* Holds the markup that should be sent to the prince executable. | ||
* | ||
* @var string | ||
*/ | ||
private $markup = ''; | ||
|
||
/** | ||
* Prince constructor. | ||
* | ||
* @param Application $app | ||
*/ | ||
public function __construct(Application $app) | ||
{ | ||
$this->app = $app; | ||
|
||
$this->executable = getenv('PRINCE_EXECUTABLE_PATH') ? getenv('PRINCE_EXECUTABLE_PATH') : '/usr/bin/prince'; | ||
|
||
$this->arguments = ' --server -i "html" --silent -'; | ||
|
||
$this->displayErrors = true; | ||
|
||
$this->useUtf8 = false; | ||
} | ||
|
||
/** | ||
* Takes a View and returns $this to further chain methods on. | ||
* | ||
* @param View $view | ||
* @return $this | ||
*/ | ||
public function view(View $view) | ||
{ | ||
$this->markup .= $view->render(); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Takes a HTML string and returns $this to further chain methods on. | ||
* | ||
* @param $html | ||
* @return $this | ||
*/ | ||
public function html($html) | ||
{ | ||
$this->markup .= $html; | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Returns the generated PDF as as a Response. | ||
* | ||
* @return Response | ||
*/ | ||
public function download() | ||
{ | ||
$data = $this->generate(); | ||
|
||
$this->reset(); | ||
|
||
return ResponseFacade::stream(function () use ($data) { | ||
$out = fopen('php://output', 'w'); | ||
fputs($out, $data); | ||
fclose($out); | ||
}, 200, [ | ||
'Content-Type' => 'application/pdf' | ||
]); | ||
|
||
} | ||
|
||
/** | ||
* Stores the generated PDF in at a provided path. | ||
* | ||
* @param $path | ||
* @return mixed | ||
*/ | ||
public function store($path) | ||
{ | ||
$data = $this->generate(); | ||
|
||
File::put($path, $data); | ||
|
||
$this->reset(); | ||
|
||
return $path; | ||
} | ||
|
||
/** | ||
* Does the actual generation of a PDF. Returns raw PDF data for further | ||
* processing. | ||
* | ||
* @return string | ||
* @throws UnableToExecute | ||
*/ | ||
private function generate() | ||
{ | ||
$markup = ($this->useUtf8) ? utf8_decode($this->markup) : $this->markup; | ||
|
||
// The different ways we want to communicate with the executable. | ||
$descriptorSpec = array( | ||
0 => array("pipe", "r"), | ||
1 => array("pipe", "w"), | ||
2 => array("pipe", "w") | ||
); | ||
|
||
// Tries to open up a process of prince at $this->executable path, | ||
// appends $this->arguments to the executable call. | ||
if (!is_resource($process = proc_open($this->executable . $this->arguments, $descriptorSpec, $pipes))) { | ||
throw new UnableToExecute('Unable to open a prince executable at path ' . $this->executable . '.'); | ||
} | ||
|
||
// Write all the markup to the pipe we can write to | ||
// and tell the executable we're done sending markup. | ||
fwrite($pipes[0], $markup); | ||
fclose($pipes[0]); | ||
|
||
// Get the pure response from the executable. | ||
$rawData = stream_get_contents($pipes[1]); | ||
fclose($pipes[1]); | ||
|
||
// Check if the executable gave us any errors. | ||
$this->parseErrors($pipes[2]); | ||
fclose($pipes[2]); | ||
|
||
// End the executable in it's entirety. | ||
proc_close($process); | ||
|
||
$this->reset(); | ||
|
||
return $rawData; | ||
} | ||
|
||
/** | ||
* Checks if there are any errors in the pipeline. | ||
* | ||
* @param resource $pipe | ||
* @throws PrinceError | ||
* @return bool | ||
*/ | ||
protected function parseErrors($pipe) | ||
{ | ||
// While the executable is still piping data. | ||
while (!feof($pipe)) { | ||
$line = fgets($pipe); | ||
|
||
if ($line) { | ||
$tag = substr($line, 0, 3); | ||
$body = substr($line, 4); | ||
|
||
if ($tag == 'fin') { | ||
// End of data. | ||
return false; | ||
} | ||
|
||
$messages[] = $body; | ||
} | ||
} | ||
|
||
// If we have any errors we throw a PrinceError. | ||
if (isset($messages)) { | ||
$errorMessage = 'Prince error: ' . implode(', ', $messages); | ||
|
||
throw new PrinceError($errorMessage); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Prepares the object for re-use. | ||
*/ | ||
protected function reset() | ||
{ | ||
$this->markup = ''; | ||
} | ||
|
||
} |
Oops, something went wrong.