/home/coolpkct/www/websites/cake3.cool.rocks/admin/classes/page.php
<?php
/**
 * Part of SimpleViewer.net portfolio web site package.
 *
 * @package Showkase
 * @author Jack Hardie {@link http://www.jhardie.com}
 * @copyright Copyright (c) 2014, SimpleViewer Inc.
 */
defined('SK_ACCESS')||die('<h1>403: Forbidden</h1>');
$ds = DIRECTORY_SEPARATOR;
require_once "classes{$ds}layer.php";
require_once "classes{$ds}fieldfactory.php";
require_once "classes{$ds}pagereader.php";
require_once "classes{$ds}textfield.php";
require_once "classes{$ds}numberfield.php";
require_once "classes{$ds}nav.php";
require_once "classes{$ds}helpers.php";
require_once "classes{$ds}themeset.php";
require_once "classes{$ds}pageset.php";
require_once "classes{$ds}layerwriter.php";
require_once "smarty{$ds}Smarty.class.php";
/**
 * Models a web page
 *
 * @package Showkase
 */
abstract class Page extends Layer
{
    /**
     * @var object instance of SkConfig
     *
     */
    protected $config;
 
    /**
     * @var object gallery object
     */
    public $gallery;
    
    /**
     * @var integer 'permanent' page ref (might change on repair)
     */
    protected $pageRef;
 
    /**
     * @var string page (template) type
     *
     */
    protected $pageType;
    
    /**
     * @var boolean page type supported by current theme
     *
     */
    protected $supportedPageType = true;
    
    /**
     * @var string plugin name
     */
    protected $plugin;
    
    /**
     * @var string page path rel Showkase
     */
    protected $pagePathRelSvm;
    
    /**
     * @var object theme set
     */
    protected $themeSet;
    
    /**
     * @var array original field objects derived from ini file
     */
    protected $templateDefaultFields = array();
    
    /**
     * @var array of field object from this page template
     */
    protected $layerFields = array();
    
    /**
     * @var array of field objects from theme
     */
    protected $themeFields = array();
    
    /**
     * @var array of field objects with viewer config settings
     */
    protected $viewerFields = array();
    
    /**
     * @var array of site-wide field objects
     */
    protected $siteFields = array();
    
    /**
     * @var string variable to hold gallery list
     */
    protected $galleryList = array('name'=>'galleryList', 'exposed'=>'false', 'value'=>'');
    
    /**
     * @var object instance of Theme
     */
    protected $theme;
    
    /**
     * Constructor
     * Overriden by LibraryPage
     */
    public function __construct(Layer $layer, $ref, $pageType, $path, ThemeSet $themeSet)
    {
        $this->theme = $layer->getTheme();
        $this->config = SkConfig::getInstance();
        $this->pageType = $pageType;
        $this->plugin = strtolower(str_replace('Page', '', get_class($this)));
        $this->themeSet = $themeSet;
        $this->pageRef = $ref;
        $this->pagePathRelSvm = $path;
        $this->settingsPath = $this->pagePathRelSvm.'page.xml';
        $iniFields = array();
        $navFields = array();
        $iniPaths = $this->themeSet->getPageIniPaths($this->pageType);
        if (file_exists($iniPaths['theme']) || file_exists($iniPaths['parent'])) {
            $iniFields = $this->readFieldInis($iniPaths);
        } else {
            $this->supportedPageType = false;
        }
        $navFields = $this->readFieldInis($this->themeSet->getNavIniPaths());
        $navNameDefault = $navFields['ss_navName']->getValue();
        $iniFields = array_merge($navFields, $iniFields);
        foreach ($iniFields as $name => $field) {
            $this->layerDefaults[$name] = $field->getValue();
        }
        $this->incomingFields = $layer->getAccumulatedFields();
        $this->layerFields = $this->mergeFields($iniFields, $this->incomingFields);
        $layerSettings = PageReader::readPageVars($this->settingsPath);
        $this->loadFields($this->layerFields, $layerSettings);
        $this->accumulatedFields = $this->layerFields + $this->incomingFields;
        if (!is_dir($this->pagePathRelSvm)) {
            $this->pagePathRelSvm = $this->addPage($this->pageRef);
            $this->settingsPath = $this->pagePathRelSvm.'page.xml';
        }
        $this->pageUrl = $this->config->getContentUrl().'/'.basename($this->pagePathRelSvm);
    }
    
    /**
     * enforce child classes to set isGallery
     */
    public abstract function isGallery();
    
    /**
     * get Theme
     *
     * @return object
     */
    public function getTheme()
    {
        return $this->theme;
    }
    
    /**
     * returns plugin name (may be different from page type)
     *
     * @return string
     */
    public function getPluginType()
    {
        return $this->plugin;
    }
    
    /**
     * Get page ref
     *
     * @return integer
     */
    public function getRef()
    {
        return $this->pageRef;
    }
    
    /**
     * Get page path
     *
     * @return string
     */
    public function getPagePathRelSvm()
    {
        return $this->pagePathRelSvm;
    }
    
    /**
     * Create new page from master copy
     *
     * @param integer next available reference
     * @return string new page path relative to cwd
     */
    protected function addPage($ref)
    {
        $pageTypes = $this->themeSet->getPageTypes();
        $baseName = isset($pageTypes[$this->pageType]['baseNavName'])
            ? $pageTypes[$this->pageType]['baseNavName']
            : 'Unknown-page-type';
        $basePath = strtolower($baseName);
        $i = 1;
        $dirSuffix = '';
        $nameSuffix = '';
        while (file_exists($pagePathRelSvm = $this->config->getRelativeContentPath(getcwd()).$basePath.$dirSuffix)) {
            $i++;
            $dirSuffix = '-'.$i;
            $nameSuffix = ' '.$i;
        }
        $this->layerFields['ss_navWeight']->setValue($ref);
        $this->layerFields['ss_navName']->setValue($baseName.$nameSuffix);
        $this->cacheViewer($this->config->getAbsoluteViewersPath());
        Filer::skMkdir($pagePathRelSvm, NEW_DIR_MODE, true);
        return $pagePathRelSvm.DIRECTORY_SEPARATOR;
    }
    
    /**
     * Update cached version of viewer code
     *
     * @return integer number of files NOT copied
     * @param string path to cache directory
     */
    public function cacheViewer($cacheDirectory)
    {
        // pages with nothing to copy should not set viewerCore
        if (empty($this->viewerCore)) return;
        $source = 
            PLUGINS_DIRECTORY
            .DIRECTORY_SEPARATOR
            .$this->plugin
            .DIRECTORY_SEPARATOR
            .PLUGINS_MASTER_DIRECTORY
            .DIRECTORY_SEPARATOR
            .$this->viewerCore;
        if (!file_exists($source)) {
            throw new Exception('Cannot find master '.$source);
        }
        if (   !is_dir($cacheDirectory.DIRECTORY_SEPARATOR.$this->pageType)
            && !Filer::skMkdir($cacheDirectory.DIRECTORY_SEPARATOR.$this->pageType, NEW_DIR_MODE, true)
        ) {
            throw new Exception('Cannot create viewer cache for '.$this->pageType);
        }
        $destination =
            $cacheDirectory
            .DIRECTORY_SEPARATOR
            .$this->pageType
            .DIRECTORY_SEPARATOR
            .$this->viewerCore;
        $failures = Filer::rcopy($source, $destination, NEW_DIR_MODE, NEW_FILE_MODE);
        return $failures;
    }
    /**
     * Get all page vars with color prefix
     *
     * @param string color prefix
     * @return array
     */
    public function getAllVars($colorPrefix = '')
    {
        $allVars = array();
        foreach ($this->accumulatedFields as $name=>$field) {
            $prefix =
                $field->type() == 'hexcolor'
                ? $colorPrefix
                : '';
            $allVars[$name] = $prefix.$field->getValue();
        }
        return $allVars;
    }
    /**
     * Get parent page
     *
     * @return integer
     */
    public function getParentPage()
    {
        $parentPage = $this->getLayerVar('ss_parentPage');
        return is_null($parentPage) ? 0 : $parentPage;
    }
    
    /**
     * Set parent page
     *
     * @param integer
     * @return boolean
     */
    public function setParentPage($parent)
    {
        if (isset($this->layerFields['ss_parentPage'])) {
            $this->layerFields['ss_parentPage']->setValue($parent);
            return true;
        }
        return false;
    }
    
    /**
     * Get Nav weight
     *
     * @return float
     */
    public function getNavWeight()
    {
        $weight = $this->getLayerVar('ss_navWeight');
        return is_null($weight)
            ? $this->pageRef
            : $weight;
    }
    
    /**
     * Set Nav weight
     *
     * @return void
     */
    public function setNavWeight($weight)
    {
        if (isset($this->layerFields['ss_navWeight'])) {
            $this->layerFields['ss_navWeight']->setValue($weight);
        }
    }
    
    /**
     * Get Nav Name
     *
     * @return string
     */
    public function getNavName()
    {
        $name = $this->getLayerVar('ss_navName');
        return is_null($name)
            ? 'Unknown'
            : $name;
    }
    
    /**
     * Set Nav name
     *
     * @return void
     */
    public function setNavName($name)
    {
        if (isset($this->layerFields['ss_navName'])) {
            $this->layerFields['ss_navName']->setValue($name);
        }
    }
    
    /**
     * Get Nav Show
     *
     * @return string
     */
    public function getNavShow()
    {
        $show = $this->getLayerVar('ss_navShow');
        return is_null($show)
            ? 'true'
            : $show;
    }
    
    /**
     * Set Nav Show
     *
     * @return void
     * @param boolean
     */
    public function setNavShow($show)
    {
        if (!isset($this->layerFields['ss_navShow'])) return;
        $showString = (bool) $show
            ? 'true'
            : 'false';
        $this->layerFields['ss_navShow']->setValue($showString);
    }
    
    /**
     * Get index page show
     *
     * @return string
     */
    public function getIndexShow()
    {
        $show = $this->getLayerVar('ss_indexShow');
        return is_null($show)
            ? 'true'
            : $show;
    }
    
    /**
     * Set Index Show
     *
     * @return void
     * @param boolean
     */
    public function setIndexShow($show)
    {
        if (!isset($this->layerFields['ss_indexShow'])) return;
        $showString = (bool) $show
            ? 'true'
            : 'false';
        $this->layerFields['ss_indexShow']->setValue($showString);
    }
    
    /**
     * Is this page type supported by current theme
     *
     * @return boolean
     */
    function isSupportedPageType()
    {
        return $this->supportedPageType;
    }
    
    /**
     * Save page html to index.html file
     * 
     * @return void
     */
    public function savePageHtml(Nav $nav, GalleryIndex $galleryIndex)
    {
        if (!$this->supportedPageType) return false;
        $savePath = $this->pagePathRelSvm.'index.html';
        try {
            $pageHtml = $this->makePageHtml($nav, $galleryIndex);
            $bytes = Filer::skPutContents($savePath, $pageHtml);
            if ($bytes === false) throw new Exception('cannot save page html');
        } catch (Exception $e) {
            Board::addExceptionMessage($e);
        }
    }
    
    /**
     * Generate web page html
     *
     * @return string
     */
    private function makePageHtml(Nav $nav, GalleryIndex $galleryIndex)
    {
        $smarty = new Smarty();
        $smarty->force_compile = $this->themeSet->getDevMode();
        $themeDirectory        = $this->themeSet->getCurrentThemeName();
        $themePath             = $this->themeSet->getThemePath();
        $parentPath            = $this->themeSet->getParentPath();
        $themeTemplateDir      = $themePath.THEME_PAGE_TEMPLATE_DIRECTORY;
        $parentTemplateDir     = $parentPath.THEME_PAGE_TEMPLATE_DIRECTORY;
        $hostName              = Helpers::getHost();
        if (
            !file_exists($themeTemplateDir.DIRECTORY_SEPARATOR.$this->pageType.'.tpl')
            && !file_exists($parentTemplateDir.DIRECTORY_SEPARATOR.$this->pageType.'.tpl')
        ) {
	          throw new Exception('Page '.$this->pageRef.' not updated, this theme does not support the <i>'.$this->pageType.'</i> page type.');
        }
        if (empty($parentPath)) {
	          $smarty->setTemplateDir($themeTemplateDir);
        }
        else {
	          $smarty->setTemplateDir(array($themeTemplateDir, $parentTemplateDir));
        }
        $smarty->setCompileDir($this->config->getSmartyCompilePath());
        $smarty->setCacheDir($this->config->getSmartyCachePath());
        $smarty->setConfigDir($this->config->getSmartyConfigsPath());
        // Smarty needs to distinguish between compiled templates from different themes.
        $smarty->compile_id = $themeDirectory;
        $allVars            = $this->getAllVars('#');
        $allGalleryLinks    = $galleryIndex->getGalleryLinks($this);
        $groupGalleryLinks  = $galleryIndex->getGalleryLinks($this, true);
        $allNavLinks        = $nav->getHtml($this->pageRef, true);
        $activeNavLinks     = $nav->getHtml($this->pageRef, false);
        $navLinks =
            isset($allVars['ss_showAllSubNav'])
            && strtolower($allVars['ss_showAllSubNav']) == 'true'
            ? $allNavLinks
            : $activeNavLinks;
        $pageDescription = isset($allVars['ss_pageDescription'])
            ? htmlspecialchars($allVars['ss_pageDescription'], ENT_QUOTES, 'UTF-8')
            : '';
        $imageObjects = array(); 
        if (isset($this->gallery)) {
            $imageObjects = $this->gallery->getImageObjects();
        }
        $ogImageUrl = '';
				if (!empty($groupGalleryLinks[0]) && is_object($groupGalleryLinks[0])) {
				   $ogImageUrl = $hostName.$groupGalleryLinks[0]->thumbUrl;
				
				}
				if (!empty($imageObjects[0]) && is_object($imageObjects[0])) {
				   $ogImageUrl = $hostName.$imageObjects[0]->imageAbsUrl;
				}
        $smarty->assign($allVars);
        $smarty->assign('ss_images', $imageObjects);
        $smarty->assign('ss_SEOContent', $this->SeoContent($allVars, $imageObjects, $pageDescription));
        $smarty->assign('ss_pageDescription', $pageDescription);
        $smarty->assign('ss_showkaseVersion', SK_VERSION);
        $smarty->assign('ss_showkaseBuild', SK_BUILD);
        $smarty->assign('ss_pageRef', $this->pageRef);
        $smarty->assign('ss_pageType', $this->pageType);
        $smarty->assign('ss_pageVersion', $this->themeSet->getVersionString($this->pageType));
        $smarty->assign('ss_pageUrl', $this->pageUrl);
        $smarty->assign('ss_hostName', $hostName);
        $smarty->assign('ss_navLinks', $navLinks);
        $smarty->assign('ss_allNavLinks', $allNavLinks);
        $smarty->assign('ss_activeNavLinks', $activeNavLinks);
        $smarty->assign('ss_siteUrl', $this->config->getContentUrl());
        $smarty->assign('ss_themesUrl', $this->config->getThemesAbsUrl());
        $smarty->assign('ss_themeUrl', $this->config->getThemesAbsUrl().'/'.$themeDirectory);
        $smarty->assign('ss_viewersUrl', $this->config->getViewersUrl());
        $smarty->assign('ss_allGalleryLinks', $allGalleryLinks);
        $smarty->assign('ss_groupGalleryLinks', $groupGalleryLinks);
        $smarty->assign('ss_ogTitle', htmlspecialchars($allVars['ss_pageTitle'], ENT_QUOTES, 'UTF-8'));
        $smarty->assign('ss_ogImageUrl', $ogImageUrl);
        return $smarty->fetch('file:'.$this->pageType.'.tpl');
    }
    
    /**
     * Create SEO html for gallery pages
     *
     * @return string html
     * @param array all theme, viewer and page vars
     * @param array of image objects
     * @param string page description
     */
    private function SeoContent(array $allVars, array $imageObjects, $pageDescription)
    {
        if (
           !isset($this->gallery)
           || !isset($allVars['addSEOContent'])
           || strtolower($allVars['addSEOContent']) != 'true'
        ) {
            return '';
        } 
        $imageTags = '';
        foreach ($imageObjects as $image) {
            // SimpleViewer does not support image titles
            $imageTitle = htmlspecialchars($image->title, ENT_QUOTES, 'UTF-8');
            $imageCaption = htmlspecialchars($image->caption, ENT_QUOTES, 'UTF-8');
            $imageTitleAttribute = !empty($imageTitle) ? $imageTitle : $imageCaption;
            $imageAltAttribute = !empty($imageCaption) ? $imageCaption : $imageTitle;
            $imageTags .= '
  <p>
    <img title="'.$imageTitleAttribute.'" alt="'.$imageAltAttribute.'" src="'.$image->imageAbsUrl.'"><br>
    '.$imageTitle.'<br>
    '.$imageCaption.'
  </p>';
        }
        $titleHtml = empty($allVars['galleryTitle'])
            ? ''
            : '<h1>'.$allVars['galleryTitle'].'</h1>';
        $descriptionHtml = empty($pageDescription)
            ? ''
            : '<p>'.$pageDescription.'</p>';
        $html = <<<EOD
<noscript>
  <!-- Image gallery content for non-javascript devices -->
  {$titleHtml}
  {$descriptionHtml}
  {$imageTags}
</noscript>
EOD;
        return $html;
    }
    
    /**
     * Change page directory
     *
     * @param string new directory name
     * @return boolean success
     */
    public function renameFolder($newPath)
    {
        $oldPath = $this->pagePathRelSvm;
        if (file_exists($newPath)) {
            throw new Exception('Please choose a different name, folder <i>'.basename($newPath).'</i> already exists.');
        }
        if (Filer::skRename($oldPath, $newPath)) {
            $this->pagePathRelSvm = $newPath;
            $this->settingsPath = $this->pagePathRelSvm.'page.xml';
            return true;
        }
        throw new Exception('Cannot rename the page folder');
    }
    
    /**
     * import settings from gallery xml file
     *
     * @return void
     */
    public function importGallery()
    {
        if (!$this->isGallery()) return false;
        $gallerySettings = $this->gallery->importConfig();
        foreach ($gallerySettings as $name=>$value) {
            if (isset($this->layerFields[$name])) {
                $this->layerFields[$name]->setValue($value);
            } else {
                $this->layerFields[$name] = FieldFactory::make(array(
                    'name'   =>$name,
                    'type'   =>'text',
                    'exposed'=>'false',
                    'value'  =>$value)
                );
            }
        }
        $imagesData = $this->gallery->readImagesData();
        $this->gallery->makeImageObjects($imagesData);
    }
    
}