protected function getRelateFieldDefinition($sourceModule, $relationshipName, $vnameLabel = '')
 {
     $vardef = array();
     $vardef['name'] = $this->getValidDBName($relationshipName . "_name");
     // must end in _name for the QuickSearch code in TemplateHandler->createQuickSearchCode
     $vardef['type'] = 'relate';
     $vardef['source'] = 'non-db';
     if (!empty($vnameLabel)) {
         $vardef['vname'] = 'LBL_' . strtoupper($relationshipName . '_FROM_' . $vnameLabel) . '_TITLE';
     } else {
         $vardef['vname'] = 'LBL_' . strtoupper($relationshipName . '_FROM_' . $sourceModule) . '_TITLE';
     }
     $vardef['save'] = true;
     // the magic value to tell SugarBean to save this relate field even though it is not listed in the $relationship_fields array
     // id_name matches the join_key_ column in the relationship table for the sourceModule - that is, the column in the relationship table containing the id of the corresponding field in the source module's table (vardef['table'])
     $vardef['id_name'] = $this->getIDName($sourceModule);
     // link cannot match id_name otherwise the $bean->$id_name value set from the POST is overwritten by the Link object created by this 'link' entry
     $vardef['link'] = $this->getValidDBName($relationshipName);
     // the name of the link field that points to the relationship - required for the save to function
     $vardef['table'] = $this->getTablename($sourceModule);
     $vardef['module'] = $sourceModule;
     $module = null;
     switch (strtolower($sourceModule)) {
         case 'prospects':
             $bean = BeanFactory::getBean($this->definition['rhs_module']);
             $fields = array_keys($bean->field_name_map);
             if (in_array('name', $fields)) {
                 $vardef['rname'] = 'name';
             } else {
                 $vardef['rname'] = 'account_name';
             }
             break;
         case 'documents':
             $vardef['rname'] = 'document_name';
             break;
         case 'kbdocuments':
             $vardef['rname'] = 'kbdocument_name';
             break;
         default:
             $module = $sourceModule;
             $vardef['rname'] = 'name';
             break;
     }
     if ($module) {
         $class = BeanFactory::getBean($module);
         $tplconfig = array();
         if (!$class) {
             $parsedModuleName = AbstractRelationships::parseDeployedModuleName($sourceModule);
             if (isset($parsedModuleName['packageName'])) {
                 // added relationship to yet non-deployed module
                 require_once 'modules/ModuleBuilder/MB/ModuleBuilder.php';
                 $mb = new ModuleBuilder();
                 $module = $mb->getPackageModule($parsedModuleName['packageName'], $parsedModuleName['moduleName']);
                 $tplconfig = array_keys($module->config['templates']);
             } else {
                 throw new \RuntimeException('Module does not exist as a bean and no template found in its config');
             }
         }
         if (is_subclass_of($class, 'File') || in_array('file', $tplconfig)) {
             $vardef['rname'] = 'document_name';
         } elseif (is_subclass_of($class, 'Person') || in_array('person', $tplconfig)) {
             $vardef['rname'] = 'full_name';
             $vardef['db_concat_fields'] = array(0 => 'first_name', 1 => 'last_name');
         } elseif ($class && $class->getFieldDefinition('name')) {
             $vardef['rname'] = 'name';
         }
     }
     return $vardef;
 }
 protected function getRelateFieldDefinition($sourceModule, $relationshipName, $vnameLabel = '')
 {
     $vardef = array();
     $vardef['name'] = $relationshipName . "_name";
     // must end in _name for the QuickSearch code in TemplateHandler->createQuickSearchCode
     $vardef['type'] = 'relate';
     $vardef['source'] = 'non-db';
     if (!empty($vnameLabel)) {
         $vardef['vname'] = 'LBL_' . strtoupper($relationshipName . '_FROM_' . $vnameLabel) . '_TITLE';
     } else {
         $vardef['vname'] = 'LBL_' . strtoupper($relationshipName . '_FROM_' . $sourceModule) . '_TITLE';
     }
     $vardef['save'] = true;
     // the magic value to tell SugarBean to save this relate field even though it is not listed in the $relationship_fields array
     // id_name matches the join_key_ column in the relationship table for the sourceModule - that is, the column in the relationship table containing the id of the corresponding field in the source module's table (vardef['table'])
     $vardef['id_name'] = $this->getIDName($sourceModule);
     // link cannot match id_name otherwise the $bean->$id_name value set from the POST is overwritten by the Link object created by this 'link' entry
     $vardef['link'] = $relationshipName;
     // the name of the link field that points to the relationship - required for the save to function
     $vardef['table'] = $this->getTablename($sourceModule);
     $vardef['module'] = $sourceModule;
     require_once 'modules/ModuleBuilder/parsers/relationships/AbstractRelationships.php';
     $parsedModuleName = AbstractRelationships::parseDeployedModuleName($sourceModule);
     // now determine the appropriate 'rname' field for this relate
     // the 'rname' points to the field in source module that contains the displayable name for the record
     // usually this is 'name' but sometimes it is not...
     $vardef['rname'] = 'name';
     if (isset($parsedModuleName['packageName'])) {
         require_once 'modules/ModuleBuilder/MB/ModuleBuilder.php';
         $mb = new ModuleBuilder();
         $module = $mb->getPackageModule($parsedModuleName['packageName'], $parsedModuleName['moduleName']);
         if (in_array('file', array_keys($module->config['templates']))) {
             $vardef['rname'] = 'document_name';
         }
     } else {
         switch (strtolower($sourceModule)) {
             case 'prospects':
                 $vardef['rname'] = 'account_name';
                 break;
             case 'documents':
                 $vardef['rname'] = 'document_name';
                 break;
             case 'kbdocuments':
                 $vardef['rname'] = 'kbdocument_name';
                 break;
             case 'leads':
             case 'contacts':
                 // special handling as these modules lack a name column in the database; instead 'name' refers to a non-db field that concatenates first_name and last_name
                 // luckily, the relate field mechanism can handle this with an equivalent additional db_concat_fields entry
                 $vardef['rname'] = 'name';
                 $vardef['db_concat_fields'] = array(0 => 'first_name', 1 => 'last_name');
                 break;
             default:
                 // now see if we have any module inheriting from the 'file' template - records in file-type modules are named by the document_name field, not the usual 'name' field
                 $object = $GLOBALS['beanList'][$sourceModule];
                 require_once $GLOBALS['beanFiles'][$object];
                 $bean = new $object();
                 if (isset($GLOBALS['dictionary'][$object]['templates']) && in_array('file', $GLOBALS['dictionary'][$object]['templates'])) {
                     $vardef['rname'] = 'document_name';
                 }
         }
     }
     return $vardef;
 }
 private function updateUndeployedLayout($relationship, $actionAdd = true)
 {
     // many-to-many relationships don't have fields so if we have a many-to-many we can just skip this...
     if ($relationship->getType() == MB_MANYTOMANY) {
         return false;
     }
     $successful = true;
     $layoutAdditions = $relationship->buildFieldsToLayouts();
     require_once 'modules/ModuleBuilder/parsers/views/GridLayoutMetaDataParser.php';
     foreach ($layoutAdditions as $deployedModuleName => $fieldName) {
         foreach (array(MB_EDITVIEW, MB_DETAILVIEW) as $view) {
             $parsedName = AbstractRelationships::parseDeployedModuleName($deployedModuleName);
             if (isset($parsedName['packageName'])) {
                 $GLOBALS['log']->debug(get_class($this) . ": " . ($actionAdd ? "adding" : "removing") . " {$fieldName} on {$view} layout for undeployed module {$parsedName['moduleName']} in package {$parsedName['packageName']}");
                 $parser = new GridLayoutMetaDataParser($view, $parsedName['moduleName'], $parsedName['packageName']);
                 if ($actionAdd ? $parser->addField(array('name' => $fieldName)) : $parser->removeField($fieldName)) {
                     $parser->handleSave(false);
                 } else {
                     $GLOBALS['log']->debug(get_class($this) . ": couldn't " . ($actionAdd ? "add" : "remove") . " {$fieldName} on {$view} layout for undeployed module {$deployedModuleName}");
                     $successful = false;
                 }
             }
         }
     }
     return $successful;
 }