Archive for August, 2008

Entry Points in Sugar 5.1

Friday, August 29th, 2008

One of the many code re-factoring changes we’ve made with Sugar 5.1 is to consolidate the number of entry points into the application as well as rerouting the current entry points through the MVC framework. An entry point is a PHP file that can be called either via URL or command line to actually invoke a Sugar process.  For instance when calling the home page of the application via URL or starting the scheduler via command line.  Consolidating the entry points has also helped us secure the application better and improve quality by making sure each request goes through the same initialization code.

Backwards compatibility with custom code
It does however present some backwards compatibility problems.  Most notably you will need to update your code if you have custom code that relies on a deprecated entry point such as a custom Quote template that may have called pdf.php which is no longer a stand-alone entry point. In these cases, you will need to change the URL reference as described below:

  1. Look for the entry point file name in the include/MVC/Controller/entry_point_registry.php. It will be the in the ‘file’ key in the sub-array.
  2. Make note of the key of that array. So for the pdf.php entry point, it appears in include/MVC/Controller/entry_point_registry.php as:
    'pdf' => array('file' => 'pdf.php', 'auth' => true),

    So we will want to use the ‘pdf’ part in the next step.

  3. Change the URL reference from the current reference to one in the form of:
    index.php?entryPoint=<<entrypoint>>

    So for the above pdf.php example, we would change our references from

    pdf.php

    to:

    index.php?entryPoint=pdf

The only remaining entry points in 5.1 that aren’t using this new index.php URL pattern (and therefore continue to be valid entry points) are:

  • campaign_tracker.php – used by the Campaign Management module for tracking campaign responses. Deprecated as of Sugar 5.1.0.
  • cron.php – used by the Windows Scheduler Service or the cron service on Linux and Unix for executing the Sugar Scheduler periodically.
  • index.php – default entry point into the Sugar application
  • install.php – used for initial install
  • maintenance.php – invoked when the application is down for maintenance.
  • metagen.php - Deprecated as of Sugar 5.1.0.
  • silentUpgrade.php – used for silent installer
  • soap.php – entry point for all SOAP calls
  • vcal_server.php – used for syncing information to Outlook

Module Builder - What’s new in 5.1

Thursday, August 28th, 2008

One of the best parts of using Sugar has to be customizing it. You don’t want to use a software package if it can’t meet your needs, and no two people or businesses have the same set of requirements. Sugar provides some really neat tools when it comes to customization, and in 5.1 they have been made even better.

There are a lot of really cool additions to the 5.1 developer tool set, and I’d thought I’d take a minute to quickly go over a couple of them.

Once you open up Module Builder in 5.1, you will notice the addition of two new templates, File and Sale. The File template is for document-based modules such as resumes, photos, or any other files you need to work with. Sale is based on the opportunities module and is designed to store information on sales and possible future sales.

After you have created a new module, you may also notice a few more new things. One that I would like to point out is under layouts, we have added Sugar Dashlet views. Starting in 5.1, your new custom modules will have Sugar Dashlets available straight out of Module Builder. You can edit the Sugar Dashlet layouts in the same manner as standard list and search views.

Finally, I’d like to touch on the area of integrations. In previous versions of Sugar, there wasn’t an easy way to integrate with existing web based systems from Studio or Module Builder. Certainly you can find many tutorials on how to add custom logic hooks to do this, but there hasn’t been a way to do integrations writing any code. In 5.1, this has changed with the addition of Link fields and iFrames with auto-generated URLs.
I’ll show how this is used with a fairly simple example, adding a Google map to the DetailView of a company. In this case my new “Partners” module which is based on the company template.

  1. Open up your custom module’s fields, and click “Add Field”.
  2. Select the IFrame field type.
  3. Fill in the following data:
    • FieldName: GoogleMap
    • Display Label: Google Map
    • Generate URL: check
    • Default Value (now this is where the magic happens):
      http://maps.google.com/maps?f=q&q={shipping_address_street}+
      {shipping_address_city}+
      {shipping_address_state}+
      {shipping_address_postalcode}+
      {shipping_address_country}
    • Max Size: 255
    • IFrame Height: 400
  4. Add the new field to your DetailView. Be sure to give the field a full row to itself for maximum readability. Note that adding an iFrame or a Link field that has a generated URL to an EditView will result in a read-only field that is un-editable.
  5. Deploy your package and create a new record in your new module, be sure to enter a real address into the shipping address fields.
  6. Save the record and view the Google map pointing to the business’ location.

The uses for generated URLs are almost endless, as you can embed links and iFrames to either internal or external systems without writing a single line of code. Feel free to post some ideas for other integrations.

Adding items to the Shortcuts menu

Wednesday, August 27th, 2008

Want to add items to the shortcut menu?  No problem.  Create the following file

custom/modules/<module name>/Ext/Menus/menu.ext.php

Here is an example of the contents:

<?php
$module_menu[] =Array(”index.php?module=Reports&action=index&view=contacts”, $mod_strings[’LNK_CONTACT_REPORTS’],”ContactReports”, ‘Contacts’);
$module_menu[] =Array(”javascript:SUGAR.subpanelUtils.loadSubpanelGroup(’Activities’);”, $mod_strings[’LBL_ACTIVITIES’],”Contacts”);

?>

The $module_menu array contains 4 elements:

  • The first element is target of the click.  It can either be a URL or Javascript
  • The second element is the text to display in the menu.  This must obviously be defined in a language file
  • The third element is the icon to display next to the shortcut.  The icons can be found in the themes\default\images directory.
  • The fourth element (which is optional) is the name of the module.

In the examples above, the first line takes you to Contact Reports.  The second example changes the tab in the detail view to make the Activities subpanel have focus

Importing into custom modules in 5.1

Wednesday, August 27th, 2008

The Import functionality in Sugar has had tremendous overhaul in Sugar 5.1 to make it a more robust and more user-friendly tool. Among the many improvements made is the ability to leverage the import tool very easily for custom modules.

Enable the module for import

To begin with, enabling a module for import can be easily done through Module Builder. When creating or editing a module’s properties, an new option entitled ‘Importing’ has been added. By checking this option, the import utility will be enabled for the module.

Module Builder showing the \

When you deploy the newly created package, a new option will appear in the left sidebar called “Import”, which will trigger the built-in Import function for the module.

You can also manually enable Importing for a module with two simple changes to your code. The first change is to the module’s bean file, where you’ll need to add the line of code below inside the bean class.

var $importable = true;

Next, you’ll need to add a line similar to what’s below into the Menu.php file, to add the left sidebar menu option that allows a user to import into the module.

if(ACLController::checkAccess('<<module name>>', 'import', true))
$module_menu[]=Array(
"index.php?module=Import&action=Step1&import_module=<<module name>>&return_module=<<module name>>&return_action=index",
$app_strings['LBL_IMPORT'],"Import", '<<module name>>');

Controlling the importable fields

You can also have fine-grained control over the fields you wish to import by optionally disabling a field from being imported into or requiring a field to be specified in the import file. Again, this can be controlled from Module Builder in the properties for each field. You can also set this option for custom fields you to the existing core modules through Studio.

Module Builder adding a new field with the \

The Importable option has three possible values: “Yes” indicates that you can import into the field and “No” indicates you can’t. In addition, setting it to “Required” forces users to specify a value for that field when importing.

You can also set this value manually in the vardefs, by setting the ‘importable’ option for the field you wish to change. SugarCRM assumes the field is importable, but not required, if no option is set ( the equivalent of the ‘Yes’ value of the importable flag as shown above ).

'new_text' => array (
'required' => false,
'name' => 'new_text',
'vname' => 'LBL_NEW_TEXT',
'type' => 'varchar',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'false', // don't allow importing into this field
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => 0,
'reportable' => 1,
'len' => '25',
),
'new_text_2' => array (
'required' => false,
'name' => 'new_text_2',
'vname' => 'LBL_NEW_TEXT_2',
'type' => 'varchar',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'required', // this field is required for importing
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => 0,
'reportable' => 1,
'len' => '25',
),

The improvements to the Import module in SugarCRM 5.1 allow you to easily leverage the powerful import utility with a few simple changes to your existing modules.

Enabling IMAP support under OS X Leopard

Tuesday, August 26th, 2008

With the release of Mac OS X 10.5 Leopard last fall, Apple (finally) included a modern version of PHP (currently version 5.2.6 as of this writing). With it comes several improvements in the areas of performance, web services support (including extensions for JSON and XML), OOP, and error handling. However, the default install of PHP that Apple included didn’t include all of the available PHP extensions. Most notable is the IMAP extension, which is used in SugarCRM for the Campaigns and Emails modules. However you can build this extension and have it loaded dynamically, without affecting the rest of the default PHP install.

First, we’ll need to compile the c-client imap libraries, which can be obtained at ftp://ftp.cac.washington.edu/imap/. Notice the make command below; it has extra arguments added to be sure we are building the libraries as universal binaries, which is important since mod_php and apache are both compiled for 64-bit architecture.

$ curl -O ftp://ftp.cac.washington.edu/imap/c-client.tar.Z
$ tar -zxvf c-client.tar.Z
$ cd imap-2007b
$ make oxp EXTRACFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -g -Os  -pipe -no-cpp-precomp"

We’ll then copy the libraries we built to the /usr/local directory, which is a place we can put any user-built programs and libraries and won’t affect the base system install.

$ sudo cp c-client/*.h /usr/local/include/
$ sudo cp c-client/*.c /usr/local/lib
$ sudo cp c-client/c-client.a /usr/local/lib/libc-client.a

Next, we’ll grab the PHP tarball for the version of PHP we are using, which is currently 5.2.6, from the source: http://www.php.net/downloads.

$ curl -O http://www.php.net/distributions/php-5.2.6.tar.bz2
$ tar -xjf php-5.2.6.tar.bz2

Now we’ll go to the source directory of the imap extension and compile it. Again you’ll notice the additional agruments added for building the extension as a universal binary. ( Edit: note that the configure line below is multiple lines; each new command to enter is denoted by the $ at the beginning of the line, although the $ is not part of the command ).

$ phpize
$ MACOSX_DEPLOYMENT_TARGET=10.5 \
CFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -g -Os  -pipe -no-cpp-precomp" \
CCFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -g -Os  -pipe" \
CXXFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -g -Os  -pipe" \
LDFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -bind_at_load" \
./configure --with-kerberos --with-imap-ssl
$ make
$ sudo make install
$ sudo echo "extension=imap.so" >> /etc/php.ini

Also, you’ll want to comment out the line ‘extension_dir = “./”‘ in the php.ini file, since it will interfere with the extension loading.

Finally, restart apache and you should see the imap extension listed in the output of phpinfo().

phpinfo() output showing imap enabled

Migrating data into Sugar with file attachments using Talend

Monday, August 25th, 2008

As a member of the Professional Services team here at Sugar, one of the services that is often requested of us is migrating a client’s data from their existing CRM into Sugar. In the past, our team would write custom migration scripts that read their data, performed some basic cleansing, transformed it into Sugar format, and then imported it into the database. This was a laborious task given the disparate data formats out there and varying levels of data quality–a task which none of us looked forward to doing.

Recently, however, some of us began experimenting with a tool called Open Studio, which is provided by one of Sugar’s technology partners, Talend. Open Studio is an open source data integration suite licensed under GPLv2 and provides a variety of tools for bridging the gap between disparate applications.

Using Talend Open Studio 2.4, the following are the steps that I followed to setup a migration of Note records from a Salesforce.com CSV file, including copying and renaming the associated attachments. Theser steps will work for Sugar Community Edition, Sugar Professional Edition and Sugar Enterprise Edition.

Note that the copy and rename step isn’t necessary for migrating SFDC Note data since their file attachments are already uniquely named with the record id (as it is in Sugar).  However this step highlights some of the additional functionality provided by Talend and is a useful exercise as other CRM systems don’t save their attachments with a corresponding GUID.

First download and install SugarCRM. Then download and install Talend Open Studio.  Next request a backup of your data from Salesforce.com.

Now open Talend Open Studio and follow these steps:

  1. Setup a tFileInputDelimited object that points to the SFDC Note.csv file
  2. Create a tFileList object that points to the directory that contains your attachment files (setting up the proper filters if more than the attachments exists within the directory)
  3. Create a tFileProperties object
  4. Right click the tFileList object and select Row->Iterate, and drag the line over to the tFileProperties object
  5. Click on the Component tab for the tFileProperties object and click in the File textbox. Press ctrl+space to bring up the contextual selection menu, and select the CURRENT_FILEPATH property for the tFileList object.
  6. Create a tMap object
  7. Right click the Notes tFileInputDelimited object and select Row->Main, and drag the line over to the tMap object
  8. Right click the tFileProperties object and select Row->Lookup, and drag the line over to the tMap object.
  9. Create a tFileCopy object
  10. Create a database output object (i.e. tMysqlOutput)
  11. Right click the tMap object and select Row->*New Output* (main), and drag the line over to the tFileCopy object. Give this output object a unique name (i.e. file_copy).
  12. Right click the tMap object and select Row->*New Output* (main), and drag the line over to the database output object (tMysqlOutput). Give this output object a unique name (i.e. notes)
  13. Double click the tMap object to bring up the map editor.
  14. On the left hand side of the map drag the column that contains the file name of the attachment down to the basename column on the tFileProperties schema. Select Inner Join.
  15. Drag the columns from the Notes schema on the left hand side over to the corresponding notes schema on the Right hand side. Make sure that your schema types are setup properly to avoid runtime errors. (i.e. date fields are set to Date, Boolean fields are set to Boolean, etc)
  16. Create a new column called new_file_name on the file_copy schema.
  17. Drag the column containing the id from the left hand side notes schema over to the new_file_name column on the file_copy schema
  18. Click OK to close the map editor.
  19. Click the Component tab for the tFileCopy object.
  20. Enter the CURRENT_FILEPATH property for the tFileList object into the File Name text box as you did for the tFileProperties object (step 5).
  21. Select your destination directory (for Sugar attachments, this is cache/uploads)
  22. Select the Rename checkbox and enter the new_file_name property for the file_copy object into the Destination filename textbox (for the above scenario it would be file_copy.new_file_name)
  23. Click the Run tab.
  24. Select the Statistics checkbox if you want to see where in the migration the job currently is, plus how fast the data is being migrated over.
  25. Click Run.

This should get you going to handle a basic migration of Notes data with copy and rename of the attachments. Hopefully, you will be able to take this and extend it to handle migration of data from any source into Sugar.

Wrapping up first version of Sugar Developer Guide

Friday, August 22nd, 2008

A quick update on the Sugar Developer Guide.  We are wrapping up the first round of editing of the new Sugar Developer Guide and are getting ready for a public review in the next week or so.  I’d like to open up an early review to a few community members who can dedicate some time over the next week to giving the 120 pages a thorough review.  Any takers?  Leave a comment with your email address.

SugarCRM stack available on Bitnami.org

Friday, August 22nd, 2008

The intrepid BitRock team has outdone themselves again and released SugarCRM on their Bitnami Stack.  The Bitnami Stack installers allow you to install Apache and various different run-time languages (PHP, Ruby, etc) along with various databases (MySQL, PostGres, etc).  Then you can plug in different applications like SugarCRM or Drupal on top of those stacks.

The BitNami-packaged SugarCRM stack is available as both a complete, self-contained Stack, and as a BitNami Modules. BitNami Modules enable users to run several applications on top of one AMPStack (Apache/MySQL/PHP) that runs on Windows, Linus or Mac. Here’s an article on how the Modules system works.  It’s very quick and easy to download and install the BitNami SugarCRM package on your local machine.

What I found even cooler was that you can sign up on RightScale for 10 free hours of time on the Amazon EC2 cloud computing platform and deploy your Bitnami for SugarCRM stack there.  Unfortunately I haven’t been able to actually get the SugarCRM application to correctly deploy on my RightScale test account yet, but I’m sure I’ll get it figured out here shortly.

Very cool all around!

Fun with Sugar Wireless!

Friday, August 8th, 2008

With our 5.1 release approaching, one of the features that I was most looking forward to was the revamped Sugar Wireless functionality.  I’m a devoted iPhone user, and I’m usually in need of getting to information in Sugar quickly.. but I don’t want to lug my laptop around with me everywhere I go.

Prior to 5.1, Sugar’s wireless capabilities didn’t provide me with much help as a customer support person, for the simple fact that the Cases module wasn’t exposed.  Sure, I suppose I could have hacked it together at some point in the past, but knowing that we would revamp Wireless eventually, I never got around to it.  Until now!

I spent a few minutes recently seeing how functional Sugar Wireless was for a customer support person….the initial verdict was “not very”.  Yes, Cases are now available, but the absence of Notes is something of a non-starter for companies who are using Sugar Portal to manage their customer interactions (like SugarCRM Inc. ourselves).  The thinking was that Notes were primarily used as a vehicle for file attachments — a decision that I disagree with.  My support engineers use Notes as the most common method of communication with our customers; leaving it out of Wireless cripples our ability to use Wireless.

Would I let that stop me, though?  Of course not!  So I spent a little bit of time over the last couple of days looking into how to customize Sugar Wireless 5.1, and I figured I’d share my findings with the developer community.

(As an aside, I’ll mention here that I haven’t really spent a lot of time understanding MVC and much of the metadata introduced with Sugar 5.0.  I’m not a developer; if I’d filled out Clint’s Developer Survey, I would have called myself a “Fearless Hacker”.  Most of my time spent with my fingers in Sugar’s code dates back before the 5.0 days…)

I set out with the following objectives in mind:

  • Modify the Cases views in Wireless to include some custom fields that we rely upon
  • Add the Notes module, related to Cases
  • Make it all upgrade-safe

There were a few changes that needed to be made to the 5.1 code base in order to support these objectives.  Those changes will be included in the final released version of 5.1, but are not available in 5.1 RC.  Big thanks to SugarCRM software engineer John Mertic for sneaking the necessary changes into Wireless while 5.1 is hunkering down for release.

Customizing the Cases module

First things first, get my custom fields to appear in the Cases module.  Without certain key pieces of information, it would be difficult for a support engineer to glean enough information to do anything useful.

I copied three files from SUGARROOT/modules/Cases/metadata/ to SUGARROOT/custom/modules/Cases/metadata:

  • wireless.editviewdefs.php
  • wireless.searchdefs.php
  • wireless.subpaneldefs.php

Once there, I could edit these files in an upgrade-safe manner, since they’ll override the stock files in SUGARROOT/modules/Cases/metadata.

To wireless.editviewdefs.php, I added lines into the ‘panels’ array, like:

array(’product_category_c’),
array(’sugar_edition_c’),
array(’sugar_version_c’),
array(’deployment_c’),

I also added a line in read-only mode:

array(array(’name’=>’Support_Service_Level_c’, ‘displayParams’=>array(’wireless_detail_only’=>true,)),),

Your field names will most presumably be different than mine, but the rest of the syntax will be the same.

In wireless.searchdefs.php, I added lines into the ‘layout’ array for ‘name’ and ’status’, which would make searching easier.  Especially for ‘name’, or Subject as it would appear through the UI, this is helpful if you don’t know the case number, and Wireless will obey the % wildcard in the search field.

In wireless.subpaneldefs.php, I added this block into the ’subpanel_setup’ array:

‘notes’ => array(
‘order’ => 1,
‘module’ => ‘Notes’,
‘get_subpanel_data’ => ‘notes’,
‘title_key’ => ‘LBL_NOTES_SUBPANEL_TITLE’,
),
More on this later, when we get to adding the Notes module…

Finally, with regards to the Cases module, I wanted to add the Number to the ListView for search results.  Two steps were needed for this:

1)  Create a directory SUGARROOT/custom/modules/Cases/views/ and add a view.wirelesslist.php file to that new directory.  This will allow me to subclass out the main wireless ListView:

require_once(’include/MVC/View/views/view.wirelesslist.php’);

/**
* ViewWirelesslist extends SugarWirelessView and is the view for wireless list views.
*
*/
class CasesViewWirelesslist extends ViewWirelesslist
{
public function display(){
// print the header
$this->wl_header();
// print the select list
$this->wl_select_list();

// check for presence of parent_id — this is the subpanel list view
if (isset($_REQUEST[’parent_id’])){
$this->wl_subpanel_list_view_display();
}
// normal list view display
else{
$this->wl_list_view_display();
}

// display the list view
$this->ss->display(’custom/modules/Cases/tpls/wirelesslist.tpl’);

// print the footer
$this->wl_footer();
}
}

2)  Create a directory SUGARROOT/custom/modules/Cases/tpls/ and copy the file SUGARROOT/include/SugarWireless/tpls/wirelesslist.tpl here, as referenced in the ‘display the list view’ section above.  Then, I built out from this line:

<a href=”index.php?module={$MODULE}&action=wirelessdetail&record={$record.ID}”>{$record.NAME}</a>

To these lines:

{if $MODULE == “Cases”}
<a href=”index.php?module={$MODULE}&action=wirelessdetail&record={$record.ID}”>{$record.CASE_NUMBER}  {$record.NAME}</a>
{else}
<a href=”index.php?module={$MODULE}&action=wirelessdetail&record={$record.ID}”>{$record.NAME}</a>
{/if}

Adding the Notes module

Most of the changes necessary for Notes are upgrade-safe. First was the Cases subpaneldefs, covered above.

Next is creating Wireless metadata files for the Notes module.  Since these were being written from scratch, I copied the following files from SUGARROOT/modules/Calls/metadata/ to SUGARROOT/custom/modules/Notes/metadata:

  • wireless.editviewdefs.php
  • wireless.searchdefs.php
  • wireless.subpaneldefs.php

Then edited those files to replace ‘Calls’ with ‘Notes’.

In wireless.editviewdefs.php:

$viewdefs[’Calls’][’EditView’] = array(

became

$viewdefs[’Notes’][’EditView’] = array(

And equivalent changes in the other two files.

Upgrade-Safe?

Up to this point, everything should be upgrade-safe. Unfortunately, there’s one step that won’t be upgrade-safe… :-(

In the file SUGARROOT/include/MVC/Controller/wireless_module_registry.php, I needed to add Notes to the registry:

‘Notes’ => array(),

[EDIT, August 11, 2008:  John Mertic pointed out to me how to make this step upgrade-safe as well.]

One more change to make, and this one is upgrade-safe as well.  In the directory SUGARROOT/custom/include/MVC/Controller, create a file named wireless_module_registry.php, which will contain this:

<?php

$wireless_module_registry[’Notes’] = array();

?>
This controls the hyperlinks within the Wireless application to keep your browser within Wireless, instead of going back to the main Sugar application.  Without this step, the links will send you to your main Sugar application, which isn’t optimized for your mobile browser.

Conclusion

All in all, not too painful!  I did my development on a local instance, and tweaked things to the point where I was happy with the appearance, then made my changes in our production instance.  From a testing perspective, you can use your computer’s browser by logging into the mobile interface:

http://YOUR.SUGAR.SITE/index.php?module=Users&action=Login&mobile=1

I hope you find this useful.  If you come up with other ways to extend Sugar Wireless, let’s hear them!

Have feedback for us? Drop us a line.
Terms & Conditions | Privacy | Trademark Info | Contact Info | FAQs | SugarCRM Inc.© 2004 - 2008 All rights reserved.