Hi everyone,
I am creating an admin page for a custom module. In this page I present a list that shows the names of SuiteCRM modules. By selecting the modules I would like to create for each one a new one-to-many relationship with my custom module. I think it is possible to do this but I don’t find the right function.
Hi,
I saw the video, actually I would need more to understand how to use the already in use features of SuiteCRM to create relationships between modules from code.
Searching a bit I think it should use the methods of the DeployedRelationships class found in /modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php.
For example in a test EntryPoint I created this code taking cue from another example shown at this link
I had to comment out the instruction on line 44 //SugarTestHelper::setUp('dictionary');
it generated an error because the SugarTestHelper class no longer exists.
Launching the code through the entryPoint the desired relation is created, but in the subpanel of the starting form nothing is presented.
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once 'modules/ModuleBuilder/parsers/relationships/DeployedRelationships.php';
class SugarTestRelationshipUtilities
{
private static $_relsAdded = array();
protected static $_relRequiredKeys = array('relationship_type', 'lhs_module', 'rhs_module');
/**
* Create a relationship
*
* Params should be passed in as this:
*
* array(
* 'relationship_type' => 'one-to-many',
* 'lhs_module' => 'Accounts',
* 'rhs_module' => 'Accounts',
* )
*
* @static
* @param array $relationship_def
* @return ActivitiesRelationship|bool|ManyToManyRelationship|ManyToOneRelationship|OneToManyRelationship|OneToOneRelationship
*/
public static function createRelationship(array $relationship_def)
{
if (!self::checkRequiredFields($relationship_def)) {
return false;
}
$relationships = new DeployedRelationships($relationship_def['lhs_module']);
if (!isset($relationship_def['view_module'])) {
$relationship_def['view_module'] = $relationship_def['lhs_module'];
}
$REQUEST_Backup = $_REQUEST;
$_REQUEST = $relationship_def;
$relationship = $relationships->addFromPost();
$relationships->save();
$relationships->build();
LanguageManager::clearLanguageCache($relationship_def['lhs_module']);
SugarRelationshipFactory::rebuildCache();
// rebuild the dictionary to make sure that it has the new relationship in it
//SugarTestHelper::setUp('dictionary');
// reset the link fields since we added one
VardefManager::$linkFields = array();
$_REQUEST = $REQUEST_Backup;
unset($REQUEST_Backup);
self::$_relsAdded[] = $relationship->getDefinition();
return $relationship;
}
/**
* Remove all created relationships
*
* @static
*/
public static function removeAllCreatedRelationships()
{
foreach (self::$_relsAdded as $rel) {
$relationships = new DeployedRelationships($rel['lhs_module']);
$relationships->delete($rel['relationship_name']);
$relationships->save();
$relationships->build();
LanguageManager::clearLanguageCache($rel['lhs_module']);
require_once "data/Relationships/RelationshipFactory.php";
SugarRelationshipFactory::deleteCache();
SugarRelationshipFactory::rebuildCache();
}
// since we are creating a relationship we need to unset this global var
if (isset($GLOBALS['reload_vardefs'])) {
unset($GLOBALS['reload_vardefs']);
}
}
/**
* Make sure we have at least the required keys
*
* @static
* @param array $relationship_def
* @return bool
*/
protected static function checkRequiredFields(array $relationship_def)
{
foreach (self::$_relRequiredKeys as $key) {
if (!array_key_exists($key, $relationship_def)) {
return false;
}
}
return true;
}
}
$arr_def=array(
'relationship_type' => 'one-to-many',
'lhs_module' => 'Bugs',
'rhs_module' => 'AOS_Quotes'
);
$rel= new SugarTestRelationshipUtilities();
$res=$rel->createRelationship($arr_def);
?>
<pre>
<?php
var_dump($res);
?>
</pre>
public static function createRelationship(array $relationship_def)
{
if (!self::checkRequiredFields($relationship_def)) {
return false;
}
$relationships = new DeployedRelationships($relationship_def['lhs_module']);
if (!isset($relationship_def['view_module'])) {
$relationship_def['view_module'] = $relationship_def['lhs_module'];
}
$REQUEST_Backup = $_REQUEST;
$_REQUEST = $relationship_def;
$relationship = $relationships->addFromPost();
$relationships->save();
ini_set('opcache.enable',false);
$relationships->build();
LanguageManager::clearLanguageCache($relationship_def['lhs_module']);
SugarRelationshipFactory::rebuildCache();
// rebuild the dictionary to make sure that it has the new relationship in it
//SugarTestHelper::setUp('dictionary');
// reset the link fields since we added one
VardefManager::$linkFields = array();
$_REQUEST = $REQUEST_Backup;
unset($REQUEST_Backup);
self::$_relsAdded[] = $relationship->getDefinition();
return $relationship;
}
but the result is the same, in the subpanel I don’t see anything.
It seems I’m missing a function that goes to create the information for the subpanel, maybe an instruction that goes to write in the /Layoutdefs ?
@web_elinet
Your function createRelationship calls method $relationships->build() and this metod make files.
You can look at the methods build of child and parent classes for detail:
Hi,
as suggested I inspected the code… but I had another doubt, probably the subpanel definitions are not written in the layoutdefs.
I tried to create 2 new one-to-many relationships with the custom module, at this point the settings of the fields presented in the subpanel were default.
Next I went to studio-> primary module (Bugs) -> Subpanels -> secondary module (NP_NotePlus).
Here I set the fields to be displayed.
At this point after saving and publishing the changes I checked the files on disk.
No new files were written in /custom/Extension/modules/1st_Module/Ext/Layoutdefs/ , instead a new file was created in /custom/modules/NP_NotePlus/metadata/subpanels/ named Bug_subpanel_bugs_np_noteplus_1.php
By checking the classes in the
Hi,
I checked the build() method in the DeployedRelationships Class and it is true that it uses the ModuleInstaller Class… but it seems to me that it does not deal with the creation of the files used to define the fields visible in the sub menu list.
I tried to search in /ModuleBuilder/Module/StudioModule.php and in /ModuleBuilder/MB/MBModule.php but I find only methods to load the settings set for the submenu, I could not find a function that writes these values.
Hi,
By thoroughly inspecting the classes involved, the SubPanel class the subpanels.txt file located in the /include/SubPanel folder I found that the solution is simpler than I thought.
When the build() method of the DeployedRelationships Class is called, all concatenated events generate the vardefs and layoutdefs related to the relationship.
Take for example the one-to-many relationship between the Lead module and my custom NP_NotePlus module. After calling the build method the file leads_np_noteplus_1_Leads.php is created in /custom/Extension/modules/Leads/Ext/Layoutdefs/.
The value 'subpanel_name' => 'default' specifies to take the ‘default’ display of the subpanel, which is specified in the default.php file in the /var/www/html/suitecrm/custom/modules/NP_NotePlus/metadata/subpanels folder.
Which was the folder mentioned in previous posts.
So modifying the structure in the default.php file I get that every subpanel created will have the visualization I want.
Moreover if you want to modify the visualization through Studio, a file will be created in the folder layoutdefs _overrideLead_subpanel_leads_np_noteplus_1.php :
<?php
//auto-generated file DO NOT EDIT
$layout_defs['Leads']['subpanel_setup']['leads_np_noteplus_1']['override_subpanel_name'] = 'Lead_subpanel_leads_np_noteplus_1';
?>
Where the name of the file with the layout to be used in the subpanel edited by Studio is specified.
In my case the name is Lead_subpanel_leads_np_noteplus_1
and in the folder /var/www/html/suitecrm/custom/modules/NP_NotePlus/metadata/subpanels I will find the file with name Lead_subpanel_leads_np_noteplus_1.php that contains the changes to the layout.