Skip navigation
All Places > Developer > Blog > Author: Matt Marum
1 2 3 4 5 Previous Next

Developer

112 Posts authored by: Matt Marum Employee

Here are a couple more UnCon promo videos from SugarCRM's remarkable technical teams.

 

First off, we have a video Nick Rose, an experienced solutions architect, and also the Director of Solutions Consulting in the Americas. Come to UnCon and check out Nick's session on the Understanding the Sugar Platform.

 

 

Next, we have the brilliant and humble Robert Gonzalez, Software Engineering Manager on the Product team. You can bet that his tutorial at UnCon will be truly remarkable!

 

 

Stay tuned for more videos from the UnCon team!Register for SugarCon today!

Are you learning about Sugar for the first time?  Or maybe, it has been a while, and you want to see how the Sugar platform has evolved since the Community Edition days?

 

Watch the video below to learn why SugarCon and UnCon is the perfect way to get started with building on and integrating with Sugar.

 

An Advanced Workflow process can only be triggered once per PHP process or HTTP request. This is intended to prevent Sugar Administrators from defining infinitely looping processes. (A real catastrophe!) But what does this mean for PHP customizations?

 

Assume that you have an Advanced Workflow process enabled for the Contacts module that performs an update on this Contact each time it is saved. If you have an Accounts after_save logic hook that performs an update on each related Contact SugarBean then the process will only run against the first related Contact. Any other related Contact that gets saved during your logic hook execution will not have a process run.

 

This affects not just logic hooks but any other class of PHP customization such as custom API endpoints or jobs.

 

Workaround

 

If you really need to run that process more than once in the same request, here is a workaround:

use Sugarcrm\Sugarcrm\ProcessManager\Registry;

...

Registry\Registry::getInstance()->drop('triggered_starts');

Calling this method will clear the internal Advanced Workflow registry that keeps track of the triggered process starts. After calling this method, the same process can then be triggered again inside the same PHP process or HTTP request.

 

Careful use of this method can make sure that PHP customizations play nicely with processes defined in Advanced Workflow.

Want to make sure you are included in upcoming Developer Webinars, Newsletters, and other developer updates straight from SugarCRM? Don't miss out. Sign up to get Sugar Developer News today!
You may have noticed that we made changes to Sugar University over the past few months. We introduced new online role based learning pathways for Administrators, Developers, and Solution Architects. This will help you locate the training you need to get your job done and hone the skills you need to be certified. All the online learning pathways are free!

 

We have also added some classes to the calendar that Sugar Developers should definitely check out!

 

New Virtual Classes

 

We have introduced a new form of training called a Virtual Class. This is a short form of live training on specific topics that can last anywhere from 2 to 4 hours. The cost for these shorter forms of classes have been adjusted accordingly.

 

Most of the classes are focused on Sugar Administrator topics today like Sugar Studio, Sugar Logic, Record & Module Level Security, and Advanced Workflow. A firm understanding of Sugar Administration capabilities is an important skill for a Sugar Developer and I think these classes are an easy and cost effective way to refresh and advance these skills.

 

Upcoming Live Sugar Developer Training

 

Make sure you take advantage of these multi-day live training opportunities for Sugar Developers at any level. These classes are being run the week of August 14th at SugarCRM headquarters in Cupertino, CA.

 

Get trained and certified at SugarCon!

 

If you are coming to SugarCon then you should not overlook the opportunity to get trained and certified!

 

When you register for SugarCon, make sure to include the Training option. We will be providing special 1-day versions of the Sugar Development Essentials and Advanced classes on Monday, September 25th at the Hilton Union Square in San Francisco, CA.

 

Getting trained on Monday will ensure they are primed and ready to get hands on with SugarCRM Engineers and fellow Sugar Developers at UnCon on Tuesday and Wednesday! It is also a great way to help practice for Sugar Developer and Solution Architect certification exams. Exams are offered for free on Monday afternoon and Thursday morning of SugarCon. See the full SugarCon agenda for more details.

 

I hope to see you there!

Note from the SugarCRM team

 

This post represents an individual customer's experience with using CloudFlare CDN. The results are pretty exciting! But here is a word of warning.

 

SugarCRM does not officially support use of a Content Delivery Networks (CDNs). CDNs alter the behavior and content of HTTP requests which can cause bugs and prevent the propagation of administrative (ex. Studio) and code changes. The author has provided a process that works for them but may not work for everyone.

 

Sugar Support will not help you with CDN configuration. If you run into problems with Sugar using a CDN that you cannot resolve on your own then you should discontinue use of the CDN.

The following post was written by Sugar Customer Mark Anderson. It was originally posted on his personal blog and is reproduced here in a lightly edited form.

 

The CloudFlare content delivery network (CDN) is an inexpensive but powerful way to optimize the performance of a Sugar on-premise deployment. This post looks at how a free CloudFlare account could double the performance of a Sugar On-Site instance.

 

The experiment started with a review of the performance of a Sugar deployment, using GTMetrix to establish baseline performance. The ultimate goal was to improve performance. We wanted to explore all options since our initial assumption was that better performance would require a costly server upgrade.

 

Step 1: Establish Baseline Performance

 

GTMetrix is a fantastic online tool for measuring the performance of a website. It lets you test a page from a number of servers spread across the world (Dallas, Hong Kong, London, Mumbai, Sydney, Sao Paulo and Vancouver) in any one of Firefox, Chrome Desktop or Chrome Mobile. It then presents you with both PageSpeed and YSlow scores and offers suggestions on how a page can be optimized.

 

 

 

Setting up the test in GTMetrix is straightforward but a little more complex than testing a simple web page that is accessible by the public. The first step is to click the small gray "Analysis Options" button, just underneath the larger blue "Analyze" button on the right hand side.

 

The URL is the page you want to test, in this case the list view of the Sugar Accounts module. The location setting is important, different locations will perform very differently so you likely want to test from a few (but make sure you only compare results from the same location).

 

Unless your Sugar users are working with a particular browser the most important thing is to perform all tests using the same browser (the "Using" setting) so you can compare results.

 

For this test it is also essential that you enter a valid username and password so that GTMetrix can log into the account.

 

So... mixed results:Bad News

  • The tests where it does poorly (gzip compression, minifying HTML, etc) it does really poorly.
Good News
  • Sugar gets great scores on most of the tests!
  • It is likely that CloudFlare (if it works) can make huge performance improvements.

 

More tests of other Sugar pages from different locations show similar results.

 

We have had great results using CloudFlare with our public facing sites but had never considered using it with our Sugar instance. The test results suggest a CDN like CloudFlare could greatly improve Sugar performance, but there was no supporting information available on the internet and so we had no expectation it would work.

 

Step 2: Enable CloudFlare

 

Our next step was to enable CloudFlare for the Sugar On-Site instance. In our case this was very easy because Sugar is hosted on a sub-domain of a domain that is already set up in CloudFlare. We just have to turn CloudFlare on in the DNS section of the CloudFlare admin page for that domain.

 

When a subdomain is not enabled in CloudFlare it looks like this:

 

Just click on the cloud icon and it will change color like this...

 

... indicating that CloudFlare is now providing both DNS and HTTP proxy for that sub-domain.

 

If you are setting up CloudFlare for the first time for a new domain it will be slightly more work but manageable and absolutely worth it for the performance gains.

 

Step 3: Wait...

 

Having made changes to the DNS settings we now needed to wait for them to propagate. This usually takes less than 10 minutes.

 

Step 4: Debug

 

In our case we knew that the DNS settings had propagated because our Sugar instance stopped working – no Sugar pages were available – and we were worried that using CloudFlare was not working.

 

Fortunately an excellent technician caught the problem! This particular Sugar instance used a non-standard port for HTTP traffic. This port was one that CloudFlare does not support.

 

It turns out CloudFlare can only proxy traffic going over specific ports. The supported ports are listed below.

HTTPHTTPS
80443
80802053
88802083
20522087
20822096
20868443
2095

 

The fix was relatively simple; we just changed the Sugar instance to use a supported port.

 

It is not likely you will encounter this issue but if you do lose access to your Sugar instance after enabling CloudFlare then this is a good place to start looking – just make sure that you are using the supported ports.

 

After making the change... success! We were able to again access Sugar but through the CloudFlare content delivery network.

 

Step 5: CloudFlare Settings

 

One of the great things about CloudFlare is that it takes very little tweaking to get great results. But there are a few settings that you should confirm.

 

Start in the Speed settings of CloudFlare admin for the domain:

 

Remember that a big part of the problem in the initial GTMetrix report was minification, so make sure all three of these are checked.

 

Farther down the Speed page are the settings for the Rocket Loader feature. They should look like this:

 

Next up are the caching settings (choose "Caching" from the icons arranged across the top of the CloudFlare dashboard...

 

The Caching Level should be set to standard but the really important setting here is Browser Cache Expiration. Try setting it for 1 day.

 

That's it for CloudFlare settings.

 

Step 6: Initial Testing

 

The next step was to use Sugar, clicking to navigate between modules, to test the application and make sure that everything worked as expected.

 

Some improvements, like magnification and gzip, were experienced right away but there was some mystery about how CloudFlare actually builds the cache. We assumed that using the CRM application like this encouraged CloudFlare to fill up the cache. We also used a proxy service to browse the instance from other locations to help propagate the changes to other CloudFlare servers.

 

This may not have been needed but we were only testing and very little effort was required to test from different geographical locations.

 

Step 7: Performance Testing

 

Now the interesting part – we looked to see what (if any) performance gains we had accomplished. We did all the same tests again in GTMetrix and compared the results. The old test, before CloudFlare, appear at the top of the list and the newer results appear at the bottom.

 

The improvements are remarkable! PageSpeed scores go from straight F's at 26% to straight A's at 99%. YSlow scores improve from straight B's at 85% to straight A's at 98%.

 

The times are even more interesting than the scores:

TestBefore CloudFlareAfter CloudFlareTime saved (s)Savings (%)Increase
Home (CA)2.7s1.3s1.4s52%2.08x
Home (UK)2.5s1.6s0.9s36%1.56x
Home (US)2.5s1.1s1.4s56%2.27x
Account List (AU)5.0s3.2s1.8s36%1.56x
Account List (UK)4.2s1.6s2.6s62%2.63x
Account List (US)1.7s1.1s0.6s35%1.55x
Account Record (AU)5.4s3.2s2.2s41%1.69x
Account Record (CA)2.5s1.3s1.2s48%1.92x
Account Record (UK)4.2s3.0s1.2s29%1.40x
Account Record (US)1.6s1.2s0.4s25%1.33x
Total Time32.3s18.6s13.7s
Averages3.23s1.86s1.37s42%1.74x

 

Highlights:

  • Average page load time was reduced by almost 50% (over 1 second)
  • Speed increased an average of 1.74x after introducing CloudFlare CDN
  • Best gain was a saving of 2.6 seconds for a 2.63x increase in speed
  • Smallest gain was still just under half a second for 25% savings

 

It is also worth using a great feature in GTMetrix that lets you compare two or more reports. Here it is used to compare the before and after performance of the Sugar home page from Dallas TX. This is likely the most relevant test in our case – most users are in the US and this is the first page they load each day.

 

Propagating Sugar changes to the CDN

 

A variety of changes on the server side can require the CDN to be purged to ensure changes are propagated to clients. For example, most changes done via the Administration panel like Sugar Studio or the deployment of code customizations like a new Sugar Dashlet or integration package will require caches to be purged.

 

We generally do any work in a development instance on a subdomain that does not use the the CDN feature in CloudFlare. This can be easily configured in the CloudFlare DNS settings, you just click the orange cloud for the A record associated with the specific sub-domain and when it turns grey then that indicates the CDN is disabled.

 

When making changes to the production instance, we just flip CloudFlare into development mode (in Quick Actions on Overview panel), which turns off the CDN and any caching temporarily. We can then deploy our changes to the Sugar application. The CDN remains off until you manually turn it back on or two hours pass. Either way caches are rebuilt when the CDN comes back on.

 

If we expect development work to take any more than thirty minutes then we completely disable the CDN for the production subdomain until we are ready.

 

If there are any lingering doubts, then we go to Caching > Purge > Purge Everything.

 

Conclusions

 

There were significant improvements in every single test and overall performance nearly doubled. This is a great result especially when the minimal costs are considered.

 

What were the costs? Making the change, debugging the port issue and all of the testing and reporting took us under three hours. In this case a CloudFlare Pro plan ($20/mo) was already in place for the domain, so there was absolutely no additional cost incurred there.

 

If you don't have CloudFlare already, then the free CloudFlare starter plan could provide the same benefit.All in all this was a great investment for us, we significantly improved the speed and performance of our Sugar on-site instance at very little cost.

Where will you be on September 26th at 1:00pm Pacific Time? If you are a Sugar Developer then you better be in San Francisco, the City By the Bay, at the Hilton Union Square!

 

The annual UnCon is the top rated event at SugarCon because of the in-depth technical content, knowledgable speakers, and our enthusiastic developer and admin community.  This is a unique event where you get an incredible level of access to the development teams and decision makers that build our products and platforms.

 

Essential to the success of UnCon is input from the Sugar Developer and Administrator community! We are just over 90 days away so planning is well underway. Now is the time to provide your input on the content presented at UnCon.

 

Please fill out this very short on question survey. This will help us focus the event on the types of content that you want to see.

 

UnCon 2017 Theme Survey

 

 

Fill out the UnCon 2017 Theme Survey!

 

 

 

UnCon will be bigger than ever

 

We will be growing UnCon massively this year with a longer running time, more activities, and more space than ever before. This will allow you more time with the SugarCRM experts in Product Engineering, Product Manage

 

ment, and other technical staff from across the company.

 

Never attended before?

 

Check out the UnCon archive where you can find all the available content from the last two years. Some popular past presentations and workshops have been on topics ranging from introductory sessions on debugging Sugar, Elasticsearch, Sugar CLI, and Mobile SDK to deep dives into Sidecar and Advanced Workflow. All those topics and more can be found in the archive.

 

Other ways to get involved

  1. RSVP to the event in the UnCon community to let everyone know you will be there. Separate registration to SugarCon is required to attend.
  2. Share additional feedback in the UnCon community as discussions or ideas.
  3. Stay tuned for more updates! Follow the UnCon space in the Sugar Community.

 

See you in San Francisco!



You may have seen that that Sugar 7.9 has now been released! We have moved the Quotes module and Reports list view to Sidecar framework. We've also made plenty of platform enhancements such as adding prepared statements support.

 



 

Quotes Module Developer Guide

 

We have created an all new Quotes section in the Sugar 7.9 Developer Guide that is designed to address common customizations that Sugar Developers make to the Quotes module.

 

Sugar 7.9 Migration Guide

 

The Migration Guide for Sugar 7.9 is an essential resource for any Sugar Developer upgrading a customer from Sugar 7.8.x. The guide will help you identify code and platform changes that you need to make in order to ensure that you can upgrade your code and customers successfully.

 

Sugar 7.9 Unit Tests

 

The Sugar Unit Tests repository has been updated with unit tests for Sugar 7.9. This is the same test suite that the product team used in developing Sugar 7.9. Remember that you need to sign up for access to the Sugar test repositories.

 

Sugar 7.9 Overview for Sugar Developers

 

We delivered a recorded webinar that will be shortly available in the Developer space in the Sugar Community. This is a great way to get immediate understanding about all the new features and platform changes that were introduced in Sugar 7.9. The presentation slides will also be posted in the Developer community shortly.

What are Prepared Statements?

Prepared Statements, also known as parameterized statements, is a database feature that allows the same or similar queries to be executed with more efficiency and greater security. It has also been a common Sugar platform feature request for some time.

 

A prepared statement looks something like this:

SELECT * FROM table WHERE id = ?

 

As you can see, a prepared statement is basically a SQL template that allows you to identify parameters that can be bound later. The database engine can parse, optimize, and cache this statement without executing it.

 

This reduces the overhead associated with parsing complex queries that are used frequently by applications like Sugar. For example, you can imagine that List View queries would benefit from prepared statements since they are often complex and executed each time a list is displayed, searched, filtered, or paginated. With prepared statements, the database will do less work each time one of these actions is repeated.

 

Another key strength of prepared statements is that it helps prevent SQL injection vulnerabilities. Parameters are expected to be constant values (strings, integers, etc.) and not SQL. So if an attacker managed to bind raw SQL as a parameter to a prepared statement it will not be interpreted as SQL. Attack defeated!

 

Database Administrators (DBAs) like prepared statements too because it tends to give them more control over how these queries are executed and cached by backend database engines. In the hands of a good DBA, prepared statements allows an application to be better tuned for high performance.

 

Changes in Sugar 7.9.0

 

Sugar 7.9.0 will be available in the next few weeks at the time of this writing. In Sugar 7.9.0, most queries that Sugar executes are now parameterized. Some new Query APIs have been added to support prepared statements as well.

 

The most important change is that we have adopted parts of Doctrine's Database Abstraction Layer, especially the QueryBuilder class, for working with prepared statements.

 

DBManager

The DBManager class will use Doctrine QueryBuilder for building INSERT and UPDATE queries.

 

SugarQuery

The SugarQuery class will use Doctrine QueryBuilder for building SELECT queries.

 

SugarBean

The SugarBean class will continue to use DBManager class for saving all fields.

 

Things to watch out for in Sugar 7.9.0

 

There are a few things that Sugar Developers need to know as they prepare their code customizations for Sugar 7.9.0.

 

DBManager and SugarQuery API changes

 

As documented in the Sugar 7.7.1 Release Notes, many DBManager APIs and some SugarQuery APIs were deprecated as part of our plans to add prepared statement support to Sugar. These deprecated APIs have been removed in Sugar 7.9.0. If you haven't already, you must migrate your custom code that uses these APIs to alternative APIs prior to Sugar 7.9.0 upgrades.

 

The following deprecated PHP classes and methods have been removed in this Sugar release.

SugarQuery_Builder_Delete

 

SugarQuery_Builder_Insert

 

SugarQuery_Builder_Update

 

SugarQuery_Builder_Literal

 

SugarQuery_Compiler

 

SugarQuery::joinRaw()

 

SugarQuery::compileSql()

 

DBManager::delete()

 

DBManager::retrieve()

 

DBManager::insertSQL()

 

DBManager::updateSQL()

 

DBManager::deleteSQL()

 

DBManager::retrieveSQL()

 

DBManager::preparedQuery()

 

DBManager::pQuery()

 

DBManager::prepareQuery()

 

DBManager::prepareTypeData()

 

DBManager::prepareStatement()

 

The $execute parameter on DBManager::insertParams() and DBManager::updateParams() has also been removed.

 

SugarQuery::compileSql()

SugarQuery::compileSql() was commonly used to debug the raw SQL built using SugarQuery APIs. SugarQuery::compileSql() was deprecated in Sugar 7.7.x and is no longer supported in Sugar 7.9.0. Because SugarQuery now uses prepared statements, it no longer compiles a complete SQL statement by itself. Remember that parameterized queries are assembled and executed within the DB engine. So you will need to separately fetch the parameterized SQL and the parameters. From this information, you can determine how the query will be executed.

For example,

 

 

 

$compiled = $query->compile(); // create compiled prepared statement

 

$compiled->getSQL(); // fetches parameterized SQL

 

$compiled->getParameters(); // fetches parameters

 

 

The $compiled->getSQL() will return SQL with placeholders instead of parameters:

SELECT * FROM users WHERE id=?

The $compiled->getParameters() will return an array of parameters:

['ec2f4abb-b6b9-3d49-0382-5730e67c116c']

 

How to use Prepared Statements in Sugar 7.9.0

If you already use SugarQuery or SugarBean then congratulations! Your code customizations will automatically benefit from prepared statements. We have made changes to both of these interfaces to ensure that they use prepared statements. The underlying behavior is transparent to custom code.

 

However, if you need more finesse with your queries then we will explore how to use prepared statements using new DBManager and Doctrine QueryBuilder APIs.

 

SELECT queries

 

For simple static SELECT queries, the changes are pretty straight forward.Before:

 

 

 

$query = 'SELECT * FROM table WHERE id = ' . $this->db->quoted($id);

 

$db->query($query);

 

 

After:

 

 

 

$query = 'SELECT * FROM table WHERE id = ?';

 

$conn = $db->getConnection();

 

$stmt = $conn->executeQuery($query, array($id));

 

 

 

In the case that query logic is variable or conditionally built then it makes sense to use Doctrine QueryBuilder directly.Before:

 

 

 

$query = 'SELECT * FROM table';

 

if ($status !== null) {

 

   $query .= ' WHERE status = ' . $this->db->quoted($status);

 

}

 

$db->query($query);

 

 

After:

 

 

 

$builder = $db->getConnection()->createQueryBuilder();

 

$builder->select('*')->from('table');

 

if ($status !== null) {

 

   $builder->where(

 

       'status = ' . $builder->createPositionalParameter($status))

 

   );

 

}

 

$builder->execute();

 

 

 

INSERT queries

 

INSERT queries can be easily performed using DBManager class.Before:

 

 

 

$query = 'INSERT INTO table (foo, bar) VALUES ("foo", "bar")';

 

$db->query($query);

 

 

 

After:

 

 

 

$fieldDefs = $GLOBALS['dictionary']['table']['fields'];

 

$db->insertParams('table', $fieldDefs, array(

 

   'foo' => 'foo',

 

   'bar' => 'bar',

 

));

 

 

 

UPDATE queries

When updating records with known IDs or a set of records with simple filtering criteria, then DBManager can be used:Before:

 

 

 

$query = 'UPDATE table SET foo = "bar" WHERE id = ' . $db->quoted($id);

 

$db->query($query);

 

 

After:

 

 

 

$fieldDefs = $GLOBALS['dictionary']['table']['fields'];

 

$db->updateParams('table', $fieldDefs, array(

 

'foo' => 'bar',

 

), array(

 

'id' => $id,

 

), );

 

 

 

For more complex criteria or when column values contain expressions or references to other fields in the table then Doctrine QueryBuilder can be used.Before:

 

 

 

$query = 'UPDATE table SET foo = "bar" WHERE foo = "foo" OR foo IS NULL';

 

$db->execute($query);

 

 

After:

 

 

 

$query = 'UPDATE table SET foo = ? WHERE foo = ? OR foo IS NULL';

 

$conn = $db->getConnection();

 

$stmt = $conn->executeQuery($query, array('bar', 'foo'));

 

 

SugarCRM recently released versions 4.1.0 and 5.0.0 of SugarCRM Mobile and version 1.2.0 of the Mobile Application Configurator Service (MACS). These releases represent a significant technology evolution for our Mobile products that is worthy of a summary of the benefits to the Sugar Developer community.

 

Even more exciting, we are also getting tantalizingly close to general availability for the SugarCRM Mobile SDK!

 

Enhanced Offline mode in SugarCRM Mobile 4.1.0

 

Who likes waiting? Nobody! Well our previous offline storage would make the user wait after login while the app would download records so they were available offline. We did not want users waiting too long so we limited the offline storage to a modest 100 records per module. This allowed the Mobile app to be available to users quickly but not instantly.

 

This changed with SugarCRM Mobile 4.1.0 because we improved how offline record storage works CRM records are now (asynchronously) downloaded into offline storage behind the scenes whenever the Mobile app is in use. This allows the user to be productive with the Mobile app immediately after login even while offline storage is being loaded up. We also increased the offline storage limit to 1000+ records per module because the time taken to download thousands of records over a slow cellular network was no longer a concern.

 

Since we drastically increased the download size, we also added an option to download records over Wifi only. That should help anyone worried about blowing up their data plans!

 

New SugarCRM Mobile UX in 5.0.0!



 

As part of the SugarCRM Mobile 5.0.0 release, we introduced a redesigned user experience. We reduced the number of clicks needed to reach information, for example, by redesigning the record details view to show more information on the initial screen in a Details tab. We also improved navigation and re-ordered tabs and elements in the user interface based upon customer feedback.

 

From administrative perspective, we have added AppConfig standard which makes it easier to manage the app using Enterprise Mobile Management (EMM) solutions. This included the ability to preset Sugar instance URLs to allow for easier deployment of the Mobile app to end users.

 

Mobile 5.0.0 also simplified the login page by moving configuration settings into a separate screen and added support for Apple Touch ID among other changes.

 

Updates to Mobile Application Configuration Service (MACS)

MACS allows Sugar Partners and Customers to create re-branded binaries of the SugarCRM Mobile app that gives them full control over how they distribute and deploy the mobile application.

 

Every time SugarCRM releases a new version of our Mobile app, it is also added to MACS. We also recently added the ability to cancel a build as well as delete old ones. This will help keep your list of built Apps pristine as newer versions of Mobile app are added to MACS.

 

More details on Mobile SDK!

 

We have talked about the Mobile SDK before and I am excited to say that we are making great progress. The SugarCRM Mobile SDK is currently in a limited beta with a few key Sugar Partners and customers and we look forward to making it generally available very soon.

 

The first generally available release of the Mobile SDK will be based on SugarCRM Mobile 5.0.0.

 



 

Some resources you can expect when the Mobile SDK is released is a Getting Started Guide, detailed Mobile API documentation, a Mobile developer community, and eventually a Mobile Styleguide. You will be able to reach all these resources from the same Mobile Tools portal that you use for Mobile Application Configuration Service (MACS).

 

The Mobile Tools portal is available to Sugar Partners and Sugar Enterprise customers. So if that means YOU then watch that space! This will be where you will get your hands on the SDK.

To be honest, I do not get to sling code all that often anymore. But I do spend a lot of time thinking about software even when I have no real hand (or keyboard) in creating it. I also talk to people about software a lot - software design, solution architecture, teams, and development processes. This means my growth today as a software professional comes primarily from the wisdom of others. And this was probably always true.

 

I have started to read more books about software and most recently that meant reading The Pragmatic Programmer. For those who do not know it, it is a classic software engineering book that was released in 1999. In a fast moving industry, what could you possible learn from a 17+ year old technology book? Well if you read it (again) then you may be surprised. The Pragmatic Programmer is not about programming - it is about programming processes, practices, and code craftsmanship. While you may not agree with everything you find in it, some parts feel out of date, it remains overall a very worthy book. I recommend it.

 

Something that books do for me is to put names on some concepts that I acquired from first-hand experience. It has also fully explained others I have known from having heard them tossed over cubicle walls or conference room tables over the years. Terms like Reversibility, Orthogonality, and many others represent concepts that should guide any Sugar Developer who sits down to her daily work of customizing, integrating, and extending the Sugar platform.

 

So in the spirit of The Pragmatic Programmer, here is my take on what some of the lessons taught in the Pragmatic Programmer mean to a Sugar Developer.

For a "cliff notes" version of the Pragmatic Programmer, you can find a quick reference guides and other summaries online.

 

The Pragmatic Sugar Developer

 

This blog post will help you become a better Sugar Developer. Apologies to Andrew Hunt and David Thomas who are the authors of The Pragmatic Programmer.

 

Orthogonality of Sugar customizations

 

The Pragmatic Sugar Developer designs Sugar customizations to be as orthogonal to Sugar core code as possible. Keeping customizations independent and loosely coupled from the Sugar platform means that Sugar version upgrades will rarely introduce side effects or breakages. The reverse is also true, which means the Developer can make changes to her customizations that will not cause side effects or breakages in the Sugar platform either.

 

For example, overriding core Sugar code (like SugarBean.php) using the custom directory to implement a customization is decidedly non-orthogonal with respect to the Sugar platform. Any change in the core file will impact the override. However, customizations implemented using an Extension such as a Logic Hook, a custom Sidecar Dashlet, or using the REST API would be orthogonal to the Sugar platform. As Sugar platform evolves, these orthogonal customizations will be better protected from side effects.

 

Sugar core code and the DRY Principle

 

DRY stands for Don't Repeat Yourself. Every piece of knowledge should have an single, unambiguous, and authoritative representation in the system.

 

This means that a Pragmatic Sugar Developer will not blindly copy and paste core code into the custom directory. Developers should be calling APIs and not copying them. Core code should never be repeated under the custom directory where it will not be updated during upgrades.

 

Reversibility

 

The Pragmatic Sugar Developer knows that customers/stakeholders/management will often change their mind. This means that the Developer will ensure that design decisions are easily reversible in the future. The long term success of her project will likely depend on it.

 

Today, a customer is deploying on MySQL but later they might want to use Oracle instead. That custom chart was in a Sidecar Dashlet today may need to be moved into a custom layout tomorrow. Pragmatic Sugar Developers ensure that the right set of abstractions are in place to minimize the amount of rework associated with these change requests. Any required irreversible (final) decisions are postponed or delayed as long as possible.

 

Deconstruct user workflows to leverage concurrency

 

A Pragmatic Sugar Developer understands how to analyze user workflows and business processes to identify tasks that can be run independently and therefore concurrently. Implementing a giant workflow in one place can easily result in a solution that is a mess. Complex single threaded processes take a long time to run and lock up resources in the mean time like the user's UI, memory, etc.

 

Performance can be improved by scheduling these tasks to be run asynchronously using the Sugar Job Queue or on different web servers for horizontal scaling. Additionally, breaking down a large workflow into independent tasks allows for each of them to be implemented more simply and maintained more easily.

 

Use Sidecar to separate views from models

 

The Pragmatic Sugar Developer understands the difference between the views and models when building Sidecar user interfaces. They create Sidecar Views that focus on representing models in the UI and keeping them synchronized. Sidecar allows Developers to build more flexible and adaptable user interfaces.

 

A Pragmatic Sugar Developer works with the Sidecar framework and not around it in order to drop in foreign frameworks (ex. to incorporate a flavor of the week JavaScript framework) or techniques (ex. fetching Sugar data using jqXHRs instead of using Beans or BeanCollections). Using the native Sidecar framework allows you to minimize complexity and maintain cohesion with the rest of Sugar platform.

 

Design to Test using Sugar Test Tools

 

The Pragmatic Sugar Developer designs her tests before writing any code and includes that additional QA scope in project plans. The Developer also designs her code with the intention to make it easy to test.

 

Pragmatic Sugar Developers benefit from using Sugar Test Tools instead of needing to build new test frameworks from scratch.

 

Dig for requirements for customer success (and your own)

 

Developers know that sometimes customers and stakeholders can provide unreliable or incomplete information. So Pragmatic Sugar Developers do not gather requirements, they dig for them.

 

An experienced Developer knows Sugar better and has done more CRM projects than her customers. She uses her experience to ask lots of questions to test assumptions and uncover new requirements that need to be addressed. Very importantly, customers are often focused on explaining their current systems and processes - Developers should challenge their customers to improve processes and not implement sub-optimal or broken processes on a brand new system.

 

For example, has her customer thought about mobile use cases? Will they want e-mail notifications for certain actions and, if so, what should the e-mail templates look like? Is there customer data outside the CRM today that could be integrated so that users do not need to switch between systems? Is the right data captured in the CRM to support the customer's reporting requirements?

Many customers want to configure Sugar for Single Sign On (SSO). Well Sugar supports Security Assertion Markup Language (SAML) so this must be easy, right? But the devil is always in the details.

 

Each SAML identity provider behaves a little differently. Each of these systems has different terminology and methods for configuration and may use different default settings. Some of these important configuration settings can make the difference between a successful SSO implementation and a tire fire. For example, are users provisioned Just-In-Time or will they be provisioned manually? Did you know that Sugar uses the e-mail address as the SAML application username format?

 

Below are instructions for configuring SAML SSO with a couple of common identity providers.

 

Okta

 

One of our Solution Architects, Enrico Simonetti, wrote a good summary of how to configure SAML authentication for Sugar using Okta as the identity provider. Okta is convenient for trying out SSO because they have a developer program you can join. Enrico also covers a few tips and details that can trip up any SAML implementation.

 

Please visit Enrico's post called SSO Authentication on SugarCRM with SAML for more details including screen shots and even code examples.

 

Active Directory Federation Service

 

The most common system that we get questions about is Microsoft's Active Directory Federation Service (ADFS). ADFS is pretty complicated so there are several steps that you need to follow to get it done right.

 

We recently publish a SugarCRM Knowledge Base article called Configuring SSO With Active Directory's ADFS. It was written by Lars Blockken, one of our Senior Technical Account Managers, and in it he walks you through each of these steps in detail along with screenshots. It will have you up and running on ADFS in no time!

You may have seen that that Sugar 7.8 has now been released! We have introduced some important platform updates in this release. Have you read the developer release notes yet? Here are three additional and essential resources for you to use before you embark on new Sugar 7.8 projects.

 

Sugar 7.8 Migration Guide

 

The Migration Guide for Sugar 7.8 is an essential resource for any Sugar Developer upgrading a customer from Sugar 7.7.x. The guide will help you identify code and platform changes that you need to make in order to ensure that you can upgrade your code and customers successfully.

 

Sugar 7.8 Unit Tests

 

The Sugar Unit Tests repository has been updated with our unit test suites for Sugar 7.8. This is an essential resource for ensuring that your Sugar 7.8 custom code is working correctly and hasn't introduced regressions within Sugar core code. Remember that you need to sign up for access to the Sugar test repositories.

 

Sugar 7.8 Overview for Sugar Developers

 

We delivered a recorded webinar that is now available in the Developer space in the Sugar Community. This is a great way to get immediate understanding about the new platform features and changes that were introduced in Sugar 7.8. The presentation slides are also available in the community.

Important security changes in Sugar 7.8

 

As we near the release of Sugar 7.8, we wanted to update the Sugar Developer community on a couple of important security changes that are coming in this release.

 

The oauth_token URL parameter is disabled by default

 

A convenience feature that allowed an OAuth 2.0 access token to be passed via the oauth_token URL parameter instead of using the OAuth-Token HTTP header is no longer supported in Sugar 7.8. The examples in the Sugar Developer Guide always used the OAuth-Token HTTP header - but a few people had discovered they could pass the oauth_token as a URL parameter on their own.

 

If you have been using it, you should know that this feature has been disabled by default due to security concerns. The practice of passing and accepting session identifiers via URL parameters is against OWASP guidelines.

 

For reference: Session Management Cheat Sheet - OWASPThis example is no longer allowed by default

GET /sugar/rest/v10/Contacts?oauth_token={GUID} HTTP/1.1Host: localhost:8080Content-Type: application/jsonCache-Control: no-cache

This example continues to work and is preferred

GET /sugar/rest/v10/Contacts HTTP/1.1Host: localhost:8080Content-Type: application/jsonOAuth-Token: {GUID}Cache-Control: no-cache

 

If you want to enable this feature again, then you can use a new SugarConfig setting called allow_oauth_via_get. When the config setting is true, this will permit the oauth_token URL parameter to be used to pass access tokens.

$sugar_config['allow_oauth_via_get'] = true;

 

CSRF Tokens are now enforced by default

 

In a previous post on CSRF tokens in Sugar 7.7, we indicated that CSRF authentication would be enabled by default in future Sugar versions.

 

Well in Sugar 7.8, the $sugar_config['csrf']['soft_fail_form'] setting will default to false and the $sugar_config['csrf']['opt_in'] setting has been removed. This means that CSRF tokens are now enabled by default as of Sugar 7.8

 

For more details on Sugar’s CSRF implementation, please review the original post on this blog.

 

HTML forms used in BWC modules need to be authenticated in order to continue to function. If necessary, Sugar Developers can temporarily set the following configuration variable to disable enforcement of CSRF tokens.

$sugar_config['csrf']['soft_fail_form'] = true;

 

The above setting will generate FATAL messages in the sugarcrm.log file whenever a CSRF authentication failure occurs.

 

Sugar Developers and Administrators should resist the temptation to use soft fail mode in production instances.

Sugar's Single Page Architecture

 

Sugar relies on a single page architecture (SPA) for the Sidecar framework. But when a user navigates across the Sugar application (for example, when switching to another Sugar module), while the page is not refreshed, you will find that the majority of the HTML on the page is still re-rendered based upon the newly selected layout. This is done to not only change the style or configuration of the view (ex. List View → Record View) but also to update the context and configuration for the dashboard panel.

 

But not everything changes - the footer and header of the application remain fixed so they can serve as navigational anchors for Sugar users. This is an important use case but there are certainly others.

 

Telephony integration scenarios

 

A common set of integrations that are built for Sugar involve integrating a phone system for use by customer service organizations. This can vary from simple "click to dial" softphone functionality to full blown multi-channel call center capability where an agent handles phone, SMS, and e-mail inquiries at the same time.

 

A typical in-bound call process follows:

 

Step 1) A customer calls support desk with an inquiry

 

Step 2) The call is routed to an available support agent desktop

 

Step 3) The agent desktop displays current customer information

 

Step 4) The service agent handles customer inquiry

 

Step 5) The interaction details are logged to the customer record

 


 

While the call is active, it is typically necessary to have a persistent display of the call's status and caller information. The service agent may need to be able to review CRM data across multiple modules without losing the call's context.

 

This need is not addressed by customizing standard Sidecar Record or List layouts because they aren't fixed. An alternative could be to open a pop-up windows but that is a pretty crappy user experience.

 

There are better alternatives. Users expect to be able to work within the Sugar application and this can be accommodated by adding a floating frame to the Sugar user interface that will serve our needs.

 

Floating Div Action Building Block

 

We have created a package that provides a prescribed pattern for handling persistent content within the Sugar UI using a floating frame. This frame can be configured to iframe web content from an external system or as a basis for a native Sidecar component. There are multiple telephony solutions in the Sugar ecosystem that use variations on this approach.

 

We will dig into some of the code below.

 

Footer contribution via Sidecar Extension

 

We can add the Call button seen in the screenshot above using a Sidecar Extension for a new custom Sidecar View. We will talk about this new click-to-call view (ClickToCallView) later.custom/Extension/application/Ext/clients/base/layouts/footer/addClickToCallAction.php

 

 


<?php

// Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.

//  Append new View to Footer layout's list of components

$viewdefs['base']['layout']['footer']['components'][] = array (
    'view' => 'click-to-call',
);

 

The ClickToCallView toggle button

 

The toggle button that appears in footer is implemented as part of our new custom ClickToCallView within custom/clients/base/views/click-to-call/click-to-call.js and custom/clients/base/views/click-to-call/click-to-call.hbs. Since this Sidecar View is attached to the footer, it will be persistent as the user navigates. We can conveniently use it to manage the lifecycle of our "popup" frame to ensure it is only loaded once. Instead of removing the pop-up frame completely when a user closes it, we will simply hide it from view so that it does not need to be recreated later.

 

 


...

    events: {

        //On click of our "button" element

        'click [data-action=open_phone]': 'togglePopup',

    },

    // tagName attribute is inherited from Backbone.js.

    // We set it to "span" instead of default "div" so that our "button" element is displayed inline.

    tagName: "span",

    // Used to keep track of Popup since it is not attached to this View's DOM

    $popup: undefined,

    /**

     * Toggle the display of the popup.  Called when the phone icon is pressed in the footer of the page.

     */


    togglePopup: function () {

        //Toggle active status on button in footer

        var $button = this.$('[data-action="open_phone"]');

        $button.toggleClass('active');

        //Create popup if necessary, otherwise just toggle the hidden class to hide/show.

        if (!this.$popup) {

            this._createPopup();

        } else {

            this.$popup.toggleClass('hidden');

        }

    },

...

 

 


{{! Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license. }}

{{!

    Define HTML for our new button.  We will mimic the style of other buttons

    in the footer so we remain consistent.

}}

<button data-action="open_phone" class="btn btn-invisible" aria-label="{{str "Call"}}" role="link" type="button">

    <i class="fa fa-phone icon-phone"></i><span class="action-label"> {{str "Call"}}</span>

</button>

 

The floating frame

 

Sugar does not provide a popup frame component out of the box, so we can create one from scratch with our own Handlebars templates for the HTML and necessary CSS. We also use the Draggable jQuery UI plug-in that is already included with Sidecar to allow users to reposition the frame as they want.

 

Our JavaScript code will lazy load in the CSS to the HEAD section of the page and append our popup frame to the main content DIV element when the Call button is toggled the very first time.custom/clients/base/views/click-to-call/click-to-call.js

 

 


...

    /**

     * Used to create Popup as needed. Avoid calling this directly, should only need to be called once.

     * @private

     */


    _createPopup: function () {

        var popupCss = app.template.get("click-to-call.popup-css");

        // We need to load some custom CSS, this is an easy way to do it without having to edit custom.less

        $('head').append(popupCss());

        var popup = app.template.get("click-to-call.popup")(this);

        // Add to main content pane of screen

        $('#sidecar').append(popup);

        this.$popup = $('#sidecar').find('div.cti-popup');

        // Hide pop up on click of X (close button)

        this.$popup.find('[data-action=close]').click(_.bind(this._closePopup, this));

        // Make pop up draggable using existing jQuery UI plug-in

        this.$popup.draggable();

    },

...

custom/clients/base/views/click-to-call/popup.hbs

 

 


{{! Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license. }}

<div class="cti-popup">

<div class="cti-popup-header">

        <strong>CTI Window</strong>

        <a class="cti-close pull-right" data-action="close"><i class="fa fa-times fa-large"></i></a></div>

<div class="cti-popup-content">

        <iframe src="{{meta.iframeSrc}}"></iframe></div>

</div>

custom/clients/base/views/click-to-call/popup-css.hbs

 

 

 

{{! Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license. }}

<style type="text/css">

    .cti-popup {

        position: fixed;

        top: 50%;

        left: 50%;

        z-index: 1050;

        max-height: 500px;

        background-color: #f6f6f6;

        border: 1px solid #cfcfcf;

        *border: 1px solid #999;

        /* IE6-7 */

        -webkit-border-radius: 4px;

        -moz-border-radius: 4px;

        border-radius: 4px;

        -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);

        -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);

        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);

        -webkit-background-clip: padding-box;

        -moz-background-clip: padding-box;

        background-clip: padding-box;

    }

    .cti-popup-header {

        background-color: #f6f6f6;

        padding: 10px 15px;

        border-bottom: 1px solid #f5f5f5;

    }

    .cti-close{

        position: relative;

        top: -2px;

    }

</style>

 

 

 

Full example available in Github

 

You can find the full example as a module loadable package you can build yourself on Github. Just find the Floating Div Action package that is part of the SugarCRM Building Blocks repository. As of today, I have tested this package with Sugar 7.6 and Sugar 7.7.

 

Let me know what you think!