<?php

/**
 * 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\module\comments
 * @copyright Copyright (c) 2013 - 2017 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * commentsBackendController Class
 *
 * Backend controller for editing managing comments.
 *
 * @package clearFusionCMS\module\comments
 */
class commentsBackendController extends cfBackendController {

	/**
	 * Render the page.
	 *
	 * @param string $content The page content.
	 * @param int $active The ID of the active comment.
	 */
	function renderAdminPage($content, $active = 0) {

		// Create FAM
		$fam = new flWidgetFloatingActionMenu();
		$fam->addAction('add', __('Add Comment', 'commentsBackend'), $this->assemble('comments', 'add'));

		$this->tpl->registerChunk('fam', $fam->render());

		$rootTree = new flWidgetTreeView();

		// Build tree of unpublished comments
		$tree = new flWidgetTreeView();
		$results = $this->db->query('SELECT id,author FROM cf_comments_' . clearFusionCMS::getSite() . ' WHERE !published ORDER BY commentdate DESC LIMIT 100');
		while($row = $results->fetch()) {
			$tree->addNode(new flWidgetTreeLinkNode($row['author'], $this->assemble('comments', 'edit', array($row['id'])), flWidgetTreeNode::DOC))
				->setLastNodeActive($row['id'] == $active);
		}

		$rootTree->addNode($results->numRows() ? new flWidgetTreeChildNode(__('Unpublished Comments', 'commentsBackend'), $tree, null) : new flWidgetTreeNode(__('Unpublished Comments', 'commentsBackend'), flWidgetTreeNode::CONTAINER));

		// Render the page
		$this->renderPage(__('Comments', 'commentsBackend'), $content, $this->renderBlock('', $rootTree->render($this->tpl->getCodeBuffer())));
	}

	/**
	 * Dashboard action.
	 */
	function dashboardAction() {
		$this->testPermission('cfComments.post');
		$this->breadcrumbTrail->addCrumb(__('Comments', 'commentsBackend'), $this->assemble('comments', 'dashboard'));

		$content = '';

		// Router to build pagination with
		$paginationRoute = new flRouterRoute(str_replace(array(':module', ':action', '*'), array('comments', 'dashboard', ':page'), (string)$this->router->getRoute('cfManagerModule')), array('page' => '0'), array('page' => '\d+'), $this->request);
		$route = new flRouterRoute(':page', array('page' => '0'), array('page' => '\d+'));
		if($params = $route->match($this->request->getParam('*', array()))) {

			$numItems = $this->db->fetchOne('SELECT COUNT(*) FROM cf_comments_' . clearFusionCMS::getSite());
			$pagination = new flWidgetPagination($params['page'], $numItems, 10);
			$pagination->setRoute($paginationRoute, array(), 'page');

			$results = $this->db->fetchAll('SELECT * FROM cf_comments_' . clearFusionCMS::getSite() . ' ORDER BY commentdate DESC LIMIT ' . $pagination->getStart() . ',' . $pagination->getRows());
			if(count($results)) {
				$table = new flWidgetTable();
				$table->setClass('tablewidget bordered striped rowhover responsive')
					->setHeadings(__('ID', 'commentsBackend'), __('Author', 'commentsBackend'), __('Comment', 'commentsBackend'), __('In Response To', 'commentsBackend'), __('Operation', 'commentsBackend'))
					->setColData('id', 'author', 'comment', 'responseto', 'ops')
					->skipEncode('ops', 'author', 'comment', 'responseto');

				$modMgr = new flModuleMgr($this->db);
				foreach($results as $item) {
					$item['author'] .= '<br /> ' . $item['email'] . '<br /><img src="system/modules/comments/images/stars' . $item['rating'] . '.png" alt="' . $item['rating'] . '" />';
					$item['responseto'] = '';
					if($helper = cfSearchHelper::getHelper($item['modulename'])) {
						if($info = $helper->getSearchSummary($item['contentid'])) {
							if($item['modulename'] == 'content')
								$minfo =  __('Document', 'commentsBackend');
							else {
								$minfo = $modMgr->getInfo($item['modulename']);
								$minfo = $minfo->name;
							}
							$item['responseto'] = $minfo . '<br /> ' . $info['title'] . '<br /> ';
						}
					}

					$t = new flDate($item['commentdate'] . ' UTC', clearFusionCMS::getSysTimezone());
					$item['responseto'] .= $t->toString(flDate::DATE);
					$item['ops'] = "<a href=\"" . $this->assemble('comments', 'edit', array($item['id'])) . "\">" . __('Edit', 'commentsBackend') . "</a>";
					$item['comment'] = nl2br(fusionLib::htmlChars($item['content']));
					$table->addRow($item);
				}

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

			$content .= sprintf(__("<p>Found: %d comments.</p>", 'commentsBackend'), $numItems);

			$this->renderAdminPage($this->renderBlock(__('Existing Comments', 'commentsBackend'), $content, '', '', $pagination->render()));
		}
		else
			$this->response->redirectTo($this->assemble('comments', 'dashboard', array(), true));
	}

	/**
	 * Add comment action.
	 */
	function addAction() {
		$this->testPermission('cfComments.post');
		$this->breadcrumbTrail->addCrumb(__('Comments', 'commentsBackend'), $this->assemble('comments', 'dashboard'));
		$this->breadcrumbTrail->addCrumb(__('Add Comment', 'commentsBackend'), $this->assemble('comments', 'add'));

		$form = new flForm($this->request, 'contentform', $this->assemble('comments', 'add'), true);
		$form->setCSS('metaSSubmit');

		// Get available modules
		$modMgr = new flModuleMgr($this->db);
		$m = array();
		foreach($modMgr->getInstalled() as $n => $v) {
			if($n == 'content')
				$m[$n] =  __('Document', 'commentsBackend');
			else {
				$info = $modMgr->getInfo($n);
				$m[$n] = $info->name;
			}
		}
		$module = new flFormElementSelect($form, 'modname', '', $m);
		$module->setLabel(__('Module', 'commentsBackend'));

		$contentId = new flFormElementInteger($form, 'contentid', 0);
		$contentId->setLabel(__('Content ID', 'commentsBackend'))
			->setRequired()
			->addValidator(new flFormValidatorRequired())
			->setDescription('&nbsp;');

		$rating = new flFormElementSelect($form, 'rating', 3, array(
			1 => __('1 - Worst', 'commentsBackend'),
			2 => __('2', 'commentsBackend'),
			3 => __('3', 'commentsBackend'),
			4 => __('4', 'commentsBackend'),
			5 => __('5 - Best', 'commentsBackend')
		));
		$rating->setLabel(__('Content Rating', 'commentsBackend'));

		$name = new flFormElementText($form, 'name');
		$name->setLabel(__('Name', 'commentsBackend'))
			->setDescription(__('Name of author', 'commentsBackend'))
			->setRequired()
			->addValidator(new flFormValidatorRequired())
			->addValidator(new flFormValidatorMaxLength(255));

		$email = new flFormElementEmail($form, 'email');
		$email->setLabel(__('Email', 'commentsBackend'))
			->setRequired()
			->addValidator(new flFormValidatorRequired())
			->addValidator(new flFormValidatorMaxLength(255));

		// Capture ctrl+s for save
		$this->tpl->getCodeBuffer()->bufferHeadJS('system/app/js/cfMetaS.js');
		$this->confirmLeavePage();

		$ctnt = cfEditor::create(
			$this->getCodeEditorModule(),
			$form,
			'content',
			null
		);
		$ctnt->setLabel(__('Comment', 'commentsBackend'))
			->setRequired()
			->addValidator(new flFormValidatorRequired())
			->addValidator(new flFormValidatorMaxLength(2097152))
			->editorContentType('textwrap');

		$_cmntDate = new flDate(null, clearFusionCMS::getSysTimezone());
		$tz = flDateTzMenu::get();
		$cmntDate = new flFormElementText($form, 'cmntdate', $_cmntDate->toString(flDate::DATETIMESHORT));
		$cmntDate->setLabel(__('Date of Comment (year-month-day hh:mm)', 'commentsBackend'))
			->setRequired()
			->setDescription($this->alertMessage('Info', sprintf(__('All dates are %s.', 'commentsBackend'), $tz[clearFusionCMS::getSysTimezone()])))
			->addValidator(new flFormValidatorRequired())
			->addValidator(new flFormValidatorRegex('/^\d{4}-(0?[0-9]|1[0-2])-\d{1,2} \d{1,2}:\d{1,2}$/', __('The date must be in the form yyyy-mm-dd hh:mm.', 'commentsBackend')));

		$publish = new flFormElementCheckbox($form, 'publish', 1);
		$publish->setLabel(__('Publish Comment', 'commentsBackend'));

		$submit = new flFormElementSubmit($form, 'create');
		$submit->setCaption(__('Create Comment', 'commentsBackend'))->setCSS('primary');

		$form->groupElements('content1', array($name, $email, $module, $contentId))
			->groupElements('content2', array($rating, $cmntDate, $publish))
			->groupElements('content', array($ctnt))
			->groupElements('submit', array($submit), new flFormDecoratorList(new flFormDecoratorDl()));

		$form->focusElement($name);

		$ajaxTgt = $this->assemble('comments', 'lookup');
		$this->tpl->getCodeBuffer()->bufferReadyJS("
	function updateCtntInfo(module, id) {
		\$fl.post('$ajaxTgt', {
			m: module,
			i: id
		}, function(d) {
			\$fl('#contentid-desc').html(d);
		});
	}

	\$fl('#modname').bind('change', function(event) {
		updateCtntInfo(\$fl(this).val(), \$fl('#contentid').val());
	});

	\$fl('#contentid').bind('change', function(event) {
		updateCtntInfo(\$fl('#modname').val(), \$fl(this).val());
	}).bind('keyup', function(event) {
		updateCtntInfo(\$fl('#modname').val(), \$fl(this).val());
	});
");

		$msg = '';
		if($form->isSubmitted() && $form->isValid()) {
			// Convert the dates to UTC
			$_cmntDate = new flDate($cmntDate->getValue(), clearFusionCMS::getSysTimezone());
			$_cmntDate->setTimezone('UTC');

			// Create testimonial
			if($this->db->insert('cf_comments_' . clearFusionCMS::getSite(), $d = array(
				'commentdate' => $_cmntDate->toString(),
				'rating' => $rating->getValue(),
				'published' => $publish->getValue(),
				'contentid' => $contentId->getValue(),
				'modulename' => $module->getValue(),
				'author' => $name->getValue(),
				'email' => $email->getValue(),
				'content' => $ctnt->getCleanedValue()
			))) {
				$id = $this->db->insertID();

				commentsAudit::create($id, $name->getValue());

				// If published flush cache
				if($publish->getValue())
					$this->cache->flush();

				$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The new comment has been created.', 'commentsBackend')));
				$this->response->redirectTo($this->assemble('comments', 'edit', array($id), true));
			}
			else
				$msg = $this->alertMessage('Error', __('Unable to create the comment, please try again.', 'commentsBackend'));
		}

		$content = $this->renderBlock(__('Add Comment', 'commentsBackend'), $form->render($this->tpl->getCodeBuffer()), '', $msg);

		$this->renderAdminPage($content);
	}

	/**
	 * Edit comment action.
	 */
	function editAction() {
		$this->testPermission('cfComments.post');
		$this->breadcrumbTrail->addCrumb(__('Comments', 'commentsBackend'), $this->assemble('comments', 'dashboard'));
		$this->breadcrumbTrail->addCrumb(__('Edit Comment', 'commentsBackend'), $this->assemble('comments', 'edit'));

		$msg = $this->session->flashGet('cfManagerOpSuccess') ? $this->session->flashGet('cfManagerOpSuccess') : '';

		$route = new flRouterRoute(':id', array(), array('id' => '\d+'));
		if($params = $route->match($this->request->getParam('*', array()))) {
			if(($content = $this->lockObject('comments', $params['id'])) === true && ($data = $this->db->fetchRow('SELECT * FROM cf_comments_' . clearFusionCMS::getSite() . ' WHERE id=?', $params['id']))) {

				$form = new flForm($this->request, 'contentform', $this->assemble('comments', 'edit', array($params['id'])), true);
				$form->setCSS('metaSSubmit');

				// Get available modules
				$modMgr = new flModuleMgr($this->db);
				$m = array();
				foreach($modMgr->getInstalled() as $n => $v) {
					if($n == 'content')
						$m[$n] =  __('Document', 'commentsBackend');
					else {
						$info = $modMgr->getInfo($n);
						$m[$n] = $info->name;
					}
				}
				$module = new flFormElementSelect($form, 'modname', $data['modulename'], $m);
				$module->setLabel(__('Module', 'commentsBackend'));

				$contentId = new flFormElementInteger($form, 'contentid', 0, null, $data['contentid']);
				$contentId->setLabel(__('Content ID', 'commentsBackend'))
					->setRequired()
					->addValidator(new flFormValidatorRequired())
					->setDescription('&nbsp;');

				if($helper = cfSearchHelper::getHelper($data['modulename'])) {
					if($info = $helper->getSearchSummary($data['contentid']))
						$contentId->setDescription($info['title']);
				}

				$rating = new flFormElementSelect($form, 'rating', $data['rating'], array(
					1 => __('1 - Worst', 'commentsBackend'),
					2 => __('2', 'commentsBackend'),
					3 => __('3', 'commentsBackend'),
					4 => __('4', 'commentsBackend'),
					5 => __('5 - Best', 'commentsBackend')
				));
				$rating->setLabel(__('Content Rating', 'commentsBackend'));

				$name = new flFormElementText($form, 'name', $data['author']);
				$name->setLabel(__('Name', 'commentsBackend'))
					->setDescription(__('Name of author', 'commentsBackend'))
					->setRequired()
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMaxLength(255));

				$email = new flFormElementEmail($form, 'email', $data['email']);
				$email->setLabel(__('Email', 'commentsBackend'))
					->setRequired()
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMaxLength(255));

				// Capture ctrl+s for save
				$this->tpl->getCodeBuffer()->bufferHeadJS('system/app/js/cfMetaS.js');
				$this->confirmLeavePage();

				$ctnt = cfEditor::create(
					$this->getCodeEditorModule(),
					$form,
					'content',
					$data['content']
				);
				$ctnt->setLabel(__('Comment', 'commentsBackend'))
					->setRequired()
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMaxLength(2097152))
					->editorContentType('textwrap');

				$_cmntDate = new flDate($data['commentdate'] . ' UTC', clearFusionCMS::getSysTimezone());
				$tz = flDateTzMenu::get();
				$cmntDate = new flFormElementText($form, 'cmntdate', $_cmntDate->toString(flDate::DATETIMESHORT));
				$cmntDate->setLabel(__('Date of Comment (year-month-day hh:mm)', 'commentsBackend'))
					->setRequired()
					->setDescription($this->alertMessage('Info', sprintf(__('All dates are %s.', 'commentsBackend'), $tz[clearFusionCMS::getSysTimezone()])))
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorRegex('/^\d{4}-(0?[0-9]|1[0-2])-\d{1,2} \d{1,2}:\d{1,2}$/', __('The date must be in the form yyyy-mm-dd hh:mm.', 'commentsBackend')));

				$publish = new flFormElementCheckbox($form, 'publish', $data['published']);
				$publish->setLabel(__('Publish Comment', 'commentsBackend'));

				$submit = new flFormElementSubmit($form, 'update');
				$submit->setCaption(__('Update Comment', 'commentsBackend'))->setCSS('primary');

				$del = new flFormElementSubmit($form, 'delete');
				$del->setCaption(__('Delete Comment', 'commentsBackend'))
					->setCSS('danger');

				$form->groupElements('content1', array($name, $email, $module, $contentId))
					->groupElements('content2', array($rating, $cmntDate, $publish))
					->groupElements('content', array($ctnt))
					->groupElements('submit', array($submit, $del), new flFormDecoratorList(new flFormDecoratorDl()));

				$form->focusElement($name);

				$ajaxTgt = $this->assemble('comments', 'lookup');
				$this->tpl->getCodeBuffer()->bufferReadyJS("
	function updateCtntInfo(module, id) {
		\$fl.post('$ajaxTgt', {
			m: module,
			i: id
		}, function(d) {
			\$fl('#contentid-desc').html(d);
		});
	}

	\$fl('#modname').bind('change', function(event) {
		updateCtntInfo(\$fl(this).val(), \$fl('#contentid').val());
	});

	\$fl('#contentid').bind('change', function(event) {
		updateCtntInfo(\$fl('#modname').val(), \$fl(this).val());
	}).bind('keyup', function(event) {
		updateCtntInfo(\$fl('#modname').val(), \$fl(this).val());
	});
");

				if($form->isSubmitted() && $form->isValid()) {

					// Convert the dates to UTC
					$_cmntDate = new flDate($cmntDate->getValue(), clearFusionCMS::getSysTimezone());
					$_cmntDate->setTimezone('UTC');

					if($del->getValue())
						$this->response->redirectTo($this->assemble('comments', 'delete', array($params['id']), true));

					// Make update data
					$d = array(
						'commentdate' => $_cmntDate->toString(),
						'rating' => $rating->getValue(),
						'published' => $publish->getValue(),
						'contentid' => $contentId->getValue(),
						'modulename' => $module->getValue(),
						'author' => $name->getValue(),
						'email' => $email->getValue(),
						'content' => $ctnt->getCleanedValue()
					);

					// Update the news item
					if($this->db->update('cf_comments_' . clearFusionCMS::getSite(), $d, 'id=?', $params['id'])) {
						commentsAudit::update($params['id'], $name->getValue(), $data);

						$this->cache->flush();

						$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The comment has been updated.', 'commentsBackend')));
						$this->response->redirectTo($this->assemble('comments', 'edit', array($params['id']), true));
					}
					else
						$msg = $this->alertMessage('Error', __('Unable to update the comment, please try again.', 'commentsBackend'));
				}

				$content = $this->renderBlock(__('Edit Comment', 'commentsBackend'), $form->render($this->tpl->getCodeBuffer()), '', $msg);
			}

			$this->renderAdminPage($content, $params['id']);
		}
		else
			$this->response->redirectTo($this->assemble('testimonials', 'dashboard', array(), true));
	}

	/**
	 * Action for deleting a comment.
	 */
	function deleteAction() {
		$this->testPermission('cfComments.post');
		$this->breadcrumbTrail->addCrumb(__('Comments', 'commentsBackend'), $this->assemble('comments', 'dashboard'));
		$this->breadcrumbTrail->addCrumb(__('Delete Comment', 'commentsBackend'), $this->assemble('comments', 'delete'));

		$route = new flRouterRoute(':id', array(), array('id' => '\d+'));
		if($params = $route->match($this->request->getParam('*', array()))) {

			if(($content = $this->lockObject('comments', $params['id'])) === true && ($data = $this->db->fetchRow('SELECT * FROM cf_comments_' . clearFusionCMS::getSite() . ' WHERE id=?', $params['id']))) {
				$form = new flForm($this->request, 'deleteform', $this->assemble('comments', 'delete', array($params['id'])), true);

				$name = new flFormElementText($form, 'name', $data['author']);
				$name->setLabel(__('Delete Comment', 'commentsBackend'))
					->setDisabled()
					->setReadonly();

				$delSubmit = new flFormElementSubmit($form, 'deletesubmit');
				$delSubmit->setCaption(__('Permanently Delete The Comment', 'commentsBackend'))
					->setCSS('danger')
					->setDescription($this->alertMessage('Warning', __('This operation cannot be undone and will delete the comment permanently.', 'commentsBackend')));

				$msg = '';
				if($form->isSubmitted() && $form->isValid()) {
					$this->db->delete('cf_comments_' . clearFusionCMS::getSite(), 'id=?', $params['id']);
					commentsAudit::delete($params['id'], $data);

					$this->cache->flush();
					$this->response->redirectTo($this->assemble('comments', 'dashboard', array(), true));
				}

				$content = $this->renderBlock(__('Delete Comment', 'commentsBackend'), $form->render($this->tpl->getCodeBuffer()), '', $msg);
			}

			$this->renderAdminPage($content, $params['id']);
		}
		else
			$this->response->redirectTo($this->assemble('comments', 'dashboard', array(), true));
	}

	/**
	 * Action for looking up content.
	 */
	function lookupAction() {
		$this->testPermission('cfComments.post');

		$title = '&nbsp;';
		if($helper = cfSearchHelper::getHelper($this->request->getPost('m', ''))) {
			if($info = $helper->getSearchSummary($this->request->getPost('i', '0')))
				$title = $info['title'];
		}

		$this->response->noCache()
			->setContentType('text/plain')
			->setBody($title)
			->sendResponse();
		die;
	}
}
