File indexing completed on 2024-05-12 05:59:09

0001 <?php
0002 /**
0003  *  ocs-webserver
0004  *
0005  *  Copyright 2016 by pling GmbH.
0006  *
0007  *    This file is part of ocs-webserver.
0008  *
0009  *    This program is free software: you can redistribute it and/or modify
0010  *    it under the terms of the GNU Affero General Public License as
0011  *    published by the Free Software Foundation, either version 3 of the
0012  *    License, or (at your option) any later version.
0013  *
0014  *    This program is distributed in the hope that it will be useful,
0015  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017  *    GNU Affero General Public License for more details.
0018  *
0019  *    You should have received a copy of the GNU Affero General Public License
0020  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021  **/
0022 class Statistics_Model_GoalStatistics
0023 {
0024 
0025     const MYSQL_DATE_FORMAT = "Y-m-d H:i:s";
0026     const DEFAULT_RANKING_PLUGIN = 'Statistics_Ranking_WeightedAverageRanking';
0027 
0028     /** @var Statistics_Ranking_RankingInterface */
0029     protected $_rankingPlugin;
0030 
0031 
0032     /**
0033      * @param Statistics_Ranking_RankingInterface $rankingPlugin
0034      */
0035     function __construct(Statistics_Ranking_RankingInterface $rankingPlugin = null)
0036     {
0037         if (is_null($rankingPlugin)) {
0038             $default = self::DEFAULT_RANKING_PLUGIN;
0039             $this->_rankingPlugin = new $default;
0040             return $this;
0041         }
0042         $this->_rankingPlugin = $rankingPlugin;
0043     }
0044 
0045     public function setupDatabase()
0046     {
0047         exit(0);
0048 
0049         $sql = "
0050                 CREATE TABLE `stat_daily` (
0051                   `daily_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
0052                   `project_id` INT(11) NOT NULL COMMENT 'ID of the project',
0053                   `project_category_id` INT(11) DEFAULT '0' COMMENT 'Category',
0054                   `project_type` INT(11) NOT NULL COMMENT 'type of the project',
0055                   `count_views` INT(11) DEFAULT '0',
0056                   `count_plings` INT(11) DEFAULT '0',
0057                   `count_updates` INT(11) DEFAULT NULL,
0058                   `count_comments` INT(11) DEFAULT NULL,
0059                   `count_followers` INT(11) DEFAULT NULL,
0060                   `count_supporters` INT(11) DEFAULT NULL,
0061                   `created_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
0062                   `year` INT(11) DEFAULT NULL COMMENT 'z.B.: 1988',
0063                   `month` INT(11) DEFAULT NULL COMMENT 'z.b: 1-12',
0064                   `day` INT(11) DEFAULT NULL COMMENT 'z.B. 1-31',
0065                   `year_week` INT(11) DEFAULT NULL COMMENT 'z.b.: 201232',
0066                   PRIMARY KEY (`daily_id`)
0067                 ) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='Store daily statistic';
0068 
0069                 CREATE TABLE `app_config` (
0070                   `config_id` INT(11) NOT NULL AUTO_INCREMENT,
0071                   `group` VARCHAR(20) NOT NULL,
0072                   `name` VARCHAR(20) NOT NULL,
0073                   `value` VARCHAR(20) NOT NULL,
0074                   PRIMARY KEY (`config_id`),
0075                   KEY `index_group` (`group`)
0076                 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Store config for statistic';
0077                ";
0078 
0079         $sql_alter = "
0080         ALTER TABLE pling.stat_daily
0081           ADD ranking_value INT AFTER year_week;
0082         ALTER TABLE pling.stat_daily
0083           ADD count_money FLOAT AFTER count_supporters;
0084         ALTER TABLE pling.stat_daily
0085          CHANGE ranking_value ranking_value FLOAT;
0086         ALTER TABLE pling.stat_daily
0087          CHANGE project_type project_type_id INT(11) NOT NULL COMMENT 'type of the project';
0088            ";
0089 
0090         $database = Zend_Db_Table::getDefaultAdapter();
0091         $database->query($sql)->execute();
0092         $database->query($sql_alter)->execute();
0093     }
0094 
0095     public function dailyPageviews()
0096     {
0097        $sql = '
0098                insert into stat_daily_pageviews 
0099                select project_id
0100                ,count(project_id) cnt
0101                ,(select p.project_category_id from project p where v.project_id = p.project_id) project_category_id
0102                ,CURDATE() created_at
0103                from stat_page_views v where v.created_at > date_sub(CURDATE(), interval 6 month)
0104                group by project_id
0105        ';
0106        $database = Zend_Db_Table::getDefaultAdapter();
0107        $database->query($sql)->execute();      
0108     }
0109 
0110     public function migrateStatistics()
0111     {
0112         $database = Zend_Db_Table::getDefaultAdapter();
0113 
0114         $sqlTruncate = "TRUNCATE stat_daily";
0115         $result = $database->query($sqlTruncate);
0116 
0117 
0118         $sql = "
0119                 SELECT DATE_FORMAT(stat_page_views.created_at,\"%d.%m.%Y\") AS stat_date
0120                   FROM pling.stat_page_views stat_page_views
0121                 GROUP BY stat_date
0122                 ORDER BY created_at ASC;
0123         ";
0124 
0125         $queryObject = $database->query($sql);
0126         $resultSet = $queryObject->fetchAll();
0127 
0128         $addedRows = 0;
0129         $resultMessage = new stdClass();
0130 
0131         if (count($resultSet) > 0) {
0132             foreach ($resultSet as $element) {
0133                 $resultMessage = $this->generateDailyStatistics($element['stat_date']);
0134                 if ($resultMessage->result === false) {
0135                     break;
0136                 }
0137                 $addedRows += $resultMessage->AffectedRows;
0138             }
0139 
0140         }
0141 
0142         $resultMessage->AffectedRows = $addedRows;
0143         $resultMessage->Environment = APPLICATION_ENV;
0144 
0145         return $resultMessage;
0146     }
0147 
0148     /**
0149      * @param string|null $forDate
0150      * @return stdClass
0151      */
0152     public function generateDailyStatistics($forDate = null)
0153     {
0154         $database = Zend_Db_Table::getDefaultAdapter();
0155 
0156         $dateCreatedAt = new DateTime();
0157         $mysqlCreatedAt = $dateCreatedAt->format(self::MYSQL_DATE_FORMAT);
0158 
0159         if (is_null($forDate)) {
0160             $generateForDateObject = new DateTime();
0161         } else {
0162             $generateForDateObject = new DateTime($forDate);
0163         }
0164 
0165         $generateForDateObject->setTime(0, 0, 0);
0166         $mysqlStartDate = $generateForDateObject->format(self::MYSQL_DATE_FORMAT);
0167 
0168         $generateForDateObject->setTime(23, 59, 59);
0169         $mysqlEndDate = $generateForDateObject->format(self::MYSQL_DATE_FORMAT);
0170 
0171         $sql = "
0172                   select
0173                       prj.project_id,
0174                       prj.type_id as project_type_id,
0175                       prj.project_category_id,
0176                       (select count(1) from stat_page_views pv where pv.project_id = prj.project_id and pv.created_at between '{$mysqlStartDate}' and '{$mysqlEndDate}' group by pv.project_id) AS count_views,
0177                       (select count(1) from plings p where p.project_id = prj.project_id and p.pling_time between '{$mysqlStartDate}' and '{$mysqlEndDate}' AND p.status_id in (2,3,4) group by p.project_id) AS count_plings,
0178                       (select count(1) from project pu where pu.pid = prj.project_id and (pu.created_at between '{$mysqlStartDate}' and '{$mysqlEndDate}') and pu.type_id = 2 group by pu.pid) AS count_updates,
0179                       (select count(1) from project_follower pf where pf.project_id = prj.project_id) AS count_followers,
0180                       (SELECT count(1) FROM plings WHERE status_id >= 2 AND create_time BETWEEN '{$mysqlStartDate}' AND '{$mysqlEndDate}' AND project_id = prj.project_id AND comment is not null GROUP BY project_id) AS count_comments,
0181                       (SELECT count(member_id) FROM (SELECT member_id, project_id FROM plings WHERE status_id >= 2 AND create_time BETWEEN '{$mysqlStartDate}' AND '{$mysqlEndDate}' GROUP BY member_id, project_id) AS tempCountProjectSupporter WHERE project_id = prj.project_id) AS count_supporters,
0182                       (SELECT sum(amount) FROM plings WHERE status_id >= 2 AND create_time BETWEEN '{$mysqlStartDate}' AND '{$mysqlEndDate}' AND project_id = prj.project_id GROUP BY project_id) AS count_money,
0183                       '" . $mysqlCreatedAt . "' AS created_at,
0184                       DATE_FORMAT('{$mysqlStartDate}', '%Y') AS year,
0185                       DATE_FORMAT('{$mysqlStartDate}', '%m') AS month,
0186                       DATE_FORMAT('{$mysqlStartDate}', '%d') AS day,
0187                       YEARWEEK('{$mysqlStartDate}',1) AS year_week
0188                   from
0189                       project as prj
0190                   where
0191                       prj.status = " . Default_Model_DbTable_Project::PROJECT_ACTIVE . "
0192                       and prj.type_id = " . Default_Model_DbTable_Project::PROJECT_TYPE_STANDARD . "
0193                   group by prj.project_id;
0194                ";
0195 
0196         $statement = $database->query($sql);
0197 
0198         $statTable = new Statistics_Model_DbTable_StatDaily();
0199 
0200         while ($row = $statement->fetch(Zend_Db::FETCH_ASSOC, Zend_Db::FETCH_ORI_NEXT)) {
0201             $row['ranking_value'] = $this->_rankingPlugin->calculateRankingValue($row);
0202             $statTable->save($row);
0203         }
0204 
0205         $resultMessage = new stdClass();
0206         $resultMessage->result = $statement->errorCode() == '00000' ? true : false;
0207         $resultMessage->errorMessage = implode(' ', $statement->errorInfo());
0208         $resultMessage->errorCode = $statement->errorCode();
0209         $resultMessage->AffectedRows = $statement->rowCount();
0210 
0211         return $resultMessage;
0212 
0213     }
0214 
0215     /**
0216      * @param string $identifier
0217      * @param int $year
0218      * @param int $month
0219      * @param int $day
0220      * @return array
0221      */
0222     public function getDailyStatistics($identifier, $year, $month, $day)
0223     {
0224         $sql = "
0225                 SELECT sd.count_views AS views, sd.count_plings AS plings, sd.count_updates AS updates, sd.count_comments AS comments, sd.count_followers AS followers, sd.count_supporters AS supporters
0226                 FROM stat_daily AS sd
0227                 WHERE
0228                     sd.project_id = ?
0229                     AND sd.year = ?
0230                     AND sd.month = ?
0231                     AND sd.day = ?;
0232               ";
0233         $database = Zend_Db_Table::getDefaultAdapter();
0234         $sql = $database->quoteInto($sql, $identifier, 'INTEGER', 1);
0235         $sql = $database->quoteInto($sql, $year, 'INTEGER', 1);
0236         $sql = $database->quoteInto($sql, $month, 'INTEGER', 1);
0237         $sql = $database->quoteInto($sql, $day, 'INTEGER', 1);
0238 
0239         $resultSet = $database->query($sql)->fetchAll();
0240 
0241         return $resultSet;
0242     }
0243 
0244     /**
0245      * @param string $identifier
0246      * @param int $year
0247      * @param int $month
0248      * @return array
0249      */
0250     public function getMonthlyStatistics($identifier, $year, $month)
0251     {
0252         $sql = "
0253                 SELECT sd.year_week, sum(sd.count_views) AS views, sum(sd.count_plings) AS plings, sum(sd.count_updates) AS updates, sum(sd.count_comments) AS comments, avg(sd.count_followers) AS followers, avg(sd.count_supporters) AS supporters
0254                 FROM stat_daily AS sd
0255                 WHERE
0256                     sd.project_id = ?
0257                     AND sd.year = ?
0258                     AND sd.month = ?
0259                 GROUP BY sd.year_week
0260                 ORDER BY sd.day ASC;
0261         ";
0262         $database = Zend_Db_Table::getDefaultAdapter();
0263         $sql = $database->quoteInto($sql, $identifier, 'INTEGER', 1);
0264         $sql = $database->quoteInto($sql, $year, 'INTEGER', 1);
0265         $sql = $database->quoteInto($sql, $month, 'INTEGER', 1);
0266 
0267         $resultSet = $database->query($sql)->fetchAll();
0268 
0269         return $resultSet;
0270 
0271     }
0272 
0273     /**
0274      * @param string $identifier
0275      * @param int $yearWeek
0276      * @return array
0277      */
0278     public function getWeeklyStatistics($identifier, $yearWeek)
0279     {
0280         $sql = "
0281                 SELECT sd.day, sd.count_views AS views, sd.count_plings AS plings, sd.count_updates AS updates, sd.count_comments AS comments, sd.count_followers AS followers, sd.count_supporters AS supporters
0282                 FROM stat_daily AS sd
0283                 WHERE
0284                     sd.project_id = ?
0285                     AND sd.year_week = ?
0286                 ORDER BY sd.day ASC;
0287         ";
0288         $database = Zend_Db_Table::getDefaultAdapter();
0289         $sql = $database->quoteInto($sql, $identifier, 'INTEGER', 1);
0290         $sql = $database->quoteInto($sql, $yearWeek, 'INTEGER', 1);
0291 
0292         $resultSet = $database->query($sql)->fetchAll();
0293 
0294         return $resultSet;
0295 
0296     }
0297 
0298     /**
0299      * @param DateTime $forDate
0300      * @throws Exception
0301      */
0302     protected function generateRanking(DateTime $forDate)
0303     {
0304         throw new Exception('this code is outdated');
0305 
0306         $statisticsTable = new Statistics_Model_DbTable_StatDaily();
0307 
0308         $statement = $statisticsTable->select();
0309         $statement->setIntegrityCheck(false)->where('year = ?', $forDate->format('Y'))
0310             ->where('month = ?', $forDate->format('m'))
0311             ->where('day = ?', $forDate->format('d'))
0312             ->forUpdate(true);
0313 
0314         $rowSet = $statisticsTable->fetchAll($statement);
0315 
0316         foreach ($rowSet as $row) {
0317             $row->ranking_value = $this->_rankingPlugin->calculateRankingValue($row->toArray());
0318             $row->save();
0319         }
0320 
0321     }
0322 
0323 }