<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
/*********************************************************************************
 * SugarCRM is a customer relationship management program developed by
 * SugarCRM, Inc. Copyright (C) 2004 - 2007 SugarCRM Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 3 as published by the
 * Free Software Foundation with the addition of the following permission added
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 * 
 * 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 or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 * 
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU General Public License version 3,
 * these Appropriate Legal Notices must retain the display of the "Powered by
 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
 * technical reasons, the Appropriate Legal Notices must display the words
 * "Powered by SugarCRM".
 ********************************************************************************/



require_once('include/utils/file_utils.php');
require_once('include/dir_inc.php');
require_once('modules/DynamicFields/FieldCases.php');

class DynamicField {
    var $db;
    var $bean;
    var $avail_fields = array();
    var $module;
    var $modules = array();
    var $cached_field_types = array();
    var $use_existing_labels = false;
	var $maintain_label_value = false;

    function DynamicField($module=''){
        $this->db = & PearDatabase::getInstance();
        $this->module = $module;
        if(empty($this->module) && !empty($_REQUEST['module'])){
            $this->module = $_REQUEST['module'];
        }

    }
    var $table_name = 'fields_meta_data';

    function setup($bean=null, $clean_setup=true){
        if($bean){
            $this->bean =& $bean;
        }
        if(isset( $this->bean->module_dir)){
            $this->module = $this->bean->module_dir;
        }
        $this->loadCustomModulesList();
        $this->getAvailableFields();
        if($clean_setup && empty($this->bean->added_custom_field_defs)){
            $this->populateBean();
        }
    }

    function setLabel($language='en_us', $key, $value){
        require_once ('modules/ModuleBuilder/parsers/ParserFactory.php');
        $params ["label_" . $key] = $value;
        $parser = ParserFactory::getParser('label');
        $parser->handleSave($params, $this->module, $language);
    }


    /*
     THIS CREATES CUSTOM DATA FIELDS FOR MODULES
     */
    function createCustomTable(){

        if (!$this->db->tableExists($this->bean->table_name."_cstm")) {
            $query = 'CREATE TABLE '.$this->bean->table_name.'_cstm ( ';
            $query .='id_c ' . $this->bean->dbManager->helper->getColumnType('id') .' NOT NULL';
            $query .=', PRIMARY KEY ( id_c ) )';
            if($this->db->dbType == 'mysql'){
                $query .= ' CHARACTER SET utf8 COLLATE utf8_general_ci';
            }

            $this->db->query($query);
            $this->add_existing_custom_fields();
            //$this->populate_existing_ids();
        }

    }

    function getFields(){
        static $fields = array();
        if(isset($fields[$this->module])){
            return 	$fields[$this->module];
        }
        $fields[$this->module] = array();
        $this->getAvailableFields(false);
        foreach(array_keys($this->avail_fields) as $name){
            $fields[$this->module][$name] = $this->getField($name);
        }
        return 	$fields[$this->module];
    }
    function add_existing_custom_fields(){
        $this->avail_fields = array();
        $this->getAvailableFields(true);
        foreach($this->avail_fields as $name=>$data){
            $field = $this->getField($name);
            $query = $field->get_db_add_alter_table($this->bean->table_name . '_cstm');
            $this->db->query($query);
        }
    }


    function populate_existing_ids(){
        $result = $this->db->query("SELECT id FROM " . $this->bean->table_name);
        while($row = $this->db->fetchByAssoc($result)){
            $this->db->query("INSERT INTO ". $this->bean->table_name . "_cstm (id_c) VALUES ('". $row['id'] . "')");
        }
    }

    /*
     * get the join for joining the custom table
     *
     * */

    function getJOIN(){

        if(!array_key_exists($this->module, $this->modules)){

            return false;
        }
        return array('select'=>" , ". $this->bean->table_name. "_cstm.*", 'join'=> " LEFT JOIN " .$this->bean->table_name. "_cstm ON " .$this->bean->table_name. ".id = ". $this->bean->table_name. "_cstm.id_c ");

    }

    /**
     *
     * DEPRICATED
     loads fields into the bean
     This used to be called during the retrieve process now it is done through a join
     */

    function retrieve(){

        if(!array_key_exists($this->module, $this->modules)){

            return false;
        }

        $query = "SELECT * FROM ".$this->bean->table_name."_cstm WHERE id_c='".$this->bean->id."'";
        $result = $this->db->query($query);
        $row = $this->db->fetchByAssoc($result);

        if($row){
            foreach($row as $name=>$value){
                if(isset($this->avail_fields[$name])){
                    $this->bean->$name = $value;
                }


            }


        }
        //$this->populateBean();

    }

    function fill_relationships(){
        global $beanList, $beanFiles;
        $this->avail_fields = array();
        $this->getAvailableFields(false);
        if(!empty($this->bean->relDepth)) {
			if($this->bean->relDepth > 1)return;
		}else{	
			$this->bean->relDepth = 0;
        }
        foreach($this->avail_fields as	$field){

            if($field['type'] == 'relate'){
                $related_module =$field['ext2'];
                $name = $field['name'];
                $id_name = $field['id_name'];
                if(isset($beanList[ $related_module])){
                    $class = $beanList[$related_module];

                    if(file_exists($beanFiles[$class]) && isset($this->bean->$name)){
                        require_once($beanFiles[$class]);
                        $mod = new $class();
                        $mod->relDepth = $this->bean->relDepth + 1;
                        $mod->retrieve($this->bean->$id_name);
                        $bean_name = $name . '_name';
                        $this->bean->$name = $mod->name;
                    }
                }
            }
        }
    }



    /*
     Save Fields From The Bean
     */
    function save($isUpdate){

        if(array_key_exists($this->module, $this->modules) && isset($this->bean->id)){

            if($isUpdate){
                $query = "UPDATE ". $this->bean->table_name. "_cstm SET ";
            }
            $queryInsert = "INSERT INTO ". $this->bean->table_name. "_cstm (id_c";
            $values = "('".$this->bean->id."'";
            $first = true;
            foreach($this->avail_fields as $name=>$field){

                if(!empty($field['source']) && $field['source'] == 'non-db')continue;
                if($field['type'] == 'html')continue;
                if($field['type'] == 'multienum'){
                    if(isset($_POST[$name])) {
                        $this->bean->$name = is_array($_POST[$name]) ? implode('^,^',$_POST[$name]) : $_POST[$name];
                    } else {
                        $this->bean->$name = '';
                    } 
                }
                if(isset($this->bean->$name)){
                    $quote = "'";
                    if($field['type'] == 'int' || $field['type']== 'float'){
                        if (!empty($this->bean->$name)) {
                            $this->bean->$name = unTranslateNum($this->bean->$name);
                        }
                        $quote = '';
                        if(!isset($this->bean->$name) || !is_numeric($this->bean->$name) ){
                            if($field['required']){
                                $this->bean->$name = 0;
                            }else{
                                $this->bean->$name = 'NULL';
                            }
                        }
                    }
                    if($field['type'] == 'date' && (empty($this->bean->$name )|| $this->bean->$name == '1900-01-01')){
                    	$quote = '';
                        $this->bean->$name = 'NULL';
                    }
                    if($isUpdate){
                        if($first){
                            $query .= " $name=$quote".PearDatabase::quote(from_html($this->bean->$name))."$quote";

                        }else{
                            $query .= " ,$name=$quote".PearDatabase::quote(from_html($this->bean->$name))."$quote";
                        }
                    }
                    $first = false;
                    $queryInsert .= " ,$name";
                    $values .= " ,$quote". PearDatabase::quote(from_html($this->bean->$name )). "$quote";
                }
                $this->clearBean($name);
            }
            if($isUpdate){
                $query.= " WHERE id_c='" . $this->bean->id ."'";

            }

            $queryInsert .= " ) VALUES $values )";
            if(!$first){
                if(!$isUpdate){
                    $this->db->query($queryInsert);
                }else{

                    $result = $this->db->query($query);
                    if((($this->db->dbType=='mysql' || $this->db->dbType=='mssql') && $this->db->getAffectedRowCount($result) == 0) || (($this->db->dbType=='oci8' ) && $this->db->getRowCount($result) == 0) ){
                        $this->db->query($queryInsert);
                    }
                }
            }
        }


    }


    function getType($name){
        if(isset($cached_field_types[$name]))
        {
            return $this->cached_field_types[$name];
        }
        else if(!empty($this->avail_fields[$name]))
        {
            $this->cached_field_types[$name] = $this->avail_fields[$name]['type'];
        }
        else if(!empty($this->avail_fields[$name.'_c']))
        {
            $this->cached_field_types[$name] = $this->avail_fields[$name.'_c']['type'];
        }
        else
        {
            $db_name = $this->getDBName($name);
            if(!empty($this->avail_fields[$db_name]))
            {
                $this->cached_field_types[$name] = $this->avail_fields[$db_name]['type'];
            }
            else
            {
                $this->cached_field_types[$name] = '';
            }
        }

        return $this->cached_field_types[$name];
    }

    function getField($name, $type='', $refresh= false){

        static $loadedFields = array();
        if($refresh){
            $loadedFields = array();
        }
        if(isset($loadedFields[$this->module][$name])){
            return $loadedFields[$this->module][$name];
        }
        if(!isset($this->avail_fields[$name]) && isset($this->avail_fields[$this->getDBName($name)])){
            $name = $this->getDBName($name);
        }
        if(empty($type)){
            if(isset($this->avail_fields[$name])){
                $type = $this->avail_fields[$name]['type'];
                //$type = $this->avail_fields[$name]['type'];
                if($type == 'text'){
                    $type = 'textarea';
                }
            }
        }

        $field = get_widget($type);


        if(isset($this->avail_fields[$name])){
            $field->set($this->avail_fields[$name]);
        }else{
            $field->set($this->getFieldSetFromFieldDef($name));
        }
        if(isset($this->bean)){
            $field->bean =& $this->bean;
        }
        $loadedFields[$this->module][$name] = $field;

        return $field;
    }

    /**
     * Return bool based on whether the field already exists
     *
     * @param $name - the name of the field
     * @param $type - the type of the field
     * @return true if field exists, false otherwise.
     */
    function fieldExists($name = '', $type = ''){
        $field = $this->getField($name, $type);
        if(empty($type) && empty($name))
        return false;
        else if(empty($type))
        return ($field->name == $name);
        else if(empty($name))
        return ($field->type == $type);
        else
        return (($field->name == $name) && ($field->type == $type));
    }

    function getFieldLabelHTML($name, $view){
        $field = $this->getField($name);
        $field->view = $view;
        return $field->get_html_label();
    }


    function getFieldHTML($name, $view){
        $field = $this->getField($name);
        $field->view = $view;
        return $field->get_html();
    }

    function getFieldXTPL($name, $view){
        $field = $this->getField($name);
        $field->view = $view;
        return $field->get_xtpl($this->bean);
    }

    function getAllFieldsHTML($view){
        return $this->getAllFieldsView($view, 'html');
    }

    function getAllFieldsXTPL($view){
        return $this->getAllFieldsView($view, 'xtpl');
    }

    function getDBName($name, $_C= true){
        static $cached_results = array();

        if(!empty($cached_results[$name]))
        {
            return $cached_results[$name];
        }

        $exclusions = array('parent_type', 'parent_id', 'currency_id', 'parent_name');
        // Remove any non-db friendly characters
        $return_value = preg_replace("/[^\w]+/","_",$name);
        if($_C == true && !in_array($return_value, $exclusions) && substr($return_value, -2) != '_c'){
            $return_value .= '_c';
        }
        $cached_results[$name] = $return_value;
        return $return_value;
    }
    //only custom fields
    function getAllFieldsView($view, $type){
        if(!array_key_exists($this->module, $this->modules)){
            return array();
        }
        $results = array();
        if(empty($this->avail_fields)){
            $this->getAvailableFields();
        }
        $fields = $this->getFields();
        foreach($fields as $name=>$field){
            $field->view = $view;
            $field->bean =& $this->bean;
            switch(strtolower($type)){
                case 'xtpl':
                    $results[$name] = array('xtpl'=>$field->get_xtpl());
                    break;
                case 'html':
                    $results[$name] = array('html'=> $field->get_html(), 'label'=> $field->get_html_label(), 'fieldType'=>$field->data_type, 'isCustom' =>true);
                    break;

            }

        }
        return $results;
    }
    //this includes non-custom fields
    function getAllBeanFieldsView($view, $type){
        static $bad_types = array();
        if(!isset($this->bean)){
            return array();
        }
        $this->avail_fields = array();
        $results = $this->getAllFieldsView($view, $type);

        foreach($this->bean->field_defs as $name=>$value){

            if(((isset($value['type']) && $value['type'] != 'id') && (!isset($value['dbType']) || $value['dbType'] != 'id')) && ((!isset($value['source']) || $value['source'] == 'db') || (!empty($value['table']) || $value['type'] == 'relate'))){

                $ftype = $value['type'];
                if(!isset($bad_types[$ftype]) ){



                    if(isset($this->avail_fields[$value['name']])){
                        $ftype = $this->avail_fields[$value['name']]['type'];
                    }
                    if($ftype == 'text'){
                        $ftype = 'textarea';
                    }


                    $field = $this->getField($value['name'], $ftype);
                    $field->view = $view;


                    if(strcmp($type, 'xtpl') == 0) {
                        $results[$name] = array('xtpl'=>$field->get_xtpl($this->bean), 'type'=>$ftype);
                    } else if($type == 'html') {
                        $a = array();
                        $a['html'] = $field->get_html();
                        $a['label'] = $field->get_html_label();
                        $a['fieldType'] = $ftype;
                        $a['isCustom'] = !empty($this->avail_fields[$name]) ? true : false;
                        $results[$name] = $a;
                    }

                }
            }

        }

        return $results;
    }

    function getFieldSetFromFieldDef($name){
        $set = array();
        if(isset($this->bean->field_defs[$name]))
        {
            $set['name'] = $name;
            if(isset($this->bean->field_defs[$name]['vname'])){
                $set['label'] = $this->bean->field_defs[$name]['vname'];
            }else{
                $set['label'] = 'NO_LABEL';
            }
            if(isset($this->bean->field_defs[$name]['len'])){
                $set['len'] = $this->bean->field_defs[$name]['len'];
            }
            if(isset($this->bean->field_defs[$name]['required']) && $this->bean->field_defs[$name]['required']){
                $set['required'] = 'required';
            }
            if(isset($this->bean->field_defs[$name]['default'])){
                $set['default_value'] = $this->bean->field_defs[$name]['default'];
            }
            if(isset($this->bean->field_defs[$name]['options'])){
                $set['ext1'] = $this->bean->field_defs[$name]['options'];
            }
        }

        return $set;
    }

    function populateXTPL(&$xtpl, $view){

        $results = $this->getAllFieldsView($view, 'xtpl');
        foreach($results as $name=>$value){

            if(is_array($value['xtpl'])){
                foreach($value['xtpl'] as $xName=>$xValue){
                    $xtpl->assign(strtoupper($xName), $xValue);

                }
            }else{
                $xtpl->assign(strtoupper($name), $value['xtpl']);
            }
        }

    }

    function populateAllXTPL(&$xtpl, $view, $html_var_name='', $set_fields = array()){
        if(!empty($_SERVER['HTTP_REFERER']) && preg_match('/action=EditView/', $_SERVER['HTTP_REFERER'])) return; // from EditView cancel
        $results = $this->getAllBeanFieldsView($view, 'xtpl');
        foreach($results as $name=>$value){
            if(is_array($value['xtpl'])){
                foreach($value['xtpl'] as $xName=>$xValue){
                    if(!empty($html_var_name)){
                        $xtpl->append($html_var_name, strtoupper($xName), $xValue);
                    }else{
                        if(!isset($xtpl->VARS[strtoupper($xName)]))
                        $xtpl->assign(strtoupper($xName), $xValue);
                    }
                }
            }else{

                if(!empty($html_var_name)){
                    if(!isset($set_fields[strtoupper($name)])){
                        $xtpl->append($html_var_name, strtoupper($name), $value['xtpl']);
                    }
                }else{
                    if(!isset($xtpl->VARS[strtoupper($name)]))
                    $xtpl->assign(strtoupper($name), $value['xtpl']);
                }
            }
        }

    }

    function setWhereClauses(&$where_clauses){
        if(!array_key_exists($this->module, $this->modules)){
            return false;
        }
        foreach($this->avail_fields as $name=>$value){
            if(!empty($_REQUEST[$name])){
                array_push($where_clauses, $this->bean->table_name . "_cstm.$name LIKE '". PearDatabase::quote($_REQUEST[$name]). "%'");
            }
        }

    }
    function updateField($id, $values){
        if(empty($values)){
            return;
        }
        $query = "UPDATE fields_meta_data SET id='$id' ";
        if(empty($values['max_size']))unset($values['max_size']);
        foreach($values as $key=>$value){
            $query .= ",$key='$value' ";
        }
        $query .= " WHERE id='$id'";
        $this->db->query($query);
        $this->cleanSaveToCache();
        $this->avail_fields = array();
        $this->getAvailableFields(true);
        $name = str_replace( $this->module, '', $id);
        $field = $this->getField($name, '' , true);
        $field->new_field_definition=$values;  //set updated fields.
        if($field){
            $query = $field->get_db_modify_alter_table($this->bean->table_name . '_cstm');
            if(!empty($query)){
                $this->db->query($query);
            }
        }

    }

    function dropFieldById($id){
        $result = $GLOBALS['db']->query("SELECT custom_module, name FROM fields_meta_data WHERE id='$id'");
        if($row = $GLOBALS['db']->fetchByAssoc($result)){
            $GLOBALS['db']->query("DELETE FROM  fields_meta_data WHERE id='$id'");
            $db_name = ' COLUMN ' . $row['name'];
            $module = $row['custom_module'];
            if(!empty($GLOBALS['beanList'][$module])){
                $class = $GLOBALS['beanList'][$module];
                require_once($GLOBALS['beanFiles'][$class]);
                $mod = new $class();
                $GLOBALS['db']->query("ALTER TABLE " .$mod->table_name . "_cstm DROP $db_name");
            }

        }
        DynamicField::deleteCache();

    }
    function deleteField($name){
        $this->dropField($name);
    }

    function dropField($name){
        $object_name = $this->module;

        $db_name = $name;
        $this->db->query("DELETE FROM  fields_meta_data WHERE id='$object_name$db_name'");

        $db_name = ' COLUMN ' . $db_name;


        $this->db->query("ALTER TABLE " . $this->bean->table_name . "_cstm DROP $db_name");

        $this->cleanSaveToCache();
    }

    function addFieldObject(&$field){


        $object_name = $this->module;
        $db_name = $field->name;

        require_once('modules/EditCustomFields/FieldsMetaData.php');
        $fmd = new FieldsMetaData();
        $id =  $fmd->retrieve($object_name.$db_name,true, false);

        $is_update = false;
        $label = $field->label;
        if(!empty($id)){
            $is_update = true;
        }else{
            $db_name = $this->getDBName($field->name);
            $field->name = $db_name;
            //$label = $this->addLabel($field->vname);
        }

        if(!array_key_exists($this->module, $this->modules)){
            $this->createCustomTable();
        }

        $fmd->id = $object_name.$db_name;
        $fmd->custom_module= $object_name;
        $fmd->name = $db_name;
        $fmd->vname = $label;
        $fmd->type = $field->type;
        $fmd->help = $field->help;
        $fmd->len = $field->len; // tyoung bug 15407 - was being set to $field->size so changes weren't being saved
        $fmd->required = ($field->required ? 1 : 0);
        $fmd->default_value = $field->default;
        $fmd->ext1 = $field->ext1;
        $fmd->ext2 = $field->ext2;
        $fmd->ext3 = $field->ext3;
        $fmd->ext4 = (isset($field->ext4) ? $field->ext4 : '');
        $fmd->comments = $field->comment;
        $fmd->massupdate = $field->massupdate;
        $fmd->duplicate_merge = $field->duplicate_merge;
        $fmd->audited =$field->audited;
        $fmd->reportable = ($field->reportable ? 1 : 0);

        if(!$is_update){
            $fmd->new_with_id=true;
        }

        $fmd->save();

        $this->cleanSaveToCache();
        if(!array_key_exists($this->module, $this->modules)){
            $this->createCustomTable();
            $this->saveCustomModulesList();
        }

        $this->avail_fields = array();
        $this->getAvailableFields(true);


        if($field){
            if(!$is_update){
                $query = $field->get_db_add_alter_table($this->bean->table_name . '_cstm');
            }else{
                $query = $field->get_db_modify_alter_table($this->bean->table_name . '_cstm');
            }
            if(!empty($query)){
                $this->db->query($query);
            }
        }
        return true;
    }

    function addField($name,$label='', $type='Text',$max_size='255',$required_option='optional', $default_value='', $ext1='', $ext2='', $ext3='',$audited=0, $mass_update = 0 , $ext4='', $help='',$duplicate_merge=0, $comment=''){

        if(empty($label)){
            $label = $name;
        }
        if(!$this->maintain_label_value){
			$label = $this->addLabel($label);
		}

        $object_name = $this->module;
        $db_name = $this->getDBName($name);
        
        if(isset($this->avail_fields[$db_name])){
            return false;
        }
        if(!array_key_exists($this->module, $this->modules)){
            $this->createCustomTable();
        }
        require_once('modules/EditCustomFields/FieldsMetaData.php');
        $fmd = new FieldsMetaData();
        $fmd->id = $object_name.$db_name;
        $fmd->custom_module= $object_name;
        $fmd->name = $db_name;
        $fmd->vname = $label;
        $fmd->type = $type;
        $fmd->len = $max_size;
        $fmd->required = $required_option;
        $fmd->default_value = $default_value;
        $fmd->ext1 = $ext1;
        $fmd->ext2 = $ext2;
        $fmd->ext3 = $ext3;
        $fmd->ext4 = $ext4;
        $fmd->help = $help;
        $fmd->massupdate = $mass_update;
        $fmd->duplicate_merge = $duplicate_merge;
        $fmd->comments = $comment;

        $fmd->audited =$audited;
        $fmd->new_with_id=true;

        $fmd->save();

        $this->cleanSaveToCache();
        if(!array_key_exists($this->module, $this->modules)){
            $this->createCustomTable();
            $this->saveCustomModulesList();
        }

        $this->avail_fields = array();
        $this->getAvailableFields(true);
        $field = $this->getField($name, '', true);

        if($field){
            $query = $field->get_db_add_alter_table($this->bean->table_name . '_cstm');
            if(!empty($query)){
                $this->db->query($query);
            }
        }
        return true;
    }

    function add_existing_custom_field($name){
        $this->avail_fields = array();
        $this->getAvailableFields(true);
        $field = $this->getField($name);

        if($field){
            $query = $field->get_db_add_alter_table($this->bean->table_name . '_cstm');
            if(!empty($query)){
                $this->db->query($query);
            }
        }
    }

    function getAvailableFields($clean=false, $saveToCache = true){

        if(!$clean){
            if(!array_key_exists($this->module, $this->modules)){
                $this->avail_fields = array();
                return $this->avail_fields;
            }

            if($this->loadFromCache()){
                return $this->avail_fields;
            }

        }
        static $results = array();
		if(!empty($results[$this->module]) && (!isset($_REQUEST['module']) || ($_REQUEST['module'] != 'ModuleBuilder' && ($_REQUEST['module'] != 'Administration' && isset($_REQUEST['action']) && $_REQUEST['action'] == 'UpgradeWizard_commit')))){
			$this->avail_fields = $results[$this->module];
			return $this->avail_fields;
		}
	
        $query = "SELECT * FROM fields_meta_data WHERE custom_module='$this->module' AND deleted = 0";
        $result = $this->db->query($query);
        require_once('modules/DynamicFields/FieldCases.php');
        while($row = $this->db->fetchByAssoc($result)){

            $field = get_widget($row['type']);
            foreach($row as $key => $value){
                $field->$key = $value;
            }
            $field->default = $field->default_value;
            $vardef = $field->get_field_def();
            $vardef['id'] = $row['id'];
            $vardef['custom_module'] = $row['custom_module'];
        	if(!isset($vardef['default'])){
                $vardef['default_value'] = $row['default_value'];
                $vardef['default'] = $vardef['default_value'];
            }
            if(empty($vardef['source']))
            $vardef['source'] = 'custom_fields';
            
            
            $this->avail_fields[$row['name']] = $vardef;
        }
        $results[$this->module] = $this->avail_fields;
        if(!$clean) {
            return $this->avail_fields;
        }

        $this->saveToVardef($saveToCache);
        return $this->avail_fields;
    }




    function addLabel($label){
        global $current_language;
        $mod_strings = return_module_language($current_language, $this->module);
        $limit = 10;
        $count = 0;
        $field_key = $this->getDBName($label, false);
        $curr_field_key = $this->getDBName($label, false);
        if(!$this->use_existing_labels){
            while(isset($mod_strings[$curr_field_key]) && $count <= $limit )
            {
                $curr_field_key = $field_key. "_$count";
                $count++;
            }
        }
        require_once('modules/ModuleBuilder/parsers/ParserFactory.php');
        $parser = ParserFactory::getParser('label');
        $parser->handleSave(array('label_'. $curr_field_key=>$label),$this->module, $current_language);
        return $curr_field_key;
    }



    function populateBean(){
        if(isset($this->bean->added_custom_field_defs) && $this->bean->added_custom_field_defs){
            return;
        }
        $fields = $this->getAvailableFields(false, false);
        foreach($fields as $name=>$field){
            $this->bean->field_name_map[$name] = $field;
            $this->bean->field_defs[$name] = $this->bean->field_name_map[$name];
            $this->bean->column_fields[] = $name;
            if($this->bean->field_name_map[$name]['required']){
                $this->bean->required_fields[$name] = 1;
            }

        }
        $this->bean->added_custom_field_defs= true;
    }



    function clearBean($name){
        unset($this->bean->$name);
    }

    function cleanSaveToCache(){
        $this->deleteCache();
        $this->getAvailableFields(true, true);

    }

    function saveToVardef($saveToCache = true) {
        require_once('include/SugarObjects/VardefManager.php');
        global $beanList;
        if(!empty($beanList[$this->module])){
            $object = $beanList[$this->module];
            if ($object=='aCase')
            	$object='Case';

            if(!empty($GLOBALS['dictionary'][$object])){
                $def = $GLOBALS['dictionary'][$object];
                if(isset($this->avail_fields)) {
                    // First loop to add
                    $manager = new VardefManager();
                    foreach($this->avail_fields as $field) {
                        $GLOBALS['dictionary'][$object]['fields'][$field['name']] = $field;
                    }  //for

                    // Second loop to remove
                    foreach($GLOBALS['dictionary'][$object]['fields'] as $name=>$fieldDef) {
                        if(isset($fieldDef['custom_module']) && !isset($this->avail_fields[$name])) {
                            unset($GLOBALS['dictionary'][$object]['fields'][$name]);
                        }
                    }
                    if($saveToCache) $manager->saveCache($this->module, $object);

                } //if
            }
        }
    }

    function deleteCache(){
        $GLOBALS['log']->debug("deleting the dynamic fields cache from disk");
        $file = 'cache/dynamic_fields/';
        if(file_exists($file)){
            rmdir_recursive($file);
        }
        if (isset($this->module)) // deleteCache() is called as a class function from some modules and so $this->module may not be set. This is not an issue, as the following code is only relevant for ModuleBuilder, which does set $this->module
        {
            global $beanList;
            $object = $beanList[$this->module];
            $GLOBALS['log']->debug("clearing vardef cache for module=".$this->module." and object=".$object);
            VardefManager::clearVardef($this->module, $object);
            // tyoung bug 15858 - VardefManager::clearVardef doesn't clear out the entry from the GLOBALS['dictionary'] - we need to clear this as getAvailableFields calls loadFromCache which adds back the entries in GLOBALS['dictionary'], which we don't want to include deleted fields
            if (isset($GLOBALS['dictionary'][$object]))
            {
                unset($GLOBALS['dictionary'][$object]);
            }
        }
        return true;
    }

    function loadFromCache(){
        static $loaded_fields;
        if(isset($loaded_fields[$this->module])){
            $this->avail_fields = $loaded_fields[$this->module];
            return true;
        }

        require_once('include/SugarObjects/VardefManager.php');
        global $beanList;
        $object = $beanList[$this->module];
        $manager = new VardefManager();
        $manager->loadVardef($this->module, $object);
        if(isset($dictionary[$object]['fields'])) {
            $loaded_fields[$this->module] = $dictionary[$object]['fields'];
            return true;
        }

        return false;
    }

    function loadCustomModulesList(){
        // leverage a cache to decrease the work as much as possible
        static $modules_array = null;

        if(!is_null($modules_array))
        {
            // Make a copy so that when the bean is destroyed it does not clear the master copy
            $this->modules =& $modules_array;
            return;
        }

        $file = 'cache/dynamic_fields/modules.php';
        $this->modules = array();
        if(file_exists($file)){
            include($file);
            // Make a copy so that when the bean is destroyed it does not clear the master copy
            $this->modules = $custom_modules;
        }
        else{
            $this->saveCustomModulesList();
        }

        // Either the file was included, or the custom modules have been loaded.  Save the custom modules for this round trip.
        // Make a copy so that when the bean is destroyed it does not clear the master copy
        $modules_array = $this->modules;
    }

    function saveCustomModulesList(){
        $modules = array();
        //added check to avoid creation of cache before the table is created.
        if ($this->db->tableExists('fields_meta_data')) {
            $query = 'SELECT DISTINCT custom_module FROM fields_meta_data';
            $result = $this->db->query($query);
            if($result){
                while($row = $this->db->fetchByAssoc($result)){
                    $modules[$row['custom_module']] = $row['custom_module'];
                }
            }
            $this->modules = $modules;
            $file = 'dynamic_fields/modules.php';
            $file = create_cache_directory($file);
            $vardump = var_export($modules, true);
            $fp = fopen($file, 'wb');
            fwrite($fp,"<?php\n\$custom_modules=".  $vardump . "\n?>");
            fclose($fp);
        }
        return $modules;
    }
}
