Let the platform do the work

Creating an Installable Package for a Logic Hook

Overview

These examples will demonstrate how to create module loadable packages for logic hooks based on different scenarios.

Logic Hook File vs. Logic Hook Definition

No matter the deployment method, all logic hooks require being registered (meaning they are attached to the $hook_array array), defining the logic hook event, module, file to load, and class and function to run for that logic hook event. For all deployment options, the logic hook definition points to a file where the class and function to run is located, and this file must be copied to the instance via the copy installdefs of the manifest. The bulk of this article will focus on the various options for registering the logic hook definition via the package manifest. But all deployment strategies will assume the same logic hook definition, the same logic hook file, and will use the same copy array to move the logic hook file into the instance.

Note: More information on the $manifest or $installdef can be found in the Introduction to the Manifest .

The Logic Hook

This logic hook will install a before_save hook to the accounts module that will default the account name to 'My New Account Name ({time stamp})'. This various ways of installing this hook will be shown in the following sections.

Logic Hook Definition

<basepath>/Files/custom/Extension/Accounts/Ext/LogicHooks/account_name_hook.php

  <?php

$hook_array['before_save'][] = Array(
    99, 
    'Example Logic Hook - Updates account name', 
    'custom/modules/Accounts/accounts_save.php', 
    'Accounts_Save', 
    'updateAccountName'
);

Logic Hook File

<basepath>/Files/custom/modules/Accounts/accounts_save.php

  <?php

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

class Accounts_Save
{
	function updateAccountName($bean, $event, $arguments)
	{
		$bean->name = "My New Account Name (" . time() . ")";
	}
}

Distributed Plugin

If the package being built is intended to be distributed to various Sugar instances as part of a distributed plugin, your logic hook definition should be created as part of the extension framework using the LogicHooks Extension, which can be done using $installdefs['logic_hooks'] in the package manifest. When using this extension, the logic hook will be installed and uninstalled along with the plugin.

Note: More information on the $installdefs['logic_hooks'] can be found in LogicHooks Extensions.

Package Example

The following files are relative to the root of the .zip archive which is referred to at the basepath. This example package can be downloaded here.

<basepath>/manifest.php

  <?php

$manifest = array(
    'acceptable_sugar_flavors' => array(
        'PRO',
        'ENT',
        'ULT'
    ),
    'acceptable_sugar_versions' => array(
        'exact_matches' => array(),
        'regex_matches' => array(
            '13.0.*
        '),
    ),
    'author' => 'SugarCRM',
    'description' => 'Installs a sample logic hook - using extension framework',
    'icon' => '',
    'is_uninstallable' => true,
    'name' => 'Example Logic Hook Installer - Using Extension Framework',
    'published_date' => '2018-01-01 00:00:00',
    'type' => 'module',
    'version' => '1.0.0',
);

$installdefs = array(
	'id' => 'package_123',
	'copy' => array(
		array(
			'from' => '<basepath>/Files/custom/modules/Accounts/accounts_save.php',
			'to' => 'custom/modules/Accounts/accounts_save.php',
		),
	),
	'hookdefs' => array(
		array(
			'from' => '<basepath>/Files/custom/Extension/Accounts/Ext/LogicHooks/account_name_hook.php',
			'to_module' => 'Accounts',
		)
	),
);

<basepath>/Files/custom/Extension/Accounts/Ext/LogicHooks/account_name_hook.php

  <?php

$hook_array['before_save'][] = Array(
    99, 
    'Example Logic Hook - Updates account name', 
    'custom/modules/Accounts/accounts_save.php', 
    'Accounts_Save', 
    'updateAccountName'
);

<basepath>/Files/custom/modules/Accounts/accounts_save.php

  <?php

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

class Accounts_Save
{
	function updateAccountName($bean, $event, $arguments)
	{
		$bean->name = "My New Account Name (" . time() . ")";
	}
}

Promotion Process

If the package being built is intended to be part of a code promotion process, you are welcome to use the LogicHooks Extension as mentioned above or you may find it easier to update the ./custom/modules/<module>/logic_hooks.php file, which can be done using the $installdefs['logic_hooks'] in the package manifest.

Package Example

The following files are relative to the root of the .zip archive which is referred to at the basepath. This example package can be downloaded here.

<basepath>/manifest.php

  <?php

$manifest = array(
        'acceptable_sugar_flavors' => array(
            'PRO',
            'ENT',
            'ULT'
        ),
        'acceptable_sugar_versions' => array(
            'exact_matches' => array(),
            'regex_matches' => array(
                '13.0.*
            '),
        ),
	'author' => 'SugarCRM',
	'description' => 'Installs a sample logic hook - using logic_hooks installdefs',
	'icon' => '',
	'is_uninstallable' => true,
	'name' => 'Example Logic Hook Installer - Using logic_hooks installdefs',
	'published_date' => '2018-01-01 00:00:00',
	'type' => 'module',
	'version' => '1.0.0',
);

$installdefs = array(
	'id' => 'package_456',
	'copy' => array(
		array(
			'from' => '<basepath>/Files/custom/modules/Accounts/accounts_save.php',
			'to' => 'custom/modules/Accounts/accounts_save.php',
		),
	),
	'logic_hooks' => array(
		array(
			'module' => 'Accounts',
			'hook' => 'before_save',
			'order' => 99,
			'description' => 'Example Logic Hook - Updates account name',
			'file' => 'custom/modules/Accounts/accounts_save.php',
			'class' => 'Accounts_Save',
			'function' => 'updateAccountName',
		),
	),
);

<basepath>/Files/custom/modules/Accounts/accounts_save.php

  <?php

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

class Accounts_Save
{
	function updateAccountName($bean, $event, $arguments)
	{
		$bean->name = "My New Account Name (" . time() . ")";
	}
}

Conditionally Add or Remove Logic Hook via post_execute script

A developer may want to be able to trigger the addition or removal of logic hooks from a customization. This can be done using a post execute script with the check_logic_hook_file and remove_logic_hook_file functions.

It is recommended to be cautious when doing this and limit any updates to off-hours as not to affect system behavior for users.

Noteremove_logic_hook_file only removes hooks defined in the given module's logic_hooks.php file. check_logic_hook_file only checks hooks defined in the given module's logic_hooks.php file. Neither check or remove hooks defined via the Logic Hook Extension framework. Thus this deployment option should be considered a subset of the Promotion Process deployment option listed earlier.

Package Example

Note: For demonstration purposes, in the post_execute script, the Accounts_Save logic hook from the earlier example package is unregistered (if it exists) and a second logic hook Accounts_Save_Enterprise is registered. The second logic hook points to a different logic hook file, which is moved to the instance using copy in the manifest.

The following files are relative to the root of the .zip archive which is referred to at the basepath. This example package can be downloaded here.

<basepath>/manifest.php

  <?php

$manifest = array(
        'acceptable_sugar_flavors' => array(
            'PRO',
            'ENT',
            'ULT'
        ),
        'acceptable_sugar_versions' => array(
            'exact_matches' => array(),
            'regex_matches' => array(
                '13.0.*
            '),
        ),
	'author' => 'SugarCRM',
	'description' => 'Installs a sample logic hook - using post_execute check_logic_hook_file',
	'icon' => '',
	'is_uninstallable' => true,
	'name' => 'Example Logic Hook Installer - Using post_execute check_logic_hook_file',
	'published_date' => '2018-01-01 00:00:00',
	'type' => 'module',
	'version' => '1.0.0',
);

$installdefs = array(
	'id' => 'package_789',
	'copy' => array(
		array(
			'from' => '<basepath>/Files/custom/modules/Accounts/accounts_save_enterprise.php',
			'to' => 'custom/modules/Accounts/accounts_save_enterprise.php',
		),
	),
	'post_execute' => array(
		 '<basepath>/change_hooks.php',
	),

);

<basepath>/Files/custom/modules/Accounts/accounts_save_enterprise.php

  <?php

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

class Accounts_Save_Enterprise
{
	function updateAccountName($bean, $event, $arguments)
	{
		$bean->name = "My New Account Name (" . time() . ") -- Enterprise";
	}
}

<basepath>/change_hooks.php

  <?php

if(!defined('sugarEntry')) define('sugarEntry', true);

require_once 'include/entryPoint.php';

$accounts_hook_pro = array(
	99,
	'Example Logic Hook - Updates account name',
	'custom/modules/Accounts/accounts_save.php',
	'Accounts_Save',
	'updateAccountName'
);

$accounts_hook_ent = array(
	99,
	'Example Logic Hook - Updates account name - Enterprise',
	'custom/modules/Accounts/accounts_save_enterprise.php',
	'Accounts_Save_Enterprise',
	'updateAccountName'
);

if( $GLOBALS['sugar_flavor'] == 'ENT' ) {

	//unregister Accounts_Save logichook
	remove_logic_hook("Accounts", "before_save", $accounts_hook_pro);

	//register Accounts_Save_Enterprise logichook
	check_logic_hook_file("Accounts", "before_save", $accounts_hook_ent);
}