/home/coolpkct/www/websites/cake3.cool.rocks/admin/classes/layer.php
<?php
/**
 * Part of Showkase web site management 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>');
require_once "classes{$ds}fieldfactory.php";
require_once "classes{$ds}layerwriter.php";

/**
 * Site, Theme, Viewer, Page are layers
 * Fields are piped through the layers
 *
 * @package Showkase
 */
 abstract class Layer
 {
    /**
     * @var array of field objects to appear in the layer customize screen
     *
     */
    protected $layerFields = array();
    
    /**
     * @var array of default values from layer ini file
     */
    protected $layerDefaults = array();
    
    /**
     * @var array of incoming fields from previous layer
     */
    protected $incomingFields = array();
    
    /**
     * @var array of field objects accumulated from this and previous layers
     */
    protected $accumulatedFields = array();
    
    /**
     * @var string path to settings file
     */
    protected $settingsPath;
    
    /**
     * @var object Themeset
     */
    protected $themeSet;
        
    /**
     * get array of field objects from ini file
     *
     * @param string path to file
     * @return array of field objects or false for unsupported page type
     */
    /*
    protected function readFieldsIni($path)
    {
        $fields = array();
        if (!file_exists($path)) throw new Exception('Cannot find '.basename($path));
        $iniVars = parse_ini_file($path, true);
        if ($iniVars === false) throw new Exception('Cannot read '.basename($path));
        foreach ($iniVars as $name => $var) {
            if (!is_array($var)) throw new Exception('Error in ini file: '.$name.' is not an array');
            $fields[$name] = FieldFactory::make($var + array('name'=>$name));
        }
        return $fields;
    }
    */
    
    /**
     * get array of field objects from ini file
     *
     * @param array of paths to theme and parent ini files
     * @return array of field objects or false for unsupported page type
     */
    protected function readFieldInis(array $paths)
    {
        $themeIniVars = array();
        $parentIniVars = array();
        $fields = array();
        if (!empty($paths['parent'])) {
            $parentIniVars = parse_ini_file($paths['parent'], true);
            if ($parentIniVars === false) throw new Exception('Cannot read parent theme ini file '.basename($$paths['parent']));
        }
        if (file_exists($paths['theme'])) {
	          $themeIniVars = parse_ini_file($paths['theme'], true);
        }
        if ($themeIniVars === false) throw new Exception('Cannot read theme ini file '.basename($paths['theme']));
        // parent theme determines order in customize pages
        $union = $parentIniVars + $themeIniVars;
        foreach ($union as $name => $var) {
            if (!is_array($var)) throw new Exception('Error in ini file: '.$name.' is not an array');
            $fieldVars = array();
            if (isset($parentIniVars[$name])) {
	              $fieldVars = $parentIniVars[$name];
	              if (isset($themeIniVars[$name])) {
		              $fieldVars = array_merge($parentIniVars[$name], $themeIniVars[$name]);
	              }
            }
            else {
                $fieldVars = $themeIniVars[$name];
            }
            $fields[$name] = FieldFactory::make($fieldVars + array('name'=>$name));
        }
        return $fields;
    }
    
    /**
     * Merge data from xml file into field objects
     * Data will be merged if current layer has a variable to receive the data
     * Or a new non-exposed text field will be created to carry the settings forward
     * The fields array must be passed by reference to add elements
     *
     * @param array of field objects
     * @param array of theme or page settings
     * @param array of deprecated settings as array('oldname', 'newname')
     * @return void
     */
    protected function loadFields(array &$fields, array $settings, array $deprecated = array())
    {
        foreach ($deprecated as $old=>$new) {
            if (
                isset($settings[$old])
                && !isset($settings[$new])
            ) {
                $settings[$new] = $settings[$old];
            }
            unset($settings[$old]);
        }
        foreach ($settings as $name=>$value) {
            if (isset($fields[$name])) {
                $fields[$name]->setValue($value);
                continue;
            }
            $fields[$name] = FieldFactory::make(
                array(
                    'name'   =>$name,
                    'type'   =>'text',
                    'exposed'=>'false',
                    'value'  =>$value
                )
            );
        }
    }
    
    /**
     * Merge incoming field objects with local objects from ini file
     * Incoming values and local structure have precedence
     *
     * @return array of field objects
     * @param field objects from ini file (local level)
     * @param field objects accumulated from previous layers (upper level)
     */
    protected function mergeFields(array $iniFields, array $accumulatedFields)
    {
        $intersect = array_intersect_key($iniFields, $accumulatedFields);
        foreach ($intersect as $name=>$field) {
            $iniFields[$name]->setValue($accumulatedFields[$name]->getValue());
        }
        //return $iniFields + $accumulatedFields;
        return $iniFields;
    }
     
    
    /** Clean data from form and update class properties
     *
     * @return array containing keys of changed fields
     * @param array as $_POST. Need not contain all settings.
     */
    protected function updateFields($fields, $newSettings)
    {
        if (!is_array($newSettings) || count($newSettings) == 0) return array();
        $oldFields = array();
        $changes = array();
        foreach ($fields as $name=>$field) {
            $oldFields[$name] = clone $field;
            if (!isset($newSettings[$name])) continue;
            // fix for CKEditor adding Windows line endings
            $newValue = trim(str_replace(array("\r\n", "\n", "\r"), PHP_EOL, $newSettings[$name]));
            if ($field->type() == 'rgbacolor') {
                $newValue = array($newValue, $newSettings[$name.'Alpha']);
            }
            $fields[$name]->setValue($newValue);
            if ($oldFields[$name]->getValue() != $fields[$name]->getValue()) $changes[] = $name;
        }
        return $changes;
    }
    
    /**
     * Get a single layer var value
     * Does not include accumulated fields
     *
     * @param string page var name
     * @return string or null if not found
     */
    public function getLayerVar($name, $colorPrefix = '')
    {
        $fields = $this->getLayerFields();
        if (!isset($fields[$name])) return null;
        $prefix =
            $fields[$name]->type() == 'hexcolor'
            ? $colorPrefix
            : '';
        return $colorPrefix.$fields[$name]->getValue();
    }
    
    /** Clean data from form and update class properties
     *
     * @return array containing keys of changed fields
     * @param array as $_POST. Need not contain all settings.
     */
    public function customize($newSettings)
    {
        if (!is_array($newSettings) || count($newSettings) == 0) return array();
        $oldLayerFields = array();
        $layerFields = $this->layerFields;
        $changes = array();
        foreach ($layerFields as $name=>$field) {
            $oldLayerFields[$name] = clone $field;
            if (!isset($newSettings[$name])) continue;
            // fix for CKEditor adding Windows line endings
            $newValue = trim(str_replace(array("\r\n", "\n", "\r"), PHP_EOL, $newSettings[$name]));
            if ($field->type() == 'rgbacolor') {
                $newValue = array($newValue, $newSettings[$name.'Alpha']);
            }
            $this->layerFields[$name]->setValue($newValue);
            if ($oldLayerFields[$name]->getValue() != $layerFields[$name]->getValue()) $changes[] = $name;
        }
        return $changes;
    }
    
    /**
     * returns instance of theme set
     */
    public function getThemeSet()
    {
        return $this->themeSet;
    }
    
    /**
     * returns page type
     *
     * @return string
     */
    public function getPageType()
    {
        return $this->pageType;
    }
    
    /**
     * Get page ref
     *
     * @return string
     */
    public function getRef()
    {
       return $this->pageRef;
    }
    
    /**
     * Get relative path
     *
     * @return string
     */
    public function getPagePathRelSvm()
    {
        return $this->pagePathRelSvm;
    }
    
    /**
     * Get path to settings file
     *
     * @return string
     */
    public function getSettingsPath()
    {
        return $this->settingsPath;
    }
    
    /**
     * Get layer fields
     *
     * @return array of field objects
     */
    public function getLayerFields()
    {
       return $this->layerFields;
    }
    
    /**
     * Get incoming fields from previous layer
     *
     * @return array of field objects
     */
    public function getIncomingFields()
    {
       return $this->incomingFields;
    }
    
    /**
     * Get outgoing fields to next layer
     *
     * @return array of field objects
     */
    public function getAccumulatedFields()
    {
       return $this->accumulatedFields;
    }
    
    /**
     * Save to xml file
     *
     * @param string file name
     * @return void
     */
    public function saveLayer()
    {
        try {
            LayerWriter::writeLayerVars($this);
        } catch (Exception $e) {
            throw new Exception('Data not saved. '.$e->getMessage());
        }
    }
    
 }