The purpose of this document is to provide insight to Sugar Developers for upgrading custom Sugar code, extensions, and integrations to the Sugar 14.1 (Q3 2024) release. This guide focuses on changes in Sugar 14.1 (Q3 2024) that could cause an immediate impact on Sugar customizations and integrations built for earlier Sugar versions.
Please check out the Q3 2024 Developer Webinar recording for more developer highlights. For Admin and End User release notes, please visit the Sugar 14.1.0 Release Notes.
User Experience Updates
AI Summary Dashlet for Opportunities and Cases
We are very excited to introduce AI-driven summarization capabilities to Sugar on Opportunities and Cases modules.
This will empower users to extract key insights and information from their CRM data more efficiently by adding new dashlets to display those summaries in those modules. This feature leverages GPT (Generative Pre-trained Transformer) technology to generate concise and contextually relevant summaries, sentiment etc. of record details.
Any users with access to Opportunities or Cases can view the dashlet once it is added (see note).
The initial summary will be generated when an opportunity or case record is opened. The summary will be regenerated once the record view page is refreshed, and new or updated data analyzed by the summary is available. The summary is generated using OpenAI’s most advanced LLM. All data used by the summary is anonymized by SugarCRM before sharing it with OpenAI.
NOTE: Extra license/cost is required to enable AI Dashlet data.
Static Conversion Rates on Quotes
In this release, we're introducing a concept of Locking Currency Rate in Quote and Quote Line Items (QLIs). Prior to this version, the conversion rate remains dynamic unless the quote is in a closed stage (Closed Dead, Closed Lost, Closed Accepted), furthermore closing the Quote only maintained the currency rate for the original line items. If new items were added later, and the conversion rate had changed in admin>currencies, the new items would adopt the latest conversion rate, thus failing to ensure a truly static rate.
This solution involved adding a new checkbox field, "Lock Currency Rates." This field, along with the existing Currency Rate field, will be displayed as a field set in the Record View and Record View Dashlet layout (available to be added in different layouts), where users typically work with Quotes and Quoted Line Items. When users select the "Lock Currency Rates" field, the Quote will store the current conversion rates for existing QLIs, and any future QLIs created will maintain the same conversion rate, even if it changes in admin>currencies. If users choose to unlock the "Lock Currency Rate" field, all related RLIs will update to reflect the most recent conversion rate in admin>currencies.
The addition of this new field allows admins and users to lock currency conversion rates without having to close the Quote, thereby preserving the accurate Quote Stage.
Users will be notified through CONFIRM dialogs when enabling/disabling Lock conversion rate checkbox.
Making Chart Colors consistent in Sugar
In this release, we have implemented a consistent way to assign colors in Sugar. The idea is to use consistent algorithm to pick colors to be rendered across the application.
Every dropdown field, except those dynamically generated – gets a color from the pallet for each value. That color will be used in any chart that shows the data from this dropdown.
Product Catalog for Serve
In this release, we are enabling Product Catalog for Serve license users, they can easily access and manage product catalog making everything more organized and accessible.
Accessibility Improvements
In this release, we've enhanced Sugar to provide greater accessibility to the user interface, including improvements to VoiceOver and keyboard accessibility commands.
Sugar is now injecting some javascript attributes to the HTML necessary for VoiceOver and Keyboard to properly work with newer browser versions.
Some HTML elements were modified to include such attributes directly in their handlebar templates where injecting wasn't feasible.
Sugar areas that are part of these improvements are:
- Service Consoles
- Dropdowns
- Subpanels and its options (+ and More)
- Table Headers (sorted tables)
- Alerts (warning, success, errors)
- List Views (sorting arrow icon)
- Column Descriptions
Sugar REST API updates
This Sugar release introduces REST v11_25
.
Retrieve record with given sync_key from the query params
Allows the user to retrieve a record by sync_key using query params instead of endpoint URL.
GET <sugar instance>/rest/v11_25/<module>/sync_key?sync_key_field_value=<sync key value>
GET <sugar instance>/rest/v11_25/integrate/<module>/?sync_key_field_name=<sync key field name>&sync_key_field_value=<sync key value>
PATCH/PUT/UPSERT record with given sync_key from the query params
Allows the user to patch a record by sync_key using query params instead of endpoint URL.
PATCH <sugar instance>/rest/v11_25/<module>/sync_key?sync_key_field_value=<sync key value>
PATCH <sugar instance>/rest/v11_25/integrate/<module>/?sync_key_field_name=<sync key field name>&sync_key_field_value=<sync key value>
Delete record with given sync_key from the query params
Allows the user to retrieve a record by sync_key using query params instead of endpoint URL.
DELETE <sugar instance>/rest/v11_25/<module>/sync_key?sync_key_field_value=<sync key value>
DELETE <sugar instance>/rest/v11_25/integrate/<module>/?sync_key_field_name=<sync key field name>&sync_key_field_value=<sync key value>
Configurability updates
Studio
"processed" not allowed as custom field in Moduie Builder
In this release, we are adding processed
word to the list of reserved words in Sugar.
You will not be able to use processed
as a field name in Module Builder when creating a new module.
For reference, this is the list of disallowed fields in Module Builder:
- ID
- ID_C
- PARENT_NAME
- PARENT_ID
- * PROCESSED
Sugar Config Settings
Setting Name |
Default |
Override Example |
Description |
moduleInstaller.features.enableRectorModuleScanner | false |
$sugar_config['moduleInstaller']['packageScan'] = true; $sugar_config['moduleInstaller']['features']['enableRectorModuleScanner'] = true; |
Enables scanning of code of MLPs before installation for compatibility with modern versions of PHP. This occurs as one of the stages in Package Scanner, so it should also be enabled (moduleInstaller.packageScan). If the package contains incompatible code, installation will be rejected and report provided containing the list of suggested fixes. |
pruneDelay | 86400000 | $sugar_config['pruneDelay'] = 106400000 | Adds a delay to the Prune job to take into account the date_modified < today()-pruneDelay used to select the records to be deleted. |
moduleInstaller.features.enforceSecureSmarty | false | $sugar_config['moduleInstaller']['features'][‘enforceSecureSmarty’] = true; | When enabled it enforces usage of SecureSmarty instead of Smarty and Sugar_Smarty. SecureSmarty enforces usage of secure Smarty settings. |
Removed Functions / Libraries / Features
Upgrade Scripts
Over time our upgrade scripts have accumulated a lot of steps that are likely no longer necessary to to it's version restrictions. In this release, we've removed the deprecated/outdated upgrade scripts.
Platform Updates
Add rector scanner step into PackageScanner during MLP installation
As part of our ongoing efforts to help our customers to install MLPs compatible with PHP 8.2+, we are introducing Rector (compatibility tool) checks to our ModuleLoader.
PackageScanner will execute a dry-run of rector looking for incompatibilities on the package being installed and will deny the install if incompatible, if denied, an option to download the Rector report will be available to download the diff file for further investigation.
This feature relies on $sugar_config['moduleInstaller']['features']['enableRectorModuleScanner']
which is disabled by default until further notice.
ExternalResourceClient Enhancements
In this release, we've added the missing pieces you need to make HTTP requests from Sugar without relying on third-party frameworks like curl, guzzle, or any other transport client.
The features we added were:
- Base Uri:
- The base URI of the client that is merged into relative URIs
<?php // Base URI $baseUri = 'https://httpbin.org/anything/'; $path = 'foo/bar'; $erc = (new ExternalResourceClient())->setBaseUri($baseUri); $response = $erc->get($path); // Sends request to https://httpbin.org/anything/foo/bar ?>
- File downloads
- The external file may be downloaded into the directory returned by
UploadStream::getDir()
call (`upload` by default)
- The external file may be downloaded into the directory returned by
<?php $url = 'https://httpbin.org/image/png'; // Url of file to download $filename = 'img.png'; // Local filename $response = $erc->download($url, $filename); // Downloads file from $url into `upload` as $filename ?>
- Trusted external resources.
- The new method `
ExternalResourceClient::trustTo(...$hosts)
` has been added to prevent issues with firewalls. - The specified hostnames will not be translated to the corresponding IP addresses.
- Note: the IP of the target hostname should not belong to the private network (or it should be allowed via
$sugar_config['security']['private_ips']).
- The new method `
<?php $erc->trustTo('mytrusted.website.com');
Note: This functionality has been backported to 13.0.4
and 14.0.1
releases.
Integrate (UPSERT) API Enhancements
In this release, we have improved our Integrate API endpoints to support sync_keys
with special characters such as forward slash ("/") that prior to this would be considered part of the endpoint and subsequently fail. In the following example, we are passing the sync_key field name and its value as part of the query string instead of endpoint allowing us to search a sync_key value including "/":
GET:
// using integrate api curl --location --request GET 'https://<instance>/rest/v11_25/integrate/Contacts/?' \ 'sync_key_field_name=sync_key&sync_key_field_value=123db%2F002' \ -H 'Content-Type: application/json' // using module 'sync_key' curl --location --request GET 'https://<instance>/rest/v11_25/Contacts/sync_key?'\ 'sync_key_field_value=329bc7ec-f745-11ee-8f5b-021b212599db%2F002' \ -H 'Content-Type: application/json'
PATCH/PUT (a.k.a UPSERT):
// using integrate API (PATH or PUT) works curl --location --request PATCH 'https://<instance>/rest/v11_25/integrate/Accounts/?'\ 'sync_key_field_name=sync_key&sync_key_field_value=123db%2F002' \ --data-raw '{"name": "rafa test 1"}' \ -H 'Content-Type: application/json' // using module 'sync_key' curl --location --request PATCH 'https://<instance>/rest/v11_25/Accounts/sync_key' \ '?sync_key_field_value=123db%2F002' \ --data-raw '{"name": "rafa test 1"}' \ -H 'Content-Type: application/json'
DELETE:
// using integrate API curl --location --request DELETE 'https://<instance>/rest/v11_25/integrate/Accounts/?' \ 'sync_key_field_name=sync_key&sync_key_field_value=123db%2F002' \ -H 'Content-Type: application/json' // using module 'sync_key' curl --location --request DELETE 'https://<instance>/rest/v11_25/Accounts/sync_key?' \ 'sync_key_field_value=123db%2F002' \ -H 'Content-Type: application/json'
NOTE: Those improvements were "added" to the current implementation therefore what's currently available is still valid.
Bulk API Enhancements
In this release, we have also improved how we return data from our bulk
endpoint where now you can specify which fields you would like to return as part of the bulk endpoint when it is successful.
In the following example, notice that we'd like to get back few extra fields from the record itself, we can by specifying an extra "fields" attribute in the payload. if ['fields
'] param provided (it is optional) in the request body (in 'data
' param) we handle this as a list of responsive fields. It could be passed via string with fields separated by comma or an array of strings.
{"requests":[ { "url":"v11_25/integrate/Contacts/sync_key/sync_key_test", "method":"PATCH", "data":{"title":"Recruiting Manager_","name":"2", "fields":["id","sync_key","name","title", "first_name"]} }, { "url":"v11_25/integrate/Accounts/sync_key/sync_key_test", "method":"PATCH", "data":{"name":"NEw Name", "fields":"1"} } ] } //===== RESPONSE [ { "contents": { "record": { "id": "dd21a094-e78a-11ee-ac3a-02d786a79729", "name": "", "first_name": "", "title": "Recruiting Manager_", "sync_key": "sync_key_test" } }, "headers": [], "status": 200, "status_text": "OK" }, { "contents": { "record": [] }, "headers": [], "status": 200, "status_text": "OK" } ]
Enhance the "Prune Database on 1st of Month" Scheduler with time delay criteria
Currently the “Prune Database on 1st of Month“ deletes everything from the database that has the column “deleted“ equal to 1, in this release, we are adding a time sensitive criteria in the query for pruning the database using date_modified, something like: SELECT id FROM table WHERE deleted = 1 AND date_modified < today() - pruneDelay_24h
NOTE: If someone deletes the record through raw queries in the last 24 hours, it will still get picked up by the scheduler, because the date_modified will not be updated.
Restricting Access to Admins Only
In this release, we have added a restriction at the API layer for Admin/Developer Only to access the following modules:
- Shippers
- TaxRates
- Releases
- Styleguide
- Roles
- Teams
Improve TeamSecurity subqueries in ProspectList module
In this release, we have improved the subquery mechanism used on /modules/ProspectLists/ProspectList.php to use \SugarBean::addVisibilityWhere
to use an optimized version of queries and make it possible to disable TeamSecurity or apply custom visibility if needed.
Sugar Mobile Metadata Improvements
In this release, we are improving our Sugar Mobile metadata integration to include some extra views to be used by the app to render its customized server side version, those views are:
- activity-card-content
- activity-card-definition
- activity-card-detail
- activity-card-header
- activity-timeline
Fix: Portal users can submit cases if disabled with an active token
We have fixed a bug where the user with an active login token gets disabled by an admin could still use the portal until its token expired. Now, at the time of disabling, Sugar will invalidate all tokens for that particular user, cutting access to anything active.
Note: This functionality has been backported to 13.0.4
and 14.0.1
releases.
Introducing SecureSmarty
In this release, we are introducing SecureSmarty
a safer replacement to Smarty, SugarPdfSmarty,
Sugar_Smarty
. This new class enforces usage of secure Smarty settings preventing the use of unsecure functions that could potentially endanger your instance.
After upgrade, when this feature is enabled (see $sugar_config['moduleInstaller']['features'][‘enforceSecureSmarty’]
), PackageScanner will not allow those classes (Smarty, SugarPdfSmarty,
Sugar_Smarty
) to be used in MLP/Addons and they'll have to be replaced with SecureSmarty
.
Note: This feature is disabled in 14.1
and will automatically enabled in 14.2
.
Sanitizing data in templates
In this release, variables in templates will be escaped according to the context they are used.
- Smarty has modifiers to escape variables, most of the variables are already escaped
- Hanldebars escapes variables by default if you use
{{
. Places that use{{{
should be sanitized with{sanitize}
- XTemplate doesn’t have any functionality to escape variables and uses them as is. We are escaping data before passing to the template and/or introduce modifiers when necessary/
Sugar Core Security Updates
As part of our ongoing efforts to keep Sugar clean, fast, reliable, and most importantly secure, we have updated Sugar Core code in different areas of the application such as Package Scanner, Module Installer, UI rendering, Handlebar templates, File Uploads and Imports.
Sugar Core readiness to PHP 8.3
We are constantly conducting code reviews making Sugar compatible with the latest versions PHP, in this case PHP 8.3. Sugar Core is now fully compatible with PHP 8.2 and PHP 8.3. We leverage the use of Rector for this work.
Denylist Updates
show_source()
php_strip_whitespace()
highlight_file()
When $sugar_config['moduleInstaller']['features'][‘enforceSecureSmarty’]
), gets enabled, these classes will be added to the PackageScanner's denylist:
Smarty
SugarPdfSmarty
Sugar_Smarty