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

/**
 * cfBackendSitemgrAction Class
 *
 * Action class to manage the sites supported by the system.
 *
 * @package clearFusionCMS
 */
class cfBackendSitemgrAction extends cfBackendControllerAction {
	/**
	 * Process the action.
	 */
	function process() {
		$this->testPermission('cfContent.managesites');
		$this->breadcrumbTrail->addCrumb(__('Manage Sites', 'cfBackend'), $this->assemble('', 'sitemgr'));

		// Get list of locales
		$folders = glob(FLAPPPATH . 'lang/*', GLOB_ONLYDIR);
		$locales = array('en_US' => 'en_US');
		foreach($folders as $path) {
			$path = basename($path);
			$locales[$path] = $path;
		}

		$siteMgr = new cfSiteManager($this->db);

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

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

		if($addSite) {
			// Build form for adding sites
			$formAdd = new flForm($this->request, 'addform', $this->assemble('', 'sitemgr', array('_add')), true);

			$newName = new flFormElementText($formAdd, 'newshort');
			$newName->setLabel(__('Short Name', 'cfBackend'))
				->setRequired()
				->setDescription(__('Short name for site for use in code.', 'cfBackend'))
				->addValidator(new flFormValidatorRegex(__('/^[a-z0-9][a-z0-9_]+$/', 'The short name can only contain letters, numbers and _ characters.', 'cfBackend')))
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(1))
				->addValidator(new flFormValidatorMaxLength(32));

			$newDomain = new flFormElementText($formAdd, 'newdomain');
			$newDomain->setLabel(__('Domain Name', 'cfBackend'))
				->setDescription(__('The domain name that you want the site to appear under e.g. www.example.com', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRegex(__('/^[a-z0-9_\.-]+$/', 'The domain name can only contain letters, numbers, ., - and _ characters.', 'cfBackend')))
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(3))
				->addValidator(new flFormValidatorMaxLength(255));

			$newDisp = new flFormElementText($formAdd, 'newdisp');
			$newDisp->setLabel(__('Site Name', 'cfBackend'))
				->setDescription(__('The site name to display in the manager.', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(1))
				->addValidator(new flFormValidatorMaxLength(64));

			$newSSL = new flFormElementCheckbox($formAdd, 'sslonly');
			$newSSL->setLabel(__('Site Only Available On SSL', 'cfBackend'));

			$newLocale = new flFormElementSelect($formAdd, 'newlocale', '', $locales);
			$newLocale->setLabel(__('Site Locale', 'cfBackend'));

			// Access & edit permission
			$ac = new flAcMgr($this->db);
			$availEdPerms = array('' => __('[None]', 'cfBackend'));
			foreach($ac->getPermissionsInGroup('ctntedt') as $p => $d) {
				if($this->user->hasPermission($p))
					$availEdPerms[$p] = $d;
			}
			$edPerm = new flFormElementSelect($formAdd, 'edperm', '', $availEdPerms);
			$edPerm->setLabel(__('Edit Permission', 'cfBackend'))
				->setDescription(__('This permission will be required to edit the site, [None] allows all backend users to edit the site.', 'cfBackend'));

			$twitter = new flFormElementText($formAdd, 'twitter');
			$twitter->setLabel(__('Twitter Username', 'cfBackend'))
				->setDescription(__('The optional twitter username the site is attributed to.'))
				->addValidator(new flFormValidatorMaxLength(15))
				->addValidator(new flFormValidatorRegex('/^@?[a-z0-9_]+$/i'));

			$aliases = new flFormElementWYSIWYG($formAdd, 'aliases');
			$aliases->setLabel(__('Aliases', 'cfBackend'))
				->setDescription(__('Domain names that will be redirected to this site, one per line.', 'cfBackend'))
				->addValidator(new flFormValidatorMaxLength(16384))
				->setRows(20)
				->editorSize('100%', '225')
				->setDB($this->db)
				->editorModule($this->getCodeEditorModule())
				->editorContentType('text');

			new flFormElementPane($formAdd, 'info', $this->alertMessage('Info', __('The settings from the current site will be copied to the new site when it is created.', 'cfBackend')));

			$addSubmit = new flFormElementSubmit($formAdd, 'add');
			$addSubmit->setCaption(__('Add New Site', 'cfBackend'))->setCSS('primary');

			$formAdd->focusElement($newName);

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

			if($formAdd->isSubmitted() && $formAdd->isValid()) {
				if($siteMgr->createSite($newName->getValue(), $newDomain->getValue(), $newDisp->getValue(), clearFusionCMS::getSite(), $newLocale->getValue(), $twitter->getValue(), $edPerm->getValue(), preg_split('/\s+/', trim($aliases->getValue())), $newSSL->getValue())) {
					cfSiteAudit::created($newDisp->getValue());
					$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('The new website has been added.', 'cfBackend')));
					$this->response->redirectTo($this->assemble('', 'sitemgr', array($newName->getValue()), true));
				}
				else
					$edmsg = $this->alertMessage('Error', __('Unable to create new site.', 'cfBackend'));
			}

			$content = $this->renderBlock(__('Add New Site', 'cfBackend'), $formAdd->render($this->tpl->getCodeBuffer()), '', $edmsg);
		}
		else if($edType) {
			$data = $this->db->fetchRow('SELECT domain,displayname,redirectto,locale,editperm,twitterusername,puressl FROM cf_sites WHERE shortname=? && redirectto=\'\'', $edType);
			$alts = array();
			$results = $this->db->query('SELECT domain FROM cf_sites WHERE shortname=? && redirectto != \'\'', $edType);
			while($row = $results->fetch())
				$alts[] = $row['domain'];

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

			$name = new flFormElementText($form, 'shortname', $edType);
			$name->setLabel(__('Short Name', 'cfBackend'))
				->setReadonly()
				->setDisabled()
				->setDescription(__('Short name for site for use in code, this name cannot be changed.', 'cfBackend'))
				->addValidator(new flFormValidatorRegex('/^[a-z0-9_]+$/', __('The short name can only contain letters, numbers and _ characters.', 'cfBackend')))
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(1))
				->addValidator(new flFormValidatorMaxLength(32));

			$domain = new flFormElementText($form, 'domain', $data['domain']);
			$domain->setLabel(__('Domain Name', 'cfBackend'))
				->setDescription(__('The domain name that you want the site to appear under e.g. www.example.com', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRegex('/^[a-z0-9_\.-]+$/', __('The domain name can only contain letters, numbers, ., - and _ characters.', 'cfBackend')))
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(3))
				->addValidator(new flFormValidatorMaxLength(255));

			$disp = new flFormElementText($form, 'disp', $data['displayname']);
			$disp->setLabel(__('Site Name', 'cfBackend'))
				->setDescription(__('The site name to display in the manager.', 'cfBackend'))
				->setRequired()
				->addValidator(new flFormValidatorRequired())
				->addValidator(new flFormValidatorMinLength(1))
				->addValidator(new flFormValidatorMaxLength(64));

			$ssl = new flFormElementCheckbox($form, 'sslonly', $data['puressl']);
			$ssl->setLabel(__('Site Only Available On SSL', 'cfBackend'));

			$locale = new flFormElementSelect($form, 'newlocale', $data['locale'], $locales);
			$locale->setLabel(__('Site Locale', 'cfBackend'))
				->setDescription(__('Changing the locale will require that you rebuild the search index, it will also replace the current stop word list.', 'cfBackend'));

			// Access & edit permission
			$ac = new flAcMgr($this->db);
			$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(__('This permission will be required to edit the site, [None] allows all backend users to edit the site.', 'cfBackend'));

			$twitter = new flFormElementText($form, 'twitter', $data['twitterusername']);
			$twitter->setLabel(__('Twitter Username', 'cfBackend'))
				->setDescription(__('The optional twitter username the site is attributed to.'))
				->addValidator(new flFormValidatorMaxLength(15))
				->addValidator(new flFormValidatorRegex('/^@?[a-z0-9_]+$/i'));

			$aliases = new flFormElementWYSIWYG($form, 'aliases', implode("\n", $alts));
			$aliases->setLabel(__('Aliases', 'cfBackend'))
				->setDescription(__('Domain names that will be redirected to this site, one per line.', 'cfBackend'))
				->addValidator(new flFormValidatorMaxLength(16384))
				->setRows(20)
				->editorSize('100%', '225')
				->setDB($this->db)
				->editorModule($this->getCodeEditorModule())
				->editorContentType('text');

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

			if($edType !== 'default_site' && $edType != clearFusionCMS::getSite()) {
				$delTypeSub = new flFormElementSubmit($form, 'delete');
				$delTypeSub->setCaption(__('Delete Site', 'cfBackend'))
					->setCSS('danger');
			}

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

			$form->focusElement($name);

			if($form->isSubmitted() && $form->isValid()) {
				if($siteMgr->updateSite($edType, $domain->getValue(), $disp->getValue(), preg_split('/\s+/', trim($aliases->getValue())), $locale->getValue(), $edPerm->getValue(), $twitter->getValue(), $ssl->getValue())) {
					$edmsg = $this->alertMessage('Success', __('The website information has been updated.', 'cfBackend'));
					cfSiteAudit::update($disp->getValue(), [
						'site' => $data,
						'aliases' => $alts
					]);
				}
				else
					$edmsg = $this->alertMessage('Error', __('Unable to update the website information, please try again.', 'cfBackend'));

				$this->cache->flush();

				if(isset($delTypeSub) && $delTypeSub->getValue())
					$this->response->redirectTo($this->assemble('', 'sitemgr', array($edType, 'delete')));
			}
		}
		else if($delType) {
			$data = $this->db->fetchRow('SELECT shortname,domain,displayname,locale FROM cf_sites WHERE shortname=? && redirectto=\'\'', $delType);

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

			// Don't allow delete of current site
			if($delType != clearFusionCMS::getSite()) {

				$name = new flFormElementText($form, 'shortname', $delType);
				$name->setLabel(__('Short Name', 'cfBackend'))
					->setReadonly()
					->setDisabled()
					->addValidator(new flFormValidatorRegex('/^[a-z0-9][a-z0-9_]+$/', __('The short name can only contain letters, numbers and _ characters.', 'cfBackend')))
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMinLength(1))
					->addValidator(new flFormValidatorMaxLength(32));

				$domain = new flFormElementText($form, 'domain', $data['domain']);
				$domain->setLabel(__('Domain Name', 'cfBackend'))
					->setReadonly()
					->setDisabled()
					->addValidator(new flFormValidatorRegex('/^[a-z0-9_\.-]+$/', __('The domain name can only contain letters, numbers, ., - and _ characters.', 'cfBackend')))
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMinLength(3))
					->addValidator(new flFormValidatorMaxLength(255));

				$disp = new flFormElementText($form, 'disp', $data['displayname']);
				$disp->setLabel(__('Site Name', 'cfBackend'))
					->setReadonly()
					->setDisabled()
					->addValidator(new flFormValidatorRequired())
					->addValidator(new flFormValidatorMinLength(1))
					->addValidator(new flFormValidatorMaxLength(64));

				$locale = new flFormElementSelect($form, 'newlocale', $data['locale'], $locales);
				$locale->setLabel(__('Site Locale', 'cfBackend'))
					->setReadonly()
					->setDisabled();

				$delSubmit = new flFormElementSubmit($form, 'deletetype');
				$delSubmit->setCaption(__('Permanently Delete The Website', 'cfBackend'))
					->setCSS('danger')
					->setDescription($this->alertMessage('Warning', __('This operation cannot be undone, all site data will be lost!', 'cfBackend')));

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

					$alts = [];
					$results = $this->db->query('SELECT domain FROM cf_sites WHERE shortname=? && redirectto != \'\'', $delType);
					while($row = $results->fetch())
						$alts[] = $row['domain'];
					cfSiteAudit::delete($data['displayname'], [
						'site' => $data,
						'aliases' => $alts
					]);

					$siteMgr->deleteSite($delType);

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

		$typeRootTree = new flWidgetTreeView();
		$sites = $siteMgr->listSites();

		if(count($sites)) {
			$typeTree = new flWidgetTreeView();
			foreach($sites as $sn => $dn) {
				$typeTree->addNode(new flWidgetTreeLinkNode($dn, $this->assemble('', 'sitemgr', array($sn))))
					->setLastNodeActive($sn == $edType || $sn == $delType);
			}

			$typeRootTree->addNode(new flWidgetTreeChildNode(__('Websites', 'cfBackend'), $typeTree, null));
		}
		else
			$typeRootTree->addNode(new flWidgetTreeNode(__('Websites', 'cfBackend'), flWidgetTreeNode::CONTAINER));

		$tree = $typeRootTree->render();

		if($edType || $delType) {
			if(($content = $this->lockObject('cfSiteMgr', $edType ? $edType : $delType, true)) === true)
				$content = $this->renderBlock($edType ? __('Edit Site Information', 'cfBackend') : __('Delete Website', 'cfBackend'), $form->render($this->tpl->getCodeBuffer()), '', $edmsg);
		}
		else if(!$addSite)
			$content = '';


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

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

		$this->renderPage(__('Manage Sites', 'cfBackend'), $content, $this->renderBlock(__('Websites', 'cfBackend'), $tree));
	}
}
