sugarcon 2010 - best practices for creating custom apps in sugar

40
05/25/2022 ©2010 SugarCRM Inc. All rights reserved. 1

Upload: john-mertic

Post on 17-Jun-2015

5.785 views

Category:

Technology


2 download

DESCRIPTION

One of the most important features of SugarCRM for developers is the ability to build customizations, even custom apps, to suit your needs. In this talk, John Mertic will detail some of the most common customization use cases from the field and provide guidelines on how to build upgrade-safe customizations and custom apps that will help meet the needs of your given company.

TRANSCRIPT

Page 1: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

04/13/2023 ©2010 SugarCRM Inc. All rights reserved. 1

Page 2: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Best Practices for Creating Custom Apps in Sugar

John Mertic

SugarCRM

04/13/2023 ©2010 SugarCRM Inc. All rights reserved. 2

Page 3: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

The golden rules of customizations

Use Module Builder/Studio for customizations if possible

Otherwise, put your code inside the custom directory

04/13/2023©2010 SugarCRM Inc. All rights reserved. 3

Page 4: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Why do this?

Module Builder/Studio changes are well supported and easier to manage

Customizations are separated from the shipped code

Allows you to manage your customizations via version control ( SVN, Git, etc )

Files in here aren’t disturbed by any Sugar upgrades

Exception – sometimes we will try to fix metadata templates on upgrades for new/removed fields.

Makes your app “Upgrade Safe”

04/13/2023©2010 SugarCRM Inc. All rights reserved. 4

Page 5: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Exceptions to this…

New modules need to be under modules/ directory.

Bean class customizations to OOTB modules need to be on the original bean file.

We’ll look at using logic hooks and other techniques to avoid this for many use cases.

Will need to manually manage this during upgrades, so best to avoid.

04/13/2023©2010 SugarCRM Inc. All rights reserved. 5

Page 6: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Let’s see what we can do

04/13/2023©2010 SugarCRM Inc. All rights reserved. 6

Page 7: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework

MVC stands for Model View Controller

04/13/2023©2010 SugarCRM Inc. All rights reserved. 7

Page 8: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – The anatomy of a request

04/13/2023©2010 SugarCRM Inc. All rights reserved. 8

Page 9: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – SugarApplication

Bootstraps the application

Loads many of the default application settingsLanguage

Theme

Session

Handles User Authentication

Loads the controller

04/13/2023©2010 SugarCRM Inc. All rights reserved. 9

Page 10: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework - SugarController

Manages all the actions of a module

Contains logic for handling requests that don’t require a view

Example: Record saving

Maps all other requests to the correct viewLogic for mapping an action of one name to a view of another

Can detect if we should be using MVC or classic views

04/13/2023©2010 SugarCRM Inc. All rights reserved. 10

Page 11: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – SugarController API

04/13/2023©2010 SugarCRM Inc. All rights reserved. 11

Method Description

public function pre_action() Called before the named action

public function action_action() Called for the named action

public function post_action() Called after the named action

public function loadBean() Loads the bean and the record for the module

public function preProcess() Used to interject logic into the controller before processing the controller.

Page 12: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – Controller Example

04/13/2023©2010 SugarCRM Inc. All rights reserved. 12

<?php

class ExampleController extends SugarController{ public function action_hello() { echo "Hello World!"; } public function action_goodbye() { $this->view = 'goodbye'; }}

Page 13: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – Controller-less mapping

If your module doesn’t need to have any controller logic, use action mapping insteads.

Create file named action_view_map.php with the following contents:

04/13/2023©2010 SugarCRM Inc. All rights reserved. 13

<?php

$action_view_map['goodbye'] = 'goodbye';

Page 14: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework - SugarView

Contains the display logic for the actionUses a metadata backend for Edit, Detail, List, Popup views

And Convert Lead in Sugar 6.0

For other views, you write the code for the view and put it in modules/modulename/views/view.viewname.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 14

Page 15: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – SugarView API

04/13/2023©2010 SugarCRM Inc. All rights reserved. 15

Method Description

public function preDisplay() Called prior to outputing anything from the view

public function display() Called to display the view

protected function _getModuleTab() Returns the name of the module tab to be highlighted ( 6.0 only )

protected function _getModuleTitleParams() Returns the breadcrumbs to be displayed at the top of the view as an array ( 6.0 only )

Page 16: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – SugarView API

04/13/2023©2010 SugarCRM Inc. All rights reserved. 16

Property Description

public $ss Smarty object

public $module Name of module

public $action Name of action

public $errors Array of errors returned by the view or controller

public $options Options for the view, specified as an array:

Choices:show_headershow_titleshow_subpanelsshow_searchshow_footershow_javascriptview_print

Page 17: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – View Example

04/13/2023©2010 SugarCRM Inc. All rights reserved. 17

<?php

class ViewExample extends SugarView{ public function preDisplay() { if ( !is_admin($GLOBALS["current_user"]) )

sugar_die("Not an Admin"); } public function display() { echo "Hello Admin!"; }}

Page 18: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

MVC Framework – ViewDetail Example

04/13/2023©2010 SugarCRM Inc. All rights reserved. 18

<?php

require_once('include/MVC/View/views/view.detail.php');

class ContactsViewDetail extends ViewDetail { public function display() { $admin = new Administration(); $admin->retrieveSettings(); if(isset($admin->settings['portal_on']) && $admin->settings['portal_on']) { $this->ss->assign("PORTAL_ENABLED", true); } parent::display(); }}

Page 19: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

04/13/2023©2010 SugarCRM Inc. All rights reserved. 19

Where do I put my customizations?

Controllers/custom/modules/Modulename/controller.php

class CustomModulenameController extends SugarController

Views/custom/modules/Modulename/views/view.viewname.php

class CustomModulenameViewViewname extends ModulenameViewViewname

If that class doesn’t exist extend from ViewViewname or SugarView

Page 20: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Metadata Layer

04/13/2023©2010 SugarCRM Inc. All rights reserved. 20

Page 21: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Kinds of metadata

editviewdefs.php / detailviewdefs.php / quickcreatedefs.php

Wireless variants: wireless.editviewdefs.php, wireless.detailviewdefs.php

subpaneldefs.php

listviewdefs.phpwireless.listviewdefs.php

searchdefs.phpwireless.searchdefs.php

SearchFields.php

popupdefs.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 21

Page 22: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

editviewdefs.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 22

<?php$viewdefs[$module_name]['EditView'] = array( 'templateMeta' => array( 'maxColumns' => '2', 'widths' => array( array('label' => '10', 'field' => '30'), array('label' => '10', 'field' => '30'), ), ), 'panels' =>array ( 'default' => array ( array ( 'name', 'assigned_user_name', ), array(array ( 'name' => 'date_modified', 'customCode' => '{$fields.date_modified.value} {$APP.LBL_BY} {$fields.modified_by_name.value}', 'label' => 'LBL_DATE_MODIFIED', )), ), array( array ( 'description', ), ), ), );

Page 23: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

subpaneldefs.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 23

<?php$layout_defs[$module_name] = array( 'subpanel_setup' => array(

'contacts' => array('order' => 20,'module' => 'Contacts','sort_by' => 'last_name, first_name','sort_order' => 'asc','subpanel_name' => 'default','get_subpanel_data' => 'contacts','title_key' => 'LBL_CONTACTS_SUBPANEL_TITLE','top_buttons' => array(

array('widget_class' => 'SubPanelTopButtonQuickCreate'),array(

'widget_class'=>'SubPanelTopSelectButton','mode'=>'MultiSelect’

),),

), ),);

Page 24: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

searchdefs.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 24

<?php$searchdefs[$module_name] = array( 'templateMeta' => array( 'maxColumns' => '3', 'widths' => array('label' => '10', 'field' => '30'), ), 'layout' => array( 'basic_search' => array( 'name', array('name'=>'current_user_only', 'label'=>'LBL_CURRENT_USER_FILTER', 'type'=>'bool'), ), 'advanced_search' => array( 'name',

array('name' => 'phone', 'label' =>'LBL_ANY_PHONE', 'type' => 'name'), array('name' => 'address_city', 'label' =>'LBL_CITY', 'type' => 'name'), array('name' => 'email', 'label' =>'LBL_ANY_EMAIL', 'type' => 'name'), array('name' => 'assigned_user_id', 'type' => 'enum',

'label' => 'LBL_ASSIGNED_TO', 'function' => array('name' => 'get_user_array',

'params' => array(false))), ), ),);

Page 25: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

SearchFields.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 25

<?php$searchFields[$module_name] = array ( 'name' => array( 'query_type'=>'default'), 'current_user_only'=> array('query_type'=>'default',

'db_field'=>array('assigned_user_id'),'my_items'=>true, 'vname' => 'LBL_CURRENT_USER_FILTER', 'type' => 'bool'),

'assigned_user_id'=> array('query_type'=>'default'),);

Page 26: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

popupdefs.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 26

<?phpglobal $mod_strings;

$popupMeta = array( 'moduleMain' => 'Account', 'varName' => 'ACCOUNT', 'orderBy' => 'name', 'whereClauses' => array( 'name' => 'accounts.name', 'billing_address_city' => 'accounts.billing_address_city', 'phone_office' => 'accounts.phone_office'), 'searchInputs' => array('name', 'billing_address_city', 'phone_office'), 'create' => array( 'formBase' => 'AccountFormBase.php', 'formBaseClass' => 'AccountFormBase', 'getFormBodyParams' => array('','','AccountSave'), 'createButton' => $mod_strings['LNK_NEW_ACCOUNT’]), 'listviewdefs' => array( 'NAME' => array( 'width' => '40', 'label' => 'LBL_LIST_ACCOUNT_NAME', 'link' => true,'default' => true,), ), 'searchdefs' => array( 'name', array('name' => 'assigned_user_id', 'label'=>'LBL_ASSIGNED_TO', 'type' => 'enum', 'function' => array('name' => 'get_user_array', 'params' => array(false))), ),);

Page 27: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Where do I put my customizations?

Subpaneldefscustom/Extension/modules/Modulename/Ext/Layoutdefs/NameWhateverYouWant.php

Need to run ‘Quick Repair and Rebuild’ after changes are made

Everything else/custom/modules/Modulename/metadata

Watch for Studio blowing out your changes.

04/13/2023©2010 SugarCRM Inc. All rights reserved. 27

Page 28: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Logic Hooks

04/13/2023©2010 SugarCRM Inc. All rights reserved. 28

Page 29: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Logic Hook Types

04/13/2023©2010 SugarCRM Inc. All rights reserved. 29

Type Description

after_ui_frame Fired after the frame has been invoked and before the footer has been invoked. This hook does not have access to the current bean object ( meaning you can not view or change a record's values ).    

after_ui_footer Fired after the footer has been invoked. This hook does not have access to the current bean object. 

server_round_trip

Fired at the end of every SugarCRM page. It is called in the in the sugar_cleanup() method, which is called as the shutdown function for Sugar. This hook does not have access to the current bean object ( meaning you can not view or change a record's values ).     

before_delete Fired before a record is deleted using the SugarBean::mark_deleted()

after_delete Fired after a record is deleted using the SugarBean::mark_deleted() 

before_restore Fired before a record is undeleted using the SugarBean::mark_undeleted() method

after_restore Fired after a record is undeleted using the SugarBean::mark_undeleted() method

before_retrieve Fired before a record has been retrieved from the database using the SugarBean::retrieve() method. This hook does not fire when you create a new record.

after_retrieve Fired after a record has been retrieved from the database using the SugarBean::retrieve() method. This hook does not fire when you create a new record.

Page 30: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Logic Hook Types (cont)

04/13/2023©2010 SugarCRM Inc. All rights reserved. 30

Type Description

before_save

Fired before a record is saved using the SugarBean::save() method. One thing to note is that with certain modules, such as Cases and Bugs, the human-readable ID of the record (like the case_number field in the Case module), is not available within a before_save call since the business logic that calculates this value simply hasn't been executed yet. 

after_save

Fired after a record is saved using the SugarBean::save() method. One thing to note is that with certain modules, such as Cases and Bugs, the human-readable ID of the record (like the case_number field in the Case module), is not available within a after_save call since the business logic that calculates this value simply hasn't been executed yet.  

process_record

Fired immediately prior to the database query resulting in a record being made current.  This gives developers an opportunity to examine and tailor the underlying queries. This is also a perfect place to set values in a record’s fields prior to display in the DetailView or ListView. This event is not fired in the EditView.

before_logout Fired before a user logs out of the system

after_logout Fired after a user logs out of the system. This hook does not have access to the current bean object. ( meaning you can not view or change a record's values ).    

after_login Fired after a user successfully logs into the system.

before_login Fired before a user logs into the system. This hook does not have access to the current bean object. ( meaning you can not view or change a record's values ).     

login_failed Fired on a failed login attempt. This hook does not have access to the current bean object. ( meaning you can not view or change a record's values ).    

Page 31: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Logic Hook Types (new in 6.0)

04/13/2023©2010 SugarCRM Inc. All rights reserved. 31

Type Description

after_relationship_addFired after a relationship between two records is created. Called on both the records involved in the relationship. 

after_relationship_deleteFired after a relationship between two records is deleted. Called on both the records involved in the relationship. 

Page 32: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

logic_hooks.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 32

<?php

$hook_version = 1; $hook_array = Array(); $hook_array['before_save'] = Array(); $hook_array['before_save'][] = Array(1, 'AccountHooks', 'custom/Accounts/AccountHooks.php','AccountHooks', 'getParentAccountIndustry');

Parameters for Logic Hook Definition

Parameter 1 - Sorting index used to sort the arrays of logic hook definitions before they are processed.Parameter 2 - A string value to identify the hookParameter 3 - Path to the PHP file to include which contains your logic hook codeParameter 4 - Name of the PHP class the logic hook method is inParameter 5 - Name of the PHP method to call

Page 33: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

AccountHooks.php

04/13/2023©2010 SugarCRM Inc. All rights reserved. 33

<?php

class AccountHooks { public function getParentAccountIndustry( SugarBean $bean, $event, $arguments ) { if ( empty($bean->industry)

&& !empty($bean->parent_id) ) { $parentAccountFocus = new Account(); $parentAccountFocus->retrieve($bean->parent_id); if ( !empty($parentAccountFocus->id) ) $bean->industry = $parentAccountFocus->industry; } } }

Page 34: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Where do I put my customizations?

Application Level Logic Hooks/custom/modules/

Module Level Logic Hooks/custom/modules/Modulename/

04/13/2023©2010 SugarCRM Inc. All rights reserved. 34

Page 35: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Themes

04/13/2023©2010 SugarCRM Inc. All rights reserved. 35

Page 36: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Theme Directory Layout

12/30/08©2009 SugarCRM Inc. All rights reserved. 36

css/ - contains all css files

images/ - contains all images

js/ - contains any js files.

tpls/ - smarty templates

themedef.php definition file.

Page 37: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

12/30/08©2009 SugarCRM Inc. All rights reserved. 37

Themes can inherit from other themes

Theme Inheritance Model

Page 38: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

12/30/08©2009 SugarCRM Inc. All rights reserved. 38

Allow upgrade-safe modifications to themes

All themes can be modified by putting the replacement or overriding file in the custom/theme/<themename> directory

Image, HTML template file overrides are used as a replacement of the previous file

Example: an image custom/theme/<themename>/dog.gif would be used instead of theme/<themename>/dog.gif

CSS and Javascript files are combined in order of inheritance

Uses cssmin and jsmin to help reduce file size

No further code changes are required – changes are picked up automatically when themes cache is rebuilt.

Page 39: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Resources

04/13/2023©2010 SugarCRM Inc. All rights reserved. 39

http://developers.sugarcrm.com

Buy my book!

Page 40: SugarCon 2010 - Best Practices for Creating Custom Apps in Sugar

Thanks for coming!

04/13/2023 ©2010 SugarCRM Inc. All rights reserved. 40