Forums / General Questions / Use Of Notifiers - How To

Use Of Notifiers - How To

Sticky

Views: 80,912

Results 1 to 20 of 38
30 Mar 2006, 19:44
#1
milosh avatar

milosh

New Zenner

Join Date:
Nov 2004
Location:
Estonia
Posts:
33
Plugin Contributions:
0

Use Of Notifiers - How To

I have read the wiki tutorial and previous v1.3 anouncment posts in the forum and I understand the concept of notifieriers, but cannot get it working...

I presumed, that when I save a new class which has

$_SESSION['cart']->attach($this, array('NOTIFIER_CART_ADD_CART_END', 'NOTIFIER_CART_REMOVE_END'));

or similar in the class consturctor, then the observer class should implement the code and wake it up, when notified, but nothing... [Tried also with the original code in the wiki]

As far as I understand, the application_top does not read in the classes that are saved under includes/classes/observers catalog, so the class and its constructor that should attach notifier to praticular event is never called and observers array stays empty... Should aplication_top read in all observers that are saved into this folder or should I explicitly say somewhere, that these classes should be included, so the class constructors are waked and observers are added to observers array?

Debuging the code with breakpoint at class.base notify function indicates indeed that $this->observers array is empty in spite of the fact that I copied the observer code from the wiki API...

30 Mar 2006, 22:29
#2
wilt avatar

wilt

Oji-san

Join Date:
Jun 2003
Location:
Newcastle UK
Posts:
1,788
Plugin Contributions:
3

Re: Use Of Notifiers - How To

Hi,

The includes/classes/observers directory is not an autoload directory, so you will need to arrange for application_top.php to autlload the class.

lets assume you are using the freeProduct class example, and you have saved this in includes/classes/observers/class.freeProduct.php

You now need to arrange for this class to be loaded and instantiated.

To do this tou need to use tha application_top.php autoload system.

In includes/autoloaders xreate a file called config.freeProduct.php containing

<?php
 $autoLoadConfig[90][] = array('autoType'=>'class',
                'loadFile'=>'observers/class.freeProduct.php');
 $autoLoadConfig[90][] = array('autoType'=>'classInstantiate',
                'className'=>'freeProduct',
                'objectName'=>'freeProduct');
?>

Note: I chose 90 as the offset as the observer needs to attach to the $SESSION['cart'] class. This is instantiated at offset 80.

The free product class should now work as advertised :)

31 Mar 2006, 06:43
#3
milosh avatar

milosh

New Zenner

Join Date:
Nov 2004
Location:
Estonia
Posts:
33
Plugin Contributions:
0

Re: Use Of Notifiers - How To

Thank you! :)

I copied your reply into Wiki as well, see at between "Observe and Prosper" and "Real World examples" chapters.

02 Apr 2006, 20:34
#4
milosh avatar

milosh

New Zenner

Join Date:
Nov 2004
Location:
Estonia
Posts:
33
Plugin Contributions:
0

Re: Use Of Notifiers - How To

I am still learning it...

I got it working with the example above! However, when I just changed the notifier into NOTIFY_HEADER_START_CHECKOUT_CONFIRMATION or NOTIFY_HEADER_END_CHECKOUT_CONFIRMATION then the script cannot find the observing script anymore...

Debug'ign the code shows that the $this->observers array is empty, when the notifier returns from the checkout_process header, but the same array is filled when the notifier returns from chart (during the same debuging process :blink: ).

I presume that $_SESSION['cart'] is not the right place to attach the notifier in the case when I would like to be notified by checkout_confirmation header (I tried to play around with the autoload position), but what is then a right place?

Are there some tricks, how to load notifiers from different parts of the script?

03 Apr 2006, 19:57
#5
wilt avatar

wilt

Oji-san

Join Date:
Jun 2003
Location:
Newcastle UK
Posts:
1,788
Plugin Contributions:
3

Re: Use Of Notifiers - How To

**I copied your reply into Wiki as well, see at between "Observe and Prosper" and "Real World examples" chapters. **

::tup

On your other point.

the observer/notifier system is really written for a completely OOPs based application, as the observer expects to attach to a class that has notifiers within its methods. However a lot of the code within ZC is still procedural in nature and not contained withn a class.

To work around this, we added the 'stub' notifier class. So if you want ot create an observer for a notifier that lies within procedural code you should do something like

$zco_notifier->attach($this, array('NOTIFY_HEADER_END_CHECKOUT_CONFIRMATION'));

I seemed to have missed this from the docs :(

03 Apr 2006, 20:14
#6
milosh avatar

milosh

New Zenner

Join Date:
Nov 2004
Location:
Estonia
Posts:
33
Plugin Contributions:
0

Re: Use Of Notifiers - How To

Thanks!

I just discovered it out just few moments ago and -- "boom" -- found also your reply in the forums :)

The point, where I got stucked yesterday, was really silly: I actually tried to attach the notifier into $zco_notifier notifier class, but just forgot to add:

global $zco_notifier;

before the $zco_notifier->attach statement in my observer class...

02 May 2006, 22:30
#7
samtherobot avatar

samtherobot

New Zenner

Join Date:
Mar 2005
Location:
London, Ontario
Posts:
44
Plugin Contributions:
0

Re: Use Of Notifiers - How To

So quick question then. I've got the notifier working fine. Trying to write a plugin that will sync newsletter subscriptions with PHPlist. However what means are there for passing parameters? I need to find out whether the person signed up to the newsletter or not.

03 May 2006, 20:31
#8
wilt avatar

wilt

Oji-san

Join Date:
Jun 2003
Location:
Newcastle UK
Posts:
1,788
Plugin Contributions:
3

Re: Use Of Notifiers - How To

Hi,

There is no parameter passing at all.

variables are available in a number of ways.

If you are writing a notifier that attaches to a class, then the class is passed to the observer as $class, you can therefore query class variables as $class->class-variable.(note the above does not work for session based classes, like the cart, however you can reference these as normal as $_SESSION['cart'] etc.

You can accesss procedural code variables using the superglobal $GLOBALS array, and of course all normal superglobals e.g. $_SESSION, $_POST, $_GET are available as normal.

In your example you can access the $_SESSION['customer_id'] directly and then do a quick sql query to see if that customer is signed up to newsletters.

HTH

04 May 2006, 00:10
#9
samtherobot avatar

samtherobot

New Zenner

Join Date:
Mar 2005
Location:
London, Ontario
Posts:
44
Plugin Contributions:
0

Re: Use Of Notifiers - How To

Ok, I'm beggining to get the picture here.

Next challenge. I've written a class to modify the description before it is displayed. I've used the NOTIFY_MAIN_TEMPLATE_VARS_EXTRA_PRODUCT_INFO notifier to run my code after the database has been queried and before it is displayed.

I can get the description by using the GET variable products_id. However then how would I modify the variable products_description?

What I'm trying to do is parse through the description text looking for keywords I have in an array (from a glossary table). I want to make any matching terms into hyperlinks.

Related to this, I'm a little sketchy on how to tell the notifier is in a class or not. I'm assuming the class declaration should be in the same file as the notifier? ie NOTIFY_MAIN_TEMPLATE_VARS_EXTRA_PRODUCT_INFO is not in a class.

thanks, I'm liking this notifier system more and more! Any idea what phase will see all notifiers contained in classes?

22 Aug 2006, 22:55
#10
wdrwc avatar

wdrwc

New Zenner

Join Date:
Sep 2004
Posts:
13
Plugin Contributions:
0

Re: Use Of Notifiers - How To

I am trying to write the observer class attached to events during the checkout process. I need the session class with several variables storing values for session. But I can not properly initialize them and get them reinitialized several times during the checkout process. A a result I loose the values assigned to these variables on previous entry to the class. It looks like I do not understand how does the ONS work.

For test purposes I wrote a stupid testclass attached to the same events. But it does not work at all. I would appreciate if someone could advice what is wrong.

The file config.testclass.php in the includes/auto_loaders directory contains:

<?php
/*
 * instantiate class.testclass at 180 - when
 * everything is initialized
 * in <root>/includes/auto_loaders
 */

$autoLoadConfig[180][]= array('autoType' => 'class',
				'loadFile' => 'observers/class.testclass.php');

$autoLoadConfig[180][]= array('autoType' => 'classInstantiate',
				'className' => 'testclass',
				'objectName' => 'testClassObject',
        'checkInstantiated' => true,
        'classSession' => true );

?>

and class.testclass.php in includes/classes/observers looks like this:

<?php

class testclass extends base {
  var $initialized= false;
  var $field;
  /*constructor*/
  function testclass() {
    global $zco_notifier;

    $this->test_log($this->initialized ."\t=initialized at start constructor");
    $this->test_log($this->field ."\t=field at start constructor");
    $zco_notifier -> attach($this,
                            array('NOTIFY_HEADER_START_CHECKOUT_CONFIRMATION',
                                  'NOTIFY_HEADER_END_CHECKOUT_CONFIRMATION',
                                  /*'NOTIFY_HEADER_END_CHECKOUT_SUCCESS',*/
                                  'NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE_ADD_PRODUCTS',
                                  'NOTIFY_HEADER_START_ACCOUNT_HISTORY_INFO'));

    if( !($this->initialized) ) {
      $this->initialized= true;
      $this->field= -10;
    }
    $this->test_log($this->initialized ."\t=initialized at end constructor");
    $this->test_log($this->field ."\t=field at end constructor");
  }
  
  /* update method */
  function update(&$callingClass, $eventID, $paramsArray) {
    if($eventID == 'NOTIFY_HEADER_START_CHECKOUT_CONFIRMATION') {
      $this->test_log($this->initialized ."\t=initialized at start " .$eventID);
      $this->test_log($this->field ."\t=field at start " .$eventID);
      $this->field= 200;
      $this->test_log($this->initialized ."\t=initialized at end " .$eventID);
      $this->test_log($this->field ."\t=field at end " .$eventID);
    } else if($eventID == 'NOTIFY_HEADER_END_CHECKOUT_CONFIRMATION') {
      $this->test_log($this->initialized ."\t=initialized at start " .$eventID);
      $this->test_log($this->field ."\t=field at start " .$eventID);
      $this->field= 300;
      $this->test_log($this->initialized ."\t=initialized at end " .$eventID);
      $this->test_log($this->field ."\t=field at end " .$eventID);
    } else if($eventID == 'NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE_ADD_PRODUCTS') {
      $this->test_log($this->initialized ."\t=initialized at start " .$eventID);
      $this->test_log($this->field ."\t=field at start " .$eventID);
      $this->field= 400;
      $this->test_log($this->initialized ."\t=initialized at end " .$eventID);
      $this->test_log($this->field ."\t=field at end " .$eventID);
    } else if($eventID == 'NOTIFY_HEADER_START_ACCOUNT_HISTORY_INFO') {
      $this->test_log($this->initialized ."\t=initialized at start " .$eventID);
      $this->test_log($this->field ."\t=field at start " .$eventID);
      $this->field= 500;
      $this->test_log($this->initialized ."\t=initialized at end " .$eventID);
      $this->test_log($this->field ."\t=field at end " .$eventID);
    }
  }
  
  /* write debug */
  function test_log($message) {
    $flog= fopen("/tmp/zc_log.txt","a");
    fwrite($flog,$message ."\n");
    fclose($flog);
  }
} /* end testclass */
?>

As you can see the class only changes the value of the $this->field and writes simple trace to the file. But the written zc_log.txt file contains only the output from the constructor method. It seems the update method is never called. What is wrong here?

05 Dec 2006, 06:40
#11
sumit_pilankar avatar

sumit_pilankar

New Zenner

Join Date:
Dec 2006
Posts:
6
Plugin Contributions:
0

Re: Use Of Notifiers - How To

Hi all,

I need to add a product to the shopping cart when the user is visiting the site for the first time and a new shopping cart object is created. Can anyone please help me with the event i should attach to? I was trying to attach to event 'NOTIFIER_CART_INSTANTIATE_END' but it does not work at all.

Please help.

Thanks Sumit Pilankar

05 Apr 2007, 08:14
#12
sophwise_com avatar

sophwise_com

New Zenner

Join Date:
Apr 2006
Location:
Sunny California
Posts:
44
Plugin Contributions:
0

Re: Use Of Notifiers - How To

Howdy All,

Just a quick question regarding the procedural workaround code.

If the notification that I am watching for happens in /includes/modules/checkout_process.php

as

$zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE');

Is it right to assume that I need to implement my observer class with the procedural:

global $zco_notifier;
$zco_notifier->attach($this, array('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE'));

rather than the OOP version:

$this->attach($this, array('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE'));

I suppose I could just do a simple test to find out, but for the benefit of those reading, I'll go ahead and put it here in writing.

05 Apr 2007, 08:40
#13
swguy avatar

swguy

Administrator

Join Date:
Feb 2006
Location:
Tampa Bay, Florida
Posts:
10,649
Plugin Contributions:
214

Re: Use Of Notifiers - How To

The first form is correct. Use zco_notifier for procedural cases.

31 Jul 2007, 23:00
#14
stevekim avatar

stevekim

New Zenner

Join Date:
Apr 2007
Location:
Los Angeles, CA
Posts:
44
Plugin Contributions:
0

Re: Use Of Notifiers - How To

Hi!

I'm trying to generate a file with shipping & order detail using the notifiers (NOTIFY_CHECKOUT_PROCESS_AFTER_SEND_ORDER_EMAIL).

The problem is that I need certain values be also included in the output file such as order id, product details and shipping weight.

I think when the trigger calls for my notifier, it is attached to order.php class only and $order->variables works just fine (except $order->order_id).

But I'd definitely like $shipping_weight (all cart weight + tare or large_tare) and $order_id be included.

How do I pass variables from shipping.php class? And why wouldn't $order->order_id not working whereas $order->total_weight does?

01 Aug 2007, 04:53
#15
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,513
Plugin Contributions:
174

Re: Use Of Notifiers - How To

Without looking in great detail, I suspect you will need to "global" the $shipping_weight variable in order to use it in your notifier class.

Also global the $insert_id if you want the number of the current order.

01 Aug 2007, 17:14
#16
stevekim avatar

stevekim

New Zenner

Join Date:
Apr 2007
Location:
Los Angeles, CA
Posts:
44
Plugin Contributions:
0

Re: Use Of Notifiers - How To

DrByte:

Without looking in great detail, I suspect you will need to "global" the $shipping_weight variable in order to use it in your notifier class.

Also global the $insert_id if you want the number of the current order.

Thanks Dr. Byte!

'global'ling $insert_id worked. However, I still can't get the $shipping_weight to work, which I suspect that my observer is attached so well only to class order.php. Perhaps use a different notifier than NOTIFY_CHECKOUT_PROCESS_AFTER_SEND_ORDER_EMAIL?

Below is the code:

<?php
 class xml_generate extends base { 
   function xml_generate() {
     global $zco_notifier;
     $zco_notifier->attach($this, array('NOTIFY_CHECKOUT_PROCESS_AFTER_SEND_ORDER_EMAIL'));
   }
   function xml_config_switch() {
       if ( defined('GENERATE_XML') && (GENERATE_XML == 'false') ) {
          return false;
       } 
       return true;
   }
   function update(&$callingClass, $eventID) { 
       if (!$this->xml_config_switch()) return;
       global $order, $shipping_weight, $insert_id;
     //Begin USPS Domestic clause
     if (strpos($order->info['shipping_module_code'], 'usps') !== FALSE) {
     $xml_msg = "<DAZzle Layout='c:\endicia\dazzle7\Zebra Label.lyt' OutputFile='C:\endicia\dazzle7\xmlout\domestic" . strftime('%Y%b%d-%H%M%S') . ".xml' Start='PRINTING' Test='YES' Prompt='NO' AutoClose='NO'>" . "\r\n";
  $xml_msg .= "<Package ID='1'>\r\n";
  if (strpos($order->info['shipping_method'], 'Parcel') !== FALSE) {$xml_msg .= "<MailClass>PARCELPOST</MailClass>\r\n";}
  if (strpos($order->info['shipping_method'], 'First') !== FALSE) {$xml_msg .= "<MailClass>FIRST</MailClass>\r\n";}
  if (strpos($order->info['shipping_method'], 'Priority') !== FALSE) {$xml_msg .= "<MailClass>PRIORITY</MailClass>\r\n";}
  if (strpos($order->info['shipping_method'], 'Express') !== FALSE) {$xml_msg .= "<MailClass>EXPRESS</MailClass>\r\n";}
  $xml_msg .= "<DateAdvance>0</DateAdvance>\r\n";
  $xml_msg .= "<PackageType>NONRECTPARCEL</PackageType>\r\n";
  $xml_msg .= "<Oversize>FALSE</Oversize>\r\n";
  $xml_msg .= "<WeightOz>" . ($order->total_weight * 16) . "</WeightOz>\r\n"; //works without handling charge
  $xml_msg .= "<WeightOz>" . ($shipping->shipping_weight * 16) . "</WeightOz>\r\n"; //returns 0
  $xml_msg .= "<WeightOz>" . ($shipping_weight * 16) . "</WeightOz>\r\n";  //returns 0
  $xml_msg .= "<Services>CertifiedMail='OFF' DeliveryConfirmation='OFF' ></Services>\r\n";
  $xml_msg .= "<Value>" . $order->info['total'] . "</Value>\r\n";
  $xml_msg .= "<Description>" . $order->products_ordered . "</Description>\r\n";
  $xml_msg .= "<ReferenceID>" . $insert_id . "</ReferenceID>\r\n";
  $xml_msg .= "<ToName>" . $order->delivery['firstname'] . " " . $order->delivery['lastname'] . " - " . $order->delivery['company'] . "</ToName>\r\n";
  $xml_msg .= "<ToAddress1>" . $order->delivery['street_address'] . "</ToAddress1>\r\n";
  $xml_msg .= "<ToCity>" . $order->delivery['city'] . "</ToCity>\r\n";
  $xml_msg .= "<ToState>" . $order->delivery['state'] . "</ToState>\r\n";
  $xml_msg .= "<ToPostalCode>" . $order->delivery['postcode'] . "</ToPostalCode>\r\n";
  $xml_msg .= "<ToEMail>" . $order->customer['email_address'] . "</ToEMail>\r\n";
  $xml_msg .= "</Package>\r\n</DAZzle>\r\n";
  $OutFile = "includes/xml/usps/domestic" . strftime('%Y%b%d-%H%M%S') . ".xml"; //Setting path n file name to USPS domestic
  } //End if USPS Domestic clause
  
  //Generate XML File
  $fp = fopen($OutFile, 'a');
  $fout = fwrite( $fp , $xml_msg );
  fclose($fp);
   }
 }
?>

Notice I'm trying 3 possible weight (in oz)?

01 Aug 2007, 19:45
#17
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,513
Plugin Contributions:
174

Re: Use Of Notifiers - How To

$order->total_weight is likely your only option.

The $shipping_weight is only available in the shopping cart, which is empty after the order is placed.

Or you could write your own weight recalculator using the weight calculations in the calculate() function of the shopping_cart class.

02 Aug 2007, 02:32
#18
stevekim avatar

stevekim

New Zenner

Join Date:
Apr 2007
Location:
Los Angeles, CA
Posts:
44
Plugin Contributions:
0

Re: Use Of Notifiers - How To

DrByte:

$order->total_weight is likely your only option.

The $shipping_weight is only available in the shopping cart, which is empty after the order is placed.

Or you could write your own weight recalculator using the weight calculations in the calculate() function of the shopping_cart class.

Thanks Dr. Byte.

As I'm not much of a programmer, I'm just putting the static tare value matching what I've put on the configuration, unless there is a method of saving $weight in shopping_cart class to some other (global?) varible that does not get reset and passed onto my observer. Or should resetting of $weight commented out from shopping_cart class and be reset at the end of my observer?

07 Aug 2007, 02:45
#19
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,513
Plugin Contributions:
174

Re: Use Of Notifiers - How To

SteveKim:

a method of saving $weight in shopping_cart class to some other (global?) varible that does not get reset and passed onto my observer. Or should resetting of $weight commented out from shopping_cart class and be reset at the end of my observer?

Options: a. extend the order database table to also store the total weight as calculated by shopping cart, and then write code to ensure that info gets stored appropriately b. add a $_SESSION['shipping_weight'] variable before the shopping cart is reset, and then refer to that during your observer activities c. alter the order-total class to store the weight in the shipping method details, and then extract that information during your export d. recalculate the entire weight from scratch, rewriting much of the shopping-cart class

10 Aug 2007, 08:39
#20
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,513
Plugin Contributions:
174

Re: Use Of Notifiers - How To

SteveKim:

I'm just putting the static tare value matching what I've put on the configuration, unless there is a method of saving $weight in shopping_cart class to some other (global?) varible that does not get reset and passed onto my observer.Try using this:``` $_SESSION['cart']->weight