mirror of
				https://github.com/Mibew/i18n.git
				synced 2025-11-01 01:36:57 +03:00 
			
		
		
		
	Refactor cron_calculate_statistics function
This commit is contained in:
		
							parent
							
								
									a7ce1ff704
								
							
						
					
					
						commit
						289fb76906
					
				| @ -19,6 +19,7 @@ | ||||
| require_once('libs/init.php'); | ||||
| require_once('libs/classes/thread.php'); | ||||
| require_once('libs/track.php'); | ||||
| require_once('libs/statistics.php'); | ||||
| require_once('libs/cron.php'); | ||||
| 
 | ||||
| $cron_key = empty($_GET['cron_key']) ? '' : $_GET['cron_key']; | ||||
| @ -32,7 +33,11 @@ set_time_limit(0); | ||||
| 
 | ||||
| // Run cron jobs of the core
 | ||||
| cron_index_messages(); | ||||
| cron_calculate_statistics(); | ||||
| 
 | ||||
| calculate_thread_statistics(); | ||||
| calculate_operator_statistics(); | ||||
| calculate_page_statistics(); | ||||
| 
 | ||||
| 
 | ||||
| // Trigger cron event
 | ||||
| $dispatcher = EventDispatcher::getInstance(); | ||||
|  | ||||
| @ -202,204 +202,6 @@ function cron_index_messages() { | ||||
| 	$db->query('COMMIT'); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Calculate aggregated 'by thread' and 'by operator' statistics | ||||
|  */ | ||||
| function cron_calculate_statistics() { | ||||
| 	// Prepare database
 | ||||
| 	$db = Database::getInstance(); | ||||
| 	$db->throwExeptions(true); | ||||
| 
 | ||||
| 	try { | ||||
| 		// Start transaction
 | ||||
| 		$db->query('START TRANSACTION'); | ||||
| 
 | ||||
| 		// Build 'by thread' statistics
 | ||||
| 		// Get last record date
 | ||||
| 		$result = $db->query( | ||||
| 			"SELECT MAX(date) as start FROM {chatthreadstatistics}", | ||||
| 			array(), | ||||
| 			array('return_rows' => Database::RETURN_ONE_ROW) | ||||
| 		); | ||||
| 
 | ||||
| 		$start = empty($result['start']) ? 0 : $result['start']; | ||||
| 
 | ||||
| 		// Reset statistics for the last day, because cron can be ran many
 | ||||
| 		// times in a day.
 | ||||
| 		$result = $db->query( | ||||
| 			"DELETE FROM {chatthreadstatistics} WHERE date = :start", | ||||
| 			array(':start' => $start) | ||||
| 		); | ||||
| 
 | ||||
| 		// Calculate 'by thread' statistics
 | ||||
| 		$db->query( | ||||
| 			"INSERT INTO {chatthreadstatistics} ( " . | ||||
| 				"date, threads, operatormessages, usermessages, " . | ||||
| 				"averagewaitingtime, averagechattime " . | ||||
| 			") SELECT (FLOOR(t.dtmcreated / (24*60*60)) * 24*60*60) AS date, " . | ||||
| 				"COUNT(distinct t.threadid) AS threads, " . | ||||
| 				"SUM(m.ikind = :kind_agent) AS operators, " . | ||||
| 				"SUM(m.ikind = :kind_user) AS users, " . | ||||
| 				"ROUND(AVG(t.dtmchatstarted-t.dtmcreated),1) as avgwaitingtime, " . | ||||
| 				// Prevent negative values of avgchattime field.
 | ||||
| 				// If avgchattime < 0 it becomes to zero.
 | ||||
| 				// For random value 'a' result of expression ((abs(a) + a) / 2)
 | ||||
| 				// equals to 'a' if 'a' more than zero
 | ||||
| 				// and equals to zero otherwise
 | ||||
| 				"ROUND(AVG( " . | ||||
| 					"ABS(tmp.lastmsgtime-t.dtmchatstarted) + " . | ||||
| 					"(tmp.lastmsgtime-t.dtmchatstarted) " . | ||||
| 				")/2,1) as avgchattime " . | ||||
| 			"FROM {indexedchatmessage} m, " . | ||||
| 				"{chatthread} t, " . | ||||
| 				"(SELECT i.threadid, MAX(i.dtmcreated) AS lastmsgtime " . | ||||
| 					"FROM {indexedchatmessage} i " . | ||||
| 					"WHERE (ikind = :kind_user OR ikind = :kind_agent) " . | ||||
| 					"GROUP BY i.threadid) tmp " . | ||||
| 			"WHERE m.threadid = t.threadid " . | ||||
| 				"AND tmp.threadid = t.threadid " . | ||||
| 				"AND t.dtmchatstarted <> 0 " . | ||||
| 				"AND m.dtmcreated > :start " . | ||||
| 			"GROUP BY date " . | ||||
| 			"ORDER BY date", | ||||
| 			array( | ||||
| 				':kind_agent' => Thread::KIND_AGENT, | ||||
| 				':kind_user' => Thread::KIND_USER, | ||||
| 				':start' => $start | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		// Build 'by operator' statistics
 | ||||
| 		// Get last record date
 | ||||
| 		$result = $db->query( | ||||
| 			"SELECT MAX(date) as start FROM {chatoperatorstatistics}", | ||||
| 			array(), | ||||
| 			array('return_rows' => Database::RETURN_ONE_ROW) | ||||
| 		); | ||||
| 
 | ||||
| 		$start = empty($result['start']) ? 0 : $result['start']; | ||||
| 
 | ||||
| 		// Reset statistics for the last day, because cron can be ran many
 | ||||
| 		// times in a day.
 | ||||
| 		$result = $db->query( | ||||
| 			"DELETE FROM {chatoperatorstatistics} WHERE date = :start", | ||||
| 			array(':start' => $start) | ||||
| 		); | ||||
| 
 | ||||
| 		// Caclculate 'by operator' statistics
 | ||||
| 		$db->query( | ||||
| 			"INSERT INTO {chatoperatorstatistics} ( " . | ||||
| 				"date, operatorid, threads, messages, averagelength" . | ||||
| 			") SELECT (FLOOR(m.dtmcreated / (24*60*60)) * 24*60*60) AS date, " . | ||||
| 				"o.operatorid AS opid, " . | ||||
| 				"COUNT(distinct m.threadid) AS threads, " . | ||||
| 				"SUM(m.ikind = :kind_agent) AS msgs, " . | ||||
| 				"AVG(CHAR_LENGTH(m.tmessage)) AS avglen " . | ||||
| 			"FROM {indexedchatmessage} m, {chatoperator} o " . | ||||
| 			"WHERE m.agentId = o.operatorid " . | ||||
| 				"AND m.dtmcreated > :start " . | ||||
| 			"GROUP BY date " . | ||||
| 			"ORDER BY date", | ||||
| 			array( | ||||
| 				':kind_agent' => Thread::KIND_AGENT, | ||||
| 				':start' => $start | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		// Build 'by page' statistics
 | ||||
| 		$visited_pages = $db->query( | ||||
| 			"SELECT FLOOR(p.visittime / (24*60*60)) * 24*60*60 AS date, " . | ||||
| 				"p.address AS address, " . | ||||
| 				// 'visittimes' is not calculated pages count. It means that
 | ||||
| 				// 'visittimes' is count of NEW visited pages, not total count.
 | ||||
| 				"COUNT(DISTINCT p.pageid) AS visittimes, " . | ||||
| 				// 'chattimes' is total count of threads related with a page
 | ||||
| 				// address, not a visited page row. It means that 'chattimes' is
 | ||||
| 				// TOTAL chats count from this page, not only new.
 | ||||
| 				"COUNT(DISTINCT t.threadid) AS chattimes " . | ||||
| 			"FROM {visitedpage} p " . | ||||
| 				"LEFT OUTER JOIN {chatthread} t ON (" . | ||||
| 					"p.address = t.referer " . | ||||
| 					"AND DATE(FROM_UNIXTIME(p.visittime)) = " . | ||||
| 						"DATE(FROM_UNIXTIME(t.dtmcreated))) " . | ||||
| 			"WHERE p.calculated = 0 " . | ||||
| 			"GROUP BY date, address " . | ||||
| 			"ORDER BY date", | ||||
| 			array(), | ||||
| 			array('return_rows' => Database::RETURN_ALL_ROWS) | ||||
| 		); | ||||
| 
 | ||||
| 		foreach($visited_pages as $visited_page) { | ||||
| 			// Check is there statistics for current visited page in database.
 | ||||
| 			$count_result = $db->query( | ||||
| 				"SELECT COUNT(*) AS count " . | ||||
| 				"FROM {visitedpagestatistics} " . | ||||
| 				"WHERE date = :date AND address = :address", | ||||
| 				array( | ||||
| 					':date' => $visited_page['date'], | ||||
| 					':address' => $visited_page['address'] | ||||
| 				), | ||||
| 				array('return_rows' => Database::RETURN_ONE_ROW) | ||||
| 			); | ||||
| 
 | ||||
| 			if (! empty($count_result['count'])) { | ||||
| 				// Stat already in database. Update it.
 | ||||
| 				$db->query( | ||||
| 					"UPDATE {visitedpagestatistics} SET " . | ||||
| 						"visits = visits + :visits, " . | ||||
| 						// Do not add chat because of it is total count of chats
 | ||||
| 						// related with this page.
 | ||||
| 						// TODO: Think about old threads removing. In current
 | ||||
| 						// configuration it can cause problems with wrong
 | ||||
| 						// 'by page' statistics.
 | ||||
| 						"chats = :chats " . | ||||
| 					"WHERE date = :date " . | ||||
| 						"AND address = :address " . | ||||
| 					"LIMIT 1", | ||||
| 					array( | ||||
| 						':date' => $visited_page['date'], | ||||
| 						':address' => $visited_page['address'], | ||||
| 						':visits' => $visited_page['visittimes'], | ||||
| 						':chats' => $visited_page['chattimes'] | ||||
| 					) | ||||
| 				); | ||||
| 			} else { | ||||
| 				// Create stat row in database.
 | ||||
| 				$db->query( | ||||
| 					"INSERT INTO {visitedpagestatistics} (" . | ||||
| 						"date, address, visits, chats" . | ||||
| 					") VALUES ( " . | ||||
| 						":date, :address, :visits, :chats" . | ||||
| 					")", | ||||
| 					array( | ||||
| 						':date' => $visited_page['date'], | ||||
| 						':address' => $visited_page['address'], | ||||
| 						':visits' => $visited_page['visittimes'], | ||||
| 						':chats' => $visited_page['chattimes'] | ||||
| 					) | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Mark all visited pages as 'calculated'
 | ||||
| 		$db->query("UPDATE {visitedpage} SET calculated = 1"); | ||||
| 
 | ||||
| 		// Remove old tracks from the system
 | ||||
| 		track_remove_old_tracks(); | ||||
| 	} catch(Exception $e) { | ||||
| 		// Something went wrong: warn and rollback transaction.
 | ||||
| 		trigger_error( | ||||
| 			'Statistics calculating faild: ' . $e->getMessage(), | ||||
| 			E_USER_WARNING | ||||
| 		); | ||||
| 		$db->query('ROLLBACK'); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	// Commit transaction
 | ||||
| 	$db->query('COMMIT'); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Generates cron URI | ||||
|  * | ||||
|  | ||||
| @ -39,4 +39,249 @@ function setup_statistics_tabs($active) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Calculate aggregated 'by thread' statistics | ||||
|  */ | ||||
| function calculate_thread_statistics() { | ||||
| 	// Prepare database
 | ||||
| 	$db = Database::getInstance(); | ||||
| 	$db->throwExeptions(true); | ||||
| 
 | ||||
| 	try { | ||||
| 		// Start transaction
 | ||||
| 		$db->query('START TRANSACTION'); | ||||
| 
 | ||||
| 		// Get last record date
 | ||||
| 		$result = $db->query( | ||||
| 			"SELECT MAX(date) as start FROM {chatthreadstatistics}", | ||||
| 			array(), | ||||
| 			array('return_rows' => Database::RETURN_ONE_ROW) | ||||
| 		); | ||||
| 
 | ||||
| 		$start = empty($result['start']) ? 0 : $result['start']; | ||||
| 
 | ||||
| 		// Reset statistics for the last day, because cron can be ran many
 | ||||
| 		// times in a day.
 | ||||
| 		$result = $db->query( | ||||
| 			"DELETE FROM {chatthreadstatistics} WHERE date = :start", | ||||
| 			array(':start' => $start) | ||||
| 		); | ||||
| 
 | ||||
| 		// Calculate statistics
 | ||||
| 		$db->query( | ||||
| 			"INSERT INTO {chatthreadstatistics} ( " . | ||||
| 				"date, threads, operatormessages, usermessages, " . | ||||
| 				"averagewaitingtime, averagechattime " . | ||||
| 			") SELECT (FLOOR(t.dtmcreated / (24*60*60)) * 24*60*60) AS date, " . | ||||
| 				"COUNT(distinct t.threadid) AS threads, " . | ||||
| 				"SUM(m.ikind = :kind_agent) AS operators, " . | ||||
| 				"SUM(m.ikind = :kind_user) AS users, " . | ||||
| 				"ROUND(AVG(t.dtmchatstarted-t.dtmcreated),1) as avgwaitingtime, " . | ||||
| 				// Prevent negative values of avgchattime field.
 | ||||
| 				// If avgchattime < 0 it becomes to zero.
 | ||||
| 				// For random value 'a' result of expression ((abs(a) + a) / 2)
 | ||||
| 				// equals to 'a' if 'a' more than zero
 | ||||
| 				// and equals to zero otherwise
 | ||||
| 				"ROUND(AVG( " . | ||||
| 					"ABS(tmp.lastmsgtime-t.dtmchatstarted) + " . | ||||
| 					"(tmp.lastmsgtime-t.dtmchatstarted) " . | ||||
| 				")/2,1) as avgchattime " . | ||||
| 			"FROM {indexedchatmessage} m, " . | ||||
| 				"{chatthread} t, " . | ||||
| 				"(SELECT i.threadid, MAX(i.dtmcreated) AS lastmsgtime " . | ||||
| 					"FROM {indexedchatmessage} i " . | ||||
| 					"WHERE (ikind = :kind_user OR ikind = :kind_agent) " . | ||||
| 					"GROUP BY i.threadid) tmp " . | ||||
| 			"WHERE m.threadid = t.threadid " . | ||||
| 				"AND tmp.threadid = t.threadid " . | ||||
| 				"AND t.dtmchatstarted <> 0 " . | ||||
| 				"AND m.dtmcreated > :start " . | ||||
| 			"GROUP BY date " . | ||||
| 			"ORDER BY date", | ||||
| 			array( | ||||
| 				':kind_agent' => Thread::KIND_AGENT, | ||||
| 				':kind_user' => Thread::KIND_USER, | ||||
| 				':start' => $start | ||||
| 			) | ||||
| 		); | ||||
| 	} catch(Exception $e) { | ||||
| 		// Something went wrong: warn and rollback transaction.
 | ||||
| 		trigger_error( | ||||
| 			'Thread statistics calculating faild: ' . $e->getMessage(), | ||||
| 			E_USER_WARNING | ||||
| 		); | ||||
| 		$db->query('ROLLBACK'); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	// Commit transaction
 | ||||
| 	$db->query('COMMIT'); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Calculate aggregated 'by operator' statistics | ||||
|  */ | ||||
| function calculate_operator_statistics() { | ||||
| 	// Prepare database
 | ||||
| 	$db = Database::getInstance(); | ||||
| 	$db->throwExeptions(true); | ||||
| 
 | ||||
| 	try { | ||||
| 		// Start transaction
 | ||||
| 		$db->query('START TRANSACTION'); | ||||
| 
 | ||||
| 		// Get last record date
 | ||||
| 		$result = $db->query( | ||||
| 			"SELECT MAX(date) as start FROM {chatoperatorstatistics}", | ||||
| 			array(), | ||||
| 			array('return_rows' => Database::RETURN_ONE_ROW) | ||||
| 		); | ||||
| 
 | ||||
| 		$start = empty($result['start']) ? 0 : $result['start']; | ||||
| 
 | ||||
| 		// Reset statistics for the last day, because cron can be ran many
 | ||||
| 		// times in a day.
 | ||||
| 		$result = $db->query( | ||||
| 			"DELETE FROM {chatoperatorstatistics} WHERE date = :start", | ||||
| 			array(':start' => $start) | ||||
| 		); | ||||
| 
 | ||||
| 		// Caclculate statistics
 | ||||
| 		$db->query( | ||||
| 			"INSERT INTO {chatoperatorstatistics} ( " . | ||||
| 				"date, operatorid, threads, messages, averagelength" . | ||||
| 			") SELECT (FLOOR(m.dtmcreated / (24*60*60)) * 24*60*60) AS date, " . | ||||
| 				"o.operatorid AS opid, " . | ||||
| 				"COUNT(distinct m.threadid) AS threads, " . | ||||
| 				"SUM(m.ikind = :kind_agent) AS msgs, " . | ||||
| 				"AVG(CHAR_LENGTH(m.tmessage)) AS avglen " . | ||||
| 			"FROM {indexedchatmessage} m, {chatoperator} o " . | ||||
| 			"WHERE m.agentId = o.operatorid " . | ||||
| 				"AND m.dtmcreated > :start " . | ||||
| 			"GROUP BY date " . | ||||
| 			"ORDER BY date", | ||||
| 			array( | ||||
| 				':kind_agent' => Thread::KIND_AGENT, | ||||
| 				':start' => $start | ||||
| 			) | ||||
| 		); | ||||
| 	} catch(Exception $e) { | ||||
| 		// Something went wrong: warn and rollback transaction.
 | ||||
| 		trigger_error( | ||||
| 			'Operator statistics calculating faild: ' . $e->getMessage(), | ||||
| 			E_USER_WARNING | ||||
| 		); | ||||
| 		$db->query('ROLLBACK'); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	// Commit transaction
 | ||||
| 	$db->query('COMMIT'); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Calculate aggregated 'by page' statistics | ||||
|  */ | ||||
| function calculate_page_statistics() { | ||||
| 	// Prepare database
 | ||||
| 	$db = Database::getInstance(); | ||||
| 	$db->throwExeptions(true); | ||||
| 
 | ||||
| 	try { | ||||
| 		// Start transaction
 | ||||
| 		$db->query('START TRANSACTION'); | ||||
| 
 | ||||
| 		$visited_pages = $db->query( | ||||
| 			"SELECT FLOOR(p.visittime / (24*60*60)) * 24*60*60 AS date, " . | ||||
| 				"p.address AS address, " . | ||||
| 				// 'visittimes' is not calculated pages count. It means that
 | ||||
| 				// 'visittimes' is count of NEW visited pages, not total count.
 | ||||
| 				"COUNT(DISTINCT p.pageid) AS visittimes, " . | ||||
| 				// 'chattimes' is total count of threads related with a page
 | ||||
| 				// address, not a visited page row. It means that 'chattimes' is
 | ||||
| 				// TOTAL chats count from this page, not only new.
 | ||||
| 				"COUNT(DISTINCT t.threadid) AS chattimes " . | ||||
| 			"FROM {visitedpage} p " . | ||||
| 				"LEFT OUTER JOIN {chatthread} t ON (" . | ||||
| 					"p.address = t.referer " . | ||||
| 					"AND DATE(FROM_UNIXTIME(p.visittime)) = " . | ||||
| 						"DATE(FROM_UNIXTIME(t.dtmcreated))) " . | ||||
| 			"WHERE p.calculated = 0 " . | ||||
| 			"GROUP BY date, address " . | ||||
| 			"ORDER BY date", | ||||
| 			array(), | ||||
| 			array('return_rows' => Database::RETURN_ALL_ROWS) | ||||
| 		); | ||||
| 
 | ||||
| 		foreach($visited_pages as $visited_page) { | ||||
| 			// Check is there statistics for current visited page in database.
 | ||||
| 			$count_result = $db->query( | ||||
| 				"SELECT COUNT(*) AS count " . | ||||
| 				"FROM {visitedpagestatistics} " . | ||||
| 				"WHERE date = :date AND address = :address", | ||||
| 				array( | ||||
| 					':date' => $visited_page['date'], | ||||
| 					':address' => $visited_page['address'] | ||||
| 				), | ||||
| 				array('return_rows' => Database::RETURN_ONE_ROW) | ||||
| 			); | ||||
| 
 | ||||
| 			if (! empty($count_result['count'])) { | ||||
| 				// Stat already in database. Update it.
 | ||||
| 				$db->query( | ||||
| 					"UPDATE {visitedpagestatistics} SET " . | ||||
| 						"visits = visits + :visits, " . | ||||
| 						// Do not add chat because of it is total count of chats
 | ||||
| 						// related with this page.
 | ||||
| 						// TODO: Think about old threads removing. In current
 | ||||
| 						// configuration it can cause problems with wrong
 | ||||
| 						// 'by page' statistics.
 | ||||
| 						"chats = :chats " . | ||||
| 					"WHERE date = :date " . | ||||
| 						"AND address = :address " . | ||||
| 					"LIMIT 1", | ||||
| 					array( | ||||
| 						':date' => $visited_page['date'], | ||||
| 						':address' => $visited_page['address'], | ||||
| 						':visits' => $visited_page['visittimes'], | ||||
| 						':chats' => $visited_page['chattimes'] | ||||
| 					) | ||||
| 				); | ||||
| 			} else { | ||||
| 				// Create stat row in database.
 | ||||
| 				$db->query( | ||||
| 					"INSERT INTO {visitedpagestatistics} (" . | ||||
| 						"date, address, visits, chats" . | ||||
| 					") VALUES ( " . | ||||
| 						":date, :address, :visits, :chats" . | ||||
| 					")", | ||||
| 					array( | ||||
| 						':date' => $visited_page['date'], | ||||
| 						':address' => $visited_page['address'], | ||||
| 						':visits' => $visited_page['visittimes'], | ||||
| 						':chats' => $visited_page['chattimes'] | ||||
| 					) | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Mark all visited pages as 'calculated'
 | ||||
| 		$db->query("UPDATE {visitedpage} SET calculated = 1"); | ||||
| 
 | ||||
| 		// Remove old tracks from the system
 | ||||
| 		track_remove_old_tracks(); | ||||
| 	} catch(Exception $e) { | ||||
| 		// Something went wrong: warn and rollback transaction.
 | ||||
| 		trigger_error( | ||||
| 			'Page statistics calculating faild: ' . $e->getMessage(), | ||||
| 			E_USER_WARNING | ||||
| 		); | ||||
| 		$db->query('ROLLBACK'); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	// Commit transaction
 | ||||
| 	$db->query('COMMIT'); | ||||
| } | ||||
| 
 | ||||
| ?>
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user