Call script when do quick repair and rebuild

Is there a way to have a php script called when a Quick Repair and Rebuild is run?

I am trying to keep all my customizations compatible with a version control system, so I cannot use studio to add custom fileds, but I have found a way to add custom fields if I can call a script when a Repair and Rebuild is done.

Anyone have any ideas how I can have a php script called when Quick Repair and Rebuild is run?

Note: the solution selected addresses the question AND provides a (preferred) alternative - using vardefs to create custom fields ion the _cstm database table - since that is what I really wanted to do. It turned out that creating custom fields - fields stored in the _cstm database table for a module - is NOT a straight-forward process so the solution selected answers the real question and (if you read the whole solution) does answer the question asked. I apologize for the (excrutiatingly) long answer in the solution, but if you do take the time to read it all, you will, as I did, learn a lot about custom fields.

@Ramblin

You can add a custom item to the admin menu. There is a short comment that this is possible (Extension Framework :: SuiteCRM Documentation). Perhaps you can find more information in the SugarCRM documentation.

@p.konetskiy

That was helpful.

I now know where I can put the information required to create custom fields - one file per field in custom/Ext/application/Ext/Extensions/{oneFilePerField}.php - and have the fields all consolidated into one file in custom/application/Ext/Extensions/extensions.ext.php. That does help. And after creating the custom field using the install_custom_field() method and after a Quick Repair and Rebuild, I can set a flag in the file of the custom fields that have already been created so it does not try to create them again - which would create a database error.

Now I just need to figure out how to trigger a script when a Quick Repair and Rebuild is run - BEFORE the Quick Repair and Rebuild actually runs.

I know how to do this in a way that is NOT upgrade safe

In modules/Administration/QuickRepairAndRebuild.php at the start of the

public function repairAndClearAll( ...

method, I can put a require_once() and call the script to do what needs to be done. This will work, but is not upgrade safe.

I tried copying the QuickRepairAndRebuild.php file to custom/modules/Administration/QuickRepairAndRebuild.php and doing the require_once() and script calls there. but the custom version of QuickRepairAndRebuild.php was not accessed; it was ignored.

I also tried extending the RepairAndClear class and that made no difference.

Is there a way to have the QuickRepairAndRebuild.php file - or more specifically the repairAndClearAll method - customized within the custom directory and have it used instead of the core repairAndClearAll method?

@Ramblin

These are some details for my previous comment.

  1. Look at the file ‘modules/Administration/metadata/adminpaneldefs.php’.
  2. Create the file ‘custom/modules/Administration/Ext/Administration/administration.ext.php’ to add a new section to the admin menu.
  3. Create a new submenu for your custom scripts as a new entry point (look at the ‘modules/Administration/Upgrade.php’ file).
  4. Create an entry point with your custom code, including calling the “repairAndClearAll” method, which will be called from the new submenu.

The solution will be safe to upgrade.

Another upgrade-safe solution would be to extend modules/Administration/views/view.repair.php in custom/modules/Administration/views/view.repair.php

@p.konetskiy

That is VERY helpful!

I can add a “Add Custom Fields” menu to appear in the Repair submenu and put my custom coding in the EntryPoint/Controller file.

I understand what I need to do to create a new submenu under the Repair menu in the Admin view - edit the Upgrade.php file - I assumed I would do so in custom/Extension/modules/Administration/Ext/Upgrade.php to make it upgrade-safe but you have added the edits directly as a .ext. file in custom/modules/Administration/Ext/Administration/administration.ext.php . See my separate Q on this.

If I wanted to create a new main menu at the same level as the Repair menu in the Admin view, the I would edit the contents of modules/Administration/metadata/adminpaneldefs.php file. I assume I would do this in custom/modules/Administration/metadata/adminpaneldefs.php

I would copy the contents

$admin_option_defs['Administration']['repair'] = [
    'Repair',
    'LBL_UPGRADE_TITLE',
    'LBL_UPGRADE',
    './index.php?module=Administration&action=Upgrade',
    'repair'
];

and paste just below, editing to suit.

The LBL_… entries I am good with
The ./index.php?.. I can set to the EntryPoint/Controller

Three things I am not sure about:

  1. When declaring the array for the menu
$admin_option_defs['Administration']['repair']

the definition has a second-level key ‘repair’. Can I just create my own key name (eg ‘custom_fields’) or is the array definition looking for something specific

  1. The first entry in the array is ‘Repair’. Where is this used and can I just use my own definition here (eg ‘CustomFields’)
  2. The last entry in the array is 'repair. Where is this used and can I just use my own definition here (eg ‘customfields’)

You are being extrememely helpful and I appreciate it

@blqt

Thank you, always nice to have options.

I am trying to maintain the MVC architecture as much as I can. If I put my custom code into the view definition, I would be mixing the V and C parts of MVC.

The advantage of your suggestion is that It does not add another menu so the user actually does not need to take any additional steps; they just do what they have always done and behind-the-scenes the system does more than it used to.

So I need to noodle this and get some user feedback on this compared to the new menu option.

Appreciate the suggestion.

@p.konetskiy

I see that you are adding the edits directly to the .ext. file.

I thought we were supposed to add replacements to

custom/Extension/modules/Administration/Ext/Administration.php

or edits to

custom/Extension/modules/Administration/Ext/customAdministration.php

by extending the class.

After a QR&R, this creates the .ext. file.

Can you help me understand why you have recommended your approach? Or would the normal approach just not work in this case?

@Ramblin

Some time ago I tested the solution and created the following array. It worked.

<?php
$admin_option_defs=array();
$admin_option_defs['Administration']['BFM_admin_menu_configs'] = array(
    'BFM_admin_menu_configs',
    'LBL_BFM_HUBOT_CONFIG_TITLE',
    'LBL_BFM_HUBOT_CONFIG_DESCRIPTION',
    './index.php?module=BFM_Configs&action=EditView',
    'bfm-admin-menu bfm-configs'
);
$admin_option_defs['Administration']['BFM_admin_menu_outputs'] = array(
    'BFM_admin_menu_outputs',
    'LBL_BFM_HUBOT_OUTPUT_TITLE',
    'LBL_BFM_HUBOT_OUTPUT_DESCRIPTION',
    './index.php?module=BFM_Outputs&action=index',
    'bfm-admin-menu bfm-outputs'
);
$admin_group_header['BFM_admin_menu'] = array(
    'LBL_BFM_HUBOT_TITLE',
    '',
    false,
    $admin_option_defs,
    'LBL_BFM_HUBOT_DESCRIPTION'
);
echo getVersionedScript('custom/modules/Administration/js/bfm_admin_menu.js');

And installed the file using standard manifest.php:

...
   'administration' => array(
        0 => array(
           'from' => '<basepath>/SugarModules/Administration/BFM_admin_menu.php',
        ),
    ),
...

@Ramblin
I wrote already.

And you will be able to understand why the file name is ‘custom/modules/Administration/Ext/Administration/administration.ext.php’

@p.konetskiy

I had mmissed the include statement near the end of the file

if (file_exists('custom/modules/Administration/Ext/Administration/administration.ext.php')) {
    include('custom/modules/Administration/Ext/Administration/administration.ext.php');
}

Sorry about that.

I also edited my orginal post after getting a better understanding of what you had shown previously


******** DO NOT spend time reading this post ********
New discoveries changed the recomended solution
See later post marked Solution for the final word on this


I apologize for the bad formatting below (I have no idea why things turned red and I could not attach a PDF) but I was not going to re-type all the explanation in or re-format for this post (yes, I am that lazy). However the information is useful for anyone looking to try and create custom fields in SuiteCRM from code. My suggestion for anyone trying to read the solution is for them to copy the contents of the solution into a text processing document (Notepad++, Libre Office Writer, Microsoft Word (ugh) or whatever you prefer and see if it can be more easily read there.)

A BIG thank you to @p.konetskiy for sticking with me on this one.

1.1	Create new custom fields in the _cstm table of a module

SuiteCRM has two database tables for each module: the core table (eg contacts) and another table with a _cstm suffix (eg contacts_cstm).  
Fields that are part of the original SuiteCRM code are in the core database table.  Fields added to the module with Studio have _c appended as a suffix to the field name and go into the _cstm database table.  The _cstm database table for a module does not exist until a field is created that would be stored in the _cstm table.
Just to complicate things:
* 1. Fields added in Module Builder go into the core database table for the module, but since Module Builder is used to create a custom module, this is not an issue.
* 2. However, fields added via direct entry in the vardefs file (eg custom/Extension/modules/{modulename}/Ext/Vardefs/{filename}.php) go into the core database table, unless particular steps are taken which direct the system to add the new fields to the _cstm table.  These steps are convoluted to say the least.

Best practice for adding fields to CORE modules in SuiteCRM is to create new fields in the _cstm database table for each core module, not the core database table.  
* Installations on cloud SuiteCRM systems likely will not allow you to alter core database tables
* For CORE modules, if you add new fields to the core database table, if SuiteCRM updates a core module and it creates its own new fields in the core database table, you risk your new field having conflict with a future SuiteCRM update.  Additionally, there are times when an update to a core module does not just add to a database table but replaces it with the new structure, copying over the old data - but only for fields that were in the original core database table definition.
* Having said this, another developer could add another field to the _cstm module database table that has the same name as your new field and you would be back into the confict issue.  This is a risk you can control though (choosing which add-on modules to install).  However, it is recommended to ALWAYS have a prefix (I use ayu_ , the first 3 letters of my company Ayuda) for any new field you create in any module.  This minimizes the odds of a conflict in either the core or _cstm database tables.  Unfortunately, I learned this lesson after creating this system so you will not see an ayu_ prefix in my custom fields for this system.
* When you are creating your own CUSTOM module, you may be better off adding new fields to the core database table for the new module and that is fine since you would use some kind of installer (manifest file, …) to add fields for that new module so all would work fine, even on cloud SuiteCRM systems.  In fact, there is no JOIN required in the sql lookups if all fields are in the core dataqbase table, so if your custom module has a number of fields, it is preferable, from a performance perspective, to keep all the fields in the core database table.

You cannot add fields to the _cstm database table by just defining them in vardefs like you do for fields going into the core database table.  Even with the special array entries (like 'source' => 'custom_field',) included in the vardefs, you would still need to:
* Manually, via sql commands add entries into the fields_meta_data table
* Make sure a _cstm table exists for the module into which you want to add your custom field(s)
* Define the vardefs and run Quick Repair and Rebuild
You can add custom fields using the manifest file structure like what is created with Module Builder when it is Published

You can add custom fields using a SuiteCRM built-in function.  This is my choice and is explained below
Details are available at https://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_11.0/Data_Framework/Vardefs/Manually_Creating_Custom_Fields 

Two steps involved here:
1) Create code that will call the install_custom_fields() method in the ModuleInstaller class in the  {SuiteCRM_Directory}/ModuleInstall/ModuleInstaller.php (around line 1272)
2) Trigger the code BEFORE a Quick Repair and Rebuild is run

Re 1) The code for calling the install_custom_fields() method will look something like the following sample text field shown):
Note: the name will have _c added as a suffix by the install_custom_fields() method.  If you do add the _c in your name definition, the install_custom_fields() method will recognize that and NOT add another _c suffix.

<?php
if(!defined('sugarEntry') || !sugarEntry) {
    die('Not A Valid Entry Point');
}
$fields = array (
    //Text
    array(
        'name' => 'program_text_field',
        'label' => 'LBL_PROGRAM_TEXT_FIELD',
        'type' => 'varchar',
        'module' => 'FP_events',
        'help' => 'Text Field Help Text',
        'comment' => 'Text Field Comment Text',
        'default_value' => '',
        'max_size' => 255,
        'required' => false, // true or false
        'reportable' => true, // true or false
        'audited' => false, // true or false
        'importable' => 'true', // 'true', 'false', 'required'
        'duplicate_merge' => false, // true or false
    ),
);
require_once('ModuleInstall/ModuleInstaller.php');
$moduleInstaller = new ModuleInstaller();
$moduleInstaller->install_custom_fields($fields);
// Return the user to the Administration menu
SugarApplication::redirect('index.php?module=Administration&action=index');

Notes:
In additional to the field elements that are defined, there are some entries required that are put into fields_meta_data and used by the install_custom_fields() method to add the fields to the _cstm database table
module

The only field elements that are defined in a _cstm table are shown below with their type shown after.
id varchar(255)
This is the equivalent of a foreign_key setup so is not restricted to the normal ID length of 36 characters
name varchar(255)
vname varchar(255)
comments varchar(255)
help varchar(255)
custom_module varchar(255)	
type varchar(255)
len int
required bool
default_value varchar(255)
date_modified datetime
deleted bool
audited bool
massupdate bool
duplicate_merge bool
reportable bool
importable varchar(255)
ext1 varchar(255)
ext2 varchar(255)
ext3 varchar(255)
ext4

If you have any additional elements you want defined (eg inline_edit or Label value), you need to separately define them in the appropriate custom/.. directory as follows.  Remember, the field name has _c as the suffix in a _cstm table

For additional elements

cd {SuiteCRM_Directory}
mkdir -p custom/Extension/modules{ModuleName}/Ext/Vardefs/
nano custom/Extension/modules{ModuleName}/Ext/Vardefs/{filename}.php
$dictionary['{ModuleName}']['fields']['field_name']['{element}'] = '{element_value}';
{ModuleName} may be singular; check the other entries in vardefs
{element} is the element you wish to define (eg inline_edit)
(element_value} matches the type definition (eg bool = true/false)

For Label defintions

cd {SuiteCRM_Directory}
mkdir -p custom/Extension/modules{ModuleName}/Ext/Language/
nano custom/Extension/modules{ModuleName}/Ext/Vardefs/en_us.{filename}.php
$mod_strings['LBL_...'] = 'The text string you want';

The method for triggering that code is up to you.  Options include
* Adding a logic hook that when triggered includes code like the above
* Using SuiteCRM APIs
* Manully calling the code from a browser after enabling the code as an EntryPoint
* Add a button/menu to a SuiteCRM GUI that triggers the code when clicked

Make sure that whatever method you use, you only run the code once for each field.  If you run it again for the same field, you will be trying to add a vield to a _cstm database table when the field already exists in the table and you will get an sql error.

Simplest method: add a file with the above code, define the file as an allowed EntryPoint, and access the file from your browser.  You could put the file anywhere; for the purpose of this explanation, I will put it into custom/…

Create the code
cd (SuiteCRM_Directory}
nano custom/addCustomFields.php
//
…  add the code shown above, editing to suit your situation …
… one array element defined for each field
//

Enable the page with the code to serve as an Entry Point
mkdir -p custom/Extension/application/Ext/EntryPointRegistry/
nano custom/Extension/application/Ext/EntryPointRegistry/addCustomFieldsEntryPoint.php
<?php
$entry_point_registry['addCustomFieldsEntryPoint'] = array(
    // Pointer to the location of the file for which this EntryPoint is defined
    'file' => 'custom/addCustomFields.php',
    // auth true means peron using the EntryPoint must be an authenticated User
    // auth false means anyone could the EntryPoint - NOT a good idea usually
    'auth' => true,
);

Call the code using your browser
http://{SuiteCRM _Site}/index.php?EntryPoint=addCustomFieldsEntryPoint

This is all that is needed and it will work.  The admin has to remember to populate the php code with each field to be added, manually run the code (ONCE for each field to be added) by calling the EntryPoint from their browser, and then running Quick Repar and Rebuild and then removing the field definition from the code once the field has been created.

However, if you are going to use this on an ongoing development basis, I would do the following:

Create the file and the EntryPoint as shown above
Add a submenu to the Repair option in Admin -> Admin Tools.  We add a new submenu "Create Custom Fields"

mkdir -p custom/modules/Administration
cp -a modules/Administration/Upgrade.php custom/modules/Administration/Upgrade.php 
nano custom/modules/Administration/Upgrade.php 
Change
<tr>
	<td scope="row"><?php echo SugarThemeRegistry::current()->getImage('Repair', 'align="absmiddle" border="0"', null, null, '.gif', $mod_strings['LBL_QUICK_REPAIR_AND_REBUILD']); ?>&nbsp;<a href="./index.php?module=Administration&action=repair"><?php echo $mod_strings['LBL_QUICK_REPAIR_AND_REBUILD']; ?></a></td>
	<td> <?php echo $mod_strings['LBL_QUICK_REPAIR_AND_REBUILD_DESC'] ; ?> </td>
</tr>
<tr>
	<td scope="row"><?php echo SugarThemeRegistry::current()->getImage('Repair', 'align="absmiddle" border="0"', null, null, '.gif', $mod_strings['LBL_EXPAND_DATABASE_COLUMNS']); ?>&nbsp;<a href="./index.php?module=Administration&action=expandDatabase"><?php echo $mod_strings['LBL_EXPAND_DATABASE_COLUMNS']; ?></a></td>
	<td> <?php echo $mod_strings['LBL_EXPAND_DATABASE_COLUMNS_DESC'] ; ?> </td>
</tr>
To (add a new item between them)
<tr>
	<td scope="row"><?php echo SugarThemeRegistry::current()->getImage('Repair', 'align="absmiddle" border="0"', null, null, '.gif', $mod_strings['LBL_QUICK_REPAIR_AND_REBUILD']); ?>&nbsp;<a href="./index.php?module=Administration&action=repair"><?php echo $mod_strings['LBL_QUICK_REPAIR_AND_REBUILD']; ?></a></td>
	<td> <?php echo $mod_strings['LBL_QUICK_REPAIR_AND_REBUILD_DESC'] ; ?> </td>
</tr>
<tr>
	<td scope="row"><?php echo SugarThemeRegistry::current()->getImage('Repair', 'align="absmiddle" border="0"', null, null, '.gif', $mod_strings['LBL_CREATE_CUSTOM_FIELDS']); ?>&nbsp;<a href="./index.php?entryPoint=addCustomFieldsEntryPoint"><?php echo $mod_strings['LBL_CREATE_CUSTOM_FIELDS']; ?></a></td>
	<td> <?php echo $mod_strings['LBL_CREATE_CUSTOM_FIELDS_DESC'] ; ?> </td>
</tr>
<tr>
	<td scope="row"><?php echo SugarThemeRegistry::current()->getImage('Repair', 'align="absmiddle" border="0"', null, null, '.gif', $mod_strings['LBL_EXPAND_DATABASE_COLUMNS']); ?>&nbsp;<a href="./index.php?module=Administration&action=expandDatabase"><?php echo $mod_strings['LBL_EXPAND_DATABASE_COLUMNS']; ?></a></td>
	<td> <?php echo $mod_strings['LBL_EXPAND_DATABASE_COLUMNS_DESC'] ; ?> </td>
</tr>

Add the language definitions
mkdir -p custom/Extension/modules/Administration/Ext/Language/
nano custom/Extension/modules/Administration/Ext/Language/en_us.repairSubMenu.php
<?php
$mod_strings['LBL_CREATE_CUSTOM_FIELDS'] = 'Create Custom Fields';
$mod_strings['LBL_CREATE_CUSTOM_FIELDS_DESC'] = 'Add fields specified in ./custom/AYU_CustomFields/... to _cstm database table(s)';

This provides a menu to trigger the code so users do not have to remember the URL to trigger the EntryPoint directly.  The user still needs to remove the field definition after each use to prevent attempts to create the same field again.

If I was going to use it a lot, I would create a module called AYU_Customfields with ModuleBuilder to store the code and be the target URL for the user access and add code in custom/AYU_Customfields to read files, programmatically add the new field definitions to the code, run the program, run Quick Repair and Rebuild and set a flag to show that the fields have been added.  

Create the AYU_Customfields module in Module Builder and in that new module's controller, add an action called add_custom_fields

Create a new Module AYU_Customfields using ModuleBuilder and Deploy
Edit/Create a custom controller in that module and add a add_custom_fields action
nano modules/AYU_Customfields/controller.php
if (!defined('sugarEntry') || !sugarEntry) {
    die('Not A Valid Entry Point');
}
class AYU_CustomfieldsController extends SugarController
{
    public function action_add_custom_fields () {
        // insert the above code, edited to suit the situation
        // (Optionally) add code to run Quick Repair and Rebuild 
        // from within this script
        require_once('modules/Administration/QuickRepairAndRebuild.php');
        $newFields = new RepairAndClear();
        //  Populate Parameters
        $newFields->repairAndClearAll($selected_actions, $modules, $autoexecute=false, $show_output=true);
    }
}

Change the URL in the new menu
From
./index.php?entryPoint=addCustomFieldsEntryPoint
To
./index.php?module=AYU_Customfields&action=add_custom_fields

And in the new module, add a list view to show what field(s) have been added and what field(s) remain to be added, and direct the return after running the code back to the list view (the normal default return).

Add code to store field definitions and flag ones which have already been created
One way to handle this would be to add one file per field to custom/Extension/application/Ext/Extensions/{filename1}.php
A Quick Repair and Rebuild consolidates all these files into one file at custom/application/Ext/Extensions/extensions.ext.php
You could run your check code on either location and set flags to prevent an attempt to add a custom field more than once.

Using a custom field prefix is a good idea.

I don’t know what document this is, but this statement is incorrect.

If you use the 'source' => 'custom_field' option in the field array, the column is created in the table with the DB suffix _cstm I tested it and it worked. SuiteCRM get data from DB table fields_meta_data if you created field using Studio.
SuiteCRM collent fields from 3 places:

  • module/<module_name>/vardefs.php
  • custom/modules/<module_name>/Ext/Vardefs/vardefs.ext.php
  • DB table fields_meta_data (after taking files with _override_sugarfield_ prefix from custom/Extension/modules/<module_name>/Ext/Vardefs/)
    After that SuiteCRM create files like this cache/modules/<module_name>/<object_name>vardefs.php and is working with that fields only.

I didn’t see the new version change the whole data structure in the db tables. This can be a big problem for custom code. I have sometimes seen developers make a direct database call and not use the SuiteCRM object model.

Thanks you to @Ramblin for the discussion.

@p.konetskiy

You won’t find the document anywhere; I created it so I could remember what I learned during this exercise.

I tried adding custom fields using the vardefs without first entering the field in fields_meta-data and could not get it to work. I did include ‘source’ => ‘custom_field’ in the vardef and it did not make a difference - until I manually added the record in fields_meta_data with id = {Modulename}{fieldname}_c and then the vardef was recognized

I did already have a _cstm table for the module

I did already have another field for the module listed in fields_meta_data

But when I put into vardefs the following - WITHOUT first entering anything in fields_meta_data for this field - and I tried with enerything in one array() definition and again with each array element individually defined with a $dictionary entries, there was no entry added to fields_meta_data after a Quick Repair and Rebuild and I could not see the field in Studio so I could not use it in layouts, …

$dictionary['FP_events']['fields']['wierdname_c']['name'] = 'wierdname_c';
$dictionary['FP_events']['fields']['wierdname_c']['inline_edit'] = '';
$dictionary['FP_events']['fields']['wierdname_c']['labelValue'] = 'A very wierdname';
$dictionary['FP_events']['fields']['wierdname_c']['required'] = false;
$dictionary['FP_events']['fields']['wierdname_c']['source'] = 'custom_fields';
$dictionary['FP_events']['fields']['wierdname_c']['vname'] = 'LBL_WIERDNAME';
$dictionary['FP_events']['fields']['wierdname_c']['type'] = 'varchar';
$dictionary['FP_events']['fields']['wierdname_c']['massupdate'] = '0';
$dictionary['FP_events']['fields']['wierdname_c']['default'] = '';
$dictionary['FP_events']['fields']['wierdname_c']['no_default'] = false;
$dictionary['FP_events']['fields']['wierdname_c']['comments'] = '';
$dictionary['FP_events']['fields']['wierdname_c']['help'] = '';
$dictionary['FP_events']['fields']['wierdname_c']['importable'] = 'true';
$dictionary['FP_events']['fields']['wierdname_c']['duplicate_merge'] = 'disabled';
$dictionary['FP_events']['fields']['wierdname_c']['duplicate_merge_dom_value'] = '0';
$dictionary['FP_events']['fields']['wierdname_c']['audited'] = false;
$dictionary['FP_events']['fields']['wierdname_c']['reportable'] = true;
$dictionary['FP_events']['fields']['wierdname_c']['unified_search'] = false;
$dictionary['FP_events']['fields']['wierdname_c']['merge_filter'] = 'disabled';
$dictionary['FP_events']['fields']['wierdname_c']['len'] = '255';
$dictionary['FP_events']['fields']['wierdname_c']['size'] = '20';
$dictionary['FP_events']['fields']['wierdname_c']['id'] = 'FP_eventswierdname_c';
$dictionary['FP_events']['fields']['wierdname_c']['custom_module'] = '';
$dictionary['FP_events']['fields']['wierdname_c']['studio'] = 'visible';

Can you see what I am missing to get it to work with vardefs?

@Ramblin

  1. What name of file in directory: custom/Extension/modules/<module_name>/Ext/Vardefs/ ? The file shoudn’t be prefix _override_sugarfield_
  2. Try to run ‘Quick Repair and Rebuild’ twice in a row.
  3. Using array. It is more comfortable.

@p.konetskiy

*** Edited after original post to correct typos and add relevant information ***

The vardef is in custom/Extension/modules/FP_events/Ext/Vardefs/wierdname.php

After a Quick Repair and Rebuild, the entries do appear in custom/modules/FP_events/Ext/Vardefs/vardefs.ext.php

I tried it with the file named:
wierdname.php
wierdname_c.php
_override_sugarfield_wierdname.php

I have tried it with $dictionary as an array and with each element individually defined in a $dictionary line. The last one I tried was with each element individually defined in a $dictionary line so that is what I showed you. I prefer the array as well, but the instructions linked previously said to use the individual $dictionary definitions so I tried that.

I just tried using Quick Repair and Rebuild twice in a row

There was no entry in the fp_events_cstm database table or in fields_meta_data

I cannot see the field in Studio

I am on SuiteCRM v7.12.8 on Debian 10. A relatively fresh install just to try this out.

I have disabled the CRON job which triggers the scheduler since I am just using this installation to test some install techniques.

Anything else you can think of that may be causing the difference between what you are doing and what I am doing?

@Ramblin

It was an interesting task. :slightly_smiling_face:

There are some details before the answer.

  1. I couldn’t create a new field for the FP_events module as you did.
  2. I could easily create a new field for the Contacts module because this module has custom fields created with Studio (e.g. custom/Extension/modules/Contacts/Ext/Vardefs/_override_sugarfield_jjwg_maps_address_c. php )
  3. SuiteCRM checks the fields_meta_data table when calling the ‘Quick Repair and Rebuild’ process. The process set the special variable to true. (The Studio writes data to the table when creating a new field and creates a file in the custom/Extension/modules/<module_name>/Ext/Vardefs/ directory with the prefix _override_sugarfield_.)

Answer:
You can directly set the value of a special variable. It is safe.

$dictionary[<object_name>]['custom_fields'] = true;

You can do this in any file with custom fields in the directory:
custom/Extension/modules/<module_name>/Ext/Vardefs/

Note: <module_name> and <object_name> do not match in some modules.

@p.konetskiy

You have a way of understating … :slight_smile:

Definitely an interesting task.

I cannot match your success even after duplicating what worked for you.

Question: Does the $dictionary[’’][‘custom_fields’] = true; declaration go into custom/Extension/modules//Ext/Vardefs/.php ?

That is where I tried putting it.

I tried adding, to custom/Extension/modules/FP_events/Ext/Vardefs/setCustomFlag.php

<?php
$dictionary['FP_events']['custom_fields'] = true;

to see if doing that enabled QR&R to create the custom field from the following vardef in custom/Extension/modules/FP_events/Ext/Vardefs/maybe_c.php

<?php
$dictionary['FP_events']['fields']['maybe_c'] = array(
    'name' => 'maybe_c',
    'vname' => 'LBL_MAYBE',
    'type' => 'varchar',
    'len' => '255',
    'size' => '20',
    'source' => 'custom_fields',
    'custom_module' => 'FP_events',
    'id' => 'FP_eventsmaybe_c',
    'help' => '',
    'comments' => '',
    'default' => '',
    'no_default' => true,
    'duplicate_merge' => 'disabled',
    'duplicate_merge_dom_value' => '0',
    'required' => false,
    'inline_edit' => '',
    'massupdate' => '0',
    'audited' => false,
    'reportable' => true,
    'importable' => 'true',
    'unified_search' => false,
    'merge_filter' => 'disabled',
    'studio' => 'visible',
);

There is an entry for FP_events in the fp_events_cstm table in the database from previously adding fields to FP_events via Studio and via the method in the above post.

There are previous entries in fields_meta_table for FP_events from previously adding fields to FP_events via Studio and via the method in the above post.

After QR&R the maybe_c field definition was added to custom/modules/FP_events/Ext/Vardefs/vardefs.ext.php

But, after the QR&R, nothing was added to either of the fields_metda_data or fp_events_cstm databae tables. I did try running QR&R twice

So I then tried adding the same field definition - edited for Contacts - to the the Contacts vardefs in custom/Extension/modules/Contacts/Ext/Vardefs/maybe_c.php

<?php
$dictionary['Contact']['fields']['maybe_c'] = array(
    'name' => 'maybe_c',
    'vname' => 'LBL_MAYBE',
    'type' => 'varchar',
    'len' => '255',
    'size' => '20',
    'source' => 'custom_fields',
    'custom_module' => 'Contacts',
    'id' => 'Contactsmaybe_c',
    'help' => '',
    'comments' => '',
    'default' => '',
    'no_default' => true,
    'duplicate_merge' => 'disabled',
    'duplicate_merge_dom_value' => '0',
    'required' => false,
    'inline_edit' => '',
    'massupdate' => '0',
    'audited' => false,
    'reportable' => true,
    'importable' => 'true',
    'unified_search' => false,
    'merge_filter' => 'disabled',
    'studio' => 'visible',
);

As you said, there were already entries in contacts_cstm and fields_meta_data for Contacts.

After a QR&R, nothing was added to fields_meta_data or contacts_cstm

So I THINK I am doing the same as you but I am not getting the same results as you.

I got my vardef parameters by looking at the cache/modules/FP_events/FP_eventsvardefs.php so I think I am using the right vardefs definition, but do you see anything in my vardef that would be preventing what I am doing from working with vardefs?

Just to see if my system was totally messed up, I tried adding a custom field to each of FP_events and Contacts using the programatic method described above and it worked, with 2 new entries in fields_meta_data and a new entry in each of fp_events_cstm and contacts_cstm

Create a new file in {SuiteCRM_Directory}/addCustomFields.php with

<?php

if(!defined('sugarEntry') || !sugarEntry) {
    die('Not A Valid Entry Point');
}

$fields = array ();

$fields[] = array(
    // Text Field
    'name' => 'maybe2_c',
    'label' => 'LBL_MAYBE2',
    'type' => 'varchar',
    'module' => 'FP_events',
    'help' => 'Text Field Help Text',
    'comment' => 'Text Field Comment Text',
    'default_value' => '',
    'max_size' => 255,
    'required' => false, // true or false
    'reportable' => true, // true or false
    'audited' => false, // true or false
    'importable' => 'true', // 'true', 'false', 'required'
    'duplicate_merge' => false, // true or false
);

$fields[] = array(
    // Text Field
    'name' => 'maybe2_c',
    'label' => 'LBL_MAYBE2',
    'type' => 'varchar',
    'module' => 'Contacts',
    'help' => 'Text Field Help Text',
    'comment' => 'Text Field Comment Text',
    'default_value' => '',
    'max_size' => 255,
    'required' => false, // true or false
    'reportable' => true, // true or false
    'audited' => false, // true or false
    'importable' => 'true', // 'true', 'false', 'required'
    'duplicate_merge' => false, // true or false
);

require_once('ModuleInstall/ModuleInstaller.php');
$newInstallerBean = new ModuleInstaller();
$newInstallerBean->install_custom_fields($fields);
// Return the user to the Administration menu
SugarApplication::redirect('index.php?module=Administration&action=index');

Enable that file to be an entry point by adding the file at custom/Extension/application/Ext/EntryPointRegistry/addCustomFieldsEntryPoint.php

<?php
$entry_point_registry['addCustomFieldsEntryPoint'] = array(
    // Pointer to the location of the file for which this EntryPoint is defined
    'file' => 'addCustomFields.php',
    // auth true means person using the EntryPoint must be an authenticated User
    // auth false means anyone could the EntryPoint - NOT a good idea usually
    'auth' => true,
);

Quick Repair and Rebuild

Point my browser to the EntryPoint at

{SuiteCRM_URL}/index.php?entryPoint=addCustomFieldsEntryPoint

and yes, the maybe2_c custom fields were created in fields_meta_data, fp_events_cstm and contacts_cstm

So this is DEFINITELY getting interesting.

I cannot get to work what works on your system

And you cannot get to work what works on my system

Maybe we should take our 2 systems and send them to counselling so they can agree … :slight_smile:

Any ideas?

@Ramblin

  1. I recommend fixing the bug here first. You missed the key for the field 'maybe_c'
`$dictionary['FP_events']['fields']['maybe_c'] = array(`
  1. I created the video so you can see my system.
    https://drive.google.com/file/d/1-1ujCJVGVXIR9jjRBj56Kbcpj29DT1u9/view?usp=share_link

  2. The fields_meta_data table is not used when the custom field is created from a file and not from Studio.

This is a good idea. :laughing:

@p.konetskiy [quote=“p.konetskiy, post:19, topic:87306”]
I recommend fixing the bug here first. You missed the key for the field 'maybe_c'
[/quote]

I copy/pasted the wrong text in the post above. In the version I used in my system, the ‘maybe_c’ field was included in the vardef. I have updated the post above. Thank you for the catch.

I watched your video.

I am doing exactly the same thing and am not getting the “Execute SQL” option after a QR&R so there is no field being added to the fp_events_cstm table. I even tried running QR&R twice.

I noticed that in your video, the field you added was the first/only custom field for FP_events.

I had previously added custom fields via Studio and via the programatic method described above to check the correct parameters and then tried adding via vardefs. I wonder if the prior existence of a Studio-generated or programatic-=generated custom field in the fp_events_cstm table is somehow blocking the addition of another custom field via vardefs. I’ll setup a fresh SuiteCRM and try the vardefs first.

Are you saying that the programatic method described in my last post for adding custom fields does not work on your sytem?

R