Browse Source

Can now add repeating header and footer to PDF output - https://github.com/jonnnnyw/php-phantomjs/issues/99

Jonny Wenmoth 9 years ago
parent
commit
dafb41807d

+ 2 - 1
composer.json

@@ -23,7 +23,8 @@
     },
     "require-dev": {
         "phpunit/phpunit": "~4.0",
-        "zendframework/zendpdf": "~2.0"
+        "zendframework/zendpdf": "~2.0",
+        "smalot/pdfparser": "~0.9"
     },
     "autoload": {
         "psr-0": {

+ 2 - 2
src/JonnyW/PhantomJs/Http/AbstractRequest.php

@@ -375,7 +375,7 @@ abstract class AbstractRequest
      *
      * @access public
      * @param  string $format
-     * @return array
+     * @return array|string
      */
     public function getHeaders($format = 'default')
     {
@@ -405,7 +405,7 @@ abstract class AbstractRequest
      *
      * @access public
      * @param  string $format (default: 'default')
-     * @return array
+     * @return array|string
      */
     public function getBodyStyles($format = 'default')
     {

+ 72 - 0
src/JonnyW/PhantomJs/Http/PdfRequest.php

@@ -57,6 +57,22 @@ class PdfRequest extends CaptureRequest
      */
     protected $margin;
 
+    /**
+     * Repeating header
+     *
+     * @var array
+     * @access protected
+     */
+    protected $header;
+
+    /**
+     * Repeating footer
+     *
+     * @var array
+     * @access protected
+     */
+    protected $footer;
+
     /**
      * Internal constructor
      *
@@ -75,6 +91,8 @@ class PdfRequest extends CaptureRequest
         $this->margin      = '1cm';
         $this->format      = 'A4';
         $this->orientation = 'portrait';
+        $this->header      = array();
+        $this->footer      = array();
 
     }
 
@@ -221,4 +239,58 @@ class PdfRequest extends CaptureRequest
     {
         return $this->margin;
     }
+
+    /**
+     * Set repeating header.
+     *
+     * @access public
+     * @param  string $content
+     * @param  string $height  (default: '1cm')
+     * @return void
+     */
+    public function setRepeatingHeader($content, $height = '1cm')
+    {
+        $this->header = array(
+            'content' => $content,
+            'height'  => $height
+        );
+    }
+
+    /**
+     * Get repeating header.
+     *
+     * @access public
+     * @return array
+     */
+    public function getRepeatingHeader()
+    {
+        return $this->header;
+    }
+
+    /**
+     * Set repeating footer.
+     *
+     * @access public
+     * @param  string $content
+     * @param  string $height  (default: '1cm')
+     * @return void
+     */
+    public function setRepeatingFooter($content, $height = '1cm')
+    {
+        $this->footer = array(
+            'content' => $content,
+            'height'  => $height
+        );
+    }
+
+    /**
+     * Get repeating footer.
+     *
+     * @access public
+     * @return array
+     */
+    public function getRepeatingFooter()
+    {
+        return $this->footer;
+    }
 }

+ 36 - 0
src/JonnyW/PhantomJs/Http/PdfRequestInterface.php

@@ -110,4 +110,40 @@ interface PdfRequestInterface
      * @return string
      */
     public function getMargin();
+
+    /**
+     * Set repeating header.
+     *
+     * @access public
+     * @param  string $content
+     * @param  string $height  (default: '1cm')
+     * @return void
+     */
+    public function setRepeatingHeader($content, $height = '1cm');
+
+    /**
+     * Get repeating header.
+     *
+     * @access public
+     * @return array
+     */
+    public function getRepeatingHeader();
+
+    /**
+     * Set repeating footer.
+     *
+     * @access public
+     * @param  string $content
+     * @param  string $height  (default: '1cm')
+     * @return void
+     */
+    public function setRepeatingFooter($content, $height = '1cm');
+
+    /**
+     * Get repeating footer.
+     *
+     * @access public
+     * @return array
+     */
+    public function getRepeatingFooter();
 }

+ 3 - 4
src/JonnyW/PhantomJs/Http/RequestInterface.php

@@ -180,10 +180,9 @@ interface RequestInterface
      * Get request headers
      *
      * @access public
-     * @param  string $format
-     * @return array
+     * @return array|string
      */
-    public function getHeaders($format = 'default');
+    public function getHeaders();
 
     /**
      * Set body styles
@@ -197,7 +196,7 @@ interface RequestInterface
      * Get body styles
      *
      * @access public
-     * @return array
+     * @return array|string
      */
     public function getBodyStyles();
 }

+ 1 - 1
src/JonnyW/PhantomJs/Resources/procedures/page_body_styles.partial

@@ -1,7 +1,7 @@
 
 page.evaluate(function() {
     
-    var styles = {{ input.getBodyStyles('json') }};
+    var styles = {{ input.getBodyStyles()|json_encode(constant('JSON_FORCE_OBJECT')) }};
     
     for(var property in styles) {
         document.body.style[property] = styles[property];

+ 1 - 3
src/JonnyW/PhantomJs/Resources/procedures/page_custom_headers.partial

@@ -1,5 +1,3 @@
 
-var headers = {{ input.getHeaders('json') }};
-
-page.customHeaders = headers ? headers : {};
+page.customHeaders = {{ input.getHeaders()|json_encode(constant('JSON_FORCE_OBJECT')) }};
 

+ 24 - 7
src/JonnyW/PhantomJs/Resources/procedures/page_paper_size.partial

@@ -5,28 +5,45 @@
         paperHeight      = '{{ input.getPaperHeight() }}',
         paperFormat      = '{{ input.getFormat() }}',
         paperOrientation = '{{ input.getOrientation() }}',
-        paperMargin      = '{{ input.getMargin() }}';
-    
+        paperMargin      = '{{ input.getMargin() }}',
+        header           = {{ input.getRepeatingHeader()|json_encode(constant('JSON_FORCE_OBJECT')) }},
+        footer           = {{ input.getRepeatingFooter()|json_encode(constant('JSON_FORCE_OBJECT')) }};
+
     if(paperWidth && paperHeight) {
         
         debug.push(new Date().toISOString().slice(0, -5) + ' [INFO] PhantomJS - Set page size ~ width: ' + paperWidth + ' height: ' + paperHeight + ' margin: ' + paperMargin);
         
-        page.paperSize = { 
+        var paperSize = { 
             width:  paperWidth, 
             height: paperHeight, 
-            margin: paperMargin 
+            margin: paperMargin
         };
 
     } else {
         
         debug.push(new Date().toISOString().slice(0, -5) + ' [INFO] PhantomJS - Set page size ~ format: ' + paperFormat + ' orientation: ' + paperOrientation + ' margin: ' + paperMargin);
         
-        page.paperSize = { 
+        var paperSize = { 
             format:      paperFormat, 
             orientation: paperOrientation, 
-            margin:      paperMargin 
+            margin:      paperMargin
         };
-        
     }
+    
+    paperSize.header = {
+        height: header.height,
+        contents: phantom.callback(function(pageNum, pageTotal) {
+            return header.content.replace('%pageNum%', pageNum).replace('%pageTotal%', pageTotal);
+        })
+    };
+    
+    paperSize.footer = {
+        height: footer.height,
+        contents: phantom.callback(function(pageNum, pageTotal) {
+            return footer.content.replace('%pageNum%', pageNum).replace('%pageTotal%', pageTotal);
+        })
+    };
+    
+    page.paperSize = paperSize;
 
 {% endif %}

+ 1 - 1
src/JonnyW/PhantomJs/Resources/procedures/validator.proc

@@ -7,7 +7,7 @@ var system  = require('system'),
 
 try {
     
-  syntax = esprima.parse("{{ input.get('procedure')|replace({'"': '\'', '\n': ' ', '\r': ' '}) }}");
+  syntax = esprima.parse("{{ input.get('procedure')|escape('js') }}");
       
 } catch(e) {
     

+ 75 - 3
src/JonnyW/PhantomJs/Tests/Integration/ClientTest.php

@@ -378,7 +378,7 @@ EOF;
     }
 
     /**
-     * Test capture request saves file to
+     * Test PDF request saves file to
      * disk with correct paper size.
      *
      * @access public
@@ -415,7 +415,7 @@ EOF;
     }
 
     /**
-     * Test capture request saves file to
+     * Test PDF request saves file to
      * disk with correct format size.
      *
      * @access public
@@ -449,7 +449,7 @@ EOF;
     }
 
     /**
-     * Test capture request saves file to
+     * Test PDF request saves file to
      * disk with correct orientation.
      *
      * @access public
@@ -482,6 +482,78 @@ EOF;
         $this->assertEquals(30, $pdfWidth);
         $this->assertEquals(21, $pdfHeight);
     }
+    
+    /**
+     * Test can set repeating header
+     * for PDF request
+     *
+     * @access public
+     * @return void
+     */
+    public function testCanSetRepeatingHeaderForPDFRequest()
+    {
+        $this->filename = 'test.pdf';
+        $file = ($this->directory . '/' . $this->filename);
+
+        $client = $this->getClient();
+
+        $request  = $client->getMessageFactory()->createPdfRequest();
+        $response = $client->getMessageFactory()->createResponse();
+
+        $request->setMethod('GET');
+        $request->setUrl('http://jonnyw.kiwi/tests/test-capture.php');
+        $request->setOutputFile($file);
+        $request->setFormat('A4');
+        $request->setOrientation('landscape');
+        $request->setMargin('0cm');
+        $request->setRepeatingHeader('<h1>Header <span style="float:right">%pageNum% / %pageTotal%</span></h1>', '2cm');
+        $request->setRepeatingFooter('<footer>Footer <span style="float:right">%pageNum% / %pageTotal%</span></footer>', '2cm');
+
+        $client->send($request, $response);
+
+        $pdf = (new \Smalot\PdfParser\Parser())
+            ->parseFile($file);
+
+        $text = str_replace(' ', '', $pdf->getText());
+
+        $this->assertContains('Header', $text);
+    }
+    
+    /**
+     * Test can set repeating footer
+     * for PDF request
+     *
+     * @access public
+     * @return void
+     */
+    public function testCanSetRepeatingFooterForPDFRequest()
+    {
+        $this->filename = 'test.pdf';
+        $file = ($this->directory . '/' . $this->filename);
+
+        $client = $this->getClient();
+
+        $request  = $client->getMessageFactory()->createPdfRequest();
+        $response = $client->getMessageFactory()->createResponse();
+
+        $request->setMethod('GET');
+        $request->setUrl('http://jonnyw.kiwi/tests/test-capture.php');
+        $request->setOutputFile($file);
+        $request->setFormat('A4');
+        $request->setOrientation('landscape');
+        $request->setMargin('0cm');
+        $request->setRepeatingHeader('<h1>Header <span style="float:right">%pageNum% / %pageTotal%</span></h1>', '2cm');
+        $request->setRepeatingFooter('<footer>Footer <span style="float:right">%pageNum% / %pageTotal%</span></footer>', '2cm');
+
+        $client->send($request, $response);
+
+        $pdf = (new \Smalot\PdfParser\Parser())
+            ->parseFile($file);
+
+        $text = str_replace(' ', '', $pdf->getText());
+
+        $this->assertContains('Footer', $text);
+    }
 
     /**
      * Test set viewport size sets

+ 3 - 3
src/JonnyW/PhantomJs/Tests/Integration/Procedure/ProcedureCompilerTest.php

@@ -60,7 +60,7 @@ class ProcedureCompilerTest extends \PHPUnit_Framework_TestCase
         $request = $this->getRequest();
         $request->setUrl('http://test.com');
 
-        $renderer = $this->getMock('\JonnyW\PhantomJs\Template\TemplateRendererInterface');
+        $renderer = $this->createMock('\JonnyW\PhantomJs\Template\TemplateRendererInterface');
         $renderer->expects($this->exactly(1))
             ->method('render')
             ->will($this->returnValue('var test=1; phantom.exit(1);'));
@@ -94,7 +94,7 @@ class ProcedureCompilerTest extends \PHPUnit_Framework_TestCase
         $request = $this->getRequest();
         $request->setUrl('http://test.com');
 
-        $renderer = $this->getMock('\JonnyW\PhantomJs\Template\TemplateRendererInterface');
+        $renderer = $this->createMock('\JonnyW\PhantomJs\Template\TemplateRendererInterface');
         $renderer->expects($this->exactly(2))
             ->method('render')
             ->will($this->returnValue('var test=1; phantom.exit(1);'));
@@ -127,7 +127,7 @@ class ProcedureCompilerTest extends \PHPUnit_Framework_TestCase
         $request = $this->getRequest();
         $request->setUrl('http://test.com');
 
-        $renderer = $this->getMock('\JonnyW\PhantomJs\Template\TemplateRendererInterface');
+        $renderer = $this->createMock('\JonnyW\PhantomJs\Template\TemplateRendererInterface');
         $renderer->expects($this->exactly(2))
             ->method('render')
             ->will($this->returnValue('var test=1; phantom.exit(1);'));

+ 4 - 4
src/JonnyW/PhantomJs/Tests/Unit/ClientTest.php

@@ -121,7 +121,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase
      */
     protected function getEngine()
     {
-        $engine = $this->getMock('\JonnyW\PhantomJs\Engine');
+        $engine = $this->createMock('\JonnyW\PhantomJs\Engine');
 
         return $engine;
     }
@@ -134,7 +134,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase
      */
     protected function getMessageFactory()
     {
-        $messageFactory = $this->getMock('\JonnyW\PhantomJs\Http\MessageFactoryInterface');
+        $messageFactory = $this->createMock('\JonnyW\PhantomJs\Http\MessageFactoryInterface');
 
         return $messageFactory;
     }
@@ -147,7 +147,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase
      */
     protected function getProcedureLoader()
     {
-        $procedureLoader = $this->getMock('\JonnyW\PhantomJs\Procedure\ProcedureLoaderInterface');
+        $procedureLoader = $this->createMock('\JonnyW\PhantomJs\Procedure\ProcedureLoaderInterface');
 
         return $procedureLoader;
     }
@@ -160,7 +160,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase
      */
     protected function getProcedureCompiler()
     {
-        $procedureCompiler = $this->getMock('\JonnyW\PhantomJs\Procedure\ProcedureCompilerInterface');
+        $procedureCompiler = $this->createMock('\JonnyW\PhantomJs\Procedure\ProcedureCompilerInterface');
 
         return $procedureCompiler;
     }

+ 2 - 2
src/JonnyW/PhantomJs/Tests/Unit/Procedure/ChainProcedureLoaderTest.php

@@ -153,7 +153,7 @@ class ChainProcedureLoaderTest extends \PHPUnit_Framework_TestCase
      */
     protected function getProcedureLoader()
     {
-        $procedureLoader = $this->getMock('\JonnyW\PhantomJs\Procedure\ProcedureLoaderInterface');
+        $procedureLoader = $this->createMock('\JonnyW\PhantomJs\Procedure\ProcedureLoaderInterface');
 
         return $procedureLoader;
     }
@@ -166,7 +166,7 @@ class ChainProcedureLoaderTest extends \PHPUnit_Framework_TestCase
      */
     protected function getProcedure()
     {
-        $procedure = $this->getMock('\JonnyW\PhantomJs\Procedure\ProcedureInterface');
+        $procedure = $this->createMock('\JonnyW\PhantomJs\Procedure\ProcedureInterface');
 
         return $procedure;
     }

+ 1 - 1
src/JonnyW/PhantomJs/Tests/Unit/Procedure/ProcedureLoaderFactoryTest.php

@@ -93,7 +93,7 @@ class ProcedureLoaderFactoryTest extends \PHPUnit_Framework_TestCase
      */
     protected function getProcedureFactory()
     {
-        $procedureFactory = $this->getMock('\JonnyW\PhantomJs\Procedure\ProcedureFactoryInterface');
+        $procedureFactory = $this->createMock('\JonnyW\PhantomJs\Procedure\ProcedureFactoryInterface');
 
         return $procedureFactory;
     }

+ 1 - 1
src/JonnyW/PhantomJs/Tests/Unit/Procedure/ProcedureLoaderTest.php

@@ -268,7 +268,7 @@ class ProcedureLoaderTest extends \PHPUnit_Framework_TestCase
      */
     protected function getFileLocator()
     {
-        $fileLocator = $this->getMock('\Symfony\Component\Config\FileLocatorInterface');
+        $fileLocator = $this->createMock('\Symfony\Component\Config\FileLocatorInterface');
 
         return $fileLocator;
     }

+ 1 - 1
src/JonnyW/PhantomJs/Tests/Unit/Procedure/ProcedureTest.php

@@ -232,7 +232,7 @@ class ProcedureTest extends \PHPUnit_Framework_TestCase
      */
     protected function getEngine()
     {
-        $engine = $this->getMock('\JonnyW\PhantomJs\Engine');
+        $engine = $this->createMock('\JonnyW\PhantomJs\Engine');
 
         return $engine;
     }