<?php
/**
* © Copyright 2009 IntraHealth International, Inc.
* 
* This File is part of I2CE 
* 
* I2CE is free software; you can redistribute it and/or modify 
* it under the terms of the GNU General Public License as published by 
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License 
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
* @package I2CE
* @subpackage Core
* @author Carl Leitner <litlfred@ibiblio.org>
* @version v3.2.69
* @since v3.2.69
* @filesource 
*/ 
/** 
* Class I2CE_FormField_MAPPED
* 
* @access public
*/


abstract class I2CE_FormField_MAPPED extends I2CE_FormField_DB_STRING { 

    /**
     * Componentizes the given $db_value based on component
     * @param string $db_value.  The non-componentized value
     * @param array $forms of stirng. The form names which we wish to componentize.
     * @param string $component The component we wish to encode
     * @returns string The componentized db_value
     */
    abstract public function getComponentizedValue($db_value,$forms,$component);

    /**
     * Componentizes the given $db_value based on component
     * @param string $db_ref.  The reference to the data
     * @param array $forms of stirng. The form names which we wish to componentize.
     * @param string $component The component we wish to encode
     * @returns string The componentized db_value
     */
    abstract public function getSQLComponentization($db_ref,$forms,$component);


    abstract public function getDefaultDisplayStyle($type);



    

    /**
     * Hooked method to remap a given id on a given form and field
     * @param I2CE_List $lsit
     * @param string $oldid
     * @param string $newid
     */
    public function remapField($form,$oldid,$newid) {
        I2CE::raiseError("Remapping of field not implement for " . get_class($this));
        return false;
    }






    public function getDisplayedStyle($type = 'default') {
        $default_style = $this->getDefaultDisplayStyle($type);
        $path = "meta/display/$type/style";
        if ( !$this->optionsHasPath($path) || ! is_scalar( $style = $this->getOptionsByPath($path) )) {
            $style =  $default_style;
        }
        if ($style !== $default_style) {
            $checkMethod = "checkStyle_$style";
            if (!$this->_hasMethod($checkMethod) || !$this->$checkMethod()) {
                $style = $default_style;
            }
        }
        return $style;
    }

    public function getDisplayedFields($type = 'default', $check_forms = true) {            
        $path = "meta/display/$type/fields";
        if (!$this->optionsHasPath($path) || ! is_scalar( $fields = $this->getOptionsByPath($path) )) {
            $path = "meta/form";
            if (!$check_forms  || !$this->optionsHasPath($path) || ! is_array( $forms = $this->getOptionsByPath($path) )) {
                return array($this->name);
            } else {
                return $forms;
            }
        }
        return explode(':', $fields);
    }




    public function getFormOrders ($type = 'default') {
        $path = "meta/display/orders/$type";
        if (!$this->optionsHasPath($path) || ! is_array( $orders = $this->getOptionsByPath($path) )) {
            return array();
        }
        return $orders;
    }


    /**
     * Checks to see if this field can have map to any form or not.   Set to true in meta/form_any
     *@returns boolean
     */
    public function canSelectAnyForm() {
        $path = "meta/form_any";
        return ($this->optionsHasPath($path) && $this->getOptionsByPath($path));
    }

    /**
     * Checks to see which forms this form can map to.
     * @returns array()
     */

    public function getSelectableForms() {            
        if ($this->canSelectAnyForm()) {
            return I2CE::getConfig()->getKeys("/modules/forms/forms");
        }
        $path = "meta/form";
        if (!$this->optionsHasPath($path) || ! is_array( $forms = $this->getOptionsByPath($path) )) {
            return array($this->name);
        }
        return $forms;
    }


    public function getFormLimits ($type = 'default') {
        $path = "meta/limits/$type";
        if (!I2CE_ModuleFactory::instance()->isEnabled('form-limits')
            || !$this->optionsHasPath($path) || ! is_array( $limits = $this->getOptionsByPath($path) )) {
            return array();
        }
        return $limits;
    }



    /**
     *@returns array where keys are ids, values are arrays with the following keys 'value', 'display'
     */
    public function getMapOptions($type='default', $show_hidden= false,$flat = true) {
        $forms = $this->getSelectableForms();
        $fields = $this->getDisplayedFields($type);
        $limits = $this->getFormLimits($type);
        $orders = $this->getFormOrders($type);
        $data = I2CE_List::buildDataTree( $fields,$forms,$limits, $orders, $show_hidden);        
        if ($flat) {
            $data = I2CE_List::flattenDataTree( $data);
        } 
        return $data;
    }
    




    
     // /modules/forms/forms/$form/fields/$field/meta/forms =   array(county,district)
     //  selectable forms for this field    // if it does not exist it is $field
     //
     // /modules/forms/forms/$form/fields/$field/meta/display/default/fields = county+district:district+region:[region]:country
     // /modules/forms/forms/$form/fields/$field/meta/display/default/fields = county:district+cssc_region:[cssc_region+cssc_country]:country
     //  if it does not exist, it is "$field"
     //
     //
     // /modules/forms/forms/$form/fields/$field/meta/display/fancy/fields = facility:position
     // /modules/forms/forms/$form/fields/$field/meta/limits/fancy/position = BLAH (status = position_status|open)
     // /modules/forms/forms/$form/fields/$field/meta/limits/fancy/facility =NULL
     // /modules/forms/forms/$form/fields/$field/meta/display/fancy/style = tree
     // /modules/forms/forms/$form/fields/$field/meta/display/fancy/style = list

     /**
      * Set up the default editable display for this form field.
      * @return array of DOMNode
      */
    public function processDOMEditable( $node, $template, $form_node ) {
        return $this->_processDOMEditable($node,$template,$form_node,'default');
    }

     /**
      * Set up the default editable display for this form field.
      * @return array of DOMNode
      */    
    protected function _processDOMEditable( $node, $template,  $form_node, $display ) {
        $permissionParser = new I2CE_PermissionParser($template,new I2CE_User());
        $show_hidden =  (
            $form_node->hasAttribute('show_i2ce_hidden') 
            && $form_node->getAttribute('show_i2ce_hidden')
            && $permissionParser->hasTask('can_hide_list_members')
            );
        $form_node->removeAttribute('show_i2ce_hidden');
        if ($form_node->hasAttribute('selectableforms')) {
            $forms = $this->getSelectableForms();
            $t_forms  = explode(':',$form_node->getAttribute('selectableforms'));
            $t_forms = array_intersect($forms,$t_forms);
            if (count($t_forms) > 0) {
                $forms = $t_forms;
            }
            $form_node->removeAttribute('selectableforms');
        } else {
            $forms = $this->getSelectableForms();
        }
        if ($form_node->hasAttribute('show')) {
            $type = $form_node->getAttribute('show');
            $form_node->removeAttribute('show');
        } else {
            $type = 'default';
        }
        $limits = $this->getFormLimits($type);
        $orders = $this->getFormOrders($type);
        $style = $this->getDisplayedStyle($display);        
        $method = 'create_DOMEditable_' . $display;
        if (!$this->_hasMethod($method)) {
            $method = 'create_DOMEditable_' . $style;
            if (!$this->_hasMethod($method)) {
                $method =   'create_DOMEditable_' . $this->getDefaultDisplayStyle($type);
            }
        }
        $this->$method($node,$template,$form_node,$show_hidden);
    }


    
    public function __call($method,$params) { 
        if (preg_match('/^processDOMEditable_(.+)$/',$method,$matches)) {
            if ($this->hasDisplay($matches[1])) {
                if (parent::_hasMethod($method)) {
                    return parent::__call($method,$params);//check if there is a fuzzy method first.  if not pass it to the default handler
                } else {
                    $params[] = $matches[1];
                    return call_user_func_array(array($this,'_processDOMEditable'), $params);
                }
            }
        }
        return parent::__call($method,$params);
    }


    public function _hasMethod($method,$getFuzzy = false,$returnErrors = false) {  //this is b/c of the laziness above
        if (preg_match('/^processDOMEditable_(.+)$/',$method,$matches)) {
            return $this->hasDisplay($matches[1]);
        }
        return parent::_hasMethod($method,$getFuzzy,$returnErrors);
    }





}
# Local Variables:
# mode: php
# c-default-style: "bsd"
# indent-tabs-mode: nil
# c-basic-offset: 4
# End:
