<?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
 */

/**
 * cfBackendBrowsefilesAction Class
 *
 * The action class to show the file tree for embedding in WYSIWYG editor.
 *
 * @package clearFusionCMS
 */
class cfBackendBrowsefilesAction extends cfBackendControllerAction {

	/**
	 * The query string.
	 *
	 * @var string
	 */
	protected $queryString;

	/**
	 * The base path.
	 *
	 * @var string
	 */
	protected $basePath;

	/**
	 * 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 $editor The editor in use.
	 * @param string $active The active folder.
	 * @param bool $move true if moving else false for normal operation.
	 * @param string $rootText The text for the root node.
	 * @return flWidgetTreeNode The built tree.
	 */
	function buildFolderTree($base, $path, $editor, $active, $move, $rootText = '') {
		if($base === null) $base = $path;

		$displayPath = substr($path, strlen($base) + 1);
		if(empty($displayPath)) {
			$displayPath = $rootText;
			$lockOpen = null;
		}
		else
			$lockOpen = false;

		$folders = glob($path . '/*', GLOB_ONLYDIR);
		$files = array_diff(glob($path . '/*'), $folders);
		if(empty($folders) && empty($files))
			$node = new flWidgetTreeLinkNode($displayPath, $this->basePath . "$path{$this->queryString}" . ($move ? "#$path" : ''), flWidgetTreeNode::CONTAINER);
		else {
			$tree = new flWidgetTreeView();
			foreach($folders as $fpath)
				$tree->addNode($this->buildFolderTree($path, $fpath, $editor, $active, $move));

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

				if($move)
					$tree->addNode(new flWidgetTreeNode(substr($file, strlen($path) + 1), $nodeType))
						->setLastNodeActive($active == $file);
				else
					$tree->addNode(new flWidgetTreeLinkNode(substr($file, strlen($path) + 1), $this->basePath . "$file{$this->queryString}" . ($editor == '_' ? '' : '#' . $this->request->getBasePath() . $file), $nodeType))
						->setLastNodeActive($active == $file);
			}

			$node = new flWidgetTreeChildNode($displayPath, $tree, $lockOpen, $this->basePath . "$path{$this->queryString}" . ($move ? "#$path" : ''));
		}

		if($path == $active)
			$node->setActive();

		return $node;
	}

	/**
	 * Delete a folder and all children.
	 *
	 * @param string $folder The folder to delete.
	 */
	function deleteFolder($folder) {
		$folder = rtrim($folder, '/\\') . '/';

		$folders = glob($folder . '*', GLOB_ONLYDIR);
		foreach($folders as $f) {
			$this->deleteFolder($f);
			@rmdir($folder);
		}

		$files = glob($folder . '*');
		foreach($files as $f)
			@unlink($f);

		@rmdir($folder);
	}

	/**
	 * Process the page.
	 */
	function process() {
		$q = array();
		foreach($_GET as $k => $v)
			$q[] = urlencode($k) . '=' . urlencode($v);
		if(count($q))
			$this->queryString = '?' . join('&amp;', $q);
		else
			$this->queryString = '';

		$active = '';
		$editor = '_';
		$cmd = 'browse';
		$private = false;
		$toolbarCtnt = $previewCtnt = $content = '';
		$msg = $this->session->flashGet('cfManagerOpSuccess', '');
		$rt = new flRouterRoute(':private/:editor/:cmd/*.*', array('private' => 'private', 'editor' => '_', 'cmd' => 'browse'), array('private' => 'private|public', 'editor' => '[a-z0-9_]+', 'cmd' => 'browse|edit|delete|move|add|upload|resize'));
		$path = $this->request->getParam('*', array());
		if($ext = $this->request->getParam('extension')) // Add extension back on
			$path[count($path) - 1] .= '.' . $ext;
		if($params = $rt->match($path)) {
			$editor = $params['editor'];
			$cmd = $params['cmd'];
			$private = $params['private'] == 'private';
			if(isset($params['*']))
				$active = join('/', $params['*']) . ($this->request->getParam('extension', '') == '' ? '' : '.' . $this->request->getParam('extension'));
		}

		// Make route for building routes
		$rt = new flRouterRoute(':private/:editor/:cmd/*', array('private' => 'private', 'editor' => '_', 'cmd' => 'browse'), array('private' => 'private|public', 'editor' => '[a-z0-9_]+', 'cmd' => 'browse|edit|delete|move|add|upload|resize'));

		$this->testPermission($private ? 'cfContent.private' : 'cfContent.documents');
		$this->basePath = $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'browse', 'private' => $private ? 'private' : 'public', 'editor' => $editor));
		$pubpriv = $private ? 'private/' : 'public/';

		$cfg = clearFusionCMS::getSiteConfig('cfSystemFileStore');
		$storageRoot = $private ? $cfg->privateFiles : $cfg->publicFiles;
		$isFile = !is_dir($active);

		if(!$isFile) {
			$location = rtrim(($private ? __('Private Files', 'cfBackend') : __('Public Files', 'cfBackend')) . ':/' . preg_replace('#^' . $storageRoot . '/?#', '', $active), '/') . '/';
			$isRoot = rtrim(preg_replace('#^' . $storageRoot . '/?#', '', $active), '/') == '';

			$form = new flForm($this->request, 'browserform', $this->request->getSelf() . $this->queryString, true);

			switch($cmd) {
				// Upload files
				case 'upload':

					$lctn = new flFormElementText($form, 'location', $location);
					$lctn->setLabel(__('Upload File(s) To', 'cfBackend'))
						->setDisabled();

					$files = array();
					for($i=1;$i<7;$i++) {
						$files[$i] = new flFormElementFile($form, "upload$i");
						$files[$i]->setLabel(sprintf(__('Upload File %s', 'cfBackend'), $i))->setCSS('primary');
					}

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

					$back = new flFormElementSubmit($form, 'back');
					$back->setCaption(__('Back to Browse Files', 'cfBackend'))->setCSS('flat accent');

					$form->groupElements('upld', array_merge(array($lctn), $files), new flFormDecoratorList(new flFormDecoratorDl()))
					->groupElements('submit', array($submit, $back), new flFormDecoratorList(new flFormDecoratorDl()));

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

						if($back->getValue()) {
							$this->response->redirectTo($this->basePath . "$active{$this->queryString}");
						}

						$m = '';
						$cacheFiles = array();
						for($i=1;$i<7;$i++) {
							if($files[$i]->fileUploaded()) {
								if($files[$i]->moveTo($dst = $active . '/' . ($n = $files[$i]->getFileName()))) {
									cfFileAudit::uploaded($dst);
									$m .= $this->alertMessage('Success', sprintf(__('The file %s has been uploaded.', 'cfBackend'), $n));
									if(!$private)
										$cacheFiles[] = $this->request->getBaseUri(false) . $active . '/' . $n;
								}
								else
									$m .= $this->alertMessage('Error', sprintf(__('The file %s failed to upload.', 'cfBackend'), $n));
							}
						}

						clearFusionCMS::getEventManager()->notify(new flEvent('system.cachePurge', array('files' => $cacheFiles)));

						$this->session->flashSet('cfManagerOpSuccess', $m);
						$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/$active{$this->queryString}");
					}
					break;

				// Create a folder
				case 'add':
					$lctn = new flFormElementText($form, 'location', $location);
					$lctn->setLabel(__('Create Folder In', 'cfBackend'))
						->setDisabled();

					$folder = new flFormElementText($form, 'folder');
					$folder->setLabel(__('New Folder Name', 'cfBackend'))
						->setRequired()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorMaxLength(255))
						->addValidator(new flFormValidatorRegex('/^[a-zA-Z0-9_-]+$/', __('The folder name can only contain the characters a-z, 0-9 and _.', 'cfBackend')));

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

					if($form->isSubmitted() && $form->isValid()) {
						if(@mkdir($dst = $active . '/' . $folder->getValue())) {
							cfFileAudit::newFolder($dst);
							$m = $this->alertMessage('Success', __('The folder has been created.', 'cfBackend'));
						}
						else
							$m = $this->alertMessage('Error', __('The folder could not be created.', 'cfBackend'));
						$this->session->flashSet('cfManagerOpSuccess', $m);
						$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/$active{$this->queryString}");
					}
					break;

				// Rename a folder
				case 'edit':
					$folder = new flFormElementText($form, 'folder', basename($active));
					$folder->setLabel(__('New Folder Name', 'cfBackend'))
						->setRequired()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorMaxLength(255))
						->addValidator(new flFormValidatorRegex('/^[a-zA-Z0-9_-]+$/', __('The folder name can only contain the characters a-z, 0-9 and _.', 'cfBackend')));

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

					if(!$isRoot && $form->isSubmitted() && $form->isValid()) {
						if(@rename($active, $dst = dirname($active) . '/' . $folder->getValue())) {
							cfFileAudit::renameFolder($active, $dst);
							$m = $this->alertMessage('Success', __('The folder has been renamed.', 'cfBackend'));
						}
						else
							$m = $this->alertMessage('Error', __('The folder could not be renamed.', 'cfBackend'));
						$this->session->flashSet('cfManagerOpSuccess', $m);
						$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/" . dirname($active) . '/' . $folder->getValue() . $this->queryString);
					}
					break;

				// delete a folder
				case 'delete':
					$folder = new flFormElementText($form, 'folder', basename($active));
					$folder->setLabel(__('Folder Name', 'cfBackend'))
						->setReadonly()->setDisabled()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorMaxLength(255))
						->addValidator(new flFormValidatorRegex('/^[a-zA-Z0-9_ -]+$/', __('The folder name can only contain the characters a-z, 0-9 and _.', 'cfBackend')));

					$submit = new flFormElementSubmit($form, 'submit');
					$submit->setCaption(__('Permanently Delete Folder', 'cfBackend'))
						->setCSS('danger')
						->setDescription($this->alertMessage('Warning', __('This operation cannot be undone and will delete the folder and all files and folders that it contains.', 'cfBackend')));

					if(!$isRoot && $form->isSubmitted() && $form->isValid()) {
						if($active == $storageRoot) {
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Error', __('The folder could not be deleted.', 'cfBackend')));
							$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/$active{$this->queryString}");
						}
						else {
							$this->deleteFolder($active);
							cfFileAudit::deleteFolder($active);
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The folder and the files and folders that it contains have been deleted.', 'cfBackend')));
							$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/" . dirname($active) . $this->queryString);
						}
					}
					break;

				// Move a folder
				case 'move':
					$toolbarCtnt = $this->alertMessage('Info', __('Click the folder in the tree where you wish to move this folder to.', 'cfBackend'));

					$folder = new flFormElementHidden($form, 'folder', '');

					if(!$isRoot && $form->isSubmitted() && $form->isValid()) {
						if(@rename($active, $dst = rtrim($folder->getValue(), '/\\') . '/' . basename($active))) {
							cfFileAudit::moveFolder($active, $dst);
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The folder has been moved to the new location.', 'cfBackend')));
							$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/" . $folder->getValue() . '/' . basename($active) . $this->queryString);
						}
						else
							$msg = $this->alertMessage('Error', __('The folder could not be moved to the new location.', 'cfBackend'));
					}

					break;
			}

			$content = $form->render($this->tpl->getCodeBuffer());

			if($cmd == 'browse') {

				$fam = new flWidgetFloatingActionMenu();
				$fam->setCSS('[[+css]]');

				$fam->addAction('file_upload', __('Upload to Folder', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'upload', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");
				$fam->addAction('create_new_folder', __('Create Folder', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'add', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");

				if(!$isRoot) {
					$fam->addAction('edit', __('Edit Folder', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'edit', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");
					$fam->addAction('subdirectory_arrow_left', __('Move Folder', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'move', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");
					$fam->addAction('delete', __('Delete Folder', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'delete', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");
				}

				$this->tpl->registerChunk('fam', $fam->render());
			}
			else {
				if(!$form->hasGroup('submit')) {
					$previewCtnt = '<p><a href="' . $this->basePath . "$active{$this->queryString}" . '" class="back button flat accent">' . __('Back to Browse Files', 'cfBackend') . '</a></p>';
				}
			}
		}
		// Working with files
		else if(!empty($active) && is_readable($active)) {

			$form = new flForm($this->request, 'browserform', $this->request->getSelf() . $this->queryString, true);

			switch($cmd) {
				// Rename a file
				case 'edit':
					$file = new flFormElementText($form, 'file', basename($active));
					$file->setLabel(__('New File Name', 'cfBackend'))
						->setRequired()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorMaxLength(255))
						->addValidator(new flFormValidatorRegex('/^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_]+)+$/', __('The file name can only contain the characters a-z, 0-9, - and _, it must also have an extension.', 'cfBackend')));

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

					if($form->isSubmitted() && $form->isValid()) {
						if(@rename($active, $dst = dirname($active) . '/' . $file->getValue())) {
							cfFileAudit::renameFile($active, $dst);
							$m = $this->alertMessage('Success', __('The file has been renamed.', 'cfBackend'));
							if(!$private)
								clearFusionCMS::getEventManager()->notify(new flEvent('system.cachePurge', array('files' => array($this->request->getBaseUri(false) . dirname($active) . '/' . $file->getValue()))));
						}
						else
							$m = $this->alertMessage('Error', __('The file could not be renamed.', 'cfBackend'));
						$this->session->flashSet('cfManagerOpSuccess', $m);
						$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/" . dirname($active) . '/' . $file->getValue() . $this->queryString);
					}
					break;

				// Resize and image
				case 'resize':
					$image = new flImage($active);

					$file = new flFormElementText($form, 'file', basename($active));
					$file->setLabel(__('New File Name', 'cfBackend'))
						->setRequired()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorMaxLength(255))
						->addValidator(new flFormValidatorRegex('/^[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_]+)+$/', __('The file name can only contain the characters a-z, 0-9 and _, it must also have an extension.', 'cfBackend')));

					$width = new flFormElementText($form, 'width', $image->getWidth());
					$width->setLabel(__('New Width', 'cfBackend'))
						->setRequired()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorInteger());

					$height = new flFormElementText($form, 'height', $image->getHeight());
					$height->setLabel(__('New Height', 'cfBackend'))
						->setRequired()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorInteger());

					$crop = new flFormElementCheckbox($form, 'crop', false);
					$crop->setLabel(__('Crop to Size', 'cfBackend'))
						->setDescription($this->alertMessage('Info', __('If Crop to Size ticked the image will be sized to fit the new sizes exactly and excess cropped off. If not ticked then the image will be sized to fit within the given sizes.', 'cfBackend')));

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

					if($form->isSubmitted() && $form->isValid()) {
						if($crop->getValue())
							$image->resizeCrop($width->getValue(), $height->getValue());
						else
							$image->resize($width->getValue(), $height->getValue());

						if($image->save($dst = dirname($active) . '/' . $file->getValue())) {
							cfFileAudit::resize($active, $dst, $image->getWidth(), $image->getHeight());
							if(!$private)
								clearFusionCMS::getEventManager()->notify(new flEvent('system.cachePurge', array('files' => array($this->request->getBaseUri(false) . dirname($active) . '/' . $file->getValue()))));
							$m = $this->alertMessage('Success', __('The image has been resized.', 'cfBackend'));
						}
						else
							$m = $this->alertMessage('Error', __('The image could not be resized.', 'cfBackend'));
						$this->session->flashSet('cfManagerOpSuccess', $m);
						$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/" . dirname($active) . '/' . $file->getValue() . $this->queryString);
					}
					break;

				// delete a file
				case 'delete':
					$file = new flFormElementText($form, 'file', basename($active));
					$file->setLabel(__('File Name', 'cfBackend'))
						->setReadonly()->setDisabled()
						->addValidator(new flFormValidatorRequired())
						->addValidator(new flFormValidatorMaxLength(255))
						->addValidator(new flFormValidatorRegex('/^[a-zA-Z0-9_ -]+(\.[a-zA-Z0-9_]+)+$/', __('The file name can only contain the characters a-z, 0-9 and _, it must also have an extension.', 'cfBackend')));

					$submit = new flFormElementSubmit($form, 'submit');
					$submit->setCaption(__('Permanently Delete File', 'cfBackend'))
						->setCSS('danger')
						->setDescription($this->alertMessage('Warning', __('This operation cannot be undone only continue if you are sure the file is not needed.', 'cfBackend')));

					if($form->isSubmitted() && $form->isValid()) {
						if(@unlink($active)) {
							cfFileAudit::deleteFile($active);
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The file has been deleted.', 'cfBackend')));
							$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/" . dirname($active) . $this->queryString);
						}
						else {
							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Error', __('The file could not be deleted.', 'cfBackend')));
							$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/$active{$this->queryString}");
						}
					}
					break;

				// Move a file
				case 'move':
					$toolbarCtnt = $this->alertMessage('Info', __('Click the folder in the tree where you wish to move this file to.', 'cfBackend'));

					$folder = new flFormElementHidden($form, 'folder', '');

					if($form->isSubmitted() && $form->isValid()) {
						if(@rename($active, $dst = rtrim($folder->getValue(), '/\\') . '/' . basename($active))) {
							cfFileAudit::moveFile($active, $dst);
							if(!$private)
								clearFusionCMS::getEventManager()->notify(new flEvent('system.cachePurge', array('files' => array($this->request->getBaseUri(false) . rtrim($folder->getValue(), '/\\') . '/' . basename($active)))));

							$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The file has been moved to the new location.', 'cfBackend')));
							$this->response->redirectTo($this->assemble('', 'browsefiles', array(), true) . "$pubpriv$editor/browse/" . $folder->getValue() . '/' . basename($active) . $this->queryString);
						}
						else
							$msg = $this->alertMessage('Error', __('The file could not be moved to the new location.', 'cfBackend'));
					}

					break;
			}

			$content = $form->render($this->tpl->getCodeBuffer());

			if($cmd == 'browse') {

				$fam = new flWidgetFloatingActionMenu();
				$fam->setCSS('[[+css]]');

				$fam->addAction('select_all', __('Use File', 'cfBackend'), '#usefile', 'filebrowserUseFile', false, true);
				$fam->addAction('edit', __('Edit File', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'edit', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");

				$previewCtnt = '<div class="filename_title">' . basename($active) . '</div>';
				$previewCtnt .= '<p>' . sprintf(__('File Size: %d', 'cfBackend'), filesize($active)) . '</p>';
				if(preg_match('/\.(jpg|png|gif)$/i', $active)) {
					try {
						$img = new flImage($active);
						$previewCtnt .= '<p>' . sprintf(__('Image Size: %1$d x %2$d', 'cfBackend'), $img->getWidth(), $img->getHeight()) . '</p>';
						$previewCtnt .= '<img src="' . ($private ? $this->assemble('', 'imagepreview') . ltrim(substr($active, strlen($cfg->privateFiles)), '/') : $active) . '" alt="preview" />';

						$fam->addAction('transform', __('Resize Image', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'resize', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");
					}
					catch(flException $e) {
					}
				}

				$fam->addAction('subdirectory_arrow_left', __('Move File', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'move', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");
				$fam->addAction('delete', __('Delete File', 'cfBackend'), $this->assemble('', 'browsefiles') . $rt->assemble(array('cmd' => 'delete', 'private' => $private ? 'private' : 'public', 'editor' => $editor)) . "$active{$this->queryString}");

				$this->tpl->registerChunk('fam', $fam->render());
			}
			else
				$previewCtnt = '<p><a href="' . $this->basePath . "$active{$this->queryString}" . '" class="back button flat accent">' . __('Back to Browse Files', 'cfBackend') . '</a></p>';
		}

		if($cmd == 'move') {
			$this->tpl->getCodeBuffer()->bufferReadyJS("
	\$fl('.treeviewwidget a').bind('click', function(evt) {
		if(evt.target.tagName == 'A') {
			\$fl('[name=\"folder\"]').value(\$fl(evt.target).attr('href').replace(/^.*#/, ''));
			\$fl('#browserform').submit();
		}
		else if(evt.target.tagName == 'SPAN') {
			\$fl('[name=\"folder\"]').value(\$fl(evt.target).parent().attr('href').replace(/^.*#/, ''));
			\$fl('#browserform').submit();
		}

		evt.preventDefault();
		evt.stopPropagation();
		return false;
	});
");
		}

		$rootTree = new flWidgetTreeView($private ? 'cfPrivateFileBrowseTreeView' : 'cfFileBrowseTreeView');
		$rootTree->addNode($this->buildFolderTree(null, $storageRoot, "$editor/$cmd", $active, $cmd == 'move', $private ? __('Private Files', 'cfBackend') : __('Public Files', 'cfBackend')));

		if($editor != '_')
			$this->tpl->getCodeBuffer()->bufferHeadJS("system/modules/$editor/browsefiles.js");

		$this->response
			->setBody($this->tpl->parseDocument('managerFileBrowser',
				'backend_' . $this->request->getSelf(),
				array('page_title' => $private ? __('Private File Browser', 'cfBackend') : __('File Browser', 'cfBackend'),
					'tree' => ($cmd != 'browse' && $cmd != 'move') ? '' : $rootTree->render($this->tpl->getCodeBuffer()),
					'preview' => $previewCtnt,
					'toolbar' => $toolbarCtnt,
					'content' => $content,
					'message' => $msg
			)))
			->sendResponse();
	}
}
