Show a particular page in PDF using DOMPDF - php

I am using DOMPDF to generate a PDF file from PHP. It works very good.
But now when I click on the link that generates the PDF I want it to take me to the fifth page of the PDF (if there's content on that page). Is there a way to do this?

According to the source code posted on this page, you can use the function Cpdf.openHere:
/**
* specify where the document should open when it first starts
*/
function openHere($style, $a = 0, $b = 0, $c = 0) {
// this function will open the document at a specified page, in a specified style
// the values for style, and the required paramters are:
// 'XYZ' left, top, zoom
// 'Fit'
// 'FitH' top
// 'FitV' left
// 'FitR' left,bottom,right
// 'FitB'
// 'FitBH' top
// 'FitBV' left
$this->numObj++;
$this->o_destination($this->numObj, 'new', array('page' => $this->currentPage, 'type' => $style, 'p1' => $a, 'p2' => $b, 'p3' => $c));
$id = $this->catalogId;
$this->o_catalog($id, 'openHere', $this->numObj);
}

Related

Randomly show image + link in html newsletter template

Let's say i have a list of 4 images and i'm trying to randomly show 2 of them each time the newsletter is loaded.
I have a file show_image.php with the following code:
$images = array(
0 => array(
'image' => 'http://example.com/img/partner1.jpg',
'link' => 'http://www.example1.com'
),
1 => array(
'image' => 'http://example.com/img/partner2.jpg',
'link' => 'http://www.example2.com'
),
2 => array(
'image' => 'http://example.com/img/partner3.jpg',
'link' => 'http://www.example3.com'
),
3 => array(
'image' => 'http://example.com/img/partner4.jpg',
'link' => 'http://www.example4.com'
)
);
$i = 0
foreach($images as $image)
{
$i++;
$zones[$i][] = $image;
if($i == 2)
$i = 0;
}
if(!empty($zones[$_GET['zone']]))
{
$zone = $zones[$_GET['zone']];
$random_index = array_rand($zone);
$partner = $zone[$random_index];
if($_GET['field'] == 'image')
{
$file = getFullPath($partner['image']);
$type = 'image/jpeg';
header('Content-Type:'.$type);
header('Content-Length: ' . filesize($file));
readfile($file);
}
elseif($_GET['field'] == 'link')
{
wp_redirect( $partner['link'], 301);
exit();
}
}
In my current situation, the images in the (html) newsletter template look like this:
<a href="http://example.com/show_image.php?zone=1&field=link">
<img src="http://example.com/show_image.php?zone=1&field=image">
</a>
<a href="http://example.com/show_image.php?zone=2&field=link">
<img src="http://example.com/show_image.php?zone=2&field=image">
</a>
As you can see, the call for a random image and link are separate, causing the php script to respond with a random link that doesn't match the random image.
Can anyone point me in the right direction how to randomly show an image with the right corresponding link?
First, there is a syntax error in your code. All your child arrays are missing a comma:
0 => array(
'image' => 'http://example.com/img/partner1.jpg' // <-- Error
'link' => 'http://www.example1.com'
)
Should be:
0 => array(
'image' => 'http://example.com/img/partner1.jpg', // <-- Fixed
'link' => 'http://www.example1.com'
)
You should use rand() to get an image randomly:
$images = array(
0 => array(
'image' => 'http://example.com/img/partner1.jpg',
'link' => 'http://www.example1.com'
),
1 => array(
'image' => 'http://example.com/img/partner2.jpg',
'link' => 'http://www.example2.com'
),
2 => array(
'image' => 'http://example.com/img/partner3.jpg',
'link' => 'http://www.example3.com'
),
3 => array(
'image' => 'http://example.com/img/partner4.jpg',
'link' => 'http://www.example4.com'
)
);
$total_images = count($images) - 1; // Get total number of images. Deducted one because arrays are zero-based
$random_img = rand(0, $total_images); // Get a random number between 0 and $total_images
echo $images[$random_img]['image'] . '<br />';
echo $images[$random_img]['link'] . '<br />';
there are could be multiple solutions, all of them have positive and negative sides:
Instead of static html file with hard-coded links, you can generate page on fly with php, so in this way you will generate random number for each zone and output html with proper links/images
1.1. You can use iframe to load image and link form php server
If you have to use static html and javascript, you can perform ajax call to php with javascript, which again will fetch image and link and use them to generate html code (document.write or innerHTML)
You can try to use cookies or session mechanism, in this case in php code you will have branch like if number for zone is not generated yet - generate and store in cookie/session; return link or image for number from cookies/session
To modify your code for #3 you need to replace
$random_index = array_rand($zone);
with something like (writing without actual php, so syntax errors are possible):
$cook = 'zone' . $_GET['zone'];
$random_index = isset($_COOKIE[$cook]) ? $_COOKIE[$cook] : array_rand($zone);
setcookie($cook, $random_index);
note - it is up to you to put proper validation for any variables from GET or COOKIE
In case of e-mail clients - majority of them restrict execution of javascript code and don't store cookies (and from user's perspective is it very good that they do that), anyway you can try something like that:
during e-mail sending generate unique id for each e-mail sent (you can use UUID for that)
include this id into links in your template, like <img src="http://.../?..&id=UUID">
in image and click handler - you need to get id from url and check in database - whether you assigned value to it and if no - generate and store in db
if value in db present - you can now serve appropriate image or redirect to appropriate url
but in this scheme - users always will be presented with the same image (though different users will see different ones), to fix that you can introduce some kind of expiration, ie put timestamp in db and invalidate (regenerate) value
note - some e-mail clients can force cache of images, ignoring http headers, thus such scheme will fail
other notes:
don't forget about no-cache http headers for serving image
don't use permanent redirects, only temporary ones for your use case
some e-mail clients will not load images which are not embedded into message, for such ones you can play with <noscript> and embedded images of some single randomly picked ad

DOMPDF - Get last y position of the pdf

Is it possible to get the y position of the last HTML element when rendering an HTML document to a PDF with Dompdf?
I need to insert an element after pdf rendering at the end of my document (fields for digital signature)...
EDIT :
As described in DOMPDF Github https://github.com/dompdf/dompdf/issues/1424 ,
you need to create a callback for the event 'end_frame' :
$dompdf = new Dompdf();
$dompdf->setCallbacks(
array(
'myCallbacks' => array(
'event' => 'end_frame', 'f' => function ($infos) {
$frame = $infos["frame"];
// elements positions
$GLOBALS["array_coord"][] = $frame->get_padding_box();
// last page number
$counter_frame = $frame->lookup_counter_frame('page');
$page_number = $counter_frame->counter_value('page');
}
)
)
);
and then after the rendering :
$dompdf->render();
// get the last y position in the PDF
$ligne_sign = sizeof($GLOBALS["array_coord"]) - 2;
$y = $GLOBALS["array_coord"][$ligne_sign]["y"];

mPDF: how to remove setHeader() & setFooter() borders

i have a mPDF report on my system and in the report, it has a header and footer where i use $mpdf->setHeader(); & $mpdf->setFooter(); to set the header and footer. but it displays a bottom border for header and top border for footer. can anyone help me how to remove this?
heres the image:
Here's my Code:
$mpdf=new mPDF('','LETTER-L','','',35,35,60,25,10,10);
//left margin, right margin, body, top margin,top margin,bottom margin,
/*HEADER Monthly Accomplishment Report*/
$mpdf->SetHeader('Sample');
/*FOOTER xMonthly Accomplishment Report*/
$mpdf->SetFooter('Sample');
//==============================================================
//=====================FILE DESCRIPTION=========================
//==============================================================
$mpdf->SetTitle('Monthly Accomplishment Report');
$mpdf->SetSubject('Report');
$mpdf->SetAuthor('sample');
$mpdf->Output('sample.pdf','I');
exit;
//==============================================================
//==============================================================
//==============================================================
You could use those two mpdf properties instead:
$mpdf->defaultheaderline = 0;
$mpdf->defaultfooterline = 0;
I had a look at the documentation of the method setHeader and found that exists a line parameter :
$line: specify whether to draw a line under the Header
You passed a string to the method but it also accept an array of options.
$line mentionned in the doc is not exactly a parameter of the method, rather a key of the configuration array.
So this code should accomplish what you look for, based on the documentation:
$mpdf = new mPDF('','LETTER-L','','',35,35,60,25,10,10);
$headerFooterContent = 'Sample';
$oddEvenConfiguration =
[
'L' => [ // L for Left part of the header
'content' => '',
],
'C' => [ // C for Center part of the header
'content' => '',
],
'R' => [
'content' => $headerFooterContent,
],
'line' => 0, // That's the relevant parameter
];
$headerFooterConfiguration = [
'odd' => $oddEvenConfiguration,
'even' => $oddEvenConfiguration
];
$mpdf->SetHeader($headerFooterConfiguration);
$mpdf->SetFooter($headerFooterConfiguration);
The setHeader and setFooter methods accept the same arguments (they are almost copy/pasted in the library).
I let you look further at the specific part of the examples related to complex header configuration of mPDF.
Let me know if it solves your issue.
Depending on the version of mpdf, you can use this:
$pdf->options['defaultheaderline'] = 0;
$pdf->options['defaultfooterline'] = 0;

How to rotate full page with tcpdf?

I am using TCPDF library to write a custom size label with background image and multiple text blocks on it.
The user when sees the preview on screen of the PDF it should show in horizontal, but for printing, I need the full page rotated -90 degrees.
How can I just rotate the whole page for printing version without having to move anything?
Basically:
In my case I've already had to use a new document format for the special sizes my document required.
So I've duplicated that format, created one for Landscape and one for Portrait.
Then based on the $preview variable, if previewing I'm rendering the normal landscape document, but if not previewing, I'm using the Portrait format and orientation and also starting the transformation and rotating everything on page.
Hope this helps someone I've found no other "quick" way to accomplish this kind of full-page rotation.
<?php
// #1 get the preview attribute from
// the form that was submitted from the user
$preview= isset($_POST['preview'])?(int)$_POST['preview']:0;
// load TCPDF for CodeIgniter as a library
$this->load->library('Pdf');
// #2 set default orientation and format
$orientation='L';
$format='MAKE-L';
// #3 if not previewing, switch orientation and format to portrait
if (!$preview) {
$orientation='P';
$format='MAKE-P';
}
// create new pdf object
// (same as doing new TCPDF(), it is just the CodeIgniter wrapper)
$pdf = new Pdf($orientation, 'mm', $format, true, 'UTF-8', false);
// remove default header/footer
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetMargins(0, 0, 0);
$pdf->AddPage($orientation, $format);
// #4 if not previewing, start transformation
// and rotate everything before inserting any content
if (!$preview) {
// Start Transformation
$pdf->StartTransform();
// Rotate counter-clockwise centered by (x,y)
$pdf->Rotate(-90, 70, 70); // <-- TODO: test this very well because 70 and 70 was just guessing, there is no math behind that so not sure if it will work always
}
// put your content here,
// for example set font and add a text
$pdf->SetFont('times', '', 7, '', true);
$pdf->writeHTMLCell(0, 0, 25.4, 2, 'lot number', 0, 1, 0, true, '', true);
/// end content
// #5 if not in preview mode, finish the transformation
if (!$preview) {
// Stop Transformation
$pdf->StopTransform();
}
$pdf->Output('example.pdf', 'I');
/**
* Last but very important note:
* I have added my formats in tcpdf/includes/tcpdf_static.php file.
* >> MAKE-L for Landscape
* >> MAKE-P for Portrait
*/
public static $page_formats = array(
// Make
'MAKE-L' => array( 396.850, 425.196), // = ( h 140 x w 150 ) mm
// Make
'MAKE-P' => array( 425.196, 396.850 ), // = ( h 140 x w 150 ) mm
// .. rest of formats here ../
);
The setPageFormat() method should do the job. You also can pass the parameter to the $format parameter of AddPage():
$pdf->AddPage($orientation, ['format' => $format, 'Rotate' => -90]);

SetSerieDescription - pChart not working

I'm trying to assign a label to the x axis of a Bar Chart, the label is a normal text string stored in an array under $gsettings['axisXlabel']. Unfortunatly pCharts SetSerieDescription doesn't seem to be working as expected.
Below is the function producing the graphs and an attachment of the current output. The part of interest is the 3 lines under /* Bind a data series to the X axis */
/**
* function to plot bar charts
*/
function cg_graphs_plot_bar_graph($gdata, $gsettings){
$graph_data = new pData();
if(isset($gdata['bar_plots2'])){ //if this is set, its a duel bar graph
$graph_data->addPoints($gdata['bar_plots'],"surgeondata");
$graph_data->addPoints(array(0,0,0,0),"surgeondatanull");
$graph_data->addPoints($gdata['bar_plots2'],"everyonedata");
$graph_data->addPoints(array(0,0,0,0),"everyonedatanull");
$graph_data->setSerieDrawable(array("everyonedatanull"), FALSE);
$graph_data->setSerieDescription("surgeondata",$gdata['surgeonname']);
$graph_data->setSerieDescription("everyonedata","All Surgeons");
$graph_data->setAxisUnit(0,"%");
$surgeon = array("R"=>21,"G"=>0,"B"=>0); //surgeon series colour
$all = array("R"=>191,"G"=>160,"B"=>36); //everyone series colour
$graph_data->setPalette("surgeondata",$surgeon);
$graph_data->setPalette("everyonedata",$all);
$graph_data->setPalette("surgeondatanull",$surgeon);
$graph_data->setPalette("everyonedatanull",$all);
} else {
$graph_data->addPoints($gdata['bar_plots'],"percentiles");
$graph_data->addPoints($gdata['surgeon_bar'],"surgeonbar");
$graph_data->setSerieDrawable(array("surgeonbar"), FALSE);
}
$graph_data->setAxisName(0,$gsettings['axisYlabel']);
/* Bind a data serie to the X axis */
$graph_data->addPoints($gdata['xaxis_names'],"Labels");
$graph_data->setSerieDescription("Labels",$gsettings['axisXlabel']);
$graph_data->setAbscissa("Labels");
$width=540;
$height=419;
$chart = new pImage($width,$height,$graph_data);
$chart->drawFromJPG(0,0,drupal_get_path('module', 'cg_graphs')."/images/graphbg.jpg");
/* Write the picture title */
$chart->setFontProperties(array("FontName"=>drupal_get_path('module', 'cg_graphs')."/pChart/fonts/ARIAL.TTF","FontSize"=>8));
$chart->setFontProperties(array("R"=>0,"G"=>0,"B"=>0));
$chart->drawText(270,70,$gsettings['title'],array("R"=>0,"G"=>0,"B"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE, "FontSize" => 12));
/* Set the graph area */
$chart->setGraphArea(70,120,490,310);
/* Draw a rectangle */
$chart->drawFilledRectangle(70,120,489,309,array("R"=>255,"G"=>255,"B"=>255,"Dash"=>FALSE, "BorderR"=>201,"BorderG"=>201,"BorderB"=>201));
/* Turn on shadow computing */
$chart->setShadow(TRUE,array("X"=>1,"Y"=>1,"R"=>0,"G"=>0,"B"=>0,"Alpha"=>20));
$format = array(
"DisplayValues"=>FALSE,
"DisplayColor"=>DISPLAY_AUTO,
"Rounded"=>FALSE,
"Gradient"=>TRUE,
"GradientAlpha"=>100,
"GradientMode"=>GRADIENT_EFFECT_CAN,
"GradientStartR"=>251,
"GradientStartG"=>220,
"GradientStartB"=>96,
"GradientEndR"=>191,
"GradientEndG"=>160,
"GradientEndtB"=>36
);
if(isset($gdata['bar_plots2'])){
/* Draw the scale */
$chart->drawScale(array("XMargin"=>50, "Mode"=>SCALE_MODE_MANUAL, "ManualScale"=> $gsettings['maxmin'], "Pos" => SCALE_POS_LEFTRIGHT,'DrawXLines' => FALSE, 'GridTicks' => 500,'GridR'=>0,'GridG'=>0,'GridB'=>0, 'LabelRotation'=>0, 'AroundZero' => TRUE, 'Interleave' => 0.1));
$graph_data->setSerieDrawable(array("surgeondata"), FALSE);
$graph_data->setSerieDrawable(array("surgeondatanull"), TRUE);
} else {
/* Draw the scale*/
$chart->drawScale(array("XMargin"=>40, "Mode"=>SCALE_MODE_MANUAL, "ManualScale"=> $gsettings['maxmin'], "Pos" => SCALE_POS_LEFTRIGHT,'DrawXLines' => FALSE, 'GridTicks' => 500,'GridR'=>0,'GridG'=>0,'GridB'=>0, 'LabelRotation'=>0, 'AroundZero' => TRUE));
}
$chart->drawBarChart($format);
//draw next bar with new colour.
$format = array(
"DisplayValues"=>FALSE,
"DisplayColor"=>DISPLAY_AUTO,
"Rounded"=>FALSE,
"Gradient"=>TRUE,
"GradientAlpha"=>100,
"GradientMode"=>GRADIENT_EFFECT_CAN,
"GradientStartR"=>255,
"GradientStartG"=>230,
"GradientStartB"=>126,
"GradientEndR"=>21,
"GradientEndG"=>0,
"GradientEndtB"=>0
);
if(!isset($gdata['bar_plots2'])){ //not set? we need to draw the second one.
//set draw series to false / true here
$graph_data->setSerieDrawable(array("percentiles"), FALSE);
$graph_data->setSerieDrawable(array("surgeonbar"), TRUE);
$chart->drawBarChart($format);
} else {
$graph_data->setSerieDrawable(array("surgeondatanull", "everyonedata"), FALSE);
$graph_data->setSerieDrawable(array("surgeondata", "everyonedatanull"), TRUE);
$chart->drawBarChart($format);
$graph_data->setSerieDrawable(array("everyonedatanull"), FALSE);
$graph_data->setSerieDrawable(array("everyonedata"), TRUE);
$chart->drawLegend(190,100,array("Style"=>LEGEND_NOBORDER, "Mode" => LEGEND_HORIZONTAL)); //draw legand
}
$imagename = str_replace(' ', '-', $gdata['surgeonname']);
$chart->render(drupal_get_path('module', 'cg_graphs')."/pChart/examples/pictures/".$imagename."-".$gsettings['name'].".png");
}
And here's the output, I want to label the Xaxis, currently the label isn't showing. (sorry for removed title etc, data isn't in the public domain yet and names needed removing)
You need to use the function setAbscissaName as defined in http://wiki.pchart.net/doc.dataset.setabscissaname.html
Example:
$MyData->setAbscissaName("Months");
This will display Months in the X axis under ticks.
The pChart documentation is a mess. I've found an error or two where the documentation differs from the source code. Their naming scheme also needs work. It's unintuitive to anyone besides the creator.
I believe you are trying to add a label to the X-Axis. In order to do this, you need to use setXAxisName().
The "Temperature" that appears in the code for setSerieDescription() is a string that is used to tie that set of series data to that name. It is not actually the label that appears on the chart (which is the same name). It is the name that is used again in setAbscissa().

Categories