<?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
 * @copyright Copyright (c) 2012 - 2016 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * cfBackendContenttypesAction Class
 *
 * Action class to manage the content types within the system.
 *
 * @package clearFusionCMS
 */
class cfBackendContenttypesAction extends cfBackendControllerAction {
	/**
	 * Process the action.
	 */
	function process() {
		$this->testPermission('cfContent.types');
		$this->breadcrumbTrail->addCrumb(__('Content Types', 'cfBackend'), $this->assemble('', 'contenttypes'));

		// Get the role that we're currently editing
		$edType = $this->request->getParam('*');
		$delType = 0;
		$addType = false;
		if($edType !== null && count($edType) == 1 && preg_match('/^\d+$/', $edType[0]))
			$edType = $edType[0];
		else if($edType !== null && count($edType) == 2 && preg_match('/^\d+$/', $edType[0]) && $edType[1] == 'delete') {
			$delType = $edType[0];
			$edType = 0;
		}
		else if($edType !== null && count($edType) == 1 && $edType[0] == 'add') {
			$addType = true;
			$edType = 0;
		}
		else
			$edType = 0;

		$edmsg = $this->session->flashGet('cfManagerOpSuccess', '');

		if($addType) {
			// Build form for adding types
			$formAdd = new flForm($this->request, 'addtypeform', $this->assemble('', 'contenttypes', array('add')), true);

			$newName = new flFormElementText($formAdd, 'newtype');
			$newName->setLabel(__('Type Name', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(3))
				->addValidator(new flFormValidatorMaxLength(255));

			$newMime = new flFormElementText($formAdd, 'newmime');
			$newMime->setLabel(__('Mime Type', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(3))
				->addValidator(new flFormValidatorMaxLength(255));

			$newExt = new flFormElementText($formAdd, 'newext');
			$newExt->setLabel(__('File Extension', 'cfBackend'))
				->addValidator(new flFormValidatorMinLength(2))
				->addValidator(new flFormValidatorMaxLength(4))
				->addValidator(new flFormValidatorRegex('/^[a-z0-9]+$/', __('The file extension can only use letters a-z and numbers 0-9.', 'cfBackend')));

			$el = cfEditor::getAvailable(true);

			// Augment the editor names with their filters
			foreach($el as $ed => $n) {
				$filter = cfEditor::getFilter($ed);
				if(!empty($filter)) {
					$el[$ed] .= ' ' . sprintf(__('(Needs filter: %s)', 'cfBackend'), $filter);
				}
			}

			$editor = new flFormElementSelect($formAdd, 'editor', null, $el);
			$editor->setLabel(__('WYSIWYG Editor', 'cfBackend'));

			$newSnippet = new flFormElementText($formAdd, 'newsnippet');
			$newSnippet->setLabel(__('Filter Snippet', 'cfBackend'))
				->addValidator(new flFormValidatorMaxLength(64))
				->addValidator(new flFormValidatorRegex('/^[a-z0-9_.]+$/i', __('The snippet name can only contain the characters a-z, 0-9, _ and ..', 'cfBackend')))
				->setDescription(__('If given the name of the snippet called to pre-process the content. The content to process is passed to the snippet as the content parameter.', 'cfBackend'));

			$newGzip = new flFormElementCheckbox($formAdd, 'newgzip', true);
			$newGzip->setLabel(__('Compress Output', 'cfBackend'));

			$addSubmit = new flFormElementSubmit($formAdd, 'addtype');
			$addSubmit->setCaption(__('Add Content Type', 'cfBackend'))->setCSS('primary');

			$formAdd->focusElement($newName);

			$formAdd->groupElements('submit', array($addSubmit), new flFormDecoratorList(new flFormDecoratorDl()));

			if($formAdd->isSubmitted() && $formAdd->isValid()) {
				$id = 0;
				if($this->db->insert('cf_contenttype', array('typename' => $newName->getValue(), 'mimetype' => $newMime->getValue(), 'fileext' => $newExt->getValue(), 'gzip' => $newGzip->getValue(), 'snippet' => $newSnippet->getValue(), 'editor' => $editor->getValue()))) {
					$id = $this->db->insertID();
					cfCtntTypeAudit::created($id, $newName->getValue());
					$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The new content type has been added.', 'cfBackend')));
					$this->response->redirectTo($this->assemble('', 'contenttypes', array($id), true));
				}
				else
					$edmsg = $this->alertMessage('Error', __('Unable to create new content type.', 'cfBackend'));
			}

			$content = $this->renderBlock(__('Add Content Type', 'cfBackend'), $formAdd->render($this->tpl->getCodeBuffer()), '', $edmsg);

		}
		else if($edType) {
			$data = $this->db->fetchRow('SELECT * FROM cf_contenttype WHERE id=?', $edType);

			// Build the edit form
			$form = new flForm($this->request, 'edTypeform', $this->assemble('', 'contenttypes', array($edType)), true, null, new flFormDecoratorList(new flFormDecoratorDl()));

			$name = new flFormElementText($form, 'typename', $data['typename']);
			$name->setLabel(__('Type Name', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(3))
				->addValidator(new flFormValidatorMaxLength(255));

			$mime = new flFormElementText($form, 'mime', $data['mimetype']);
			$mime->setLabel(__('Mime Type', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(3))
				->addValidator(new flFormValidatorMaxLength(255));

			$ext = new flFormElementText($form, 'ext', $data['fileext']);
			$ext->setLabel(__('File Extension', 'cfBackend'))
				->addValidator(new flFormValidatorMinLength(2))
				->addValidator(new flFormValidatorMaxLength(4))
				->addValidator(new flFormValidatorRegex('/^[a-z0-9]+$/', __('The file extension can only use letters a-z and numbers 0-9.', 'cfBackend')));

			$el = cfEditor::getAvailable(true);

			// Augment the editor names with their filters
			foreach($el as $ed => $n) {
				$filter = cfEditor::getFilter($ed);
				if(!empty($filter)) {
					$el[$ed] .= ' ' . sprintf(__('(Needs filter: %s)', 'cfBackend'), $filter);
				}
			}

			$editor = new flFormElementSelect($form, 'editor', $data['editor'], $el);
			$editor->setLabel(__('Editor', 'cfBackend'));

			$snippet = new flFormElementText($form, 'snippet', $data['snippet']);
			$snippet->setLabel(__('Filter Snippet', 'cfBackend'))
				->addValidator(new flFormValidatorMaxLength(64))
				->addValidator(new flFormValidatorRegex('/^[a-z0-9_.]+$/i', __('The snippet name can only contain the characters a-z, 0-9, _ and ..', 'cfBackend')))
				->setDescription(__('If given the name of the snippet called to pre-process the content. The content to process is passed to the snippet as the content parameter.', 'cfBackend'));

			$gzip = new flFormElementCheckbox($form, 'gzip', $data['gzip']);
			$gzip->setLabel(__('Compress Output', 'cfBackend'));

			$submit = new flFormElementSubmit($form, 'updatetype');
			$submit->setCaption(__('Update Content Type', 'cfBackend'))->setCSS('primary');

			$delTypeSub = new flFormElementSubmit($form, 'deletetype');
			$delTypeSub->setCaption(__('Delete Content Type', 'cfBackend'))
				->setCSS('danger');

			$form->focusElement($name);

			$form->groupElements('submit', array($submit, $delTypeSub), new flFormDecoratorList(new flFormDecoratorDl()));

			if($form->isSubmitted() && $form->isValid()) {
				if($this->db->update('cf_contenttype', array('typename' => $name->getValue(), 'mimetype' => $mime->getValue(), 'fileext' => $ext->getValue(), 'gzip' => $gzip->getValue(), 'snippet' => $snippet->getValue(), 'editor' => $editor->getValue()), 'id=?', $edType)) {
					$edmsg = $this->alertMessage('Success', __('The content type has been updated.', 'cfBackend'));
					cfCtntTypeAudit::update($edType, $name->getValue(), $data);
				}
				else
					$edmsg = $this->alertMessage('Error', __('Unable to update the content type, please try again.', 'cfBackend'));

				if($delTypeSub->getValue())
					$this->response->redirectTo($this->assemble('', 'contenttypes', array($edType, 'delete')));
			}
		}
		else if($delType) {
			$data = $this->db->fetchRow('SELECT * FROM cf_contenttype WHERE id=?', $delType);

			$form = new flForm($this->request, 'delTypeform', $this->assemble('', 'contenttypes', array($delType, 'delete')), true);

			$name = new flFormElementText($form, 'typename', $data['typename']);
			$name->setLabel(__('Delete Content Type', 'cfBackend'))
				->setDisabled()
				->setReadonly();

			$delSubmit = new flFormElementSubmit($form, 'deletetype');
			$delSubmit->setCaption(__('Permanently Delete Content Type', 'cfBackend'))
				->setCSS('danger')
				->setDescription($this->alertMessage('Warning', __('This operation cannot be undone and will delete the content type permanently.', 'cfBackend')));

			if($form->isSubmitted() && $form->isValid()) {
				$sites = new cfSiteManager($this->db);
				$list = $sites->listSites();
				$count = 0;
				foreach($list as $site => $desc)
					$count += $this->db->fetchOne("SELECT COUNT(*) FROM cf_content_{$site} WHERE contenttype=?", $delType);

				if($count)
					$edmsg = $this->alertMessage('Error', __('Unable to delete the content type as it is in use by documents.', 'cfBackend'));
				else {
					$this->db->delete('cf_contenttype', 'id=?', $delType);
					cfCtntTypeAudit::delete($delType, $data['typename'], $data);
					$this->response->redirectTo($this->assemble('', 'contenttypes', array(), true));
				}
			}
		}

		$typeTree = new flWidgetTreeView();

		$result = $this->db->query('SELECT id,typename FROM cf_contenttype ORDER BY typename');
		while($row = $result->fetch()) {
			$typeTree->addNode(new flWidgetTreeLinkNode($row['typename'], $this->assemble('', 'contenttypes', array($row['id']))))
				->setLastNodeActive($row['id'] == $edType || $row['id'] == $delType);
		}

		$typeRootTree = new flWidgetTreeView();
		$typeRootTree->addNode(new flWidgetTreeChildNode(__('Content Types', 'cfBackend'), $typeTree, null));

		if($edType || $delType) {
			if(($content = $this->lockObject('cfContentTypes', $edType ? $edType : $delType, true)) === true)
				$content = $this->renderBlock($edType ? __('Edit Content Type', 'cfBackend') : __('Delete Content Type', 'cfBackend'), $form->render($this->tpl->getCodeBuffer()), '', $edmsg);
		}
		else if(!$addType)
			$content = '';

		// Build floating action menu
		$fam = new flWidgetFloatingActionMenu();
		$fam->setCSS('[[+css]]')
			->addAction('add', __('Add Content Type', 'cfBackend'), $this->assemble('', 'contenttypes', array('add')));

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

		$this->renderPage(__('Content Types', 'cfBackend'), $content, $this->renderBlock(__('Content Types', 'cfBackend'), $typeRootTree->render()));
	}
}
