use Sugarcrm\Sugarcrm\Elasticsearch\Provider\Visibility\Filter\FilterInterface;
use Sugarcrm\Sugarcrm\Elasticsearch\Provider\Visibility\Visibility;
/**
 *
 * Custom opportunity filter by sales_stage
 *
 * This logic can exist directly in the FilterOpportunities visibility class.
 * However by abstracting the (custom) filters makes it possible to re-use
 * them in other places as well.
 */
class OpportunitySalesStagesFilter implements FilterInterface
{
    /**
     * @var Visibility
     */
    protected $provider;
    /**
     * {@inheritdoc}
     */
    public function setProvider(Visibility $provider)
    {
        $this->provider = $provider;
    }
    /**
     * {@inheritdoc}


}
    /**
     * {@inheritdoc}
     */
    public function buildFilter(array $options = array())
    {
        return new \Elastica\Query\Terms(
            'visibility_sales_stage',
            $options['filter_sales_stages']
        );
    }
}
After creating the above files, log in to your Sugar instance as an administrator and navigate toÂ AdministrationÂ > Repair > Quick Repair and Rebuild.Â Â
Next, perform a full reindex by navigating toÂ AdministrationÂ > SearchÂ and selecting the "delete existing data" option.Â
Execute a cron to process all of the queued records into ElasticsearchÂ by doing the following:Â
Open a command line client and navigate to your Sugar directory.


Open a command line client and navigate to your Sugar directory.
ExecuteÂ chmod +x bin/sugarcrmÂ to ensureÂ bin/sugarcrm is executable.
ExecuteÂ php cron.phpÂ to consume the queue.
ExecuteÂ bin/sugarcrm elastic:queueÂ to see if the queue has finished.
Repeat steps 3 and 4 until the queue has 0 records.
This example requires the Sales Stage field to be part of the Opportunities module.Â Â Navigate toÂ Administration > OpportunitiesÂ and ensure theÂ OpportunitiesÂ radio button is selected.


Create a new role named "Demo Visibility"Â and assign a user to this role.Â  Note: if you are using the sample data, do NOT use Jim as he has admin permission on the Opportunities module and will be able to view all records. We recommend using Max.
Configure your instance to filter opportunities for a given sales stages for this role by adding the following to ./config_override.php:
<?php
$sugar_config['custom']['visibility']['opportunities']['target_role'] = 'Demo Visibility';
$sugar_config['custom']['visibility']['opportunities']['filter_sales_stages'] = array('Closed Won', 'Closed Lost');


Log in as the user to whom you assigned the Demo Visibility role. Observe that opportunity records in the sales stages "Closed Won" and "Closed Lost"Â areÂ no longer accessible.
You can download a module loadable package of this example here.
  	Last modified: 2023-02-03 21:04:03


Manipulating Teams Programmatically
Overview
How to manipulate team relationships.
Fetching Teams
To fetch teams related to a bean, you will need to retrieve an instance of a TeamSet object and use the getTeams() method to retrieve the teams using the team_set_id. An example is shown below:
//Create a TeamSet bean - no BeanFactory
require_once 'modules/Teams/TeamSet.php';
$teamSetBean = new TeamSet();
//Retrieve the bean
$bean = BeanFactory::getBean($module, $record_id);
//Retrieve the teams from the team_set_id
$teams = $teamSetBean->getTeams($bean->team_set_id);
Adding Teams


Adding Teams
To add a team to a bean, you will need to load the team's relationship and use the add() method. This method accepts an array of team ids to add. An example is shown below:
//Retrieve the bean
$bean = BeanFactory::getBean($module, $record_id);
//Load the team relationship
$bean->load_relationship('teams');
//Add the teams
$bean->teams->add(
    array(
        $team_id_1,
        $team_id_2
    )
);
Considerations
If adding teams in a logic hook, the recommended approach is to use an after_save hook rather than a before_save hook as the $_REQUEST may reset any changes you make.
Removing Teams


Removing Teams
To remove a team from a bean, you will need to load the team's relationship and use the remove() method. This method accepts an array of team ids to remove. An example is shown below:
//Retrieve the bean
$bean = BeanFactory::getBean($module, $record_id);
//Load the team relationship
$bean->load_relationship('teams');
//Remove the teams
$bean->teams->remove(
    array(
        $team_id_1,
        $team_id_2
    )
);
Considerations
If removing teams in a logic hook, the recommended approach is to use an after_save hook rather than a before_save hook as the $_REQUEST may reset any changes you make.
Replacing Team Sets


Replacing Team Sets
To replace all of the teams related to a bean, you will need to load the team's relationship and use the replace() method. This method accepts an array of team ids. An example is shown below:
//Retrieve the bean
$bean = BeanFactory::getBean($module, $record_id);
//Load the team relationship
$bean->load_relationship('teams');
//Set the primary team
$bean->team_id = $team_id_1
//Replace the teams
$bean->teams->replace(
    array(
        $team_id_1,
        $team_id_2
    )
);
//Save to update primary team
$bean->save()
Considerations


);
//Save to update primary team
$bean->save()
Considerations
If replacing teams in a logic hook, the recommended approach is to use an after_save hook rather than a before_save hook as the $_REQUEST or workflow may reset any changes you make.
This method does not replace (or set) the primary team for the record. When replacing teams, you need to also make sure that the primary team, determined by the team_id field, is set appropriately and included in the replacement ids. If this is being done in a logic hook you should set the primary team in a before_save hook and replace the team set in the after_save hook.
When using an after_saveÂ hook, be sure to call $bean->teams->setSaved(false) to explicitly reset the save state. This ensures that the updates to the team sets are applied.
Example:
//before save function


Example:
//before save function
public function before_save_hook($bean, $event, $arguments)
{
    $bean->team_id = $team_id_1;
}
//after save function
public function after_save_hook($bean, $event, $arguments)
{
	$bean->teams->setSaved(false); // Manually reset TeamSet state for save
    $bean->teams->replace(
        array(
            $team_id_1,
            $team_id_2
        )
    );
}
Creating and Retrieving Team Set IDs


)
    );
}
Creating and Retrieving Team Set IDs
To create or retrieve the team_set_id for a group of teams, you will need to retrieve an instance of a TeamSet object and use the addTeams() method. If a team set does not exist, this method will create it and return an id. An example is below:
//Create a TeamSet bean - no BeanFactory
require_once 'modules/Teams/TeamSet.php';
$teamSetBean = new TeamSet();
//Retrieve/create the team_set_id
$team_set_id = $teamSetBean->addTeams(
    array(
        $team_id_1,
        $team_id_2
    )
);
Adding Additional Access


$team_id_2
    )
);
Adding Additional Access
To enable additional access for a record, you can either set the team id or team setÂ to the beansÂ acl_team_set_id field. An example of this is shown below:
require_once 'modules/Teams/TeamSet.php';
// Create a new teamset or fetch the id of an existing teamset
$teamSetBean = new TeamSet();
$teamSetId = $teamSetBean->addTeams([
    'East', // Demo Team ID
    'West', // Demo Team ID
]);
$bean = BeanFactory::getBean('Accounts', '15bcf01c-1e1e-11e8-9e13-f45c89a8598f');
// Set additional access


// Set additional access
$bean->acl_team_set_id = $teamSetId; // if set to NULL, this will remove any existing value
$bean->save();
  	Last modified: 2023-02-03 21:04:03


Themes
Overview
How to customize theÂ Sugar theme.Â
Theme Variables
Sugar's themeÂ variables, defined inÂ ./styleguide/themes/clients/base/default/variables.php,Â determine theÂ color of the primary actionÂ buttons, links,Â andÂ header navigation. An example of the definition is shown below:
./styleguide/themes/clients/base/default/variables.php
$lessdefs = array(
    'colors' => array(
        /**
         * Secondary Color:
         * color of the navbar
         * -------------------------
         * was @secondary
         */
        'NavigationBar' => '#fff',
        /**
         * Primary Button Color:
         * color of the primary button
         * -------------------------


* color of the primary button
         * -------------------------
         * was @primaryBtn
         */
        'PrimaryButton' => '#0679c8',
    ),
);
Variable Descriptions
It is important to understand what the purpuse and utility of each variable is before you apply in your code, below is an in-depth description:
@NavigationBar
Used to customize the mega menu background colourÂ
Defaults to Sugar's @whiteÂ (#ffffff)Â
Note: This variable is only supported in light mode
@PrimaryButton
Used to customize the background colour for primary buttonsÂ (elements using `btnÂ btn-primary`)Â
Defaults to Sugar's @blue (#0679c8)Â
@LinkColor Â
Used to customize the text color of link (anchor) elementsÂ


Used to customize the text color of link (anchor) elementsÂ
Defaults to Sugar's @blue (#0679c8)Â
Note: This variable is only supported in light mode
Custom Themes
Modifications toÂ theÂ theme can be made by creatingÂ ./custom/themes/clients/base/default/variables.php. Within this file, you can define the custom hex codes for the colors you would like to use. You should note that this is limited to theÂ @NavigationBar, and @PrimaryButton less variables. An example is shown below.
Â ./custom/themes/clients/base/default/variables.php
Note:Â DevelopersÂ cannot override existing bootstrapÂ lessÂ variables using this file.
Adding CSS


Adding CSS
Sugar allows you to customize CSS using the less language in ./custom/themes/custom.less.Â As Sugar makes use of the Bootstrap library, you have access to the features of Bootstrap and can make use of its variables to create your own CSS.Â An example is shown below.Â
./custom/themes/custom.less
//You can import any less file you want and define your own file structure
//@import 'anyotherfile.less
@myCustomBgColor: lighten(@NavigationBar,10%); //variable defined on a custom variable.
.myCustomClass {
    color: @linkColor; //bootstrap variable
    background-color: @myCustomBgColor;
}
Overriding CSS Definitions


}
Overriding CSS Definitions
You can use theÂ ./custom/themes/custom.less fileÂ toÂ overrideÂ CSS classes. The following example overridesÂ the record label font size.
./custom/themes/custom.less
/*
* Changes record field label sizes to 13px;
*/
.record-cell .record-label{
    font-size:13px;
}
Overriding the MegaMenu
As the MegaMenu has limited color customization within ./custom/themes/clients/base/default/variables.php,Â you may want to customize the look and feel further. The following example will automatically set the menu's link color to a contrasting color based on the @NavigationBarÂ variableÂ andÂ determine the hover and active colors for the tabs.Â Â


./custom/themes/custom.less
// Workaround for luminance calculation
// Use luma() function once Sugar upgraded Lessphp to 1.7+ (see: http://lesscss.org/functions/#color-channel-luminance)
@luma: 1 - ( (0.299 * red(@NavigationBar)) + (0.587 * green(@NavigationBar)) + (0.114 * blue(@NavigationBar)))/255;
/**
 * LESS GUARDS
 */
// General Nav Colors
.mixin-color() {
    // Darker Colors
    & when (@luma > 0.5) {
        color: darken(contrast(@NavigationBar), 10%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {


// Bright Colors
    & when (@luma <= 0.5) {
        color: lighten(contrast(@NavigationBar), 10%) !important;
        // color: darken(@NavigationBar, 30%) !important;
    }
}
// Nav Fa Icon Colors
.mixin-fa-color(){
    // Darker Colors
    & when (@luma > 0.5) {
        color: darken(contrast(@NavigationBar), 10%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        // color: lighten(@NavigationBar, 30%);
        color: lighten(contrast(@NavigationBar), 10%) !important;
        // color: darken(@NavigationBar, 30%) !important;
    }
}


}
}
// Hover Button Groups Background colors
.mixin-background-color-hover(){
    // Dark Colors
    & when (@luma > 0.5) {
        background-color: lighten(@NavigationBar, 15%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        background-color: darken(@NavigationBar, 15%) !important;
    }
}
// Hover Button Groups colors
.mixin-color-hover(){
    // Dark Colors
    & when (@luma > 0.5) {
        color: darken(contrast(@NavigationBar), 10%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        // color: lighten(@NavigationBar, 20%) !important;


// color: lighten(@NavigationBar, 20%) !important;
        color: lighten(contrast(@NavigationBar), 10%) !important;
    }
}
// Active Button Group Background Colors
.mixin-background-color-active(){
    // Dark Colors
    & when (@luma > 0.5) {
        background-color: lighten(@NavigationBar, 10%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        background-color: darken(@NavigationBar, 10%) !important;
    }
}
// Active Button Group Hover Colors
.mixin-color-active-hover(){
    // Dark Colors
    & when (@luma > 0.5) {
        color: darken(contrast(@NavigationBar), 5%) !important;


color: darken(contrast(@NavigationBar), 5%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        color: lighten(contrast(@NavigationBar), 5%) !important;
    }
}
// Open Button Group Background Colors
.mixin-background-color-open(){
    // Dark Colors
    & when (@luma > 0.5) {
        background-color: lighten(@NavigationBar, 20%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        background-color: darken(@NavigationBar, 20%) !important;
    }
}
// Open Button Group Hover Colors
.mixin-color-open-hover(){
    // Dark Colors


.mixin-color-open-hover(){
    // Dark Colors
    & when (@luma > 0.5) {
        color: darken(contrast(@NavigationBar), 15%) !important;
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        color: lighten(contrast(@NavigationBar), 15%) !important;
    }
}
// Background/Foreground Dropdown Menu Hover
.mixin-background-foreground-dropdown-menu-hover(){
    // Dark Colors
    & when (@luma > 0.5) {
        background-color: lighten(@NavigationBar, 15%) !important;
        color: darken(contrast(@NavigationBar), 15%) !important;
        .fa {


.fa {
            color: darken(contrast(@NavigationBar), 15%) !important;
        }
    }
    // Bright Colors
    & when (@luma <= 0.5) {
        background-color: @NavigationBar !important;
        color: lighten(contrast(@NavigationBar), 5%) !important;
        .fa {
            color: lighten(contrast(@NavigationBar), 5%) !important;
        }
    }
}
/**
 * LESS Definitions
 */
// Nav Button Group
.module-list .megamenu > .dropdown .module-name{
    .mixin-color;
}
// Home Button Caret
.navbar .megamenu > .dropdown.active .btn-group:not(.open).home .fa-caret-down,


// More Button Caret
.module-list .megamenu > .dropdown.more .fa,
// Module Toggle caret
.navbar .megamenu > .dropdown .btn-group > .dropdown-toggle .fa {
    .mixin-fa-color;
}
// Nav Button Group Hover
.megamenu .dropdown .btn-group{
    &:hover, &:focus{
        .mixin-background-color-hover;
        .btn,
        > .dropdown-toggle .fa{
            .mixin-color-hover;
        }
    }
}
// Active Button Group
.navbar .megamenu > .dropdown.active .btn-group{
    .mixin-background-color-active;
    > .dropdown-toggle .fa,


> .dropdown-toggle .fa,
    > a.btn{
        .mixin-fa-color;
    }
}
// Active Button Group Hover
.navbar .megamenu > .dropdown.active .btn-group:hover{
    .mixin-color-active-hover;
    > .dropdown-toggle .fa,
    > a.btn{
        .mixin-color-active-hover;
    }
}
// Open Nav Button Group
.navbar .megamenu > .dropdown .btn-group.open{
    .mixin-background-color-open;
    > .dropdown-toggle .fa,
    > a.btn{
        .mixin-fa-color;
    }
}
// Open Nav Button Group Hover


}
}
// Open Nav Button Group Hover
.navbar .megamenu > .dropdown .btn-group.open:hover{
    .mixin-color-open-hover;
    > .dropdown-toggle .fa,
    > a.btn{
        .mixin-color-open-hover;
    }
}
// Nav Button Group Dropdown Menu
.navbar .megamenu > .dropdown .dropdown-menu li a{
    &:hover, &:focus{
        .mixin-background-foreground-dropdown-menu-hover;
    }
}
  	Last modified: 2023-02-03 21:04:03


Email
Overview
OutlinesÂ the relationshipsÂ between emails, email addresses, and bean records.
Email Tables
Table Name
Description
email_addresses
Each record in this table represents an email address in the system. Note that the invalid_email column and opt_out column are stored on this table, meaning that they are treated as properties of the email address itself, not a relationship attribute between a given email address and related record. This means if a Lead opts-out of a campaign, this email address will be considered opted-out in all contexts, not just with further correspondence with that specific Lead.
email_addr_bean_rel


email_addr_bean_rel
The email_addr_bean_rel table maintains the relationship between the email address and its parent module record (Contacts, Accounts, Leads, Users, etc) to determine which record of the given module the email address belongs to. Note that this relationship table also has the primary_address and reply_to_address columns to indicate whether a given email address for a given record is the primary email address, the reply to email address, or some other address for the contact. A contactÂ can have one address flagged as primary, and one flagged as "Reply To". This can be the same email address or two different email addresses.
emails_email_addr_rel


emails_email_addr_rel
The emails_email_addr_rel table maintains the relationships between the email address and email records. Note that this relationship table also has the address_type column to indicate if the email address is related to the email as a "To", "From", "CC", or "BCC" address. The valid values at the database level for this column are: from, to, cc, bcc.
emails
Each record in this table represents an email in the system. Note that emails fall outside the scope of this document, but are mentioned here for clarity, as the two modules are closely related.
emails_beans
Similar to the email_addr_bean_rel table, the emails_beans table maintains the relationship between an email record and any related records (Contacts, Accounts, Cases, etc.).
<module>


<module>
This is used to showÂ how an email address record relates to a recordÂ in anyÂ module is set on bean_module. If bean_module is set to Contacts, <module>Â would be the contacts table.
The following diagram illustrates table relationships between email addresses and other modules, email addresses and email records, and email records and other modules.
Helper Queries
Retrieve the Primary Email Address of a Contact
The following query will fetch the email address given a specific contacts id:
SELECT
  email_address
FROM email_addresses
JOIN email_addr_bean_rel eabr
  ON eabr.email_address_id = email_addresses.id
WHERE eabr.bean_module = "Contacts"
AND eabr.bean_id = "<contact id>"
AND email_addresses.invalid_email = 0


AND email_addresses.invalid_email = 0
AND eabr.deleted = 0
AND eabr.primary_address = 1;
Retrieve All Records Related to an Email Address
The following query will fetch the id and module name of all records related to the specified email address:
SELECT
  bean_module,
  bean_id
FROM email_addr_bean_rel eabr
JOIN email_addresses
  ON eabr.email_address_id = email_addresses.id
WHERE email_addresses.email_address = "<email address>"
AND eabr.deleted = 0;
Retrieve All Emails Sent From An Email Address
The following query will fetchÂ all emails sent from aÂ specified email address:
SELECT
  emails.name,
  emails.date_sent
FROM emails


SELECT
  emails.name,
  emails.date_sent
FROM emails
JOIN emails_email_addr_rel eear
  ON eear.email_id = emails.id
JOIN email_addresses
  ON eear.email_address_id = email_addresses.id
WHERE email_addresses.email_address = "<email address>"
AND eear.address_type = "from"
AND eear.deleted = 0
Cleanup Duplicate Email Addresses
The following queries will remove any duplicateÂ email addresses.
Â First, create aÂ temporary tableÂ with distinct records from theÂ email_addr_bean_rel table:
create table email_addr_bean_rel_tmp_ful
SELECT
  *
FROM email_addr_bean_rel
WHERE deleted = '0'


*
FROM email_addr_bean_rel
WHERE deleted = '0'
GROUP BY email_address_id,
         bean_module,
         bean_id
ORDER BY primary_address DESC;
Next, clear out the email_addr_bean_rel table:
truncate email_addr_bean_rel;
Move the records from the temporary table back toÂ email_addr_bean_rel:
INSERT INTO email_addr_bean_rel
 SELECT
 *
 FROM email_addr_bean_rel_tmp;
Validate that all of the duplicates have been removed:
SELECT
 COUNT(*) AS repetitions,
 date_modified,
 bean_id,
 bean_module
FROM email_addr_bean_rel
WHERE deleted = '0'
GROUP BY bean_id,
 bean_module,
 email_address_id


GROUP BY bean_id,
 bean_module,
 email_address_id
HAVING repetitions > 1;
Finally, remove the temporary table:
drop table email_addr_bean_rel_tmp;
Email Address Validation
Sugar validates emails addresses according to theÂ RFC 5321Â andÂ RFC 5322Â standards. The following sections will detail how a developer can validate email addresses both server and client side.
Server Side
To validate an email address in a server-side context, the EmailAddress::isValidEmail() static method should be used. For example:
$emailAddress = "test@example.com";
$isValid = EmailAddress::isValidEmail($emailAddress);


$isValid = EmailAddress::isValidEmail($emailAddress);
TheÂ EmailAddress::isValidEmail method leverages the PHPMailer library bundled with Sugar, specifically the PHPMailer::validateAddress method, which validates the addressÂ according to theÂ RFC 5321Â and RFC 5322 standards.
Client Side
To validate an email address client-side context, theÂ app.utils.isValidEmailAddress()Â function can be used.
var emailAddress = "test@example.com";
var isValid = app.utils.isValidEmailAddress(emailAddress);
Note: This function is more permissive and does not conform exactly to the RFC standards used on the server. As such, theÂ email addressÂ will be validated again on theÂ serverÂ when theÂ record is saved, which could still fail validation.


TopicsMailer FactoryThe Mailer Factory, located in ./modules/Mailer/MailerFactory.php, helps developers generate outbound mailers for the system account as well as individual user accounts. The Mailer Factory is a replacement for SugarPHPMailer which is now deprecated.
  	Last modified: 2023-02-03 21:04:03


Mailer Factory
Overview
The Mailer Factory, located in ./modules/Mailer/MailerFactory.php, helps developers generate outbound mailersÂ for the system account as well as individual user accounts. The Mailer Factory is a replacement for SugarPHPMailer which is now deprecated.
Mailers
There areÂ two types of outbound mailers:Â System andÂ User. The follow sections will outline how to use each.
System Mailer
TheÂ system outbound mailer can be setÂ using theÂ getSystemDefaultMailerÂ method. This will set the mailer to use the system outbound email account.Â
Example
$mailer = MailerFactory::getSystemDefaultMailer();
User Mailer


$mailer = MailerFactory::getSystemDefaultMailer();
User Mailer
The user outbound mailer can be setÂ using the getMailerForUserÂ method. This will set the mailer to use the outbound email account for a specific user.Â
Example
$user = BeanFactory::getBean("Users", 1);
$mailer = MailerFactory::getMailerForUser($user);
Populating the Mailer
Setting the Subject
To set the email subject, use theÂ setSubject method. It accepts a plain text string.
Example
$mailer->setSubject("Test Mail Subject");
Setting the Body
Depending on your email type, you can use the setTextBodyÂ and/or setHtmlBody methods respectively to populate the content of the email body.
Example
// Text Body


Example
// Text Body
$mailer->setTextBody("This is a text body message");
// HTML Body
$mailer->setHtmlBody("This is an HTML body message.
 You can use html tags.");
Note:Â The email HTML body is not necessary if you have populated the text body.
Adding Recipients
To add recipients to your email, you can use theÂ addRecipientsTo, addRecipientsCc, or addRecipientsBcc methods . These methods require an EmailIdentity object as a parameter.
Example
$mailer->addRecipientsTo(new EmailIdentity('user1@yourcompany.crm', 'User 1'));
$mailer->addRecipientsCc(new EmailIdentity('user2@yourcompany.crm', 'User 2'));


$mailer->addRecipientsBcc(new EmailIdentity('user3@yourcompany.crm', 'User 3'));
Clearing Recipients
You can clear the current recipients specified in the mailer by using the clearRecipients method.
Example
$to = true;
$cc = true;
$bcc = true;
$mailer->clearRecipients($to, $cc, $bcc);
Adding Attachments
To add attachments,Â use theÂ addAttachment method.
Example
$path = "/path/to/your/document";
$mailer->addAttachment(new Attachment($path));
Sending Emails


$mailer->addAttachment(new Attachment($path));
Sending Emails
Once your email is populated, you can send it using theÂ send method. TheÂ send method will returnÂ the content of the mail. If the Mailer Factory experiences an error, it will throw an exception. It is highly recommended to use a try and catch when sending emails.
Example
$mailSubject = "Test Mail Subject";
$mailHTML = "
SugarCRM

 Test body message";
$mailTo = array(
    0 => array(
        'name' => 'Test User',
        'email' => 'test@yourcompany.crm',
    ),
    1 => array(
        'name' => 'Other Recipient',
        'email' => 'email@addres'
    )
);


'email' => 'email@addres'
    )
);
$mailAttachment = "/path/to/pdf/files/document.pdf";
try {
    $mailer = MailerFactory::getSystemDefaultMailer();
    $mailTransmissionProtocol = $mailer->getMailTransmissionProtocol();
    $mailer->setSubject($mailSubject);
    $body = trim($mailHTML);
    $textOnly = EmailFormatter::isTextOnly($body);
    if ($textOnly) {
        $mailer->setTextBody($body);
    } else {
        $textBody = strip_tags(br2nl($body)); // need to create the plain-text part
        $mailer->setTextBody($textBody);
        $mailer->setHtmlBody($body);
    }


$mailer->setHtmlBody($body);
    }
    $mailer->clearRecipients();
    foreach ($mailTo as $mailTo) {
        $mailer->addRecipientsTo(new \EmailIdentity($mailTo['email'], $mailTo['name']));
    }
    $mailer->addAttachment(new \Attachment($mailAttachment));
    $result = $mailer->send();
    if ($result) {
        // $result will be the body of the sent email
    } else {
        // an exception will have been thrown
    }
} catch (MailerException $me) {
    $message = $me->getMessage();
    switch ($me->getCode()) {
        case \MailerException::FailedToConnectToRemoteServer:


case \MailerException::FailedToConnectToRemoteServer:
            $GLOBALS["log"]->fatal("BeanUpdatesMailer :: error sending email, system smtp server is not set");
            break;
        default:
            $GLOBALS["log"]->fatal("BeanUpdatesMailer :: error sending e-mail (method: {$mailTransmissionProtocol}), (error: {$message})");
            break;
    }
}
  	Last modified: 2023-02-03 21:04:03


Logic Hooks
Overview
The Logic Hook framework allows you toÂ append actions to systemÂ events such as when creating, editing, and deleting records.
Hook Definitions
A logic hook definition file defines the various actions to execute when an event is triggered. It is important to note that there are various ways to implement a logic hook. The following sections describe the different ways to implement a logic hook and when to use each.
Methodologies
Logic hook definitions canÂ pertainÂ toÂ aÂ specific module or to the entire application. Either way, you must decide if the logic hook definition will be implemented as an extension of or directly to the module or application. The following sections explain the difference between these methodologies.
Module Extension Hooks


Module Extension Hooks
Module extension hooks are located in ./custom/Extension/modules/<module>/Ext/LogicHooks/Â and allow a developerÂ to defineÂ hook actions that will be executed for the specifiedÂ events in a given module.Â Extensions are best used when creating customizations that may be installed in various environments. They help prevent conflicting edits that occur whenÂ modifying ./custom/modules/<module>/logic_hooks.php. More information can be found in theÂ Logic HooksÂ extension section.
Module Hooks


Module Hooks
Module hooks are located inÂ ./custom/modules/<module>/logic_hooks.phpÂ and allow a developerÂ to defineÂ hook actions that will be executed for the specified events in a given module. This path can be used for private development, however, it is not recommended for useÂ withÂ distributed modules and plugins. For distributed code, please refer to using module extensions.
Application Extension Hooks
Application extension hooks are located in ./custom/Extension/application/Ext/LogicHooks/Â and allow a developer to defineÂ hook actions that will be executed for all specified application-level eventsÂ using the extension framework. More information can be found in theÂ Logic HooksÂ extension section.
Application Hooks


Application Hooks
ApplicationÂ hooks are located inÂ ./custom/modules/logic_hooks.phpÂ and allow a developerÂ to defineÂ hook actions that will be executed for the specifiedÂ events in all modules. This path can be used for private development, however, it is not recommended for useÂ withÂ distributed modules and plugins. For distributed code, please refer to usingÂ application extensions.
Definition Properties
All logic hooks must have aÂ $hook_version and $hook_arrayÂ variable defined. The following sections cover each required variable.
hook_version
All logic hook definitions will define a $hook_version. This determines the version of the logic hook framework. Currently, the only supported hook version is 1.
$hook_version = 1;
hook_array


$hook_version = 1;
hook_array
The logic hook definition will also contain a $hook_array. This defines the specific action to execute. The hook array will be defined as follows:
Name
Type
Description
event_name
String
The name of the event to append the action to
process_index
Integer
The order of action execution
description
String
A short description ofÂ the hook action
file_path
String
The path to the logic hook fileÂ in the ./custom/ directory, or null if using namespaces
class_name
String
The name of the logic hook action class including any namespaces
method_name
String
The name of the logic hook action method
Your definition should resemble the code block below:
<?php
    $hook_version = 1;
    $hook_array['<event_name>'][] = array(


$hook_array['<event_name>'][] = array(
        <process_index>, //Integer
        '<description>', //String
        '<file_path>', //String or null if using namespaces
        '<class_name>', //String
        '<method_name>', //String
    );
Hook Method
The hook action class can be located anywhere you choose. WeÂ recommended grouping the hooks with the module they are associated with in the ./custom/ directory. You can create a hook action method either with a namespace or without.
Namespaced Hooks
As of 7.7, developers can create namespaced logic hooks. When using namespaces, the file path in ./custom/Â will be automatically built out when using the corresponding namespace. The filename defining the class must match the class name exactly to allow the autoloader to find the class definition.


Namespace
File Path
Sugarcrm\Sugarcrm\custom
./custom/
Sugarcrm\Sugarcrm\custom
./custom/src/
Sugarcrm\Sugarcrm\custom\any\path
./custom/any/path/
Sugarcrm\Sugarcrm\custom\any\path
./custom/src/any/path/
./custom/Extension/modules/Accounts/Ext/LogicHooks/<file>.php
<?php
    $hook_array['before_save'][] = array(
        1,
        'Hook description',
        null,
        'Sugarcrm\\Sugarcrm\\custom\\modules\\Accounts\\className',
        'methodName'
    );
?>
./custom/modules/Accounts/className.php
<?php


?>
./custom/modules/Accounts/className.php
<?php
namespace Sugarcrm\Sugarcrm\custom\modules\Accounts;
    class className
    {
        function methodName($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
The logic hook method signature may contain different arguments depending on the hook event you have selected.
Hooks without Namespaces
./custom/Extension/modules/Accounts/Ext/LogicHooks/<file>.php
<?php
    $hook_array['before_save'][] = array(
        1,
        'Hook description',
        'custom/modules/Accounts/customLogicHook.php',
        'className',
        'methodName'
    );
?>


'className',
        'methodName'
    );
?>
./custom/modules/Accounts/customLogicHook.php
<?php
    class className
    {
        function methodName($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
The logic hook method signature may contain different arguments depending on the hook event you have selected.
Considerations
When using logic hooks, keep in mind the following best practices:
As of PHP 5.3, objects are automatically passed by reference. When creating logic hook signatures, do notÂ append the ampersand (&) to the $bean variable. Doing this will cause unexpected behavior.
There is no hook that fires specifically for the ListView, DetailView or EditView events. Instead,Â use either the process_recordÂ or after_retrieve logic hooks.


In order to compare new values with previous values, use fetched_row to determine whether a change has occurred: if ($bean->fetched_row['{field}'] != $bean->{field})
{
    //logic
}
Make sure that the permissions on theÂ logic_hooks.php file and the class file that it references are readable by the web server. Otherwise, Sugar will not read the files and your business logic extensions will not work. For example, *nix developers who are extending the Tasks logic should use the following command for the logic_hooks file and the same command for the class file that will be called:
chmod +r ./custom/modules/Tasks/logic_hooks.php
Make sure that the entire ./custom/ directory is writable by the web server or else the logic hooks code will not work properly.


TopicsApplication HooksApplication hooks execute logic when working with the global application.Module HooksModule hooks execute logic when working with Sugar modules (e.g. Accounts, Cases, etc.).User HooksUser hooks execute logic around user actions such as logging in and logging out.Job Queue HooksJob Queue hooks execute logic when working with the Job Queue module.SNIP HooksSNIP hooks execute logic when working with the SNIP email-archiving service.API HooksAPI hooks execute logic when working with the REST API and routing.Web Logic HooksWeb logic hooks let administrators post record and event information to a specified URL when certain sugar events take place.Logic Hook Release NotesThis page documents historical changes to Sugar's logic hook libraries.
  	Last modified: 2023-02-03 21:04:03


Job Queue Hooks
Job Queue hooks execute logic when working with the Job Queue module.
Topicsjob_failureThe job_failure hook executes when a job's final failure occurs.job_failure_retryThe job_failure_retry hook executes each time a job fails before its final failure. If you only want action on the final failure, use the job_failure logic hook.
  	Last modified: 2023-02-03 21:04:03


job_failure_retry
Overview
The job_failure_retry hook executes each time a job fails before its final failure. If you only want action on the final failure, use theÂ job_failure logic hook.
Definition
function job_failure_retry($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The SchedulersJob object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
6.5.0RC1
Added job_failure_retry hook
Example
./custom/modules/SchedulersJobs/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();


$hook_version = 1;
    $hook_array = Array();
    $hook_array['job_failure_retry'] = Array();
    $hook_array['job_failure_retry'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'job_failure_retry example',
        //The PHP file where your class is located.
        'custom/modules/SchedulersJobs/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'job_failure_retry_method'
    );
?>


'job_failure_retry_method'
    );
?>
./custom/modules/SchedulersJobs/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function job_failure_retry_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Â
  	Last modified: 2023-02-03 21:04:03


job_failure
Overview
The job_failure hook executes when a job's final failure occurs.
Definition
function job_failure($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The SchedulersJob object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
6.5.0RC1
Added job_failure hook
Example
./custom/modules/SchedulersJobs/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['job_failure'] = Array();
    $hook_array['job_failure'][] = Array(
        //Processing index. For sorting the array.
        1,


//Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'job_failure example',
        //The PHP file where your class is located.
        'custom/modules/SchedulersJobs/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'job_failure_method'
    );
?>
./custom/modules/SchedulersJobs/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {


class logic_hooks_class
    {
        function job_failure_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


User Hooks
User hooks execute logic aroundÂ user actions such as logging in and logging out.
Topicsafter_loginThe after_login hook executes after a user logs into the system.after_logoutThe after_logout hook executes after a user logs out of the system.before_logoutThe before_logout hook executes before a user logs out of the system.login_failedThe login_failed hook executes on a failed login attempt.
  	Last modified: 2023-02-03 21:04:03


after_logout
Overview
The after_logoutÂ hook executes after a user logs out of the system.
Definition
function after_logout($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
5.0.0a
Added after_logoutÂ hook
Example
./custom/modules/Users/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_logout'] = Array();
    $hook_array['after_logout'][] = Array(
        //Processing index. For sorting the array.
        1,


//Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_logout example',
        //The PHP file where your class is located.
        'custom/modules/Users/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'after_logout_method'
    );
?>
./custom/modules/Users/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function after_logout_method($bean, $event, $arguments)
        {
            //logic
        }


{
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


login_failed
Overview
The login_failed hook executes on a failed login attempt.
Definition
function login_failed($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
5.0.0a
Added login_failed hook
Example
./custom/modules/Users/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['login_failed'] = Array();
    $hook_array['login_failed'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.


1,
        //Label. A string value to identify the hook.
        'login_failed example',
        //The PHP file where your class is located.
        'custom/modules/Users/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'login_failed_method'
    );
?>
./custom/modules/Users/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function login_failed_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Â


{
            //logic
        }
    }
?>
Â
  	Last modified: 2023-02-03 21:04:03


after_login
Overview
The after_login hook executes after a user logs into the system.
Definition
function after_login($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
5.0.0a
Added after_login hook
Example
./custom/modules/Users/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_login'] = Array();
    $hook_array['after_login'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.


1,
        //Label. A string value to identify the hook.
        'after_login example',
        //The PHP file where your class is located.
        'custom/modules/Users/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'after_login_method'
    );
?>
./custom/modules/Users/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function after_login_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>


before_logout
Overview
The before_logoutÂ hook executes before a user logs out ofÂ the system.
Definition
function before_logout($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
5.0.0a
Added before_logoutÂ hook
Example
./custom/modules/Users/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['before_logout'] = Array();
    $hook_array['before_logout'][] = Array(
        //Processing index. For sorting the array.
        1,


//Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_logout example',
        //The PHP file where your class is located.
        'custom/modules/Users/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'before_logout_method'
    );
?>
./custom/modules/Users/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function before_logout_method($bean, $event, $arguments)
        {
            //logic
        }


Application Hooks
Application hooks execute logic when working with the global application.


Topicsafter_entry_pointThe after_entry_point application hook executes at the start of every request.after_load_userThe after_load_user hook executes after the current user is set for the current request. It handles actions that are dependent on the current user, such as setting ACLs or configuring user-dependent parameters.after_session_startThe after_session_start hook executes before the user's session starts, but after the user's visibility rules have been set up and the after_load_user logic hook has executed.after_ui_footerafter_ui_frameThe after_ui_frame hook executes after the frame has been invoked and before the footer has been invoked for modules in backward compatibility mode. This logic hook has been deprecated and will be removed in a future release.entry_point_variables_settingThe entry_point_variables_setting application hook executes at the start of every entry


entry_point_variables_setting application hook executes at the start of every entry point.handle_exceptionThe handle_exception logic hook executes when an exception is thrown.server_round_tripExecutes at the end of every page.


Last modified: 2023-02-03 21:04:03


after_ui_footer
  	Last modified:


server_round_trip
Overview
Executes at the end of every page.
Definition
function server_round_trip($event, $arguments){}
Arguments
Name
Type
Description
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Considerations
This is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
If you are intending to write display logic to the screen, you must first wrap the display logic in an if condition to prevent breaking the Ajax page loads:if (!isset($_REQUEST["to_pdf"]) || $_REQUEST["to_pdf"] == false)
{
    //display logic
}
This hook is executed on all page loads.
Application hooks do not make use of the $bean argument.
Change Log
Version
Note


Application hooks do not make use of the $bean argument.
Change Log
Version
Note
5.0.0a
Added server_round_trip hook.
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['server_round_trip'] = Array();
    $hook_array['server_round_trip'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'server_round_trip example',
        //The PHP file where your class is located.
        'custom/modules/application_hooks_class.php',
        //The class the method is in.
        'application_hooks_class',


'application_hooks_class',
        //The method to call.
        'server_round_trip_method'
    );
?>
./custom/modules/application_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class application_hooks_class
    {
        function server_round_trip_method($event, $arguments)
        {
            //display logic should check for $_REQUEST["to_pdf"]
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


after_entry_point
Overview
The after_entry_pointÂ application hook executes at the start of every request.
Definition
function after_entry_point($event, $arguments){}
Arguments
Name
Type
Description
event
String
The current event
arguments
Array
Additional information related to the eventÂ (typicallyÂ empty)
Considerations
The after_entry_pointÂ hook is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
This hook is executed at the start of every request at the end of ./include/entryPoint.php.
This hook should not be used for any type of display output.
The after_entry_pointÂ hook is ideally used for logging or loading libraries.
Application hooks do not make use of the $bean argument.
Change Log
Version
Note


Application hooks do not make use of the $bean argument.
Change Log
Version
Note
6.4.3
Added after_entry_point hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_entry_point'] = Array();
    $hook_array['after_entry_point'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_entry_point example',
        //The PHP file where your class is located.
        'custom/modules/application_hooks_class.php',
        //The class the method is in.
        'application_hooks_class',


'application_hooks_class',
        //The method to call.
        'after_entry_point_method'
    );
?>
./custom/modules/application_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class application_hooks_class
    {
        function after_entry_point_method($event, $arguments)
        {
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


handle_exception
Overview
The handle_exception logic hook executes when an exception is thrown.
Definition
function handle_exception($event, $exception){}
Arguments
Name
Type
Description
event
String
The current event
exception
Object
The exception object
Considerations
This hook should not be used for any type of display output.
You can retrieve the exception message by using $exception->getMessage(). All exception classes extend the PHP Exceptions class.
Change Log
Version
Note
6.4.4
Added handle_exception hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['handle_exception'] = Array();
    $hook_array['handle_exception'][] = Array(


$hook_array['handle_exception'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'handle_exception example',
        //The PHP file where your class is located.
        'custom/modules/handle_exception_class.php',
        //The class the method is in.
        'handle_exception_class',
        //The method to call.
        'handle_exception_method'
    );
?>
./custom/modules/handle_exception_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class handle_exception_class
    {


class handle_exception_class
    {
        function handle_exception_method($event, $exception)
        {
            //logic with $exception->getMessage()
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


after_ui_frame
Overview
The after_ui_frame hook executes after the frame has been invoked and before the footer has been invoked for modules in backward compatibility mode.Â This logic hook has been deprecated and will be removed in a futureÂ release.Â
Definition
function after_ui_frame($event, $arguments){}
Arguments
Name
Type
Description
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Considerations
This hook is only applicable for modules in backward compatibility mode.
This hook is executed on most views such as the DetailView, EditView, and Listview.
Application hooks do not make use of the $bean argument.


Application hooks do not make use of the $bean argument.
This is logic hook can be used as a global reference (./custom/modules/logic_hooks.php) or as a module reference (./custom/modules/<module>/logic_hooks.php).
Change Log
Version
Note
7.10.0.0
Deprecated after_ui_frame hook
5.0.0a
Added after_ui_frame hook
Example
Module-Specific Hook
This hook can be used at the application level for all modules or limited to specific modules. An example limiting the hook for specific modules is shown below:
./custom/modules/<module>/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_ui_frame'] = Array();


$hook_array['after_ui_frame'] = Array();
    $hook_array['after_ui_frame'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_ui_frame example',
        //The PHP file where your class is located.
        'custom/modules/{module}/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'after_ui_frame_method'
    );
?>
./custom/modules/<module>/logic_hooks_class.php
<?php


<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function after_ui_frame_method($event, $arguments)
        {
            //display logic
        }
    }
?>
Application Hook
This hook can be used at the application level for all modules or limited to specific modules. An example of executing the hook for all modules is shown below:
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_ui_frame'] = Array();
    $hook_array['after_ui_frame'][] = Array(
        //Processing index. For sorting the array.
        1,


//Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_ui_frame example',
        //The PHP file where your class is located.
        'custom/modules/application_hooks_class.php',
        //The class the method is in.
        'application_hooks_class',
        //The method to call.
        'after_ui_frame_method'
    );
?>
./custom/modules/application_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class application_hooks_class
    {
        function after_ui_frame_method($event, $arguments)
        {
            //display logic
        }


{
            //display logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


after_session_start
Overview
The after_session_startÂ hook executes before the user's session starts, but after the user's visibility rules have been set up and the after_load_user logic hook has executed.
Definition
function after_session_start($event, $arguments){}
Arguments
Name
Type
Description
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
6.4.3
Added after_session_start hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_session_start'] = Array();
    $hook_array['after_session_start'][] = Array(


$hook_array['after_session_start'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_session_start example',
        //The PHP file where your class is located.
        'custom/modules/application_hooks_class.php',
        //The class the method is in.
        'application_hooks_class',
        //The method to call.
        'after_session_start_method'
    );
?>
./custom/modules/application_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class application_hooks_class
    {


class application_hooks_class
    {
        function after_session_start_method($event, $arguments)
        {
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


entry_point_variables_setting
Overview
The entry_point_variables_settingÂ application hook executes at the start of every entryÂ point.
Definition
function entry_point_variables_setting($event, $arguments){}
Arguments
Name
Type
Description
event
String
The current event
arguments
Array
Additional information related to the eventÂ (typicallyÂ empty)
Considerations
The entry_point_variables_settingÂ hook is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
This hook is executed at the start of every request at the end of ./include/entryPoint.php.
This hookÂ doesÂ not make use of the $bean argument.
Change Log
Version
Note
6.4.3
Added entry_point_variables_setting hook


Note
6.4.3
Added entry_point_variables_setting hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['entry_point_variables_setting'] = Array();
    $hook_array['entry_point_variables_setting'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'entry_point_variables_setting example',
        //The PHP file where your class is located.
        'custom/modules/application_hooks_class.php',
        //The class the method is in.
        'application_hooks_class',
        //The method to call.


'application_hooks_class',
        //The method to call.
        'entry_point_variables_setting_method'
    );
?>
./custom/modules/application_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class application_hooks_class
    {
        function entry_point_variables_setting_method($event, $arguments)
        {
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


after_load_user
Overview
The after_load_userÂ hook executes after the current user is set for the current request. It handles actions that are dependent on the current user, such as setting ACLs or configuring user-dependent parameters.
Definition
function after_load_user($event, $arguments){}
Arguments
Name
Type
Description
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Change Log
Version
Note
6.6.0
Added after_load_user hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_load_user'] = Array();
    $hook_array['after_load_user'][] = Array(


$hook_array['after_load_user'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_load_user example',
        //tde PHP file where your class is located.
        'custom/modules/application_hooks_class.php',
        //tde class the method is in.
        'application_hooks_class',
        //tde method to call.
        'after_load_user_method'
    );
?>
./custom/modules/application_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class application_hooks_class
    {


class application_hooks_class
    {
        function after_load_user_method($event, $arguments)
        {
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


Web Logic Hooks
Overview
Web logic hooks let administrators post record and event information to a specified URL when certain sugar events take place.
The administration panel for web logic hooks can be found by navigating to Admin > Web Logic Hooks in the Sugar application. When a web logic hook is triggered, Sugar creates a record in the job queue.
Note: You must have the cron set up and running in order to process the job queue for web logic hooks. The POST of the information to the external URL will happen when the cron runs and not when the actual event occurs.
Arguments
Name
Description
URL
The URL to post JSON-encoded information
Module Name
The name of the module to which the web logic hook will apply
Trigger Event
The event that will trigger the web logic hookThe following events are applicable to a web logic hook:
after_save
after_delete
after_relationship_add


after_save
after_delete
after_relationship_add
after_relationship_delete
after_login
after_logout
after_login_failed
Request Method
The request method to use when sending the informationThe following methods mayÂ be used:
POST
GET
PUT
DELETE
Example
The followingÂ example shows how to receive the information posted to the web logic hook URL parameter.
http://{url}/receive.php
<?php
//get the posted JSON data
$data = file_get_contents('php://input');
//decode the data
$decoded_data = json_decode(trim($data));
//use the data
$file = 'receivedData-'.time().'.txt';
file_put_contents($file, print_r($decoded_data, true));
?>
Result


?>
Result
receivedData-1380158171.txt
stdClass Object
(
    [isUpdate] => 1
    [dataChanges] => Array
    (
    )
    [bean] => Account
    [data] => stdClass Object
    (
        [id] => e0623cdb-ac4b-e7ff-f681-5242e9116892
        [name] => Super Star Holdings Inc
        [date_modified] => 2013-09-25T21:16:06-04:00
        [modified_user_id] => 1
        [modified_by_name] => admin
        [created_by] => 1
        [created_by_name] => Administrator
        [description] =>
        [deleted] =>
        [assigned_user_id] => seed_will_id


[assigned_user_id] => seed_will_id
        [assigned_user_name] => Will Westin
        [team_count] =>
        [team_name] => Array
        (
            [0] => stdClass Object
                (
                    [id] => East
                    [name] => East
                    [name_2] =>
                    [primary] => 1
                )
            [1] => stdClass Object
                (
                    [id] => West
                    [name] => West
                    [name_2] =>
                    [primary] =>
                )
        )
        [linkedin] =>
        [facebook] =>
        [twitter] =>
        [googleplus] =>
        [account_type] => Customer
        [industry] => Energy
        [annual_revenue] =>


[industry] => Energy
        [annual_revenue] =>
        [phone_fax] =>
        [billing_address_street] => 111 Silicon Valley Road
        [billing_address_city] => Los Angeles
        [billing_address_state] => NY
        [billing_address_postalcode] => 84028
        [billing_address_country] => USA
        [rating] =>
        [phone_office] => (374) 791-2199
        [phone_alternate] =>
        [website] =>
        [ownership] =>
        [employees] =>
        [ticker_symbol] =>
        [shipping_address_street] => 111 Silicon Valley Road
        [shipping_address_city] => Los Angeles
        [shipping_address_state] => NY


[shipping_address_state] => NY
        [shipping_address_postalcode] => 84028
        [shipping_address_country] => USA
        [email] => Array
        (
            [0] => stdClass Object
                (
                    [email_address] => example@example.tw
                    [invalid_email] =>
                    [opt_out] =>
                    [primary_address] => 1
                    [reply_to_address] =>
                )
            [1] => stdClass Object
                (
                    [email_address] => the.example@example.name
                    [invalid_email] =>
                    [opt_out] =>
                    [primary_address] =>
                    [reply_to_address] =>
                )
        )
        [email1] => example@example.tw


)
        )
        [email1] => example@example.tw
        [parent_id] =>
        [sic_code] =>
        [parent_name] =>
        [email_opt_out] =>
        [invalid_email] =>
        [campaign_id] =>
        [campaign_name] =>
    )
    [event] => after_save
)
  	Last modified: 2023-02-03 21:04:03


API Hooks
APIÂ hooks execute logic when working with the REST API and routing.
Topicsafter_routingThe after_routing hook executes when the v10+ REST Service has found the route for the request.before_api_callThe before_api_call hook executes when the v10+ REST Service is about to call the API implementation.before_filterThe before_filter hook executes when the v10+ REST Service is about to route the request.before_respondThe before_respond hook executes before the v10+ REST Service call returns data to the user.before_routingThe before_routing hook executes when the v10+ REST Service is about to route the request.
  	Last modified: 2023-02-03 21:04:03


before_filter
Overview
The before_filter hook executes when the v10+ REST Service is about to route the request.
Definition
function before_filter($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
An empty bean object of the module being queried.
event
String
The name of the logic hook event.
arguments
Array
Additional information related to the event.
arguments[0]
Object
The SugarQuery Object
arguments[1]
Array
The query options
Considerations
This hook can be executed for a specific module in ./custom/modules/<module>/logic_hooks.php or globally in ./custom/modules/logic_hooks.php.
This hook can change request object parameters that influence routing.
This hook should not be used for any type of display output.
Change Log
Version
Note


Change Log
Version
Note
7.0.0RC1
Added before_filter hook
Example
./custom/modules/{module}/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['before_filter'] = Array();
    $hook_array['before_filter'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_filter example',
        //The PHP file where your class is located.
        'custom/modules/{module}/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.


'logic_hooks_class',
        //The method to call.
        'before_filter_method'
    );
?>
./custom/modules/{module}/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function before_filter_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Â
  	Last modified: 2023-02-03 21:04:03


before_respond
Overview
The before_respond hook executes before the v10+ REST Service call returns data to the user.
Definition
function before_respond($event, $response){}
Arguments
Name
Type
Description
event
String
The name of the logic hook event
response
Object
The RestResponse Object
Considerations
This is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
It is not advised to remove or unset any data. Sugar may be using this data and it can adversely affect your instance.
This hook should not be used for any type of display output.
This hook should be used when you want to add data to all API responses. If you are looking to modify data received from one specific endpoint, It is a much better approach to override that specific endpoint rather than to use this logic hook.
Change Log
Version
Note


Change Log
Version
Note
7.0.0RC1
Added before_respond hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['before_respond'] = Array();
    $hook_array['before_respond'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_routing example',
        //The PHP file where your class is located.
        'custom/modules/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'before_respond_method'
    );


'before_respond_method'
    );
?>
./custom/modules/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function before_respond_method($event, $response)
        {
            //logic
        }
    }
?>
Â
  	Last modified: 2023-02-03 21:04:03


before_routing
Overview
The before_routing hook executes when the v10+ REST Service is about to route the request.
Definition
function before_routing($event, $arguments){}
Arguments
Name
Type
Description
event
String
The name of the logic hook event
arguments
Array
Additional information related to the event
arguments.api
Object
The RestService Object
arguments.request
Object
The RestResponse Object
Considerations
This is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
This hook can change request object parameters that influence routing.
This hook should not be used for any type of display output.
Change Log
Version
Note
7.0.0RC1
Added before_routing hook
Example
./custom/modules/logic_hooks.php
<?php


Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['before_routing'] = Array();
    $hook_array['before_routing'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_routing example',
        //The PHP file where your class is located.
        'custom/modules/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'before_routing_method'
    );
?>
./custom/modules/logic_hooks_class.php


?>
./custom/modules/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function before_routing_method($event, $arguments)
        {
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


after_routing
Overview
The after_routing hook executes when the v10+ REST Service has found the route for the request.
Definition
function after_routing($event, $arguments){}
Arguments
Name
Type
Description
event
String
The name of the logic hook event
arguments
Array
Additional information related to the event
arguments.api
Object
The RestService Object
arguments.request
Object
The RestResponse Object
Considerations
This is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
This hook can change request object parameters that influence routing.
This hook should not be used for any type of display output.
Change Log
Version
Note
7.0.0RC1
Added after_routing hook
Example
./custom/modules/logic_hooks.php
<?php


Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_routing'] = Array();
    $hook_array['after_routing'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_routing example',
        //The PHP file where your class is located.
        'custom/modules/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'after_routing_method'
    );
?>
./custom/modules/logic_hooks_class.php


?>
./custom/modules/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function after_routing_method($event, $arguments)
        {
            //logic
        }
    }
?>Â
  	Last modified: 2023-02-03 21:04:03


before_api_call
Overview
The before_api_call hook executes when the v10+ REST Service is about to call the API implementation.
Definition
function before_api_call($event, $arguments){}
Arguments
Name
Type
Description
event
String
The name of the logic hook event
arguments
Array
Additional information related to the event
arguments.api
Object
The RestService Object
arguments.request
Object
The RestResponse Object
Considerations
This is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
This hook can change the method being called and the parameters.
This hook should not be used for any type of display output.
Change Log
Version
Note
7.0.0RC1
Added before_api_call hook
Example


Note
7.0.0RC1
Added before_api_call hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['before_api_call'] = Array();
    $hook_array['before_api_call'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_api_call example',
        //The PHP file where your class is located.
        'custom/modules/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.


'logic_hooks_class',
        //The method to call.
        'before_api_call_method'
    );
?>
./custom/modules/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function before_api_call_method($event, $arguments)
        {
            //logic
        }
    }
?>
Â
  	Last modified: 2023-02-03 21:04:03


Logic Hook Release Notes
This page documentsÂ historical changes to Sugar's logic hook libraries.
10.2.0
The following parameter was added in the 10.2.0 release:
after_save arguments.stateChanges
7.0.0RC1
Web Logic Hooks were introduced in this release.
The following hooks were also added in the 7.0.0RC1 release:
after_routing
before_api_call
before_filter
before_respond
before_routing
The following parameters were added in the 7.0.0RC1 release:
after_save arguments.isUpdate
after_save arguments.dataChanges
before_save arguments.isUpdate
6.6.0
The after_load_user hook was added in the 6.6.0 release.
6.5.0RC1


6.5.0RC1
The following hooks were added in the 6.5.0RC1 release:
after_email_import
before_email_import
job_failure
job_failure_retry
6.4.5
The following hooks were added in the 6.4.5 release:
before_relationship_add
before_relationship_delete
6.4.4
The handle_exception hook was added in the 6.4.4 release.
6.4.3
The after_entry_point hook was added in the 6.4.3 release.
6.0.0RC1
The following hooks were added in the 6.0.0RC1 release:
after_relationship_add
after_relationship_delete
5.0.0a
The following hooks were added in the 5.0.0a release:
after_login


The following hooks were added in the 5.0.0a release:
after_login
after_logout
after_ui_footer
after_ui_frame
before_logout
login_failed
process_record
server_round_trip
4.5.0c
The after_save hook was added in the 4.5.0c release.
  	Last modified: 2023-02-03 21:04:03


SNIP Hooks
SNIP hooks execute logic when working withÂ the SNIP email-archiving service.
Topicsafter_email_importThe after_email_import hook executes after a SNIP email has been imported.before_email_importThe before_email_import hook executes before a SNIP email has been imported.
  	Last modified: 2023-02-03 21:04:03


after_email_import
Overview
The after_email_import hook executes after a SNIP email has been imported.
Definition
function after_email_import($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The Email object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Considerations
This is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
Change Log
Version
Note
6.5.0RC1
Added after_email_import hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['after_email_import'] = Array();


$hook_array['after_email_import'] = Array();
    $hook_array['after_email_import'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_email_import example',
        //The PHP file where your class is located.
        'custom/modules/SNIP/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'after_email_import_method'
    );
?>
./custom/modules/SNIP/logic_hooks_class.php
<?php


<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function after_email_import_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Â
  	Last modified: 2023-02-03 21:04:03


before_email_import
Overview
The before_email_import hook executes before a SNIP email has been imported.
Definition
function before_email_import($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The Email object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Considerations
This is a global logic hook where the logic hook reference must be placed in ./custom/modules/logic_hooks.php.
Change Log
Version
Note
6.5.0RC1
Added before_email_import hook
Example
./custom/modules/logic_hooks.php
<?php
    $hook_version = 1;
    $hook_array = Array();
    $hook_array['before_email_import'] = Array();


$hook_array['before_email_import'] = Array();
    $hook_array['before_email_import'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_email_import example',
        //The PHP file where your class is located.
        'custom/modules/SNIP/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'before_email_import_method'
    );
?>
./custom/modules/SNIP/logic_hooks_class.php
<?php


<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function before_email_import_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Â
  	Last modified: 2023-02-03 21:04:03


Module Hooks
Module hooks execute logic when working with Sugar modules (e.g. Accounts, Cases, etc.).


Topicsafter_deleteThe after_delete hook executes after a record is deleted.after_fetch_queryThe after_fetch_query logic hook executes after a sugar query has been executed.after_relationship_addThe after_relationship_add hook executes after a relationship has been added between two records.after_relationship_deleteThe after_relationship_delete hook executes after a relationship between two records has been deleted.after_restoreThe after_restore hook executes after a record gets undeleted (i.e. the deleted field's value changes from 1 to 0).after_retrieveThe after_retrieve hook executes after a record has been retrieved from the database.after_saveThe after_save hook executes after a record is saved.before_deleteThe before_delete logic hook executes before a record is deleted.before_fetch_queryThe before_fetch_query logic hook executes before a sugar query has been


before_fetch_query logic hook executes before a sugar query has been executed.before_relationship_addThe before_relationship_add logic hook executes before a relationship has been added between two records.before_relationship_deleteThe before_relationship_delete logic hook executes before a relationship between two records is deleted.before_restoreThe before_restore logic hook executes before a record gets undeleted (i.e. the deleted field's value changes from 1 to 0).before_saveThe before_save logic hook executes before a record is saved.process_recordThe process_record logic hook executes when the record is being processed as a part of the ListView or subpanel list.


Last modified: 2023-02-03 21:04:03


after_save
Overview
The after_save hook executes after a record is saved.
Definition
function after_save($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
arguments.isUpdate
Boolean
Whether or not the record is newly created or not. True is an existing record being saved. False is a new record being created
arguments.dataChanges
Array
A list of the fields in the auditable fields on the bean, including the ones that changed and the ones that did not.Note: This argument is deprecated and it is recommended to use arguments.stateChanges instead.
arguments.stateChanges
Array
AÂ list of only the fields in the auditable fields on the bean that changed
Considerations


Considerations
Calling save on the bean in this hook will cause an infinite loop if not handled correctly. (i.e: $bean->save())
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
    $hook_array['after_save'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_save example',
        //The PHP file where your class is located.
        'custom/modules/<module>/after_save_class.php',
        //The class the method is in.
        'after_save_class',
        //The method to call.
        'after_save_method'
    );
?>


'after_save_method'
    );
?>
./custom/modules/<module>/after_save_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class after_save_class
    {
        function after_save_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Creating a Core Logic Hook
Prior to Sugar 6.3.x, logic hooks could only be created using the following method. Please note that this approach is still valid but is not recommended when building plugins as it may conflict with existing customizations.
./custom/modules/<module>/logic_hooks.php
<?php
   $hook_version = 1;
   $hook_array = Array();


$hook_version = 1;
   $hook_array = Array();
   $hook_array['after_save'] = Array();
   $hook_array['after_save'][] = Array(
      //Processing index. For sorting the array.
      1,
      //Label. A string value to identify the hook.
      'after_save example',
      //The PHP file where your class is located.
      'custom/modules/<module>/after_save_class.php',
      //The class the method is in.
      'after_save_class',
      //The method to call.
      'after_save_method'
   );
?>
./custom/modules/<module>/after_save_class.php
<?php


./custom/modules/<module>/after_save_class.php
<?php
   if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
   class after_save_class
   {
      function after_save_method($bean, $event, $arguments)
      {
         //logic
      }
   }
?>
  	Last modified: 2023-02-03 21:04:03


before_relationship_add
Overview
The before_relationship_add logic hook executes before a relationship has been added between two records.
Definition
function before_relationship_add($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event
arguments.id
String
Module ID
arguments.module
String
Module name
arguments.related_id
String
Related module ID
arguments.related_module
String
Related module name
arguments.link
String
Link field name
arguments.relationship
String
Relationship name
Considerations
This hook will be executed for each side of the relationship. For example, if you add an association between an account and a contact, the hook will run for both records.


The arguments parameter will have additional information regarding the records being modified. The $bean variable will not contain this information.
Change Log
Version
Note
6.4.5
Added before_relationship_add hook
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
    $hook_array['before_relationship_add'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_relationship_add example',
        //The PHP file where your class is located.
        'custom/modules/<module>/before_relationship_add_class.php',
        //The class the method is in.
        'before_relationship_add_class',


'before_relationship_add_class',
        //The method to call.
        'before_relationship_add_method'
    );
?>
./custom/modules/<module>/before_relationship_add_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class before_relationship_add_class
    {
        function before_relationship_add($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
  	Last modified: 2023-02-03 21:04:03


after_relationship_delete
Overview
The after_relationship_delete hook executes after a relationship between two records has been deleted.
Definition
function after_relationship_delete($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event
arguments.id
String
Module ID
arguments.module
String
Module name
arguments.related_id
String
Related module ID
arguments.related_module
String
Related module name
arguments.link
String
Link field name
arguments.relationship
String
Relationship name
Considerations
This hook will be executed for each side of the relationship. For example, if you delete an association between an account and contact, the hook will run for both.


The 'arguments' parameter will have additional information regarding the records being modified. The $bean variable will not contain this information.
Change Log
Version
Note
6.0.0
Added after_relationship_delete hook
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
    $hook_array['after_relationship_delete'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_relationship_delete example',
        //The PHP file where your class is located.
        'custom/modules/<module>/after_relationship_delete_class.php',
        //The class the method is in.


//The class the method is in.
        'after_relationship_delete_class',
        //The method to call.
        'after_relationship_delete_method'
    );
?>
./custom/modules/<module>/after_relationship_delete_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class after_relationship_delete_class
    {
        function after_relationship_delete_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Creating a Core Logic Hook
Prior to Sugar 6.3.x, logic hooks could only be created using the following method. Please note that this approach is still valid but is not recommended when building plugins as it may conflict with existing customizations.


./custom/modules/<module>/logic_hooks.php
<?php
   $hook_version = 1;
   $hook_array = Array();
   $hook_array['after_relationship_delete'] = Array();
   $hook_array['after_relationship_delete'][] = Array(
      //Processing index. For sorting the array.
      1,
      //Label. A string value to identify the hook.
      'after_relationship_delete example',
      //The PHP file where your class is located.
      'custom/modules/<module>/after_relationship_delete_class.php',
      //The class the method is in.
      'after_relationship_delete_class',
      //The method to call.
      'after_relationship_delete_method'
   );


'after_relationship_delete_method'
   );
?>
./custom/modules/<module>/after_relationship_delete_class.php
<?php
   if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
   class after_relationship_delete_class
   {
      function after_relationship_delete_method($bean, $event, $arguments)
      {
         //logic
      }
   }
?>
  	Last modified: 2023-02-03 21:04:03


process_record
Overview
The process_record logic hook executes when the record is being processed as a part of the ListView or subpanel list.
Definition
function process_record($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Considerations
This can be used to set values in a record's fields prior to display in the ListView or in the subpanel of a DetailView.
This event is not fired in the EditView.
You should not call save on the referenced bean. The bean is only populated for list fields and will result in a loss of information.
Change Log
Version
Note
5.0.0a
Added process_record hook
Examples
Creating a Logic Hook using the Extension Framework


Added process_record hook
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
    $hook_array['process_record'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'process_record example',
        //The PHP file where your class is located.
        'custom/modules/<module>/process_record_class.php',
        //The class the method is in.
        'process_record_class',
        //The method to call.
        'process_record_method'
    );
?>
./custom/modules/<module>/process_record_class.php
<?php


./custom/modules/<module>/process_record_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class process_record_class
    {
        function process_record_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Creating a Core Logic Hook
Prior to Sugar 6.3.x, logic hooks could only be created using the following method. Please note that this approach is still valid but is not recommended when building plugins as it may conflict with existing customizations.
./custom/modules/<module>/logic_hooks.php
<?php
   $hook_version = 1;
   $hook_array = Array();
   $hook_array['process_record'] = Array();


$hook_array['process_record'] = Array();
   $hook_array['process_record'][] = Array(
      //Processing index. For sorting the array.
      1,
      //Label. A string value to identify the hook.
      'process_record example',
      //The PHP file where your class is located.
      'custom/modules/<module>/process_record_class.php',
      //The class the method is in.
      'process_record_class',
      //The method to call.
      'process_record_method'
   );
?>
./custom/modules/<module>/process_record_class.php
<?php
   if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
   class process_record_class
   {


class process_record_class
   {
      function process_record_method($bean, $event, $arguments)
      {
         //logic
      }
   }
?>
  	Last modified: 2023-02-03 21:04:03


after_relationship_add
Overview
The after_relationship_add hook executes after a relationship has been added between two records.
Definition
function after_relationship_add($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event
arguments.id
String
Module ID
arguments.module
String
Module name
arguments.related_id
String
Related module ID
arguments.related_module
String
Related module name
arguments.link
String
Link field name
arguments.relationship
String
Relationship name
Considerations
This hook will be executed for each side of the relationship. An example is that if you add an association between an Account and Contact, the hook will be run for both.


The arguments parameter will have additional information regarding the records being modified. The $bean variable will not contain this information.
Change Log
Version
Note
6.0.0
Added after_relationship_add hook.
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
    $hook_array['after_relationship_add'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_relationship_add example',
        //The PHP file where your class is located.
        'custom/modules/{module}/after_relationship_add_class.php',
        //The class the method is in.
        'after_relationship_add_class',


'after_relationship_add_class',
        //The method to call.
        'after_relationship_add_method'
    );
?>
./custom/modules/<module>/after_relationship_add_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class after_relationship_add_class
    {
        function after_relationship_add_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Creating a Core Logic Hook
Prior to Sugar 6.3.x, logic hooks could only be created using the following method. Please note that this approach is still valid but is not recommended when building plugins as it may conflict with existing customizations.


./custom/modules/<module>/logic_hooks.php
<?php
   $hook_version = 1;
   $hook_array = Array();
   $hook_array['after_relationship_add'] = Array();
   $hook_array['after_relationship_add'][] = Array(
      //Processing index. For sorting the array.
      1,
      //Label. A string value to identify the hook.
      'after_relationship_add example',
      //The PHP file where your class is located.
      'custom/modules/<module>/after_relationship_add_class.php',
      //The class the method is in.
      'after_relationship_add_class',
      //The method to call.
      'after_relationship_add_method'
   );


'after_relationship_add_method'
   );
?>
./custom/modules/<module>/after_relationship_add_class.php
<?php
   if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
   class after_relationship_add_class
   {
      function after_relationship_add_method($bean, $event, $arguments)
      {
         //logic
      }
   }
?>
  	Last modified: 2023-02-03 21:04:03


before_delete
Overview
The before_delete logic hook executes before a record is deleted.
Definition
function before_delete($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event
arguments.id
String
ID of the record to delete
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
    $hook_array['before_delete'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_delete example',
        //The PHP file where your class is located.


'before_delete example',
        //The PHP file where your class is located.
        'custom/modules/<module>/before_delete_class.php',
        //The class the method is in.
        'before_delete_class',
        //The method to call.
        'before_delete_method'
    );
?>
./custom/modules/<module>/before_delete_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class before_delete_class
    {
        function before_delete_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Creating a Core Logic Hook


//logic
        }
    }
?>
Creating a Core Logic Hook
Prior to Sugar 6.3.x, logic hooks could only be created using the following method. Please note that this approach is still valid but is not recommended when building plugins as it may conflict with existing customizations.
./custom/modules/<module>/logic_hooks.php
<?php
   $hook_version = 1;
   $hook_array = Array();
   $hook_array['before_delete'] = Array();
   $hook_array['before_delete'][] = Array(
      //Processing index. For sorting the array.
      1,
      //Label. A string value to identify the hook.
      'before_delete example',
      //The PHP file where your class is located.


//The PHP file where your class is located.
      'custom/modules/<module>/before_delete_class.php',
      //The class the method is in.
      'before_delete_class',
      //The method to call.
      'before_delete_method'
   );
?>
./custom/modules/<module>/before_delete_class.php
<?php
   if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
   class before_delete_class
   {
      function before_delete_method($bean, $event, $arguments)
      {
         //logic
      }
   }
?>
  	Last modified: 2023-02-03 21:04:03


before_restore
Overview
The before_restore logic hook executes before a record gets undeleted (i.e. the deleted field's value changes from 1 to 0).
Definition
function before_restore($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event (typically empty)
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'before_restore example',
        //The PHP file where your class is located.


//The PHP file where your class is located.
        'custom/modules/<module>/before_restore_class.php',
        //The class the method is in.
        'before_restore_class',
        //The method to call.
        'before_restore_method'
    );
?>
./custom/modules/<module>/before_restore_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class before_restore_class
    {
        function before_restore_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Creating a Core Logic Hook


//logic
        }
    }
?>
Creating a Core Logic Hook
Prior to Sugar 6.3.x, logic hooks could only be created using the following method. Please note that this approach is still valid but is not recommended when building plugins as it may conflict with existing customizations.
./custom/modules/<module>/logic_hooks.php
<?php
$hook_version = 1;
$hook_array = Array();
$hook_array['before_restore'] = Array();
$hook_array['before_restore'][] = Array(
//Processing index. For sorting the array.
1,
//Label. A string value to identify the hook.
'before_restore example',
//The PHP file where your class is located.
'custom/modules/<module>/before_restore_class.php',


'custom/modules/<module>/before_restore_class.php',
//The class the method is in.
'before_restore_class',
//The method to call.
'before_restore_method'
);
?>
./custom/modules/<module>/before_restore_class.php
<?php
if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
class before_restore_class
{
function before_restore_method($bean, $event, $arguments)
{
//logic
}
}
?>
  	Last modified: 2023-02-03 21:04:03


after_delete
Overview
The after_delete hook executes after a record is deleted.
Definition
function after_delete($bean, $event, $arguments){}
Arguments
Name
Type
Description
bean
Object
The bean object
event
String
The current event
arguments
Array
Additional information related to the event
arguments.id
String
ID of the deleted record
Examples
Creating a Logic Hook using the Extension Framework
./custom/Extension/modules/<module>/Ext/LogicHooks/<file>.php
<?php
    $hook_array['after_delete'][] = Array(
        //Processing index. For sorting the array.
        1,
        //Label. A string value to identify the hook.
        'after_delete example',
        //The PHP file where your class is located.


//The PHP file where your class is located.
        'custom/modules/<module>/logic_hooks_class.php',
        //The class the method is in.
        'logic_hooks_class',
        //The method to call.
        'after_delete_method'
    );
?>
./custom/modules/<module>/logic_hooks_class.php
<?php
    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
    class logic_hooks_class
    {
        function after_delete_method($bean, $event, $arguments)
        {
            //logic
        }
    }
?>
Creating a Core Logic Hook