SlideShare uma empresa Scribd logo
1 de 11
Baixar para ler offline
Alfredo PUMEX
Pluggable Users Module Additions for SugarCRM



Introduction / The SugarCRM way
When developing new modules for SugarCRM, a frequent requirement is to provide per-user
customizations for the new module, e.g. login credentials for some external enterprise resource.
However, customizing SugarCRMs Users module turns out to be painful, simply because the Users
module was not designed to be customization friendly!
An approach chosen by some module writers (most notably YAAI, where we @ abcona e.K. were
somewhat involved, see http://www.sugarforge.org/projects/yaai/ is to OVERWRITE some core
files in SugarCRMs Users module, providing logic for displaying and editing custom fields.
For instance, in YAAI we used to overwrite DetailView.{php,html},EditView.{php,html} and
Save.php. Obviously, this solution is rather ugly, as it involves creating a new patch release for
every SugarCRM update1, and it doesn't scale well: have two modules using this approach and you
are busted. (The YAAI manual has some elaborations on that topic).
Rumours are there will be a rewritten Users module for SugarCRM 6, but we needed a more
modular solution for SugarCRM 5.2 NOW!



To the rescue / The Alfredo way

To provide an plug-in mechanism for the Users module, we make extensive use of Alfredo Patch
and jQuery. By using jQuerys magic powers, we dynamically extend the Users module functionality
WITHOUT ALTERING A SINGLE FILE in that module.
A basic understanding of jQuery and Alfredo Patch is thus helpful to understand the following
walkthrough.


We'll outline only the basic control flow and the most important statements, so you should use
PUMEX source file as reference.



custom/modules/Users/Ext/javascript/Alfredo-ext.php

This is the entry point into the extension mechanism and invoked from Alfredo Patch. Alfredo-
ext.php takes care of including the required jQuery libraries, and then includes, depending on the
current request's action parameter, either
- DetailView-ext.js or
- EditView-ext.js



1 And one good thing about SugarCRM is that the hard-working guys at SugarCRM, Inc. provide maintenance
  releases on a frequent schedule.
custom/modules/Users/Ext/Alfredo/DetailView-ext.js

This is the snippet of jQuery code that extends the Users module DetailView page. Essentially, it
uses jQuery magic to insert some <div> into the DOM tree and then uses an AJAX call to fetch the
extended DetailView.
Typically for jQuery, this is very compact code:

jQuery(document).ready(function() {
      // Extract user id from form data
      var userId = jQuery(':input[name=record]').val();
      jQuery('#subpanel_list').before('<div id="Alfredo_Extension_Point"></div>');
    jQuery('#Alfredo_Extension_Point').load('index.php?
module=Users&entryPoint=extend_detail_view&record=' + userId);
});


Please note the use of SugarCRM's entryPoint mechanism; the actual mapping from entryPoints to
executed scripts is defined in entry_point_registry.php.



custom/modules/Users/Ext/Alfredo/ajax/ExtendDetailView.php

This is the server-side AJAX script which creates the additional HTML to display custom
parameters in the DetailView.
Basically, it sets up a SugarSmarty template and then renders an arbitrary number of DetailView.tpl
templates found at a well-known location:

$sugar_smarty = new Sugar_Smarty();
$sugar_smarty->assign('MOD', $mod_strings);
$sugar_smarty->assign('APP', $app_strings);
$sugar_smarty->assign('APP_LIST', $app_list_strings);
$sugar_smarty->assign('USER', $cUser);


foreach (glob("custom/modules/Users/Ext/Alfredo.Ext.Dir/*") as $extDir) {
      if (is_dir($extDir)) {
          $GLOBALS['log']->fatal("Using extensions from $extDir");
          $sugar_smarty->display($extDir . '/DetailView.tpl');
      }
}



Please note that all the custom properties for User are automagically set up by the SugarCRM
framework, and thus available through the $cUser variable (resp. {$USER->....} in the
templates).
custom/modules/Users/Ext/Alfredo/EditView-ext.js

This is somewhat similar to the DetailView case, again we use jQuery magic to modify the DOM
tree:

jQuery(document).ready(function() {
      // Insert extension point into main form...
      var mainForm = jQuery('#EditView');
      var userId = jQuery(':input[name=record]', mainForm).val();
      mainForm.find("div[id]:last").after('<div id="Alfredo_Extension_Point"></div>');


      // Then use AJAX wizardry to load extended settings
    jQuery('#Alfredo_Extension_Point').load('index.php?
module=Users&entryPoint=extend_edit_view&record=' + userId);
      //
      // Finally, hook into sumbit handler
      // Intercept standard 'Save' action with own
      //
      mainForm.submit(function(e) {
            var currentAction = jQuery(':input[name=action]', this);
            if (currentAction.val() == 'Save') {
                currentAction.val('AlfredoDispatch');
            }
            var action = jQuery(':input[name=action]', this).val();
            return true;
      });
});



However, this time we also changed the forms action from the customary Save into
AlfredoDispatch! By using this trick, we may safely intercept the EditView's save action without
actually touching Save.php.




custom/modules/Users/AlfredoDispatch.php

This is the modified save action for the Users module EditView form. To perform its duties, we first
do a loopback call into Save.php, using PHPs curl library:


$curlHandle = curl_init($loopbackURL);
…
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $encodedArgs);
…
$curlResult = curl_exec($curlHandle);
$httpRC = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE);
…


On success of the save action, an instance of the User bean is instantiated and passed to all custom
save actions, using the same globbing mechanism we have seen before:


            $focus = new User();
            $id = isset ($_POST['record']) ? $_POST['record'] : $continuationArgs['record'];
            $focus->retrieve($id);
            $log->fatal('_________________ @ ' . __FILE__);
            $log->fatal("     Retrieved User bean for id=$id");


            //
            // Gather extended save actions
            //
            foreach (glob("custom/modules/Users/Ext/Alfredo.Ext.Dir/*") as $extDir) {
                 if (is_dir($extDir)) {
                     $extSaveFile = $extDir . "/save_params.php";
                     if (file_exists($extSaveFile)) {
                         $log->fatal("    Using extended save action: $extSaveFile");
                         $rc = include($extSaveFile);
                         $log->fatal('_________________ @ ' . __FILE__);
                         $log->fatal("    rc:$rc");
                     }
                 }
            }
            $focus->save();



Finally, the updated bean is again persisted to save our changes.
Tutorial: Alfredofying the YAAI module
As mentioned in the introduction, YAAI used to use the ill-fated approach of overwriting
SugarCRMs core files for customization of the Users module. Now, with PUMEX in our toolchest,
it should be easy to cure that! Let's get started:

Creating the extension folder

Remember? We need a folder, containing exactly 3 files, that will become our PUMEX extension.
We'll gonna create them at the root level of my modules source folder:




We'll leave the content of the files empty now, they are filled with live soon....
Surely I dont forget to add the new files to manifest.php:
Fixing the DetailView
To augment the DetailView in the Users module, we previously had to overwrite DetailView.php
and DetailView.html, where DetailView.html is really a Xtemplate template (sic).
DetailView.php takes care of setting the templates parameters from the User bean, thus we had to
copy&paste this snippet of code somewhere inside DetailView.php:




Likewise, we had to extend DetailView.html to show YAAI's custom parameters:




With Alfredo PUMEX, we can neatly replace that cut&paste approach by putting the template code
in DetailView.tpl. Unfortunately, we cannot simply copy this code, as the Users module uses the
legacy Xtemplate library, while Alfredo uses the newer Smarty templates, also favored by
SugarCRM.
Thus, our new DetailView.tpl will finally look like this:

<p>
<!-- Asterisk refactored -->
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="tabDetailView">
          <tr>
                  <th align="left" class="tabDetailViewDL" colspan="3" width="100%">
                          <h4 class="tabDetailViewDL">{$MOD.LBL_ASTERISK_OPTIONS_TITLE}</h4>
                  </th>
          </tr>
          <tr>
                  <td class="tabDetailViewDL" style="width: 15%">{$MOD.LBL_ASTERISK_EXT}</td>
                  <td class="tabDetailViewDF" style="width: 15%">{$USER->asterisk_ext_c}</td>
                  <td class="tabDetailViewDF">{$MOD.LBL_ASTERISK_EXT_DESC}</td>
          </tr>
          <tr>
                  <td class="tabDetailViewDL">{$MOD.LBL_ASTERISK_INBOUND}</td>
               <td class="tabDetailViewDF"><input class="checkbox" type="checkbox" disabled {if
$USER->asterisk_inbound_c}checked{/if}/></td>
                  <td class="tabDetailViewDF">{$MOD.LBL_ASTERISK_INBOUND_DESC}</td>
          </tr>
          <tr>
                  <td class="tabDetailViewDL">{$MOD.LBL_ASTERISK_OUTBOUND}</td>
               <td class="tabDetailViewDF"><input class="checkbox" type="checkbox" disabled {if
$USER->asterisk_outbound_c}checked{/if}/></td>
                  <td class="tabDetailViewDF">{$MOD.LBL_ASTERISK_OUTBOUND_DESC}</td>
          </tr>
</table>
</p>



There are a few points worth noting:
      •   There is no counterpart for the olde DetailView.php!

          The setup of template variables is automagically done by PUMEX; notably we have the
          standard variables in the templates scope:

          $USER                  Focused user
          $MOD                   Module strings
          $APP                   Application strings
          Also the necessary translation from config values (0,1) to HTML 'checked' attribute is no
          done in the template.
      •   Note the different Syntax for $USER (An User Object) and $MOD/$APP (plain arrays).



Fixing the EditView
This is very similar to the DetailView case, however this time we have to write a little snippet of
code to save our custom settings.
Again, let's start with the template code we have in EditView.html:




Translated in Smartyspeak this becomes

<div id="asterisk">
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="tabForm">
         <tr>
                 <th align="left" class="dataLabel" colspan="3">
                         <h4 class="dataLabel">{$MOD.LBL_ASTERISK_OPTIONS_TITLE}</h4>
                 </th>
         </tr>
         <tr>
         <td width="15%" class="dataLabel" valign="top"><slot>{$MOD.LBL_ASTERISK_EXT}</slot></td>
        <td width="15%" class="dataField"><slot><input type="text" tabindex='3'
name="asterisk_ext_c" value="{$USER->asterisk_ext_c}" size="3"></slot></td>
         <td class="dataField"><slot>{$MOD.LBL_ASTERISK_EXT_DESC}</slot></td>
    </tr>
    <tr>
         <td class="dataLabel" valign="top"><slot>{$MOD.LBL_ASTERISK_INBOUND}</slot></td>
               <td class="dataField"><slot><input type="checkbox" tabindex='3'
name="asterisk_inbound_c" value="1" {if $USER->asterisk_inbound_c}checked{/if}></slot></td>
         <td class="dataField"><slot>{$MOD.LBL_ASTERISK_INBOUND_DESC}</slot></td>
    </tr>
    <tr>
         <td class="dataLabel" valign="top"><slot>{$MOD.LBL_ASTERISK_OUTBOUND}</slot></td>
               <td class="dataField"><slot><input type="checkbox" tabindex='3'
name="asterisk_outbound_c" value="1" {if $USER->asterisk_outbound_c}checked{/if}></slot></td>
                 <td class="dataField"><slot>{$MOD.LBL_ASTERISK_OUTBOUND_DESC}</slot></td>
    </tr>
</table>
</div>



No big surprises here, the most important difference is that the checkboxes are now enabled...
We need to make a final move to deal with the checkboxes, though.
Put this in save_params.php to translate the values passed for the checkboxes into {0,1} values:

<?php


global $log;


$log->fatal('_________________ @ ' . __FILE__);
$log->fatal('Working with User bean:' . $focus->id);


$focus->asterisk_inbound_c = (isset($_REQUEST['asterisk_inbound_c']) &&
$_REQUEST['asterisk_inbound_c']) ? 1 : 0;
$focus->asterisk_outbound_c = (isset($_REQUEST['asterisk_outbound_c']) &&
$_REQUEST['asterisk_outbound_c']) ? 1 : 0;


return 0;


?>




Replacing the logic hook
YAAI uses a logic hook to inject Javascript code into all of SugarCRMs generated pages.
Here is the hooks' code which conditionally emits some Javascript:

function echoJavaScript($event,$arguments){

        // asterisk hack: include ajax callbacks in every sugar page except ajax requests:
        if(empty($_REQUEST["to_pdf"])){
               if(isset($GLOBALS['current_user']->asterisk_ext_c) && ($GLOBALS['current_user']-
>asterisk_ext_c != '') && (($GLOBALS['current_user']->asterisk_inbound_c == '1') ||
($GLOBALS['current_user']->asterisk_outbound_c == '1'))){
               echo '<script type="text/javascript"
src="include/javascript/jquery/jquery.pack.js"></script>';
               echo '<link rel="stylesheet" type="text/css" media="all"
href="modules/Asterisk/include/asterisk.css">';
               if($GLOBALS['current_user']->asterisk_inbound_c == '1')
                echo '<script type="text/javascript"
src="modules/Asterisk/include/javascript/dialin.js"></script>';
        if($GLOBALS['current_user']->asterisk_outbound_c == '1')
                echo '<script type="text/javascript"
src="modules/Asterisk/include/javascript/dialout.js"></script>';
        }
        }
  }



Of course we want to use Alfredo Patch for that! So we need to drop an include file for Alfredo
Patch into its global extension folder at custom/application/Ext/javascript/ . Lets call it YAAI-
ext.php:
And its content is as simple as this:

<?php
require_once 'custom/include/javascript/jquery/1.3/include-core.php';
echo "<link rel='stylesheet' type='text/css' media='all'
href='modules/Asterisk/include/asterisk.css'>n";
?>



Remember to use require_once(), if at all possible to avoid duplicate inclusion of Javascript code!


Again, we add this new file to manifest.php:




And we're done!
Conclusion
Using Alfredo Patch and Alfredo PUMEX, we can easily extend the Users module in a pluggable
and modular fashion. Extending is as easy as writing 2 template and one PHP file, which are
dropped at some well known location.
Currently, Alfredo Connector and the forthcoming Version 2.0 of the YAAI SugarCRM-Asterisk
connector use this technique, but hopefully the Alfredo approach is useful to other SugarCRM
module writers too.....




Copyright
Alfredo source files and documentation are © abcona e.K (www.abcona.de) and released to the
public under the terms of the GNU Public License, Version 3.

Mais conteúdo relacionado

Mais procurados

Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Rabble .
 
Demystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsDemystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsMichael Miles
 
Building Web Interface On Rails
Building Web Interface On RailsBuilding Web Interface On Rails
Building Web Interface On RailsWen-Tien Chang
 
Ajax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsAjax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsTse-Ching Ho
 
Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8Michael Miles
 
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8Michael Miles
 
Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Ivan Chepurnyi
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsAlessandro Molina
 
Introduction to backbone presentation
Introduction to backbone presentationIntroduction to backbone presentation
Introduction to backbone presentationBrian Hogg
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batisday
 

Mais procurados (19)

Rails Best Practices
Rails Best PracticesRails Best Practices
Rails Best Practices
 
RicoLiveGrid
RicoLiveGridRicoLiveGrid
RicoLiveGrid
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Alfredo-PUMEX
Alfredo-PUMEXAlfredo-PUMEX
Alfredo-PUMEX
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007
 
Demystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback CommandsDemystifying Drupal AJAX Callback Commands
Demystifying Drupal AJAX Callback Commands
 
Building Web Interface On Rails
Building Web Interface On RailsBuilding Web Interface On Rails
Building Web Interface On Rails
 
Ajax nested form and ajax upload in rails
Ajax nested form and ajax upload in railsAjax nested form and ajax upload in rails
Ajax nested form and ajax upload in rails
 
Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8Demystifying AJAX Callback Commands in Drupal 8
Demystifying AJAX Callback Commands in Drupal 8
 
YouDrup_in_Drupal
YouDrup_in_DrupalYouDrup_in_Drupal
YouDrup_in_Drupal
 
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
MidCamp 2016 - Demystifying AJAX Callback Commands in Drupal 8
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 
Introduction to backbone presentation
Introduction to backbone presentationIntroduction to backbone presentation
Introduction to backbone presentation
 
Django
DjangoDjango
Django
 
Drupal 8 Services
Drupal 8 ServicesDrupal 8 Services
Drupal 8 Services
 
Magento Indexes
Magento IndexesMagento Indexes
Magento Indexes
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batis
 

Destaque

Gita Study Nov 9 Dr. Shriniwas J. Kashalikar
Gita Study Nov 9 Dr. Shriniwas J. KashalikarGita Study Nov 9 Dr. Shriniwas J. Kashalikar
Gita Study Nov 9 Dr. Shriniwas J. Kashalikardrsolapurkar
 
Recursos tecnologicos para el aprendizaje
Recursos tecnologicos para el aprendizajeRecursos tecnologicos para el aprendizaje
Recursos tecnologicos para el aprendizajeCindia Ovares araya
 
XSD%20and%20jCAM%20tutorial
XSD%20and%20jCAM%20tutorialXSD%20and%20jCAM%20tutorial
XSD%20and%20jCAM%20tutorialtutorialsruby
 
Year 2070 &quot;Save Water&quot;
Year 2070 &quot;Save Water&quot;Year 2070 &quot;Save Water&quot;
Year 2070 &quot;Save Water&quot;Ismail K
 
Blossoming Together Dr. Shriniwas Kashalikar
Blossoming Together Dr. Shriniwas KashalikarBlossoming Together Dr. Shriniwas Kashalikar
Blossoming Together Dr. Shriniwas Kashalikardrsolapurkar
 
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>tutorialsruby
 

Destaque (11)

Icicles
IciclesIcicles
Icicles
 
Gita Study Nov 9 Dr. Shriniwas J. Kashalikar
Gita Study Nov 9 Dr. Shriniwas J. KashalikarGita Study Nov 9 Dr. Shriniwas J. Kashalikar
Gita Study Nov 9 Dr. Shriniwas J. Kashalikar
 
tutorial5
tutorial5tutorial5
tutorial5
 
Recursos tecnologicos para el aprendizaje
Recursos tecnologicos para el aprendizajeRecursos tecnologicos para el aprendizaje
Recursos tecnologicos para el aprendizaje
 
XSD%20and%20jCAM%20tutorial
XSD%20and%20jCAM%20tutorialXSD%20and%20jCAM%20tutorial
XSD%20and%20jCAM%20tutorial
 
Year 2070 &quot;Save Water&quot;
Year 2070 &quot;Save Water&quot;Year 2070 &quot;Save Water&quot;
Year 2070 &quot;Save Water&quot;
 
Perl-crash-course
Perl-crash-coursePerl-crash-course
Perl-crash-course
 
Tutores Articuladores(1)
Tutores Articuladores(1)Tutores Articuladores(1)
Tutores Articuladores(1)
 
08.d mst12.logistics
08.d mst12.logistics08.d mst12.logistics
08.d mst12.logistics
 
Blossoming Together Dr. Shriniwas Kashalikar
Blossoming Together Dr. Shriniwas KashalikarBlossoming Together Dr. Shriniwas Kashalikar
Blossoming Together Dr. Shriniwas Kashalikar
 
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
 

Semelhante a Alfredo PUMEX: Extend SugarCRM Users Module

Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)arcware
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolGordon Forsythe
 
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...LEDC 2016
 
Migrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mindMigrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mindValentine Matsveiko
 
Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016John Napiorkowski
 
07 Php Mysql Update Delete
07 Php Mysql Update Delete07 Php Mysql Update Delete
07 Php Mysql Update DeleteGeshan Manandhar
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
First Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentNuvole
 
Simple module Development in Joomla! 2.5
Simple module Development in Joomla! 2.5Simple module Development in Joomla! 2.5
Simple module Development in Joomla! 2.5Vishwash Gaur
 
Whmcs addon module docs
Whmcs addon module docsWhmcs addon module docs
Whmcs addon module docsquyvn
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Michelangelo van Dam
 
Empowering users: modifying the admin experience
Empowering users: modifying the admin experienceEmpowering users: modifying the admin experience
Empowering users: modifying the admin experienceBeth Soderberg
 
WordPress Structure and Best Practices
WordPress Structure and Best PracticesWordPress Structure and Best Practices
WordPress Structure and Best Practicesmarkparolisi
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
Debugging in drupal 8
Debugging in drupal 8Debugging in drupal 8
Debugging in drupal 8Allie Jones
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 

Semelhante a Alfredo PUMEX: Extend SugarCRM Users Module (20)

Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
Yii Introduction
Yii IntroductionYii Introduction
Yii Introduction
 
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
 
Migrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mindMigrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mind
 
Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016Catalyst patterns-yapc-eu-2016
Catalyst patterns-yapc-eu-2016
 
07 Php Mysql Update Delete
07 Php Mysql Update Delete07 Php Mysql Update Delete
07 Php Mysql Update Delete
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
First Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven Development
 
Simple module Development in Joomla! 2.5
Simple module Development in Joomla! 2.5Simple module Development in Joomla! 2.5
Simple module Development in Joomla! 2.5
 
Whmcs addon module docs
Whmcs addon module docsWhmcs addon module docs
Whmcs addon module docs
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Empowering users: modifying the admin experience
Empowering users: modifying the admin experienceEmpowering users: modifying the admin experience
Empowering users: modifying the admin experience
 
WordPress Structure and Best Practices
WordPress Structure and Best PracticesWordPress Structure and Best Practices
WordPress Structure and Best Practices
 
Drupal 8 Hooks
Drupal 8 HooksDrupal 8 Hooks
Drupal 8 Hooks
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
Debugging in drupal 8
Debugging in drupal 8Debugging in drupal 8
Debugging in drupal 8
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 

Mais de tutorialsruby

&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />tutorialsruby
 
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>tutorialsruby
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />tutorialsruby
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />tutorialsruby
 
Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0tutorialsruby
 
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269tutorialsruby
 
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269tutorialsruby
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008tutorialsruby
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008tutorialsruby
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheetstutorialsruby
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheetstutorialsruby
 
Winter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20JavascriptWinter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20Javascripttutorialsruby
 

Mais de tutorialsruby (20)

&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 
Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0
 
xhtml_basics
xhtml_basicsxhtml_basics
xhtml_basics
 
xhtml_basics
xhtml_basicsxhtml_basics
xhtml_basics
 
xhtml-documentation
xhtml-documentationxhtml-documentation
xhtml-documentation
 
xhtml-documentation
xhtml-documentationxhtml-documentation
xhtml-documentation
 
CSS
CSSCSS
CSS
 
CSS
CSSCSS
CSS
 
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
 
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
 
HowTo_CSS
HowTo_CSSHowTo_CSS
HowTo_CSS
 
HowTo_CSS
HowTo_CSSHowTo_CSS
HowTo_CSS
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheets
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheets
 
Winter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20JavascriptWinter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20Javascript
 

Último

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Último (20)

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

Alfredo PUMEX: Extend SugarCRM Users Module

  • 1. Alfredo PUMEX Pluggable Users Module Additions for SugarCRM Introduction / The SugarCRM way When developing new modules for SugarCRM, a frequent requirement is to provide per-user customizations for the new module, e.g. login credentials for some external enterprise resource. However, customizing SugarCRMs Users module turns out to be painful, simply because the Users module was not designed to be customization friendly! An approach chosen by some module writers (most notably YAAI, where we @ abcona e.K. were somewhat involved, see http://www.sugarforge.org/projects/yaai/ is to OVERWRITE some core files in SugarCRMs Users module, providing logic for displaying and editing custom fields. For instance, in YAAI we used to overwrite DetailView.{php,html},EditView.{php,html} and Save.php. Obviously, this solution is rather ugly, as it involves creating a new patch release for every SugarCRM update1, and it doesn't scale well: have two modules using this approach and you are busted. (The YAAI manual has some elaborations on that topic). Rumours are there will be a rewritten Users module for SugarCRM 6, but we needed a more modular solution for SugarCRM 5.2 NOW! To the rescue / The Alfredo way To provide an plug-in mechanism for the Users module, we make extensive use of Alfredo Patch and jQuery. By using jQuerys magic powers, we dynamically extend the Users module functionality WITHOUT ALTERING A SINGLE FILE in that module. A basic understanding of jQuery and Alfredo Patch is thus helpful to understand the following walkthrough. We'll outline only the basic control flow and the most important statements, so you should use PUMEX source file as reference. custom/modules/Users/Ext/javascript/Alfredo-ext.php This is the entry point into the extension mechanism and invoked from Alfredo Patch. Alfredo- ext.php takes care of including the required jQuery libraries, and then includes, depending on the current request's action parameter, either - DetailView-ext.js or - EditView-ext.js 1 And one good thing about SugarCRM is that the hard-working guys at SugarCRM, Inc. provide maintenance releases on a frequent schedule.
  • 2. custom/modules/Users/Ext/Alfredo/DetailView-ext.js This is the snippet of jQuery code that extends the Users module DetailView page. Essentially, it uses jQuery magic to insert some <div> into the DOM tree and then uses an AJAX call to fetch the extended DetailView. Typically for jQuery, this is very compact code: jQuery(document).ready(function() { // Extract user id from form data var userId = jQuery(':input[name=record]').val(); jQuery('#subpanel_list').before('<div id="Alfredo_Extension_Point"></div>'); jQuery('#Alfredo_Extension_Point').load('index.php? module=Users&entryPoint=extend_detail_view&record=' + userId); }); Please note the use of SugarCRM's entryPoint mechanism; the actual mapping from entryPoints to executed scripts is defined in entry_point_registry.php. custom/modules/Users/Ext/Alfredo/ajax/ExtendDetailView.php This is the server-side AJAX script which creates the additional HTML to display custom parameters in the DetailView. Basically, it sets up a SugarSmarty template and then renders an arbitrary number of DetailView.tpl templates found at a well-known location: $sugar_smarty = new Sugar_Smarty(); $sugar_smarty->assign('MOD', $mod_strings); $sugar_smarty->assign('APP', $app_strings); $sugar_smarty->assign('APP_LIST', $app_list_strings); $sugar_smarty->assign('USER', $cUser); foreach (glob("custom/modules/Users/Ext/Alfredo.Ext.Dir/*") as $extDir) { if (is_dir($extDir)) { $GLOBALS['log']->fatal("Using extensions from $extDir"); $sugar_smarty->display($extDir . '/DetailView.tpl'); } } Please note that all the custom properties for User are automagically set up by the SugarCRM framework, and thus available through the $cUser variable (resp. {$USER->....} in the templates).
  • 3. custom/modules/Users/Ext/Alfredo/EditView-ext.js This is somewhat similar to the DetailView case, again we use jQuery magic to modify the DOM tree: jQuery(document).ready(function() { // Insert extension point into main form... var mainForm = jQuery('#EditView'); var userId = jQuery(':input[name=record]', mainForm).val(); mainForm.find("div[id]:last").after('<div id="Alfredo_Extension_Point"></div>'); // Then use AJAX wizardry to load extended settings jQuery('#Alfredo_Extension_Point').load('index.php? module=Users&entryPoint=extend_edit_view&record=' + userId); // // Finally, hook into sumbit handler // Intercept standard 'Save' action with own // mainForm.submit(function(e) { var currentAction = jQuery(':input[name=action]', this); if (currentAction.val() == 'Save') { currentAction.val('AlfredoDispatch'); } var action = jQuery(':input[name=action]', this).val(); return true; }); }); However, this time we also changed the forms action from the customary Save into AlfredoDispatch! By using this trick, we may safely intercept the EditView's save action without actually touching Save.php. custom/modules/Users/AlfredoDispatch.php This is the modified save action for the Users module EditView form. To perform its duties, we first do a loopback call into Save.php, using PHPs curl library: $curlHandle = curl_init($loopbackURL); … curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $encodedArgs); … $curlResult = curl_exec($curlHandle);
  • 4. $httpRC = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE); … On success of the save action, an instance of the User bean is instantiated and passed to all custom save actions, using the same globbing mechanism we have seen before: $focus = new User(); $id = isset ($_POST['record']) ? $_POST['record'] : $continuationArgs['record']; $focus->retrieve($id); $log->fatal('_________________ @ ' . __FILE__); $log->fatal(" Retrieved User bean for id=$id"); // // Gather extended save actions // foreach (glob("custom/modules/Users/Ext/Alfredo.Ext.Dir/*") as $extDir) { if (is_dir($extDir)) { $extSaveFile = $extDir . "/save_params.php"; if (file_exists($extSaveFile)) { $log->fatal(" Using extended save action: $extSaveFile"); $rc = include($extSaveFile); $log->fatal('_________________ @ ' . __FILE__); $log->fatal(" rc:$rc"); } } } $focus->save(); Finally, the updated bean is again persisted to save our changes.
  • 5. Tutorial: Alfredofying the YAAI module As mentioned in the introduction, YAAI used to use the ill-fated approach of overwriting SugarCRMs core files for customization of the Users module. Now, with PUMEX in our toolchest, it should be easy to cure that! Let's get started: Creating the extension folder Remember? We need a folder, containing exactly 3 files, that will become our PUMEX extension. We'll gonna create them at the root level of my modules source folder: We'll leave the content of the files empty now, they are filled with live soon.... Surely I dont forget to add the new files to manifest.php:
  • 6. Fixing the DetailView To augment the DetailView in the Users module, we previously had to overwrite DetailView.php and DetailView.html, where DetailView.html is really a Xtemplate template (sic). DetailView.php takes care of setting the templates parameters from the User bean, thus we had to copy&paste this snippet of code somewhere inside DetailView.php: Likewise, we had to extend DetailView.html to show YAAI's custom parameters: With Alfredo PUMEX, we can neatly replace that cut&paste approach by putting the template code in DetailView.tpl. Unfortunately, we cannot simply copy this code, as the Users module uses the legacy Xtemplate library, while Alfredo uses the newer Smarty templates, also favored by
  • 7. SugarCRM. Thus, our new DetailView.tpl will finally look like this: <p> <!-- Asterisk refactored --> <table width="100%" border="0" cellspacing="0" cellpadding="0" class="tabDetailView"> <tr> <th align="left" class="tabDetailViewDL" colspan="3" width="100%"> <h4 class="tabDetailViewDL">{$MOD.LBL_ASTERISK_OPTIONS_TITLE}</h4> </th> </tr> <tr> <td class="tabDetailViewDL" style="width: 15%">{$MOD.LBL_ASTERISK_EXT}</td> <td class="tabDetailViewDF" style="width: 15%">{$USER->asterisk_ext_c}</td> <td class="tabDetailViewDF">{$MOD.LBL_ASTERISK_EXT_DESC}</td> </tr> <tr> <td class="tabDetailViewDL">{$MOD.LBL_ASTERISK_INBOUND}</td> <td class="tabDetailViewDF"><input class="checkbox" type="checkbox" disabled {if $USER->asterisk_inbound_c}checked{/if}/></td> <td class="tabDetailViewDF">{$MOD.LBL_ASTERISK_INBOUND_DESC}</td> </tr> <tr> <td class="tabDetailViewDL">{$MOD.LBL_ASTERISK_OUTBOUND}</td> <td class="tabDetailViewDF"><input class="checkbox" type="checkbox" disabled {if $USER->asterisk_outbound_c}checked{/if}/></td> <td class="tabDetailViewDF">{$MOD.LBL_ASTERISK_OUTBOUND_DESC}</td> </tr> </table> </p> There are a few points worth noting: • There is no counterpart for the olde DetailView.php! The setup of template variables is automagically done by PUMEX; notably we have the standard variables in the templates scope: $USER Focused user $MOD Module strings $APP Application strings Also the necessary translation from config values (0,1) to HTML 'checked' attribute is no done in the template. • Note the different Syntax for $USER (An User Object) and $MOD/$APP (plain arrays). Fixing the EditView This is very similar to the DetailView case, however this time we have to write a little snippet of
  • 8. code to save our custom settings. Again, let's start with the template code we have in EditView.html: Translated in Smartyspeak this becomes <div id="asterisk"> <table width="100%" border="0" cellspacing="0" cellpadding="0" class="tabForm"> <tr> <th align="left" class="dataLabel" colspan="3"> <h4 class="dataLabel">{$MOD.LBL_ASTERISK_OPTIONS_TITLE}</h4> </th> </tr> <tr> <td width="15%" class="dataLabel" valign="top"><slot>{$MOD.LBL_ASTERISK_EXT}</slot></td> <td width="15%" class="dataField"><slot><input type="text" tabindex='3' name="asterisk_ext_c" value="{$USER->asterisk_ext_c}" size="3"></slot></td> <td class="dataField"><slot>{$MOD.LBL_ASTERISK_EXT_DESC}</slot></td> </tr> <tr> <td class="dataLabel" valign="top"><slot>{$MOD.LBL_ASTERISK_INBOUND}</slot></td> <td class="dataField"><slot><input type="checkbox" tabindex='3' name="asterisk_inbound_c" value="1" {if $USER->asterisk_inbound_c}checked{/if}></slot></td> <td class="dataField"><slot>{$MOD.LBL_ASTERISK_INBOUND_DESC}</slot></td> </tr> <tr> <td class="dataLabel" valign="top"><slot>{$MOD.LBL_ASTERISK_OUTBOUND}</slot></td> <td class="dataField"><slot><input type="checkbox" tabindex='3' name="asterisk_outbound_c" value="1" {if $USER->asterisk_outbound_c}checked{/if}></slot></td> <td class="dataField"><slot>{$MOD.LBL_ASTERISK_OUTBOUND_DESC}</slot></td> </tr> </table> </div> No big surprises here, the most important difference is that the checkboxes are now enabled...
  • 9. We need to make a final move to deal with the checkboxes, though. Put this in save_params.php to translate the values passed for the checkboxes into {0,1} values: <?php global $log; $log->fatal('_________________ @ ' . __FILE__); $log->fatal('Working with User bean:' . $focus->id); $focus->asterisk_inbound_c = (isset($_REQUEST['asterisk_inbound_c']) && $_REQUEST['asterisk_inbound_c']) ? 1 : 0; $focus->asterisk_outbound_c = (isset($_REQUEST['asterisk_outbound_c']) && $_REQUEST['asterisk_outbound_c']) ? 1 : 0; return 0; ?> Replacing the logic hook YAAI uses a logic hook to inject Javascript code into all of SugarCRMs generated pages. Here is the hooks' code which conditionally emits some Javascript: function echoJavaScript($event,$arguments){ // asterisk hack: include ajax callbacks in every sugar page except ajax requests: if(empty($_REQUEST["to_pdf"])){ if(isset($GLOBALS['current_user']->asterisk_ext_c) && ($GLOBALS['current_user']- >asterisk_ext_c != '') && (($GLOBALS['current_user']->asterisk_inbound_c == '1') || ($GLOBALS['current_user']->asterisk_outbound_c == '1'))){ echo '<script type="text/javascript" src="include/javascript/jquery/jquery.pack.js"></script>'; echo '<link rel="stylesheet" type="text/css" media="all" href="modules/Asterisk/include/asterisk.css">'; if($GLOBALS['current_user']->asterisk_inbound_c == '1') echo '<script type="text/javascript" src="modules/Asterisk/include/javascript/dialin.js"></script>'; if($GLOBALS['current_user']->asterisk_outbound_c == '1') echo '<script type="text/javascript" src="modules/Asterisk/include/javascript/dialout.js"></script>'; } } } Of course we want to use Alfredo Patch for that! So we need to drop an include file for Alfredo Patch into its global extension folder at custom/application/Ext/javascript/ . Lets call it YAAI- ext.php:
  • 10. And its content is as simple as this: <?php require_once 'custom/include/javascript/jquery/1.3/include-core.php'; echo "<link rel='stylesheet' type='text/css' media='all' href='modules/Asterisk/include/asterisk.css'>n"; ?> Remember to use require_once(), if at all possible to avoid duplicate inclusion of Javascript code! Again, we add this new file to manifest.php: And we're done!
  • 11. Conclusion Using Alfredo Patch and Alfredo PUMEX, we can easily extend the Users module in a pluggable and modular fashion. Extending is as easy as writing 2 template and one PHP file, which are dropped at some well known location. Currently, Alfredo Connector and the forthcoming Version 2.0 of the YAAI SugarCRM-Asterisk connector use this technique, but hopefully the Alfredo approach is useful to other SugarCRM module writers too..... Copyright Alfredo source files and documentation are © abcona e.K (www.abcona.de) and released to the public under the terms of the GNU Public License, Version 3.