<?php
/*********************************************************************************
 * 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".
 ********************************************************************************/
class MBRelationship{
	var $relationships = array();
	var $availableSubpanels = array();
	var $relParams = array('name', 'relate', 'rsub', 'msub', 'label');
	var $activities = array('Calls', 'Meetings','Notes', 'Tasks', 'Emails');
	function MBRelationship($name, $path, $key_name){
		$this->key_name = $key_name;
		$this->path = $path;
		$this->name = $name;
		$this->load();
	}
	function findRelatableModules(){
		$this->relatableModules = array();
		$d = dir('modules');
		$this->relatableModules['Activities']['default'] = $GLOBALS['mod_strings']['LBL_DEFAULT'];
		while($e = $d->read()){
			if(in_array($e, $this->activities))continue;
			if(file_exists('modules/' . $e . '/metadata/subpanels/') && file_exists('modules/' . $e . '/metadata/studio.php')){
				$f = dir('modules/' . $e . '/metadata/subpanels/');
				while($g = $f->read()){
					
					if(substr($g, 0, 1) != '.'){
						$subname = str_replace( '.php', '', $g);
						$this->relatableModules[$e][$subname] = $subname;
					}
				}
			}
		}
		//go up one directory

		$a = dir($this->path . '/..');
		$key = substr($this->key_name, 0 , strlen($this->key_name) - strlen($this->name) );
		while($b = $a->read()){
			if(substr($b, 0, 1) != '.'){
				if(file_exists($this->path . '/../' . $b . '/metadata/subpanels/')){
								$f = dir($this->path . '/../' . $b . '/metadata/subpanels/');
								while($g = $f->read()){
									if(substr($g, 0, 1) != '.'){
										$subname =  str_replace( '.php', '', $g);
										$this->relatableModules[$key . $b][$subname] = $subname;
									
									}
								}
							}
						}
					}
				
		
	
		
	}
	
	function relationshipFromPost(){
		$rel = array();
		if(!empty($_REQUEST['name']) && !empty($this->relationships[$_REQUEST['name']])){
			$rel = $this->relationships[$_REQUEST['name']];
		}
		foreach($this->relParams as $param){
			if(!empty($_POST[$param]))$rel[$param] =  $_POST[$param];
		}
		return $rel;
	}
	
	function addRelationship($name, $relatedTo, $relatedSubpanel='default', $mysubpanel='default'){
		$this->relationships[$name] = array('name'=>$name, 'relate'=>$relatedTo, 'rsub'=>$relatedSubpanel, 'msub'=>$mysubpanel);
	}
	function add($rel){
		$this->relationships[$rel['name']] = $rel;
	}
	function delete($name){
		unset($this->relationships[$name]);
	}
	
	function save(){
		$header = file_get_contents('modules/ModuleBuilder/MB/header.php');
		write_array_to_file('relationships', $this->relationships, $this->path . '/relationships.php', 'w', $header);
	}
	function build($path){
		$this->installDefs = array();
		$this->load();
		$paths = explode('/',$path);
		//take off the module name
		unset($paths[count($paths)-1]);
		//take off the modules directory
		unset($paths[count($paths)-1]);
		$path = implode('/', $paths);
		foreach($this->relationships as $def){
			if($def['name'] == 'activities'){
				foreach($this->activities as $activity){
					$rel = array(
						'name'=>strtolower($activity),
						'relate'=>$activity,
						'rsub'=>'default',
						'msub'=>$def['msub'],
						'label'=>$def['label'],
					);
	
						$this->buildRelationshipDef($rel, $path);
						$this->buildRelatedLayoutDef($rel, $path, true, false);
				}
				$this->buildActivitesLayoutDef($rel, $path);
			}else{
					
				$additionalFields = array();
				if($def['name'] == 'documents'){
					$additionalFields = array(array('name' =>'document_revision_id', 'type' =>'varchar', 'len'=>'36'));
				}
					$this->buildRelatedLayoutDef($def, $path);
					$this->buildRelationshipDef($def, $path,  $additionalFields);
			}
			
		}
		
	}
	
	function addInstallDefs(&$installDef){
		foreach($this->installDefs as $name=>$def){
			if(!empty($def)){
				foreach($def as $val){
					$installDef[$name][] = $val;
				}
			}
		}
	}
	
	function load(){
		$GLOBALS['log']->warn("load: ".$this->path);
		if(file_exists($this->path . '/relationships.php')){
			include($this->path. '/relationships.php');
			$this->relationships = $relationships;
		}
	}
	
/*
 * creates necessary metadata to create relationship between 2 objects.
 * All relationship changes can be persisted by running rebuild relationship.
 * 
 *  'name' => 'quote_products'	
 *  'lhs_module'=>'Quotes'
 *  'rhs_module'=>'Products'
 *  'type'=>'one-to-many'  /other supported type many-to-many
 * 
 *  relationship definition will be added to the custom directory. 
 *  if the file already exist add definition to the file.
 *  if definition already exists then update it. vardef.php file in modules directory will not be checked. 
 *     as the definition in  custom directory will override the original definition.
 * 
 * Usage:
 * one-to-many example
 * define_relationship(array('name' => 'quote_products','lhs_module'=>'Quotes','rhs_module'=>'Products','type'=>'one-to-many'));
 * 
 * many-to-many example
 * define_relationship(array('name' => 'accounts_contracts','lhs_module'=>'Accounts','rhs_module'=>'Contracts','type'=>'many-to-many'));
 */
function buildRelationshipDef ($def, $path, $additionalFields=array()) {
		$object_name=trim($this->key_name . '_' . $def['name']);
		$file_name =  $object_name;
		$metatable=$path.'/relationships/'. $file_name.'MetaData.php';
		mkdir_recursive($path.'/relationships/');
		$metavardef=$path.'/vardefs/'.   $def['relate'] .'.php';
		mkdir_recursive($path.'/vardefs/');
		if (!isset($def['table'])) {   //set table name if not set.
			$def['table']=$object_name;
		}
		if(strlen($def['table']) > 22){
			$len = strlen($def['table']);
			$def['table'] = substr($def['table'], 0, 11) . substr($def['table'], $len - 12);
		}
		$def['table'] = strtolower($def['table']);

	/////////////////////////////////
	
	////////////////construct properties for the relationship////////////////////
	$rel_properties=array();
	$properties = array();
	//handle lhs	
	$rel_properties['lhs_module']=$this->key_name;
	$rel_properties['lhs_table']=strtolower($this->key_name);
	$rel_properties['lhs_key']='id';
	$rel_object = $def['relate'];
	if(isset($GLOBALS['beanList'][$def['relate']])){
		$class = $GLOBALS['beanList'][$def['relate']];
		require_once($GLOBALS['beanFiles'][$class]);
		$mod = new $class();
		$table = $mod->table_name;
		$rel_object = $mod->object_name;
	}else{
		$table = strtolower($def['relate']);
	}
	//handle rhs
	$rel_properties['rhs_module']=$def['relate'];
	$rel_properties['rhs_table']=$table;
	$rel_properties['rhs_key']='id';
	
	//handle other properties.
	$rel_properties['relationship_type']='many-to-many';
	//handle many to many
	$rel_properties['join_table']=$def['table'];
	//a and b are incase the module is relating to itself
	$rel_properties['join_key_lhs']=strtolower($this->key_name."_ida");
	$rel_properties['join_key_rhs']=strtolower($def['relate']."_idb");
	$properties['table']=$def['table'];
	//create fields properties.
	$properties['fields'][]=array('name'=>'id','type'=>'varchar','len'=>36);
	$properties['fields'][]=array('name'=>'date_modified','type'=>'datetime');
	$properties['fields'][]=array('name'=>'deleted','type'=>'bool','len'=> '1','default'=> '0','required'=> true);
	$properties['fields'][]=array('name'=>$rel_properties['join_key_lhs'],'type'=>'varchar','len'=>36);
	$properties['fields'][]=array('name'=>$rel_properties['join_key_rhs'],'type'=>'varchar','len'=>36);
	foreach($additionalFields as $field){
		$properties['fields'][]=$field;
	}
	$properties['indices'][] = array('name'=>$def['table'].'spk', 'type'=>'primary', 'fields'=>array('id'));
	$properties['indices'][] = array('name'=>$def['table'].'_ida1', 'type'=>'index', 'fields'=>array($rel_properties['join_key_lhs']));
	$properties['indices'][] = array('name'=>$def['table'].'_idb2', 'type'=>'index', 'fields'=>array($rel_properties['join_key_rhs']));
	$properties['indices'][] = array('name'=>$def['table'].'_idc3', 'type'=>'index', 'fields'=>array($rel_properties['join_key_lhs'],$rel_properties['join_key_rhs']));
	$relationship[$def['name']]=$rel_properties;
	$properties['relationships'][$object_name]=$rel_properties;
	$header = file_get_contents('modules/ModuleBuilder/MB/header.php');
	write_array_to_file('dictionary["'. $object_name .'"]', $properties, $metatable, 'a', $header);
	$rel_vardef  = array();
	$rel_vardef['name'] = strtolower($this->key_name);
	$rel_vardef['type'] = 'link';
	$rel_vardef['relationship']= $object_name;
	$rel_vardef['source']='non-db';
	write_array_to_file('dictionary["' . $rel_object . '"]["fields"]["'. strtolower($this->key_name). '"]',$rel_vardef, $metavardef, 'a', $header);
	$this->installDefs['relationships'][] = array('module'=>$def['relate'], 'module_vardefs'=>'<basepath>/SugarModules/vardefs/'. $def['relate'] .'.php', 'meta_data'=>'<basepath>/SugarModules/relationships/' .$file_name.'MetaData.php');
	
	if(!empty($def['rsub'])){
		$rel_vardef  = array();
		$rel_vardef['name'] = strtolower($def['relate']);
		$rel_vardef['type'] = 'link';
		$rel_vardef['relationship']= $object_name;
		$rel_vardef['source']='non-db';
		
		$file_name =  $this->key_name;
		$vardef=$path.'/vardefs/'.   $file_name .'.php';
		
		write_array_to_file('dictionary["' . $this->key_name . '"]["fields"]["'. strtolower($def['relate']). '"]',$rel_vardef, $vardef, 'a', $header);
		$this->installDefs['vardefs'][] = array('from'=>'<basepath>/SugarModules/vardefs/'. $file_name .'.php', 'to_module'=>$this->key_name);
	}
	
}
	
	function buildRelatedLayoutDef($def, $path, $subpanel=true, $rel_subpanel = true){
		$header = file_get_contents('modules/ModuleBuilder/MB/header.php');
		if($subpanel)
		$this->_buildLayoutDef($path, $this->key_name, $def['name'], $def['msub'], $def['relate'], 'a', $header);
		if(!empty($def['rsub'])){
			if($rel_subpanel)$this->_buildLayoutDef($path, trim($def['relate']), $def['name'], $def['rsub'], $this->key_name, 'b', $header);
		}
	}
	
	function buildActivitesLayoutDef($rel, $path){
		$header = file_get_contents('modules/ModuleBuilder/MB/header.php');
		
		$layoutDefs = array(
		'activities' => array(
			'order' => 10,
			'sort_order' => 'desc',
			'sort_by' => 'date_start',
			'title_key' => 'lbl_activities',
			'type' => 'collection',
			'subpanel_name' => 'activities',   //this values is not associated with a physical file.
			'module'=>'Activities',

			'top_buttons' => array(
				array('widget_class' => 'SubPanelTopCreateTaskButton'),
				array('widget_class' => 'SubPanelTopScheduleMeetingButton'),
				array('widget_class' => 'SubPanelTopScheduleCallButton'),
				array('widget_class' => 'SubPanelTopComposeEmailButton'),
			),
			'collection_list' => array(	
				'meetings' => array(
					'module' => 'Meetings',
					'subpanel_name' => 'ForActivities',
					'get_subpanel_data' => 'meetings',
				),
				'tasks' => array(
					'module' => 'Tasks',
					'subpanel_name' => 'ForActivities',
					'get_subpanel_data' => 'tasks',
				),
				'calls' => array(
					'module' => 'Calls',
					'subpanel_name' => 'ForActivities',
					'get_subpanel_data' => 'calls',
				),	
			)			
		),

		'history' => array(
			'order' => 20,
			'sort_order' => 'desc',
			'sort_by' => 'date_modified',
			'title_key' => 'LBL_HISTORY',
			'type' => 'collection',
			'subpanel_name' => 'history',   //this values is not associated with a physical file.
			'module'=>'History',

			'top_buttons' => array(
			array('widget_class' => 'SubPanelTopCreateNoteButton'),
			array('widget_class' => 'SubPanelTopArchiveEmailButton'),
            array('widget_class' => 'SubPanelTopSummaryButton'),
			),

			'collection_list' => array(	
				'meetings' => array(
					'module' => 'Meetings',
					'subpanel_name' => 'ForHistory',
					'get_subpanel_data' => 'meetings',
				),
				'tasks' => array(
					'module' => 'Tasks',
					'subpanel_name' => 'ForHistory',
					'get_subpanel_data' => 'tasks',
				),
				'calls' => array(
					'module' => 'Calls',
					'subpanel_name' => 'ForHistory',
					'get_subpanel_data' => 'calls',
				),	
				'notes' => array(
					'module' => 'Notes',
					'subpanel_name' => 'ForHistory',
					'get_subpanel_data' => 'notes',
				),	
				'emails' => array(
					'module' => 'Emails',
					'subpanel_name' => 'ForHistory',
					'get_subpanel_data' => 'emails',
				),	
			)			
		)
		);
		
		$metafile=$path.'/layoutdefs/' .$this->key_name . '.php';
		mkdir_recursive($path.'/layoutdefs/');
		write_array_to_file('layout_defs["'. $this->key_name .'"]["subpanel_setup"]["activities"]', $layoutDefs['activities'], $metafile, "a", $header);
		write_array_to_file('layout_defs["'. $this->key_name .'"]["subpanel_setup"]["history"]', $layoutDefs['history'], $metafile, "a", $header);
		$this->installDefs['layoutdefs'][$this->key_name] = array('from'=>'<basepath>/SugarModules/layoutdefs/' . $this->key_name . '.php', 'to_module'=>$this->key_name);
		
	}
	
	function _buildLayoutDef($path, $this_name, $def_name, $subpanel_name, $relate, $idsuffix='a', $header=''){
		$object_name=trim($relate);	
		$metafile=$path.'/layoutdefs/'.$relate.'.php';
		mkdir_recursive($path.'/layoutdefs/');
		$props = array(); 
		$label = ($idsuffix == 'a')? 'LBL_'.strtoupper($this->key_name).'_SUBPANEL_TITLE': 'lbl_'. $def_name;
		$props['order']= 100;
		$props['module']= $this_name;
		$props['subpanel_name']= $subpanel_name;
		$props['get_subpanel_data'] = strtolower($this_name);
		$props['add_subpanel_data']= $this_name . '_id' . $idsuffix;
		$props['title_key'] = $label;
		//$props['top_buttons'] = array(array('widget_class' => 'SubPanelTopSelectButton'));
		write_array_to_file('layout_defs["'. $object_name .'"]["subpanel_setup"]["'. strtolower($this_name).'"]', $props, $metafile, "a", $header);
		$this->installDefs['layoutdefs'][$relate] = array('from'=>'<basepath>/SugarModules/layoutdefs/'. $relate. '.php', 'to_module'=>$relate);
	}
}


	


?>
