public function dashboard($request, $match) { $url = Pluf_HTTP_URL_urlForView('pluf_ab_dashboard'); $can_edit = $request->user->hasPerm('Pluf_AB.edit-test'); if ($can_edit && $request->method == 'POST') { // We mark the winner. $form = new Pluf_AB_Form_MarkWinner($request->POST); if ($form->isValid()) { $form->save(); $request->user->setMessage(__('The test has been updated.')); return new Pluf_HTTP_Response_Redirect($url); } } else { // To have it available for the control of the errors in // the template. $form = new Pluf_AB_Form_MarkWinner(); } // Get the list of tests $db = Pluf_AB::getDb(); $active = array(); $stopped = array(); foreach ($db->tests->find() as $test) { $test['stats'] = Pluf_AB::getTestStats($test); if ($test['active']) { $active[] = $test; } else { $stopped[] = $test; } } return Pluf_Shortcuts_RenderToResponse('pluf/ab/dashboard.html', array('active' => $active, 'stopped' => $stopped, 'form' => $form, 'can_edit' => $can_edit), $request); }
/** * Save the test. * * @return array Test. */ function save($commit = true) { $this->test['winner'] = $this->cleaned_data['alt']; $this->test['active'] = false; $this->test['stop_dtime'] = gmdate('Y-m-d H:i:s'); $db = Pluf_AB::getDb(); $db->tests->update(array('_id' => $this->cleaned_data['test']), $this->test); return $this->test; }
/** * Get stats for a given funnel. * * @param $funnel string Funnel * @param $period string Time period 'yesterday', ('today'), '7days', 'all' * @param $prop string Property to filter (null) */ public static function getStats($funnel, $period = 'today', $prop = null) { $db = Pluf_AB::getDb(); $steps = array(); for ($i = 1; $i <= 20; $i++) { $steps[$i] = array(); } switch ($period) { case 'yesterday': $q = array('t' => (int) gmdate('Ymd', time() - 86400)); break; case 'today': $q = array('t' => (int) gmdate('Ymd')); break; case '7days': $q = array('t' => array('$gte' => (int) gmdate('Ymd', time() - 604800))); break; case 'all': default: $q = array(); break; } $q['f'] = $funnel; if ($prop) { $q['p.' . $prop] = array('$exists' => true); } $uids = array(); // With very big logs, we will need to find by schunks, this // will be very easy to adapt. foreach ($db->funnellogs->find($q) as $log) { if (!isset($uids[$log['u'] . '##' . $log['s']])) { if ($prop and !isset($log['p'][$prop])) { continue; } $uids[$log['u'] . '##' . $log['s']] = true; $step = $log['s']; $steps[$step]['name'] = $log['sn']; $steps[$step]['id'] = $log['s']; if ($prop and !isset($steps[$step]['props'])) { $steps[$step]['props'] = array(); } $steps[$step]['total'] = isset($steps[$step]['total']) ? $steps[$step]['total'] + 1 : 1; if ($prop) { $steps[$step]['props'][$log['p'][$prop]] = isset($steps[$step]['props'][$log['p'][$prop]]) ? $steps[$step]['props'][$log['p'][$prop]] + 1 : 1; } } } // Now, compile the stats for steps 2 to n // First, we find the "max" for the reference number of // visitors along this funnel. This is $t1 and $tprops[prop] $t1 = 0; foreach ($steps as $step) { if (isset($step['total']) and $step['total'] > $t1) { $t1 = $step['total']; } if ($prop and isset($step['props'])) { foreach ($step['props'] as $v => $t) { if (!isset($tprops[$v])) { $tprops[$v] = $t; continue; } if ($tprops[$v] < $t) { $tprops[$v] = $t; } } } } if ($t1 == 0) { return array(); } $prev_step = null; for ($i = 1; $i <= 20; $i++) { if ($prev_step == null) { } if ($steps[$i]) { $tp = $prev_step['total']; $tn = $steps[$i]['total']; if ($tp) { $steps[$i]['conv'] = sprintf('%01.2f%%', 100.0 - (double) ($tp - $tn) / $tp * 100.0); } else { $steps[$i]['conv'] = 'N/A'; } if ($t1) { $steps[$i]['conv1'] = sprintf('%01.2f%%', 100.0 - (double) ($t1 - $tn) / $t1 * 100.0); } else { $steps[$i]['conv1'] = 'N/A'; } if ($prop) { $steps[$i]['sprops'] = array(); $steps[$i]['sprops1'] = array(); foreach ($steps[$i]['props'] as $v => $t) { if (!isset($tprops[$v])) { $tprops[$v] = $t; } $pv = isset($prev_step['props'][$v]) ? $prev_step['props'][$v] : 0; $steps[$i]['sprops'][$v] = array($t, $pv); $steps[$i]['sprops1'][$v] = array($t, $tprops[$v]); if ($pv) { $steps[$i]['sprops'][$v][] = round(100 * (double) $t / (double) $pv, 2) . '%'; } else { $steps[$i]['sprops'][$v][] = 0; } $steps[$i]['sprops1'][$v][] = round(100 * (double) $t / (double) $tprops[$v], 2) . '%'; } } $steps[$i]['bigtotal'] = $t1; $prev_step = $steps[$i]; } } for ($i = 20; $i >= 1; $i--) { if (!$steps[$i]) { unset($steps[$i]); // We remove the inexisting steps } } return $steps; }