<?php /* -*- mode: php; tab-width: 4; c-set-style: k&r -*- */
/*
 * Copyright (c) 2009 TrueStep
 * Author: Rory Arms - http://www.TrueStep.com/
 * Name: pi.feedback_popup.php
 * Cdate: 2009-05-24
 * Description: EE 1.x plugin to present arbitrary output such as 
 *              feedback popup forms, surveys, etc.
 * Tested with: EE-1.6.3+PHP-4.3.9+MySQL-4.1.22, EE 1.6.3+PHP-5.2.6+MySQL-4.1.20
 * Tag syntax: {exp:feedback_popup}
 * $Id: pi.feedback_popup.php,v 1.13 2009/06/19 08:01:40 rorya Exp $
 */

//ini_set('display_errors', 1);
//error_reporting(E_ALL);

// EE plugin properties
$plugin_info = array(
     
'pi_name' => 'Feedback_popup',
     
'pi_version' => '1.2',
     
'pi_author' => 'TrueStep',
     
'pi_author_url' => 'http://www.TrueStep.com/',
     
'pi_description' => 'Displays markup data to every x number of visitors, which have resided on your site for an m number of minutes',
     
'pi_usage' => Feedback_popup::usage()
     );

class 
Feedback_popup {
     
// EE required vars
     
var $return_data "";

     
// app vars
     
var $debug;
     var 
$plugin_version "1.2";
     var 
$ee_globals_table;
     var 
$persistence_table;
     var 
$use_global;
     var 
$visitor_count 0// Tracks count of new sessions created
     
var $survey_count 0;
     var 
$date;
     
// app settings
     
var $setting_count;
     var 
$setting_max_count;
     var 
$setting_time;

     function 
Feedback_popup() {
          
// this order is crucial, as otherwise this breaks PHP 4.2
          
global $OUT$TMPL$FNS;

          
// initialize members with app vars and app settings
          //
          // debug toggle, overrides output with debug info
          // make sure this is set to FALSE, in production
          
$this->debug FALSE;

          
// init date with ISO-8601 format
          
$this->date date("Y-m-d\TH:i:sO");

          
// cookie basenames
          
$cookie_name_selected "feedback_popup_selected";
          
$cookie_name_start "feedback_popup_start";

          
// table name to use for EE globals
          
$this->ee_globals_table "exp_global_variables";

          
$this->persistence_table "exp_feedback_popup";

          
// Whether or not to use EE global variables
          
$this->use_global FALSE;

          
// app default for visitor count
          
$this->setting_count 50;

          
// app default for max visitor count
          
$this->setting_max_count 1000000000000// 10^12

          // app default for visitor session time limit
          
$this->setting_time 2;

          
/* Variable names expected in the exp_global_variables table
           *
           * feedback_popup_setting_count - survey every n visitors
           * feedback_popup_setting_minutes - show popup survey of chosen visitor after n minutes
           */

          // init visitor_count member with current visitor count
          
if (! ($this->visitor_count $this->getAppVisitorCount()) )
               if (
$this->debug$this->result_data "Post-init : visitor_count = " $this->visitor_count "<br />\n";

          
// init setting_session_count member
          
if (! ($this->setting_count $this->getSettingVisitorCount()) )
               if (
$this->debug$OUT->fatal_error("getSettingVisitorCount(): error: setting_count = " $this->setting_count "<br />\n");

          
// init setting_time member
          
if (! ($this->setting_time $this->getSettingVisitorTime()) )
               if (
$this->debug$OUT->fatal_error("error: getSettingVisitorTime(): setting_time = " $setting_time);

          if (! isset(
$_COOKIE['exp_'.$cookie_name_start])) {
               
// session start doesn't exist

               // count this visitor
               
if (! $this->incrAppVisitorCount() ) {
                    
$this->debug_print("incrAppVisitorCount() error: failed to increment visitor_count = " $this->visitor_count "<br />\n");
               }
               
// set session start cookie
               
$FNS->set_cookie($cookie_name_starttime(), 0);

               if (! isset(
$_COOKIE['exp_'.$cookie_name_selected])) {
                    
// selected cookie not set
                    
if (($this->visitor_count $this->setting_count) == 0) {
                         
// this visitor selected, so assert selected cookie
                         
$FNS->set_cookie($cookie_name_selected10);
                    } 
               } else {
                    
// this one has all ready participated, so disable selected
                    
$FNS->set_cookie($cookie_name_selected00);
               }


               
// debug section
               //if ($this->debug) print("No-cookie mode : visitor_count = " . $this->visitor_count . "<br />\n");
               //if ($this->debug) if (isset($_COOKIE['exp_'.$cookie_name_selected])) print("visitor selected: ". $_COOKIE['exp_'.$cookie_name_selected]."<br />\n");

          
} else {
               
// have session

               
if (isset($_COOKIE['exp_'.$cookie_name_selected]) && ($_COOKIE['exp_'.$cookie_name_selected] == 1)) {
                    
// this is the chosen visitor
                    
$session_age time() - $_COOKIE['exp_'.$cookie_name_start];
                    if (
time() >= ($_COOKIE['exp_'.$cookie_name_start] + ($this->setting_time 60))) {
                         
// survey given, so disable selected cookie
                           
if (isset($_COOKIE['exp_'.$cookie_name_selected]))
                                
$FNS->set_cookie($cookie_name_selected00);

                         
// display embedded tag data in template
                         
if ($this->debug) {
                              if (! 
$this->incrAppSurveyCount() )
                                   
$this->debug_print("incrAppSurveyCount() failed. survey_count = "$this->survey_count ."<br />\n");
                              
$this->return_data "feedback_popup tag engaged. feedback_popup: <br />Cookie: $cookie_name_start = " $_COOKIE['exp_'.$cookie_name_start]."<br />App Vars: visitor_count = "$this->visitor_count."; session age = ".$session_age."s ; survey_count = "$this->survey_count ."<br />App Settings: setting_count = ".$this->setting_count."; setting_time = "$this->setting_time ."m ; setting_max_count = "$this->setting_max_count;
                         } else {
                              
$this->incrAppSurveyCount();
                              
$this->return_data $TMPL->tagdata;
                         }
                    }
               }
               
// debug section
               //debug_print("Have-cookie mode | visitor_count = " . $this->visitor_count."<br />\n");
               //if ($this->debug) if (isset($_COOKIE['exp_'.$cookie_name_selected])) $this->debug_print("visitor selected: ". $_COOKIE['exp_'.$cookie_name_selected]."<br />\n");

          
}
     }

     
// public
     
function getSettingVisitorCount() {
          global 
$DB$TMPL;

          
// check parameters
          
if (strlen($TMPL->fetch_param('visitors')) > 0)
               return 
$TMPL->fetch_param('visitors');

          
// if directed, use EE's global variables to find app settings
          
if ($this->use_global) {
               
// get feedback_popup_setting_count setting
               
$sql "SELECT variable_name,variable_data FROM `".$this->ee_globals_table."` WHERE `variable_name` = 'feedback_popup_setting_count' LIMIT 0, 1";
               if (! (
$results $DB->query($sql)) )
                    return 
$this->setting_count;
               else
                    return (int)
$results->row['variable_data'];
          } else {
               return 
$this->setting_count;
          }
     }

     
// public
     
function getSettingVisitorTime() {
          global 
$DB$TMPL;

          
// check parameters
          
if (strlen($TMPL->fetch_param('time')) > 0)
               return 
$TMPL->fetch_param('time');

          
// if directed, EE's global variables to find app settings
          
if ($this->use_global) {
               
// get feedback_popup_setting_minutes setting
               
$sql "SELECT variable_name,variable_data FROM `".$this->ee_globals_table."` WHERE `variable_name` = 'feedback_popup_setting_minutes' LIMIT 0, 1";
               if (! (
$results $DB->query($sql)) )
                    return 
$this->setting_time;
               else
                    return (int)
$results->row['variable_data'];
          } else {
               return 
$this->setting_time;
          }
     }

     
// private
     
function getAppVisitorCount() {
          global 
$DB;

          
// Create plugin table to store visitor count, if need be.
          
$DB->query("CREATE TABLE IF NOT EXISTS `".$this->persistence_table ."` (
                      `id` int(3) PRIMARY KEY AUTO_INCREMENT,
                      `name` varchar(25) NOT NULL,
                      `value_char` char(40) DEFAULT NULL,
                      `value_int` int(12) UNSIGNED DEFAULT NULL
                      )"
);

          
// Check to see if visitor_count record has been initialized
          
$visitor_count $DB->query("SELECT value_int FROM `".$this->persistence_table ."` WHERE name = 'visitor_count' LIMIT 0, 1");
          if (! 
$visitor_count->num_rows 0) {
               
// no records, so  & init

               // For the sake of efficiency, we're not checking
               // that all necessary records exist prior to creating them
               // therefore, we'll assume all are not there if visitor_count
               // record is missing.

               // add & initialize visitor_count record
               
$DB->query("INSERT INTO `".$this->persistence_table ."` SET `name` = 'visitor_count', `value_int` = 0");
               
$DB->query("INSERT INTO `".$this->persistence_table ."` SET `name` = 'visitor_count_reset_date', `value_char` = '$this->date'");
               
// add & initialize survey_count record
               
$DB->query("INSERT INTO `".$this->persistence_table ."` SET `name` = 'survey_count', `value_int` = 0");
               
// add & initialize survey_count_reset_date record
               
$DB->query("INSERT INTO `".$this->persistence_table ."` SET `name` = 'survey_count_reset_date', `value_char` = '$this->date'");
               
// add & initialize survey_count_reset_date record
               
$DB->query("INSERT INTO `".$this->persistence_table ."` SET `name` = 'survey_hitrate', `value_char` = NULL");
               return 
0;
          } else {
               
// have record, now check that it is initialized
               
if ($visitor_count->row['value_int'] == '') {
                    
// but record is blank, so initialize
                    
$DB->query("INSERT INTO `"$this->persistence_table ."` SET `name` = 'visitor_count', `value_int`= 0");
                    return 
0;
               }

               
// table initialized, get visitor_count value
               
$visitor_count $DB->query("SELECT value_int FROM `".$this->persistence_table ."` WHERE `name` = 'visitor_count' LIMIT 0, 1");
               return 
$visitor_count->row['value_int'];
          }

     }

     
// private
     
function incrAppVisitorCount() {
          global 
$DB;

          if (
$this->visitor_count $this->setting_max_count) {
               
// visitor count has reached its limit, reset
               
if (! $this->resetAppVisitorCount() )
                    
$this->debug_print("Failed to reset. visitor_count = " $this->visitor_count ."<br />\n");
               
               
// reset member too
               
$this->visitor_count 0;

               
// and reset survey_count
               
if (! $this->resetAppSurveyCount() )
                    
$this->debug_print("Failed to reset. survey_count = " $this->survey_count ."<br />\n");
          }

          
$sql "UPDATE `"$this->persistence_table ."` SET `value_int` = ". ++$this->visitor_count ." WHERE name = 'visitor_count'";
          return 
$DB->query($sql);
     }

     
// private
     
function resetAppVisitorCount() {
          global 
$DB;

          
// reset visitor_count
          
$DB->query("UPDATE `".$this->persistence_table."` SET `value_char` = 0 WHERE `name` = 'visitor_count'");

          
// update survey_count_reset_date record, timestamp
          // this is to have an idea as to when this counter was last reset.
          
return $DB->query("UPDATE `".$this->persistence_table."` SET `value_char` = '"$this->date ."' WHERE `name` = 'visitor_count_reset_date'");
          
     }

     
// private
     
function incrAppSurveyCount() {
          global 
$DB;

          
// get count for persistence store
          
$count $DB->query("SELECT value_int FROM `"$this->persistence_table ."` WHERE name = 'survey_count'");

          
// assign to member
          
$this->survey_count $count->row['value_int'];

          
// increment survey_count
          
$DB->query("UPDATE `".$this->persistence_table."` SET `value_int` = ". ++$this->survey_count ." WHERE `name` = 'survey_count'");

          
// XXX this calculation is based on the current visitor setting
          // what should really happen is when the visitor setting
          // changes, all counters should be reset. But this is good enough
          // for now. For now, it's easiest to just drop the  persistence table
          // whenever the visitors parameter is changed, otherwise the 
          // survey_hitrate value will be innacurate.

          // calculate survey hit rate percentage
          
$survey_hitrate round($this->survey_count / ($this->visitor_count $this->setting_count) * 100);
          
          
// write survey hit rate to persistence and return
          
return $DB->query("UPDATE `".$this->persistence_table ."` SET `value_char` = '"$survey_hitrate "%' WHERE `name` = 'survey_hitrate'");
     }

     
// private
     
function resetAppSurveyCount() {
          global 
$DB;

          
// reset survey_count
          
$DB->query("UPDATE `".$this->persistence_table."` SET `value_int` = 0 WHERE `name` = 'survey_count'");
          
// update survey_count_reset_date record, timestamp
          // this is to have an idea as to when this counter was last reset.
          
return $DB->query("UPDATE `".$this->persistence_table."` SET `value_char` = '".$this->date ."' WHERE `name` = 'survey_count_reset_date'");
     }

     
// private
     
function debug_print($msg) {
          print(
"DEBUG:> "$msg);
     }

     
// 3-segment tags

     // Note: These should not be used on PHP 4, at least embedded the main
     // 2-segment. Otherwise the constructor executes for each tag. 
     // Not sure if this is an EE bug or PHP, probably both.
     // I will look into this further with EE support later, as we've managed
     // to work around these for now. Well, maybe never, it's likely
     // something beyond the capabilities of this software stack combo.

     // public
     // 3-segment tag: {exp:feedback_popup:visitor_count}
     // returns int (visitor count setting)
     
function visitor_count() {
          return 
$this->setting_count;
     }

     
// public
     // 3-segment tag: {exp:feedback_popup:visitor_time}
     // returns int
     
function visitor_time() {
          return 
$this->setting_time;
     }

     
// public
     // 3-segment tag: {exp:feedback_popup:version
     // returns int (plugin version)
     
function version() {
          return 
$this->plugin_version;
     }

     
// public
     
function usage() {
          
ob_start(); 
          
?>
              The Feedback_popup Plugin 
                 
Displays your markup data to every x number of visitors, which have 
resided on your site for an m number of minutes.

Usage:

{exp:feedback_popup}
HTML fragment, etc and/or EE tags you want feedback_popup to display when activated, here.
{/exp:feedback_popup}

There are two optional pameters that can be specified, which
override the default of every 50 visitors with a 2 minute session age.
For example, specifying this one as the opening tag:

      {exp:feedback_popup visitors="10" time="5"}
      <p>Hello, you are our lucky 10th visitor!</p>
      {/exp:feedback_popup}

This would make feedback_popup display the markup you specify inside, to
every 10th visitor, with a session age of at least 5 minutes into their 
browsing session, on every template that uses this tag.

3- segment tags

Note, Do not use 3-segment tags on PHP 4 runtime, only the main, 
2-segment. This will hopefully be resolved in a future version of this plugin.

3-segment tags for use inside the {exp:feedback_popup} {/exp:feedback_popup}
{exp:feedback_popup:visitor_count} : displays the visitor count
{exp:feedback_popup:visitor_time} : displays the visitor session length

- other 3-segment tags
{exp:feedback_popup:version} : displays the version number of the plugin.

Finally, here is an example that uses all possible options. This is 
a good one to use for testing:

{exp:feedback_popup visitors="1" time="1"}
feedback_popup version {exp:feedback_popup:version} activated. You are visitor {exp:feedback_popup:visitor_count}, and your session is at least {exp:feedback_popup:visitor_time} minutes old.
{/exp:feedback_popup}

<?php
          $buffer 
ob_get_contents();
          
ob_end_clean(); 

          return 
$buffer;
     } 
// end usage()
}

?>