<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 ff=unix fenc=utf8: */
/**
* Classe de gestion des stats
*
* PHP version 5
*
* LICENSE: Ce programme est un logiciel libre distribué sous licence GNU/GPL
*
* @author Yves Tannier <yves@grafactory.net>
* @copyright 2006 Yves Tannier
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.1.0
* @link http://www.grafactory.net
*/
/**
* Appel de la classe abstraite Theatre
*
*/
namespace TheatreCore\Classes\Stats;
use App\Service\IdCookie;
use TheatreCore\Traits\TheatreTrait;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\ORM\EntityManagerInterface;
class Stats extends ServiceEntityRepository
{
use TheatreTrait;
// la base statistiques
private $stats_base = 'statistiques';
public function __construct(ManagerRegistry $registry, EntityManagerInterface $em)
{
parent::__construct($registry, \TheatreCore\Entity\Stats::class);
$this->em = $em;
}
/** Enregistre une stats
*
* Enregistre une stats dans la table correspondante
*
* @access public
* @return string
*/
public function log($table, $values)
{
// verification de la clé pour prévention flood
// if ($_GET['key'] != md5($_ENV['URL_THTV'].date('Ymd'))) return;
// logguer le cookie de session (2h)
if (!empty($_COOKIE['stats'])) {
$values['cookie_visitor'] = preg_replace('/[^a-zA-Z0-9\-]/', '', $_COOKIE['stats']);
} else {
// créer le cookie si n'exste pas
$idcookie = new IdCookie('stats');
$uniqid = $idcookie->get(1 * 60); /* 1 heures */
$values['cookie_visitor'] = $uniqid;
}
// table de stats de la journée
$table = $table . '_' . date('Ymd');
// on vérifie que la table de la journée existe, sinon, on la crée
// les valeurs
foreach ($values as $k => $v) {
$keys_tab[] = $k;
$values_tab[] = '\'' . $v . '\'';
}
// clé unique id + cookie
$res = $this->execute('INSERT IGNORE INTO ' . $this->stats_base . '.' . $table . ' (' . join(',', $keys_tab) . ') VALUES (' . join(',', $values_tab) . ')');
// si erreur, continuer l'exécution mais le loguer
if (empty($res)) {
//$this->logError('Impossible d\'enregistrer la statistique');
error_log('Impossible d\'enregistrer la stats');
$res = 0;
}
return $res;
}
// }}}
// {{{ createStatsTable()
/** Créer les tables de stats
*
* Enregistre une stats dans la table correspondante
*
* @access public
* @return string
*/
public function createStatsTable($table, $type_table = 'daily', $date_stats = null)
{
// la date de demain
if (empty($date_stats)) {
$date_stats = date('Ymd', strtotime('+1 day'));
}
// creation
$create = 'CREATE TABLE IF NOT EXISTS ' . $this->stats_base . '.`' . $table . '_' . $date_stats . '` (
`idmultimedia` int(11) unsigned NOT NULL,
`module` varchar(10) NOT NULL,
`time_view` timestamp NOT NULL default CURRENT_TIMESTAMP,
`cookie_visitor` varchar(50) NOT NULL,
PRIMARY KEY (`idmultimedia`,`cookie_visitor`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;';
// création
$this->execute($create);
}
// }}}
// {{{ getTableDays()
/** Récupère la liste des tables de stats
*
* récupère la liste des tables de stats et filtre par type de stats
*
* @access public
* @param string $type_table Type de table (ex : multimedias)
* @return array
*/
public function getTableDays($type_table, $params = array())
{
$this->loadModule('Manager');
$tables = $this->listTables($this->stats_base);
foreach ($tables as $t) {
if (preg_match('/' . $type_table . '_([0-9]+)/', $t, $match)) {
if (!empty($params['date_start']) && !empty($params['date_end'])) {
if ($match[1] >= $params['date_start'] && $match[1] <= $params['date_end']) {
$tables_tab[$match[1]] = array(
'table' => $match[0],
'date' => $match[1],
);
}
} else {
$tables_tab[$match[1]] = array(
'table' => $match[0],
'date' => $match[1],
);
}
}
}
return $tables_tab;
}
// }}}
// {{{ getStatsByDays()
/** Récupère les stats de vues par jour
*
* récupère les stats de vues par jour avec différentes valeurs
*
* @access public
* @param string $type_table Type de table (ex : multimedias)
* @return array
*/
public function getStatsByDays($type_table, $params = array())
{
// liste des tables
$tables = $this->getTableDays($type_table, $params);
//setDebug(print_r($tables, true));
// on compte le total pour chaque jour et l'id de la vidéo la plus vues
foreach ($tables as $d => $t) {
// on souhaite une recherche par objet
if (!empty($params['object']) && !empty($params['idobject'])) {
// joindre avec multimedias
$sql = 'SELECT COUNT(' . $this->stats_base . '.' . $t['table'] . '.`idmultimedia`)
FROM ' . $this->stats_base . '.' . $t['table'] . '
JOIN ' . $_ENV['TH_BDD'] . '.object_multimedia ON ' . $this->stats_base . '.' . $t['table'] . '.`idmultimedia`= ' . $_ENV['TH_BDD'] . '.object_multimedia.`idmultimedia` ';
$sql .= ' WHERE ' . $_ENV['TH_BDD'] . '.object_multimedia.`idobject`=' . (int)$params['idobject'] . '
AND ' . $_ENV['TH_BDD'] . '.object_multimedia.`object`=\'' . $params['object'] . '\' ';
} else {
$sql = 'SELECT COUNT(idmultimedia) FROM ' . $this->stats_base . '.' . $t['table'] . ' ';
}
$nb = $this->queryOne($sql);
$stats_tab[$d] = array(
'day' => $d,
'day_string' => $this->getFormeDate($d, '%a %d %B %Y', true),
'day_short_string' => $this->getFormeDate($d, ' %d/%m/%Y', true),
'views' => $nb,
'most_view' => $this->getBestView($type_table, 'day', $d, 1, $params),
);
}
return $stats_tab;
}
// }}}
// {{{ getDailyMostViewed()
/** Récupère les stats de vues par jour
*
* récupère les stats de vues par jour avec différentes valeurs
*
* @access public
* @param string $type_table Type de table (ex : multimedias)
* @return array
*/
public function getDailyMostViewed($type_table, $day, $nb_viewed = 10, $params = array())
{
// on compte le total pour chaque jour et l'id de la vidéo la plus vues
$table = $this->stats_base . '.' . $type_table . '_' . $day;
// on souhaite une recherche par objet
if (!empty($params['object']) && !empty($params['idobject'])) {
// joindre avec multimedias
$sql = 'SELECT COUNT(' . $table . '.`idmultimedia`)
FROM ' . $table . '
JOIN ' . $_ENV['TH_BDD'] . '.object_multimedia ON ' . $table . '.`idmultimedia`= ' . $_ENV['TH_BDD'] . '.object_multimedia.`idmultimedia`
WHERE ' . $_ENV['TH_BDD'] . '.object_multimedia.`idobject`=' . (int)$params['idobject'] . '
AND ' . $_ENV['TH_BDD'] . '.object_multimedia.`object`=\'' . $params['object'] . '\' ';
} else {
$sql = 'SELECT COUNT(' . $table . '.`idmultimedia`) FROM ' . $table . ' ';
}
$nb = $this->queryOne($sql);
$stats_tab = array(
'day' => $day,
'day_string' => $this->getFormeDate($day, '%a %d %B %Y', true),
'day_short_string' => $this->getFormeDate($day, ' %d/%m/%Y', true),
'views' => $nb,
'most_view' => $this->getBestView($type_table, 'day', $day, $nb_viewed, $params),
);
return $stats_tab;
}
// }}}
// {{{ getBestView()
/** La vidéo la plus vue sur une journée
*
* récupère la vidéo la plus vue sur une période et son nombre de vue
*
* @access public
* @param string $type_table Type de table (ex : multimedias)
* @return array
*/
public function getBestView($type_table, $periode = 'day', $date, $limit = 1, $params = array())
{
$table = $this->stats_base . '.' . $type_table . '_' . $date;
if (!empty($params['object']) && !empty($params['idobject'])) {
// joindre avec multimedias
$sql = 'SELECT ' . $table . '.`idmultimedia`, COUNT(' . $table . '.`idmultimedia`) as views
FROM ' . $table . '
JOIN ' . $_ENV['TH_BDD'] . '.object_multimedia ON ' . $table . '.`idmultimedia`= ' . $_ENV['TH_BDD'] . '.object_multimedia.`idmultimedia`
WHERE ' . $_ENV['TH_BDD'] . '.object_multimedia.`idobject`=' . (int)$params['idobject'] . '
AND ' . $_ENV['TH_BDD'] . '.object_multimedia.`object`=\'' . $params['object'] . '\'
GROUP BY ' . $table . '.`idmultimedia`
ORDER BY COUNT(' . $table . '.`idmultimedia`) DESC
LIMIT 0,' . $limit;
} else {
$sql = 'SELECT ' . $table . '.`idmultimedia`, COUNT(' . $table . '.`idmultimedia`) as views
FROM ' . $table . '
GROUP BY ' . $table . '.`idmultimedia`
ORDER BY COUNT(' . $table . '.`idmultimedia`) DESC
LIMIT 0,' . $limit;
}
// la plus vue ou les plus vues
if ($limit > 1) {
$infos = $this->queryAll($sql);
if (!empty($infos)) {
foreach ($infos as $k => $v) {
$infos[$k] = array_merge($infos[$k], Theatre::factory($type_table)->getObjectTitle($v['idmultimedia'], array(), array('return_array' => true)));
}
}
} else {
$infos = $this->queryRow($sql);
if (!empty($infos)) {
$infos = array_merge($infos, Theatre::factory($type_table)->getObjectTitle($infos['idmultimedia'], array(), array('return_array' => true)));
}
}
return $infos;
}
// }}}
// {{{ createDaysView()
/** Créer une vue sur les x derniers jours à partir du jour
*
* créer une vue ou remplacer l'ancienne pour xjours
*
* @access public
* @param string $nb_days Nombre de jours pour la vue
* @return array
*/
public function createDaysView($nb_days = 7)
{
// créer ou remplacer la vue
$sql = 'CREATE OR REPLACE VIEW ' . $this->stats_base . '.' . date('Ymd') . '_days' . $nb_days . ' AS ';
for ($i = 0; $i < $nb_days; $i++) {
$table_date = date('Ymd', strtotime('-' . $i . ' day'));
$tables_days[] = ' SELECT * FROM ' . $this->stats_base . '.multimedias_' . $table_date . ' ';
}
// union sur les tables depuis 7 jours
$sql .= join('UNION', $tables_days);
// création
$this->execute($sql);
return true;
}
// }}}
// {{{ deleteDaysView()
/** Supprimer les vues des jours précédents
*
* supprime des vues
*
* @access public
* @param string $nb_days Nombre de jours pour la vue
* @return array
*/
public function deleteDaysView()
{
// trouver et supprimer les vues des jours
$sql = 'SELECT *
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = \'statistiques\'
AND TABLE_NAME LIKE \'%_days%\' ';
$this->query($sql);
while ($this->fetch()) {
$sql_drop_view = 'DROP VIEW ' . $this->stats_base . '.' . $this->TABLE_NAME;
$this->exec($sql_drop_view);
}
return true;
}
// }}}
// {{{ getMostViewed()
/** Récupère les plus vues les X derniers jours
*
* Récupère les plus vues les X derniers jours
*
* @access public
* @param string $nb_days Nombre de jour de test
* @param string $limit nombre max d'éléments
* @param array $exclude liste des éléments devant être exclu
*
* @return array
*/
public function getMostViewed($nb_days = 7, $limit = 5, $exclude = array())
{
if (!$this->isViewExists('statistiques', date('Ymd') . '_days' . $nb_days)) {
$this->createDaysView($nb_days);
}
// requête sur la vue
$sql = 'SELECT idmultimedia, COUNT(idmultimedia) as views
FROM ' . $this->stats_base . '.' . date('Ymd') . '_days' . $nb_days . ' ';
if (!empty($exclude)) {
$sql .= 'WHERE idmultimedia NOT IN (' . implode(',', $exclude) . ') ';
}
$sql .= 'GROUP BY idmultimedia
ORDER BY COUNT(idmultimedia) DESC
LIMIT 0,' . (int)$limit;
$results = $this->queryAll($sql, array(), null, true);
if (empty($results)) {
return false;
} else {
return $results;
}
return true;
}
// }}}
// {{{ getMostDvdViewed()
/** Récupère les vidéos les plus vues avec un DVD les X derniers jours
*
*
* @access public
* @param string $nb_days Nombre de jour de test
* @param string $type_table Type de table (ex : multimedias)
* @return array
*/
public function getMostDvdViewed($nb_days = 7, $limit = 5)
{
if (!$this->isViewExists('statistiques', date('Ymd') . '_days' . $nb_days)) {
$this->createDaysView($nb_days);
}
// requête sur la vue
$sql = 'SELECT s.`idmultimedia`, COUNT(s.`idmultimedia`) as views
FROM `' . $this->stats_base . '`.`' . date('Ymd') . '_days' . $nb_days . '` as s, `' . $_ENV['TH_BDD'] . '`.`dvd_multimedia` as dm
WHERE dm.`idmultimedia`=s.`idmultimedia`
GROUP BY dm.`iddvd`
ORDER BY COUNT(s.`idmultimedia`) DESC
LIMIT 0,' . (int)$limit;
$results = $this->queryAll($sql, array(), null, true);
if (empty($results)) {
return false;
} else {
return $results;
}
return true;
}
// }}}
// {{{ isViewExists()
/** Tester si une vue existe
*
* teste si une vue existe pour une base données
*
* @access public
* @param string $database Base de la vue
* @param string $name Nom de la vue
* @return array
*/
public function isViewExists($database, $name)
{
// si la vues n'existe pas, on la crée
$sql = 'SELECT COUNT(*)
FROM information_schema.VIEWS
WHERE TABLE_SCHEMA = \'' . $database . '\'
AND TABLE_NAME = \'' . $name . '\' ';
$result = $this->queryOne($sql);
if (empty($result) || $result == 0) {
return false;
} else {
return true;
}
}
// }}}
// {{{ getMonthStats()
/** Statistiques mensuelles
*
* @access public
* @param string $nb_days Nombre de jours pour la vue
* @return array
*/
public function getMonthStats($type_table, $params = array())
{
// liste des tables
$tables = $this->getTableDays($type_table, $params);
// grouper par mois
foreach ($tables as $k => $v) {
$date = $v['date'];
// découpage
$annee = substr($date, 0, 4);
$mois = substr($date, 4, 2);
$jour = substr($date, 6, 2);
// tableau
$tabs_date[$annee][$mois][$jour] = $v;
}
$with_union = false;
// les classer par mois
foreach ($tabs_date as $a => $annees) {
foreach ($annees as $k => $mois) {
$sql_jour = array();
foreach ($mois as $jour) {
// on souhaite une recherche par objet
if (!empty($params['object']) && !empty($params['idobject'])) {
// joindre avec multimedias
$sql = '(SELECT COUNT(' . $this->stats_base . '.' . $jour['table'] . '.`idmultimedia`)
FROM ' . $this->stats_base . '.' . $jour['table'] . '
JOIN ' . $_ENV['TH_BDD'] . '.object_multimedia ON ' . $this->stats_base . '.' . $jour['table'] . '.`idmultimedia`= ' . $_ENV['TH_BDD'] . '.object_multimedia.`idmultimedia` ';
$sql .= ' WHERE ' . $_ENV['TH_BDD'] . '.object_multimedia.`idobject`=' . (int)$params['idobject'] . '
AND ' . $_ENV['TH_BDD'] . '.object_multimedia.`object`=\'' . $params['object'] . '\')';
$sql_jour[] = $sql;
} else {
$sql_jour[] = '(SELECT COUNT(*) FROM ' . $this->stats_base . '.' . $jour['table'] . ') ';
}
}
// le mois
$m = strftime('%B', strtotime($jour['date']));
if ($with_union) {
$sql_mois[$a . $k] = '(SELECT \'' . $a . '\' as year,\'' . $k . '\' as month, \'' . $m . '\' as month_string, ' . join('+', $sql_jour) . ' as vues)';
} else { // requête par requête
$sql_mois_string = '(SELECT \'' . $a . '\' as year,\'' . $k . '\' as month, \'' . $m . '\' as month_string, ' . join('+', $sql_jour) . ' as vues)';
$stats[] = $this->queryRow($sql_mois_string);
}
}
}
// lourdingue
if ($with_union) {
$sql_all = join(' UNION ', $sql_mois);
$stats = $this->queryAll($sql_all);
}
//setDebug($stats);
return $stats;
}
// }}}
}