/phpab.php
PHP | 301 lines | 252 code | 42 blank | 7 comment | 50 complexity | 095ca27df2a5ed551b36b0198a5dcb94 MD5 | raw file
- <?php
- /*
- Name : phpA/B v1.2
- Author : Brian Cray
- License : GPL 2.0
- License URL : http://www.gnu.org/licenses/gpl-2.0.html
- URL : phpabtest.com
- */
- class phpab
- {
- private $variations = array();
- private $current_variation = '!unset';
- private $current_variation_key;
- private $test_name;
- private $test_ran = FALSE;
- private $trial_mode = FALSE;
- private $content;
- private $tag = 'phpab';
- private $auto_ga = TRUE;
- private $ga_slot = 1;
- private $test_domain;
- private $detect_bots = TRUE;
- private $is_bot = FALSE;
- private $version = '1.2';
-
- function __construct ($n, $t = FALSE)
- {
- if($this->detect_bots == TRUE)
- {
- $bots = array('googlebot', 'msnbot', 'slurp', 'ask jeeves', 'crawl', 'ia_archiver', 'lycos');
- foreach($bots as $botname)
- {
- if(stripos($_SERVER['HTTP_USER_AGENT'], $botname) !== FALSE)
- {
- $this->trial_mode = TRUE;
- $this->is_bot = TRUE;
- break;
- }
- }
- }
-
- if($this->is_bot == FALSE)
- {
- $this->trial_mode = $t;
- }
-
- ob_start(array($this, 'execute'));
-
- $this->test_domain = '.' . $_SERVER['HTTP_HOST'];
-
- $n = trim(strtolower($n));
- $n = preg_replace('/[^a-z0-9 _]*/', '', $n);
- $n = str_replace(' ', '_', $n);
- $this->test_name = $n;
- }
-
- function __destruct ()
- {
- ob_end_flush();
- }
-
- private function grab_content ()
- {
- if(empty($this->content))
- {
- $this->content = ob_get_contents();
- }
- }
-
- private function setup_ga ()
- {
- $try_auto = FALSE;
- $sync = '{' . $this->tag . ' ' . $this->test_name . ' ga_sync}';
- $async = '{' . $this->tag . ' ' . $this->test_name . ' ga_async}';
- $syncPos = strpos($this->content, $sync);
- if($syncPos !== FALSE)
- {
- $this->content = str_replace($sync, 'pageTracker._setCustomVar(' . $this->ga_slot . ', "' . $this->test_name . '", "' . $this->current_variation . '", 3);', $this->content);
- }
- else
- {
- $asyncPos = strpos($this->content, $async);
- if($asyncPos !== FALSE)
- {
- $this->content = str_replace($async, '_gaq.push(["_setCustomVar", ' . $this->ga_slot . ', "' . $this->test_name . '", "' . $this->current_variation . '", 3]);', $this->content);
- }
- else
- {
- $try_auto = TRUE;
- }
- }
-
- if($this->auto_ga == TRUE && $try_auto == TRUE)
- {
- $sync = strpos($this->content, 'pageTracker._trackPageview');
- if($sync === FALSE)
- {
- $async = preg_match('/_gaq\.push\(\[[\'\"]_trackPageview[\'\"]\]\)/', $this->content, $matches, PREG_OFFSET_CAPTURE);
- if($async == FALSE)
- {
- $auto_fail = TRUE;
- $async = FALSE;
- }
- else
- {
- $auto_fail = FALSE;
- $async = $matches[0][1];
- }
- }
- else
- {
- $auto_fail = FALSE;
- }
-
- if($auto_fail === FALSE && $sync !== FALSE)
- {
- $this->content = substr($this->content, 0, $sync - 1) . 'pageTracker._setCustomVar(' . $this->ga_slot . ', "' . $this->test_name . '", "' . $this->current_variation . '", 3);' . substr($this->content, $sync);
- }
- elseif($auto_fail === FALSE && $async !== FALSE)
- {
- $this->content = substr($this->content, 0, $async - 1) . ' _gaq.push(["_setCustomVar", ' . $this->ga_slot . ', "' . $this->test_name . '", "' . $this->current_variation . '", 3]); ' . substr($this->content, $async);
- }
- }
- }
-
- private function record_user_segment ()
- {
- $cookie_domain = (($colon_position = strrpos($this->test_domain, ":")) === false) ? $this->test_domain : substr($this->test_domain, 0, $colon_position);
- setcookie($this->tag . '-' . $this->test_name, $this->current_variation, time() + (60 * 60 * 24 * 365), '/', $cookie_domain);
- }
-
- public function set_domain ($d)
- {
- $this->test_domain = !empty($d) ? $d : '.' . $_SERVER['HTTP_HOST'];
- }
-
- public function set_ga_slot ($s)
- {
- $this->ga_slot = $s;
- }
-
- public function set_ga_mode ($m)
- {
- $this->ga_auto = $m;
- }
-
- public function set_tag ($t)
- {
- $this->tag = $t;
- }
-
- public function add_variation ($n, $v = '')
- {
- $n = trim(strtolower($n));
- $n = preg_replace('/[^a-z0-9 _]*/', '', $n);
- $n = str_replace(' ', '_', $n);
-
- array_push($this->variations, array('name' => $n, 'value' => $v));
- }
-
- public function get_user_segment ()
- {
- if($this->current_variation != '!unset' && $this->current_variation_key != -1)
- {
- return $this->current_variation;
- }
-
- if ($this->is_bot == TRUE)
- {
- $this->current_variation = 'control';
- return $this->current_variation;
- }
-
- if (get_magic_quotes_gpc() == TRUE)
- {
- $_COOKIE[$this->tag . '-' . $this->test_name] = stripslashes($_COOKIE[$this->tag . '-' . $this->test_name]);
- }
- if($this->trial_mode == FALSE)
- {
- $key = $this->tag . '-' . $this->test_name;
- if(array_key_exists($key, $_COOKIE))
- {
- $this->current_variation = $_COOKIE[$key];
- }
-
- if(empty($this->current_variation))
- {
- $this->current_variation = '!unset';
- }
- }
- else
- {
- $this->current_variation = '!unset';
- }
-
- array_unshift($this->variations, array('name' => 'control', 'value' => ''));
-
- $valid = FALSE;
-
- $this->current_variation_key = 0;
- foreach($this->variations as $n => $v)
- {
- if($v['name'] == $this->current_variation)
- {
- $valid = TRUE;
- break;
- }
- $this->current_variation_key++;
- }
- if($this->current_variation == '!unset' || $valid == FALSE)
- {
- srand((double)microtime() * 1000003);
- $this->current_variation_key = array_rand($this->variations);
- $this->current_variation = $this->variations[$this->current_variation_key]['name'];
- }
-
- return $this->current_variation;
- }
-
- public function execute ($buffer)
- {
- $this->content = $buffer;
-
- if($this->test_ran == FALSE)
- {
- $this->run_test();
- }
-
- if($this->trial_mode != TRUE)
- {
- $this->setup_ga();
- }
-
- $tmp = $this->content;
- $this->content = preg_replace('/<body([^>]*?)class="([^"]*?)"([^>]*?)>/i', '<body${1}class="${2} ' . $this->tag . '-' . $this->current_variation . '"${3}>', $this->content);
- if($tmp == $this->content)
- {
- $this->content = preg_replace('/<body([^>]*?)>/i', '<body${1} class="' . $this->tag . '-' . $this->current_variation . '">', $this->content);
- }
- unset($tmp);
-
- $pos = strrpos($this->content, '</body>');
- if($pos !== false)
- {
- $this->content = substr_replace($this->content, '<!--A/B tests active with phpA/B ' . $this->version . '--></body>', $pos, strlen('</body>'));
- }
- $this->content = str_replace('{' . $this->tag . ' ' . $this->test_name . ' current_varation}', $this->current_variation, $this->content);
-
- if($this->trial_mode != TRUE)
- {
- $this->record_user_segment();
- }
-
- return $this->content;
- }
-
- public function run_test ()
- {
- $this->get_user_segment();
- $this->grab_content();
-
- $open_tag = '{' . $this->tag . ' ' . $this->test_name . '}';
- $close_tag = '{/' . $this->tag . ' ' . $this->test_name . '}';
- $test_open = strpos($this->content, $open_tag);
- $test_close = strpos($this->content, $close_tag);
-
- while($test_open !== FALSE)
- {
- if($this->current_variation != 'control')
- {
- if($test_close === FALSE && $test_open !== FALSE)
- {
- $this->content = substr_replace($this->content, $this->variations[$this->current_variation_key]['value'], $test_open, strlen($open_tag));
- }
- elseif($test_close !== FALSE && $test_open !== FALSE)
- {
- $diff = $test_close + strlen($close_tag) - $test_open;
- $this->content = substr_replace($this->content, $this->variations[$this->current_variation_key]['value'], $test_open, $diff);
- }
- else
- {
- }
- }
- else
- {
- $this->content = str_replace($open_tag, $this->variations[$this->current_variation_key]['value'], $this->content);
- $this->content = str_replace($close_tag, '', $this->content);
- }
-
- $test_open = strpos($this->content, $open_tag, $test_open);
- $test_close = strpos($this->content, $close_tag, $test_open);
- }
-
- $this->test_ran = TRUE;
- }
- }