Contents


Connect your data to the outside world with SugarCRM connectors

Build a Google News connector using the Google AJAX Search API

Comments

What are connectors?

The question most people have about any application (whether it is a Web or a desktop application) is: How can you connect it to already existing applications? The typical solution is to provide an API of some sort, which exposes the application functionality or data in the form of a constant programmatic interface that a developer can use to connect to the application. This solution solves the problem of how to connect to an application, but it doesn't solve the other half of the problem, which is to connect your application to a different one. For SugarCRM, this problem is solved with the connectors framework.

The connectors framework provides a standardized way to connect your SugarCRM records to data in an another application over REST or SOAP Web services. The LinkedIn Connector in SugarCRM is an example of this; it provides LinkedIn lookups of Accounts and Contacts inside SugarCRM detail records. It comes with SugarCRM by default. Figure 1 shows how the interaction looks inside the application.

Figure 1. LinkedIn Connector inside SugarCRM
Screen capture of the LinkedIn Connector inside SugarCRM (lists three connections plus links to more)
Screen capture of the LinkedIn Connector inside SugarCRM (lists three connections plus links to more)

Figure 1 shows the integration with the Accounts module. Triggering the connector is as simple as hovering your cursor over the LinkedIn icon next to the Accounts, which does a quick LinkedIn search to see how many connections you have at the given company. It also provides links to the profile pages of those connections as a part of the widget.

Now that you have seen the usefulness of this functionality, look at how to build a custom connector for your own needs.

Building your Google News connector

For this article, you'll build a connector to the Google News service. Google News is a news aggregation service, which draws from many different news agencies and online sites around the world to present the news in a single unified site which is easily searchable. A connector to this service is a very useful add-on to SugarCRM; it gives users of the application a quick look into the latest news items for the Account record the user is currently viewing.

For the Google News connector, you'll use the Google AJAX Search API for connecting to Google News. This is a very handy API that is very lightweight and easy to use. To make things simpler on the JavaScript side, use the iframe integration, where a fully styled HTML widget is returned inside an iframe back to the client. This allows you to concentrate on the code pieces that you need to add to SugarCRM to make everything work as expected.

To begin with, add a few configuration and mapping files for the connector you are building, as well as the display template to display the connector data to the user. Figure 2 shows the directory layout that is required to add the new Google News connector. (View a text-only version of Figure 2.)

Figure 2. Google News connector directory layout
Google News connector directory layout
Google News connector directory layout

To make the connector upgrade-safe (meaning that upgrades of the main SugarCRM application won't affect your custom code modifications), you must put all of your connector files inside the custom/ directory. Also note that if you have already activated the LinkedIn connector in the application, you might have a metadata/directory inside the custom/modules/Connectors/ directory; this contains a registry of found connectors. You'll want to delete this folder so the application finds your newly added custom connector.

Source

Connectors are broken down into two parts. The source portion controls the configuration of the connector, getting the data from the Web service, and mapping the existing SugarCRM module field to a field used by the remote Web service. The second part of the connector is the formatter, which you'll look at in the next section. The source portion contains a few different files; first review the config.php file in Listing 1.

Listing 1. custom/modules/Connectors/sources/ext/rest/googlenews/config.php
<?php 
$config = array ( 
  'name' => 'Google News', 
  'properties' => array(), 
);

This file defines the name for the connector, and any properties the connector might need. Often, these Web services require an API key of some sort that must be provided to the Web service as a part of the request, so you can define it inside this file. However, for the Google AJAX Search API you are using, no other special configuration is required, so just specify the connector name and an empty properties array.

Next, in Listing 2, review the vardefs.php, which defines the fields that are provided by the connector.

Listing 2. custom/modules/Connectors/sources/ext/rest/googlenews/vardefs.php
<?php 
$dictionary['ext_rest_googlenews'] = array( 
  'comment' => 'vardefs for google news connector', 
  'fields' => array ( 
    'id' => 
 array ( 
   'name' => 'id', 
   'vname' => 'LBL_ID', 
   'type' => 'id', 
   'comment' => 'Unique identifier', 
  'hidden' => true, 
), 
    'name'=> array( 
   'name' => 'name', 
   'vname' => 'LBL_NAME', 
   'type' => 'varchar', 
'hover' => true, 
   'comment' => 'The name of the company', 
    ), 
  ) 
);

The Google News connector will query on the name field of the Accounts record, so you'll specify that field along with the id field for the record as the field used to make the Web service call to find the Google News results for the Account. (Note: Those with SugarCRM experience will recognize the file formatting, as it uses the same format as the database field vardefs.php file.)

The magic in relating an Account to a connector occurs in the mappings.php file in Listing 3.

Listing 3. custom/modules/Connectors/sources/ext/rest/googlenews/mapping.php
<?php 
$mapping = array ( 
  'beans' =>  
  array ( 
    'Accounts' =>  
    array ( 
      'name' => 'name', 
      'id' => 'id', 
    ), 
  ), 
);

Listing 3 shows how to map fields from the connector to the module in question. For this example, you request the name field of the connector; it will be the same value as in the name field of the Accounts module. Similarly, the id field of the connector is mapped to the id field of the Accounts module.

You then need to add an instance of the rest source class for the connector to be fully functioning. Check out Listing 4 for how it is handled for your connector. Since you'll use the Google AJAX Search API, which is all JavaScript/browser based, you won't use any of the built-in functionality inside the source class, so you'll just stub out the calls you need to have.

Listing 4. custom/modules/Connectors/sources/ext/rest/googlenews/googlenews.php
<?php 
require_once('include/connectors/sources/ext/rest/rest.php'); 
class ext_rest_googlenews extends ext_rest  
{ 
public function __construct() 
{ 
parent::__construct(); 
$this->_enable_in_wizard = false; 
$this->_enable_in_hover = true; 
} 
/* 
* getItem 
*  
* As the google news connector does not have a true API call, you simply 
* override this abstract method 
*/ 
public function getItem($args=array(), $module=null) {} 
/* 
* getList 
*  
* As the google news connector does not have a true API call, you simply 
* override this abstract method 
*/ 
public function getList($args=array(), $module=null) {} 
}

Finally, add a language definition file in Listing 5 for the one language string used in your connector, which specifies the field name for the name field used in the vardefs.php file in Listing 2. (custom/modules/Connectors/connectors/sources/ext/rest/googlenews/language/en_us.lang.php is the full directory path for the en_us.lang.php file.)

Listing 5. .../Connectors/connectors/sources/ext/rest/googlenews/language/en_us.lang.php
<?php 
$connector_strings = array ( 
    'LBL_NAME' => 'Company Name', 
);

With this, you have built the source mappings and configuration for the connector. Now you can use formatters to display the data pulled from the Web service.

Formatter

The other part of the connector displays the connector data to the user, and is called the formatter. Begin by creating a definition file that extends the default_formatter class and adds the needed pieces to display the connector data in the detail view. This file is named after the connector (googlenews.php) and is in Listing 6.

Listing 6. custom/modules/Connectors/formatters/ext/rest/googlenews/googlenews.php
<?php 
require_once('include/connectors/formatters/default/formatter.php'); 
class ext_rest_googlenews_formatter extends default_formatter  
{ 
    public function getDetailViewFormat()  
    {  
       $mapping = $this->getSourceMapping(); 
       $mapping_name = !empty($mapping['beans'][$this->_module]['name']) ?
 $mapping['beans'][$this->_module]['name'] : ''; 

       if(!empty($mapping_name)) { 
           $this->_ss->assign('mapping_name', $mapping_name); 
           return $this->fetchSmarty(); 
       } 

       $GLOBALS['log']->error($GLOBALS['app_strings']['ERR_MISSING_MAPPING
_ENTRY_FORM_MODULE']); 
       return ''; 
    } 

    public function getIconFilePath()  
    { 
       return 'custom/modules/Connectors/connectors/formatters/ext/rest
/googlenews/tpls/googlenews.gif'; 
    } 
}

The two functions defined in Listing 6 are called by the DetailView metadata framework to do the actual rendering of the connector inside the form. The getIconFilePath() returns the URL to the icon that is displayed next to the field in the DetailView form, which is being connected to by the connector. Then, the getDetailViewFormat() handles this rendering of the widget form, which is shown when you hover over the icon. Listing 7 shows the Smarty template for the connector widget.

Listing 7. custom/modules/Connectors/formatters/ext/rest/googlenews/tpls/default.tpl
<div style="visibility:hidden;" id="googlenews_popup_div"></div>
<script type="text/javascript" src="{sugar_getjspath 
file='include/connectors/formatters/default/company_detail.js'}"></script>
<script type="text/javascript"> 
function show_ext_rest_googlenews(event) 
{literal}  
{ 
var xCoordinate = event.clientX; 
var yCoordinate = event.clientY; 
var isIE = document.all?true:false; 

if(isIE) { 
    xCoordinate = xCoordinate + document.body.scrollLeft; 
    yCoordinate = yCoordinate + document.body.scrollTop; 
} 
{/literal} 
cd = new CompanyDetailsDialog("googlenews_popup_div",  
  '<iframe height="90px" width="728px" frameborder="0" marginheight=0 
marginwidth=0 scrolling="no" src="//www.google.com/uds/modules/elements
/newsshow/iframe.html?rsz=small&q={$fields.{{$mapping_name}}.value}
&format=728x90"></iframe>', 
  xCoordinate, yCoordinate); 
cd.setHeader("{$fields.{{$mapping_name}}.value}"); 
cd.display(); 
{literal} 
}  
{/literal} 
</script>

You need to define the JavaScript function show_ext_rest_googlenews(), which is triggered when the cursor hovers over the icon in the detailview. This JavaScript function handles rendering the popup dialog that contains the widget contents, and also makes the external call to the Web service, rendering its results inside the popup dialog. The rendering code then initializes the popup window, sets the title to the name of the current record, and finally builds an iframe that makes the API call using the passed company name coming from the record you are currently on. Figure 3 shows hows this all looks in action.

Figure 3. Google News connector in action
Screen capture of  Google News connector with news item about  target company
Screen capture of Google News connector with news item about target company

You have now built a fully functioning connector that will pull data from Google News on the given Account as your cursor hovers over the news icon next to the Account name. You can easily add this for other modules in the application as well by simply adding another module entry in the mapping.php file in Listing 2 with the record mapping to the connector. SugarCRM also provides a graphical way to do this under the Connector Settings option in the Admin section in the app; just click on the Connector Settings option in that screen to change which modules have the news icon available, as in Figure 4.

Figure 4. Connector Settings
Screen capture of Connector Settings, Google News tab with icon enabled for Accounts and Contacts
Screen capture of Connector Settings, Google News tab with icon enabled for Accounts and Contacts

The next thing to do is the field mapping for the module that you added; do this in the Map Connector Fields page under Connector Settings, as in Figure 5.

Figure 5. Map Connector Fields
Screen capture of Map Connector Fields on the Google News tab: Select Module Fields for Accounts and Contacts
Screen capture of Map Connector Fields on the Google News tab: Select Module Fields for Accounts and Contacts

For each of the fields in the connector, use the dropdown selector to pick the field you will use with the module for the mapping between the two entities. You can do a different mapping for each different module that the connector is available for.

Summary

In this article you learned about the SugarCRM connectors framework, which provides a way to connect to outside data sources from inside your application. You saw how this approach to external application integration was different from the traditional method where an application provides external hooks into the application for other applications to use. After reviewing the LinkedIn connector provided with SugarCRM, you learned how to build your own Google News connector using the Google AJAX Search APIs, as you stepped through the definition process. In the end, you have a fully working Google News connector to displaying news results for the given Account record that you view.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Open source
ArticleID=465609
ArticleTitle=Connect your data to the outside world with SugarCRM connectors
publish-date=02022010