<?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 - 2017 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * cfBackendDocumentsAction Class
 *
 * Action class for creating and managing site documents.
 *
 * @package clearFusionCMS
 */
class cfBackendDocumentsAction extends cfBackendControllerAction {

	/**
	 * The content access object.
	 *
	 * @var cfContent
	 */
	protected $content;

	/**
	 * Recursive function to build a tree of the folders.
	 *
	 * @param string $base The path base.
	 * @param string $path The path to build the tree for.
	 * @param string $rootText The text for the root node.
	 * @return flWidgetTreeNode The built tree.
	 */
	function buildFolderTree($base, $path, $rootText = '') {
		if($base === null) $base = $path;

		$displayPath = substr($path, strlen($base) + 1);
		if(empty($displayPath))
			$displayPath = $rootText;

		$folders = glob($path . '/*', GLOB_ONLYDIR);
		$files = array_diff(glob($path . '/*'), $folders);
		if(empty($folders) && empty($files))
			$node = new flWidgetTreeNode($displayPath, flWidgetTreeNode::CONTAINER);
		else {
			$tree = new flWidgetTreeView();
			foreach($folders as $fpath)
				$tree->addNode($this->buildFolderTree($path, $fpath));

			foreach($files as $file) {
				if(preg_match('/\.(png|gif|jpg)$/', $file))
					$nodeType = flWidgetTreeNode::IMAGE;
				else if(preg_match('/\.(css)$/', $file))
					$nodeType = flWidgetTreeNode::CSS;
				else if(preg_match('/\.(js)$/', $file))
					$nodeType = flWidgetTreeNode::JS;
				else if(preg_match('/\.(php)$/', $file))
					$nodeType = flWidgetTreeNode::PHP;
				else if(preg_match('/\.(avi|mp4|mpg|mpeg|mov)$/', $file))
					$nodeType = flWidgetTreeNode::VIDEO;
				else if(preg_match('/\.(mp3)$/', $file))
					$nodeType = flWidgetTreeNode::SOUND;
				else
					$nodeType = flWidgetTreeNode::DOC;

				$tree->addNode(new flWidgetTreeLinkNode(substr($file, strlen($path) + 1), '#' .$file, $nodeType));
			}

			$node = new flWidgetTreeChildNode($displayPath, $tree, false);
		}

		return $node;
	}

	/**
	 * Build and process the form for adding/editing documents.
	 *
	 * @param int $node The node to edit/add under.
	 * @param bool $edit true if editing or false to add a new node.
	 * @param string $type The resource type.
	 * @return string The content to output.
	 */
	function processForm($node, $edit, $type = 'doc') {
		$fields = new cfCustomFields($this->db);
		$tplMgr = new flTemplateManager($this->db);
		$cfg = clearFusionCMS::getSiteConfig('cfSystemCtntEdit');
		$hasDraft = false;

		if($edit) {
			$data = $this->content->getNodeData($node, array('issearchable', 'noeditor', 'contenttype', 'published', 'menuhide', 'publishedat', 'lastupdated', 'restype', 'cachetime', 'asattachment', 'accessperm', 'editperm', 'title', 'subtitle', 'meta_title', 'meta_description', 'meta_keywords', 'menutitle', 'summary', 'content', 'slug', 'template', 'draft', 'container', 'ogtitle', 'ogdesc', 'twittertitle', 'twitterdesc', 'ogimageid', 'twitterimageid'));
			if(!$data) {
				$this->response->redirectTo($this->assemble('', 'documents', [], true));
			}
			$currentSlug = $data['slug'];
			$currentContentType = $data['contenttype'];

			// If has draft
			if(!empty($data['draft'])) {
				$hasDraft = true;
				$data = unserialize($data['draft']);
			}
			else
				$data['customfields'] = $fields->loadFields($node, clearFusionCMS::getSite());
		}
		else {
			if(!($parentData = $this->content->getNodeData($node, array('title', 'template')))) {
				$parentData['title'] = __('Root', 'cfBackend');
				$parentData['template'] = $cfg->defTemplate;
			}
			else if($parentData['template'] == '')
				$parentData['template'] = $cfg->defTemplate;
			$data = array('customfields' => array(), 'issearchable' => $type == 'link' || $type == 'folder' ? '0' : '1', 'noeditor' => '0', 'cachetime' => '0', 'contenttype' => $cfg->defContentType, 'publishedat' => null, 'published' => $this->user->hasPermission('cfContent.canpublish'), 'menuhide' => '0', 'restype' => $type, 'asattachment' => '0', 'accessperm' => '', 'editperm' => '', 'title' => '', 'subtitle' => '', 'meta_title' => '', 'meta_description' => '', 'meta_keywords' => '', 'menutitle' => '', 'summary' => '', 'content' => '', 'slug' => '', 'template' => $parentData['template'], 'draft' => '', 'container' => '', 'ogtitle' => '', 'ogdesc' => '', 'twittertitle' => '', 'twitterdesc' => '', 'ogimageid' => '0', 'twitterimageid' => '0');

			// If static and a previous type selected, reuse
			if($type == 'static' && isset($this->managerSession->staticContentType))
				$data['contenttype'] = $this->managerSession->staticContentType;

			if($type == 'folder')
				$data['menuhide'] = 1;
		}

		switch($data['restype']) {
			case 'link': $typeText = __('Link', 'cfBackend'); break;
			case 'folder': $typeText = __('Folder', 'cfBackend'); break;
			case 'static': $typeText = __('Static Resource', 'cfBackend'); break;
			default: $typeText = __('Document', 'cfBackend'); break;
		}
		$blkTitle = $edit ? "$typeText: $data[title]" : sprintf(__('Create %1$s Under: %2$s', 'cfBackend'), $typeText, $parentData['title']);

		$msg = $this->session->flashGet('cfManagerOpSuccess', '');
		$form = new flForm($this->request, 'contentform', $this->assemble('', 'documents', $edit ? array($node) : array('add', $node, $data['restype'])), true);
		$form->setCSS('metaSSubmit');

		if($this->user->hasPermission($this->content->getEditPermissions($node))) {

			$title = new flFormElementText($form, 'title', $data['title']);
			$title->setLabel(__('Title', 'cfBackend'))
				->setDescription(__('The title of this document, &#91;&#91;+title&#93;&#93;', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(2))
				->addValidator(new flFormValidatorMaxLength(255));

			if($data['restype'] == 'doc') {
				$subtitle = new flFormElementText($form, 'subtitle', isset($data['subtitle']) ? $data['subtitle'] : '');
				$subtitle->setLabel(__('Subtitle', 'cfBackend'))
					->setDescription(__('The subtitle of this document, &#91;&#91;+subtitle&#93;&#93;', 'cfBackend'))
					->addValidator(new flFormValidatorMinLength(2))
					->addValidator(new flFormValidatorMaxLength(255));
			}
			else
				$subtitle = new flFormElementHidden($form, 'subtitle', '');

			// Get the parent ID and the path to this document
			$parentId = $edit ? $this->content->getParent($node) : $node;
			$docPath = '';
			if($parentId !== false) {
				if(($t = $this->content->getPath($parentId, array('slug'))) !== false) {
					foreach($t as $n)
						$docPath .= "$n[slug]/";
					$docPath = $this->request->getBaseUri(false) . $docPath;
				}
			}

			// Content type
			$mimeTypes = array();
			$ct = array();
			$idtoext = array();
			$fileExt = array();
			$editorName = array();
			$result = $this->db->query('SELECT id,typename,mimetype,fileext,editor FROM cf_contenttype ORDER BY typename');
			while($row = $result->fetch()) {
				$mimeTypes[$row['id']] = $row['mimetype'];
				$ct[$row['id']] = $row['typename'];
				$fileExt[$row['id']] = $row['fileext'];
				$idtoext[] = $row['id'] . ": '" . (empty($row['fileext']) ? '/' : '.' . $row['fileext']) . "'";
				$editorName[$row['id']] = $row['editor'];
			}
			$contType = new flFormElementSelect($form, 'contenttype', $data['contenttype'], $ct);
			$contType->setLabel(__('Content Type', 'cfBackend'));

			$slug = new flFormElementText($form, 'slug', $data['slug']);
			$slug->setLabel(__('Slug', 'cfBackend'))
				->setDescription('<span id="slugview"></span>')
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(2))
				->addValidator(new flFormValidatorMaxLength(255))
				->addValidator(new flFormValidatorRegex('/^[a-z0-9_-]+$/', __('The slug may only contain letters a to z, numbers 0 to 9, _ and -.', 'cfBackend')))
				->addValidator(new cfValidatorPageSlug($this->content, $parentId, $data['slug']));

			// Copy slug name into the output display & capture ctrl+s for save
			if($edit) {
				$js = "	\$fl('#preview').bind('click', function(e) {
		\$fl.setCookie('__preview', 'true', undefined, '" . $this->request->getBasePath() . "');
		window.open('" . $docPath . $currentSlug . "' + contentExtensions[$currentContentType] + \"?t=\" + (new Date().getTime()), \"__preview\");
		event.preventDefault();
		return false;
	});";
			}
			else
				$js = '';

			$this->tpl->getCodeBuffer()->bufferReadyJS("
	var contentExtensions = {" . join(', ', $idtoext) . "},
		slugEdited = \$fl('#slug').val().length;

	$js

	function updateSlugPath() {
		var u = \$fl('#slug').val() + contentExtensions[\$fl('#contenttype').value()];
		\$fl('#slugview').html(u);
	}
	updateSlugPath();

	function slugUpdate() {
		if(!slugEdited || \$fl('#slug').val() == '') {
			slugEdited = false;
			\$fl('#slug').val(\$fl('#title').val().toLowerCase().replace(/&amp;/g, ' ').replace(/ /g, '-').replace(/[^a-z0-9_-]/g, '').replace(/-+/g, '-').replace(/^-/, '').replace(/-$/, ''));
			updateSlugPath();
		}
	}

	\$fl('#slug')
		.bind('keyup', updateSlugPath)
		.bind('blur', slugUpdate)
		.bind('change', function(e) { slugEdited = true; });
	\$fl('#contenttype').bind('change', updateSlugPath);

	\$fl('#title').bind('blur', slugUpdate).bind('keyup', slugUpdate);
")->bufferHeadJS('system/app/js/cfMetaS.js');
			$this->confirmLeavePage();

			if($data['restype'] == 'doc') {
				$siteCfg = clearFusionCMS::getSiteConfig('cfSystemSite');
				$template = new flFormElementSelect($form, 'template', $data['template'], $tplMgr->getTemplateList($siteCfg->siteTheme));
				$template->setLabel(__('Template', 'cfBackend'))
					->addValidator(new flFormValidatorRequired());

				$metaTitle = new flFormElementText($form, 'metaTitle', isset($data['meta_title']) ? $data['meta_title'] : '');
				$metaTitle->setLabel(__('Meta Title', 'cfBackend'))
					->setDescription(__('Meta title for the document, &#91;&#91;+meta_title&#93;&#93;', 'cfBackend'))
					->addValidator(new flFormValidatorMaxLength(255));

				$desc = new flFormElementTextArea($form, 'desc', $data['meta_description']);
				$desc->setLabel(__('Meta Description', 'cfBackend'))
					->setDescription(__('Meta description for the document, &#91;&#91;+meta_description&#93;&#93;', 'cfBackend'))
					->addValidator(new flFormValidatorMaxLength(255))
					->setRows(2);

				$issearchable = new flFormElementCheckbox($form, 'issearchable', $data['issearchable']);
				$issearchable->setLabel(__('Content is Searchable', 'cfBackend'));

				// Create the OG fields
				list($ogtitle, $ogdesc, $ogImage, $ogImagePane, $twittertitle, $twitterdesc, $twitterImage, $twitterImagePane) = cfSocialImagesMgr::buildFormElement($this->tpl->getCodeBuffer(), $form, $data);
			}
			else {
				$template = new flFormElementHidden($form, 'template', '');
				$metaTitle = new flFormElementHidden($form, 'metaTitle', '');
				$desc = new flFormElementHidden($form, 'desc', '');

				$ogtitle = new flFormElementHidden($form, 'ogtitle', '');
				$ogdesc = new flFormElementHidden($form, 'ogdesc', '');
				$twittertitle = new flFormElementHidden($form, 'twittertitle', '');
				$twitterdesc = new flFormElementHidden($form, 'twitterdesc', '');
				$ogImage = new flFormElementHidden($form, 'ogimageid', '0');
				$twitterImage = new flFormElementHidden($form, 'twitterimageid', '0');

				if($data['restype'] == 'folder')
					$issearchable = new flFormElementHidden($form, 'issearchable', '0');
				else {
					$issearchable = new flFormElementCheckbox($form, 'issearchable', $data['issearchable']);
					$issearchable->setLabel(__('Content is Searchable', 'cfBackend'));
				}
			}

			if($data['restype'] == 'doc' || $data['restype'] == 'static') {
				$key = new flFormElementText($form, 'key', $data['meta_keywords']);
				$key->setLabel(__('Meta Keywords', 'cfBackend'))
					->setDescription(__('Meta keywords for the document, &#91;&#91;+meta_keywords&#93;&#93;', 'cfBackend'))
					->addValidator(new flFormValidatorMaxLength(255));
			}
			else
				$key = new flFormElementHidden($form, 'key', '');

			if($data['restype'] == 'folder') {
				$summary = new flFormElementHidden($form, 'summary', '');
				$menutitle = new flFormElementHidden($form, 'menutitle', '');

				$menuhide = new flFormElementCheckbox($form, 'menuhide', $data['menuhide']);
				$menuhide->setLabel(__('Hide from Menus', 'cfBackend'));
			}
			else {
				$menutitle = new flFormElementText($form, 'menutitle', $data['menutitle']);
				$menutitle->setLabel(__('Menu Title', 'cfBackend'))
					->setDescription(__('Short document title for use in menus.', 'cfBackend'))
					->addValidator(new flFormValidatorMaxLength(255));

				$menuhide = new flFormElementCheckbox($form, 'menuhide', $data['menuhide']);
				$menuhide->setLabel(__('Hide from Menus', 'cfBackend'));

				$summary = new flFormElementTextArea($form, 'summary', $data['summary']);
				$summary->setLabel(__('Summary', 'cfBackend'))
					->setDescription(__('The document summary, &#91;&#91;+summary&#93;&#93;', 'cfBackend'))
					->addValidator(new flFormValidatorMaxLength(65535))
					->setRows(3);
			}

			if($data['restype'] == 'static') {
				$cfg = clearFusionCMS::getSiteConfig('cfSystemFileStore');

				$rootTree = new flWidgetTreeView('cfFileFolderTreeView');
				$topTree = new flWidgetTreeView();
				if($this->user->hasPermission('cfContent.private'))
					$topTree->addNode($this->buildFolderTree(null, $cfg->privateFiles, __('Private Files', 'cfBackend')));
				$topTree->addNode($this->buildFolderTree(null, $cfg->publicFiles, __('Public Files', 'cfBackend')));
				$rootTree->addNode(new flWidgetTreeChildNode(__('Root', 'cfBackend'), $topTree, null));

				$folders = new flFormElementPane($form, 'folders', $rootTree->render($this->tpl->getCodeBuffer()));
				$folders->setLabel(__('Resource File Selector', 'cfBackend'));

				$this->tpl->getCodeBuffer()->bufferReadyJS("
	\$fl('#folders-container a').bind('click', function(evt) {
		if(evt.target.tagName != 'A') {
			\$fl('#content').value(\$fl(evt.target).parent().attr('href').replace(/^#/, ''))[0].select();
		}
		evt.preventDefault();
		evt.stopPropagation();
		return false;
	});
");
			}

			if($data['restype'] == 'link') {
				$ctnt = new flFormElementText($form, 'content', $data['content']);
				$ctnt->setLabel(__('Link To', 'cfBackend'))
					->setRequired()
					->setDescription(__('The absolute address to link to or a page id e.g. &#91;&#91;~1&#93;&#93.', 'cfBackend'))
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMaxLength(2097152))
					->addValidator(new flFormValidatorRegex('/^(\[\[.+\]\])|(((http|https):\/\/)?([\w-]+:[\w-]+@)?[\w-]+(?:\.[\w-]+)*(?::\d+)?(?:\/[\w ~\\\(\)%\=\.,\+-]*)*(?:\?[\w ~\\\(\)%\=\.,\+-]+=[\w ~\\\(\)%\=\.,\+-]*(?:&[\w ~\\\(\)%\=\.,\+-]+=[\w ~\\\(\)%\=\.,\+-]*)*)?(#[\w ~\\\(\)%\=\.,\/\+-]*)?)$/i'));
				$noeditor = new flFormElementHidden($form, 'noeditor', '1');
				$container = new flFormElementHidden($form, 'pcontainer', '');
				$containerext = new flFormElementHidden($form, 'containerext', '');
				$cachetime = new flFormElementHidden($form, 'cachetime', '0');
			}
			else if($data['restype'] == 'folder') {
				$ctnt = new flFormElementHidden($form, 'content', '');
				$noeditor = new flFormElementHidden($form, 'noeditor', '1');
				$container = new flFormElementHidden($form, 'pcontainer', '');
				$containerext = new flFormElementHidden($form, 'containerext', '');
				$cachetime = new flFormElementHidden($form, 'cachetime', '0');
			}
			else if($data['restype'] == 'static') {
				$ctnt = new flFormElementText($form, 'content', $data['content']);
				$ctnt->setLabel(__('Resource File', 'cfBackend'))
					->setRequired()
					->setDescription(__('The file on the disk.', 'cfBackend'))
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMaxLength(2097152));
				$noeditor = new flFormElementHidden($form, 'noeditor', '1');
				$container = new flFormElementHidden($form, 'pcontainer', '');
				$containerext = new flFormElementHidden($form, 'containerext', '');
				$cachetime = new flFormElementHidden($form, 'cachetime', '0');
			}
			else {
				$editorData = array(
					'db' => $this->db,
					'module' => isset($this->managerSession->editor) ? $this->managerSession->editor : $cfg->editor,
					'moduleCode' => isset($this->managerSession->codeEditor) ? $this->managerSession->codeEditor : $cfg->codeEditor,
					'tags' => array(
						__('Last Updated', 'cfBackend') => '[[+lastupdated]]',
						__('Meta Title', 'cfBackend') => '[[+meta_title]]',
						__('Meta Description', 'cfBackend') => '[[+meta_description]]',
						__('Meta Keywords', 'cfBackend') => '[[+meta_keywords]]',
						__('Document ID', 'cfBackend') => '[[+id]]',
						__('Document Title', 'cfBackend') => '[[+title]]',
						__('Document Subtitle', 'cfBackend') => '[[+subtitle]]',
						__('Published At', 'cfBackend') => '[[+publishedat]]',
						__('Site Name', 'cfBackend') => '[[+sitename]]',
						__('Site URI', 'cfBackend') => '[[+siteuri]]',
						__('Summary', 'cfBackend') => '[[+summary]]'
					)
				);

				$custFieldsBefore = $fields->addToForm($form, $data['template'], $editorData, $data['customfields'], true);

				$ctnt = cfEditor::create(
					$data['noeditor'] ? $this->getCodeEditorModule() : $this->getEditorModule($editorName[$data['contenttype']]),
					$form, 'content2',
					$data['content'],
					false,
					array(
						__('Last Updated', 'cfBackend') => '[[+lastupdated]]',
						__('Meta Title', 'cfBackend') => '[[+meta_title]]',
						__('Meta Description', 'cfBackend') => '[[+meta_description]]',
						__('Meta Keywords', 'cfBackend') => '[[+meta_keywords]]',
						__('Document ID', 'cfBackend') => '[[+id]]',
						__('Document Title', 'cfBackend') => '[[+title]]',
						__('Document Subtitle', 'cfBackend') => '[[+subtitle]]',
						__('Published At', 'cfBackend') => '[[+publishedat]]',
						__('Site Name', 'cfBackend') => '[[+sitename]]',
						__('Site URI', 'cfBackend') => '[[+siteuri]]',
						__('Summary', 'cfBackend') => '[[+summary]]'
					)
				);
				$ctnt->setLabel(__('Content', 'cfBackend'))
					->setDescription(__('The document content, &#91;&#91;+content&#93;&#93;', 'cfBackend'))
					->addValidator(new flFormValidatorMaxLength(2097152))
					->editorContentType($mimeTypes[$contType->getValue()]);


				$noeditor = new flFormElementCheckbox($form, 'noeditor', $data['noeditor']);
				$noeditor->setLabel(__('Disable WYSIWYG editor for this document.', 'cfBackend'))
					->setDescription(__('The document will need to be saved for the change to take effect, clicking the box will save the document.', 'cfBackend'));

				// On WYSIWYG disable save a draft, on template change check the user is happy to loose data then save a draft
				$this->tpl->getCodeBuffer()->bufferReadyJS("
	\$fl('#noeditor').bind('click', function(evt) {
		\$fl(window).unbind('beforeunload');
		\$fl('#contentform').append('<input name=\"draft\" value=\"1\">').submit();
	});

	var lastCtntTypeValue = '';

	\$fl('#template').bind('change', function(evt) {
		\$fl(window).unbind('beforeunload');
		\$fl('#contentform').append('<input name=\"draft\" value=\"1\">').submit();
	});

	\$fl('#contenttype')
		.bind('click', function(evt) {
			lastCtntTypeValue = evt.target.value;
		})
		.bind('change', function(evt) {
		if(confirm('" . __('If you continue a draft will be saved, do you want to continue?', 'cfBackend') . "')) {
			\$fl(window).unbind('beforeunload');
			\$fl('#contentform').append('<input name=\"draft\" value=\"1\">').submit();
		}
		else {
			evt.target.value = lastCtntTypeValue;
			return false;
		}
	});
");

				$custFieldsAfter = $fields->addToForm($form, $data['template'], $editorData, $data['customfields'], false);

				// Get the list of modules that need container pages
				$mm = new flModuleMgr($this->db);
				$modules = $mm->getInstalled();
				$el = array('' => __('[Page]', 'cfBackend'), '#' => __('Allow Virtual Pages', 'cfBackend'));
				foreach($modules as $name => $ver) {
					if(($info = $mm->getInfo($name)) && ($containerInfo = $info->get('container', false))) {
						foreach($containerInfo as $cont) {
							$c = explode(',', $cont);
							if(count($c) == 2)
								$el[$name . '.' . trim($c[0])]  = sprintf(__('Container for %s', 'cfBackend'), __(trim($c[1]), $name . 'Backend'));
						}
					}
				}

				@list($cm, $ca, $ce) = explode('.', $data['container']);
				if(isset($ca))
					$cm .= ".$ca";
				if(!isset($ce))
					$ce = '';

				$container = new flFormElementSelect($form, 'pcontainer', $cm, $el);
				$container->setLabel(__('Document Behavior', 'cfBackend'))
					->setDescription(__('Should this document act as a page or a container.', 'cfBackend'));

				$containerext = new flFormElementText($form, 'containerext', $ce);
				$containerext->setLabel(__('Behavior Extra', 'cfBackend'))
					->addValidator(new flFormValidatorMaxLength(64));

				$cachetime = new flFormElementSelect($form, 'cachetime', isset($data['cachetime']) ? $data['cachetime'] : 0, array(
					0 => __('[Default]', 'cfBackend'),
					-1 => __('Don\'t Cache', 'cfBackend'),
					3600 => __('1 Hour', 'cfBackend'),
					14400 => __('4 Hours', 'cfBackend'),
					21600 => __('6 Hours', 'cfBackend'),
					43200 => __('12 Hours', 'cfBackend'),
					86400 => __('1 Day', 'cfBackend'),
					172800 => __('2 Days', 'cfBackend'),
					259200 => __('3 Days', 'cfBackend'),
					345600 => __('4 Days', 'cfBackend'),
					432000 => __('5 Days', 'cfBackend'),
					518400 => __('6 Days', 'cfBackend'),
					604800 => __('1 Week', 'cfBackend'),
					1209600 => __('2 Weeks', 'cfBackend')
				));
				$cachetime->setLabel(__('Maximum Cache Time', 'cfBackend'));
			}

			$publish = new flFormElementCheckbox($form, 'publish', $data['published']);
			$publish->setLabel(__('Published', 'cfBackend'));
			if(!$this->user->hasPermission('cfContent.canpublish'))
				$publish->setReadonly()->setDisabled();

			// Access & edit permission
			$ac = new flAcMgr($this->db);
			$accessPerm = new flFormElementSelect($form, 'accessperm', $data['accessperm'], array('' => __('[Public]', 'cfBackend')) + $ac->getPermissionsInGroup('content'));
			$accessPerm->setLabel(__('View Permission', 'cfBackend'))
				->setDescription(__('NOTE: Permissions are inherited from all parents of this document.', 'cfBackend'));

			$availEdPerms = array('' => __('[None]', 'cfBackend'));
			foreach($ac->getPermissionsInGroup('ctntedt') as $p => $d) {
				if($this->user->hasPermission($p))
					$availEdPerms[$p] = $d;
			}
			$edPerm = new flFormElementSelect($form, 'edperm', $data['editperm'], $availEdPerms);
			$edPerm->setLabel(__('Edit Permission', 'cfBackend'))
				->setDescription(__('NOTE: Permissions are inherited from all parents of this document.', 'cfBackend'));

			if($data['restype'] == 'folder')
				$disposition = new flFormElementHidden($form, 'disposition', 0);
			else {
				$disposition = new flFormElementCheckbox($form, 'disposition', $data['asattachment']);
				if($data['restype'] != 'link') {
					$disposition->setLabel(__('Serve Content as Attachment', 'cfBackend'))
						->setDescription(__('If ticked browsers will download the content.', 'cfBackend'));
				} else {
					$disposition->setLabel(__('Permanent Redirect', 'cfBackend'))
						->setDescription(__('If ticked use a 301 redirect otherwise use a 302.', 'cfBackend'));
				}
			}

			if($edit) {
				if($data['publishedat'] == null)
					$c = __('Not Published', 'cfBackend');
				else
					$c = (string)new flDate($data['publishedat'] . ' UTC', $this->user->getTimezone());
				$publishedat = new flFormElementText($form, 'addedat', $c);
				$publishedat->setLabel(__('Published At', 'cfBackend'))
					->setDescription(__('Date and time published, &#91;&#91;+publishedat&#93;&#93;', 'cfBackend'));

				if($data['publishedat'] != null && $this->user->hasPermission('cfContent.editpubdate')) {
					$publishedat->setRequired()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorRegex('/^\d{4}-(0?[0-9]|1[0-2])-\d{1,2} \d{1,2}:\d{1,2}(:\d{1,2})?$/', __('The date and time must be in the form yyyy-mm-dd hh:mm or yyyy-mm-dd hh:mm:ss.', 'cfBackend')));
				}
				else
					$publishedat->setReadonly()->setDisabled();

				$c = (string)new flDate($data['lastupdated'] . ' UTC', $this->user->getTimezone());
				$lastupdated = new flFormElementText($form, 'lastupdated', $c);
				$lastupdated->setLabel(__('Last Updated', 'cfBackend'))
					->setDescription(__('Date and time of last update, &#91;&#91;+lastupdated&#93;&#93;', 'cfBackend'))
					->setReadonly()
					->setDisabled();

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

				$draft = new flFormElementSubmit($form, 'draft');
				$draft->setCaption(__('Save Draft', 'cfBackend'))->setCSS('primary');

				if($this->user->hasPermission('cfContent.canpublish')) {
					$update = new flFormElementSubmit($form, 'update');
					$update->setCaption(__('Save', 'cfBackend'))->setCSS('primary');
				}

				if($this->user->hasPermission('cfContent.candelete')) {
					$delSubmit = new flFormElementSubmit($form, 'delete');
					$delSubmit->setCaption(__('Delete', 'cfBackend'))
						->setCSS('danger');
				}

				$delDraft = new flFormElementSubmit($form, 'deldraft');
				$delDraft->setCaption(__('Delete Draft', 'cfBackend'))->setCSS('danger')->hide(!$hasDraft);

				$changeType = new flFormElementSubmit($form, 'changetype');
				$changeType->setCaption(__('Change Type', 'cfBackend'))->setCSS('flat accent');

				// Test if old custom fields available but not used
				$unusedFlds = array_diff_key($data['customfields'], array_flip($fields->getTemplateFields($data['template'])));
				if(count($unusedFlds)) {
					$clean = new flFormElementCheckbox($form, 'cleanflds');
					$clean->setLabel(__('Delete Unused Custom Field Data', 'cfBackend'))
						->setDescription($this->alertMessage('Warning', __('Checking this box will remove unused custom field data left over from a previous template selection. All data will be deleted and will not be recoverable.', 'cfBackend')));
				}
			}
			else {
				$create = new flFormElementSubmit($form, 'create');
				$create->setCaption(__('Create', 'cfBackend'))->setCSS('primary');
			}

			// Group elements
			$form->groupElements('content1', array($title, $subtitle, $slug, $summary, $menutitle))
				->groupElements('content2', array($metaTitle, $desc, $key, $template, $contType, $menuhide, $publish, $issearchable));

			if($data['restype'] == 'static')
				$form->groupElements('content', array($folders, $ctnt));
			else if($data['restype'] == 'doc') {
				$custFieldsBefore->createGroups($form);
				$form->groupElements('content', array_merge($custFieldsBefore->ungrouped, array($ctnt, $noeditor), $custFieldsAfter->ungrouped));
				$custFieldsAfter->createGroups($form);
			}
			else
				$form->groupElements('content', array($ctnt, $noeditor));

			$form->groupElements('content3', $data['restype'] == 'doc' ? array($accessPerm, $edPerm, $container, $containerext) : array($accessPerm, $edPerm));

			if($edit) {
				$elems = array();
				if(isset($update)) $elems[] = $update;
				if(isset($draft)) $elems[] = $draft;
				if(isset($duplicate)) $elems[] = $duplicate;
				if(isset($delDraft)) $elems[] = $delDraft;
				if(isset($delSubmit)) $elems[] = $delSubmit;

				$preview = new flFormElementButton($form, 'preview');
				$preview->setCaption(__('Preview', 'cfBackend'))->setCSS('flat accent');
				$elems[] = $preview;

				$form->groupElements('content4', isset($clean) ? array($disposition, $cachetime, $publishedat, $lastupdated, $clean, $changeType) : array($disposition, $cachetime, $publishedat, $lastupdated, $changeType))
					->groupElements('submit', $elems, new flFormDecoratorList(new flFormDecoratorDl()));
			}
			else {
				$form->groupElements('content4', array($disposition, $cachetime))
					->groupElements('submit', array($create), new flFormDecoratorList(new flFormDecoratorDl()));
			}

			if($data['restype'] == 'doc') {

				// Map in custom fields
				$docGrps = array('content1', 'content2');
				foreach($custFieldsBefore->groupFields as $catID => $elems) {
					$docGrps[] = 'content_fieldsbefore_' . $catID;
				}
				$docGrps[] = 'content';
				foreach($custFieldsAfter->groupFields as $catID => $f) {
					$docGrps[] = 'content_fieldsafter_' . $catID;
				}
				$docGrps[] = 'content3';
				$docGrps[] = 'content4';

				$form->groupElements('leftcolsocial', array($ogtitle, $ogdesc, $ogImage, $ogImagePane))
					->groupElements('rightcolsocial', array($twittertitle, $twitterdesc, $twitterImage, $twitterImagePane))
					->addTab(__('Document', 'cfBackend'), $docGrps)
					->addTab(__('Social Meta', 'cfBackend'), array('leftcolsocial', 'rightcolsocial'));
			}

			$form->focusElement($title);

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

				// If no buttons pressed then force save as js save
				if($this->user->hasPermission('cfContent.canpublish') && isset($update)) {
					$c = 0;
					if(isset($update) && $update->getValue()) $c++;
					if(isset($draft) && $draft->getValue()) $c++;
					if(isset($duplicate) && $duplicate->getValue()) $c++;
					if(isset($delDraft) && $delDraft->getValue()) $c++;
					if(isset($delSubmit) && $delSubmit->getValue()) $c++;
					if(isset($changeType) && $changeType->getValue()) $c++;

					if(!$c)
						$update->setValue(1);
				}

				// Stop user escaping the assets folder
				if($data['restype'] == 'static') {
					$realAsset = realpath($ctnt->getValue());
					$realPub = realpath($cfg->publicFiles);
					$realPriv = realpath($cfg->privateFiles);

					if(substr($realAsset, 0, strlen($realPriv)) != $realPriv && substr($realAsset, 0, strlen($realPub)) != $realPub)
						$ctnt->setValue($cfg->publicFiles . '/' . ltrim(preg_replace('#/+#', '/', preg_replace('/\.{2}/', '', $ctnt->getValue())), '/'));
				}

				$containerExtData = $container->getValue() == '#' || $container->getValue() == '' ? '' : $containerext->getValue();
				$now = new flDate();
				$d = array(
					'contenttype' => $contType->getValue(),
					'title' => $title->getValue(),
					'subtitle' => $subtitle->getValue(),
					'meta_title' => $metaTitle->getValue(),
					'meta_description' => $desc->getValue(),
					'meta_keywords' => $key->getValue(),
					'summary' => $summary->getValue(),
					'content' => $ctnt->getValue(),
					'slug' => $slug->getValue(),
					'template' => $template->getValue(),
					'lastupdated' => $now->toString(),
					'menutitle' => $menutitle->getValue(),
					'menuhide' => $menuhide->getValue(),
					'accessperm' => $accessPerm->getValue(),
					'editperm' => $edPerm->getValue(),
					'asattachment' => $disposition->getValue(),
					'noeditor' => $noeditor->getValue(),
					'issearchable' => $issearchable->getValue(),
					'cachetime' => $cachetime->getValue(),
					'published' => $this->user->hasPermission('cfContent.canpublish') ? $publish->getValue() : $data['published'],
					'publishedat' => $data['publishedat'],
					'restype' => $data['restype'],
					'container' => $container->getValue() . ($containerExtData != '0' && empty($containerExtData) ? '' : '.' . $containerext->getValue()),
					'draft' => '',
					'ogtitle' => $ogtitle->getValue(),
					'ogdesc' => $ogdesc->getValue(),
					'twittertitle' => $twittertitle->getValue(),
					'twitterdesc' => $twitterdesc->getValue(),
					'ogimageid' => $ogImage->getValue(),
					'twitterimageid' => $twitterImage->getValue()
				);

				if($type == 'static')
					$this->managerSession->staticContentType = $contType->getValue();

				if($data['publishedat'] != null && isset($publishedat) && $this->user->hasPermission('cfContent.editpubdate')) {
					$date = new flDate($publishedat->getValue(), clearFusionCMS::getSysTimezone());
					$date->setTimezone('UTC');
					$d['publishedat'] = $date->toString();
				}

				if($this->user->hasPermission('cfContent.canpublish')) {
					$d['published'] = $publish->getValue();
					if($publish->getValue() && $data['publishedat'] == null)
						$d['publishedat'] = $d['lastupdated'];
					else if(!$publish->getValue())
						$d['publishedat'] = null;
				}

				// Get values for custom fields, keep fields that user can't edit
				$fieldValues = $data['customfields'];
				if($data['restype'] == 'doc') {
					foreach($custFieldsBefore->fields as $n => $e)
						$fieldValues[$n] = $e->getValue();
					foreach($custFieldsAfter->fields as $n => $e)
						$fieldValues[$n] = $e->getValue();
				}

				// Clear unused custom fields
				if(isset($clean) && $clean->getValue())
					$fieldValues = array_diff_key($fieldValues, $unusedFlds);

				// Issue before save event (create and update only)
				if((isset($update) && $update->getValue()) || (isset($create) && $create->getValue())) {
					clearFusionCMS::getEventManager()->notify($e = new flEvent('system.beforeContentSave', array(
						'isNew' => !$edit,
						'contentData' => $d,
						'customFields' => $fieldValues
					)));
					$d = $e->getParam('contentData');
					$fieldValues = $e->getParam('customFields');
				}

				if($edit && (!isset($duplicate) || !$duplicate->getValue())) {
					$prevData = $data;
					$data['title'] = $title->getValue();
					$data['lastupdated'] = $d['lastupdated'];

					// Save update & delete draft
					if(isset($update) && $update->getValue()) {
						$d['draft'] = '';
						if($this->content->updateNodeData($node, $d)) {
							$fields->storeFields($node, clearFusionCMS::getSite(), $fieldValues);
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The content was saved!', 'cfBackend')));

							contentAudit::update($node, $prevData);

							clearFusionCMS::getEventManager()->notify(new flEvent('system.afterContentSave', array(
								'id' => $node,
								'isNew' => !$edit,
								'contentData' => $d,
								'customFields' => $fieldValues
							)));

							// Build the path to the doc & update search
							$res = $this->content->getPath($node, array('id'));
							$segs = array('content');
							foreach($res as $row)
								$segs[] = $row['id'];

							if(!$d['issearchable'] || !$d['published']) {
								$e = new flEvent('system.searchDeindex', array(
									'path' => $segs
								));
							}
							else {
								// Remove inactive fields
								$actvFields = array_flip($fields->getTemplateFields($d['template']));
								$fieldValues = array_intersect_key($fieldValues, $actvFields);

								// Send to search
								$e = new flEvent('system.searchIndex', array(
									'path' => $segs,
									'accessPerm' => $d['accessperm'],
									'publishedAt' => $d['publishedat'],
									'fields' => array_merge(array(
										'title' => $d['title'],
										'subtitle' => $d['subtitle'],
										'content' => $d['restype'] == 'doc' ? $d['content'] : '',
										'summary' => $d['summary'],
										'meta_title' => $d['meta_title'],
										'meta_description' => $d['meta_description'],
										'meta_keywords' => $d['meta_keywords']
									), $fieldValues)
								));
							}
							clearFusionCMS::getEventManager()->notify($e);

							clearFusionCMS::getEventManager()->notify(new flEvent('system.cachePurge', array('files' => array($docPath . $currentSlug . (empty($fileExt[$currentContentType]) ? '/' : '.' . $fileExt[$currentContentType])))));

							$this->cache->flush();
							$this->response->redirectTo($this->assemble('', 'documents', array($node), true));
						}
						else
							$msg = $this->alertMessage('Error', __('Failed to update the content!', 'cfBackend'));
					}
					// Save as draft/delete draft
					else {
						$d['customfields'] = $fieldValues;

						if(isset($delDraft) && $delDraft->getValue())
							contentAudit::deleteDraft($node, $prevData);
						else
							contentAudit::draft($node, $prevData);

						if($this->content->updateNodeData($node, array('draft' => (isset($delDraft) && $delDraft->getValue()) ? '' : serialize($d)))) {
							if(isset($delDraft) && $delDraft->getValue())
								$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The draft has been deleted.', 'cfBackend')));
							else
								$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The draft was saved!', 'cfBackend')));
							if((!isset($delSubmit) || !$delSubmit->getValue()) && (!isset($changeType) || !$changeType->getValue()))
								$this->response->redirectTo($this->assemble('', 'documents', array($node), true));
						}
						else
							$msg = $this->alertMessage('Error', __('Failed to save the draft.', 'cfBackend'));
					}

					if($noeditor instanceof flFormElementCheckbox)
						$ctnt->editorModule($noeditor->getValue() ? '' : (isset($this->managerSession->editor) ? $this->managerSession->editor : $cfg->editor));

					$this->cache->flush();

					// If deleting
					if(isset($delSubmit) && $delSubmit->getValue())
						$this->response->redirectTo($this->assemble('', 'documents', array('delete', $node), true));

					// If changing the document type
					if(isset($changeType) && $changeType->getValue())
						$this->response->redirectTo($this->assemble('', 'documents', array('changetype', $node), true));
				}
				else { // Create or duplicate
					if(isset($duplicate) && $duplicate->getValue()) {
						$cpycnt = 1;
						while($this->content->hasChildSlug($parentId, $newSlug = (($cpycnt >= 2 ? "copy-{$cpycnt}-of-" : 'copy-of-')  . $d['slug'])))
							$cpycnt++;

						$d['title'] = ($cpycnt >= 2 ? "Copy $cpycnt of " : 'Copy of ') . $d['title'];
						$d['slug'] = $newSlug;
						$d['published'] = '0';
						$d['publishedat'] = null;

						// Remove inactive fields
						$actvFields = array_flip($fields->getTemplateFields($d['template']));
						$fieldValues = array_intersect_key($fieldValues, $actvFields);
					}

					if($newId = $this->content->insertNode($parentId, cfContent::UNDER, $d)) {
						$fields->storeFields($newId, clearFusionCMS::getSite(), $fieldValues);

						contentAudit::create($newId, $d['restype'], $d['title']);

						clearFusionCMS::getEventManager()->notify(new flEvent('system.afterContentSave', array(
							'id' => $newId,
							'isNew' => !$edit,
							'contentData' => $d,
							'customFields' => $fieldValues
						)));

						// Build and issue search index event
						if($d['restype'] == 'doc' || $d['restype'] == 'static') {
							// Build the path to the doc
							$res = $this->content->getPath($newId, array('id'));
							$segs = array('content');
							foreach($res as $row)
								$segs[] = $row['id'];

							if(!$d['issearchable'] || !$d['published']) {
								$e = new flEvent('system.searchDeindex', array(
									'path' => $segs
								));
							}
							else {
								$e = new flEvent('system.searchIndex', array(
									'path' => $segs,
									'accessPerm' => $d['accessperm'],
									'publishedAt' => $d['publishedat'],
									'fields' => array_merge(array(
										'title' => $d['title'],
										'subtitle' => $d['subtitle'],
										'content' => $d['restype'] == 'doc' ? $d['content'] : '',
										'summary' => $d['summary'],
										'meta_title' => $d['meta_title'],
										'meta_description' => $d['meta_description'],
										'meta_keywords' => $d['meta_keywords']
									), $fieldValues)
								));
							}
							clearFusionCMS::getEventManager()->notify($e);
						}

						$this->cache->flush();
						if(isset($duplicate) && $duplicate->getValue())
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The document has been duplicated.', 'cfBackend')));
						else
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The new document has been created.', 'cfBackend')));
						$this->response->redirectTo($this->assemble('', 'documents', array($newId), true));
					}
					else {
						if(isset($duplicate) && $duplicate->getValue())
							$msg = $this->alertMessage('Error', __('Unable to duplicate the document, please try again.', 'cfBackend'));
						else
							$msg = $this->alertMessage('Error', __('Unable to create a new document, please try again.', 'cfBackend'));
					}
				}
			}
		}
		else if($edit)
			$msg = $this->alertMessage('Error', __('You do not have permission to edit this document.', 'cfBackend'));
		else
			$msg = $this->alertMessage('Error', __('You do not have permission to create a new document here.', 'cfBackend'));

		return $this->renderBlock(sprintf($hasDraft ? __('(Draft) %s', 'cfBackend') : '%s', $blkTitle), $form->render($this->tpl->getCodeBuffer()), '', $msg);
	}

	/**
	 * Process the page.
	 */
	function process() {

		$this->testPermission('cfContent.documents');

		// If looking up social media image
		cfSocialImagesMgr::handleAJAXRequest($this->request, $this->response);

		$this->breadcrumbTrail->addCrumb(__('Documents', 'cfBackend'), $this->assemble('', 'documents'));

		$this->content = new cfContent($this->db, clearFusionCMS::getSite());

		$content = '';
		$active = 0;
		$move = false;
		$orderChange = false;

		// Build routes
		$edRoute = new flRouterRoute(':id', array('id' => '0'), array('id' => '\d+'));
		$addRoute = new flRouterRoute('add/:id/:type', array(), array('id' => '\d+', 'type' => 'doc|link|static|folder'));
		$deleteRoute = new flRouterRoute('delete/:id', array(), array('id' => '\d+'));
		$changeRoute = new flRouterRoute('changetype/:id', array(), array('id' => '\d+'));
		$dragRoute = new flRouterRoute('dragdrop/:id', array(), array('id' => '\d+'));

		// If edit a content node
		if($params = $edRoute->match($this->request->getParam('*', array()))) {
			if($active = $params['id']) {
				if(($content = $this->lockObject('content', $params['id'])) === true)
					$content = $this->processForm($active, true);
			}
		}
		// If add node
		else if($params = $addRoute->match($this->request->getParam('*', array()))) {
			$active = $params['id'];
			$content = $this->processForm($active, false, $params['type']);
		}
		// If drag and drop
		else if($params = $dragRoute->match($this->request->getParam('*', array()))) {
			$result = array(
				'success' => true,
				'msg' => '',
				'dismiss' => __('Dismiss', 'cfBackend'),
				'tree' => ''
			);

			$active = $params['id'];

			$position = $this->request->getPost('position', '');
			$moving = $this->request->getPost('moving', '');
			$target = $this->request->getPost('target', '');

			if(!preg_match('/^-?[01]$/', $position) || !preg_match('/^\d+$/', $moving) || !preg_match('/^\d+$/', $target)) {
				$result['success'] = false;
				$result['msg'] = __('Internal failure, please try again.', 'cfBackend');
			}

			// Test permission
			if($result['success'] && !$this->user->hasPermission($this->content->getEditPermissions($active))) {
				$result['success'] = false;
				$result['msg'] = __('You do not have permission to edit this document.', 'cfBackend');
			}
			else if($result['success']) {

				// If target is root then always use into
				if(!$target)
					$position = 0;

				// Build the path to the doc being moved
				$res = $this->content->getPath($moving, array('id','slug'));
				$src = array('content');
				$origPath = [];
				foreach ($res as $row) {
					$src[] = $row['id'];
					$origPath[] = $row['slug'];
				}

				// Moving into
				if($position == 0) {
					$targetNode = $target;
				}
				// Moving before/after
				else {
					$targetNode = $this->content->getParent($target);
				}

				// Build the path to the new location
				$res = $this->content->getPath($targetNode, array('id', 'slug'));
				$dst = array('content');
				$newPath = [];
				foreach ($res as $row) {
					$dst[] = $row['id'];
					$newPath[] = $row['slug'];
				}

				$data = $this->content->getNodeData($moving, array('title', 'slug'));
				$this->content->lock();
				if ($position != 0 || !$this->content->hasChildSlug($target, $data['slug'])) {
					if ($this->content->moveNode($moving, $target, $position == 0 ? cfContent::UNDER : ($position == -1 ? cfContent::BEFORE : cfContent::AFTER))) {
						$result['msg'] = __('The document has been moved to the new location.', 'cfBackend');
					} else {
						$result['success'] = false;
						$result['msg'] = __('Unable to move this document to the selected location, please try again.', 'cfBackend');
					}
				} else {
					$result['success'] = false;
					$result['msg'] = __('Unable to move this document to the requested location as slug is already in use under the new parent.', 'cfBackend');
				}
				$this->content->unlock();

				// Send the event to search
				if($result['success']) {
					clearFusionCMS::getEventManager()->notify(new flEvent('system.searchMove', array(
						'src' => $src,
						'dst' => $dst
					)));

					$this->cache->flush();

					contentAudit::move(
						$moving,
						$position == 0 ? 'into' : ($position == -1 ? 'before' : 'after'),
						implode('/', $origPath),
						implode('/', $newPath)
					);
				}
			}

			// Build the new tree
			$contentTree = new cfContentTree('cfDocumentsTreeView', $this->content, '', 'documents', $active, false);
			$contentTree->setAJAXMoveHandler($this->assemble('', 'documents', array('dragdrop', $active), true));
			$result['tree'] = $contentTree->render(null, true);

			// Send AJAX response
			$this->response->setContentType('application/json')
				->noCache()
				->setBody(json_encode($result))
				->sendResponse();
			die;
		}
		// If delete
		else if($params = $deleteRoute->match($this->request->getParam('*', array()))) {
			$this->testPermission('cfContent.candelete');

			if(($content = $this->lockObject('content', $params['id'])) === true) {

				$msg = '';
				$active = $params['id'];
				$data = $this->content->getNodeData($active, array('issearchable', 'noeditor', 'contenttype', 'published', 'menuhide', 'publishedat', 'lastupdated', 'restype', 'cachetime', 'asattachment', 'accessperm', 'editperm', 'title', 'subtitle', 'meta_title', 'meta_description', 'meta_keywords', 'menutitle', 'summary', 'content', 'slug', 'template', 'draft', 'container', 'ogtitle', 'ogdesc', 'twittertitle', 'twitterdesc', 'ogimageid', 'twitterimageid'));

				// If has draft
				if(!empty($data['draft']))
					$data = unserialize($data['draft']);
				else {
					$fields = new cfCustomFields($this->db);
					$data['customfields'] = $fields->loadFields($active, clearFusionCMS::getSite());
				}

				$form = new flForm($this->request, 'deleteform', $this->assemble('', 'documents', array('delete', $active)), true);

				$name = new flFormElementText($form, 'title', $data['title']);
				$name->setLabel(__('Title', 'cfBackend'))
					->setDescription(__('This action cannot be undone!', 'cfBackend'))
					->setReadonly()
					->setDisabled();

				$delSubmit = new flFormElementSubmit($form, 'delete');
				$delSubmit->setCaption(__('Permanently Delete This Document and All its Children', 'cfBackend'))
					->setCSS('danger')
					->setDescription($this->alertMessage('Warning', __('Permanently delete this document and all of its child documents, this option cannot be undone!', 'cfBackend')));

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

					// Update audit trail
					contentAudit::delete($active, $data);

					// Build the path to the doc
					$res = $this->content->getPath($active, array('id'));
					$segs = array('content');
					foreach($res as $row)
						$segs[] = $row['id'];

					// Send the event to search
					clearFusionCMS::getEventManager()->notify(new flEvent('system.searchDelete', array(
						'path' => $segs
					)));

					// Delete document(s)
					$this->content->deleteNode($active);

					// Clean up custom fields
					$fields = new cfCustomFields($this->db);
					$fields->docDeleted(clearFusionCMS::getSite());

					clearFusionCMS::getEventManager()->notify(new flEvent('system.afterContentDelete', array(
						'id' => $active
					)));

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

				$content = $this->renderBlock(sprintf(__('Delete Document: %s', 'cfBackend'), $data['title']), $form->render($this->tpl->getCodeBuffer()), '', $msg);
			}
		}
		// If change type
		else if($params = $changeRoute->match($this->request->getParam('*', array()))) {
			if(($content = $this->lockObject('content', $params['id'])) === true) {

				$msg = '';
				$active = $params['id'];
				$data = $this->content->getNodeData($active, array('title', 'parentid', 'restype'));

				$form = new flForm($this->request, 'changeform', $this->assemble('', 'documents', array('changetype', $active)), true);

				$name = new flFormElementText($form, 'title', $data['title']);
				$name->setLabel(__('Title', 'cfBackend'))
					->setReadonly()
					->setDisabled();

				$type = new flFormElementRadio($form, 'type', $data['restype'], array('doc' => __('Document', 'cfBackend'), 'link' => __('Link', 'cfBackend'), 'static' => __('Static Resource', 'cfBackend'), 'folder' => __('Folder', 'cfBackend')));
				$type->setLabel(__('New Document Type', 'cfBackend'));

				$delSubmit = new flFormElementSubmit($form, 'delete');
				$delSubmit->setCaption(__('Change the Document Type', 'cfBackend'))
					->setCSS('danger')
					->setDescription($this->alertMessage('Warning', __('Changing the type of document will delete all existing data from the document before converting it to the new type, this option cannot be undone!', 'cfBackend')));

				if($form->isSubmitted() && $form->isValid()) {
					// No change
					if($data['restype'] == $type->getValue()) {
						$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('No change in document type was required.', 'cfBackend')));
					}
					else {
						// If currently a doc
						if($data['restype'] == 'doc') {
							// Clean up custom fields
							$fields = new cfCustomFields($this->db);
							$fields->docDeleteFields(clearFusionCMS::getSite(), $params['id']);
						}

						// Update and clean up
						$d = array(
							'restype' => $type->getValue(),
							'template' => '',
							'container' => '',
							'content' => '',
							'draft' => ''
						);
						if($type->getValue() != 'doc')
							$d['subtitle'] = $d['meta_title'] = $d['meta_description'] = $d['meta_keywords'] = '';

						$this->content->updateNodeData($params['id'], $d);
						$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The document type has been changed.', 'cfBackend')));
					}
					$this->cache->flush();
					$this->response->redirectTo($this->assemble('', 'documents', array($params['id']), true));
				}

				$content = $this->renderBlock(sprintf(__('Change Document Type For: %s', 'cfBackend'), $data['title']), $form->render($this->tpl->getCodeBuffer()), '', $msg);
			}
		}

		// Build the content tree
		$contentTree = new cfContentTree('cfDocumentsTreeView', $this->content, '', 'documents', $active, $move);
		$contentTree->setAJAXMoveHandler($this->assemble('', 'documents', array('dragdrop', $active), true));

		// Build floating action menu
		$fam = new flWidgetFloatingActionMenu();
		$fam->setCSS('[[+css]]')
			->setDefaultToOpen($orderChange);

		$fam->addAction('note_add', __('New Document', 'cfBackend'), $this->assemble('', 'documents', array('add', $active, 'doc')));
		$fam->addAction('insert_link', __('New Link', 'cfBackend'), $this->assemble('', 'documents', array('add', $active, 'link')));
		$fam->addAction('attach_file', __('New Static Resource', 'cfBackend'), $this->assemble('', 'documents', array('add', $active, 'static')));
		$fam->addAction('create_new_folder', __('New Folder', 'cfBackend'), $this->assemble('', 'documents', array('add', $active, 'folder')));

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

		// Draw the page
		$this->renderPage(__('Site Documents', 'cfBackend'), $content, $this->renderBlock('', $contentTree->render($this->tpl->getCodeBuffer())));
	}
}
