<?php

/**
 * Class file for managing social media images.
 *
 * 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) 2015 - 2017 clearFusionCMS. All rights reserved.
 * @link http://clearfusioncms.com
 */

/**
 * cfBackendSocialimgsAction Class
 *
 * Action class to list and manage social media images.
 *
 * @package clearFusionCMS
 */
class cfBackendSocialimgsAction extends cfBackendControllerAction {
	/**
	 * Process the action.
	 */
	function process() {
		$this->testPermission('cfSocialImg.canedit');
		$this->breadcrumbTrail->addCrumb(__('Social Media', 'cfBackend'), $this->assemble('', 'socialimgs'));

		$content = '';

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

		// Build routes
		$edRoute = new flRouterRoute('edit/:id', array(), array('id' => '\d+'));
		$addRoute = new flRouterRoute('add');
		$deleteRoute = new flRouterRoute('delete/:id', array(), array('id' => '\d+'));
		$pageRoute = new flRouterRoute(':page', array('page' => 0), array('page' => '\d+'));

		// If edit image
		if ($params = $edRoute->match($this->request->getParam('*', array()))) {
			if ($active = $params['id']) {
				$this->breadcrumbTrail->addCrumb(__('Edit Image', 'cfBackend'), $this->assemble('', 'socialimgs', array('edit', $active)));

				if (($content = $this->lockObject('content.social.image', $active)) === true) {
					$content = $this->processForm($active);
				}

				$this->renderPage(__('Social Media Images', 'cfBackend'),
					$this->renderBlock(__('Edit Image', 'cfBackend'), $content, '', $msg)
				);

			}
		} // If add image
		else if ($params = $addRoute->match($this->request->getParam('*', array()))) {
			$this->breadcrumbTrail->addCrumb(__('Add Image', 'cfBackend'), $this->assemble('', 'socialimgs', array('add')));

			$content = $this->processForm(null);

			$this->renderPage(__('Social Media Images', 'cfBackend'),
				$this->renderBlock(__('Add Image', 'cfBackend'), $content, '', $msg)
			);

		} // If delete image
		else if ($params = $deleteRoute->match($this->request->getParam('*', array()))) {
			$this->testPermission('cfSocialImg.candelete');

			if ($active = $params['id']) {
				if (($content = $this->lockObject('content.social.image', $active)) === true) {
					$this->breadcrumbTrail->addCrumb(__('Delete Image', 'cfBackend'), $this->assemble('', 'socialimgs', array('delete', $active)));

					$content = $this->processDeleteForm($active, true);

					$this->renderPage(__('Social Media Images', 'cfBackend'),
						$this->renderBlock(__('Delete Image', 'cfBackend'), $content, '', $msg)
					);
				}
			}
		} // Else paging
		else if ($params = $pageRoute->match($this->request->getParam('*', array()))) {

			// Build action menu
			if($this->user->hasPermission('cfSocialImg.canadd')) {
				$fam = new flWidgetFloatingActionMenu();
				$fam->setCSS('[[+css]]');
				$fam->addAction('add', __('Add Image', 'cfBackend'), $this->assemble('', 'socialimgs', array('add')));
				$this->tpl->registerChunk('fam', $fam->render());
			}

			$fileCfg = clearFusionCMS::getSiteConfig('cfSystemFileStore');

			$found = $this->db->fetchOne('SELECT COUNT(*) FROM cf_socialimages_' . clearFusionCMS::getSite());

			$pagination = new flWidgetPagination($params['page'], $found);
			$pagination->setRoute($this->router->getRoute('cfManager'), array('action' => 'socialimgs'), '*');

			$results = $this->db->fetchAll('SELECT * FROM cf_socialimages_' . clearFusionCMS::getSite() . ' ORDER BY imageid DESC LIMIT ' . $pagination->getStart() . ', ' . $pagination->getRows());

			if(count($results)) {
				$table = new flWidgetTable();
				$table->setClass('tablewidget bordered striped rowhover responsive')
					->setHeadings(__('Image', 'cfBackend'), __('Title', 'cfBackend'), __('Operation', 'cfBackend'))
					->setColData('image', 'title', 'ops')
					->skipEncode('image', 'ops');

				foreach($results as $img) {

					$idHash = md5($img['imageid']);
					$file = $fileCfg->publicStorage . '/content_social/' . clearFusionCMS::getSite() . '/' . $idHash[0] . '/' . $idHash[1] . '/' . $img['imageid'] . $img['ext'];

					$img['image'] = '<img src="' . $file . '?cache=' . time() . '" style="max-width: 15rem" />';
					$img['ops'] = "<a href=\"" . $this->assemble('', 'socialimgs', array('edit', $img['imageid'])) . "\">" . __('Edit', 'cfBackend') . "</a>";

					$table->addRow($img);
				}

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

			$content .= '<p>' . sprintf(__('Found: %d images', 'cfBackend'), $found) . '</p>';

			$this->renderPage(__('Social Media Images', 'cfBackend'),
				$this->renderBlock(__('Images', 'cfBackend'), $content, '', '', $pagination->render())
			);
		} else {
			throw new flExceptionNotFound();
		}
	}

	/**
	 * Process the form for adding/editing the image.
	 *
	 * @param int $id The ID of the image to edit or null when adding an image.
	 * @return string The form HTML
	 * @throws clearFusionCMSException
	 */
	protected function processForm($id) {
		$fileCfg = clearFusionCMS::getSiteConfig('cfSystemFileStore');

		$edit = $id ? true : false;

		if($edit) {
			$data = $this->db->fetchRow('SELECT title, ext FROM cf_socialimages_' .  clearFusionCMS::getSite() . ' WHERE imageid=?', $id);
		}
		else {
			$data = array('title' => '', 'ext' => '');
		}

		$form = new flForm($this->request, 'imgform', $this->assemble('', 'socialimgs', $edit ? array('edit', $id) : array('add')), true);

		$title = new flFormElementText($form, 'title', $data['title']);
		$title->setLabel(__('Image Title', 'cfBackend'))
			->setRequired()
			->addValidator(new flFormValidatorRequired());

		// Display the thumb of the current social media image
		$socialImgPane = new flFormElementPane($form, 'socialimgthumb', '');
		if($edit && !empty($data['ext'])) {
			$idHash = md5($id);
			$file = $fileCfg->publicStorage . '/content_social/' . clearFusionCMS::getSite() . '/' . $idHash[0] . '/' . $idHash[1] . '/' . $id . $data['ext'];

			$socialImgPane->setContent('<img src="' . $file . '?cb=' . time() . '" />');
		}

		$socialImgFile = new flFormElementFile($form, 'socialimgfile');
		$socialImgFile->setLabel(__('Upload a Social Media Image', 'cfBackend'))->setCSS('primary')
			->setDescription(__('The current recommended size for images is 1600 x 800 pixels with a 120 pixel left and right margin. File size must be 1MB or less for Twitter.', 'cfBackend'));

		$socialImgURI = new flFormElementUri($form, 'socialimguri');
		$socialImgURI->setLabel(__('Download Image From', 'cfBackend'))
			->setDescription(__('Address to download the image from.', 'cfBackend'))
			->addValidator(new flFormValidatorUri());

		if($edit) {
			$update = new flFormElementSubmit($form, 'update');
			$update->setCaption(__('Update', 'cfBackend'))->setCSS('primary');

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

				$elems = array($update, $delete);
			}
		}
		else {
			$create = new flFormElementSubmit($form, 'create');
			$create->setCaption(__('Add Image', 'cfBackend'))->setCSS('primary');

			$elems = array($create);
		}

		$form
			->groupElements('leftcolimg', array($title, $socialImgFile, $socialImgURI))
			->groupElements('rightcolimg', array($socialImgPane))
			->groupElements('submit', $elems, new flFormDecoratorList(new flFormDecoratorDl()));

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

			// If remove social image
			if(isset($delete) && $delete->getValue()) {
				$this->response->redirectTo($this->assemble('', 'socialimgs', array('delete', $id), true));
			}
			else {

				// If creating a new image
				if(!$edit) {
					$this->db->insert('cf_socialimages_' . clearFusionCMS::getSite(), array(
						'title' => $title->getValue(),
						'ext' => ''
					));
					$id = $this->db->insertID();
					cfSocialImagesAudit::created($id, $title->getValue());
				}
				else {
					$this->db->update('cf_socialimages_' . clearFusionCMS::getSite(), array(
						'title' => $title->getValue()
					), 'imageid=?', $id);
					cfSocialImagesAudit::update($id, $title->getValue(), $data);
				}

				$this->session->flashSet('cfManagerOpSuccess', $this->alertMessage('Success', __('Image saved.', 'cfBackend')));

				// If upload file given
				if($socialImgFile->fileUploaded() && ($fileName = $this->getSocialFilename($id, $socialImgFile->getFileName()))) {
					$socialImgFile->moveTo($fileCfg->publicStorage . $fileName);
				} // Else if download file give
				else if($socialImgURI->getValue() != '' && ($fileName = $this->getSocialFilename($id, $socialImgURI->getValue()))) {

					// Get the image from a remote source
					$http = new flHttpClient($socialImgURI->getValue());
					if ($http->sendRequest() && $http->getResponseCode() == 200) {
						// Save the file data
						@file_put_contents($fileCfg->publicStorage . $fileName, $http->getBody());
						unset($http); // Release the object & memory
					}
				}

				// File file present then resize and remember it
				if (isset($fileName)) {
					if (is_readable($fileCfg->publicStorage . $fileName)) {
						try {
							// Resize and save in place
							$img = new flImage($fileCfg->publicStorage . $fileName);

							switch ($img->getType()) {
								case IMAGETYPE_GIF:
									$ext = '.gif';
									break;
								case IMAGETYPE_JPEG:
									$ext = '.jpg';
									break;
								case IMAGETYPE_PNG:
									$ext = '.png';
									break;
							}
							$this->db->update('cf_socialimages_' . clearFusionCMS::getSite(), array('ext' => $ext), 'imageid=?', $id);

							// Purge the caches
							clearFusionCMS::getEventManager()->notify(new flEvent('system.cachePurge', array('files' => array(
								$this->request->getBasePath(true) . $fileCfg->publicStorage . $fileName
							))));

						} catch (flException $e) {
							// Not an image
							@unlink($fileCfg->publicStorage . $fileName);
							$this->db->update('cf_socialimages_' . clearFusionCMS::getSite(), array('ext' => ''), 'imageid=?', $id);
						}
					}
				}

				// Redirect to edit
				$this->response->redirectTo($this->assemble('', 'socialimgs', array('edit', $id), true));
			}
		}

		return $form->render($this->tpl->getCodeBuffer());
	}


	/**
	 * Process the delete image form.
	 *
	 * @param int $id The ID of the image to delete.
	 * @return string The form HTML
	 * @throws clearFusionCMSException
	 */
	protected function processDeleteForm($id) {
		$fileCfg = clearFusionCMS::getSiteConfig('cfSystemFileStore');

		$data = $this->db->fetchRow('SELECT title, ext FROM cf_socialimages_' .  clearFusionCMS::getSite() . ' WHERE imageid=?', $id);

		$form = new flForm($this->request, 'imgform', $this->assemble('', 'socialimgs', array('delete', $id)), true);

		$title = new flFormElementText($form, 'title', $data['title']);
		$title->setLabel(__('Image Title', 'cfBackend'))
			->setRequired()
			->setReadonly()
			->addValidator(new flFormValidatorRequired());

		// Display the thumb of the current social media image
		$socialImgPane = new flFormElementPane($form, 'socialimgthumb', '');
		if(!empty($data['ext'])) {
			$idHash = md5($id);
			$file = $fileCfg->publicStorage . '/content_social/' . clearFusionCMS::getSite() . '/' . $idHash[0] . '/' . $idHash[1] . '/' . $id . $data['ext'];

			$socialImgPane->setContent('<img src="' . $file . '?cb=' . time() . '" />');
		}


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

		$form
			->groupElements('leftcolimg', array($title, $delete))
			->groupElements('rightcolimg', array($socialImgPane));

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

			// If remove social image
			if($delete->getValue()) {

				// Delete from docs
				$this->db->update('cf_content_' . clearFusionCMS::getSite(), array(
					'ogimageid' => 0
				), 'ogimageid=?', $id);

				$this->db->update('cf_content_' . clearFusionCMS::getSite(), array(
					'twitterimageid' => 0
				), 'twitterimageid=?', $id);

				// Issue notification event!
				clearFusionCMS::getEventManager()->notify(new flEvent('system.socialImageDeleted', array(
					'id' => $id
				)));

				// Delete the image
				$this->getSocialFilename($id, 'delete.png');
				$this->db->delete('cf_socialimages_' . clearFusionCMS::getSite(), 'imageid=?', $id);

				cfSocialImagesAudit::delete($id, $data);

				$this->response->redirectTo($this->assemble('', 'socialimgs', array(), true));
			}
		}

		return $form->render($this->tpl->getCodeBuffer());
	}

	/**
	 * Get the filename to store the social image image under.
	 *
	 * Folders are created if required and old images are removed.
	 *
	 * @param int $id The ID of the story.
	 * @param string $fileName The file name for the image.
	 * @return bool|string The filename to use or false if failed.
	 */
	protected function getSocialFilename($id, $fileName) {
		// Calculate the storage path and file name
		$cfg = clearFusionCMS::getSiteConfig('cfSystemFileStore');
		$pathInfo = pathinfo($fileName);
		$idHash = md5($id);
		$path = '/content_social/' . clearFusionCMS::getSite() . '/' . $idHash[0] . '/' . $idHash[1] . '/';

		// Create the folder if not already present
		if(!is_writable($cfg->publicStorage . $path)) {
			if(!@mkdir($cfg->publicStorage . $path, 0777, true))
				return false;
		}

		// Remove the old file if any
		foreach(glob($cfg->publicStorage . $path . $id . '.*') as $f) {
			@unlink($f);
		}

		return isset($pathInfo['extension']) ? ($path . $id . '.' . $pathInfo['extension']) : false;
	}
}
