[mod] Conditional Placeholder / Attribute Display

3rd party code for phpList

[mod] Conditional Placeholder / Attribute Display

Postby themancan » 9:34pm, Wed 08 Aug, 2007

Problem: Client wants an email to use "Dear [FIRST NAME]," if the first name exists, but "Greetings!" if first name doesn't exist. Unless I've totally missed something, phpList doesn't do this.

Solution: Hack admin/sendemaillib.php like this:
Code: Select all
    foreach ($user_att_values as $att_name => $att_value) {
     
      // HACK
      if ((strtoupper($att_name) == 'FIRST NAME') && $att_value == '') {
        $att_value = 'Greetings!';
      } else {
        $att_value = 'Dear ' . $att_value . ',';
      }
      // HACK END
     
      if (eregi("\[".$att_name."\]",$htmlmessage,$regs)) {


Definitely not the most flexible of solutions, as it'd replace *all* instances of First Name (even when undesirable), but it could probably be modified to allow some syntax like [First Name:ifempty=`Greetings!`:else=`Dear {First Name},`] or something (to borrow from MODx's PHx syntax).

Or you could create a custom [GREETING] placeholder... anyway, this works for what we needed so I thought I'd share.

Hopefully this helps somebody.
themancan
phpList newbie
 
Posts: 1
Joined: 9:08pm, Wed 08 Aug, 2007

Postby flug » 1:19am, Mon 01 Oct, 2007

FWIW I've adopted a solution to this problem, of using this salutation:

[FIRST NAME]-


If the first name is in the database, then the salutation looks like:

Henry-


If no first name, then there is just a dash at the very top of their email, which they will probably ignore:

-

Not the best solution, but easy & works OK.
flug
PL Nut
 
Posts: 25
Joined: 12:17am, Mon 28 Aug, 2006

Postby flug » 6:57am, Mon 01 Oct, 2007

On a little bit more thinking I came up with this little mod that seems to work quite well--something really useful and missing in PHPlist so far.

This mod allows you to include one type of text for use when a certain attribute exists for a certain user, and an alternative text to use if that attribute doesn't exist.

So you can do things like:

Dear Jane, [First Name Jane in database]
Dear Harold, [First Name Harold in database]
Greetings! [for the person with no First Name in the database]

The syntax works like this:

Code: Select all
{CONDITIONAL|[FIRST NAME]|Dear [FIRST NAME],|Greetings!}


This includes "Dear [FIRST NAME]," if [FIRST NAME] exists or "Greetings!" otherwise. Note use of the {} to set off the entire conditional statement and the | character to separate the attribute, the text to use if the attribute exists, and the text to use if it does not exist.

Sample PHPlist message:
Code: Select all
{CONDITIONAL|[FIRST NAME]|Dear [FIRST NAME],|Good morning, O anonymous one,}

I am so pleased to be writing you today, {CONDITIONAL|[FIRST NAME]|[FIRST NAME]|O Thou Person Whose Name I Do Not Know}.

Your last name is {CONDITIONAL|[LAST NAME]|[LAST NAME]|something I do not know}.

Your middle name is {CONDITIONAL|[MIDDLE NAME]|[MIDDLE NAME]|a complete mystery}.
{CONDITIONAL|[ADDRESS1]||
We do not know your address and it is very important that you email us with that information today!

If we don't know your address we can't send you the $1 million check that is waiting for you here at our office. because we can scarcely email it to [EMAIL]!!!!!!!
}

[IMPORTANT! Note that the above example will work only if you have attributes named FIRST NAME, LAST NAME, MIDDLE NAME, and ADDRESS1 in your PHPlist installation. Those examples are attributes I have in my PHPlist system, but your attribute names will most likely be different.]

As in the last example, you can completely omit certain text if a certain attribute is present, or omit it if the attribute is absent.

You can also include attributes within any part of the text (the text to include if that attribute is present, or the text to include if it is absent).

In short, you can tailor your message much more the way you can when doing mail merge in a word processor.

To make this mod find sendemaillib.php. Make a backup of it.

About line 346 of sendemaillib.php find these lines,

Code: Select all
      $destinationemail = '';
 
  if (is_array($user_att_values)) {

    foreach ($user_att_values as $att_name => $att_value) {



Replace those lines with this:
Code: Select all
      $destinationemail = '';



  //bhugh, do the "CONDITIONAL" substitution thing for messages, 9-30-2007
  //Works like this, in email body:
  //{CONDITIONAL Dear [FIRST NAME]|Greetings!} includes "Dear [FIRST NAME]," if [FIRST NAME] exists
  //or "Greetings!" otherwise
  //Works for any attribute name, upper case, in brackets [LAST NAME], [ZIP], etc.

    //upcase the keys here because the format within email messages is the [UPPER CASE]
    $user_att_values_upper=array_change_key_case($user_att_values, CASE_UPPER);

    //do conditional substitution for HTML message:
    if (preg_match_all ('/\{CONDITIONAL\|\[(.*?)\]\|(.*?)\|(.*?)\}/si',
           $htmlmessage,$matches, PREG_SET_ORDER))
    {
      foreach ($matches as $regs) {
        $conditional=""; # if the attribute isn't found or there are no attributes we will still just erase the matching conditional statement
        if (is_array($user_att_values_upper)) {
          if (  array_key_exists( $regs[1], $user_att_values_upper )) { 
             $att_value=$user_att_values_upper["$regs[1]"];

           if ($att_value<>"") {
              //note: no need to replace [ATTRIBUTE] placeholders here, it will be done later
              $conditional=$regs[2];
           } else {
              $conditional=$regs[3];
           }
         }
        }
        //now substitute the conditional expression into the message (or erase it if no matching attributes found)
        $htmlmessage = str_replace($regs[0] , $conditional, $htmlmessage);
      }
    }

    //now do conditional substitution for TEXT message:
    if (preg_match_all ('/\{CONDITIONAL\|\[(.*?)\]\|(.*?)\|(.*?)\}/si',
           $textmessage,$matches, PREG_SET_ORDER))
    {
      foreach ($matches as $regs) {
        $conditional=""; # if the attribute isn't found or there are no attributes we will still just erase the matching conditional statement
        if (is_array($user_att_values_upper)) {
          if (  array_key_exists( $regs[1], $user_att_values_upper )) { 
             $att_value=$user_att_values_upper["$regs[1]"];

           if ($att_value</note> $att_value) {


This works with PHPlist ver 2.10.2 but probably also all the other 2.10.x and 2.11.x versions.

I haven't tested it very extensively yet.

[Note--this is the 2nd version of the code. The 2nd version improved performance substantially over the 1st version, added a couple helpful nuances, and changed the syntax a bit.]
flug
PL Nut
 
Posts: 25
Joined: 12:17am, Mon 28 Aug, 2006

Postby chrisirmo » 9:04pm, Mon 08 Oct, 2007

flug, this looks like it'll be a great addition. I've tried adding it into my installation of 2.10.5 but when I process the queue it hangs and never sends the emails. Any idea if something might have changed from 2.10.2 to 2.10.5 that might cause that to happen? Is the "</note>" in the last line supposed to be there? I don't think I've never seen that in PHP before, but I'm far from an expert.
chrisirmo
phpList newbie
 
Posts: 4
Joined: 3:46pm, Tue 01 Aug, 2006

Postby christiansees » 11:39pm, Fri 14 Dec, 2007

I have to agree with Chrisirmo. The code posted looks incomplete. For example for the text email message string replacement to work seems that there should be a code block like this
Code: Select all
if ($att_value<>"") {
              //note: no need to replace [ATTRIBUTE] placeholders here, it will be done later
              $conditional=$regs[2];
           } else {
              $conditional=$regs[3];
           }
         }
        }
        //now substitute the conditional expression into the message (or erase it if no matching attributes found)
        $textmessage = str_replace($regs[0] , $conditional, $textmessage);
      }
    }

to correspond to the html message string replace code block
Code: Select all
if ($att_value<>"") {
              //note: no need to replace [ATTRIBUTE] placeholders here, it will be done later
              $conditional=$regs[2];
           } else {
              $conditional=$regs[3];
           }
         }
        }
        //now substitute the conditional expression into the message (or erase it if no matching attributes found)
        $htmlmessage = str_replace($regs[0] , $conditional, $htmlmessage);
      }
    }

It would be nice if the original author or flug could post an update to this topic to confirm or deny this rumor.
christiansees
phpLister
 
Posts: 5
Joined: 9:57pm, Tue 23 Aug, 2005

Conditional Placeholders Code Hack - If data exists, _, else

Postby alloallo » 12:42am, Mon 09 Jun, 2008

Has no one made flug's code work since flug made it work with 2.10.2?

Why was this not incorporated into phplist so that as phplist changed this feature grew with it?

Is there a way to contact flug or other experts about this issue?

I had the same experience as chrisirmo

chrisirmo wrote: I've tried adding it into my installation of 2.10.5 but when I process the queue it hangs and never sends the emails. Any idea if something might have changed from 2.10.2 to 2.10.5 that might cause that to happen? Is the "</note>" in the last line supposed to be there?


Does anyone know if christiansees' is right regarding the need for a text email message string replacement like the html email message string replacement? If so, how does it fit together with flug's original? (Where do I put it?)
alloallo
PL Nut
 
Posts: 42
Joined: 3:59am, Fri 30 May, 2008
Location: Toronto

Postby bzcoder » 6:43pm, Mon 09 Jun, 2008

Possible solution would be to create a new field, for example call it "GREETING".

Than use PHPMyAdmin to update that field to "Greetings.", than a second update to change it to "Dear Firstname"

Than use GREETING instead of conditional replacement logic.
bzcoder
PL Geek
 
Posts: 53
Joined: 8:15pm, Mon 14 Apr, 2008

not isblank - does phplist understand?

Postby alloallo » 11:04am, Thu 12 Jun, 2008

bzcoder, are you suggesting that I send "Greetings!" using the criterion "FirstName=blank", and then "Dear [FirstName]," using the criterion "FirstName=Notblank"?

But textline fields can't be used as criteria
AND
As far as I know, phplist doesn't understand the logic of "is-blank", and nor does it understand the logic of "not".

Am I mistaken?

Thanks,
Jonathon
alloallo
PL Nut
 
Posts: 42
Joined: 3:59am, Fri 30 May, 2008
Location: Toronto

This is still a problem.

Postby alloallo » 6:16pm, Tue 24 Jun, 2008

Is anyone working on this issue?
Should I add it to the issue tracker / feature suggestion tracker?
alloallo
PL Nut
 
Posts: 42
Joined: 3:59am, Fri 30 May, 2008
Location: Toronto

Postby pd » 8:00am, Fri 18 Jul, 2008

This one is really urgent for me as well.

I need to translate a newsletter to German and French. Both of these languages have cases. For example:

Sehr geehrter Herr
Sehr geehrte Frau

and

Cher Monsieur
Chère Madame

So I am dependend on the value of the ***SPAM***. Now this wouldn't be a problem at all if I was able to do one of the above options you have already discussed,

or if I was able to change my form values:

***SPAM***:
Code: Select all
<select>
  &lt;option value="geehrter Herr">Herr</option>
  &lt;option value="geehrte Frau">Frau</option>
</select>


Note: I exchanged the < for an &-symbol because otherwise it doesn't show my option-value...

Since this isn't an option either though I really vote for conditional parameters in the mail, since this can be handy in many other situations as well.

Gr,
Paul[/code]
pd
phpLister
 
Posts: 14
Joined: 3:19pm, Tue 03 Jun, 2008

Rewrote conditional statements script

Postby pd » 10:23am, Fri 18 Jul, 2008

Hi people,

Because I needed a little bit more and I needed it right now I decided to rewrite the above script.

I also cleaned up the code and extended the comments for feature reference.
I also added some TODO's, so anyone: be welcome to extend.

I think my comments will speak for themselves. Any questions or comments are welcome ofcourse.

Please note that I left the portion of the original code just like it was. So

Code: Select all
// -- X marks the spot

$destinationemail = '';
 
  if (is_array($user_att_values)) {

    foreach ($user_att_values as $att_name => $att_value) {


is kept unmodified. Instead all you do is put the following code in the place of the above "// -- X marks the spot"

Code: Select all
//-- START of Conditional Statements modification --

  /**
   * @since 2007/09/30
   * @version 2008/07/18
   * @author flug @ forums.phplist.com
   * @author pd @ forums.phplist.com
   * @link http://forums.phplist.com/viewtopic.php?t=11225
   * @todo several characters -like {} and |- should be able to be escaped like \} and \{ and \|
   * @todo maybe it should be possible as well to put several conditions in one conditional statement
   *       although this might be a little bit to much as well...
   *
   * Example 1:
   * {CONDITIONAL|[FIRST NAME]|Dear [FIRST NAME],|Greetings!}
   *
   * This checks whether attribute "first name" in the database is filled.
   * If yes: then print "Dear [FIRST NAME]," (ie. Dear Paul,)
   * If no: then print "Greetings!"
   *
   *
   * Example 2:
   * Sehr {CONDITIONAL|[***SPAM***=male]|geehrter Herr|geehrte Frau} [FIRST NAME],
   *
   * This checks whether attribute "***SPAM***" in the database matches the value behind the equals-sign (=)
   * If yes: then print "geehrter Herr", otherwise print "geehrte Frau"
   *
   *
   * Example 3:
   * Sehr {CONDITIONAL|[FIRST NAME=Paul]|We all love you [FIRST NAME]!|I don't like you ;)} [FIRST NAME],
   *
   * This checks whether attribute "first name" in the database matches the value behind the equals-sign (=)
   * If yes: then print "We all love you Paul!", otherwise print "I don't like you ;)"
   *
   */

  //upcase the keys here because the format within email messages is the [UPPER CASE]
  $user_att_values_upper=array_change_key_case($user_att_values, CASE_UPPER);
  $condition_regex = '/\{CONDITIONAL\|\[(.*?)\]\|(.*?)\|(.*?)\}/si';

  /**
   * We want to modify both the htmlmessage and the textmessage
   * We want to do that that by using the same code for both, but without using a function
   * The easiest way to do that is by putting both variables in an array by reference and loop through
   * that array.
   */
  $changemessages = Array(&$htmlmessage, &$textmessage);

  for ($i=0; $i<count($changemessages); $i++) {
      //do conditional substitution for HTML message:
      if (preg_match_all ($condition_regex,
             $changemessages[$i],$matches, PREG_SET_ORDER))
      {
        foreach ($matches as $regs) {
         
          $conditional=""; # if the attribute isn't found or there are no attributes we will still just erase the matching conditional statement
          if (is_array($user_att_values_upper)) {
           
            $check_conditional_value = ( strpos('=', $regs[1])===false ? false : true );
            list($field_name,$match_conditional_value) = explode('=', $regs[1], 2);
           
            if (  array_key_exists( $field_name, $user_att_values_upper )) {
               $att_value=$user_att_values_upper[ $field_name ];
   
              /**
               * When there is no conditional value given (so there is no equals-sign)
               *  we want to check whether the $att_value is not empty
               * 
               * Otherwise we want the $att_value to match our conditional value
               */
              if ( (!$check_conditional_value && $att_value<>"") || ($check_conditional_value && $att_value==$match_conditional_value) ) {
                //note: no need to replace [ATTRIBUTE] placeholders here, it will be done later
                $conditional=$regs[2];
              } else {
                $conditional=$regs[3];
              }
           }
          }
          //now substitute the conditional expression into the message (or erase it if no matching attributes found)
          $changemessages[$i] = str_replace($regs[0] , $conditional, $changemessages[$i]);
        }
      }
  }
 
  /**
   * A little cleanup
   */
  unset($changemessages, $check_conditional_value, $field_name, $match_conditional_value, $condition_regex,
        $matches, $regs, $conditional);
 
  //-- END of Conditional Statements modification --


Gr,
Paul
pd
phpLister
 
Posts: 14
Joined: 3:19pm, Tue 03 Jun, 2008

Re: Rewrote conditional statements script

Postby Guest » 8:59am, Mon 17 Nov, 2008

pd wrote:
Code: Select all
   * Example 2:
   * Sehr {CONDITIONAL|[***SPAM***=male]|geehrter Herr|geehrte Frau} [FIRST NAME],
   *
   * This checks whether attribute "***SPAM***" in the database matches the value behind the equals-sign (=)
   * If yes: then print "geehrter Herr", otherwise print "geehrte Frau"




Hello, Paul,

Very cool MOD! Exactly what I was searching for.

But maybe you can help me. I like to use the conditional statements script as mentioned in Example 2. My "***SPAM***"-attribute is "ANREDE" and "male" is "Herr" but the rest is the same.

But ... no matter what value the attribute "ANREDE" will be (Herr or Frau) everytime the script writes the first conditional Text ("geehrter Herr").

Maybe you have an idea what went wrong?

Thank you and

kind regards from Vienna

Andreas.
Guest
 

Re: [mod] Conditional Placeholder / Attribute Display

Postby szlig » 2:50pm, Mon 03 Aug, 2009

Hi to vienna,

i know it's a little late, but maybe others have this problem, too. I had. Twice. And for me it helped, altering pd's code a little, so '$check_conditional_value' would be set properly (wich wasn't the case in my installation).

Replace the IF statemanet from line 56
Code: Select all
if (is_array($user_att_values_upper)) {
etc. to line 77 with this (changes marked with EDIT):

Code: Select all
if (is_array($user_att_values_upper)) {
            #$check_conditional_value = ( strpos('=', $regs[1])===false ? false : true );
            ###EDIT
            $cut=explode('=', $regs[1]);
            $cut=$cut[1];
            if ($cut!='') $check_conditional_value = true;
            else $check_conditional_value = false;
            ### /EDIT
            list($field_name,$match_conditional_value) = explode('=', $regs[1], 2);

            if (  array_key_exists( $field_name, $user_att_values_upper )) {
               $att_value=$user_att_values_upper[ $field_name ];

              /**
               * When there is no conditional value given (so there is no equals-sign)
               *  we want to check whether the $att_value is not empty
               *
               * Otherwise we want the $att_value to match our conditional value
               */

             ###EDIT
              if ( ($check_conditional_value==false && $att_value!="") || ($check_conditional_value==true && $att_value==$match_conditional_value)) {
              ### /EDIT
                //note: no need to replace [ATTRIBUTE] placeholders here, it will be done later
                $conditional=$regs[2];
              } else {
                $conditional=$regs[3];
              }
           }
          }


It worked fine here.
szlig
phpList newbie
 
Posts: 2
Joined: 2:33pm, Mon 03 Aug, 2009

Re: [mod] Conditional Placeholder / Attribute Display

Postby spiro » 12:50pm, Wed 07 Oct, 2009

Hi szlig,

I've just been testing this update to the above mod by flug and pd and whilst the conditional example, Sehr {CONDITIONAL|[S_EX=male]|geehrter Herr|geehrte Frau} now works, it only appears to work when a user is receiving a text version of the newsletter. If the recipient has opted to receive HTML then nothing regarding the conditional statement is shown.

Any ideas?

Kind regards
Spiro

<edit> NB: Remove underscore "_" at S_EX in above Conditional
As of July 2011
using the following on a shared Linux host:


PHPList: v2.10.14,FCKeditor: 2.6.3 (as distributed with phpList),PHP: 5.2.14,PHPMailer: ??,Apache: 2.2.11with OpenSSL enabled.
spiro
PL Geek
 
Posts: 50
Joined: 7:37pm, Thu 29 Jan, 2009

Re: [mod] Conditional Placeholder / Attribute Display

Postby AlasdairGF » 11:13am, Wed 23 Dec, 2009

I'm a bit of a php newbie & no hacker... but I can't make this work. I used pb's code above with szlig's edit, and had the following in an email:
Code: Select all
{CONDITIONAL|[Salutation]|Dear [Salutation],|Greetings!}

However, nothing was added to my emails, whether they were HTML or plain text and whether or not the Salutation field was empty or had a name in.

This should really be part of the basic functionality of PHPlist, surely? Has anyone had any luck with this, and can you tell me what you had to do to get it to work?

(running PHPlist 2.10.10 under PHP 5.2.11 w MySQL 5.0.81)

EDIT: Resolved, doh. Field name had to be in caps. Really, I despair of myself. Works fine for both HTML & plaintext emails.
AlasdairGF
phpList newbie
 
Posts: 4
Joined: 10:52pm, Sun 06 Sep, 2009

Next

Return to Contributions: Plug-ins, Add-ons, Mods

Who is online

Users browsing this forum: No registered users and 1 guest