<?php

/**
 * Class file for audit log visualization action.
 *
 * 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
 */

/**
 * cfBackendAuditAction Class
 *
 * Action class to list and search for users in the system.
 *
 * @package clearFusionCMS
 */
class cfBackendAuditAction extends cfBackendControllerAction {

	/**
	 * Process the action.
	 */
	function process() {
		$this->testPermission('core.audit');
		$this->breadcrumbTrail->addCrumb(__('Audit Log', 'cfBackend'), $this->assemble('', 'audit'));

		$userMgr = clearFusionCMS::getUserMgr();
		$content = '';
		$pagination = null;

		$data = $this->session->flashGet('cfManager.audit.search');
		$this->session->flashKeep('cfManager.audit.search');

		// Build the list of modules we can search in
		$mm = new flModuleMgr($this->db);
		$modules = [
			'cfElement' => __('Elements', 'cfBackend'),
			'cfModule' => __('Modules', 'cfBackend'),
			'cfFile' => __('Files', 'cfBackend'),
			'cfUser' => __('Users', 'cfBackend'),
			'cfTheme' => __('Themes', 'cfBackend'),
			'cfApiKey' => __('API Keys', 'cfBackend'),
			'cfSite' => __('Site', 'cfBackend'),
			'cfSettings' => __('Settings', 'cfBackend')
		];
		$installed = $mm->getInstalled();
		foreach($installed as $mod => $ver) {
			try {
				class_exists($mod . 'AuditHelper');
				if($mod == 'content') {
					$modules[$mod] = __('Documents', 'cfBackend');
				} else {
					$info = $mm->getInfo($mod);
					$modules[$mod] = $info->name;
				}
			} catch(Exception $e) {
			}
		}
		asort($modules);
		$modules = array_merge(['' => __('All', 'cfBackend')], $modules);

		// Build the search form
		$form = new flForm($this->request, 'searchform', $this->assemble('', 'audit'), true);

		$user = new flFormElementText($form, 'searchuser', $data === null ? null : $data['user']);
		$user->setLabel(__('Search For User', 'cfBackend'));

		$searchin = new flFormElementSelect($form, 'searchin', $data === null ? null : $data['in'], $modules);
		$searchin->setLabel(__('Search for Module', 'cfBackend'));

		$submit = new flFormElementSubmit($form, 'Search');
		$submit->setCaption(__('Search', 'cfBackend'))->setCSS('primary');

		$form->focusElement($user);

		// If viewing a specific record
		$viewRoute = new flRouterRoute('view/:id', array(), array('id' => '\d+'));
		if ($params = $viewRoute->match($this->request->getParam('*', array()))) {
			$this->breadcrumbTrail->addCrumb(__('Details', 'cfBackend'), $this->assemble('', 'audit', [ $params['id'] ]));

			$row = cfAudit::getRecord($params['id']);
			$viewForm = new flForm($this->request, 'viewform', $this->assemble('', 'audit'), true);

			$cls = $row['module'] . 'AuditHelper';
			try {
				$helper = new $cls();
			} catch(Exception $e) {
				$helper = new cfAuditHelper();
			}


			$userInfo = $userMgr->getInfo($row['uid']);
			$f = new flDate($row['loggedat'] . ' UTC', clearFusionCMS::getSysTimezone());

			$msg = new flFormElementPane($viewForm, 'msg', $helper->getMessage($row));
			$msg->setLabel($userInfo['username'])
				->setDescription($f->toString('%d %M %Y %H:%i:%s %O'));

			$prev = cfEditor::create(
				$this->getCodeEditorModule(),
				$viewForm,
				'previous',
				$helper->printData($row)
			);
			$prev->setLabel(__('Previous Data', 'formsBackend'))
				->setReadonly()
				->editorContentType('textwrap');

			$module = new flFormElementText($viewForm, 'code', $row['action']);
			$module->setLabel(__('Code', 'cfBackend'))
				->setReadonly();

			$module = new flFormElementText($viewForm, 'module', $row['module']);
			$module->setLabel(__('Module', 'cfBackend'))
				->setReadonly();

			$cid = new flFormElementText($viewForm, 'contentid', $row['cid']);
			$cid->setLabel(__('Content ID', 'cfBackend'))
				->setReadonly();

			$ip = new flFormElementText($viewForm, 'ip', $row['ip']);
			$ip->setLabel(__('IP Address', 'cfBackend'))
				->setReadonly();

			$content = $viewForm->render($this->tpl->getCodeBuffer());
		}
		else {

			// Get the page that we're currently on
			$onPage = $this->request->getParam('*');
			if($onPage !== null && count($onPage) == 1 && preg_match('/^\d+$/', $onPage[0]))
				$onPage = $onPage[0];
			else
				$onPage = 0;

			if($form->isSubmitted() && $form->isValid()) {
				$this->session->flashSet('cfManager.audit.search', $data = array(
					'user' => $user->getValue(),
					'in' => $searchin->getValue() == '' ? null : $searchin->getValue()
				));
				$onPage = 0;
			}

			// Look up search data
			$uid = $module = null;
			if($data) {
				if(!empty($data['user'])) {
					$users = $userMgr->find($data['user'], ['email', 'username'], true);
					$uid = count($users) ? $users[0] : 0;
				}
				$module = $data['in'];
			}

			$pagination = new flWidgetPagination(
				$onPage,
				$found = cfAudit::numMatches($uid, $module)
			);
			$pagination->setRoute($this->router->getRoute('cfManager'), array('action' => 'audit'), '*');
			$results = cfAudit::find($uid, $module, $pagination->getStart(), $pagination->getRows());

			if(count($results)) {
				$table = new flWidgetTable();
				$table->setClass('tablewidget bordered striped rowhover responsive auditlog')
					->setHeadings(__('Code', 'cfBackend'), __('Date', 'cfBackend'), __('Username', 'cfBackend'), __('Source IP', 'cfBackend'), __('Message', 'cfBackend'), '')
					->setColData('action', 'loggedat', 'username', 'ip', 'msg', 'ops')
					->skipEncode('ops', 'loggedat', 'msg');

				$helpers = [];

				foreach($results as $row) {
					$userInfo = $userMgr->getInfo($row['uid']);
					$row['username'] = $userInfo['username'];

					$f = new flDate($row['loggedat'] . ' UTC', clearFusionCMS::getSysTimezone());
					$row['loggedat'] = $f->toString('%d %M %Y<br />%H:%i:%s %O');

					if(!isset($helpers[$row['module']])) {
						$cls = $row['module'] . 'AuditHelper';
						try {
							$helpers[$module] = new $cls();
						} catch(Exception $e) {
							$helpers[$module] = new cfAuditHelper();
						}
					}

					$row['msg'] = str_replace('[', '&#91;', $helpers[$module]->getMessage($row));

					if($helpers[$module]->hasAdditionalData($row)) {
						$row['ops'] = "<a href=\"" . $this->assemble('', 'audit', array('view', '*' => $row['auditid'])) . "\">" . __('View', 'cfBackend') . "</a>";
					}
					else {
						$row['ops'] = '';
					}

					$table->addRow($row);
				}

				$content = $table->render();
			}

			$content .= '<p>' . sprintf(__('Found: %d records', 'cfBackend'), $found) . '</p>';
		}

		$this->renderPage(
			__('Audit Log', 'cfBackend'),
			$this->renderBlock(__('Audit Log', 'cfBackend'), $content, '', '', $pagination ? $pagination->render() : null),
			$this->renderBlock('', $form->render($this->tpl->getCodeBuffer()))
		);
	}
}
