<?php

/**
 * Class file for audit logging.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package clearFusionCMS
 * @copyright Copyright (c) 2016 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * cfAudit Class
 *
 * Static class to provide audit trail logging.
 *
 * @package clearFusionCMS
 */
abstract class cfAudit {

	/**
	 * Flags if auto clean run within this script instance.
	 *
	 * @var bool
	 */
	static $autoClean = true;

	/**
	 * Record an audit entry in to the database and purge old entries.
	 *
	 * @param int $action The action code.
	 * @param string $module The module to log the entry for.
	 * @param int $id The content id to log the entry for.
	 * @param array $params Parameters to store with the entry or null if not required.
	 * @param array $previous The previous data to store or null if not required.
	 */
	static function record($action, $module, $id, $params = null, $previous = null) {
		$db = clearFusionCMS::getDb();
		$cfg = new flConfigDb('cfSystemAudit', $db);
		$days = $cfg->get('days', 30);

		// If days of retention is 0 then don't log
		if($days) {
			$now = new flDate();

			$uid = clearFusionCMS::getUser()->getId();
			clearFusionCMS::getDb()->insert(
				'cf_auditlog_' . clearFusionCMS::getSite(),
				[
					'action' => $action,
					'module' => $module,
					'cid' => $id,
					'uid' => $uid ? $uid : 0,
					'loggedat' => $now->toString(),
					'ip' => clearFusionCMS::getRequest()->getClientIp(),
					'params' => $params ? json_encode($params) : '',
					'previous' => $previous ? json_encode($previous) : ''
				]
			);

			// Randomly choose to clean history
			if(self::$autoClean && mt_rand(1, 10) == 1) {
				self::$autoClean = false;

				clearFusionCMS::getDb()->delete(
					'cf_auditlog_' . clearFusionCMS::getSite(),
					'loggedat < DATE_SUB(NOW(), INTERVAL ? DAY)',
					$days
				);
			}
		}
	}

	/**
	 * Get the number of records that match the query.
	 *
	 * @param int $uid The user id to search for or null for all.
	 * @param string $module The module to search for or null for all.
	 * @return int The number of records found.
	 */
	static function numMatches($uid = null, $module = null) {
		$params = [];
		$where = [];

		if($uid !== null) {
			$where[] = 'uid=?';
			$params[] = $uid;
		}

		if($module !== null) {
			$where[] = 'module=?';
			$params[] = $module;
		}

		return clearFusionCMS::getDb()->fetchOne(
			'SELECT COUNT(*) FROM cf_auditlog_' . clearFusionCMS::getSite() . (count($where) ? ' WHERE ' . implode(' && ', $where) : ''),
			$params
		);
	}

	/**
	 * Get the records that match the query.
	 *
	 * @param int $uid The user id to search for or null for all.
	 * @param string $module The module to search for or null for all.
	 * @param int $start The start row.
	 * @param int $limit The number of rows to get.
	 * @return array The array of records found.
	 */
	static function find($uid, $module, $start, $limit) {
		$params = [];
		$where = [];

		if($uid !== null) {
			$where[] = 'uid=?';
			$params[] = $uid;
		}

		if($module !== null) {
			$where[] = 'module=?';
			$params[] = $module;
		}

		return clearFusionCMS::getDb()->fetchAll(
			'SELECT * FROM cf_auditlog_' . clearFusionCMS::getSite() . (count($where) ? ' WHERE ' . implode(' && ', $where) : '') . ' ORDER BY loggedat DESC LIMIT ' . $start . ', ' . $limit,
			$params);
	}

	/**
	 * Get the given audit record.
	 *
	 * @param int $id The ID of the record to get.
	 * @return array The record.
	 */
	static function getRecord($id) {
		return clearFusionCMS::getDb()->fetchRow('SELECT * FROM cf_auditlog_' . clearFusionCMS::getSite() . ' WHERE auditid=?', $id);
	}
}
