FPDF AddLink not working - php

I am using fpdf AddLink function to create an internal link and at the end of all page generation I am using the below function to reorder the pages after that Links are not working. What could be the reason.Thanks
public function movePages($oldIndex, $nrPages, $newIndex) {
$newPages = array();
for($i=1; $i<=sizeof($this->pages); $i++) {
if($i < $newIndex) {
$newPages[$i] = $this->pages[$i];
} elseif($i < $newIndex+$nrPages) {
$newPages[$i] = $this->pages[$oldIndex+$i-$newIndex+1];
} else {
$newPages[$i] = $this->pages[$i-$nrPages];
}
$newPages[$i] = str_replace('{pageNr}', $i, $newPages[$i]);
}
$this->pages = $newPages;
}

Right.
Just ran into this myself. Found a solution.
When the page switching occurs, it appears that the text elements are stored in one kind of mapping scheme, while the visual elements are stored in another. When the page is switched, the text moves and the hotspots do not. They're still linked and work, but are hard to find now on their original page.
The trick I found that worked was to store the Abscissa co-ordinates and page number to link to in an array (hash indexed by the original page number), do the switching within a loop (manually setting the page number of $this->page for each link) and use $this->Link($x, $y, $w, $h, $link) to make the hotspot where I want it to and then $this->SetLink($link, 0, $pageNo) to set it to the right page.
Then reset the page count or it won't render properly.

Related

PHP return value after XML exploration

I got a PHP array with a lot of XML users-file URL :
$tab_users[0]=john.xml
$tab_users[1]=chris.xml
$tab_users[n...]=phil.xml
For each user a <zoom> tag is filled or not, depending if user filled it up or not:
john.xml = <zoom>Some content here</zoom>
chris.xml = <zoom/>
phil.xml = <zoom/>
I'm trying to explore the users datas and display the first filled <zoom> tag, but randomized: each time you reload the page the <div id="zoom"> content is different.
$rand=rand(0,$n); // $n is the number of users
$datas_zoom=zoom($n,$rand);
My PHP function
function zoom($n,$rand) {
global $tab_users;
$datas_user=new SimpleXMLElement($tab_users[$rand],null,true);
$tag=$datas_user->xpath('/user');
//if zoom found
if($tag[0]->zoom !='') {
$txt_zoom=$tag[0]->zoom;
}
... some other taff here
// no "zoom" value found
if ($txt_zoom =='') {
echo 'RAND='.$rand.' XML='.$tab_users[$rand].'<br />';
$datas_zoom=zoom($r,$n,$rand); } // random zoom fct again and again till...
}
else {
echo 'ZOOM='.$txt_zoom.'<br />';
return $txt_zoom; // we got it!
}
}
echo '<br />Return='.$datas_zoom;
The prob is: when by chance the first XML explored contains a "zoom" information the function returns it, but if not nothing returns... An exemple of results when the first one is by chance the good one:
// for RAND=0, XML=john.xml
ZOOM=Anything here
Return=Some content here // we're lucky
Unlucky:
RAND=1 XML=chris.xml
RAND=2 XML=phil.xml
// the for RAND=0 and XML=john.xml
ZOOM=Anything here
// content founded but Return is empty
Return=
What's wrong?
I suggest importing the values into a database table, generating a single local file or something like that. So that you don't have to open and parse all the XML files for each request.
Reading multiple files is a lot slower then reading a single file. And using a database even the random logic can be moved to SQL.
You're are currently using SimpleXML, but fetching a single value from an XML document is actually easier with DOM. SimpleXMLElement::xpath() only supports Xpath expression that return a node list, but DOMXpath::evaluate() can return the scalar value directly:
$document = new DOMDocument();
$document->load($xmlFile);
$xpath = new DOMXpath($document);
$zoomValue = $xpath->evaluate('string(//zoom[1])');
//zoom[1] will fetch the first zoom element node in a node list. Casting the list into a string will return the text content of the first node or an empty string if the list was empty (no node found).
For the sake of this example assume that you generated an XML like this
<zooms>
<zoom user="u1">z1</zoom>
<zoom user="u2">z2</zoom>
</zooms>
In this case you can use Xpath to fetch all zoom nodes and get a random node from the list.
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$zooms = $xpath->evaluate('//zoom');
$zoom = $zooms->item(mt_rand(0, $zooms->length - 1));
var_dump(
[
'user' => $zoom->getAttribute('user'),
'zoom' => $zoom->textContent
]
);
Your main issue is that you are not returning any value when there is no zoom found.
$datas_zoom=zoom($r,$n,$rand); // no return keyword here!
When you're using recursion, you usually want to "chain" return values on and on, till you find the one you need. $datas_zoom is not a global variable and it will not "leak out" outside of your function. Please read the php's variable scope documentation for more info.
Then again, you're calling zoom function with three arguments ($r,$n,$rand) while the function can only handle two ($n and $rand). Also the $r is undiefined, $n is not used at all and you are most likely trying to use the same $rand value again and again, which obviously cannot work.
Also note that there are too many closing braces in your code.
I think the best approach for your problem will be to shuffle the array and then to use it like FIFO without recursion (which should be slightly faster):
function zoom($tab_users) {
// shuffle an array once
shuffle($tab_users);
// init variable
$txt_zoom = null;
// repeat until zoom is found or there
// are no more elements in array
do {
$rand = array_pop($tab_users);
$datas_user = new SimpleXMLElement($rand, null, true);
$tag=$datas_user->xpath('/user');
//if zoom found
if($tag[0]->zoom !='') {
$txt_zoom=$tag[0]->zoom;
}
} while(!$txt_zoom && !empty($tab_users));
return $txt_zoom;
}
$datas_zoom = zoom($tab_users); // your zoom is here!
Please read more about php scopes, php functions and recursion.
There's no reason for recursion. A simple loop would do.
$datas_user=new SimpleXMLElement($tab_users[$rand],null,true);
$tag=$datas_user->xpath('/user');
$max = $tag->length;
while(true) {
$test_index = rand(0, $max);
if ($tag[$test_index]->zoom != "") {
break;
}
}
Of course, you might want to add a bit more logic to handle the case where NO zooms have text set, in which case the above would be an infinite loop.

divide xml into chunks based on url in php

I have a robots.txt file
in that i generate dynamic sitemap links.
I get the following links if i run the robots.txt file in the browser.
Here you get 5 sitemap links for each language.
Reason: there are 10 products in database.
i want to show only two products per link. so i divided the total no.of products with no.of products on one page.
Sitemap:http://demo.com/pub/sitemap_products.php?page=1&lang=it_IT
the part in bold is dynamic.
code in: sitemap_products.php
$Qproduct : returns an array of all the products in the db for all the languages.
So the bellow loop generates an xml having links of the products for the language in the sitemap url
for eg.
if the link is
Sitemap:http://demo.com/pub/sitemap_products.php?page=1&lang=it_IT
it will generate all the products present in IT language.
The xml links that are generated now are based on languages that we get from url.
but i want to divide them into chunks of 2 product's xml per sitemap link.
while($Qproduct->next())
{
if(!isset($page_language[$Qproduct->valueInt('language_id')]))
{
$page_language[$Qproduct->valueInt('language_id')] = mxp_get_page_language($MxpLanguage->getCode($Qproduct->valueInt('language_id')), 'products');
}
if($Qproduct->valueInt('language_id') == $QproductLang->valueInt('languages_id'))
{
$string_to_out .= '<url>
<loc>' . href_link($page_language[$Qproduct->valueInt('language_id')], $Qproduct->value('keyword'), 'NONSSL', false) . '</loc>
<changefreq>weekly</changefreq>
<priority>1</priority>
</url>';
}
}
what i wish to do is apply a condition so that it gives me exactly two products links in xml when page=1(see in the sitemap links) instead of all the 10 products link in xml.
similarly if page=2 it should display next 2 products. and so on.
I am a bit confused in the condition that i am supposed to apply.
Please help me out.
First of all, use an XML library to create the XML, not string concatenation. Example:
$loc = href_link($page_language[$Qproduct->valueInt('language_id')], $Qproduct->value('keyword'), 'NONSSL', false);
$url = new SimpleXMLElement('<url/>');
$url->loc = $loc;
$url->changefreq = 'weekly';
$url->priority = 1;
In your case, you can even easily wrap that into a function that just returns such an element and which has two parameters: $Qproduct and $page_language (as string, not array (!)).
But that's just some additional advice, because the main point you ask about is the looping and more specifically the filtering and navigating inside the loop to the elements you're interested in.
First of all you operate on all results by looping over them:
while ($Qproduct->next())
{
...
}
Then you say, that you're only interested in links of a specific language:
while ($Qproduct->next())
{
$condition = $Qproduct->valueInt('language_id') == $QproductLang->valueInt('languages_id');
if (!$condition) {
continue;
}
...
}
This already filters out all elements not interested in. What is left to keep track and decide which elements to take:
$page = 1;
$start = ($page - 1) * 2;
$end = $page * 2 - 1;
$count = 0;
while ($Qproduct->next())
{
$condition = $Qproduct->valueInt('language_id') == $QproductLang->valueInt('languages_id');
if (!$condition) {
continue;
}
$count++;
if ($count < $start) {
continue;
}
...
if ($count >= $end) {
break;
}
}
Alternatively, instead writing this all the time your own, create an Iterator for $Qproduct iteration and the use FilterIterator and LimitIterator for filtering and pagination.

Adding banner between SimplePie feed articles

My SimplePie install is a straight-up linux install. (no wordpress or anything)
I'm trying to add a banner in-between my feed articles. For instance if I have 10 feed articles displaying per page, I'd like to add one after the 5th one.
Any help is much appreciated... My feed page is very basic and visible here:
http://www.oil-gas-prices.com
In case you're unfamiliar with SimplePie code, here's basically a very similar code to what makes up the page above:
http://simplepie.org/wiki/setup/sample_page?rev=1341798869
To display how many articles I want on each page, I use:
// Set our paging values
$start = (isset($_GET['start']) && !empty($_GET['start'])) ? $_GET['start'] : 0; // Where do we start?
$length = (isset($_GET['length']) && !empty($_GET['length'])) ? $_GET['length'] : 10; // How many per page?
$max = $feed->get_item_quantity(); // Where do we end?
In your loop that outputs the articles, you can use a counter and the modulus operator:
$counter = 0;
foreach ($feed->get_items($start, $length) as $key=>$item) {
if ($counter % 5 == 0) { // use modulus operator
// display banner
}
// ...
$counter++;
}
See php modulus in a loop article. The code above will display the banner when $counter = 0, 5, 10, etc.

Create multiple links automatically with a loop in Dokuwiki?

I was trying to find a way to create multiple links automatically in Dokuwiki.
I tried enabling php and using the following code:
<php>
for ( $counter = 1; $counter <= 3; $counter += 1) {
echo "[[page$counter]]";
echo $counter;
}
</php>
I thought that the "echo" would work like in HTML and its output would be interpreted by Dokuwiki as its own command
(creating 3 links), but instead of that I just get the following text output (no links):
[[page1]]1[[page2]]2[[page3]]3
Any help on how to use a loop (not necessarily with PHP) in Dokuwiki to create multiple links?
THANKS!
You should put you loop in a syntax plugin.
For example: take the skeleton plugin, replace the render function by:
function render($mode, &$renderer, $data) {
for ( $counter = 1; $counter <= 3; $counter += 1) {
$renderer->internallink("page$counter", "title$counter");
}
return true;
}
After installing it, the tag "<TEST>" will be substituted by an invocation of your plugin.
For more info you might want to check:
The documentation
The nspages plugin which use a loop to add internal links

Drupal hook_views_post_execute not getting called

I'm trying to hook into the hook_views_post_execute event in Drupal 7, my module called foo is located in sites/default/modules/features/foo.
My foo.module file contains a definition for the hook_views_api function, defined like this:
function foo_views_api() {
return array("version" => 3.0);
}
This function gets called, but my implementation of the hook_views_post_execute does not, it's defined (in the same foo.module file) like this:
function foo_views_post_execute(&$view) {
$seen_rows = array();
$newResults = array();
for($i = 0; $i < count($view->result); ++$i) {
if (!in_array($view->result[$i]->nid, $seen_rows)) {
$newResults[] = $view->results[$i];
}
$seen_rows[] = $view->result[$i]->nid;
}
$view->result = $newResults;
}
I've been over the drupal API/hooks documentation, googled and read every blog post I've been able to find. I just can't get it to work. The hook does not get called. I'm assuming I've done something simple wrong since I'm not a drupal developer or PHP developer normally.
The view has probably been cached so it doesn't go through that function.
Go to the top left and clear the cache and you should see the result.

Categories