Jump to content
fruid

increment variable with each hannacode occurence

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?

Share this post


Link to post
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!

Share this post


Link to post
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

Share this post


Link to post
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…

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

apologies, I'm a bit puzzled, what would that look like in my case? I learn so much from an example so I would very much appreciate the same advice in this very context.

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

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

Syntax error, unexpected '?'

and it doesn't work.

If that's getting too difficult, I might consider just adding an attribute by which you can manually specify the index.

Share this post


Link to post
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

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

I'm on 7.3.9

2 minutes ago, MoritzLost said:

$next = isset($GLOBALS['next_image']) ? $GLOBALS['next_image'] : 0;

 

I tried that too already, no luck…

Share this post


Link to post
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 ...

Share this post


Link to post
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…"

Share this post


Link to post
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!

Share this post


Link to post
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

Share this post


Link to post
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

Share this post


Link to post
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?

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

works perfectly. I still have to wrap my head around the preg_replace_callback and references though. Thanks!

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Greg Lumley
      Hi, this has me stumped, please help. 😳

      I'm using a field 'page_body' in a page-template as well as a blog-template. 
      HannaCodeDialogue is enabled for the field page_body.
      HannaCode works perfectly in Pages but not in Posts. 

      The dropdown is visible in the pages edit template but not in the posts edit template. 
      If I manually put the code into the Posts Template i.e. : [[YouTubeVideo videoName="my_vid"]] it simply displays the tag. 
      I'm quite sure this is a config error of some sort but for the life of me, I can't find it. 
       
      Thank you. 
       
      Greg. 
    • By msavard
      I have a situation where I have links to a bunch of forms on my site. Every year the links to the forms change slightly, adding the current year to the end. So it is something like http://www/somewhere.com/form1/2017. Next year it will be the same thing but with 2018 in the URL.
      I was hoping HannaCode could help me out here by letting me create a snippet that would read the year from a settings page and insert that at the end of any links I specify. So in the CKEditor I create a link, add [[cyr]] (my HannaCode snippet that pulls back the year from the settings page and I verified that it is indeed working properly) to the end and instead of pulling in the year it is just encoding the [[cyr]] into the URL. I was expecting
      http://www.somewhere.com/form1/2017  and I'm getting
      http://www.somewhere.com/form1/%5b%5bcyr%5d%5d .
      Is HannaCode not able to work with raw HTML this way? Is there some other way to do what I'm trying to accomplish? I really don't want to go around the site updating 100 links when a new year comes around.
      All the links are to forms on an external site in case that helps...
      Thanks.
    • By spacemonkey95
      Hi all,
      I've got a Table field on one of my pages. The first column requires the use of Hanna Code so I can add custom icons to the table cell. As per the settings for that particular field, I've set the textformatter option as TextformatterHannaCode (as the screenshot will show, for this particular field it's not possible to just select text formatters from a select dropdown. Instead I have to type in the value).
      Now, if I manually type in my HannaCode label (e.g. [[icons_copy]] )  then it will output correctly onto the page, but I need to also have the HannaCode selection menu which normally shows up in CKEditor when right-clicking in the textarea field. Does anyone know how I can achieve this? Do I need to apply a different setting in the Settings area as shown in the screenshot?
    • By Jonathan Lahijani
      Here's a little Hanna Code snippet I wrote that allows you to insert a tag that contains any HTML element of your choice along with any attributes.  The only defined Hanna Code variables are "element" and "comment".  If you leave element empty, it will automatically use the "div" HTML element.  The "comment" variable is optional and doesn't get outputted on the frontend.  It is only for internal use and if you want to actually describe what the Hanna Code is doing.
      Import these two into Hanna Code:
      "tag"
      !HannaCode:tag:eyJuYW1lIjoidGFnIiwidHlwZSI6IjIiLCJjb2RlIjoiXC8qaGNfYXR0clxuZWxlbWVudD1cImRpdlwiXG5jb21tZW50PVwiXCJcbmhjX2F0dHIqXC9cbjw/cGhwXG5cL1wvaWYoIGVtcHR5KCRhdHRyW1wiZWxlbWVudFwiXSkgKSByZXR1cm47XG4kcmV0dXJuID0gJzwnLiRhdHRyW1wiZWxlbWVudFwiXTtcbmZvcmVhY2goJGF0dHIgYXMgJGsgPT4gJGEpIHtcbiAgICBpZiggJGsgPT0gXCJlbGVtZW50XCIgfHwgJGsgPT0gXCJjb21tZW50XCIgKSBjb250aW51ZTtcbiAgICBpZiggIWVtcHR5KCRhKSApICRyZXR1cm4gLj0gJyAnLiRrLic9XCInLiRhLidcIic7XG59XG4kcmV0dXJuIC49ICc+JztcbmVjaG8gJHJldHVybjsifQ==/!HannaCode "end-tag"
      !HannaCode:end-tag:eyJuYW1lIjoiZW5kLXRhZyIsInR5cGUiOiIyIiwiY29kZSI6IlwvKmhjX2F0dHJcbmVsZW1lbnQ9XCJkaXZcIlxuaGNfYXR0cipcL1xuPD9waHBcblwvXC9pZiggZW1wdHkoJGF0dHJbXCJlbGVtZW50XCJdKSApIHJldHVybjtcbiRyZXR1cm4gPSAnPFwvJy4kYXR0cltcImVsZW1lbnRcIl0uJz4nO1xuZWNobyAkcmV0dXJuOyJ9/!HannaCode Now for some examples:
      Example 1: Section
      [[tag element="section"]] will output... <section> Example 2: Section with class
      [[tag element="section" class="myclass myotherclass"]] will output... <section class="myclass myotherclass"> Example 3: Section with id
      [[tag element="section" id="myid"]] will output... <section id="myid"> Example 4: Section with inline styles
      [[tag element="section" style="color:red"]] will output... <section style="color:red"> Example 5: Section with any attributes you want (data attributes for instance)
      [[tag element="section" my-custom-attribute="test-value" data-something="cool"]] will output... <section my-custom-attribute="test-value" data-something="cool"> Example 6: Same as above with "element" not defined (defaults to "div")
      [[tag my-custom-attribute="test-value" data-something="cool"]] will output... <div my-custom-attribute="test-value" data-something="cool"> Example 7: Same as above with "comment" set (which does not get outputted)
      [[tag my-custom-attribute="test-value" data-something="cool" comment="Don't remove this line or your page will get totally messed up!"]] will output... <div my-custom-attribute="test-value" data-something="cool"> Example 8: Close section tag
      [[end-tag element="section"]] will output... </section> Example 9: Close div tag
      [[end-tag]] will output... </div> Example with a common Bootstrap rows and columns scenario:
      [[tag class="row"]] [[tag class="col-sm-6"]] This is the first col. [[end-tag comment="end of first col"]] [[tag class="col-sm-6"]] This is the first col. [[end-tag comment="end of second col"]] [[end-tag comment="end of row"]] --
      Note the following article regarding the terms "element" and "tag": http://perfectionkills.com/tag-is-not-an-element-or-is-it/
    • By tsdtsdtsd
      Hi,
      the HannaCode snippets are currently stored in site/assets/cache/...
      I was wondering if this is the right place for them. Usually people tend to skip cache/* folders in backups and repositories (.gitignore etc). This could lead to serious data loss if one isn't aware of the fact where the snippets are stored.
      What do you think?
      Cheers
×
×
  • Create New...