Jump to content

increment variable with each hannacode occurence


froot
 Share

Recommended Posts

I'm trying to pass a variable from one hannacode occurence to the next.

hannacode: [[nextimage]]

if (isset($next)) : $next++; else: $next=0; endif;
$nextimage = $page->images->eq($next);
echo '<img title="'.$nextimage->title.'" alt="'.$nextimage->title.'" src="'.$nextimage->url.'"/>';

But everytime the hannacode runs, it's a different scope so to say.

Any ideas?

Link to comment
Share on other sites

Moderator note: this is not a module support thread, so I'm moving it to the General Support area of the forum instead. Please keep in mind that the Modules/Plugins area is only intended for module-specific support threads. Thanks!

Link to comment
Share on other sites

6 hours ago, fruid said:

I'm trying to pass a variable from one hannacode occurence to the next.

hannacode: [[nextimage]]


if (isset($next)) : $next++; else: $next=0; endif;
$nextimage = $page->images->eq($next);
echo '<img title="'.$nextimage->title.'" alt="'.$nextimage->title.'" src="'.$nextimage->url.'"/>';

But everytime the hannacode runs, it's a different scope so to say.

Any ideas?

Maybe saving it as a property of the page instance?

$page->hanna_counter = $page->hanna_count + 1

 

  • Like 2
Link to comment
Share on other sites

I tried, but no luck…

if (!$page->hanna_counter) : $page->hanna_counter = 0; echo 'nope';    
else : echo $page->hanna_counter; $page->hanna_counter = $page->hanna_counter + 1; echo 'yep';
endif;
$i = $page->hanna_counter;
$nextimage = $page->images->eq($i);
echo '<img title="'.$nextimage->title.'" alt="'.$nextimage->title.'" src="'.$nextimage->url.'"/>';

always echoes 'nope'

defining $page->hanna_counter on the template doesn't help either, nor does defining a addHookProperty if (!$i) : $i = 0; else: $i = $i++; and I think that's overkill, hannacode should be able to solve that independently…

Link to comment
Share on other sites

This is one of the rare cases where using global variables might be appropriate:

$currentImageIndex = $GLOBALS['current_image'] ?? 0;

// access the current image ...

$GLOBALS['current_image'] = ++$currentImageIndex;

Globals are accessible from everywhere and will stay available for the remainder of the current request.

  • Like 2
Link to comment
Share on other sites

Sure, here's your first example with a few adjustments and storing the current image index in a global variable:

// get current image index from global variable, or start with zero on the first iteration
$next = $GLOBALS['next_image'] ?? 0;

// get the image for the current index
$nextimage = $page->images->eq($next);

// only create output if the next image exists (i.e. not all have been output already)
if ($nextimage) {
    echo '<img title="'.$nextimage->title.'" alt="'.$nextimage->title.'" src="'.$nextimage->url.'"/>';
}

// increment the image index and store it for the next shortcode occurrence
$GLOBALS['next_image'] = ++$next;

 

  • Like 1
Link to comment
Share on other sites

This is not a direct answer on the current problem, but shows a different method for using a custom var in different scopes:

Instead of using a superglobal var it may also be possible to use ProcessWires Functions API with a custom var name.

// initialize a custom var, maybe in your site/_init.php
region('hannaCounter', 0);


// later in your templates or modules or where ever, count up the counter
region('hannaCounter', region('hannaCounter') + 1);


// and where ever you need it, get the current (or final) counter value 
echo region('hannaCounter');

 

  • Like 1
Link to comment
Share on other sites

Quote

Thanks, I like it, but HannaCode seems to not.

Syntax error, unexpected '?'

@fruid That error indicates that your PHP version doesn't support the null coalescing operator (??) which was introduced in PHP 7.0. Are you still using PHP 5.X? I would strongly recommend you upgrade to 7.3 or 7.4, the last 5.6 release has been end of life for over two years now! See the supported versions list on PHP.net.

In the meantime, you can use the ternary operator instead:

// get current image index from global variable, or start with zero on the first iteration
$next = isset($GLOBALS['next_image']) ? $GLOBALS['next_image'] : 0;

But again, please update to a supported PHP version ASAP.

  • Like 2
Link to comment
Share on other sites

5 minutes ago, fruid said:

I tried that too already, no luck…

That's very curious, the syntax is definitely correct. Two things that come to mind:

  • Maybe for some reason the compiled php file corresponding to the HannaCode has not been updated after changing the code (though I don't know how this could happen).
  • Maybe you have accidentally inserted a non-breaking space instead of a regular space? That can happen e.g. on a Mac when pressing option + space. In VS Code this extension helps with that: https://marketplace.visualstudio.com/items?itemName=wengerk.highlight-bad-chars#overview

Can you check the compiled PHP files in /site/assets/cache/HannaCode and see if you can spot anything unusual? Maybe post the entire code here ...

Link to comment
Share on other sites

the compiled file in said folder is pretty much identical to my hannacode (except for the first line)

Don't know how to check for let alone get rid of non breaking spaces, I do use mac though. 

<?php

if(!defined("PROCESSWIRE")) die("no direct access");

// get current image index from global variable, or start with zero on the first iteration
$next = $GLOBALS['next_image'] ?? 0;

// get the image for the current index
$nextimage = $page->images->eq($next);

// only create output if the next image exists (i.e. not all have been output already)
if ($nextimage) {
    echo '<p><img title="'.$nextimage->title.'" alt="'.$nextimage->title.'" src="'.$nextimage->url.'"/></p>';
}

// increment the image index and store it for the next shortcode occurrence
$GLOBALS['next_image'] = ++$next;

?>

EDIT: I also tried this…

if ($GLOBALS['next_image']) : $next = $GLOBALS['next_image']; else: $next = 0; endif;

but no luck, "undefined index 'next_image' in…"

Link to comment
Share on other sites

Ok, are you sure ProcessWire is using the correct version of PHP? Because if you get  Syntax error, unexpected '?' with the code above, the only other explanation I can think of is the null coalescing operator not being supported, which is only the case in PHP < 7.0 ... can you install Tracy Debugger and check the PHP Info Panel?

Quote

but no luck, "undefined index 'next_image' in…"

That's consistent at least, since $GLOBALS['next_image'] will not exist in the first iteration. You need to use isset($GLOBALS['next_image']) as in my example above, then the error will go away!

Link to comment
Share on other sites

I think Hanna Code is not a good candidate for solving this need. For a couple of reasons:

1. The Hanna Code textformatter does not necessarily only execute once when are outputting the field value in your template. It executes whenever the formatted value of the field is accessed. In practice I think you'll find this happens (or can happen) more than once in the same request (Ryan has pointed this out somewhere, and you can test it with Tracy Debugger) and so your counter incrementation is not going to be reliable.

2. You will be using the exact same tag [[nextimage]] multiple times within the field value. The Hanna Code textformatter uses a str_replace() to replace all matching tags in the field value. So it doesn't matter how you increment a counter within the Hanna tag code - all identical tags will get the same replacement value.

Instead I think you should use your own placeholder and then do your own replacement (either in a template file or in a custom textformatter module). Example...

In your field value, use the text {{nextimage}} inside a paragraph by itself. So the resulting markup would be <p>{{nextimage}}</p>.

In your template file you can use preg_replace_callback():

$body = $page->body;
$images = $page->images;

$pattern = '/<p>{{nextimage}}<\/p>/';
$count = 0;
$callback = function($matches) use (&$count, $images) {
	$out = '';
	$image = $images->eq($count);
	if($image) {
		$out = "<img src='$image->url' alt='$image->title' title='$image->title'>";
	}
	$count++;
	return $out;
};
$body = preg_replace_callback($pattern, $callback, $body);

 

  • Like 5
Link to comment
Share on other sites

not sure if I understand, I put this in my _init.php file (changed the variable names a bit to make sure they're unique) :

$pattern = '/{{nextimage}}/';
if (!isset($nextcount)) : $nextcount = 0; endif;
$images = $page->images;
$callback = function($matches) use ($nextcount, $images) {
    $out = '';
    $image = $images->eq($nextcount);
    if($image) {
        $out = "<img src='$image->url' alt='$image->title' title='$image->title'>";
    }
    $nextcount++;
    return $out;
};

and this in my template:

$body = preg_replace_callback($pattern, $callback, $page->body);

I don't know what $matches is supposed to be here, I haven't done much, if any, callback function coding so far.

The code replaces the image alright, but does not increment, all images are the first item (key 0) of the images-array.

Thanks for help

Link to comment
Share on other sites

Is HannaCode actually a sustainable module? I have been using TextformatterImageTags for this very purpose with a shortcode like {images:1}

This module however is discontinued and I feel like HannaCode is much closer to become a Core module plus it has a lot more applications. But I think I read, that it's not compatible with my PW version? (3.0.169). Is that a valid concern?

Link to comment
Share on other sites

4 hours ago, fruid said:

I don't know what $matches is supposed to be here

Check the documentation:

Quote

A callback that will be called and passed an array of matched elements in the subject string. The callback should return the replacement string. This is the callback signature:

handler ( array $matches ) : string

So it's an array of matched elements. But you don't need to do anything with it in your case - just return the replacement.

4 hours ago, fruid said:

The code replaces the image alright, but does not increment

You need to pass the variable that is holding the count by reference, as shown in my example.

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...