Forum How do I...?

How do I determine the number of pages in a generated PDF?

nalin1017
Is there a way (ideally using the Prince PHP class) to get the number of pages for a generated PDF? I'm trying to find a way to create documents that fit on one page. I know Prince has the ability to fit content by width, but I haven't found a way to also fit by height. So my hope was there was a get method for the Prince object to would tell me the number of pages of a PDF doc, and then in a loop I could incrementally decrease the text font-size until the resulting document is 1-page.

Is there anyway to do this? Ideally without the overhead of another lib to re-open the PDF and find out that way. Thanks for any help.
mikeday
You can capture the document page count with JavaScript and log it:
<script>
function logPageCount()
{
    Log.data("total-page-count", Prince.pageCount);
}

Prince.addEventListener("complete", logPageCount, false);
</script>

I've attached an updated Prince PHP wrapper below, which adds a $dats argument to the convert methods to capture this log data.
  1. prince.php26.5 kB
nalin1017
Thanks for the prompt response. I need to do this PDF generation server-side so not entirely sure this will work for us. Basically, I'm doing a nightly cron to generate a bunch of PDFs based on customer data in our system. Would I be able to, server-side only, find the page count in the newly created $dats argument. e.g.

$someXML = "hello world";
$output = $prince->convert_string_to_passthru($someXML, $msg, $dats);
echo $dats['pageCount']; // display pageCount

or something similar?
mikeday
Try dumping the $dats array, you should find that $dats[0][0] is "total-page-count" and $dats[0][1] is the value.
nalin1017
Doesn't that still require a Javascript invocation of the event listener and the call to the function to add total-page-count? That is to say, without some client side JS (this running thru a browser or some complex browser emulator setup), the total-page-count data would not be captured and accessible in the $dats array? Unless I'm missing something... Is there any simple mod you can make to the PHP library so a config can be set to add the event listener and capture the data purely from PHP?

Thanks again for all your help (and patience) Mike.
mikeday
Prince runs the JavaScript, not the browser.
nalin1017
Ahhh, so just put the script tag in the html string that is getting converted? Something like this?

<?php

require_once('prince.php');

$prince = new Prince('/usr/local/bin/prince');
if(!$prince) die("Prince instantiation failed");

$prince->setHTML(1);


$html = '
<!doctype html>

<html lang="en">
<head>
<script>
function logPageCount()
{
Log.data("total-page-count", Prince.pageCount);
}

Prince.addEventListener("complete", logPageCount, false);
</script>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
';
$errors = array();
$data = array();

if(!$prince->convert_string_to_passthru($html,$errors,$data)) {
echo "Failed:<br /><br />";
print_r($errors);
exit();
} else {
var_dump($data);
}

?>

* granted that code returns an empty array for data (and the pdf)...
mikeday
That was the idea, yes. Not sure why it did not return the page count, I will investigate.
nalin1017
thanks. it's creating the pdf, just not returning anything in the $dats var.
mikeday
Oops you will also need to call $prince->setJavascript(1); before performing the conversion, to enable JavaScript. This is an absolutely crucial detail which I completely forgot to mention. :D
nalin1017
Yep, that did it! Thanks for the help.
nalin1017
Following up with this, our printing company can't test print the outputted PDFs - their print software doesn't recognize them. I'm guessing I should try the various PDF profile options. I'm just a little confused from the forums on where this stands with the latest Prince code.

1) Should I be grabbing the alpha mentioned here: http://www.princexml.com/forum/topic/2410/how-does-the-profile-option-work for the most PDF compatibility options.

2) Should I be duplicating the modifications to the PDF wrapper a user made here http://www.princexml.com/forum/topic/2899/icc-profile-for-the-pdf to avoid losing the modifications you made to prince.php for me earlier in this thread? Though seems like his mods set --profile... I should change it to --pdf-profile?

3) Is there a complete list of profile settings supported in this alpha?

Thanks.
nalin1017
Also, when setting the file to the currently supported PDF/A-1b, and validate, I get the following:

Validating file for conformance level pdfa-1b
* The key F is required but missing.
* The document does not conform to the requested standard.
* The document contains hidden, invisible, non-viewable or non-printable annotations.

All that is gibberish to me... but wondering if there are other settings I need to consider. Also,my version isn't licensed yet. Just want to make sure this will all work for us before plunking down the cash. Is the prince watermark to blame?

mikeday
The watermark is to blame for the non-printable annotation warning. Not sure about the "key F" issue, any clue as to which object in the file it applies to?
nalin1017
Don't really know enough about the "key F" to know what object it would be. I've attached a PDF that doesn't open right and one that does. Our printer says their software mirrors (in terms of potential errors) this program:

http://markzware.com/flightcheck/free-markzware-flightcheck-demo/

which gives a 'File not recognized error' for: card_331_back1.pdf

but opens card_301_back1.pdf fine. very weird.

  1. card_301_back1.pdf249.2 kB
  2. card_331_back1.pdf216.3 kB
mikeday
If you open card_331_back1.pdf in a text editor it has a fragment of HTML at the beginning:
<br />
<b>Notice</b>:  Undefined index: rotate in <b>/var/www/vhosts/zwrw-2pgp.accessdomain.com/httpdocs/princetest.php</b> on line <b>23</b><br />
<br />
<b>Notice</b>:  Undefined index: color in <b>/var/www/vhosts/zwrw-2pgp.accessdomain.com/httpdocs/princetest.php</b> on line <b>28</b><br />

Edited by mikeday

nalin1017
Ahhh, duh. Thanks, you guys are the best.