Squashed 'public/legacy/' changes from 2aaee3c558..7ce0eaf560

7ce0eaf560 Merge commit 'a9b7e9d38c89bb831eed5c46ae88e1a340a9e745' into refactor_legacy
77175ae5ca Fix undefined property sentAssignmentNotifications
a12d18b3c9 Update CleanCSVTest
ed7951dc93 Update Composer
21c3adc06f SuiteCRM 7.11.21 Release
d6aa88abd2 Allow filtering Survey campaigns
7ab8113825 Adding new attribute to CaseTest for sentAssignmentNotification as well as other Tests
3b13d3d4ac Retrieve SuiteCRM version in get_server_info
db739a3116 Improve Contacts duplicates list
1ebfecf604 Help text containing quotes is not correctly displayed
9191047355 Wrong spelling of AOR_Reports module
e3aa666d15 fix for #8991
0ae8676656 Link fix to documentation site
e6bcec88cb Notes for abbreviations, VAT, Activity Stream, SAML
d2a0f08ab9 Indentation fix
9602a5ab9f Space typo fix
6105f4b231 Moving comment next to the string
49be1068b5 https url fix
85a3dfb122 SuiteP template translators notes
6025f859e4 Fix for: #9179 AOR_Charts getShortenedLabel fails on utf8 characters
092ab1f7fa Add the ability import Projects
a91fe3995e Fix Issue #4145
5d077d44e2 Fix #9205 - Duplicate audit records.
925f194db2 Fix #9203 - Duplicate notification emails.
16f6fda636 Fix Archive Folder Query
504f16f0a8 Add cases to email object_arr
fe07e1660c Fix only init Currency once
5692da9269 Fix broken image path in reports HTML
ce93d319d7  Fix php notices
013e0eee39 Change pdfheader/pdffooter data type to longtext
175df9ffe9 Set default perms on new log file
4caedf2fdf Update CaseUpdatesHook.php
8d4678fdb1 Remove spaces in fnc call ACLController::filterModuleList()
1e5e8bfecc Fix function declaration of TabController::get_key_array()
9e85083916 Wrong spelling of ProspectLists module
ce8f3b0665 Fix #9201 - Filter form label styling.
568839d1bd Fix #9237 where dates in aow actions & conditions are not saved or displayed correctly
17363c3f60 Fix #6997 - User profile password auto-fill
5b87663738 Correct layout of date fields
1de52dc97d 7.11.20
6737e71506 Fix Users index incompatible with MSSQL
bd9dd96f3a Change populateDefaultValues fatal log on empty field_defs to warning
9039d97b07 Fix theme display issues
ffb434042f Fix Missing locale in FullCalender 3.10
32e8146664 Fix Php compatibility within Admin ConfigureTabs
e0904414a1 Fix Email Address loading performance
fdea144ecb Fix #8319 - Multiple IMAP Inboxes fails to display emails
45a6527e91 Fix #7285 - Allow filter of custom fields on V8 API Get Modules
55dab76a1a Fix #8420 - V8 API issues fails on windows
8994449ef8 Upgrade ElasticSearch to v7.x
cd2e17a49a Implement PDFEngine
1a50079341 Fix PDF_Lib constructors
17035aa25b Replace deprecated fzaninotto/faker with fakerphp/faker
854daa3ef7 Move test namespaces into autoload-dev
a801513237 Upgrade nesbot/carbon to v2.x
889e73b943 Update Travis config to use composer v2.x
22f956cf74 Upgrade composer-merge-plugin to v2.x
753e6242fa Fix PHPUnit 9 deprecations and warnings
f62d8d7bed Fix test case class not matching filename deprecation warnings
1b4cefb5c3 Replace abandoned leafo/scssphp with scssphp/scssphp
53a1cf3765 Upgrade Robo to v3.x
32231c4f1d Update composer.json
5b8ea6cd49 Fix missing default config values
2555dc14b7 Consolidate global search settings
12d51f8e5c Remove duplicate "Global Search" link in the adminpanel
6c28c687ee Implement search engine selection
24a3e9d6c2 Deprecate UnifiedSearchAdvanced
6453ebf25c Unify search engines
a740042295 Remove new/legacy search engine labels
dc8a8bc8e1 Add codeception 4.1.x dependencies to composer
8404643044 Migrate PHPUnit schema for 9.5.x
ac144b8dfc Upgrade PHPUnit to 9.5.x
2f7e5790bc Remove codeception
4882f9531e Fix tests remove incompletes
74596e24b8 Fix tests deprecated asserts
8539246027 Fix tests define return type hints
ff8e2f2973 Update test namespaces for PSR-4/PSR-8
5f17109ce4 Fix tests redundant noinspection
65fa1662d2 Fix tests misordered assert arguments
d3d589c4fc Fix tests use appropriate asserts
f1c8e05d00 Fix tests one-time use variables
fad98fcead Fix tests method invocations
e660423312 Update PHPUnit schema
251bf18f31 Update Travis config to remove PHP 7.2
a715d7120c Update minimum required PHP to v7.3.0
369cd99c3a Fix #9106 - Update securexss for backwards compatibility
b1263f189f Update composer
42c065dd91 7.11.19
cdc3b47207 Fix Calender display issues in FullCalender 3.10
3caa17e1f8 Fix #7999 - Prevent securitygroups mass assign damage
df0c687ad0 Fix #5624 - Make SWSPEditRoleButton::displayList compatible w. parent
a173f1b1d2 Fix #8571 - Remove duplicate code in users detailviewdefs
4e3c62fe56 Fix #8514 - Implement effective opcache file clearing
afca8fa5f8 Fix #8461, #8462 - PHP files are potentially overwritten
5b0f1f13ed Fix #8700 - Various problems in PHPDocs throughout the codebase.
f89f115fe6 Fix #9067 - Fix the drop down width
579b894f65 Add Additional api filter option `like`
88316f8612 Add filters in relationship API
277b9e5520 Add Relationship Beans in V8 API Response
e178ef8495 Fix #9090 - User menu alignment
631c756fc0 Fix #6051 - Modulebuilder labels edit fixes
2c2b5e689b Update JQuery JS Library to v3.6.0
065306623d Update FullCalendar JS Library to v3.10.2
0634e7f533 Update YUI JS Library to 2.9.1
a74ccf7eae Fix #8999 - Hardcoded 'by' label in calls
c8f6cd9061 Fix #9034 - Business Hours does not work in non-english languages
e554511cb0 Fix #8910 - Update the V8 Api to allow for upload of documents similar to notes
ef590862fb Fix #9010 - Add missing 'view task' label on calendar
b339312d79 Fix #8894 - Add missing label for calendar dashlet
f936a6366a Fix #9032 - Prevent Notice Error During Import
42f87aac1d Fix #8182 - Update updateTimeDateFields to handle undefined dates
a744e89bf6 Fix #9075 - Removing deleted related beans via link
b17ef78ced Fix #8988 - Improve upon solution which doesn't cache incomplete beans
315c1ecf63 Fix #7772 - Only index ElasticSearch when enabled
7c05a09d90 Fix #9101 LangText exception breaking ElasticSearch
2bad09d0c0 Fix #8472 - No or not complete Searchresults using elasticsearch engine
6978a22cb1 Fix #6800 - Elasticsearch: Elastic index name is hardcoded
cf8b487e6d Fix #8916 - Misspelled elasticsearch labels
8029916390 Fix #9080 - Update config for google/apiclient at composer.json
318d91a15c Fix #9060 - Project Form action should not be changed if delete is not confirmed
b68834c47b Fix #8676 - New Scheduled Reports does not run
d87c7a0748 Fix #2645 - Calendar quick create ignores required fields
91e9d7540a Deprecate PdfParser
a1ee531f3d Deprecate advanced open discovery (AOD)
122b872c2b Fix subpanel insights to support function query
f2b6be56e2 [Legacy] Update list count query to accept alias name
932d700511 [Legacy] Admin Release Styling Fixes
e13201af39 [Legacy] Quotes & Invoices Faint Line Removed
1f0fdf0fb1 [Legacy] History Subpanel Styling Changes
a01fe52c40 [Legacy] Date Calendar Icon Color Fixes
c84dc60a1c [Legacy] Fix Add Dashlet Tab via Enter Key in Home Page Redirects to Legacy
3ea774916c [Legacy] Make anchor links within Convert Lead module point to S8
290978a5d3 [Legacy] add language labels for user auth guard ACL Error Messages
8d0ccd3ddf create user auth guard backend handler to handle User ACL
377e85090c [Legacy] Scrollbar color fix globally
e776c38c42 [Legacy] Action DropDown Arrow Alignment Fixes
bc384c226e Border Outline Color Fixes
811df34b1f [Legacy] Add utility method to retrieve install languages
39f3629b08 [Legacy] Add labels
e6388fa338 [Legacy] Configure Module Menu Styling Changes
5653a6904a [Legacy] - Increment suitecrm_version.php
95073941fa [Legacy] Add labels
5597e87745 [Legacy] Add EmailAddressLinkMapper to ApiBeanMapper
17e9e91d04 [Legacy] Add LineItemSaveHandler
366dc162e0 [Legacy] Add BeanSaveHandlers
5e38fc88d8 [Legacy] Rename Modules Styling Changes
3bb5a5d6a9 Merge commit '9c71e8c884' into fix/legacy_update
8b45c9a338 [Legacy] Fix Display Module & Subpanel Styling
85d70377d1 [Legacy] Add line item single primary email validation label
da4a6a6c40 [Legacy] Add labels
b80198be11 [Legacy] Add labels
56637aa080 Refactor filter content ApiBeanMapper to use filter mapper
bee6f9c10b [Legacy] Move Legacy Filter Mapper to legacy
6ac12e5bd4 [Legacy] Fix Campaign Email Settings Styling
0aff61bc38 [Legacy] System Settings Hover Button Changes
b9194c1c66 [Legacy] Activity Stream Styling Changes
37b80cefd6 [Legacy] Admin Language Styling Changes
ec53218574 [Legacy] Fix Theme Setting Styling Changes
951e1ae844 [Legacy] Update SugarBean to support custom union query for history timeline widget
49c754ed87 Update history timeline backend handler to handle activities and audit data along with history data
4807b6fa45 [Legacy] Add labels for history timeline widget
174bba1e38 [Legacy] Fix Admin Diagnostic Tool Styling Changes
b10a2d7e26 [Legacy] Fix Button Hover Styling
631cbbbe0e [Leagcy] Workflow & Invoice & Quotes Line Items Styling Fix
ec22f577c9 [Legacy] Fix Help Icon Styling
9a092d2d51 [Legacy] Fix Security Groups Create Styling
96dda062d2 [Legacy] Fix Security Suite Settings Styling
ed05b461aa [Legacy] Dashboard modal dashlet & add tab & edit tab
2b741a982a [Legacy] Fix Role List User Styling
b2abf4588c [Legacy] Fix AOP Settings Styling
763d0ed66b [Legacy] Dashlet Table Scroll Fixes
aa2aebfa82 [Legacy] Add attribute array mapping to ApiBeanMapper
b8e3926ace [Legacy] Add MassUpdatePort
327ddf764d [Legacy] Add labels
d10884fbad [Legacy] Fix Outline Border color
0d08b6684b [Legacy] Add Post Upgrade port service
de0ebec1d4 [Legacy] Fix Business Hours Styling
a69aa7f89b [Legacy] Fix AOS Settings Styling
942b635996 [Legacy] iFrame Modal Page Styling Changes
95c4d8a89a [Legacy] Admin Locale Styling Changes
4b4aade088 [Legacy] Role CreateView Styling Changes
4b8082c1b0 [Legacy] Password Management Styling Changes
f542903e46 [Legacy] Currency Recordview styling changes
0efba176b7 [Legacy] Email Settings Send Email Styling Changes
f8aad710e1 [Legacy] Email Settings Styling Changes
3e41d46bc6 [Legacy] Changes to support Legacy integration of Merge Duplicates action to Suite8
254619ad37 [Legacy] Roles Management Styling Changes
2ac0e9f126 [Legacy] Add legacy portability services to add records or contacts to a target list
42a1ab8e88 [Legacy] Add labels for add to target list messages
8933416dc2 [Legacy] Dashboard Settings ModalPopup Changes
157ce24459 [Legacy] Project Resource Calendar Styling Changes
86b806d990 [Legacy] System Settings CSS Changes
80e5ce0e5e [Legacy] Add Language Label Change Log
b2e9a36e6a [Legacy] Increment suitecrm_version
af1d13f4a6 Merge commit '2473298dc6' into beta2
039df6a308 [Legacy] Add Legacy portability Link Service
cde96fd758 [Legacy] Change Case update wiget items display
8ee998700d [Legacy] Add generic action success label
357655058c [Legacy] Change Cases calculated field rules
49120c6a05 [Legacy] Add non-db source field to cases
6f9cc072db [Legacy] Add null checks to CaseUpdate sendUpdate
cc68ead8ca [Legacy] Remove case threads from case detailviewdefs
b651151cc9 [Legacy] Add case updates widget configuration
5960f06d73 [Legacy] Add record-thread component related labels
2824f62499 [Legacy] Add case updates api bean mappers
7244666094 [Legacy] Add non-db author field to case updates
19e839e022 [Legacy] Add case thread update label
eae9e509f6 define datetime format conversion mappers for datetimecombo field
48ff651d60 [Legacy] Inbound Email ListView Styling Changes
144a01f3c7 [Legacy] Add link label
9a3bbaec3f [Legacy] Labels definition for link entity relationship via record subpanels
1c7b7d1770 [Legacy] Update unlink related labels
79088c678c [Legacy] Add unlink service port
7495fa6d86 [Legacy] Changes for Unlink Subpanel Relationship
c8df2643cf [Legacy] User Profile Styling Changes
ce539098dd [Legacy] Homepage Mobile Changes
22c6e4736e [Legacy] Add Saved filter related labels
6971d34c2c [Legacy] Add SavedSearch module metadata
5a70355c52 [Legacy] Add api to bean mapping handling to ApiBeanMapper
e1a94f7cd1 [Legacy] Add null check to SavedSearch bean
e37dbf171b [Legacy] Add SavedSearch module api bean mappers
a441ec08ef [Legacy] Add ApiBeanModuleMappers
913cce923f Search Bar Mobile Changes
ee1593f735 [Legacy] Remove advanced open discovery (AOD)
8f60fafec3 [Legacy] Define a new function to return all columns defined for the module list view
ead86f0d02 [Legacy] Convert Lead Styling Changes
5606baede5 [Legacy] Subpanel Design Changes
7bf0e84681 [Legacy] Tab Arrwo Misalignment Changes
6a03cc65f2 [Legacy] Inbound Email Styling Changes
784f089a90 [Legacy] Update legacy vendor pathing
aa1e3d8c59 [Legacy] Remove legacy composer
9e990b8ce7 [Legacy] Add global labels for listView Column Selector

git-subtree-dir: public/legacy
git-subtree-split: 7ce0eaf560b55293ca3f105ac776ff936b319679
This commit is contained in:
Dillon-Brown 2021-08-30 10:17:18 +01:00
parent 9c71e8c884
commit 114b895b6d
502 changed files with 10167 additions and 18546 deletions

View file

@ -53,7 +53,6 @@ ignore:
- "include/parsecsv.lib.php" - "include/parsecsv.lib.php"
- "modules/AOS_PDF_Templates/PDF_Lib/.*" - "modules/AOS_PDF_Templates/PDF_Lib/.*"
- "Zend/.*" - "Zend/.*"
- "modules/AOD_Index/Lib/.*"
- "modules/Users/authentication/SAML2Authenticate/lib/.*" - "modules/Users/authentication/SAML2Authenticate/lib/.*"
- "install/demoData.en_us.php" - "install/demoData.en_us.php"
- "include/tcpdf/.*" - "include/tcpdf/.*"

View file

@ -29,7 +29,6 @@ $finder = PhpCsFixer\Finder::create()
->exclude('include/php-sql-parser.php') ->exclude('include/php-sql-parser.php')
->exclude('include/parsecsv.lib.php') ->exclude('include/parsecsv.lib.php')
->exclude('modules/AOS_PDF_Templates/PDF_Lib') ->exclude('modules/AOS_PDF_Templates/PDF_Lib')
->exclude('modules/AOD_Index/Lib')
->exclude('modules/Users/authentication/SAML2Authenticate/lib') ->exclude('modules/Users/authentication/SAML2Authenticate/lib')
->exclude('modules/AOR_Charts/lib') ->exclude('modules/AOR_Charts/lib')
->exclude('install/demoData.en_us.php') ->exclude('install/demoData.en_us.php')

View file

@ -8,5 +8,6 @@ return CustomLoader::mergeCustomArray([
'displayErrorDetails' => true, 'displayErrorDetails' => true,
/** Routes are accessible in middleware. */ /** Routes are accessible in middleware. */
'determineRouteBeforeAppMiddleware' => true, 'determineRouteBeforeAppMiddleware' => true,
'addContentLengthHeader' => false,
] ]
], basename(__FILE__)); ], basename(__FILE__));

View file

@ -15,12 +15,16 @@ use League\OAuth2\Server\Grant\PasswordGrant;
use League\OAuth2\Server\Grant\RefreshTokenGrant; use League\OAuth2\Server\Grant\RefreshTokenGrant;
use League\OAuth2\Server\ResourceServer; use League\OAuth2\Server\ResourceServer;
use Api\Core\Loader\CustomLoader; use Api\Core\Loader\CustomLoader;
use Api\V8\Helper\OsHelper;
use League\OAuth2\Server\CryptKey;
return CustomLoader::mergeCustomArray([ return CustomLoader::mergeCustomArray([
AuthorizationServer::class => function (Container $container) { AuthorizationServer::class => function (Container $container) {
// base dir must exist in entryPoint.php // base dir must exist in entryPoint.php
$baseDir = $GLOBALS['BASE_DIR']; $baseDir = $GLOBALS['BASE_DIR'];
$shouldCheckPermissions = OsHelper::getOS() !== OsHelper::OS_WINDOWS;
$server = new AuthorizationServer( $server = new AuthorizationServer(
new ClientRepository( new ClientRepository(
new ClientEntity(), new ClientEntity(),
@ -31,8 +35,16 @@ return CustomLoader::mergeCustomArray([
$container->get(BeanManager::class) $container->get(BeanManager::class)
), ),
new ScopeRepository(), new ScopeRepository(),
sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PRIVATE_KEY), new CryptKey(
sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PUBLIC_KEY) sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PRIVATE_KEY),
null,
$shouldCheckPermissions
),
new CryptKey(
sprintf('file://%s/%s', $baseDir, ApiConfig::OAUTH2_PRIVATE_KEY),
null,
$shouldCheckPermissions
)
); );
$oauth2EncKey = isset($GLOBALS['sugar_config']['oauth2_encryption_key']) $oauth2EncKey = isset($GLOBALS['sugar_config']['oauth2_encryption_key'])

View file

@ -2,7 +2,7 @@
use Api\Core\Loader\CustomLoader; use Api\Core\Loader\CustomLoader;
include_once __DIR__ . '/../../../../vendor/symfony/validator/ValidatorBuilder.php'; include_once __DIR__ . '/../../../../../../vendor/symfony/validator/ValidatorBuilder.php';
return CustomLoader::mergeCustomArray([ return CustomLoader::mergeCustomArray([
'Validation' => function () { 'Validation' => function () {

View file

@ -0,0 +1,35 @@
<?php
namespace Api\V8\Helper;
/**
* Class OsHelper
*/
class OsHelper
{
const OS_WINDOWS = 'WINDOWS';
const OS_LINUX = 'LINUX';
const OS_OSX = 'OSX';
/**
* @return string
*
* @throws \RuntimeException When unable to determine OS.
*/
public static function getOS()
{
switch (true) {
case stristr(PHP_OS, 'DAR'):
return self::OS_OSX;
case stristr(PHP_OS, 'WIN'):
return self::OS_WINDOWS;
case stristr(PHP_OS, 'LINUX'):
return self::OS_LINUX;
default:
throw new \RuntimeException('Unable to determine OS');
}
}
}

View file

@ -60,11 +60,14 @@ class Filter
throw new \InvalidArgumentException(sprintf('Filter field %s must be an array', $field)); throw new \InvalidArgumentException(sprintf('Filter field %s must be an array', $field));
} }
$isCustom = isset($bean->field_defs[$field]['source']) && ($bean->field_defs[$field]['source'] == 'custom_fields');
$tableName = $isCustom ? $bean->get_custom_table_name() : $bean->getTableName();
foreach ($expr as $op => $value) { foreach ($expr as $op => $value) {
$this->checkOperator($op); $this->checkOperator($op);
$where[] = sprintf( $where[] = sprintf(
'%s.%s %s %s', '%s.%s %s %s',
$bean->getTableName(), $tableName,
$field, $field,
constant(sprintf('%s::OP_%s', self::class, strtoupper($op))), constant(sprintf('%s::OP_%s', self::class, strtoupper($op))),
$this->db->quoted($value) $this->db->quoted($value)

View file

@ -10,8 +10,10 @@ abstract class BaseParam implements \JsonSerializable
{ {
/** /**
* @var array * @var array
* @desc the access specifier is made public as it need to be accessed by external class
* e.g. $deleteRelationshipParams->parameters = [$params_array]
*/ */
protected $parameters = []; public $parameters = [];
/** /**
* @var ValidatorFactory * @var ValidatorFactory

View file

@ -65,6 +65,8 @@ if (!defined('sugarEntry') || !sugarEntry) {
"aow" => array("section" => "aow_actions", "extdir" => "Actions", "file" => 'actions.ext.php', "module" => "AOW_Actions"), "aow" => array("section" => "aow_actions", "extdir" => "Actions", "file" => 'actions.ext.php', "module" => "AOW_Actions"),
"actionnamemap" => array("section" => "action_name_map","extdir" => "ActionNameMap", "file" => 'action_name_map.ext.php'), "actionnamemap" => array("section" => "action_name_map","extdir" => "ActionNameMap", "file" => 'action_name_map.ext.php'),
"modulenamemap" => array("section" => "module_name_map","extdir" => "ModuleNameMap", "file" => 'module_name_map.ext.php'), "modulenamemap" => array("section" => "module_name_map","extdir" => "ModuleNameMap", "file" => 'module_name_map.ext.php'),
"filteroperatormap" => array("section" => "filter_operator_map","extdir" => "FilterOperatorMap", "file" => 'filter_operator_map.ext.php'),
"filtermappers" => array("section" => "filter_mappers","extdir" => "FilterMappers", "file" => 'filter_mappers.ext.php'),
"classicviewroutingexclusions" => array("section" => "classicview_routing_exclusions","extdir" => "ClassicViewRoutingExclusions", "file" => 'classicview_routing_exclusions.ext.php'), "classicviewroutingexclusions" => array("section" => "classicview_routing_exclusions","extdir" => "ClassicViewRoutingExclusions", "file" => 'classicview_routing_exclusions.ext.php'),
); );
if (file_exists("custom/application/Ext/Extensions/extensions.ext.php")) { if (file_exists("custom/application/Ext/Extensions/extensions.ext.php")) {

View file

@ -2,7 +2,7 @@
<img width="180px" height="41px" src="https://suitecrm.com/wp-content/uploads/2017/12/logo.png" align="right" /> <img width="180px" height="41px" src="https://suitecrm.com/wp-content/uploads/2017/12/logo.png" align="right" />
</a> </a>
# SuiteCRM 8.0.0-beta-1 # SuiteCRM 8.0.0-beta-2
[![LICENSE](https://img.shields.io/github/license/suitecrm/suitecrm.svg)](https://github.com/salesagility/suitecrm/blob/hotfix/LICENSE.txt) [![LICENSE](https://img.shields.io/github/license/suitecrm/suitecrm.svg)](https://github.com/salesagility/suitecrm/blob/hotfix/LICENSE.txt)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/salesagility/SuiteCRM-Core/issues) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/salesagility/SuiteCRM-Core/issues)

View file

@ -15,7 +15,6 @@ exclude_paths:
- 'include/parsecsv.lib.php*' - 'include/parsecsv.lib.php*'
- 'modules/AOS_PDF_Templates/PDF_Lib/**' - 'modules/AOS_PDF_Templates/PDF_Lib/**'
- 'Zend/**' - 'Zend/**'
- 'modules/AOD_Index/Lib/**'
- 'modules/Users/authentication/SAML2Authenticate/lib/**' - 'modules/Users/authentication/SAML2Authenticate/lib/**'
- 'install/demoData.en_us.php*' - 'install/demoData.en_us.php*'
- 'include/tcpdf/**' - 'include/tcpdf/**'

View file

@ -43,7 +43,6 @@ coverage:
- include/php-sql-parser.php - include/php-sql-parser.php
- include/parsecsv.lib.php - include/parsecsv.lib.php
- modules/AOS_PDF_Templates/PDF_Lib/* - modules/AOS_PDF_Templates/PDF_Lib/*
- modules/AOD_Index/Lib/*
- modules/Users/authentication/SAML2Authenticate/lib/* - modules/Users/authentication/SAML2Authenticate/lib/*
- install/demoData.en_us.php - install/demoData.en_us.php
- include/tcpdf/* - include/tcpdf/*

View file

@ -1,150 +0,0 @@
{
"name": "salesagility/suitecrm",
"description": "SuiteCRM",
"homepage": "https://suitecrm.com",
"type": "project",
"license": "GPL-3.0",
"authors": [
{
"name": "SalesAgility Ltd"
}
],
"support": {
"issues": "https://github.com/salesagility/SuiteCRM/issues",
"wiki": "https://docs.suitecrm.com",
"forum": "https://suitecrm.com/suitecrm/forum",
"chat": "https://gitter.im/suitecrm/Lobby",
"source": "https://github.com/salesagility/SuiteCRM"
},
"config": {
"vendor-dir": "vendor",
"platform": {
"php": "7.3.0"
},
"optimize-autoloader": true,
"sort-packages": true,
"preferred-install": {
"elasticsearch/elasticsearch": "dist"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=7.3.0",
"ext-curl": "*",
"ext-gd": "*",
"ext-imap": "*",
"ext-json": "*",
"ext-openssl": "*",
"ext-zip": "*",
"elasticsearch/elasticsearch": "^5.3",
"ezyang/htmlpurifier": "^4.10",
"google/apiclient": "^2.0",
"google/recaptcha": "^1.1",
"gymadarasz/ace": "^1.2",
"gymadarasz/imagesloaded": "^4.1",
"justinrainbow/json-schema": "^5.2",
"league/oauth2-server": "^5.1",
"league/uri": "^4.2.3",
"monolog/monolog": "^1.23",
"nesbot/carbon": "^2.0.0",
"onelogin/php-saml": "3.4.1",
"paragonie/random_compat": "^2.0",
"phpmailer/phpmailer": "^6.0",
"psr/container": "^1.0",
"psr/log": "^1.0",
"slim/slim": "^3.8",
"smarty/smarty": "^2.6",
"soundasleep/html2text": "~0.5",
"symfony/options-resolver": "^3.4",
"symfony/validator": "^3.4",
"symfony/yaml": "^5.2",
"tinymce/tinymce": "^4.9.11",
"tedivm/jshrink": "^1.3",
"tuupola/slim-jwt-auth": "^2.0",
"vlucas/phpdotenv": "^3.5",
"voku/anti-xss": "^2.3",
"wikimedia/composer-merge-plugin": "^2.0",
"zbateson/mail-mime-parser": "^1.1",
"zf1/zend-gdata": "^1.12",
"zf1/zend-loader": "^1.12",
"zf1/zend-oauth": "^1.12",
"zf1/zend-registry": "^1.12",
"zf1/zend-search-lucene": "^1.12",
"lcobucci/jwt": "3.3.3"
},
"require-dev": {
"consolidation/robo": "^1.4",
"browserstack/browserstack-local": "^1.1",
"codeception/codeception": "^4.1",
"codeception/module-asserts": "^1.3",
"codeception/module-filesystem": "^1.0",
"codeception/module-phpbrowser": "^1.0",
"codeception/module-rest": "^1.3",
"codeception/module-webdriver": "^1.2",
"fakerphp/faker": "^1.14",
"filp/whoops": "^2.3",
"flow/jsonpath": "^0.4",
"friendsofphp/php-cs-fixer": "^2.15",
"jeroendesloovere/vcard": "v1.5",
"mikey179/vfsstream": "1.6.*",
"mockery/mockery": "^1.1.0",
"phpunit/phpunit": "^9.5",
"scssphp/scssphp": "^1.5"
},
"autoload": {
"files": [
"deprecated.php"
],
"psr-4": {
"SuiteCRM\\": [
"lib/",
"include/"
],
"SuiteCRM\\Custom\\": [
"custom/lib"
],
"SuiteCRM\\Modules\\": [
"modules/"
]
},
"classmap": [
"Api/"
]
},
"autoload-dev": {
"psr-4": {
"SuiteCRM\\": [
"tests/SuiteCRM/",
"tests/unit/phpunit/lib/SuiteCRM/"
],
"SuiteCRM\\Tests\\Unit\\": [
"tests/unit/phpunit/"
]
}
},
"scripts": {
"post-install-cmd": [
"rm -Rf vendor/elasticsearch/elasticsearch/tests/Elasticsearch/Tests",
"Google\\Task\\Composer::cleanup"
]
},
"extra": {
"merge-plugin": {
"include": [
"composer.ext.json",
"custom/Extension/application/Ext/Composer/*/*.json"
],
"recurse": true,
"replace": false,
"ignore-duplicates": false,
"merge-dev": true,
"merge-extra": false,
"merge-extra-deep": false,
"merge-scripts": false,
"google/apiclient-services": [
"Calendar"
]
}
}
}

9244
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -44,6 +44,7 @@ if (!defined('sugarEntry') || !sugarEntry) {
require_once 'modules/DynamicFields/DynamicField.php'; require_once 'modules/DynamicFields/DynamicField.php';
require_once "data/Relationships/RelationshipFactory.php"; require_once "data/Relationships/RelationshipFactory.php";
require_once 'include/portability/SaveHandlers/BeanSaveHandlersManager.php';
/** /**
@ -414,6 +415,10 @@ class SugarBean
*/ */
public $old_modified_by_name; public $old_modified_by_name;
/**
* @var SugarBean[][] $line_item_entries
*/
public $line_item_entries = [];
/** /**
* SugarBean constructor. * SugarBean constructor.
@ -528,7 +533,7 @@ class SugarBean
public function populateDefaultValues($force = false) public function populateDefaultValues($force = false)
{ {
if (!is_array($this->field_defs)) { if (!is_array($this->field_defs)) {
$GLOBALS['log']->fatal('SugarBean::populateDefaultValues $field_defs should be an array'); $GLOBALS['log']->warn($this->module_name.'::populateDefaultValues $field_defs should be an array');
return; return;
} }
foreach ($this->field_defs as $field => $value) { foreach ($this->field_defs as $field => $value) {
@ -783,13 +788,14 @@ class SugarBean
* @param int $limit * @param int $limit
* @param int $max * @param int $max
* @param int $show_deleted * @param int $show_deleted
* @param aSubPanel $subpanel_def * @param null $subpanel_def
* @param array $list_fields
* *
* @return array * @return array
* *
* Internal Function, do not override. * Internal Function, do not override.
*/ */
public static function get_union_related_list( public static function get_union_related_list_query_params(
$parentbean, $parentbean,
$order_by = '', $order_by = '',
$sort_order = '', $sort_order = '',
@ -798,8 +804,10 @@ class SugarBean
$limit = -1, $limit = -1,
$max = -1, $max = -1,
$show_deleted = 0, $show_deleted = 0,
$subpanel_def= null $subpanel_def = null,
) { $list_fields = array()
)
{
if (is_null($subpanel_def)) { if (is_null($subpanel_def)) {
$GLOBALS['log']->fatal('subpanel_def is null'); $GLOBALS['log']->fatal('subpanel_def is null');
} }
@ -865,7 +873,7 @@ class SugarBean
} }
//If final_query is still empty, its time to build the sub-queries //If final_query is still empty, its time to build the sub-queries
if (empty($final_query)) { if (empty($final_query)) {
$subqueries = SugarBean::build_sub_queries_for_union($subpanel_list, $subpanel_def, $parentbean, $order_by); $subqueries = SugarBean::build_sub_queries_for_union($subpanel_list, $subpanel_def, $parentbean, $order_by, $list_fields);
$all_fields = array(); $all_fields = array();
foreach ($subqueries as $i => $subquery) { foreach ($subqueries as $i => $subquery) {
$query_fields = DBManagerFactory::getInstance()->getSelectFieldsFromQuery($subquery['select']); $query_fields = DBManagerFactory::getInstance()->getSelectFieldsFromQuery($subquery['select']);
@ -986,35 +994,62 @@ class SugarBean
return $response; return $response;
} }
if (method_exists($parentbean, 'process_union_list_query')) { return [
return $parentbean->process_union_list_query( $parentbean,
$parentbean, $final_query,
$final_query, $row_offset,
$row_offset, $limit,
$limit, $max,
$max, '',
'', $subpanel_def,
$subpanel_def, $final_query_rows,
$final_query_rows, $secondary_queries ];
$secondary_queries
); }
/**
* @param $subpanel_list
* @param $subpanel_def
* @param $parentbean
* @param $order_by
*
* @return array
*/
public static function get_union_related_list($parentbean,
$order_by = '',
$sort_order = '',
$where = '',
$row_offset = 0,
$limit = -1,
$max = -1,
$show_deleted = 0,
$subpanel_def= null){
if (method_exists($parentbean, 'process_union_list_query'))
{
$parent_func_args = func_get_args();
$union_list_query_args = self::get_union_related_list_query_params(...$parent_func_args);
return $parentbean->process_union_list_query(...$union_list_query_args);
} }
$GLOBALS['log']->fatal('Parent bean should be a SugarBean'); $GLOBALS['log']->fatal('Parent bean should be a SugarBean');
return null; return null;
} }
/** /**
* @param $subpanel_list * @param $subpanel_list
* @param $subpanel_def * @param $subpanel_def
* @param $parentbean * @param $parentbean
* @param $order_by * @param $order_by
* *
* @param array $list_fields
* @return array * @return array
*/ */
public static function getUnionRelatedListQueries($subpanel_list, $subpanel_def, $parentbean, $order_by): array public static function getUnionRelatedListQueries($subpanel_list, $subpanel_def, $parentbean, $order_by, $list_fields = array()): array
{ {
return self::build_sub_queries_for_union($subpanel_list, $subpanel_def, $parentbean, $order_by); return self::build_sub_queries_for_union($subpanel_list, $subpanel_def, $parentbean, $order_by, $list_fields);
} }
/** /**
@ -1023,16 +1058,17 @@ class SugarBean
* @param $parentbean * @param $parentbean
* @param $order_by * @param $order_by
* *
* @param array $union_related_list_columns
* @return array * @return array
*/ */
protected static function build_sub_queries_for_union($subpanel_list, $subpanel_def, $parentbean, $order_by) protected static function build_sub_queries_for_union($subpanel_list, $subpanel_def, $parentbean, $order_by, $union_related_list_columns = array()): array
{ {
global $beanList; global $beanList;
$subqueries = array(); $subqueries = array();
if (!is_array($subpanel_list) or is_object($subpanel_list)) { if (!is_array($subpanel_list) or is_object($subpanel_list)) {
$GLOBALS['log']->fatal('Invalid Argument: Subpanel list should be an array.'); $GLOBALS['log']->fatal('Invalid Argument: Subpanel list should be an array.');
$subpanel_list = (array) $subpanel_list; $subpanel_list = (array)$subpanel_list;
} }
foreach ($subpanel_list as $this_subpanel) { foreach ($subpanel_list as $this_subpanel) {
@ -1117,10 +1153,14 @@ class SugarBean
} }
$subwhere = $where_definition; $subwhere = $where_definition;
if(!empty($union_related_list_columns) && array_key_exists($this_subpanel->name, $union_related_list_columns)) {
$list_fields = $union_related_list_columns[$this_subpanel->name];
}else{
$list_fields = $this_subpanel->get_list_fields();
}
$list_fields = $this_subpanel->get_list_fields();
foreach ($list_fields as $list_key => $list_field) { foreach ($list_fields as $list_key => $list_field) {
if (isset($list_field['usage']) && $list_field['usage'] == 'display_only') { if (isset($list_field['usage']) && $list_field['usage'] === 'display_only') {
unset($list_fields[$list_key]); unset($list_fields[$list_key]);
} }
} }
@ -1143,7 +1183,7 @@ class SugarBean
$params = array(); $params = array();
$params['distinct'] = $this_subpanel->distinct_query(); $params['distinct'] = $this_subpanel->distinct_query();
$params['joined_tables'] = isset($query_array['join_tables']) ? $query_array['join_tables'] : null; $params['joined_tables'] = $query_array['join_tables'] ?? null;
$params['include_custom_fields'] = method_exists($subpanel_def, 'isCollection') $params['include_custom_fields'] = method_exists($subpanel_def, 'isCollection')
? !$subpanel_def->isCollection() : null; ? !$subpanel_def->isCollection() : null;
$params['collection_list'] = method_exists($subpanel_def, 'get_inst_prop_value') $params['collection_list'] = method_exists($subpanel_def, 'get_inst_prop_value')
@ -1211,10 +1251,11 @@ class SugarBean
$limit = -1, $limit = -1,
$max_per_page = -1, $max_per_page = -1,
$where = '', $where = '',
$subpanel_def= null, $subpanel_def = null,
$query_row_count = '', $query_row_count = '',
$secondary_queries = array() $secondary_queries = array()
) { )
{
if (is_null($subpanel_def)) { if (is_null($subpanel_def)) {
$GLOBALS['log']->fatal('subpanel_def is null'); $GLOBALS['log']->fatal('subpanel_def is null');
} }
@ -2025,7 +2066,7 @@ class SugarBean
* Method will load the relationship if not done so already. * Method will load the relationship if not done so already.
* *
* @param string $field_name relationship to be loaded. * @param string $field_name relationship to be loaded.
* @param string $bean_name class name of the related bean.legacy * @param string $bean_name class name of the related bean.legacy
* @param string $order_by , Optional, default empty. * @param string $order_by , Optional, default empty.
* @param int $begin_index Optional, default 0, unused. * @param int $begin_index Optional, default 0, unused.
* @param int $end_index Optional, default -1 * @param int $end_index Optional, default -1
@ -2043,7 +2084,8 @@ class SugarBean
$end_index = -1, $end_index = -1,
$deleted = 0, $deleted = 0,
$optional_where = "" $optional_where = ""
) { )
{
//if bean_name is Case then use aCase //if bean_name is Case then use aCase
if ($bean_name == "Case") { if ($bean_name == "Case") {
$bean_name = "aCase"; $bean_name = "aCase";
@ -2210,6 +2252,23 @@ class SugarBean
return false; return false;
} }
/**
* Return true if duplicate_merge is enabled for this object
* You would set the duplicate_merge flag in the implementing module's vardef file.
*
* @return bool
*
* Internal function, do not override.
*/
public function is_DuplicateMergeEnabled(): bool
{
global $dictionary;
if (isset($dictionary[$this->getObjectName()]['duplicate_merge'])) {
return !empty($dictionary[$this->getObjectName()]['duplicate_merge']);
}
return false;
}
/** /**
* Returns the name of the audit table. * Returns the name of the audit table.
* Audit table's name is based on implementing class' table name. * Audit table's name is based on implementing class' table name.
@ -2401,6 +2460,8 @@ class SugarBean
$this->custom_fields->save($isUpdate); $this->custom_fields->save($isUpdate);
} }
BeanSaveHandlersManager::getInstance()->run($this, BeanSaveHandlersManager::TYPE_BEFORE);
$this->_sendNotifications($check_notify); $this->_sendNotifications($check_notify);
if ($isUpdate) { if ($isUpdate) {
@ -2413,6 +2474,8 @@ class SugarBean
SugarRelationship::resaveRelatedBeans(); SugarRelationship::resaveRelatedBeans();
} }
BeanSaveHandlersManager::getInstance()->run($this, BeanSaveHandlersManager::TYPE_AFTER);
/* BEGIN - SECURITY GROUPS - inheritance */ /* BEGIN - SECURITY GROUPS - inheritance */
require_once('modules/SecurityGroups/SecurityGroup.php'); require_once('modules/SecurityGroups/SecurityGroup.php');
SecurityGroup::inherit($this, $isUpdate); SecurityGroup::inherit($this, $isUpdate);
@ -2784,12 +2847,12 @@ class SugarBean
* *
* TODO: remove this mechanism and replace with mechanism exclusively based on the vardefs * TODO: remove this mechanism and replace with mechanism exclusively based on the vardefs
* *
* @api
* @see save_relationship_changes
* @param string|bool $new_rel_id String of the ID to add * @param string|bool $new_rel_id String of the ID to add
* @param string Relationship Name * @param string Relationship Name
* @param array $exclude any relationship's to exclude * @param array $exclude any relationship's to exclude
* @return string|bool Return the new_rel_id if it was not used. False if it was used. * @return string|bool Return the new_rel_id if it was not used. False if it was used.
* @api
* @see save_relationship_changes
*/ */
protected function handle_preset_relationships($new_rel_id, $new_rel_link, $exclude = array()) protected function handle_preset_relationships($new_rel_id, $new_rel_link, $exclude = array())
{ {
@ -2837,10 +2900,10 @@ class SugarBean
* If the vardef has entries for field <a> of type relate, where a->id_name = <b> and field <b> of type link * If the vardef has entries for field <a> of type relate, where a->id_name = <b> and field <b> of type link
* then we receive a value for b from the MVC in the _REQUEST, and it should be set in the bean as $this->$b * then we receive a value for b from the MVC in the _REQUEST, and it should be set in the bean as $this->$b
* *
* @api
* @see save_relationship_changes
* @param array $exclude any relationship's to exclude * @param array $exclude any relationship's to exclude
* @return array the list of relationships that were added or removed successfully or if they were a failure * @return array the list of relationships that were added or removed successfully or if they were a failure
* @api
* @see save_relationship_changes
*/ */
protected function handle_remaining_relate_fields($exclude = array()) protected function handle_remaining_relate_fields($exclude = array())
{ {
@ -3010,11 +3073,11 @@ class SugarBean
* Finally, we update a field listed in the _REQUEST['%/relate_id']/_REQUEST['relate_to'] mechanism * Finally, we update a field listed in the _REQUEST['%/relate_id']/_REQUEST['relate_to'] mechanism
* (if it has not already been updated) * (if it has not already been updated)
* *
* @api
* @see save_relationship_changes
* @param string|bool $new_rel_id * @param string|bool $new_rel_id
* @param string $new_rel_link * @param string $new_rel_link
* @return bool * @return bool
* @see save_relationship_changes
* @api
*/ */
protected function handle_request_relate($new_rel_id, $new_rel_link) protected function handle_request_relate($new_rel_id, $new_rel_link)
{ {
@ -3197,7 +3260,7 @@ class SugarBean
{ {
global $current_user; global $current_user;
if (($this->object_name == 'Meeting' || $this->object_name == 'Call') || $notify_user->receive_notifications) { if ((($this->object_name == 'Meeting' || $this->object_name == 'Call') || $notify_user->receive_notifications) && !$this->sentAssignmentNotifications) {
$sendToEmail = $notify_user->emailAddress->getPrimaryAddress($notify_user); $sendToEmail = $notify_user->emailAddress->getPrimaryAddress($notify_user);
$sendEmail = true; $sendEmail = true;
if (empty($sendToEmail)) { if (empty($sendToEmail)) {
@ -3262,6 +3325,7 @@ class SugarBean
$GLOBALS['log']->fatal("Notifications: error sending e-mail (method: {$notify_mail->Mailer}), " . $GLOBALS['log']->fatal("Notifications: error sending e-mail (method: {$notify_mail->Mailer}), " .
"(error: {$notify_mail->ErrorInfo})"); "(error: {$notify_mail->ErrorInfo})");
} else { } else {
$this->sentAssignmentNotifications = true;
$GLOBALS['log']->info("Notifications: e-mail successfully sent"); $GLOBALS['log']->info("Notifications: e-mail successfully sent");
} }
} }
@ -3412,8 +3476,6 @@ class SugarBean
* This function returns a paged list of the current object type. It is intended to allow for * This function returns a paged list of the current object type. It is intended to allow for
* hopping back and forth through pages of data. It only retrieves what is on the current page. * hopping back and forth through pages of data. It only retrieves what is on the current page.
* *
* @internal This method must be called on a new instance. It trashes the values of all the fields
* in the current one.
* @param string $order_by * @param string $order_by
* @param string $where Additional where clause * @param string $where Additional where clause
* @param int $row_offset Optional,default 0, starting row number * @param int $row_offset Optional,default 0, starting row number
@ -3425,6 +3487,8 @@ class SugarBean
* @return array Fetched data. * @return array Fetched data.
* *
* Internal function, do not override. * Internal function, do not override.
* @internal This method must be called on a new instance. It trashes the values of all the fields
* in the current one.
*/ */
public function get_list( public function get_list(
$order_by = "", $order_by = "",
@ -3435,7 +3499,8 @@ class SugarBean
$show_deleted = 0, $show_deleted = 0,
$singleSelect = false, $singleSelect = false,
$select_fields = array() $select_fields = array()
) { )
{
$GLOBALS['log']->debug("get_list: order_by = '$order_by' and where = '$where' and limit = '$limit'"); $GLOBALS['log']->debug("get_list: order_by = '$order_by' and where = '$where' and limit = '$limit'");
if (isset($_SESSION['show_deleted'])) { if (isset($_SESSION['show_deleted'])) {
$show_deleted = 1; $show_deleted = 1;
@ -3516,7 +3581,8 @@ class SugarBean
$parentbean = null, $parentbean = null,
$singleSelect = false, $singleSelect = false,
$ifListForExport = false $ifListForExport = false
) { )
{
$selectedFields = array(); $selectedFields = array();
$secondarySelectedFields = array(); $secondarySelectedFields = array();
$ret_array = array(); $ret_array = array();
@ -4290,7 +4356,7 @@ class SugarBean
* *
* Internal function, do not override. * Internal function, do not override.
*/ */
public function create_list_count_query($query) public function create_list_count_query($query, $alias = 'c')
{ {
// remove the 'order by' clause which is expected to be at the end of the query // remove the 'order by' clause which is expected to be at the end of the query
$pattern = '/\sORDER BY.*/is'; $pattern = '/\sORDER BY.*/is';
@ -4308,7 +4374,7 @@ class SugarBean
// change the select expression to 'count(*)' // change the select expression to 'count(*)'
$pattern = '/SELECT(.*?)(\s){1}FROM(\s){1}/is'; $pattern = '/SELECT(.*?)(\s){1}FROM(\s){1}/is';
$replacement = 'SELECT count(' . $star . ') c FROM '; $replacement = 'SELECT count(' . $star . ') '. $alias .' FROM ';
//if the passed query has union clause then replace all instances of the pattern. //if the passed query has union clause then replace all instances of the pattern.
//this is very rare. I have seen this happening only from projects module. //this is very rare. I have seen this happening only from projects module.
@ -4328,7 +4394,7 @@ class SugarBean
$star = 'DISTINCT ' . $this->table_name . '.id'; $star = 'DISTINCT ' . $this->table_name . '.id';
} }
} // if } // if
$replacement = 'SELECT count(' . $star . ') c FROM '; $replacement = 'SELECT count(' . $star . ') '. $alias .' FROM ';
$union_qs[$key] = preg_replace($pattern, $replacement, $union_query, 1); $union_qs[$key] = preg_replace($pattern, $replacement, $union_query, 1);
} }
$modified_select_query = implode(" UNION ALL ", $union_qs); $modified_select_query = implode(" UNION ALL ", $union_qs);
@ -4371,9 +4437,6 @@ class SugarBean
* *
* It is intended for use in navigation buttons on the DetailView. It will pass an offset * It is intended for use in navigation buttons on the DetailView. It will pass an offset
* and limit argument to the sql query. * and limit argument to the sql query.
* @internal This method must be called on a new instance. It overrides the values of all the fields
* in the current one.
*
* @param string $order_by * @param string $order_by
* @param string $where Additional where clause * @param string $where Additional where clause
* @param int $offset * @param int $offset
@ -4384,6 +4447,9 @@ class SugarBean
* @return array Fetched data. * @return array Fetched data.
* *
* Internal function, do not override. * Internal function, do not override.
* @internal This method must be called on a new instance. It overrides the values of all the fields
* in the current one.
*
*/ */
public function get_detail( public function get_detail(
$order_by = "", $order_by = "",
@ -4393,7 +4459,8 @@ class SugarBean
$limit = -1, $limit = -1,
$max = -1, $max = -1,
$show_deleted = 0 $show_deleted = 0
) { )
{
$GLOBALS['log']->debug("get_detail: order_by = '$order_by' and where = '$where' and limit = '$limit' " . $GLOBALS['log']->debug("get_detail: order_by = '$order_by' and where = '$where' and limit = '$limit' " .
"and offset = '$offset'"); "and offset = '$offset'");
if (isset($_SESSION['show_deleted'])) { if (isset($_SESSION['show_deleted'])) {
@ -4525,7 +4592,7 @@ class SugarBean
$query .= " AND $this->table_name.deleted=0"; $query .= " AND $this->table_name.deleted=0";
} }
$GLOBALS['log']->debug("Retrieve $this->object_name : " . $query); $GLOBALS['log']->debug("Retrieve $this->object_name : " . $query);
$result = $this->db->limitQuery($query, 0, 1, true, "Retrieving record by id $this->table_name:$id found "); $result = $this->db->limitQuery($query, 0, 1, false, "Retrieving record by id $this->table_name:$id found ");
if (empty($result)) { if (empty($result)) {
return null; return null;
} }
@ -5070,7 +5137,8 @@ class SugarBean
$row_offset = 0, $row_offset = 0,
$limit = -1, $limit = -1,
$max = -1 $max = -1
) { )
{
global $layout_edit_mode; global $layout_edit_mode;
if (isset($layout_edit_mode) && $layout_edit_mode) { if (isset($layout_edit_mode) && $layout_edit_mode) {
@ -5544,7 +5612,8 @@ class SugarBean
$order_by = '', $order_by = '',
$limit = '', $limit = '',
$row_offset = 0 $row_offset = 0
) { )
{
$db = DBManagerFactory::getInstance('listviews'); $db = DBManagerFactory::getInstance('listviews');
// No need to do an additional query // No need to do an additional query
$GLOBALS['log']->debug("Finding linked records $this->object_name: " . $query); $GLOBALS['log']->debug("Finding linked records $this->object_name: " . $query);
@ -5899,7 +5968,8 @@ class SugarBean
$check_duplicates = true, $check_duplicates = true,
$do_update = false, $do_update = false,
$data_values = null $data_values = null
) { )
{
$where = ''; $where = '';
// make sure there is a date modified // make sure there is a date modified
@ -6158,7 +6228,8 @@ class SugarBean
public function add_address_streets( public function add_address_streets(
$street_field $street_field
) { )
{
if (isset($this->$street_field)) { if (isset($this->$street_field)) {
$street_field_2 = $street_field . '_2'; $street_field_2 = $street_field . '_2';
$street_field_3 = $street_field . '_3'; $street_field_3 = $street_field . '_3';
@ -6187,7 +6258,8 @@ class SugarBean
*/ */
public function populateRelatedBean( public function populateRelatedBean(
SugarBean $new_bean SugarBean $new_bean
) { )
{
} }
/** /**
@ -6226,7 +6298,7 @@ class SugarBean
*/ */
public function auditBean($isUpdate) public function auditBean($isUpdate)
{ {
if ($this->is_AuditEnabled() && $isUpdate) { if ($this->is_AuditEnabled() && $isUpdate && !$this->createdAuditRecords) {
$auditDataChanges = $this->db->getAuditDataChanges($this); $auditDataChanges = $this->db->getAuditDataChanges($this);
if (!empty($auditDataChanges)) { if (!empty($auditDataChanges)) {
@ -6249,5 +6321,6 @@ class SugarBean
$this->db->save_audit_records($this, $change); $this->db->save_audit_records($this, $change);
$this->fetched_row[$change['field_name']] = $change['after']; $this->fetched_row[$change['field_name']] = $change['after'];
} }
$this->createdAuditRecords = true;
} }
} }

251
files.md5
View file

@ -1,8 +1,9 @@
<?php <?php
// created: 2021-04-28 17:00:00 // created: 2021-08-18 17:00:00
$md5_string = array ( $md5_string = array (
'./.gitignore' => 'deaa6f875467f423cf0e8e193b552172',
'./Api/Core/Config/ApiConfig.php' => '69a1e7b3d7755a2a63499a16ddae81cf', './Api/Core/Config/ApiConfig.php' => '69a1e7b3d7755a2a63499a16ddae81cf',
'./Api/Core/Config/slim.php' => 'b2827381c1aee4dce054128c77984c8f', './Api/Core/Config/slim.php' => 'b134e68765e6a1403577e2a5a06322b8',
'./Api/Core/Loader/ContainerLoader.php' => '6d5e0db5708f5e34bec7ba8fb8196bdc', './Api/Core/Loader/ContainerLoader.php' => '6d5e0db5708f5e34bec7ba8fb8196bdc',
'./Api/Core/Loader/CustomLoader.php' => '318e170f91b6af19720eede0664b3d23', './Api/Core/Loader/CustomLoader.php' => '318e170f91b6af19720eede0664b3d23',
'./Api/Core/Loader/RouteLoader.php' => '6a3f49e187080d4e5ea497483da39b2d', './Api/Core/Loader/RouteLoader.php' => '6a3f49e187080d4e5ea497483da39b2d',
@ -17,7 +18,7 @@ $md5_string = array (
'./Api/V8/Config/services/factories.php' => 'abedc3b0445f9076cf55fb81f922999b', './Api/V8/Config/services/factories.php' => 'abedc3b0445f9076cf55fb81f922999b',
'./Api/V8/Config/services/globals.php' => 'd1bdcccf5150b16b84fc8192f63affdd', './Api/V8/Config/services/globals.php' => 'd1bdcccf5150b16b84fc8192f63affdd',
'./Api/V8/Config/services/helpers.php' => 'd15737677999e4f7307443aa83da8afa', './Api/V8/Config/services/helpers.php' => 'd15737677999e4f7307443aa83da8afa',
'./Api/V8/Config/services/middlewares.php' => '6f083e9dfe547fa41b87c8ee2282b0cc', './Api/V8/Config/services/middlewares.php' => '18dde9147c371f54d571ba15e2ed329c',
'./Api/V8/Config/services/params.php' => '9fd77ca190fbcea45ad11f156d5db9b7', './Api/V8/Config/services/params.php' => '9fd77ca190fbcea45ad11f156d5db9b7',
'./Api/V8/Config/services/services.php' => '1c6d1cc19c087015430b4b965705e2fb', './Api/V8/Config/services/services.php' => '1c6d1cc19c087015430b4b965705e2fb',
'./Api/V8/Config/services/validators.php' => '884d713ad8ed932500039acaf285fa45', './Api/V8/Config/services/validators.php' => '884d713ad8ed932500039acaf285fa45',
@ -35,11 +36,12 @@ $md5_string = array (
'./Api/V8/Factory/ParamsMiddlewareFactory.php' => 'f62b0bae71f85f0320b27c98a596a24c', './Api/V8/Factory/ParamsMiddlewareFactory.php' => 'f62b0bae71f85f0320b27c98a596a24c',
'./Api/V8/Factory/ValidatorFactory.php' => '499dd75139d22b4554544c06f0ac7e48', './Api/V8/Factory/ValidatorFactory.php' => '499dd75139d22b4554544c06f0ac7e48',
'./Api/V8/Helper/ModuleListProvider.php' => 'a6f9b90116408bd7d708801b0cd04001', './Api/V8/Helper/ModuleListProvider.php' => 'a6f9b90116408bd7d708801b0cd04001',
'./Api/V8/Helper/OsHelper.php' => '3fa3a69441695035a66e877fbfd0d6c2',
'./Api/V8/Helper/VarDefHelper.php' => '986916d5e675667e5f5e89da6d8fc081', './Api/V8/Helper/VarDefHelper.php' => '986916d5e675667e5f5e89da6d8fc081',
'./Api/V8/JsonApi/Helper/AttributeObjectHelper.php' => '8c2e2f889cefdc7912fd62da3e6a6f71', './Api/V8/JsonApi/Helper/AttributeObjectHelper.php' => '8c2e2f889cefdc7912fd62da3e6a6f71',
'./Api/V8/JsonApi/Helper/PaginationObjectHelper.php' => 'dbeb8f36cc7b70ff9459443c26bdfb70', './Api/V8/JsonApi/Helper/PaginationObjectHelper.php' => 'dbeb8f36cc7b70ff9459443c26bdfb70',
'./Api/V8/JsonApi/Helper/RelationshipObjectHelper.php' => '6681a3fc26e420f12875d4239532946e', './Api/V8/JsonApi/Helper/RelationshipObjectHelper.php' => '6681a3fc26e420f12875d4239532946e',
'./Api/V8/JsonApi/Repository/Filter.php' => 'e0d1441edbced7dc3c0282d2b6a3cb70', './Api/V8/JsonApi/Repository/Filter.php' => 'cc024de98508d60c0d091a58a49fa879',
'./Api/V8/JsonApi/Repository/Sort.php' => '7e9fb4704a056bc944840def1482042d', './Api/V8/JsonApi/Repository/Sort.php' => '7e9fb4704a056bc944840def1482042d',
'./Api/V8/JsonApi/Response/AttributeResponse.php' => '84318e63e42f0062c8f8231fd4c230d5', './Api/V8/JsonApi/Response/AttributeResponse.php' => '84318e63e42f0062c8f8231fd4c230d5',
'./Api/V8/JsonApi/Response/DataResponse.php' => '08239b06a911f9d0bd46a28a28d11eda', './Api/V8/JsonApi/Response/DataResponse.php' => '08239b06a911f9d0bd46a28a28d11eda',
@ -115,7 +117,7 @@ $md5_string = array (
'./ModuleInstall/PackageManager/tpls/PackageManagerLicense.tpl' => 'df5e267d1df5ce08fb9406e42d5b4816', './ModuleInstall/PackageManager/tpls/PackageManagerLicense.tpl' => 'df5e267d1df5ce08fb9406e42d5b4816',
'./ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl' => '98e396c0aa57329731fda19c790fffb2', './ModuleInstall/PackageManager/tpls/PackageManagerScripts.tpl' => '98e396c0aa57329731fda19c790fffb2',
'./ModuleInstall/extensions.php' => '87596ad3f28a39c996a5551cad3b5cab', './ModuleInstall/extensions.php' => '87596ad3f28a39c996a5551cad3b5cab',
'./README.md' => '9c639e220ed095c577fcf155a1bff5c7', './README.md' => '32252d95761ee022e09c9a54ddde4d95',
'./RoboFile.php' => '045b82c1df69553824d0e4ffcce6e03c', './RoboFile.php' => '045b82c1df69553824d0e4ffcce6e03c',
'./SugarSecurity.php' => '47e316b2d408e8c5192c8ea4a4f921b3', './SugarSecurity.php' => '47e316b2d408e8c5192c8ea4a4f921b3',
'./TreeData.php' => '32873e20cb5fd33f9d1cdaf18c3cac5c', './TreeData.php' => '32873e20cb5fd33f9d1cdaf18c3cac5c',
@ -503,9 +505,11 @@ $md5_string = array (
'./Zend/Validate/Interface.php' => 'e313ef824309253dcfab90ff1d38ac86', './Zend/Validate/Interface.php' => 'e313ef824309253dcfab90ff1d38ac86',
'./Zend/Validate/Ip.php' => 'e313ef824309253dcfab90ff1d38ac86', './Zend/Validate/Ip.php' => 'e313ef824309253dcfab90ff1d38ac86',
'./Zend/Version.php' => 'e313ef824309253dcfab90ff1d38ac86', './Zend/Version.php' => 'e313ef824309253dcfab90ff1d38ac86',
'./build/push_output.sh' => 'cde8cd38e3b0c4e988ec4be7d81faa89',
'./build/travis-ci-apache' => 'e1e212c4eaf679b6ec620cd0b12f4571',
'./campaign_tracker.php' => '321e43ca8b664e6ca57ae5589e8c0667', './campaign_tracker.php' => '321e43ca8b664e6ca57ae5589e8c0667',
'./composer.json' => 'd52907adc20637f882f43de78ef75101', './composer.json' => 'ec30e8bd48195ff38dd62cbcde73c2a7',
'./composer.lock' => 'b97e21140d5f75f8c0002393d3e0a261', './composer.lock' => '638558a83673b7e29ef0c5d4bf8189d3',
'./cron.php' => '0b8b6bd839a2232a8da074b31feaa708', './cron.php' => '0b8b6bd839a2232a8da074b31feaa708',
'./crossdomain.xml' => '24b7711640c652b21aa89c9d83d6ec13', './crossdomain.xml' => '24b7711640c652b21aa89c9d83d6ec13',
'./data/BeanFactory.php' => '84b7c36b6a59ea8c5c4069659cc72950', './data/BeanFactory.php' => '84b7c36b6a59ea8c5c4069659cc72950',
@ -519,13 +523,14 @@ $md5_string = array (
'./data/Relationships/One2OneRelationship.php' => 'c46d3067d5651fbc928763600d5e1a51', './data/Relationships/One2OneRelationship.php' => 'c46d3067d5651fbc928763600d5e1a51',
'./data/Relationships/RelationshipFactory.php' => '98a46e44186f2d2db23be9b894a4f1e2', './data/Relationships/RelationshipFactory.php' => '98a46e44186f2d2db23be9b894a4f1e2',
'./data/Relationships/SugarRelationship.php' => 'a71b96492ee7457826fc91a2356c4ebd', './data/Relationships/SugarRelationship.php' => 'a71b96492ee7457826fc91a2356c4ebd',
'./data/SugarBean.php' => '4a0fa642f22c6051175a1680d1e688b6', './data/SugarBean.php' => 'd4f57253f79507904f9eacc6502dde53',
'./deprecated.php' => 'f5f507fd6314f38d29c97e2cc2c62239', './deprecated.php' => 'f5f507fd6314f38d29c97e2cc2c62239',
'./dictionary.php' => 'b7c1370fb75a2940c04db74627c4462c', './dictionary.php' => 'b7c1370fb75a2940c04db74627c4462c',
'./download.php' => 'f2d366039d134ac463ff1e75634ce509', './download.php' => 'f2d366039d134ac463ff1e75634ce509',
'./emailmandelivery.php' => 'e079e094dd3d4e361670a179f50b1fdd', './emailmandelivery.php' => 'e079e094dd3d4e361670a179f50b1fdd',
'./export.php' => '299a444bd270a6149c02ae8b7bbb3726', './export.php' => '299a444bd270a6149c02ae8b7bbb3726',
'./ical_server.php' => '36acd0eb4bdabcdb8c70497b5cc79d16', './ical_server.php' => '36acd0eb4bdabcdb8c70497b5cc79d16',
'./include/CleanCSV.php' => '2378fc271631a459101571e1f6e78e0a',
'./include/Dashlets/Dashlet.php' => 'eef3246fc86fc80f465bd2550fffb8b2', './include/Dashlets/Dashlet.php' => 'eef3246fc86fc80f465bd2550fffb8b2',
'./include/Dashlets/DashletCacheBuilder.php' => '98a49e1176f330a59598e764ce0c6359', './include/Dashlets/DashletCacheBuilder.php' => '98a49e1176f330a59598e764ce0c6359',
'./include/Dashlets/DashletFooter.tpl' => '63e2f0394e217d1f0dcd196182e9e3a3', './include/Dashlets/DashletFooter.tpl' => '63e2f0394e217d1f0dcd196182e9e3a3',
@ -732,7 +737,7 @@ $md5_string = array (
'./include/Imap/ImapTestSettingsEntryHandler.php' => '3292a309c3331e60ab13f48c56e672c8', './include/Imap/ImapTestSettingsEntryHandler.php' => '3292a309c3331e60ab13f48c56e672c8',
'./include/Imap.php' => '0f93494ddbae70f85acdcbac5e92dbc5', './include/Imap.php' => '0f93494ddbae70f85acdcbac5e92dbc5',
'./include/ImapInterface.php' => '1cc17060f7768a0e299fafdd66410baa', './include/ImapInterface.php' => '1cc17060f7768a0e299fafdd66410baa',
'./include/InlineEditing/InlineEditing.php' => 'dd04aef467763634574004edf042d45d', './include/InlineEditing/InlineEditing.php' => '95864a199590f0e31ce66745da7a1d1f',
'./include/InlineEditing/inlineEditing.js' => 'ebc8c66cf49a2bcc77265461a120fe3c', './include/InlineEditing/inlineEditing.js' => 'ebc8c66cf49a2bcc77265461a120fe3c',
'./include/JSON.php' => '7cff996ad7e96ff1583e0837f5070f29', './include/JSON.php' => '7cff996ad7e96ff1583e0837f5070f29',
'./include/JsonApiErrorObject.php' => 'bd82e5413b53492f73cb66fa0fe35316', './include/JsonApiErrorObject.php' => 'bd82e5413b53492f73cb66fa0fe35316',
@ -764,7 +769,7 @@ $md5_string = array (
'./include/MVC/Controller/action_view_map.php' => 'fb0f1173db35edb1ed4ed191896f6274', './include/MVC/Controller/action_view_map.php' => 'fb0f1173db35edb1ed4ed191896f6274',
'./include/MVC/Controller/entry_point_registry.php' => '5fea028a937710994f0a5f5fff1a2791', './include/MVC/Controller/entry_point_registry.php' => '5fea028a937710994f0a5f5fff1a2791',
'./include/MVC/Controller/file_access_control_map.php' => '86baf77effe4eb6167c4557c481c2f5f', './include/MVC/Controller/file_access_control_map.php' => '86baf77effe4eb6167c4557c481c2f5f',
'./include/MVC/SugarApplication.php' => 'c982ac6fbd6e5fb39a245ac19b7eb9b5', './include/MVC/SugarApplication.php' => '6097782e329ee0ba4ac5ea2a5969a361',
'./include/MVC/SugarModule.php' => '7ffbda56ac7bd074795034533ef93c1a', './include/MVC/SugarModule.php' => '7ffbda56ac7bd074795034533ef93c1a',
'./include/MVC/View/SugarView.php' => '0d7a57ef9c764d60de0b7cd25bb463c7', './include/MVC/View/SugarView.php' => '0d7a57ef9c764d60de0b7cd25bb463c7',
'./include/MVC/View/ViewFactory.php' => 'a1ee66d0bd884132187ad0e8196a56c9', './include/MVC/View/ViewFactory.php' => 'a1ee66d0bd884132187ad0e8196a56c9',
@ -966,13 +971,13 @@ $md5_string = array (
'./include/StateCheckerDirectoryIterator.php' => 'b89153cd6d0ba4b17de2f9469278ac47', './include/StateCheckerDirectoryIterator.php' => 'b89153cd6d0ba4b17de2f9469278ac47',
'./include/SubPanel/SubPanel.js' => '618e95f14a83813efb3b30142d1542af', './include/SubPanel/SubPanel.js' => '618e95f14a83813efb3b30142d1542af',
'./include/SubPanel/SubPanel.php' => '2abdfe0c3b2533412b1f56f35a161dfb', './include/SubPanel/SubPanel.php' => '2abdfe0c3b2533412b1f56f35a161dfb',
'./include/SubPanel/SubPanelDefinitions.php' => 'd925ac2c6b03298c2b70a7630ca526f9', './include/SubPanel/SubPanelDefinitions.php' => 'e8ff9f462206e274dc88a72386a0c70a',
'./include/SubPanel/SubPanelDynamic.html' => '31c84e19f78d0c392072814b5d7853b7', './include/SubPanel/SubPanelDynamic.html' => '31c84e19f78d0c392072814b5d7853b7',
'./include/SubPanel/SubPanelRowCounter.php' => '4f53be54693f59a654b4b41aeeda9d32', './include/SubPanel/SubPanelRowCounter.php' => '4f53be54693f59a654b4b41aeeda9d32',
'./include/SubPanel/SubPanelSearchDisplay.php' => '3d8ffeae4b8c5d6c6114023522854fbf', './include/SubPanel/SubPanelSearchDisplay.php' => '3d8ffeae4b8c5d6c6114023522854fbf',
'./include/SubPanel/SubPanelSearchForm.php' => '0c1310aeb0d995bc740e69177550c6cd', './include/SubPanel/SubPanelSearchForm.php' => '0c1310aeb0d995bc740e69177550c6cd',
'./include/SubPanel/SubPanelTiles.js' => '56db912840e571aff66e6a7032c6e682', './include/SubPanel/SubPanelTiles.js' => '56db912840e571aff66e6a7032c6e682',
'./include/SubPanel/SubPanelTiles.php' => 'ee68cf8c8272e19087246454fd72f89d', './include/SubPanel/SubPanelTiles.php' => '4264b396cc083fb033dc7c6db2a54f33',
'./include/SubPanel/SubPanelTilesTabs.php' => 'e150f91f4cac7eaa55c2c43c21d2c3d2', './include/SubPanel/SubPanelTilesTabs.php' => 'e150f91f4cac7eaa55c2c43c21d2c3d2',
'./include/SubPanel/SubPanelViewer.php' => 'a833bafe058a680dd223a7cec0dc2602', './include/SubPanel/SubPanelViewer.php' => 'a833bafe058a680dd223a7cec0dc2602',
'./include/SubPanel/SugarTab.php' => '61e5ffb1c49f274b89675cc751a176d8', './include/SubPanel/SugarTab.php' => '61e5ffb1c49f274b89675cc751a176d8',
@ -1190,12 +1195,12 @@ $md5_string = array (
'./include/SugarFields/Parsers/SearchFormMetaParser.php' => '6846ea418bd2196a0f457939c65a107b', './include/SugarFields/Parsers/SearchFormMetaParser.php' => '6846ea418bd2196a0f457939c65a107b',
'./include/SugarFields/SugarFieldHandler.php' => 'c65abef980ae501bb2c12029075536bc', './include/SugarFields/SugarFieldHandler.php' => 'c65abef980ae501bb2c12029075536bc',
'./include/SugarFolders/SugarFolderEmptyException.php' => 'd8052a2f3abf6ff8db9563bf3e22842e', './include/SugarFolders/SugarFolderEmptyException.php' => 'd8052a2f3abf6ff8db9563bf3e22842e',
'./include/SugarFolders/SugarFolders.php' => '0d27305896436b2789f04a9497779e7b', './include/SugarFolders/SugarFolders.php' => '51ed64e78907559c6c5b5fd447280f32',
'./include/SugarHtml/SugarHtml.php' => 'b457a731768480ce81d6e709d920e2cb', './include/SugarHtml/SugarHtml.php' => 'b457a731768480ce81d6e709d920e2cb',
'./include/SugarHttpClient.php' => 'bf0aedbad0c73763186e37fb9107d3d7', './include/SugarHttpClient.php' => 'bf0aedbad0c73763186e37fb9107d3d7',
'./include/SugarLogger/LoggerManager.php' => 'd30492d39dc1aecce2e9cabdc4c148e8', './include/SugarLogger/LoggerManager.php' => 'd30492d39dc1aecce2e9cabdc4c148e8',
'./include/SugarLogger/LoggerTemplate.php' => '98f71c83836d530220292bb05012d35f', './include/SugarLogger/LoggerTemplate.php' => '98f71c83836d530220292bb05012d35f',
'./include/SugarLogger/SugarLogger.php' => 'd7b2311a2c580c65aca033589f039a9c', './include/SugarLogger/SugarLogger.php' => '6d9af5c4188da26af4e791ec168c3cf6',
'./include/SugarOAuthServer.php' => 'c0f2ca51199ee2876bcfcdd82f47875d', './include/SugarOAuthServer.php' => 'c0f2ca51199ee2876bcfcdd82f47875d',
'./include/SugarOauth.php' => '2911b35f051569a701eecb9d53f23597', './include/SugarOauth.php' => '2911b35f051569a701eecb9d53f23597',
'./include/SugarObjects/LanguageManager.php' => 'a2bae88124926a27721ce4d6f1e9bd50', './include/SugarObjects/LanguageManager.php' => 'a2bae88124926a27721ce4d6f1e9bd50',
@ -1211,7 +1216,7 @@ $md5_string = array (
'./include/SugarObjects/implements/security_groups/vardefs.php' => 'b7a5dd20f8ea3d8e73ebdd8f403974b9', './include/SugarObjects/implements/security_groups/vardefs.php' => 'b7a5dd20f8ea3d8e73ebdd8f403974b9',
'./include/SugarObjects/implements/team_security/language/en_us.lang.php' => 'ae04a55a0515ca263b3006493ab3c23a', './include/SugarObjects/implements/team_security/language/en_us.lang.php' => 'ae04a55a0515ca263b3006493ab3c23a',
'./include/SugarObjects/implements/team_security/vardefs.php' => 'c914f1e4b5f0a47b47799011ba209375', './include/SugarObjects/implements/team_security/vardefs.php' => 'c914f1e4b5f0a47b47799011ba209375',
'./include/SugarObjects/templates/basic/Basic.php' => '96166101d8261e5fc0ab7348f9f9fb1a', './include/SugarObjects/templates/basic/Basic.php' => '0b4982ef0c67b70b4b2b130d33defa95',
'./include/SugarObjects/templates/basic/Dashlets/Dashlet/m-n-Dashlet.meta.php' => '636630c684bc4b16b490c408b4751903', './include/SugarObjects/templates/basic/Dashlets/Dashlet/m-n-Dashlet.meta.php' => '636630c684bc4b16b490c408b4751903',
'./include/SugarObjects/templates/basic/Dashlets/Dashlet/m-n-Dashlet.php' => '37ec124e52fd31b3c2622ad16e6cd7f7', './include/SugarObjects/templates/basic/Dashlets/Dashlet/m-n-Dashlet.php' => '37ec124e52fd31b3c2622ad16e6cd7f7',
'./include/SugarObjects/templates/basic/icons/Createbasic.gif' => '8730fdfcc63d4d2d0f0931be9b47c9cd', './include/SugarObjects/templates/basic/icons/Createbasic.gif' => '8730fdfcc63d4d2d0f0931be9b47c9cd',
@ -1508,7 +1513,7 @@ $md5_string = array (
'./include/dir_inc.php' => '4ec954313ef7c8b164ec1232a1ec1bd7', './include/dir_inc.php' => '4ec954313ef7c8b164ec1232a1ec1bd7',
'./include/entryPoint.php' => 'fb6a599a4825228c011457393f40a482', './include/entryPoint.php' => 'fb6a599a4825228c011457393f40a482',
'./include/entryPointConfirmOptInConnector.php' => '66fed04564c4f4182f3b277d5b6dfafc', './include/entryPointConfirmOptInConnector.php' => '66fed04564c4f4182f3b277d5b6dfafc',
'./include/export_utils.php' => 'db5725a8d87429057f27d8b11653fab2', './include/export_utils.php' => '1aadde47b27108f22b6aa52342489c6e',
'./include/externalAPI/Base/ExternalAPIBase.php' => 'e52639773bbdaa1d9e3308fd7a41e392', './include/externalAPI/Base/ExternalAPIBase.php' => 'e52639773bbdaa1d9e3308fd7a41e392',
'./include/externalAPI/Base/ExternalAPIPlugin.php' => '9f8d318d518a9f950fd0d80a6bac7c20', './include/externalAPI/Base/ExternalAPIPlugin.php' => '9f8d318d518a9f950fd0d80a6bac7c20',
'./include/externalAPI/Base/ExternalOAuthAPIPlugin.php' => 'fd065e2de29e6fa0dfc86956e2c86230', './include/externalAPI/Base/ExternalOAuthAPIPlugin.php' => 'fd065e2de29e6fa0dfc86956e2c86230',
@ -2512,7 +2517,7 @@ $md5_string = array (
'./include/javascript/yui/build/yuitest/yuitest_core.js' => 'ed5230a0f4a885d8ea51c2fe78895d07', './include/javascript/yui/build/yuitest/yuitest_core.js' => 'ed5230a0f4a885d8ea51c2fe78895d07',
'./include/javascript/yui/ygDDList.js' => '0cd9051a220de7e8c79bf5b9cccce10f', './include/javascript/yui/ygDDList.js' => '0cd9051a220de7e8c79bf5b9cccce10f',
'./include/json_config.php' => 'ba7fb6f2fb1df51bc367835406ef7ba5', './include/json_config.php' => 'ba7fb6f2fb1df51bc367835406ef7ba5',
'./include/language/en_us.lang.php' => '1ebc176c890dd4b944830bf46b9f2107', './include/language/en_us.lang.php' => 'f7de79e65ab359c298fee0bb07eb82dd',
'./include/language/en_us.notify_template.html' => 'c6a897ace7af46a44889dfab1a9d44c5', './include/language/en_us.notify_template.html' => 'c6a897ace7af46a44889dfab1a9d44c5',
'./include/language/getJSLanguage.php' => '1bc910bd5a9953fbf443d3d97fddbffa', './include/language/getJSLanguage.php' => '1bc910bd5a9953fbf443d3d97fddbffa',
'./include/language/jsLanguage.php' => 'a4f5810e3d1a3c4d0aad0c63b6860beb', './include/language/jsLanguage.php' => 'a4f5810e3d1a3c4d0aad0c63b6860beb',
@ -2631,7 +2636,7 @@ $md5_string = array (
'./include/utils/security_utils.php' => 'e953d0b673df3df313ecf1ac975e8f57', './include/utils/security_utils.php' => 'e953d0b673df3df313ecf1ac975e8f57',
'./include/utils/sugar_file_utils.php' => '1c1915cad8c88feb0edbf5bbaee106c4', './include/utils/sugar_file_utils.php' => '1c1915cad8c88feb0edbf5bbaee106c4',
'./include/utils/zip_utils.php' => '0fcb792c490846bec4b9d85ded87f775', './include/utils/zip_utils.php' => '0fcb792c490846bec4b9d85ded87f775',
'./include/utils.php' => 'e1b2f454a7c4b4766a3a67efec3c8d60', './include/utils.php' => '3a1d276356eb3f7a25ec9296877c5ef9',
'./include/vCard.php' => '44052bbedcdaba3fdf67cfc10a112e75', './include/vCard.php' => '44052bbedcdaba3fdf67cfc10a112e75',
'./include/ytree/ExtNode.php' => '37505681784fe398c98fd5950a414fc2', './include/ytree/ExtNode.php' => '37505681784fe398c98fd5950a414fc2',
'./include/ytree/JQueryTree.php' => '3712d2224b93818b990b876f8405b745', './include/ytree/JQueryTree.php' => '3712d2224b93818b990b876f8405b745',
@ -2724,7 +2729,7 @@ $md5_string = array (
'./install/install_defaults.php' => 'd25503407f0db14fa875b295d0f34ae5', './install/install_defaults.php' => 'd25503407f0db14fa875b295d0f34ae5',
'./install/install_utils.php' => '8fb3fc994c368eecd4c875bf0dee4479', './install/install_utils.php' => '8fb3fc994c368eecd4c875bf0dee4479',
'./install/lang.config.php' => 'cb3e68fdb0600481497dcd60f0746aca', './install/lang.config.php' => 'cb3e68fdb0600481497dcd60f0746aca',
'./install/language/en_us.lang.php' => '8bfb019414515115e1fd6a37e75b64e3', './install/language/en_us.lang.php' => '443a21c6c24b089d6dc085a3ebb588d8',
'./install/license.js' => '9b5c798584a7ae54703dcfa2d1bb991f', './install/license.js' => '9b5c798584a7ae54703dcfa2d1bb991f',
'./install/license.php' => '73aecaa43ecaf1743897049f991fb785', './install/license.php' => '73aecaa43ecaf1743897049f991fb785',
'./install/licensePrint.php' => 'd8e905c5b6c769cd726ad94399118d88', './install/licensePrint.php' => 'd8e905c5b6c769cd726ad94399118d88',
@ -3152,7 +3157,7 @@ $md5_string = array (
'./metadata/user_feedsMetaData.php' => '95afa64e44236f27a5ca6f8ed6c45b7a', './metadata/user_feedsMetaData.php' => '95afa64e44236f27a5ca6f8ed6c45b7a',
'./metadata/usersMetaData.php' => 'a0e51e5d5a49b1f89af75ff58abd8df0', './metadata/usersMetaData.php' => 'a0e51e5d5a49b1f89af75ff58abd8df0',
'./metadata/users_last_importMetaData.php' => '70a94c871df91c8663a57bee7aeb623f', './metadata/users_last_importMetaData.php' => '70a94c871df91c8663a57bee7aeb623f',
'./metadata/users_passwordLinkMetaData.php' => 'e2adb91a892f956a21d3a37195111e02', './metadata/users_passwordLinkMetaData.php' => 'af3ed60360e263f35ed23f85e515a511',
'./metadata/users_signaturesMetaData.php' => '46aee1091eeafe3426d2435607763694', './metadata/users_signaturesMetaData.php' => '46aee1091eeafe3426d2435607763694',
'./modules/ACL/ACLController.php' => 'db2013b39620e8c5517320fc6e414034', './modules/ACL/ACLController.php' => 'db2013b39620e8c5517320fc6e414034',
'./modules/ACL/ACLJSController.php' => '455b480e63747c3cb4d5abe374effe14', './modules/ACL/ACLJSController.php' => '455b480e63747c3cb4d5abe374effe14',
@ -3160,7 +3165,7 @@ $md5_string = array (
'./modules/ACL/List.php' => '206a1b6ad4f3de12145044e83e6f1692', './modules/ACL/List.php' => '206a1b6ad4f3de12145044e83e6f1692',
'./modules/ACL/Menu.php' => 'ba8ded675cca220762fd0b06be93ea3c', './modules/ACL/Menu.php' => 'ba8ded675cca220762fd0b06be93ea3c',
'./modules/ACL/Save.php' => '3b5f8082be2834f67425e1e0febdc4b6', './modules/ACL/Save.php' => '3b5f8082be2834f67425e1e0febdc4b6',
'./modules/ACL/install_actions.php' => '4b7fe6445038875943be1807476bd64f', './modules/ACL/install_actions.php' => 'b534ed369fb1ef22d41670cec842a5c7',
'./modules/ACL/language/en_us.lang.php' => 'a23ed1fea223a17993d5396bc1b85894', './modules/ACL/language/en_us.lang.php' => 'a23ed1fea223a17993d5396bc1b85894',
'./modules/ACL/metadata/subpaneldefs.php' => 'eeb92f8d430ef3fcc134cf83dc972497', './modules/ACL/metadata/subpaneldefs.php' => 'eeb92f8d430ef3fcc134cf83dc972497',
'./modules/ACL/remove_actions.php' => 'ef5cfced421481c113e0e04ee640c3d8', './modules/ACL/remove_actions.php' => 'ef5cfced421481c113e0e04ee640c3d8',
@ -3466,7 +3471,7 @@ $md5_string = array (
'./modules/AOP_Case_Events/vardefs.php' => '60dca3b5b4b11e9c0cf6969f262211eb', './modules/AOP_Case_Events/vardefs.php' => '60dca3b5b4b11e9c0cf6969f262211eb',
'./modules/AOP_Case_Updates/AOPAssignManager.php' => 'ecc13c6a6f19283ca117b723e4da66b0', './modules/AOP_Case_Updates/AOPAssignManager.php' => 'ecc13c6a6f19283ca117b723e4da66b0',
'./modules/AOP_Case_Updates/AOP_Case_Updates.php' => '97ea70e6860015ff65554bbd60dcb901', './modules/AOP_Case_Updates/AOP_Case_Updates.php' => '97ea70e6860015ff65554bbd60dcb901',
'./modules/AOP_Case_Updates/CaseUpdatesHook.php' => '9ad88eae9b25916979c832b7c32edd85', './modules/AOP_Case_Updates/CaseUpdatesHook.php' => '807c6fd3beeacfc4ecafcfb6856f9029',
'./modules/AOP_Case_Updates/Case_Updates.php' => 'b8bcf0da7510631fb30a38e6407517fc', './modules/AOP_Case_Updates/Case_Updates.php' => 'b8bcf0da7510631fb30a38e6407517fc',
'./modules/AOP_Case_Updates/language/en_us.lang.php' => '1de0ca09e21d68bdde37e3e9676109e8', './modules/AOP_Case_Updates/language/en_us.lang.php' => '1de0ca09e21d68bdde37e3e9676109e8',
'./modules/AOP_Case_Updates/metadata/SearchFields.php' => '1c8b860ef1fb5e03c01858d167dc5b0f', './modules/AOP_Case_Updates/metadata/SearchFields.php' => '1c8b860ef1fb5e03c01858d167dc5b0f',
@ -3481,7 +3486,7 @@ $md5_string = array (
'./modules/AOP_Case_Updates/tpl/caseUpdateForm.tpl' => '090a89e828774dde4b9b744b3b73c4f9', './modules/AOP_Case_Updates/tpl/caseUpdateForm.tpl' => '090a89e828774dde4b9b744b3b73c4f9',
'./modules/AOP_Case_Updates/util.php' => '98b2f2b14fea00af615f25f4fec404b5', './modules/AOP_Case_Updates/util.php' => '98b2f2b14fea00af615f25f4fec404b5',
'./modules/AOP_Case_Updates/vardefs.php' => '20f0fcc9b6261db648076addc1e9c3a3', './modules/AOP_Case_Updates/vardefs.php' => '20f0fcc9b6261db648076addc1e9c3a3',
'./modules/AOR_Charts/AOR_Chart.php' => 'c5419924dffce0c00f7f12cdf0a7df51', './modules/AOR_Charts/AOR_Chart.php' => 'a86a91f8150546f208a78e6f5767cc76',
'./modules/AOR_Charts/chartLines.js' => '4aa11696fc23f9c1d4f300e29334dbab', './modules/AOR_Charts/chartLines.js' => '4aa11696fc23f9c1d4f300e29334dbab',
'./modules/AOR_Charts/controller.php' => '73ddd15d51aaa04a8921d170363dd42d', './modules/AOR_Charts/controller.php' => '73ddd15d51aaa04a8921d170363dd42d',
'./modules/AOR_Charts/language/en_us.lang.php' => '68f5e22ade3c47753333f19717a72d7b', './modules/AOR_Charts/language/en_us.lang.php' => '68f5e22ade3c47753333f19717a72d7b',
@ -3520,11 +3525,11 @@ $md5_string = array (
'./modules/AOR_Charts/lib/pChart/palettes/shade.color' => 'd6597f53d1fecd61b5a63421d81601f1', './modules/AOR_Charts/lib/pChart/palettes/shade.color' => 'd6597f53d1fecd61b5a63421d81601f1',
'./modules/AOR_Charts/lib/pChart/palettes/spring.color' => '402a1ac723252a591bf554a813b9c839', './modules/AOR_Charts/lib/pChart/palettes/spring.color' => '402a1ac723252a591bf554a813b9c839',
'./modules/AOR_Charts/lib/pChart/palettes/summer.color' => 'f509da217991bb5525ce9cad1d5ab053', './modules/AOR_Charts/lib/pChart/palettes/summer.color' => 'f509da217991bb5525ce9cad1d5ab053',
'./modules/AOR_Charts/vardefs.php' => 'd09f4d9d8432e700a21a886f770672b6', './modules/AOR_Charts/vardefs.php' => '4c0016a658d31732ee3d74928fab0121',
'./modules/AOR_Conditions/AOR_Condition.php' => 'b76bd7f96043a10c5b1c7c02239b9ca5', './modules/AOR_Conditions/AOR_Condition.php' => 'b76bd7f96043a10c5b1c7c02239b9ca5',
'./modules/AOR_Conditions/conditionLines.js' => 'e80c394e97e31d96222f49932dc1e32c', './modules/AOR_Conditions/conditionLines.js' => 'e80c394e97e31d96222f49932dc1e32c',
'./modules/AOR_Conditions/conditionLines.php' => 'ce1aac0705b29a126b6908e23e03488f', './modules/AOR_Conditions/conditionLines.php' => 'ce1aac0705b29a126b6908e23e03488f',
'./modules/AOR_Conditions/language/en_us.lang.php' => 'bb8f0bc65e585b0a8218f27f89fa303d', './modules/AOR_Conditions/language/en_us.lang.php' => 'de9cb666a10041cc14cc03081ee7912a',
'./modules/AOR_Conditions/vardefs.php' => '757a8b342bee5dd079f1eaf0709604a5', './modules/AOR_Conditions/vardefs.php' => '757a8b342bee5dd079f1eaf0709604a5',
'./modules/AOR_Fields/AOR_Field.php' => '60dff5c8ac694cf34c75940116ce4b4d', './modules/AOR_Fields/AOR_Field.php' => '60dff5c8ac694cf34c75940116ce4b4d',
'./modules/AOR_Fields/fieldLines.js' => '19a5c3e9ed0cc84bfa63824d9acc1407', './modules/AOR_Fields/fieldLines.js' => '19a5c3e9ed0cc84bfa63824d9acc1407',
@ -3532,7 +3537,7 @@ $md5_string = array (
'./modules/AOR_Fields/language/en_us.lang.php' => '50a4309bdae43ce819c1a9bf95db1393', './modules/AOR_Fields/language/en_us.lang.php' => '50a4309bdae43ce819c1a9bf95db1393',
'./modules/AOR_Fields/vardefs.php' => '385d0f1955e9e46e276159b67c716eb1', './modules/AOR_Fields/vardefs.php' => '385d0f1955e9e46e276159b67c716eb1',
'./modules/AOR_Reports/AOR_Report.js' => 'f95623b1ab32a4325a3f1c2649b63702', './modules/AOR_Reports/AOR_Report.js' => 'f95623b1ab32a4325a3f1c2649b63702',
'./modules/AOR_Reports/AOR_Report.php' => '068bb57a5aad9262b94b7d34cb2f0ae6', './modules/AOR_Reports/AOR_Report.php' => '1976fc28f816b3603ce9dd4be743e7f2',
'./modules/AOR_Reports/AOR_Report_After.js' => 'ab77afb81f872f96f22bc676d0ae4beb', './modules/AOR_Reports/AOR_Report_After.js' => 'ab77afb81f872f96f22bc676d0ae4beb',
'./modules/AOR_Reports/AOR_Report_Before.js' => 'ab5397e1ca56871cb28514092029fd90', './modules/AOR_Reports/AOR_Report_Before.js' => 'ab5397e1ca56871cb28514092029fd90',
'./modules/AOR_Reports/Dashlets/AORReportsDashlet/AORReportsDashlet.js' => '95fb8234d31774e011b0984229dca16a', './modules/AOR_Reports/Dashlets/AORReportsDashlet/AORReportsDashlet.js' => '95fb8234d31774e011b0984229dca16a',
@ -3541,7 +3546,7 @@ $md5_string = array (
'./modules/AOR_Reports/Dashlets/AORReportsDashlet/dashlet.tpl' => 'f988fd02f7700fbb9c3d3dae265c6f77', './modules/AOR_Reports/Dashlets/AORReportsDashlet/dashlet.tpl' => 'f988fd02f7700fbb9c3d3dae265c6f77',
'./modules/AOR_Reports/Dashlets/AORReportsDashlet/dashletConfigure.tpl' => '78ca8ef4909602f45d9a5455682502f6', './modules/AOR_Reports/Dashlets/AORReportsDashlet/dashletConfigure.tpl' => '78ca8ef4909602f45d9a5455682502f6',
'./modules/AOR_Reports/Menu.php' => '91f8cfce443d92348c4c50de8d19a499', './modules/AOR_Reports/Menu.php' => '91f8cfce443d92348c4c50de8d19a499',
'./modules/AOR_Reports/aor_utils.php' => 'a2b35153ad9396c4b6dcea5677781e6f', './modules/AOR_Reports/aor_utils.php' => '2ff4ebfe366d42212faee8277bd3a2ee',
'./modules/AOR_Reports/controller.php' => '28bbccf2390792ce2751af9a57b22d7b', './modules/AOR_Reports/controller.php' => '28bbccf2390792ce2751af9a57b22d7b',
'./modules/AOR_Reports/js/Chart.js' => 'ce39265cf9293096f8d19930bf98b5c0', './modules/AOR_Reports/js/Chart.js' => 'ce39265cf9293096f8d19930bf98b5c0',
'./modules/AOR_Reports/js/jqtree/jqtree.css' => '3f8e2b17df7771293bdcc4622dd24f42', './modules/AOR_Reports/js/jqtree/jqtree.css' => '3f8e2b17df7771293bdcc4622dd24f42',
@ -3623,7 +3628,7 @@ $md5_string = array (
'./modules/AOS_Invoices/Forms.php' => 'd41d8cd98f00b204e9800998ecf8427e', './modules/AOS_Invoices/Forms.php' => 'd41d8cd98f00b204e9800998ecf8427e',
'./modules/AOS_Invoices/Menu.php' => '316e02ea1d5e070041b9e539a9578614', './modules/AOS_Invoices/Menu.php' => '316e02ea1d5e070041b9e539a9578614',
'./modules/AOS_Invoices/controller.php' => '55e0ae72d3fbe2b6835771b05d15746f', './modules/AOS_Invoices/controller.php' => '55e0ae72d3fbe2b6835771b05d15746f',
'./modules/AOS_Invoices/language/en_us.lang.php' => 'cc8209218f24e736731d92ca91f67154', './modules/AOS_Invoices/language/en_us.lang.php' => '05f185c014aee776537694c5520a39ff',
'./modules/AOS_Invoices/metadata/SearchFields.php' => '8cda01d9709de3b9ec9d6bdf7b05b300', './modules/AOS_Invoices/metadata/SearchFields.php' => '8cda01d9709de3b9ec9d6bdf7b05b300',
'./modules/AOS_Invoices/metadata/dashletviewdefs.php' => 'c70d55483402f708ad321b78f2926766', './modules/AOS_Invoices/metadata/dashletviewdefs.php' => 'c70d55483402f708ad321b78f2926766',
'./modules/AOS_Invoices/metadata/detailviewdefs.php' => 'ea0f0f424d7181fec7d097fc21dd1fa6', './modules/AOS_Invoices/metadata/detailviewdefs.php' => 'ea0f0f424d7181fec7d097fc21dd1fa6',
@ -3809,7 +3814,7 @@ $md5_string = array (
'./modules/AOS_PDF_Templates/samples/smpl_Quote_Sample.php' => 'cfb3ca54419e66aeafb99deadecc35ef', './modules/AOS_PDF_Templates/samples/smpl_Quote_Sample.php' => 'cfb3ca54419e66aeafb99deadecc35ef',
'./modules/AOS_PDF_Templates/sendEmail.php' => 'e3100813d1f9397684f7dc75b270b873', './modules/AOS_PDF_Templates/sendEmail.php' => 'e3100813d1f9397684f7dc75b270b873',
'./modules/AOS_PDF_Templates/templateParser.php' => '27c2b4c031270ac8227b9f6a4772a60e', './modules/AOS_PDF_Templates/templateParser.php' => '27c2b4c031270ac8227b9f6a4772a60e',
'./modules/AOS_PDF_Templates/vardefs.php' => 'b019229e105ec38b126677d5fa09a8f6', './modules/AOS_PDF_Templates/vardefs.php' => 'c2222325b41dca6b38ceec42dc1d622a',
'./modules/AOS_PDF_Templates/views/view.detail.php' => 'b4e69283cf0474b65b66966d73ce43a1', './modules/AOS_PDF_Templates/views/view.detail.php' => 'b4e69283cf0474b65b66966d73ce43a1',
'./modules/AOS_PDF_Templates/views/view.edit.php' => '67da85cd48f717f59bfd74abec938721', './modules/AOS_PDF_Templates/views/view.edit.php' => '67da85cd48f717f59bfd74abec938721',
'./modules/AOS_Product_Categories/AOS_Product_Categories.php' => '2ca10c2517f6ff4e2732f2683cfe13b4', './modules/AOS_Product_Categories/AOS_Product_Categories.php' => '2ca10c2517f6ff4e2732f2683cfe13b4',
@ -3860,7 +3865,7 @@ $md5_string = array (
'./modules/AOS_Products/views/view.edit.php' => 'f70bd7bad694a0e5bb94a9e0cf0a61e3', './modules/AOS_Products/views/view.edit.php' => 'f70bd7bad694a0e5bb94a9e0cf0a61e3',
'./modules/AOS_Products_Quotes/AOS_Products_Quotes.php' => '41f133c30e5a9f4dc8467a19ca782210', './modules/AOS_Products_Quotes/AOS_Products_Quotes.php' => '41f133c30e5a9f4dc8467a19ca782210',
'./modules/AOS_Products_Quotes/AOS_Products_Quotes_sugar.php' => 'f41555a3a9d41ada58ed3fb976e0322a', './modules/AOS_Products_Quotes/AOS_Products_Quotes_sugar.php' => 'f41555a3a9d41ada58ed3fb976e0322a',
'./modules/AOS_Products_Quotes/AOS_Utils.php' => '4ecd3d90aca56359f6dd661856783487', './modules/AOS_Products_Quotes/AOS_Utils.php' => 'fe0e0b2c29e88134ae7134186c7c99e2',
'./modules/AOS_Products_Quotes/Forms.php' => 'd41d8cd98f00b204e9800998ecf8427e', './modules/AOS_Products_Quotes/Forms.php' => 'd41d8cd98f00b204e9800998ecf8427e',
'./modules/AOS_Products_Quotes/Line_Items.php' => 'd9537335985a509675369614fb9dc14c', './modules/AOS_Products_Quotes/Line_Items.php' => 'd9537335985a509675369614fb9dc14c',
'./modules/AOS_Products_Quotes/Menu.php' => 'b7ade70d995c0fb6795273fbe7717309', './modules/AOS_Products_Quotes/Menu.php' => 'b7ade70d995c0fb6795273fbe7717309',
@ -3885,7 +3890,7 @@ $md5_string = array (
'./modules/AOS_Quotes/converToInvoice.php' => 'f84361d4395d475bd58bf7005e2e65bf', './modules/AOS_Quotes/converToInvoice.php' => 'f84361d4395d475bd58bf7005e2e65bf',
'./modules/AOS_Quotes/createContract.php' => 'ce02e3a0ed459e1a584cf3d423503909', './modules/AOS_Quotes/createContract.php' => 'ce02e3a0ed459e1a584cf3d423503909',
'./modules/AOS_Quotes/createOpportunity.php' => '064e53ddf83e516f2690743ff41a35ce', './modules/AOS_Quotes/createOpportunity.php' => '064e53ddf83e516f2690743ff41a35ce',
'./modules/AOS_Quotes/language/en_us.lang.php' => '32a8fba8430b5163f77a9324fde0af7a', './modules/AOS_Quotes/language/en_us.lang.php' => '8cbc80e5bad80d9de5f95ccea8135fe2',
'./modules/AOS_Quotes/metadata/SearchFields.php' => '59f01f1ad87ba15588c535a83985a786', './modules/AOS_Quotes/metadata/SearchFields.php' => '59f01f1ad87ba15588c535a83985a786',
'./modules/AOS_Quotes/metadata/dashletviewdefs.php' => '7151208387eb21be92e4caeec9d4854e', './modules/AOS_Quotes/metadata/dashletviewdefs.php' => '7151208387eb21be92e4caeec9d4854e',
'./modules/AOS_Quotes/metadata/detailviewdefs.php' => '16cd826a87c24287cb93207e75c49cad', './modules/AOS_Quotes/metadata/detailviewdefs.php' => '16cd826a87c24287cb93207e75c49cad',
@ -3904,7 +3909,7 @@ $md5_string = array (
'./modules/AOS_Quotes/vardefs.php' => '9c6fa75bf5b4ca2898ab4595e2db6b10', './modules/AOS_Quotes/vardefs.php' => '9c6fa75bf5b4ca2898ab4595e2db6b10',
'./modules/AOS_Quotes/views/view.detail.php' => 'e231de67e42f03e8a5957cdb4b7084a2', './modules/AOS_Quotes/views/view.detail.php' => 'e231de67e42f03e8a5957cdb4b7084a2',
'./modules/AOS_Quotes/views/view.edit.php' => '5481969a90e67032e1b2677f2eedfb44', './modules/AOS_Quotes/views/view.edit.php' => '5481969a90e67032e1b2677f2eedfb44',
'./modules/AOW_Actions/AOW_Action.php' => 'ca02e47e9120cd0d52e4f1859ffe4fdc', './modules/AOW_Actions/AOW_Action.php' => 'e56b3903b8b90698e4681e5d25eec679',
'./modules/AOW_Actions/FormulaCalculator.php' => 'b8e36954646d4716949264e2fc2808af', './modules/AOW_Actions/FormulaCalculator.php' => 'b8e36954646d4716949264e2fc2808af',
'./modules/AOW_Actions/actionLines.js' => 'de3626663801a14f67f46649d6983fd6', './modules/AOW_Actions/actionLines.js' => 'de3626663801a14f67f46649d6983fd6',
'./modules/AOW_Actions/actionLines.php' => '6bb52c4830237a808c51e18b8c7e954c', './modules/AOW_Actions/actionLines.php' => '6bb52c4830237a808c51e18b8c7e954c',
@ -3947,7 +3952,7 @@ $md5_string = array (
'./modules/AOW_WorkFlow/Dashlets/AOW_WorkFlowDashlet/AOW_WorkFlowDashlet.meta.php' => '307d5c5c4e36070f26fcd7019a7c3ce7', './modules/AOW_WorkFlow/Dashlets/AOW_WorkFlowDashlet/AOW_WorkFlowDashlet.meta.php' => '307d5c5c4e36070f26fcd7019a7c3ce7',
'./modules/AOW_WorkFlow/Dashlets/AOW_WorkFlowDashlet/AOW_WorkFlowDashlet.php' => '9df3265e560ec57ed8bfaffca5335b66', './modules/AOW_WorkFlow/Dashlets/AOW_WorkFlowDashlet/AOW_WorkFlowDashlet.php' => '9df3265e560ec57ed8bfaffca5335b66',
'./modules/AOW_WorkFlow/Menu.php' => 'bda4b71d876e065f7661bce4a91bde57', './modules/AOW_WorkFlow/Menu.php' => 'bda4b71d876e065f7661bce4a91bde57',
'./modules/AOW_WorkFlow/aow_utils.php' => 'ae65e1cdf26482f54118516352078ecf', './modules/AOW_WorkFlow/aow_utils.php' => '0f06117126fbfe5cc6fa498a6ddbb4b8',
'./modules/AOW_WorkFlow/controller.php' => '80bf5d8ed3fec47f72320c318719e630', './modules/AOW_WorkFlow/controller.php' => '80bf5d8ed3fec47f72320c318719e630',
'./modules/AOW_WorkFlow/language/en_us.lang.php' => 'd3f5d7f63df072fe0d79bc5385dadbbf', './modules/AOW_WorkFlow/language/en_us.lang.php' => 'd3f5d7f63df072fe0d79bc5385dadbbf',
'./modules/AOW_WorkFlow/metadata/SearchFields.php' => '125fca8f181fd8c4fbb159fd71096bd7', './modules/AOW_WorkFlow/metadata/SearchFields.php' => '125fca8f181fd8c4fbb159fd71096bd7',
@ -3977,7 +3982,7 @@ $md5_string = array (
'./modules/Accounts/ShowDuplicates.html' => 'c2d5f8e6dabc0b942cf7474c43c52914', './modules/Accounts/ShowDuplicates.html' => 'c2d5f8e6dabc0b942cf7474c43c52914',
'./modules/Accounts/ShowDuplicates.php' => '833caf72a9a9527c05f14eb8e1ea08e1', './modules/Accounts/ShowDuplicates.php' => '833caf72a9a9527c05f14eb8e1ea08e1',
'./modules/Accounts/field_arrays.php' => 'c1329497e5cdf903b6d32194ff67aebf', './modules/Accounts/field_arrays.php' => 'c1329497e5cdf903b6d32194ff67aebf',
'./modules/Accounts/language/en_us.lang.php' => '63baa35332c8e958c130ff50937ec669', './modules/Accounts/language/en_us.lang.php' => '15f7fce63193b8323b31e923e95cd5a4',
'./modules/Accounts/metadata/SearchFields.php' => '4da6a04d1d6f62e64cfaa865c2fd74e3', './modules/Accounts/metadata/SearchFields.php' => '4da6a04d1d6f62e64cfaa865c2fd74e3',
'./modules/Accounts/metadata/acldefs.php' => '5deb2076ac603de5ad5846b99413c3c7', './modules/Accounts/metadata/acldefs.php' => '5deb2076ac603de5ad5846b99413c3c7',
'./modules/Accounts/metadata/additionalDetails.php' => '6181725b72efac0f243207dff64db7cc', './modules/Accounts/metadata/additionalDetails.php' => '6181725b72efac0f243207dff64db7cc',
@ -4008,7 +4013,7 @@ $md5_string = array (
'./modules/Activities/SubPanelView.php' => '7fd523f14f6ee918d27fdd6909e49ca6', './modules/Activities/SubPanelView.php' => '7fd523f14f6ee918d27fdd6909e49ca6',
'./modules/Activities/SubPanelViewContacts.html' => '4f9ba78f0e1f988675f1ca34f48945f9', './modules/Activities/SubPanelViewContacts.html' => '4f9ba78f0e1f988675f1ca34f48945f9',
'./modules/Activities/config.php' => '57c9e86f422dd36a9bd553ebcc9342f3', './modules/Activities/config.php' => '57c9e86f422dd36a9bd553ebcc9342f3',
'./modules/Activities/language/en_us.lang.php' => '48def97e388ad0cf9ed0e1cfb00d434f', './modules/Activities/language/en_us.lang.php' => 'b06f867cce127f217f23bddf1a8d28a4',
'./modules/Activities/metadata/subpaneldefs.php' => 'a79ff0e2b6c9213fd2711940b54c1168', './modules/Activities/metadata/subpaneldefs.php' => 'a79ff0e2b6c9213fd2711940b54c1168',
'./modules/Activities/tpls/PopupBody.tpl' => '25fa7ac9a94ba4181c1c364a99ead093', './modules/Activities/tpls/PopupBody.tpl' => '25fa7ac9a94ba4181c1c364a99ead093',
'./modules/Activities/tpls/PopupFooter.tpl' => 'e053d2a3bf157c1c93b5106f6f6a42a8', './modules/Activities/tpls/PopupFooter.tpl' => 'e053d2a3bf157c1c93b5106f6f6a42a8',
@ -4102,14 +4107,14 @@ $md5_string = array (
'./modules/Administration/action_view_map.php' => '4b6d52a4c27e279a6381536d20916b8a', './modules/Administration/action_view_map.php' => '4b6d52a4c27e279a6381536d20916b8a',
'./modules/Administration/callJSRepair.php' => 'f7ed41ce540909b326dd43036fa40b1b', './modules/Administration/callJSRepair.php' => 'f7ed41ce540909b326dd43036fa40b1b',
'./modules/Administration/clear_chart_cache.php' => 'a228ef6f10942d0c5f3dba2c25e1b938', './modules/Administration/clear_chart_cache.php' => 'a228ef6f10942d0c5f3dba2c25e1b938',
'./modules/Administration/controller.php' => '5664b9644a478bd6891fb1b228ecde01', './modules/Administration/controller.php' => 'f0073d59bece2872d5a35569ebca73d1',
'./modules/Administration/expandDatabase.php' => '894f680bcbd4386524b0812822bd2bc0', './modules/Administration/expandDatabase.php' => '894f680bcbd4386524b0812822bd2bc0',
'./modules/Administration/index.html' => '65adfd50b96a797643b4761bea958ddf', './modules/Administration/index.html' => '65adfd50b96a797643b4761bea958ddf',
'./modules/Administration/index.php' => '4b1d5098a984f8ed472e2828703997d3', './modules/Administration/index.php' => '48a888ecf78f04d198c2a9560deb8528',
'./modules/Administration/index.tpl' => 'e2267cd142b9509c13eaed32180e5e88', './modules/Administration/index.tpl' => 'e2267cd142b9509c13eaed32180e5e88',
'./modules/Administration/javascript/Administration.js' => '921f031abdae0f1a935c8558b94e458d', './modules/Administration/javascript/Administration.js' => '921f031abdae0f1a935c8558b94e458d',
'./modules/Administration/javascript/Async.js' => 'ff0b1778f9d19e100cd1624d17761c38', './modules/Administration/javascript/Async.js' => 'ff0b1778f9d19e100cd1624d17761c38',
'./modules/Administration/language/en_us.lang.php' => '431c4fc89f6124db449b8b287bf5cfab', './modules/Administration/language/en_us.lang.php' => '7a03dd1ebdc3b40588253084fe4fe818',
'./modules/Administration/metadata/SearchFields.php' => '678fb87cfc3b3e95d7e7ea8a72d8da16', './modules/Administration/metadata/SearchFields.php' => '678fb87cfc3b3e95d7e7ea8a72d8da16',
'./modules/Administration/metadata/adminpaneldefs.php' => 'e5026a148e4e04a0150b74844d5e73f5', './modules/Administration/metadata/adminpaneldefs.php' => 'e5026a148e4e04a0150b74844d5e73f5',
'./modules/Administration/ncc_config.php' => '643e7a46ad14a6aed7431c6679362b95', './modules/Administration/ncc_config.php' => '643e7a46ad14a6aed7431c6679362b95',
@ -4137,7 +4142,7 @@ $md5_string = array (
'./modules/Administration/vardefs.php' => '5d10cb1856b5987f75199efc7f195173', './modules/Administration/vardefs.php' => '5d10cb1856b5987f75199efc7f195173',
'./modules/Administration/views/view.backups.php' => '2b385c1fe06cebd198449aba42c33b11', './modules/Administration/views/view.backups.php' => '2b385c1fe06cebd198449aba42c33b11',
'./modules/Administration/views/view.configureajaxui.php' => '71f6d3ff34eb6a525eb809fa721039d1', './modules/Administration/views/view.configureajaxui.php' => '71f6d3ff34eb6a525eb809fa721039d1',
'./modules/Administration/views/view.configuretabs.php' => 'c065da4e48ce323ff22bbb08ba5e06c1', './modules/Administration/views/view.configuretabs.php' => 'd37123d3f808ae954bd5117cad33cd32',
'./modules/Administration/views/view.globalsearchsettings.php' => '29f8363f397a126602b1b5f8a95aa85f', './modules/Administration/views/view.globalsearchsettings.php' => '29f8363f397a126602b1b5f8a95aa85f',
'./modules/Administration/views/view.languages.php' => '567d94fa33ab8c8f7645a320a8abf347', './modules/Administration/views/view.languages.php' => '567d94fa33ab8c8f7645a320a8abf347',
'./modules/Administration/views/view.repair.php' => '340665e3487ce6942b9398a6152ba7bb', './modules/Administration/views/view.repair.php' => '340665e3487ce6942b9398a6152ba7bb',
@ -4169,7 +4174,7 @@ $md5_string = array (
'./modules/Bugs/Dashlets/MyBugsDashlet/MyBugsDashlet.php' => 'c827b035a8ae2a4465d8202f1eb75e35', './modules/Bugs/Dashlets/MyBugsDashlet/MyBugsDashlet.php' => 'c827b035a8ae2a4465d8202f1eb75e35',
'./modules/Bugs/Menu.php' => '86aa07d7cb3e24f38291b6c1718e4596', './modules/Bugs/Menu.php' => '86aa07d7cb3e24f38291b6c1718e4596',
'./modules/Bugs/field_arrays.php' => '61b8db5725102e6dc1a8e98275d99aae', './modules/Bugs/field_arrays.php' => '61b8db5725102e6dc1a8e98275d99aae',
'./modules/Bugs/language/en_us.lang.php' => '756f676ae0d2c19e8e33b4b55046616c', './modules/Bugs/language/en_us.lang.php' => '7aecad864177f2f40b7278cb3ea45881',
'./modules/Bugs/metadata/SearchFields.php' => 'ef00465dbff11212585b854f9644bff2', './modules/Bugs/metadata/SearchFields.php' => 'ef00465dbff11212585b854f9644bff2',
'./modules/Bugs/metadata/additionalDetails.php' => 'c998b387ac956972a2d3690a34f653ab', './modules/Bugs/metadata/additionalDetails.php' => 'c998b387ac956972a2d3690a34f653ab',
'./modules/Bugs/metadata/detailviewdefs.php' => 'b1a4caff4eb803914b3df0c8b052a3ba', './modules/Bugs/metadata/detailviewdefs.php' => 'b1a4caff4eb803914b3df0c8b052a3ba',
@ -4210,15 +4215,89 @@ $md5_string = array (
'./modules/Calendar/fullcalendar/gcal.min.js' => '1a803b3bbd80571406db6b697ad1003e', './modules/Calendar/fullcalendar/gcal.min.js' => '1a803b3bbd80571406db6b697ad1003e',
'./modules/Calendar/fullcalendar/lib/moment.min.js' => 'ab1f2f37ab92366f7b217ba0f84666f4', './modules/Calendar/fullcalendar/lib/moment.min.js' => 'ab1f2f37ab92366f7b217ba0f84666f4',
'./modules/Calendar/fullcalendar/license.txt' => 'de76520d2a2796a4d00123bc68a6e885', './modules/Calendar/fullcalendar/license.txt' => 'de76520d2a2796a4d00123bc68a6e885',
'./modules/Calendar/fullcalendar/locale/af.js' => '4cc8fff4e0eae2beceb28852407d8ee1',
'./modules/Calendar/fullcalendar/locale/ar-dz.js' => 'bdebe3cc6c859fe19a39c4dcaeb8f46f',
'./modules/Calendar/fullcalendar/locale/ar-kw.js' => 'c99dc3d59530da6680fd7ab4f4a59764',
'./modules/Calendar/fullcalendar/locale/ar-ly.js' => '56ead35e6aacb17c5b2348bb4393346b',
'./modules/Calendar/fullcalendar/locale/ar-ma.js' => '38c8ca9e899398702a4c27171f90d4a3',
'./modules/Calendar/fullcalendar/locale/ar-sa.js' => '37b2642147cf798072f41e6db0ff9e24',
'./modules/Calendar/fullcalendar/locale/ar-tn.js' => '6688881ac22f904e20d475b4f7d8e502',
'./modules/Calendar/fullcalendar/locale/ar.js' => '318ee308a3338e650e21eef9bfec4454',
'./modules/Calendar/fullcalendar/locale/be.js' => 'ee704412608520b4a15461067bf10e80',
'./modules/Calendar/fullcalendar/locale/bg.js' => '844a0e17b21f6f108a2c2d52279a4194',
'./modules/Calendar/fullcalendar/locale/bs.js' => 'ccbff7000925c53198d4994d2b020920',
'./modules/Calendar/fullcalendar/locale/ca.js' => '9f4daf05cbd58dac565e862548362e50',
'./modules/Calendar/fullcalendar/locale/cs.js' => 'dc1b420fe2a146249881910ac5db32d4',
'./modules/Calendar/fullcalendar/locale/da.js' => 'c5e64b64407b8711626d0b341dbe6aa7',
'./modules/Calendar/fullcalendar/locale/de-at.js' => 'f58ebbf82fd65ff7a547e47ecffa9a87',
'./modules/Calendar/fullcalendar/locale/de-ch.js' => '1ff636a1d3f423fc532bf18a3ca77657',
'./modules/Calendar/fullcalendar/locale/de.js' => '15d5d4e179318560629fa0eea56a8510',
'./modules/Calendar/fullcalendar/locale/el.js' => 'e84f864007f21d6d3af779676dd9bc0a',
'./modules/Calendar/fullcalendar/locale/en-au.js' => '87eb7d91bfd405f2b1fa748dd944ec2e',
'./modules/Calendar/fullcalendar/locale/en-ca.js' => 'a21ff12d18dd973274e8d83726abfb46',
'./modules/Calendar/fullcalendar/locale/en-gb.js' => 'e957c4fa13bca1f4a29528b8729eff9c',
'./modules/Calendar/fullcalendar/locale/en-ie.js' => 'a11a68388d5d7892b86857c61944f9a6',
'./modules/Calendar/fullcalendar/locale/en-nz.js' => '536427f5c3395b42415533f189aba586',
'./modules/Calendar/fullcalendar/locale/es-do.js' => '3f973a3cc32a8dfd98ba2cc768543b41',
'./modules/Calendar/fullcalendar/locale/es-us.js' => '802b70cef70015513fe2abd746812b18',
'./modules/Calendar/fullcalendar/locale/es.js' => '16cb0e49055f2982cc512bdb8be8f83f',
'./modules/Calendar/fullcalendar/locale/et.js' => 'e968806ddef3a40ac8ee3beb4630b876',
'./modules/Calendar/fullcalendar/locale/eu.js' => 'e7a94e494c802877f4563f38d92f6d0e',
'./modules/Calendar/fullcalendar/locale/fa.js' => 'fd79aa5ca8ed85c9c6deeda0ad4023c1',
'./modules/Calendar/fullcalendar/locale/fi.js' => '8da8595594a3664a85e471e21d203a82',
'./modules/Calendar/fullcalendar/locale/fr-ca.js' => 'e8153da9dc2ca4ad6a0b4dd29f217f72',
'./modules/Calendar/fullcalendar/locale/fr-ch.js' => '10d15457f413e7e46a68cd79658f30d6',
'./modules/Calendar/fullcalendar/locale/fr.js' => '140a7e017212fcfcb7969f2adadc499a',
'./modules/Calendar/fullcalendar/locale/gl.js' => '40672764b9b4e830fa5231a8c33d6d71',
'./modules/Calendar/fullcalendar/locale/he.js' => 'e340e0ad6d7324a4a01b1329ff5e8e8c',
'./modules/Calendar/fullcalendar/locale/hi.js' => '3be62d0ccf23cdc983f81fcffebf8fad',
'./modules/Calendar/fullcalendar/locale/hr.js' => 'faaefb256840cbe92ebf567d445df81a',
'./modules/Calendar/fullcalendar/locale/hu.js' => 'c69c977c4698337ef02bc6d680f87171',
'./modules/Calendar/fullcalendar/locale/id.js' => '3ad379acdd2a9c87636116db9c31a374',
'./modules/Calendar/fullcalendar/locale/is.js' => '6756a2b553dfe63771134dd621836150',
'./modules/Calendar/fullcalendar/locale/it.js' => '847cc8ca9b5f4e6e9885bdd3a80006e7',
'./modules/Calendar/fullcalendar/locale/ja.js' => '64896b3b2898658036dc49a5b231db41',
'./modules/Calendar/fullcalendar/locale/ka.js' => '29936c3375ddb8464870f36fbb434de4',
'./modules/Calendar/fullcalendar/locale/kk.js' => 'a1a408d0934f8efee6b2e251d981aff9',
'./modules/Calendar/fullcalendar/locale/ko.js' => 'baa216ba89b4cd77221c2bdf4cd7a51b',
'./modules/Calendar/fullcalendar/locale/lb.js' => 'c383c75a5e9b54fa9d23afa1c33d81f6',
'./modules/Calendar/fullcalendar/locale/lt.js' => '2973703128bcb2ebada18ff239407825',
'./modules/Calendar/fullcalendar/locale/lv.js' => '316fba27f32475d6a2deef6c3932cba9',
'./modules/Calendar/fullcalendar/locale/mk.js' => 'cec11889b3e1a471aabe912c3019ccf1',
'./modules/Calendar/fullcalendar/locale/ms-my.js' => '9b11dd8ab04790934e73026d0be5c105',
'./modules/Calendar/fullcalendar/locale/ms.js' => '6775cf3c9ec6a867a01f63865ea2b02e',
'./modules/Calendar/fullcalendar/locale/nb.js' => 'adda2aadc37a1201ada9072e771d912e',
'./modules/Calendar/fullcalendar/locale/nl-be.js' => 'a290d39d6d9956e66f33592c91f03db5',
'./modules/Calendar/fullcalendar/locale/nl.js' => '0104eea0e4be0f98dc258ad3e2331eb4',
'./modules/Calendar/fullcalendar/locale/nn.js' => '8279b5dd8d8b3583bc414a4daa59edf8',
'./modules/Calendar/fullcalendar/locale/pl.js' => '5c5178c680aa3391867239eaa12ca85c',
'./modules/Calendar/fullcalendar/locale/pt-br.js' => 'd98aac0792be3dfe0d3d5d24c0ce2045',
'./modules/Calendar/fullcalendar/locale/pt.js' => 'd0d6e93cca316749b60f842603f624b8',
'./modules/Calendar/fullcalendar/locale/ro.js' => '00221148727ea0321bb6da9aa3590f4a',
'./modules/Calendar/fullcalendar/locale/ru.js' => 'd870d9459ac48f242fd78769a558711e',
'./modules/Calendar/fullcalendar/locale/sk.js' => '47ac02a362d43c11bedb68c9a26c8ca7',
'./modules/Calendar/fullcalendar/locale/sl.js' => 'fa1ebfff7cf78ba299c867bb61de8a0b',
'./modules/Calendar/fullcalendar/locale/sq.js' => '9b1c029280b5e0a71c89c5f7180386ef',
'./modules/Calendar/fullcalendar/locale/sr-cyrl.js' => '3dbdeb11141d10d9c9e822a82ec3c5bd',
'./modules/Calendar/fullcalendar/locale/sr.js' => 'e1717b43e0b03035a76803733c0502be',
'./modules/Calendar/fullcalendar/locale/sv.js' => 'f9635cf98c68864598a9ceb65ad4f86e',
'./modules/Calendar/fullcalendar/locale/th.js' => '6f333da064dee1aae8ed587329324c29',
'./modules/Calendar/fullcalendar/locale/tr.js' => '759160f2f78b84f51820fc3a4f866889',
'./modules/Calendar/fullcalendar/locale/uk.js' => '47074b1b9f70ecf27c228c02605d8164',
'./modules/Calendar/fullcalendar/locale/vi.js' => '28b1bf8515dcaa8eb23e09ee7423b493',
'./modules/Calendar/fullcalendar/locale/zh-cn.js' => 'c87e8d5e6c7bfc4572e5d90fdcac5d4e',
'./modules/Calendar/fullcalendar/locale/zh-hk.js' => 'b3778073a8d32571487fb30986fa1274',
'./modules/Calendar/fullcalendar/locale/zh-tw.js' => '0350357773cb032e369025733afc509c',
'./modules/Calendar/fullcalendar/locale-all.js' => '78c23f4647948ffdf11a062fc893e82e',
'./modules/Calendar/index.php' => '85f2e1c502e5fe9dfea373732785c50b', './modules/Calendar/index.php' => '85f2e1c502e5fe9dfea373732785c50b',
'./modules/Calendar/language/en_us.lang.php' => '90ced016b324d3ebd720cbb52cce0fd8', './modules/Calendar/language/en_us.lang.php' => 'e03eda9ac250037d7cba19258a2944c8',
'./modules/Calendar/processScreenSize.php' => '8cee1403bc1e98fa22df8b7ff33e0ba8', './modules/Calendar/processScreenSize.php' => '8cee1403bc1e98fa22df8b7ff33e0ba8',
'./modules/Calendar/tpls/editHeader.tpl' => '3cee4a7e1dfef7aebadb94be332fcf0a', './modules/Calendar/tpls/editHeader.tpl' => '3cee4a7e1dfef7aebadb94be332fcf0a',
'./modules/Calendar/tpls/empty.tpl' => '1ed34d663c85a9d6fff2275b51989f45', './modules/Calendar/tpls/empty.tpl' => '1ed34d663c85a9d6fff2275b51989f45',
'./modules/Calendar/tpls/footer.tpl' => '0a908d402bab6297258e559b97555e1f', './modules/Calendar/tpls/footer.tpl' => '0a908d402bab6297258e559b97555e1f',
'./modules/Calendar/tpls/form.tpl' => '2af75d72a3cd7cdded978b55624cc297', './modules/Calendar/tpls/form.tpl' => '2af75d72a3cd7cdded978b55624cc297',
'./modules/Calendar/tpls/header.tpl' => 'a8d29b28f0b71a0717b75b9552adf1d9', './modules/Calendar/tpls/header.tpl' => 'a8d29b28f0b71a0717b75b9552adf1d9',
'./modules/Calendar/tpls/main.tpl' => '350ec83e8be8d5f6a046177ab6650c9f', './modules/Calendar/tpls/main.tpl' => '9e933666c7ab91460870866ee6887b18',
'./modules/Calendar/tpls/repeat.tpl' => '1fffa61cba8df4b7965b779aef48f755', './modules/Calendar/tpls/repeat.tpl' => '1fffa61cba8df4b7965b779aef48f755',
'./modules/Calendar/tpls/settings.tpl' => 'a590b6657eec6ba7bca2f9d1a17d4445', './modules/Calendar/tpls/settings.tpl' => 'a590b6657eec6ba7bca2f9d1a17d4445',
'./modules/Calendar/tpls/shared_users.tpl' => '42c8245ffd2632a216a9df85216eb1d2', './modules/Calendar/tpls/shared_users.tpl' => '42c8245ffd2632a216a9df85216eb1d2',
@ -4241,7 +4320,7 @@ $md5_string = array (
'./modules/Calls/SubPanelViewInvitees.html' => 'cdc8ebc0a682d8a858027a27a3165d67', './modules/Calls/SubPanelViewInvitees.html' => 'cdc8ebc0a682d8a858027a27a3165d67',
'./modules/Calls/SubPanelViewInvitees.php' => '90a893f155e3e6ea671eb906bc5567e4', './modules/Calls/SubPanelViewInvitees.php' => '90a893f155e3e6ea671eb906bc5567e4',
'./modules/Calls/field_arrays.php' => 'ad5f0a894fe1e0cad2476842ea202904', './modules/Calls/field_arrays.php' => 'ad5f0a894fe1e0cad2476842ea202904',
'./modules/Calls/language/en_us.lang.php' => 'd4e6910d2064f87095894731363839f1', './modules/Calls/language/en_us.lang.php' => '5532c912d4bd2c8a415d993578cc1417',
'./modules/Calls/metadata/SearchFields.php' => '0a99aa2534600ce83f7bd7d861e4a69a', './modules/Calls/metadata/SearchFields.php' => '0a99aa2534600ce83f7bd7d861e4a69a',
'./modules/Calls/metadata/additionalDetails.php' => 'ba9a81bf606e9457c59ab501301f1699', './modules/Calls/metadata/additionalDetails.php' => 'ba9a81bf606e9457c59ab501301f1699',
'./modules/Calls/metadata/detailviewdefs.php' => 'c46f7d237e02000dd22719ced7edb672', './modules/Calls/metadata/detailviewdefs.php' => 'c46f7d237e02000dd22719ced7edb672',
@ -4368,7 +4447,7 @@ $md5_string = array (
'./modules/Campaigns/controller.php' => '49829f315ce375dde5f049fce5a6614b', './modules/Campaigns/controller.php' => '49829f315ce375dde5f049fce5a6614b',
'./modules/Campaigns/field_arrays.php' => '4614ae67c309813865207771a5002651', './modules/Campaigns/field_arrays.php' => '4614ae67c309813865207771a5002651',
'./modules/Campaigns/image.php' => '4211022a4a97b6b862a6cc10ec29fbc2', './modules/Campaigns/image.php' => '4211022a4a97b6b862a6cc10ec29fbc2',
'./modules/Campaigns/language/en_us.lang.php' => 'd275c2b55c101969cfc7a09b6a63c2df', './modules/Campaigns/language/en_us.lang.php' => 'c20c1547ff52e39e478cf9e86d32f016',
'./modules/Campaigns/metadata/SearchFields.php' => '426d580999da5212587ee97c005c4ac7', './modules/Campaigns/metadata/SearchFields.php' => '426d580999da5212587ee97c005c4ac7',
'./modules/Campaigns/metadata/additionalDetails.php' => '4f65719bb4ed565afd70ab7a21a390d1', './modules/Campaigns/metadata/additionalDetails.php' => '4f65719bb4ed565afd70ab7a21a390d1',
'./modules/Campaigns/metadata/detailviewdefs.php' => '18c6de7f4d4e89fd8de6555448897d02', './modules/Campaigns/metadata/detailviewdefs.php' => '18c6de7f4d4e89fd8de6555448897d02',
@ -4407,7 +4486,7 @@ $md5_string = array (
'./modules/Cases/SugarFeeds/CaseFeed.php' => '10c3a3b5e15feb157ce1d4fba2d590ec', './modules/Cases/SugarFeeds/CaseFeed.php' => '10c3a3b5e15feb157ce1d4fba2d590ec',
'./modules/Cases/controller.php' => 'e167eae0ba5fceb883c9c497a7c72bc8', './modules/Cases/controller.php' => 'e167eae0ba5fceb883c9c497a7c72bc8',
'./modules/Cases/field_arrays.php' => '9f9ffb77f698d463d5e3dbfd5ec9ce13', './modules/Cases/field_arrays.php' => '9f9ffb77f698d463d5e3dbfd5ec9ce13',
'./modules/Cases/language/en_us.lang.php' => 'a572e9c408e5b61ac2f90558394b705b', './modules/Cases/language/en_us.lang.php' => '62ae64ee24b1cec7e1696e6d85b36e90',
'./modules/Cases/metadata/SearchFields.php' => '161e9cb4706e372b4c07ee52bb952de4', './modules/Cases/metadata/SearchFields.php' => '161e9cb4706e372b4c07ee52bb952de4',
'./modules/Cases/metadata/accountsquickcreatedefs.php' => 'a1abb219d41e7c9184864fd76cc8f53e', './modules/Cases/metadata/accountsquickcreatedefs.php' => 'a1abb219d41e7c9184864fd76cc8f53e',
'./modules/Cases/metadata/additionalDetails.php' => '5f1ed089f252ea3729f4e6c2e71a04e3', './modules/Cases/metadata/additionalDetails.php' => '5f1ed089f252ea3729f4e6c2e71a04e3',
@ -4564,14 +4643,14 @@ $md5_string = array (
'./modules/Contacts/Save.php' => 'fb1f6c56e87ee34b473f6937f8ab4645', './modules/Contacts/Save.php' => 'fb1f6c56e87ee34b473f6937f8ab4645',
'./modules/Contacts/SaveContactOpportunityRelationship.php' => '33b5a1db7240b41b2fd0e844abbe30f7', './modules/Contacts/SaveContactOpportunityRelationship.php' => '33b5a1db7240b41b2fd0e844abbe30f7',
'./modules/Contacts/ShowDuplicates.html' => '198e79a181281f58bd9cecd1daa223d2', './modules/Contacts/ShowDuplicates.html' => '198e79a181281f58bd9cecd1daa223d2',
'./modules/Contacts/ShowDuplicates.php' => '8927e60feca37cbc655cff2200202ae0', './modules/Contacts/ShowDuplicates.php' => '9c3ce1634a636119454d4fab1b3ce40c',
'./modules/Contacts/SugarFeeds/ContactFeed.php' => 'f56e6b1c528dea06bf4244e3a60caf4f', './modules/Contacts/SugarFeeds/ContactFeed.php' => 'f56e6b1c528dea06bf4244e3a60caf4f',
'./modules/Contacts/controller.php' => '7cc25b6fa126aff691ddf2ad7d7ef940', './modules/Contacts/controller.php' => '7cc25b6fa126aff691ddf2ad7d7ef940',
'./modules/Contacts/createPortalUser.php' => '13ed89b9469aedd37b326f709747f93a', './modules/Contacts/createPortalUser.php' => '13ed89b9469aedd37b326f709747f93a',
'./modules/Contacts/disablePortalUser.php' => 'e6ffa0a41f79eb88d824192a9fa975fc', './modules/Contacts/disablePortalUser.php' => 'e6ffa0a41f79eb88d824192a9fa975fc',
'./modules/Contacts/enablePortalUser.php' => '3268d84b0b2eaaf092dd26bedb871030', './modules/Contacts/enablePortalUser.php' => '3268d84b0b2eaaf092dd26bedb871030',
'./modules/Contacts/field_arrays.php' => '14c68ddc4c77631b268d8bc58de36b30', './modules/Contacts/field_arrays.php' => '14c68ddc4c77631b268d8bc58de36b30',
'./modules/Contacts/language/en_us.lang.php' => '3ff59b44be413daa27adca127f6f8db0', './modules/Contacts/language/en_us.lang.php' => '238c4650b7ba02ca28ed71a35dc2532d',
'./modules/Contacts/metadata/SearchFields.php' => '30c0d84e90a887f9d2be1a9d6e2f96a6', './modules/Contacts/metadata/SearchFields.php' => '30c0d84e90a887f9d2be1a9d6e2f96a6',
'./modules/Contacts/metadata/additionalDetails.php' => '62851cbfcd250cf1637e8f1cec418d2f', './modules/Contacts/metadata/additionalDetails.php' => '62851cbfcd250cf1637e8f1cec418d2f',
'./modules/Contacts/metadata/detailviewdefs.php' => '885a419684a488001122dc6e0be12c31', './modules/Contacts/metadata/detailviewdefs.php' => '885a419684a488001122dc6e0be12c31',
@ -4647,7 +4726,7 @@ $md5_string = array (
'./modules/Documents/controller.php' => 'f3520d01f8f5f1b5e57bf3e8445c947a', './modules/Documents/controller.php' => 'f3520d01f8f5f1b5e57bf3e8445c947a',
'./modules/Documents/documents.js' => '363a5171f2e6532ae6accefe3eebb4c8', './modules/Documents/documents.js' => '363a5171f2e6532ae6accefe3eebb4c8',
'./modules/Documents/field_arrays.php' => '0a183265383b630462eef2ea885b639d', './modules/Documents/field_arrays.php' => '0a183265383b630462eef2ea885b639d',
'./modules/Documents/language/en_us.lang.php' => 'b26640330fe392938d206e1e9e6771f6', './modules/Documents/language/en_us.lang.php' => 'e7f77cb604ed9c0b6c105a6555fd05ea',
'./modules/Documents/metadata/SearchFields.php' => '3d0a81cd336e60193fa30972a5394d32', './modules/Documents/metadata/SearchFields.php' => '3d0a81cd336e60193fa30972a5394d32',
'./modules/Documents/metadata/detailviewdefs.php' => 'b1b3baa52ac03ef83b1a5471c8b1ff43', './modules/Documents/metadata/detailviewdefs.php' => 'b1b3baa52ac03ef83b1a5471c8b1ff43',
'./modules/Documents/metadata/editviewdefs.php' => 'e8ec575c7760f0e41f431c9881fdc32a', './modules/Documents/metadata/editviewdefs.php' => 'e8ec575c7760f0e41f431c9881fdc32a',
@ -4846,7 +4925,7 @@ $md5_string = array (
'./modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.meta.php' => '31dc1ea85cee70a8abab57f66cd77684', './modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.meta.php' => '31dc1ea85cee70a8abab57f66cd77684',
'./modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.php' => 'de11a7fcc4d26b9d9e8f80e7ade68df1', './modules/Emails/Dashlets/MyEmailsDashlet/MyEmailsDashlet.php' => 'de11a7fcc4d26b9d9e8f80e7ade68df1',
'./modules/Emails/Delete.php' => '9c783f1e16850cfe4de22d719d7ce8ca', './modules/Emails/Delete.php' => '9c783f1e16850cfe4de22d719d7ce8ca',
'./modules/Emails/Email.php' => '35f7ddda97f77e3eb1920d71339e8677', './modules/Emails/Email.php' => 'c427e2179fed7e327512b30f9cb87729',
'./modules/Emails/EmailException.php' => '360377b7b2b00fc5d6bb9935c3c92a3f', './modules/Emails/EmailException.php' => '360377b7b2b00fc5d6bb9935c3c92a3f',
'./modules/Emails/EmailFromValidator.php' => '275e4e1167d68361483e18bae111fdc3', './modules/Emails/EmailFromValidator.php' => '275e4e1167d68361483e18bae111fdc3',
'./modules/Emails/EmailUI.css' => '79ef2b93606dc4b6d4e04b679c0b898f', './modules/Emails/EmailUI.css' => '79ef2b93606dc4b6d4e04b679c0b898f',
@ -4858,7 +4937,7 @@ $md5_string = array (
'./modules/Emails/EmailsDataAddress.php' => 'ba1274fe0f3bc27f4cb6d397adf42de7', './modules/Emails/EmailsDataAddress.php' => 'ba1274fe0f3bc27f4cb6d397adf42de7',
'./modules/Emails/EmailsDataAddressCollector.php' => '35e502fadb385a66d71bc44ddd62a259', './modules/Emails/EmailsDataAddressCollector.php' => '35e502fadb385a66d71bc44ddd62a259',
'./modules/Emails/EmailsSignatureResolver.php' => '67c883763451b6ff65741fc0c3b1029e', './modules/Emails/EmailsSignatureResolver.php' => '67c883763451b6ff65741fc0c3b1029e',
'./modules/Emails/Folder.php' => 'cc5ee76f16cb6e226c48f8044370ff4c', './modules/Emails/Folder.php' => '7b869a8d8f462d08656cf5cd8005e1a5',
'./modules/Emails/GenerateQuickComposeFrame.php' => 'b3c126bee579c9db56e11f3c3d3fdee0', './modules/Emails/GenerateQuickComposeFrame.php' => 'b3c126bee579c9db56e11f3c3d3fdee0',
'./modules/Emails/Grab.php' => '95b21789d0a259bd4dff2e1e50752051', './modules/Emails/Grab.php' => '95b21789d0a259bd4dff2e1e50752051',
'./modules/Emails/Menu.php' => '25ef132c32614fb9dff1c2ff9b399899', './modules/Emails/Menu.php' => '25ef132c32614fb9dff1c2ff9b399899',
@ -4893,10 +4972,10 @@ $md5_string = array (
'./modules/Emails/include/ListView/DeleteEmailAction.js' => 'f55735d833d2a77bea56b63e97d5d610', './modules/Emails/include/ListView/DeleteEmailAction.js' => 'f55735d833d2a77bea56b63e97d5d610',
'./modules/Emails/include/ListView/FoldersViewModal.js' => '3bd4d38fa4b6d5db35423005004d8d66', './modules/Emails/include/ListView/FoldersViewModal.js' => '3bd4d38fa4b6d5db35423005004d8d66',
'./modules/Emails/include/ListView/ImportEmailAction.js' => 'a658f8cb5a4bb0d17a635c7631fad088', './modules/Emails/include/ListView/ImportEmailAction.js' => 'a658f8cb5a4bb0d17a635c7631fad088',
'./modules/Emails/include/ListView/ListViewDataEmails.php' => '4a0393729be2a91f447bd7c967cccca2', './modules/Emails/include/ListView/ListViewDataEmails.php' => '0f4002220cfd3da8cc0ed9fab91cfb52',
'./modules/Emails/include/ListView/ListViewDataEmailsSearchAbstract.php' => '0c79defa61814a8ad7d5c6607068ac6e', './modules/Emails/include/ListView/ListViewDataEmailsSearchAbstract.php' => '0c79defa61814a8ad7d5c6607068ac6e',
'./modules/Emails/include/ListView/ListViewDataEmailsSearchOnCrm.php' => '4a61d87963a828e96aaae4a6305194d4', './modules/Emails/include/ListView/ListViewDataEmailsSearchOnCrm.php' => '4a61d87963a828e96aaae4a6305194d4',
'./modules/Emails/include/ListView/ListViewDataEmailsSearchOnIMap.php' => 'ac82cbdb85b9b7109484733e89de80ca', './modules/Emails/include/ListView/ListViewDataEmailsSearchOnIMap.php' => 'a41fb7a4a002db7e75bbc4f33f0b53db',
'./modules/Emails/include/ListView/ListViewHeader.js' => 'a74d18ab45171fb85502d9777c6404d9', './modules/Emails/include/ListView/ListViewHeader.js' => 'a74d18ab45171fb85502d9777c6404d9',
'./modules/Emails/include/ListView/ListViewHeader.tpl' => '548957f43d54966db79f8c03127a8560', './modules/Emails/include/ListView/ListViewHeader.tpl' => '548957f43d54966db79f8c03127a8560',
'./modules/Emails/include/ListView/ListViewSmartyEmails.php' => 'b832e8aa4a47555934cdd5c292d716c0', './modules/Emails/include/ListView/ListViewSmartyEmails.php' => 'b832e8aa4a47555934cdd5c292d716c0',
@ -4926,7 +5005,7 @@ $md5_string = array (
'./modules/Emails/metadata/composeviewdefs.php' => '4cc688ab31ce40c70a476304e890f5df', './modules/Emails/metadata/composeviewdefs.php' => '4cc688ab31ce40c70a476304e890f5df',
'./modules/Emails/metadata/dashletviewdefs.php' => 'f1b4e7eed099e0302f5f9f89ca507d12', './modules/Emails/metadata/dashletviewdefs.php' => 'f1b4e7eed099e0302f5f9f89ca507d12',
'./modules/Emails/metadata/detaildraftviewdefs.php' => '49fc6d1b8885420494460fc1037bc6ea', './modules/Emails/metadata/detaildraftviewdefs.php' => '49fc6d1b8885420494460fc1037bc6ea',
'./modules/Emails/metadata/detailviewdefs.php' => '6c902f378156240061a66d9c56fc2d97', './modules/Emails/metadata/detailviewdefs.php' => 'dc061470876aebf0a41c2e9841d103ef',
'./modules/Emails/metadata/editviewdefs.php' => 'ab93b79de12963a9ca0e112d50477958', './modules/Emails/metadata/editviewdefs.php' => 'ab93b79de12963a9ca0e112d50477958',
'./modules/Emails/metadata/importviewdefs.php' => '393b8a7c1f9d5b23bc75ce5d6dfdfc51', './modules/Emails/metadata/importviewdefs.php' => '393b8a7c1f9d5b23bc75ce5d6dfdfc51',
'./modules/Emails/metadata/listviewdefs.php' => '6352a475112c82070f741f5f6386aff3', './modules/Emails/metadata/listviewdefs.php' => '6352a475112c82070f741f5f6386aff3',
@ -5235,7 +5314,7 @@ $md5_string = array (
'./modules/InboundEmail/View.html' => 'aeaf0daf6157c5a74738a47145576ee0', './modules/InboundEmail/View.html' => 'aeaf0daf6157c5a74738a47145576ee0',
'./modules/InboundEmail/field_arrays.php' => '8daa51b73ea6499fbf2ab18767c0fe78', './modules/InboundEmail/field_arrays.php' => '8daa51b73ea6499fbf2ab18767c0fe78',
'./modules/InboundEmail/index.php' => '22be0681c56292809306913fb48f3178', './modules/InboundEmail/index.php' => '22be0681c56292809306913fb48f3178',
'./modules/InboundEmail/language/en_us.lang.php' => 'd1ba3183c8c4833be1a06f50b31f8069', './modules/InboundEmail/language/en_us.lang.php' => 'bfa663d5408d00baaa1631d53ff123a2',
'./modules/InboundEmail/temp.php' => '181b066ddeb4e0acbd93ec891ab2fb6f', './modules/InboundEmail/temp.php' => '181b066ddeb4e0acbd93ec891ab2fb6f',
'./modules/InboundEmail/tpls/checkImap.tpl' => 'e6ffd2a625f24091435894426d47016c', './modules/InboundEmail/tpls/checkImap.tpl' => 'e6ffd2a625f24091435894426d47016c',
'./modules/InboundEmail/tpls/systemSettingsForm.tpl' => 'f9fd7244167a1822c4673637ba9db2ba', './modules/InboundEmail/tpls/systemSettingsForm.tpl' => 'f9fd7244167a1822c4673637ba9db2ba',
@ -5269,7 +5348,7 @@ $md5_string = array (
'./modules/Leads/action_view_map.php' => 'd517d0082d3670640511957e5f0469ee', './modules/Leads/action_view_map.php' => 'd517d0082d3670640511957e5f0469ee',
'./modules/Leads/controller.php' => 'f7d58bdc6056c4c304ab68647c7f2327', './modules/Leads/controller.php' => 'f7d58bdc6056c4c304ab68647c7f2327',
'./modules/Leads/field_arrays.php' => '425833b7ca95298f58fef0bfd0da03e3', './modules/Leads/field_arrays.php' => '425833b7ca95298f58fef0bfd0da03e3',
'./modules/Leads/language/en_us.lang.php' => '65524be1741138c4ed1c48dd6ea8ea9e', './modules/Leads/language/en_us.lang.php' => 'c53324b5c6f16786e82771a31f949562',
'./modules/Leads/metadata/SearchFields.php' => 'c999eea16c44116f23fe6c50c74ca31a', './modules/Leads/metadata/SearchFields.php' => 'c999eea16c44116f23fe6c50c74ca31a',
'./modules/Leads/metadata/additionalDetails.php' => 'e7677494c8de57bd61027594ce86c23e', './modules/Leads/metadata/additionalDetails.php' => 'e7677494c8de57bd61027594ce86c23e',
'./modules/Leads/metadata/convertdefs.php' => '008e7871979e7ac1c026916abe696747', './modules/Leads/metadata/convertdefs.php' => '008e7871979e7ac1c026916abe696747',
@ -5339,7 +5418,7 @@ $md5_string = array (
'./modules/Meetings/duration_dependency.js' => 'd0c26b21c5b004c81e670ca8e17c7f8d', './modules/Meetings/duration_dependency.js' => 'd0c26b21c5b004c81e670ca8e17c7f8d',
'./modules/Meetings/field_arrays.php' => '8c82d14d1275fbc73595e0ae4c4fddcb', './modules/Meetings/field_arrays.php' => '8c82d14d1275fbc73595e0ae4c4fddcb',
'./modules/Meetings/jsclass_scheduler.js' => 'deb52bcbab92f703fb7f33acaeb161e6', './modules/Meetings/jsclass_scheduler.js' => 'deb52bcbab92f703fb7f33acaeb161e6',
'./modules/Meetings/language/en_us.lang.php' => '09c3a8e5126b242be197cb4506285634', './modules/Meetings/language/en_us.lang.php' => '88f68a2beb5bb265c8fd0f18eae5db7e',
'./modules/Meetings/metadata/SearchFields.php' => '0225beb0e7a21b2c2a8bca6c3bf23f23', './modules/Meetings/metadata/SearchFields.php' => '0225beb0e7a21b2c2a8bca6c3bf23f23',
'./modules/Meetings/metadata/additionalDetails.php' => '5dfdf8523adeb3a0155a069cd8c2d0f2', './modules/Meetings/metadata/additionalDetails.php' => '5dfdf8523adeb3a0155a069cd8c2d0f2',
'./modules/Meetings/metadata/detailviewdefs.php' => '6d9b08a3e767ee731700ea1a507e83be', './modules/Meetings/metadata/detailviewdefs.php' => '6d9b08a3e767ee731700ea1a507e83be',
@ -5516,7 +5595,7 @@ $md5_string = array (
'./modules/ModuleBuilder/views/view.wizard.php' => '53a882aeaa9661bd054100e094b52d69', './modules/ModuleBuilder/views/view.wizard.php' => '53a882aeaa9661bd054100e094b52d69',
'./modules/MySettings/LoadTabSubpanels.php' => 'fb6ed3f130674e770789a6882474d59f', './modules/MySettings/LoadTabSubpanels.php' => 'fb6ed3f130674e770789a6882474d59f',
'./modules/MySettings/StoreQuery.php' => 'b3d2df1adc23630516b958b72eae1374', './modules/MySettings/StoreQuery.php' => 'b3d2df1adc23630516b958b72eae1374',
'./modules/MySettings/TabController.php' => '6c4da033c543e9c43b7d3f09011c49ea', './modules/MySettings/TabController.php' => '22e5503c0120f292d2ccdb75ca9619c8',
'./modules/MySettings/language/en_us.lang.php' => 'def93a6feca616dc0430ea7c519282ee', './modules/MySettings/language/en_us.lang.php' => 'def93a6feca616dc0430ea7c519282ee',
'./modules/Notes/Dashlets/MyNotesDashlet/MyNotesDashlet.data.php' => 'd11d57bf5a9e264535f3b0525afd079e', './modules/Notes/Dashlets/MyNotesDashlet/MyNotesDashlet.data.php' => 'd11d57bf5a9e264535f3b0525afd079e',
'./modules/Notes/Dashlets/MyNotesDashlet/MyNotesDashlet.meta.php' => '089bf076ea755f3c6b9496de37414dad', './modules/Notes/Dashlets/MyNotesDashlet/MyNotesDashlet.meta.php' => '089bf076ea755f3c6b9496de37414dad',
@ -5529,7 +5608,7 @@ $md5_string = array (
'./modules/Notes/SubPanelView.php' => 'eb20271783e823ba635bd5398c0d3a78', './modules/Notes/SubPanelView.php' => 'eb20271783e823ba635bd5398c0d3a78',
'./modules/Notes/controller.php' => '269d8dec6884892e55ec3b2c46b1fa64', './modules/Notes/controller.php' => '269d8dec6884892e55ec3b2c46b1fa64',
'./modules/Notes/field_arrays.php' => '90c231d11ed7e72984123689724129b4', './modules/Notes/field_arrays.php' => '90c231d11ed7e72984123689724129b4',
'./modules/Notes/language/en_us.lang.php' => '02b318d32379c09115d7a84c4fddeee0', './modules/Notes/language/en_us.lang.php' => '1580b6b6df9986743ba30a4a23e1ccca',
'./modules/Notes/metadata/SearchFields.php' => '38864c4e9fbb487b0d3551884ba4241d', './modules/Notes/metadata/SearchFields.php' => '38864c4e9fbb487b0d3551884ba4241d',
'./modules/Notes/metadata/additionalDetails.php' => 'a2405ed7b38a795ffe901876b02bff78', './modules/Notes/metadata/additionalDetails.php' => 'a2405ed7b38a795ffe901876b02bff78',
'./modules/Notes/metadata/detailviewdefs.php' => '90d4ee937c6f7b5e204679bb1a2be577', './modules/Notes/metadata/detailviewdefs.php' => '90d4ee937c6f7b5e204679bb1a2be577',
@ -5671,9 +5750,9 @@ $md5_string = array (
'./modules/Project/Dashlets/MyProjectDashlet/MyProjectDashlet.meta.php' => 'f77f6be351839075a309369c4f307877', './modules/Project/Dashlets/MyProjectDashlet/MyProjectDashlet.meta.php' => 'f77f6be351839075a309369c4f307877',
'./modules/Project/Dashlets/MyProjectDashlet/MyProjectDashlet.php' => '25b51b9952f58d45d975b8e26045d57e', './modules/Project/Dashlets/MyProjectDashlet/MyProjectDashlet.php' => '25b51b9952f58d45d975b8e26045d57e',
'./modules/Project/Delete.php' => '7687b00a8b3cfab3ffd944af2708b330', './modules/Project/Delete.php' => '7687b00a8b3cfab3ffd944af2708b330',
'./modules/Project/Menu.php' => '106020b67d5fe0eb868f61b72a9314aa', './modules/Project/Menu.php' => 'b24a59da3c3b7309ee72e7e8fc8e38ff',
'./modules/Project/Project.js' => '79ed42c5778f501dc56ce6ef8f4a464f', './modules/Project/Project.js' => '79ed42c5778f501dc56ce6ef8f4a464f',
'./modules/Project/Project.php' => '9e365b1d96f37c9360bed81bfb90b82d', './modules/Project/Project.php' => '18dcf7210e2828f37711dc19e70c0f46',
'./modules/Project/ProjectJjwg_MapsLogicHook.php' => 'de2e3305cc404125f1201ae11f27f570', './modules/Project/ProjectJjwg_MapsLogicHook.php' => 'de2e3305cc404125f1201ae11f27f570',
'./modules/Project/ProjectListViewData.php' => '72a6d7a3b23f25a46c3f4029363d84ed', './modules/Project/ProjectListViewData.php' => '72a6d7a3b23f25a46c3f4029363d84ed',
'./modules/Project/ProjectListViewSmarty.php' => '52a0635c642726e7b2ebc05271f7dbfb', './modules/Project/ProjectListViewSmarty.php' => '52a0635c642726e7b2ebc05271f7dbfb',
@ -5700,7 +5779,7 @@ $md5_string = array (
'./modules/Project/js/main_lib_chart.js' => '91d61dc6376fef2c4b1c695b9d192a13', './modules/Project/js/main_lib_chart.js' => '91d61dc6376fef2c4b1c695b9d192a13',
'./modules/Project/js/splitter.js' => 'd59c79df0ee13a45610c508fe102b0e9', './modules/Project/js/splitter.js' => 'd59c79df0ee13a45610c508fe102b0e9',
'./modules/Project/jsclass_scheduler.js' => '68e8fb65f075df79972f2b09d8a0ee6c', './modules/Project/jsclass_scheduler.js' => '68e8fb65f075df79972f2b09d8a0ee6c',
'./modules/Project/language/en_us.lang.php' => '63703dbe4156eba0f39d1dcfb6a446da', './modules/Project/language/en_us.lang.php' => '51d8d5f311381a725a3ed323ad4294c6',
'./modules/Project/metadata/SearchFields.php' => '0c14f85c3b6470ef51134a42d98a2638', './modules/Project/metadata/SearchFields.php' => '0c14f85c3b6470ef51134a42d98a2638',
'./modules/Project/metadata/additionalDetails.php' => '56534241f092ac12f6ab27410a689ff2', './modules/Project/metadata/additionalDetails.php' => '56534241f092ac12f6ab27410a689ff2',
'./modules/Project/metadata/dashletviewdefs.php' => 'b30a45979396ce5d65ca7cd8bb41ae97', './modules/Project/metadata/dashletviewdefs.php' => 'b30a45979396ce5d65ca7cd8bb41ae97',
@ -5793,7 +5872,7 @@ $md5_string = array (
'./modules/ProspectLists/metadata/studio.php' => 'd41d8cd98f00b204e9800998ecf8427e', './modules/ProspectLists/metadata/studio.php' => 'd41d8cd98f00b204e9800998ecf8427e',
'./modules/ProspectLists/metadata/subpaneldefs.php' => '00135a1007ccae39bda2d94c13450e24', './modules/ProspectLists/metadata/subpaneldefs.php' => '00135a1007ccae39bda2d94c13450e24',
'./modules/ProspectLists/metadata/subpanels/default.php' => '271e2f81f8afde198bb7196d8cc98175', './modules/ProspectLists/metadata/subpanels/default.php' => '271e2f81f8afde198bb7196d8cc98175',
'./modules/ProspectLists/vardefs.php' => '34747acc6c91f4eba7fa940d63130b74', './modules/ProspectLists/vardefs.php' => '009962ade09fd508db08214679729600',
'./modules/Prospects/Delete.php' => 'e9ec47e61fafae5fe3afc7d6bc8844e4', './modules/Prospects/Delete.php' => 'e9ec47e61fafae5fe3afc7d6bc8844e4',
'./modules/Prospects/Import.php' => '866ded3702d87e20ec8aa853053d9fd4', './modules/Prospects/Import.php' => '866ded3702d87e20ec8aa853053d9fd4',
'./modules/Prospects/Menu.php' => '0af2124f64e4563183672100b6f8911e', './modules/Prospects/Menu.php' => '0af2124f64e4563183672100b6f8911e',
@ -5804,7 +5883,7 @@ $md5_string = array (
'./modules/Prospects/ProspectsListViewSmarty.php' => '48a47efe4bb101d6aa958b051ebfcecd', './modules/Prospects/ProspectsListViewSmarty.php' => '48a47efe4bb101d6aa958b051ebfcecd',
'./modules/Prospects/Save.php' => '8d48a85c6b8db36d63fe554573196a9f', './modules/Prospects/Save.php' => '8d48a85c6b8db36d63fe554573196a9f',
'./modules/Prospects/field_arrays.php' => '427aa1c9df31559f3c5ddc43ad11c3ea', './modules/Prospects/field_arrays.php' => '427aa1c9df31559f3c5ddc43ad11c3ea',
'./modules/Prospects/language/en_us.lang.php' => '366b201801eb9da6effef546f2140b8f', './modules/Prospects/language/en_us.lang.php' => '1aff2cfc1c2a0cf3e9d71659b1309d05',
'./modules/Prospects/metadata/SearchFields.php' => 'f16f7fbdf65d5f4d9b34c8bd9abf9f49', './modules/Prospects/metadata/SearchFields.php' => 'f16f7fbdf65d5f4d9b34c8bd9abf9f49',
'./modules/Prospects/metadata/additionalDetails.php' => 'df4717b47d70bfb7ec9c603d8181e03f', './modules/Prospects/metadata/additionalDetails.php' => 'df4717b47d70bfb7ec9c603d8181e03f',
'./modules/Prospects/metadata/detailviewdefs.php' => 'f1b05c193f3e9115053d90be36be10ed', './modules/Prospects/metadata/detailviewdefs.php' => 'f1b05c193f3e9115053d90be36be10ed',
@ -6011,7 +6090,7 @@ $md5_string = array (
'./modules/SugarFeed/SugarFeedFlush.php' => 'c5861f849a67f9129ddd03006f336ea3', './modules/SugarFeed/SugarFeedFlush.php' => 'c5861f849a67f9129ddd03006f336ea3',
'./modules/SugarFeed/action_view_map.php' => 'ef827ccc71707c55e2f4aeee52a3ea38', './modules/SugarFeed/action_view_map.php' => 'ef827ccc71707c55e2f4aeee52a3ea38',
'./modules/SugarFeed/feedLogicBase.php' => 'bfb4cbeba25d3e81b7acfc1316aef90b', './modules/SugarFeed/feedLogicBase.php' => 'bfb4cbeba25d3e81b7acfc1316aef90b',
'./modules/SugarFeed/language/en_us.lang.php' => 'df73f15e2300c0fe4dc4bbd4b6ed11f2', './modules/SugarFeed/language/en_us.lang.php' => '0ccdb1ef6048bfa72521438c72fdfae3',
'./modules/SugarFeed/linkHandlers/Image.php' => 'a31a903f29083567f3da036f42dabd11', './modules/SugarFeed/linkHandlers/Image.php' => 'a31a903f29083567f3da036f42dabd11',
'./modules/SugarFeed/linkHandlers/Link.php' => '3de956f6119b3e69ace9ee79134cc783', './modules/SugarFeed/linkHandlers/Link.php' => '3de956f6119b3e69ace9ee79134cc783',
'./modules/SugarFeed/linkHandlers/YouTube.php' => '3a53066a15c82a30a5667f27952ab8c7', './modules/SugarFeed/linkHandlers/YouTube.php' => '3a53066a15c82a30a5667f27952ab8c7',
@ -6148,7 +6227,7 @@ $md5_string = array (
'./modules/Tasks/Task.php' => '830f6e26657a32593a65209c48b44983', './modules/Tasks/Task.php' => '830f6e26657a32593a65209c48b44983',
'./modules/Tasks/TasksQuickCreate.php' => 'c9cf50c4c2051463805e357fddc7cc33', './modules/Tasks/TasksQuickCreate.php' => 'c9cf50c4c2051463805e357fddc7cc33',
'./modules/Tasks/field_arrays.php' => 'f623385316cb5b80050c38b385167e68', './modules/Tasks/field_arrays.php' => 'f623385316cb5b80050c38b385167e68',
'./modules/Tasks/language/en_us.lang.php' => '452f6bd1a92f1db433331f2681ff0deb', './modules/Tasks/language/en_us.lang.php' => '5fe62f4aedba875944eec66b76b80df6',
'./modules/Tasks/metadata/SearchFields.php' => '9d59496db381b96f781b4aed415da053', './modules/Tasks/metadata/SearchFields.php' => '9d59496db381b96f781b4aed415da053',
'./modules/Tasks/metadata/additionalDetails.php' => '95bc836a0e9b2ba3749dd8acdd064371', './modules/Tasks/metadata/additionalDetails.php' => '95bc836a0e9b2ba3749dd8acdd064371',
'./modules/Tasks/metadata/detailviewdefs.php' => '07522548e10d8faf35623ae1ac43a472', './modules/Tasks/metadata/detailviewdefs.php' => '07522548e10d8faf35623ae1ac43a472',
@ -6216,14 +6295,14 @@ $md5_string = array (
'./modules/UpgradeWizard/deleteCache.php' => '470b767cd3878224be42bb061718f9f3', './modules/UpgradeWizard/deleteCache.php' => '470b767cd3878224be42bb061718f9f3',
'./modules/UpgradeWizard/end.php' => '2f9479befa990b4071724584b76e21bd', './modules/UpgradeWizard/end.php' => '2f9479befa990b4071724584b76e21bd',
'./modules/UpgradeWizard/index.php' => '0888ccaaa20e2d76b9960281e79adcb9', './modules/UpgradeWizard/index.php' => '0888ccaaa20e2d76b9960281e79adcb9',
'./modules/UpgradeWizard/language/en_us.lang.php' => '126981067623fcb7e66e9095cafc6adc', './modules/UpgradeWizard/language/en_us.lang.php' => 'a4166110c4847d966f1869700ffa83d5',
'./modules/UpgradeWizard/layouts.php' => '71966ba2b06cda486950e150cf6d31ac', './modules/UpgradeWizard/layouts.php' => '71966ba2b06cda486950e150cf6d31ac',
'./modules/UpgradeWizard/preflight.php' => 'b62aadd0f867d2939e32c011d54e78c7', './modules/UpgradeWizard/preflight.php' => 'b62aadd0f867d2939e32c011d54e78c7',
'./modules/UpgradeWizard/preflightJson.php' => '39d77be3ff205cdb97afb33d513ac569', './modules/UpgradeWizard/preflightJson.php' => '39d77be3ff205cdb97afb33d513ac569',
'./modules/UpgradeWizard/processing.gif' => 'd7c43fc19181ee59862601bfce100b41', './modules/UpgradeWizard/processing.gif' => 'd7c43fc19181ee59862601bfce100b41',
'./modules/UpgradeWizard/silentUpgrade.php' => 'c71d5c10afa74a6a9670b38dfd60153c', './modules/UpgradeWizard/silentUpgrade.php' => 'c71d5c10afa74a6a9670b38dfd60153c',
'./modules/UpgradeWizard/silentUpgrade_dce_step1.php' => '7680ec42be6a098d9693c4fa71e91402', './modules/UpgradeWizard/silentUpgrade_dce_step1.php' => '7680ec42be6a098d9693c4fa71e91402',
'./modules/UpgradeWizard/silentUpgrade_dce_step2.php' => '3f5cfd8c9300e738c7e1105dd975db10', './modules/UpgradeWizard/silentUpgrade_dce_step2.php' => 'd43c3ec83dfcf83db5bb33f3d3350ee9',
'./modules/UpgradeWizard/silentUpgrade_step1.php' => '2f9154452c49d0daee5e49a3c8661b4e', './modules/UpgradeWizard/silentUpgrade_step1.php' => '2f9154452c49d0daee5e49a3c8661b4e',
'./modules/UpgradeWizard/silentUpgrade_step2.php' => '52a58afe6b488498da6aa9bdb5dec9b8', './modules/UpgradeWizard/silentUpgrade_step2.php' => '52a58afe6b488498da6aa9bdb5dec9b8',
'./modules/UpgradeWizard/start.php' => '8875bde8f6730d99d12c231e7e4f2b42', './modules/UpgradeWizard/start.php' => '8875bde8f6730d99d12c231e7e4f2b42',
@ -6238,7 +6317,7 @@ $md5_string = array (
'./modules/UpgradeWizard/uw_emptyFunctions.php' => '78d1a2e170174830b7dd1522db706828', './modules/UpgradeWizard/uw_emptyFunctions.php' => '78d1a2e170174830b7dd1522db706828',
'./modules/UpgradeWizard/uw_files.php' => 'acff8db8712e3f892d46e6dcdcf13fbc', './modules/UpgradeWizard/uw_files.php' => 'acff8db8712e3f892d46e6dcdcf13fbc',
'./modules/UpgradeWizard/uw_main.tpl' => '563f6ae242f53959263ac1c1715e8ceb', './modules/UpgradeWizard/uw_main.tpl' => '563f6ae242f53959263ac1c1715e8ceb',
'./modules/UpgradeWizard/uw_utils.php' => '78a90b050999c507f2d160217433a379', './modules/UpgradeWizard/uw_utils.php' => '19bfc2d1381c212026d8ef1920077d5d',
'./modules/UserPreferences/UserPreference.php' => '3cc5dbd2e7656335b3ab2840e525aa04', './modules/UserPreferences/UserPreference.php' => '3cc5dbd2e7656335b3ab2840e525aa04',
'./modules/UserPreferences/controller.php' => 'e16a3a57f09f52b0d58778017dab5957', './modules/UserPreferences/controller.php' => 'e16a3a57f09f52b0d58778017dab5957',
'./modules/UserPreferences/field_arrays.php' => '813ef8bb8a16fa4ae0875e46733227fa', './modules/UserPreferences/field_arrays.php' => '813ef8bb8a16fa4ae0875e46733227fa',
@ -6247,12 +6326,12 @@ $md5_string = array (
'./modules/Users/Authenticate.php' => '38bd32d884acd2f6eef56d4d112d62e8', './modules/Users/Authenticate.php' => '38bd32d884acd2f6eef56d4d112d62e8',
'./modules/Users/ChangeGroupTab.php' => '75c96050731409946537fd5d680b4d09', './modules/Users/ChangeGroupTab.php' => '75c96050731409946537fd5d680b4d09',
'./modules/Users/ChangePassword.php' => '5c4c364e4202327e382be7f97f9cad7f', './modules/Users/ChangePassword.php' => '5c4c364e4202327e382be7f97f9cad7f',
'./modules/Users/Changenewpassword.php' => '63989955aa0b42c16e3451075d6095f3', './modules/Users/Changenewpassword.php' => '0d9351dd4d5cf19c8eabd6a6f363b480',
'./modules/Users/Changenewpassword.tpl' => '7ab50a964566c3b61b633911a8b9b0ce', './modules/Users/Changenewpassword.tpl' => '7ab50a964566c3b61b633911a8b9b0ce',
'./modules/Users/DetailView.js' => 'dc2c0570507653dfcbc081346d2d5592', './modules/Users/DetailView.js' => 'dc2c0570507653dfcbc081346d2d5592',
'./modules/Users/Error.php' => '974cf5b2e9d530a56a38f54295452f12', './modules/Users/Error.php' => '974cf5b2e9d530a56a38f54295452f12',
'./modules/Users/Forms.php' => '542f6a00ce7cf53d86c21b24b03c286f', './modules/Users/Forms.php' => '542f6a00ce7cf53d86c21b24b03c286f',
'./modules/Users/GeneratePassword.php' => '4a5b08c17c3b07ce2078db5ab9df60c9', './modules/Users/GeneratePassword.php' => 'c14fa3a7d189159f59c0adf91bf07268',
'./modules/Users/GoogleApiKeySaverEntryPoint.php' => '4bcae8920af13ae01cc376f763d673fb', './modules/Users/GoogleApiKeySaverEntryPoint.php' => '4bcae8920af13ae01cc376f763d673fb',
'./modules/Users/ListRoles.php' => '470204e9dd0e9421f06f7304cf72e063', './modules/Users/ListRoles.php' => '470204e9dd0e9421f06f7304cf72e063',
'./modules/Users/LoggedOut.php' => '651bfc7c6c36f3791c2693bda075beb9', './modules/Users/LoggedOut.php' => '651bfc7c6c36f3791c2693bda075beb9',
@ -6294,7 +6373,7 @@ $md5_string = array (
'./modules/Users/authentication/SAML2Authenticate/SAML2Metadata.php' => '6b782e1dee5333f1750147fb897bb3de', './modules/Users/authentication/SAML2Authenticate/SAML2Metadata.php' => '6b782e1dee5333f1750147fb897bb3de',
'./modules/Users/authentication/SAML2Authenticate/lib/onelogin/settings.php' => '14bf0f95b02579fd86ec92306b8acb19', './modules/Users/authentication/SAML2Authenticate/lib/onelogin/settings.php' => '14bf0f95b02579fd86ec92306b8acb19',
'./modules/Users/authentication/SugarAuthenticate/FactorAuthEmailCode.php' => '50d80f3f698080c021cf7ecf0ab084a5', './modules/Users/authentication/SugarAuthenticate/FactorAuthEmailCode.php' => '50d80f3f698080c021cf7ecf0ab084a5',
'./modules/Users/authentication/SugarAuthenticate/FactorAuthEmailCode.tpl' => '6e8e95494b173f2afb8cc500e4459641', './modules/Users/authentication/SugarAuthenticate/FactorAuthEmailCode.tpl' => '7d47d05738a22f219f9a96ee5393792c',
'./modules/Users/authentication/SugarAuthenticate/FactorAuthFactory.php' => '02b5b7c4588faf6268b79741850379c4', './modules/Users/authentication/SugarAuthenticate/FactorAuthFactory.php' => '02b5b7c4588faf6268b79741850379c4',
'./modules/Users/authentication/SugarAuthenticate/FactorAuthInterface.php' => '01bb1e373dcf4cc53dc3ff41f0040d00', './modules/Users/authentication/SugarAuthenticate/FactorAuthInterface.php' => '01bb1e373dcf4cc53dc3ff41f0040d00',
'./modules/Users/authentication/SugarAuthenticate/SugarAuthenticate.php' => '4b1d9b735022ae8cf9a1d5ea3515617b', './modules/Users/authentication/SugarAuthenticate/SugarAuthenticate.php' => '4b1d9b735022ae8cf9a1d5ea3515617b',
@ -6303,7 +6382,7 @@ $md5_string = array (
'./modules/Users/entryPointSaveGoogleApiKey.php' => '93594685ab60cfa9a47606f9b00f7c9a', './modules/Users/entryPointSaveGoogleApiKey.php' => '93594685ab60cfa9a47606f9b00f7c9a',
'./modules/Users/field_arrays.php' => 'b2de6918c313caef59c28582475ab3a6', './modules/Users/field_arrays.php' => 'b2de6918c313caef59c28582475ab3a6',
'./modules/Users/googleApiKeySaverEntryPointError.tpl' => '5b45b5ce045c459e3e6c571d43eef873', './modules/Users/googleApiKeySaverEntryPointError.tpl' => '5b45b5ce045c459e3e6c571d43eef873',
'./modules/Users/language/en_us.lang.php' => '1716b0144df829dadf931cd55f25c926', './modules/Users/language/en_us.lang.php' => '7cf5849bd441e65eb84ae48067c4a47b',
'./modules/Users/login.css' => '2c43ea9ba2bed908c545bde7ee7c4575', './modules/Users/login.css' => '2c43ea9ba2bed908c545bde7ee7c4575',
'./modules/Users/login.js' => '9776ceb7e44df34b157a478002500782', './modules/Users/login.js' => '9776ceb7e44df34b157a478002500782',
'./modules/Users/login.tpl' => '76e56647f4334e8ee80ec2defa4d1659', './modules/Users/login.tpl' => '76e56647f4334e8ee80ec2defa4d1659',
@ -6331,12 +6410,12 @@ $md5_string = array (
'./modules/Users/password_utils.php' => 'c445ba371decfae7afb76ad09c060e8a', './modules/Users/password_utils.php' => 'c445ba371decfae7afb76ad09c060e8a',
'./modules/Users/reassignUserRecords.php' => '0db6428f348ea8ab23a1bd88a5725339', './modules/Users/reassignUserRecords.php' => '0db6428f348ea8ab23a1bd88a5725339',
'./modules/Users/tpls/DetailView.tpl' => '2b5edc433a18eab9e1dc24f55c015ced', './modules/Users/tpls/DetailView.tpl' => '2b5edc433a18eab9e1dc24f55c015ced',
'./modules/Users/tpls/EditViewFooter.tpl' => '72ad7d034dbd494bd4271e480f61b7aa', './modules/Users/tpls/EditViewFooter.tpl' => '3468ee673ada79bdb8129aeca2a739b6',
'./modules/Users/tpls/EditViewGroup.tpl' => '97bbb48546d0b13a60dac111abb8358a', './modules/Users/tpls/EditViewGroup.tpl' => '97bbb48546d0b13a60dac111abb8358a',
'./modules/Users/tpls/EditViewHeader.tpl' => '099f5e4896d623b64d44f243c33941b2', './modules/Users/tpls/EditViewHeader.tpl' => '099f5e4896d623b64d44f243c33941b2',
'./modules/Users/tpls/QuickEditFooter.tpl' => 'b7a9c930f9e885fcc51b7da358411c31', './modules/Users/tpls/QuickEditFooter.tpl' => 'b7a9c930f9e885fcc51b7da358411c31',
'./modules/Users/tpls/wizard.tpl' => 'acafbe8bf6a878386c99694798c79174', './modules/Users/tpls/wizard.tpl' => 'acafbe8bf6a878386c99694798c79174',
'./modules/Users/vardefs.php' => 'cf9501fd7fbd50e8e3c19950b8891a38', './modules/Users/vardefs.php' => 'b2eef83cd83e885aee01dd2f75afc18c',
'./modules/Users/views/view.detail.php' => 'b3ff99efac48a47a4654df64ba1cbe1d', './modules/Users/views/view.detail.php' => 'b3ff99efac48a47a4654df64ba1cbe1d',
'./modules/Users/views/view.edit.php' => '80a046d019b1aaf66bd4200bc831efe1', './modules/Users/views/view.edit.php' => '80a046d019b1aaf66bd4200bc831efe1',
'./modules/Users/views/view.list.php' => 'e314cc246214b55bf32383050a297f59', './modules/Users/views/view.list.php' => 'e314cc246214b55bf32383050a297f59',
@ -6525,7 +6604,7 @@ $md5_string = array (
'./service/v2_1/registry.php' => '30fba03dde8c6e58a1a3af61a93f5d24', './service/v2_1/registry.php' => '30fba03dde8c6e58a1a3af61a93f5d24',
'./service/v2_1/rest.php' => 'e9043e1cdec6023c62c14b4e88366a53', './service/v2_1/rest.php' => 'e9043e1cdec6023c62c14b4e88366a53',
'./service/v2_1/soap.php' => '33b9a9f02babd6840a115099ed37194c', './service/v2_1/soap.php' => '33b9a9f02babd6840a115099ed37194c',
'./service/v3/SugarWebServiceImplv3.php' => '59f8a2f407e80aba261bc9388ed5ae0f', './service/v3/SugarWebServiceImplv3.php' => '5ed2d7233e7cb3970585a7e43dca7c4c',
'./service/v3/SugarWebServiceUtilv3.php' => '20c69c6906b7b4b085dbb22a0889f3eb', './service/v3/SugarWebServiceUtilv3.php' => '20c69c6906b7b4b085dbb22a0889f3eb',
'./service/v3/registry.php' => '4b3a08f3e5bc0c24717827b6f2865e15', './service/v3/registry.php' => '4b3a08f3e5bc0c24717827b6f2865e15',
'./service/v3/rest.php' => 'e972697761509f2ac0caca7e0db74fe4', './service/v3/rest.php' => 'e972697761509f2ac0caca7e0db74fe4',
@ -6559,25 +6638,25 @@ $md5_string = array (
'./soap.php' => 'e28988c2e0b8e2c484587b537a710525', './soap.php' => 'e28988c2e0b8e2c484587b537a710525',
'./sugar_version.json' => 'bdfbcefae2f9af559bef6a36367df7bb', './sugar_version.json' => 'bdfbcefae2f9af559bef6a36367df7bb',
'./sugar_version.php' => 'db7b6c8d51f87879fce1e6172eedfbed', './sugar_version.php' => 'db7b6c8d51f87879fce1e6172eedfbed',
'./suitecrm_version.php' => '8cb4780e33c44be2c785910cb597dc8d', './suitecrm_version.php' => '000d6549775d93be1199f3d48df797e6',
'./themes/SuiteP/css/Dawn/color-palette.scss' => 'f85621a6c8b0cd015a8c4703e83e519b', './themes/SuiteP/css/Dawn/color-palette.scss' => 'f85621a6c8b0cd015a8c4703e83e519b',
'./themes/SuiteP/css/Dawn/icons.scss' => 'd59f8c5855e7a8df09542a663835a196', './themes/SuiteP/css/Dawn/icons.scss' => 'd59f8c5855e7a8df09542a663835a196',
'./themes/SuiteP/css/Dawn/style.css' => 'a675284a9615327fa30d0fa851dd2712', './themes/SuiteP/css/Dawn/style.css' => 'a6fcb84280b719f1c3dabe74385553bd',
'./themes/SuiteP/css/Dawn/style.scss' => '2fe759bc1c69865732f0ae0cca88916c', './themes/SuiteP/css/Dawn/style.scss' => '2fe759bc1c69865732f0ae0cca88916c',
'./themes/SuiteP/css/Dawn/variables.scss' => '43025e22cbae0ef63f682777231d2720', './themes/SuiteP/css/Dawn/variables.scss' => '43025e22cbae0ef63f682777231d2720',
'./themes/SuiteP/css/Day/color-palette.scss' => 'afec17a97776f397f3fd5f4cc261efbf', './themes/SuiteP/css/Day/color-palette.scss' => 'afec17a97776f397f3fd5f4cc261efbf',
'./themes/SuiteP/css/Day/icons.scss' => '7a77bb17a810866e1ec4e0667e58e536', './themes/SuiteP/css/Day/icons.scss' => '7a77bb17a810866e1ec4e0667e58e536',
'./themes/SuiteP/css/Day/style.css' => '50dfd113a581826174957d37097e91f0', './themes/SuiteP/css/Day/style.css' => '8315e19e670ca97f91800c003f9ddeb7',
'./themes/SuiteP/css/Day/style.scss' => '8adb198a13e2e95ece09ded6a01be479', './themes/SuiteP/css/Day/style.scss' => '8adb198a13e2e95ece09ded6a01be479',
'./themes/SuiteP/css/Day/variables.scss' => '581ada6cbb74750dba34e20b8775a5ae', './themes/SuiteP/css/Day/variables.scss' => '581ada6cbb74750dba34e20b8775a5ae',
'./themes/SuiteP/css/Dusk/color-palette.scss' => '81e3e7f23a39261a5bc8afaeef93deff', './themes/SuiteP/css/Dusk/color-palette.scss' => '81e3e7f23a39261a5bc8afaeef93deff',
'./themes/SuiteP/css/Dusk/icons.scss' => '7a77bb17a810866e1ec4e0667e58e536', './themes/SuiteP/css/Dusk/icons.scss' => '7a77bb17a810866e1ec4e0667e58e536',
'./themes/SuiteP/css/Dusk/style.css' => 'edc629616bedcdb4371b51fbf89aea6b', './themes/SuiteP/css/Dusk/style.css' => '9e98837b80f37f3ecb21568b37bfbe8a',
'./themes/SuiteP/css/Dusk/style.scss' => '2fe759bc1c69865732f0ae0cca88916c', './themes/SuiteP/css/Dusk/style.scss' => '2fe759bc1c69865732f0ae0cca88916c',
'./themes/SuiteP/css/Dusk/variables.scss' => '85f09129e5917047c68404f663bd672f', './themes/SuiteP/css/Dusk/variables.scss' => '85f09129e5917047c68404f663bd672f',
'./themes/SuiteP/css/Night/color-palette.scss' => '80c13a4796898d3e25ee71f5ecbeb19f', './themes/SuiteP/css/Night/color-palette.scss' => '80c13a4796898d3e25ee71f5ecbeb19f',
'./themes/SuiteP/css/Night/icons.scss' => '2adfbf917fd7f0748090ef79ec4657c9', './themes/SuiteP/css/Night/icons.scss' => '2adfbf917fd7f0748090ef79ec4657c9',
'./themes/SuiteP/css/Night/style.css' => 'b0efe55e805769440fa0af17c1763764', './themes/SuiteP/css/Night/style.css' => '42ef9876439efec0c0d27ce7bb725853',
'./themes/SuiteP/css/Night/style.scss' => '2fe759bc1c69865732f0ae0cca88916c', './themes/SuiteP/css/Night/style.scss' => '2fe759bc1c69865732f0ae0cca88916c',
'./themes/SuiteP/css/Night/variables.scss' => '3d7ed52486bbd98f73a05db26c5753c0', './themes/SuiteP/css/Night/variables.scss' => '3d7ed52486bbd98f73a05db26c5753c0',
'./themes/SuiteP/css/bootstrap/alerts.scss' => 'c0e5396555dd4c70b9eeb314e4c4613d', './themes/SuiteP/css/bootstrap/alerts.scss' => 'c0e5396555dd4c70b9eeb314e4c4613d',
@ -6665,7 +6744,7 @@ $md5_string = array (
'./themes/SuiteP/css/normalize.css' => 'a269379c3f4b76d8efbb56b19efb7669', './themes/SuiteP/css/normalize.css' => 'a269379c3f4b76d8efbb56b19efb7669',
'./themes/SuiteP/css/print.css' => '8e27ac11c816bba3a82c22574cef76a6', './themes/SuiteP/css/print.css' => '8e27ac11c816bba3a82c22574cef76a6',
'./themes/SuiteP/css/studio.css' => '5750f3b197f3d09d3f32b5c6a66cce42', './themes/SuiteP/css/studio.css' => '5750f3b197f3d09d3f32b5c6a66cce42',
'./themes/SuiteP/css/suitep-base/admin.scss' => '12efe5500c3ad93fe03c2169dc513270', './themes/SuiteP/css/suitep-base/admin.scss' => 'bd85c8d6fb7c148f673c3f28d71931d3',
'./themes/SuiteP/css/suitep-base/aor.scss' => '9e861400449f4491c1970520e0795b5e', './themes/SuiteP/css/suitep-base/aor.scss' => '9e861400449f4491c1970520e0795b5e',
'./themes/SuiteP/css/suitep-base/aow.scss' => '446ecce2b758103d3c5b7ccb209d38f5', './themes/SuiteP/css/suitep-base/aow.scss' => '446ecce2b758103d3c5b7ccb209d38f5',
'./themes/SuiteP/css/suitep-base/calendar.scss' => 'e3678f282860d08d7693080a27fb9c1e', './themes/SuiteP/css/suitep-base/calendar.scss' => 'e3678f282860d08d7693080a27fb9c1e',
@ -6673,16 +6752,16 @@ $md5_string = array (
'./themes/SuiteP/css/suitep-base/cases.scss' => '24388474c9ceb4734d9b078377263f82', './themes/SuiteP/css/suitep-base/cases.scss' => '24388474c9ceb4734d9b078377263f82',
'./themes/SuiteP/css/suitep-base/dashboard.scss' => '64f63cbdfbae00261a17b31bcaf2a98a', './themes/SuiteP/css/suitep-base/dashboard.scss' => '64f63cbdfbae00261a17b31bcaf2a98a',
'./themes/SuiteP/css/suitep-base/detailview.scss' => '4bd0749956cab6d0305dd582acbd2040', './themes/SuiteP/css/suitep-base/detailview.scss' => '4bd0749956cab6d0305dd582acbd2040',
'./themes/SuiteP/css/suitep-base/editview.scss' => 'd26e9942b26a5a3cfb6b1d00a02feb8e', './themes/SuiteP/css/suitep-base/editview.scss' => 'a84810f3570f74aa2daf3c9598ce3dde',
'./themes/SuiteP/css/suitep-base/email.scss' => '268d344598c6c69668bd6e0c1d4ebeb8', './themes/SuiteP/css/suitep-base/email.scss' => '268d344598c6c69668bd6e0c1d4ebeb8',
'./themes/SuiteP/css/suitep-base/forms.scss' => '56216314246fc251e70ca0c140ed16e6', './themes/SuiteP/css/suitep-base/forms.scss' => '56216314246fc251e70ca0c140ed16e6',
'./themes/SuiteP/css/suitep-base/jstree.scss' => '946510970bb0774a31a01c2fb57a9552', './themes/SuiteP/css/suitep-base/jstree.scss' => '946510970bb0774a31a01c2fb57a9552',
'./themes/SuiteP/css/suitep-base/listview.scss' => 'bb544602180d36472458e222c840862e', './themes/SuiteP/css/suitep-base/listview.scss' => 'f0cb4471dfd2ace4ffc463901d870e04',
'./themes/SuiteP/css/suitep-base/login.scss' => '25d85a91770e80b7b0357cece6eb5c4b', './themes/SuiteP/css/suitep-base/login.scss' => '25d85a91770e80b7b0357cece6eb5c4b',
'./themes/SuiteP/css/suitep-base/main.scss' => '0ddf085214424ea1f19a13f7930f1c9a', './themes/SuiteP/css/suitep-base/main.scss' => '0ddf085214424ea1f19a13f7930f1c9a',
'./themes/SuiteP/css/suitep-base/mixins.scss' => '9edffdf421f6277979bd76df64d34fad', './themes/SuiteP/css/suitep-base/mixins.scss' => '9edffdf421f6277979bd76df64d34fad',
'./themes/SuiteP/css/suitep-base/modal.scss' => 'a74573b8eadb3ca7b8ace684650bc3c7', './themes/SuiteP/css/suitep-base/modal.scss' => 'a74573b8eadb3ca7b8ace684650bc3c7',
'./themes/SuiteP/css/suitep-base/navbar.scss' => 'd864246bb3392f894fb828e3a0af0a94', './themes/SuiteP/css/suitep-base/navbar.scss' => 'd7281e8e250e1380b99800e6bea2893e',
'./themes/SuiteP/css/suitep-base/panels.scss' => 'cbdc8afeb77bc3e3cd5bef45f984d3eb', './themes/SuiteP/css/suitep-base/panels.scss' => 'cbdc8afeb77bc3e3cd5bef45f984d3eb',
'./themes/SuiteP/css/suitep-base/popup.scss' => 'c8bc195104af9da3fee69b31e00e490c', './themes/SuiteP/css/suitep-base/popup.scss' => 'c8bc195104af9da3fee69b31e00e490c',
'./themes/SuiteP/css/suitep-base/projects.scss' => '31d48a58629a823d0db72dd3ae976770', './themes/SuiteP/css/suitep-base/projects.scss' => '31d48a58629a823d0db72dd3ae976770',
@ -6699,7 +6778,7 @@ $md5_string = array (
'./themes/SuiteP/css/suitep-base/suitepicon.woff' => 'fa8f02d9450e6f7acfb6ca02f418bc9d', './themes/SuiteP/css/suitep-base/suitepicon.woff' => 'fa8f02d9450e6f7acfb6ca02f418bc9d',
'./themes/SuiteP/css/suitep-base/tabs.scss' => 'acc7a3ab9658b6819bb581dcfb263b1e', './themes/SuiteP/css/suitep-base/tabs.scss' => 'acc7a3ab9658b6819bb581dcfb263b1e',
'./themes/SuiteP/css/suitep-base/tinemce.scss' => '223fd0b373c3f0459f050cafce57eac9', './themes/SuiteP/css/suitep-base/tinemce.scss' => '223fd0b373c3f0459f050cafce57eac9',
'./themes/SuiteP/css/suitep-base/yui.scss' => '8c8ac796dba9fdf3203cb6a9f2101bc9', './themes/SuiteP/css/suitep-base/yui.scss' => 'f0043cba4cb535b1956b43ccd8c975c6',
'./themes/SuiteP/css/wizard.css' => '339470b379448f6b91e90ea989d50904', './themes/SuiteP/css/wizard.css' => '339470b379448f6b91e90ea989d50904',
'./themes/SuiteP/fonts/1YwB1sO8YE1Lyjf12WNiUA.woff2' => '6748e0e1c0bef825e16c649fd2ad5691', './themes/SuiteP/fonts/1YwB1sO8YE1Lyjf12WNiUA.woff2' => '6748e0e1c0bef825e16c649fd2ad5691',
'./themes/SuiteP/fonts/2HG_tEPiQ4Z6795cGfdivFtXRa8TVwTICgirnJhmVJw.woff2' => '5f662e8ae2643cb62d51bad100ac2d82', './themes/SuiteP/fonts/2HG_tEPiQ4Z6795cGfdivFtXRa8TVwTICgirnJhmVJw.woff2' => '5f662e8ae2643cb62d51bad100ac2d82',
@ -8024,7 +8103,7 @@ $md5_string = array (
'./themes/SuiteP/tpls/_headerModuleList.tpl' => '35e093da774057960b47e25d274d2fd4', './themes/SuiteP/tpls/_headerModuleList.tpl' => '35e093da774057960b47e25d274d2fd4',
'./themes/SuiteP/tpls/footer.tpl' => '38c4fa89e7f7e7118f58f8a3f28fe231', './themes/SuiteP/tpls/footer.tpl' => '38c4fa89e7f7e7118f58f8a3f28fe231',
'./themes/SuiteP/tpls/header.tpl' => '273af9526ef61f369f6622d2794acd45', './themes/SuiteP/tpls/header.tpl' => '273af9526ef61f369f6622d2794acd45',
'./themes/SuiteP/tpls/login.tpl' => '6a8535dcc39315fcdf0d5416d4ff3f50', './themes/SuiteP/tpls/login.tpl' => '2e722fa7facd9656fd1c1c348260634d',
'./themes/default/css/bootstrap.css' => '35cda076a2dfccfb460b8225f38c104f', './themes/default/css/bootstrap.css' => '35cda076a2dfccfb460b8225f38c104f',
'./themes/default/css/chart.css' => 'cc19057a4b20d6f05bcd382e25f19fa2', './themes/default/css/chart.css' => 'cc19057a4b20d6f05bcd382e25f19fa2',
'./themes/default/css/content.min.css' => '9b6a853cc6a9e8cb9e46bfc11eb0d609', './themes/default/css/content.min.css' => '9b6a853cc6a9e8cb9e46bfc11eb0d609',

View file

@ -1,14 +1,11 @@
<?php <?php
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/** /**
* *
* SugarCRM Community Edition is a customer relationship management program developed by * SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
* *
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 SalesAgility Ltd. * Copyright (C) 2011 - 2021 SalesAgility Ltd.
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the * the terms of the GNU Affero General Public License version 3 as published by the
@ -41,37 +38,69 @@ if (!defined('sugarEntry') || !sugarEntry) {
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/ */
namespace SuiteCRM;
$module_name='AOD_IndexEvent'; if (!defined('sugarEntry') || !sugarEntry) {
$subpanel_layout = array( die('Not A Valid Entry Point');
'top_buttons' => array( }
array('widget_class' => 'SubPanelTopCreateButton'),
array('widget_class' => 'SubPanelTopSelectButton', 'popup_module' => $module_name),
),
'where' => '', /**
* Class CleanCSV
* @package SuiteCRM
*/
class CleanCSV
{
/**
* @var string
*/
protected $escapeChar;
'list_fields' => array( /**
'name'=>array( * @var array|string[]
'vname' => 'LBL_NAME', */
'widget_class' => 'SubPanelDetailViewLink', protected $startingChars;
'width' => '45%',
), /**
'date_modified'=>array( * CleanCSV constructor.
'vname' => 'LBL_DATE_MODIFIED', * @param string $escapeChar character to escape each CSV field.
'width' => '45%', * @param array|string[] $startingChars starting characters to be escaped.
), */
'edit_button'=>array( public function __construct($escapeChar = "'", array $startingChars = ['=', '-', '+', '@'])
'vname' => 'LBL_EDIT_BUTTON', {
'widget_class' => 'SubPanelEditButton', $this->escapeChar = $escapeChar;
'module' => $module_name, $this->startingChars = $startingChars;
'width' => '4%', }
),
'remove_button'=>array( /**
'vname' => 'LBL_REMOVE', * @return array|string[]
'widget_class' => 'SubPanelRemoveButton', */
'module' => $module_name, public function getStartingChars()
'width' => '5%', {
), return $this->startingChars;
), }
);
/**
* @return string
*/
public function getEscapeChar()
{
return $this->escapeChar;
}
/**
* @param string $cell
* @return string
*/
public function escapeField($cell)
{
if (!is_string($cell)) {
return $cell;
}
if (in_array($cell[0], $this->startingChars, true)) {
return $this->escapeChar . $cell;
}
return $cell;
}
}

View file

@ -126,6 +126,10 @@ function getEditFieldHTML($module, $fieldname, $aow_field, $view = 'EditView', $
if (isset($vardef['name']) && ($vardef['name'] == 'date_modified')) { if (isset($vardef['name']) && ($vardef['name'] == 'date_modified')) {
$vardef['name'] = 'aow_temp_date'; $vardef['name'] = 'aow_temp_date';
} }
if (isset($vardef['help'])) {
$vardef['help'] = htmlspecialchars($vardef['help'],ENT_QUOTES);
}
// load SugarFieldHandler to render the field tpl file // load SugarFieldHandler to render the field tpl file
static $sfh; static $sfh;
@ -362,6 +366,10 @@ function saveField($field, $id, $module, $value)
} }
if (($bean->ACLAccess("edit") || is_admin($current_user)) && $enabled) { if (($bean->ACLAccess("edit") || is_admin($current_user)) && $enabled) {
$bean->in_workflow=true;
if ($field == 'email1') {
$bean->email1_set_in_workflow=true;
}
if (!$bean->save($check_notify)) { if (!$bean->save($check_notify)) {
$GLOBALS['log']->fatal("Saving probably failed or bean->save() method did not return with a positive result."); $GLOBALS['log']->fatal("Saving probably failed or bean->save() method did not return with a positive result.");
} }

View file

@ -1480,7 +1480,7 @@ class ListView
$merge_link = "&nbsp;"; $merge_link = "&nbsp;";
} }
$selected_objects_span = "&nbsp;|&nbsp;{$this->local_app_strings['LBL_LISTVIEW_SELECTED_OBJECTS']}<input style='border: 0px; background: transparent; font-size: inherit; color: inherit' type='text' readonly name='selectCount[]' value='" . ((isset($_POST['mass'])) ? count($_POST['mass']): 0) . "' />"; $selected_objects_span = "&nbsp;&nbsp;{$this->local_app_strings['LBL_LISTVIEW_SELECTED_OBJECTS']}<input class='listviewcount' type='text' readonly name='selectCount[]' value='" . ((isset($_POST['mass'])) ? count($_POST['mass']): 0) . "' />";
if ($_REQUEST['module'] == 'Home' || $this->local_current_module == 'Import' if ($_REQUEST['module'] == 'Home' || $this->local_current_module == 'Import'
|| $this->show_export_button == false || $this->show_export_button == false

View file

@ -48,169 +48,198 @@ if (!defined('sugarEntry') || !sugarEntry) {
* To change the template for this generated file go to * To change the template for this generated file go to
* Window - Preferences - PHPeclipse - PHP - Code Templates * Window - Preferences - PHPeclipse - PHP - Code Templates
*/ */
require_once('include/ListView/ListViewSmarty.php'); require_once('include/ListView/ListViewSmarty.php');
/** /**
* A Facade to ListView and ListViewSmarty * A Facade to ListView and ListViewSmarty
*/ */
class ListViewFacade class ListViewFacade
{ {
public $focus = null; public $focus = null;
public $module = ''; public $module = '';
public $type = 0; public $type = 0;
public $lv; public $lv;
//ListView fields //ListView fields
public $template; public $template;
public $title; public $title;
public $where = ''; public $where = '';
public $params = array(); public $params = array();
public $offset = 0; public $offset = 0;
public $limit = -1; public $limit = -1;
public $filter_fields = array(); public $filter_fields = array();
public $id_field = 'id'; public $id_field = 'id';
public $prefix = ''; public $prefix = '';
public $mod_strings = array(); public $mod_strings = array();
/** /**
* Constructor * Constructor
* @param $focus - the bean * @param $focus - the bean
* @param $module - the module name * @param $module - the module name
* @param - 0 = decide for me, 1 = ListView.html, 2 = ListViewSmarty * @param - 0 = decide for me, 1 = ListView.html, 2 = ListViewSmarty
*/ */
public function __construct($focus, $module, $type = 0) public function __construct($focus, $module, $type = 0)
{ {
$this->focus = $focus; $this->focus = $focus;
$this->module = $module; $this->module = $module;
$this->type = $type; $this->type = $type;
$this->build(); $this->build();
} }
/** /**
* Retrieves display columns on list view of specified module * Retrieves all columns on list view of specified module
* *
* @param string $module * @param string $module
* @param array $request * @param array $request
* @return array * @return array
*/ * @description Returns all columns(default and non-default) defined for a Module List View
public static function getDisplayColumns($module, $request = []) */
{ public static function getAllColumns($module, $request = [])
$metadataFile = null; {
$foundViewDefs = false; $metadataFile = null;
if (file_exists('custom/modules/' . $module. '/metadata/listviewdefs.php')) { $foundViewDefs = false;
$metadataFile = 'custom/modules/' . $module . '/metadata/listviewdefs.php'; if (file_exists('custom/modules/' . $module . '/metadata/listviewdefs.php')) {
$foundViewDefs = true; $metadataFile = 'custom/modules/' . $module . '/metadata/listviewdefs.php';
} else { $foundViewDefs = true;
if (file_exists('custom/modules/'. $module.'/metadata/metafiles.php')) { } else {
require_once('custom/modules/'. $module.'/metadata/metafiles.php'); if (file_exists('custom/modules/' . $module . '/metadata/metafiles.php')) {
if (!empty($metafiles[$module]['listviewdefs'])) { require_once('custom/modules/' . $module . '/metadata/metafiles.php');
$metadataFile = $metafiles[$module]['listviewdefs']; if (!empty($metafiles[$module]['listviewdefs'])) {
$foundViewDefs = true; $metadataFile = $metafiles[$module]['listviewdefs'];
} $foundViewDefs = true;
} elseif (file_exists('modules/'. $module.'/metadata/metafiles.php')) { }
require_once('modules/'. $module.'/metadata/metafiles.php'); } elseif (file_exists('modules/' . $module . '/metadata/metafiles.php')) {
if (!empty($metafiles[$module]['listviewdefs'])) { require_once('modules/' . $module . '/metadata/metafiles.php');
$metadataFile = $metafiles[$module]['listviewdefs']; if (!empty($metafiles[$module]['listviewdefs'])) {
$foundViewDefs = true; $metadataFile = $metafiles[$module]['listviewdefs'];
} $foundViewDefs = true;
} }
} }
if (!$foundViewDefs && file_exists('modules/'. $module.'/metadata/listviewdefs.php')) { }
$metadataFile = 'modules/'. $module.'/metadata/listviewdefs.php'; if (!$foundViewDefs && file_exists('modules/' . $module . '/metadata/listviewdefs.php')) {
} $metadataFile = 'modules/' . $module . '/metadata/listviewdefs.php';
}
if ($metadataFile) {
if (!file_exists($metadataFile)) {
throw new Exception("Metadata file '$metadataFile' not found for module '$module'.");
}
require_once($metadataFile);
}
$displayColumns = array(); if ($metadataFile) {
if (!empty($listViewDefs)) { if (!file_exists($metadataFile)) {
if (!empty($request['displayColumns'])) { throw new Exception("Metadata file '$metadataFile' not found for module '$module'.");
foreach (explode('|', $_REQUEST['displayColumns']) as $num => $col) { }
if (!empty($listViewDefs[$module][$col])) { require_once($metadataFile);
$displayColumns[$col] = $listViewDefs[$module][$col]; }
}
}
} else {
foreach ($listViewDefs[$module] as $col => $params) {
if (!empty($params['default']) && $params['default']) {
$displayColumns[$col] = $params;
}
}
}
} else {
throw new Exception("List view definition is not found for module '$module'");
}
return $displayColumns;
}
public function build() $displayColumns = array();
{ if (!empty($listViewDefs)) {
//we will assume that if the ListView.html file exists we will want to use that one if (!empty($request['displayColumns'])) {
if (file_exists('modules/'.$this->module.'/ListView.html')) { foreach (explode('|', $_REQUEST['displayColumns']) as $num => $col) {
$this->type = 1; if (!empty($listViewDefs[$module][$col])) {
$this->lv = new ListView(); $displayColumns[$col] = $listViewDefs[$module][$col];
$this->template = 'modules/'.$this->module.'/ListView.html'; }
} else { }
$this->lv = new ListViewSmarty(); } else {
$this->lv->displayColumns = self::getDisplayColumns($this->module, $_REQUEST); foreach ($listViewDefs[$module] as $col => $params) {
$this->type = 2; //if (!empty($params['default']) && $params['default']) {
$this->template = 'include/ListView/ListViewGeneric.tpl'; $displayColumns[$col] = $params;
} //}
} }
}
} else {
throw new Exception("List view definition is not found for module '$module'");
}
return $displayColumns;
}
public function setup($template = '', $where = '', $params = array(), $mod_strings = array(), $offset = 0, $limit = -1, $orderBy = '', $prefix = '', $filter_fields = array(), $id_field = 'id') /**
{ * Retrieves display columns on list view of specified module
if (!empty($template)) { *
$this->template = $template; * @param string $module
} * @param array $request
* @return array
* @description Returns columns displayed by default in Module List View
*/
public static function getDisplayColumns($module, $request = []): array
{
$displayColumns = [];
$this->mod_strings = $mod_strings; try {
$allColumns = self::getAllColumns($module, $request);
// filter columns with default != false
foreach ($allColumns as $col => $params) {
if (!empty($params['default']) && $params['default']) {
$displayColumns[$col] = $params;
}
}
} catch (Exception $e) {
$logMessage = "List view definition is not found for module '$module'" . $e->getMessage();
$GLOBALS['log']->fatal($logMessage);
}
if ($this->type == 1) { return $displayColumns;
$this->lv->initNewXTemplate($this->template, $this->mod_strings); }
$this->prefix = $prefix;
$this->lv->setQuery($where, $limit, $orderBy, $prefix);
$this->lv->show_select_menu = false;
$this->lv->show_export_button = false;
$this->lv->show_delete_button = false;
$this->lv->show_mass_update = false;
$this->lv->show_mass_update_form = false;
} else {
$this->lv->export = false;
$this->lv->delete = false;
$this->lv->select = false;
$this->lv->mailMerge = false;
$this->lv->multiSelect = false;
$this->lv->setup($this->focus, $this->template, $where, $params, $offset, $limit, $filter_fields, $id_field);
}
}
public function display($title = '', $section = 'main', $return = false) public function build()
{ {
if ($this->type == 1) { //we will assume that if the ListView.html file exists we will want to use that one
ob_start(); if (file_exists('modules/' . $this->module . '/ListView.html')) {
$this->lv->setHeaderTitle($title); $this->type = 1;
$this->lv->processListView($this->focus, $section, $this->prefix); $this->lv = new ListView();
$output = ob_get_contents(); $this->template = 'modules/' . $this->module . '/ListView.html';
ob_end_clean(); } else {
} else { $this->lv = new ListViewSmarty();
$output = get_form_header($title, '', false) . $this->lv->display(); $this->lv->displayColumns = self::getDisplayColumns($this->module, $_REQUEST);
} $this->type = 2;
if ($return) { $this->template = 'include/ListView/ListViewGeneric.tpl';
return $output; }
} else { }
echo $output;
}
}
public function setTitle($title = '') public function setup($template = '', $where = '', $params = array(), $mod_strings = array(), $offset = 0, $limit = -1, $orderBy = '', $prefix = '', $filter_fields = array(), $id_field = 'id')
{ {
$this->title = $title; if (!empty($template)) {
} $this->template = $template;
} }
$this->mod_strings = $mod_strings;
if ($this->type == 1) {
$this->lv->initNewXTemplate($this->template, $this->mod_strings);
$this->prefix = $prefix;
$this->lv->setQuery($where, $limit, $orderBy, $prefix);
$this->lv->show_select_menu = false;
$this->lv->show_export_button = false;
$this->lv->show_delete_button = false;
$this->lv->show_mass_update = false;
$this->lv->show_mass_update_form = false;
} else {
$this->lv->export = false;
$this->lv->delete = false;
$this->lv->select = false;
$this->lv->mailMerge = false;
$this->lv->multiSelect = false;
$this->lv->setup($this->focus, $this->template, $where, $params, $offset, $limit, $filter_fields, $id_field);
}
}
public function display($title = '', $section = 'main', $return = false)
{
if ($this->type == 1) {
ob_start();
$this->lv->setHeaderTitle($title);
$this->lv->processListView($this->focus, $section, $this->prefix);
$output = ob_get_contents();
ob_end_clean();
} else {
$output = get_form_header($title, '', false) . $this->lv->display();
}
if ($return) {
return $output;
} else {
echo $output;
}
}
public function setTitle($title = '')
{
$this->title = $title;
}
}

View file

@ -865,9 +865,6 @@ class SugarApplication
$vars[$var] = $_REQUEST['login_' . $var]; $vars[$var] = $_REQUEST['login_' . $var];
} }
} }
if (isset($_REQUEST['mobile'])) {
$vars['mobile'] = $_REQUEST['mobile'];
}
if (isset($_REQUEST['mobile'])) { if (isset($_REQUEST['mobile'])) {
$vars['mobile'] = $_REQUEST['mobile']; $vars['mobile'] = $_REQUEST['mobile'];

View file

@ -789,7 +789,8 @@ class SubPanelDefinitions
//use tab controller function to get module list with named keys //use tab controller function to get module list with named keys
require_once("modules/MySettings/TabController.php"); require_once("modules/MySettings/TabController.php");
$modules_to_check = TabController::get_key_array($moduleList); $tabController = new TabController();
$modules_to_check = $tabController->get_key_array($moduleList);
//change case to match subpanel processing later on //change case to match subpanel processing later on
$modules_to_check = array_change_key_case($modules_to_check); $modules_to_check = array_change_key_case($modules_to_check);

View file

@ -190,6 +190,8 @@ class SubPanelTiles
$tabs_properties = array(); $tabs_properties = array();
$tab_names = array(); $tab_names = array();
$module_sub_panels = [];
$default_div_display = 'inline'; $default_div_display = 'inline';
if (!empty($sugar_config['hide_subpanels_on_login'])) { if (!empty($sugar_config['hide_subpanels_on_login'])) {
if (!isset($_SESSION['visited_details'][$this->focus->module_dir])) { if (!isset($_SESSION['visited_details'][$this->focus->module_dir])) {
@ -373,7 +375,7 @@ class SubPanelTiles
$countStr = '...'; $countStr = '...';
$extraClass = ' incomplete'; $extraClass = ' incomplete';
} }
$tabs_properties[$t]['title'] .= ' (<span class="subPanelCountHint' . $extraClass . '" data-subpanel="' . $tab . '" data-module="' . $layout_def_key . '" data-record="' . $_REQUEST['record'] . '">' . $countStr . '</span>)'; $tabs_properties[$t]['title'] .= ' (<span class="subPanelCountHint' . $extraClass . '" data-subpanel="' . $tab . '" data-module="' . $layout_def_key . '" data-record="' . $_REQUEST['record'] . '">' . $countStr . '</span>)';
} }

View file

@ -60,7 +60,7 @@ var emailAddressWidgetLoaded = false;
<div class="col-xs-12 email-address-add-line-container emailaddresses" id="{$module}emailAddressesTable{$index}"> <div class="col-xs-12 email-address-add-line-container emailaddresses" id="{$module}emailAddressesTable{$index}">
{capture assign="other_attributes"}id="{$module}{$index}_email_widget_add" onclick="SUGAR.EmailAddressWidget.instances.{$module}{$index}.addEmailAddress('{$module}emailAddressesTable{$index}','', false);"{/capture} {capture assign="other_attributes"}id="{$module}{$index}_email_widget_add" onclick="SUGAR.EmailAddressWidget.instances.{$module}{$index}.addEmailAddress('{$module}emailAddressesTable{$index}','', false);"{/capture}
<button type="button" class="btn btn-danger email-address-add-button" title="{$app_strings.LBL_ID_FF_ADD_EMAIL} " {$other_attributes}> <button type="button" class="btn btn-danger email-address-add-button" title="{$app_strings.LBL_ID_FF_ADD_EMAIL} " {$other_attributes}>
<span class="suitepicon suitepicon-action-plus"></span><span></span> <span class="suitepicon suitepicon-action-plus"></span>
</button> </button>
</div> </div>
<div class="col-xs-12 email-address-lines-container"> <div class="col-xs-12 email-address-lines-container">

View file

@ -46,12 +46,14 @@
{{assign var=flag_field value=$vardef.name|cat:_flag}} {{assign var=flag_field value=$vardef.name|cat:_flag}}
<table border="0" cellpadding="0" cellspacing="0" class="dateTime"> <table border="0" cellpadding="0" cellspacing="0" class="dateTime">
<tr valign="middle"> <tr valign="middle">
<td nowrap class="dateTimeComboColumn"> <td nowrap class="dateTimeComboColumn datecalendar">
<input autocomplete="off" type="text" id="{{$idname}}_date" class="datetimecombo_date" value="{$fields[{{sugarvar key='name' stringFormat=true}}].value}" size="11" maxlength="10" title='{{$vardef.help}}' tabindex="{{$tabindex}}" onblur="combo_{{$idname}}.update();" onchange="combo_{{$idname}}.update(); {{if isset($displayParams.updateCallback)}}{{$displayParams.updateCallback}}{{/if}}" {{if !empty($displayParams.accesskey)}} accesskey='{{$displayParams.accesskey}}' {{/if}} > <input autocomplete="off" type="text" id="{{$idname}}_date" class="datetimecombo_date" value="{$fields[{{sugarvar key='name' stringFormat=true}}].value}" size="11" maxlength="10" title='{{$vardef.help}}' tabindex="{{$tabindex}}" onblur="combo_{{$idname}}.update();" onchange="combo_{{$idname}}.update(); {{if isset($displayParams.updateCallback)}}{{$displayParams.updateCallback}}{{/if}}" {{if !empty($displayParams.accesskey)}} accesskey='{{$displayParams.accesskey}}' {{/if}} >
<button type="button" id="{{$idname}}_trigger" class="btn btn-danger" onclick="return false;"><span class="suitepicon suitepicon-module-calendar" alt="{$APP.LBL_ENTER_DATE}"></span></button> <button type="button" id="{{$idname}}_trigger" class="btn calendarstart" onclick="return false;">
<span alt="{$APP.LBL_ENTER_DATE}">{sugar_getimage name="calendar"} </span>
</button>
{{if empty($displayParams.splitDateTime)}} {{if empty($displayParams.splitDateTime)}}
</td> </td>
<td nowrap class="dateTimeComboColumn"> <td nowrap class="dateTimeComboColumn dateTimeSection">
{{else}} {{else}}
<br> <br>
{{/if}} {{/if}}

View file

@ -82,7 +82,7 @@ class SugarFieldWysiwyg extends SugarFieldBase {
$config['plugins'] = 'print code preview fullpage searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern '; $config['plugins'] = 'print code preview fullpage searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists textcolor wordcount imagetools contextmenu colorpicker textpattern ';
$config['elements'] = "#{$form_name} "."#".$vardef['name']; $config['elements'] = "#{$form_name} "."#".$vardef['name'];
$config['selector'] = "#{$form_name} "."#".$vardef['name']; $config['selector'] = "#{$form_name} "."#".$vardef['name'];
$config['content_css'] = 'vendor/tinymce/tinymce/skins/lightgray/content.min.css'; $config['content_css'] = './../../vendor/tinymce/tinymce/skins/lightgray/content.min.css';
$config['toolbar1'] = 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat'; $config['toolbar1'] = 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat';
$config['theme'] = 'modern'; $config['theme'] = 'modern';

View file

@ -466,15 +466,16 @@ class SugarFolder
*/ */
public function generateArchiveFolderQuery() public function generateArchiveFolderQuery()
{ {
$query = "SELECT emails.id , emails.name, emails.date_sent_received, emails.status, emails.type, emails.flagged, ". return "SELECT emails.id , emails.name, emails.date_sent_received, emails.status, emails.type, emails.flagged, " .
"emails.reply_to_status, emails_text.from_addr, emails_text.to_addrs, 'Emails'". "emails.reply_to_status, emails_text.from_addr, emails_text.to_addrs, 'Emails' polymorphic_module " .
" polymorphic_module FROM emails JOIN emails_text on emails.id = emails_text.email_id ". "FROM emails " .
"WHERE emails.deleted=0 AND emails.type NOT IN ('out', 'draft')"." AND emails.status NOT IN ('sent', 'draft') AND emails.id IN (". "JOIN emails_text on emails.id = emails_text.email_id " .
"SELECT eear.email_id FROM emails_email_addr_rel eear " . "JOIN emails_email_addr_rel eear ON eear.email_id = emails.id " .
"JOIN email_addr_bean_rel eabr ON eabr.email_address_id=eear.email_address_id AND". "JOIN email_addr_bean_rel eabr ON eabr.email_address_id=eear.email_address_id " .
" eabr.bean_id = " . $this->db->quoted($this->currentUser->id) . " AND eabr.bean_module = 'Users' WHERE eear.deleted=0)"; "WHERE emails.deleted=0 AND emails.type NOT IN ('out', 'draft') AND emails.status NOT IN ('sent', 'draft') " .
"AND eabr.bean_id = " . $this->db->quoted($this->currentUser->id) . " AND eabr.bean_module = 'Users' " .
return $query; "AND eear.deleted=0 " .
"GROUP BY id";
} }
public function generateSugarsDynamicFolderQuery() public function generateSugarsDynamicFolderQuery()
@ -579,10 +580,46 @@ class SugarFolder
return $metadata; return $metadata;
} }
/**
* Get the count of items for dynamic folder
*
* @param bool $unread
* @return int
*/
public function getDynamicFolderCount($unread = false)
{
$selectQuery = $this->generateSugarsDynamicFolderQuery();
$pattern = '/SELECT(.*?)(\s){1}FROM(\s){1}/is'; // ignores the case
if ($this->folder_type === 'archived') {
$replacement = 'SELECT count(DISTINCT emails.id) c FROM ';
$modifiedSelectQuery = preg_replace($pattern, $replacement, $selectQuery, 1);
// remove GROUP BY statement
$pattern = '/GROUP BY id(\s)?/s';
$modifiedSelectQuery = preg_replace($pattern, '', $modifiedSelectQuery, 1);
} else {
$replacement = 'SELECT count(*) c FROM ';
$modifiedSelectQuery = preg_replace($pattern, $replacement, $selectQuery, 1);
}
$query = from_html($modifiedSelectQuery);
if ($unread) {
$query .= " AND emails.status = 'unread'";
}
$res = $this->db->query($query);
$result = $this->db->fetchByAssoc($res);
return $result['c'];
}
/** /**
* Get the count of items * Get the count of items
* *
* @param string $folderId * @param string $folderId
* @return int * @return int
*/ */
public function getCountItems($folderId) public function getCountItems($folderId)
@ -590,23 +627,19 @@ class SugarFolder
$this->retrieve($folderId); $this->retrieve($folderId);
if ($this->is_dynamic) { if ($this->is_dynamic) {
$pattern = '/SELECT(.*?)(\s){1}FROM(\s){1}/is'; // ignores the case return $this->getDynamicFolderCount();
$replacement = 'SELECT count(*) c FROM ';
$modifiedSelectQuery = preg_replace($pattern, $replacement, $this->generateSugarsDynamicFolderQuery(), 1);
$res = $this->db->query(from_html($modifiedSelectQuery));
} else {
// get items and iterate through them
$query = "SELECT count(*) c FROM folders_rel JOIN emails ON emails.id = folders_rel.polymorphic_id" .
" WHERE folder_id = " . $this->db->quoted($folderId) . " AND folders_rel.deleted = 0 AND emails.deleted = 0";
if ($this->is_group) {
$query .= " AND (emails.assigned_user_id is null or emails.assigned_user_id = '')";
}
$res = $this->db->query($query);
} }
// Get items and iterate through them
$query = "SELECT count(*) c FROM folders_rel JOIN emails ON emails.id = folders_rel.polymorphic_id" .
" WHERE folder_id = " . $this->db->quoted($folderId) . " AND folders_rel.deleted = 0 AND emails.deleted = 0";
if ($this->is_group) {
$query .= " AND (emails.assigned_user_id is null or emails.assigned_user_id = '')";
}
$res = $this->db->query($query);
$result = $this->db->fetchByAssoc($res); $result = $this->db->fetchByAssoc($res);
return $result['c']; return $result['c'];
@ -615,7 +648,7 @@ class SugarFolder
/** /**
* Get a count of the Unread Items * Get a count of the Unread Items
* *
* @param string $folderId * @param string $folderId
* @return integer * @return integer
*/ */
public function getCountUnread($folderId) public function getCountUnread($folderId)
@ -623,26 +656,23 @@ class SugarFolder
$this->retrieve($folderId); $this->retrieve($folderId);
if ($this->is_dynamic) { if ($this->is_dynamic) {
$pattern = '/SELECT(.*?)(\s){1}FROM(\s){1}/is'; // ignores the case return $this->getDynamicFolderCount(true);
$replacement = 'SELECT count(*) c FROM ';
$modified_select_query = preg_replace($pattern, $replacement, $this->generateSugarsDynamicFolderQuery(), 1);
$r = $this->db->query(from_html($modified_select_query) . " AND emails.status = 'unread'");
} else {
// get items and iterate through them
$query = "SELECT count(*) c FROM folders_rel fr JOIN emails on fr.folder_id = " . $this->db->quoted($folderId) .
" AND fr.deleted = 0 " .
"AND fr.polymorphic_id = emails.id AND emails.status = 'unread' AND emails.deleted = 0";
if ($this->is_group) {
$query .= " AND (emails.assigned_user_id is null or emails.assigned_user_id = '')";
}
$r = $this->db->query($query);
} }
$a = $this->db->fetchByAssoc($r); // Get items and iterate through them
$query = "SELECT count(*) c FROM folders_rel fr JOIN emails on fr.folder_id = " . $this->db->quoted($folderId) .
" AND fr.deleted = 0 " .
"AND fr.polymorphic_id = emails.id AND emails.status = 'unread' AND emails.deleted = 0";
return $a['c']; if ($this->is_group) {
$query .= " AND (emails.assigned_user_id is null or emails.assigned_user_id = '')";
}
$res = $this->db->query($query);
$result = $this->db->fetchByAssoc($res);
return $result['c'];
} }

View file

@ -68,6 +68,7 @@ class SugarLogger implements LoggerTemplate
protected $filesuffix = ""; protected $filesuffix = "";
protected $date_suffix = ""; protected $date_suffix = "";
protected $log_dir = '.'; protected $log_dir = '.';
protected $defaultPerms = 0664;
/** /**
@ -127,6 +128,7 @@ class SugarLogger implements LoggerTemplate
$this->logSize = $config->get('logger.file.maxSize', $this->logSize); $this->logSize = $config->get('logger.file.maxSize', $this->logSize);
$this->maxLogs = $config->get('logger.file.maxLogs', $this->maxLogs); $this->maxLogs = $config->get('logger.file.maxLogs', $this->maxLogs);
$this->filesuffix = $config->get('logger.file.suffix', $this->filesuffix); $this->filesuffix = $config->get('logger.file.suffix', $this->filesuffix);
$this->defaultPerms = $config->get('logger.file.perms', $this->defaultPerms);
$log_dir = $config->get('log_dir', $this->log_dir); $log_dir = $config->get('log_dir', $this->log_dir);
$this->log_dir = $log_dir . (empty($log_dir)?'':'/'); $this->log_dir = $log_dir . (empty($log_dir)?'':'/');
unset($config); unset($config);
@ -149,22 +151,25 @@ class SugarLogger implements LoggerTemplate
/** /**
* Checks to see if the SugarLogger file can be created and written to * Checks to see if the SugarLogger file can be created and written to
* @noinspection PhpUndefinedFieldInspection
* @return bool
*/ */
protected function _fileCanBeCreatedAndWrittenTo() protected function _fileCanBeCreatedAndWrittenTo()
{ {
$this->_attemptToCreateIfNecessary(); if (is_writable($this->full_log_file)) {
return file_exists($this->full_log_file) && is_writable($this->full_log_file); return true;
}
/**
* Creates the SugarLogger file if it doesn't exist
*/
protected function _attemptToCreateIfNecessary()
{
if (file_exists($this->full_log_file)) {
return;
} }
@touch($this->full_log_file);
if (!is_file($this->full_log_file)) {
@touch($this->full_log_file);
if ($this->defaultPerms !== false) {
@chmod($this->full_log_file, $this->defaultPerms);
}
return is_writable($this->full_log_file);
}
return false;
} }
/** /**

View file

@ -60,7 +60,7 @@ abstract class PersonFormBase extends FormBase
{ {
public $moduleName; public $moduleName;
public $objectName; public $objectName;
/** /**
* buildTableForm * buildTableForm
* *
@ -76,30 +76,28 @@ abstract class PersonFormBase extends FormBase
global $app_strings; global $app_strings;
$newLinkLabel = 'LNK_NEW_' . strtoupper($this->objectName); $newLinkLabel = 'LNK_NEW_' . strtoupper($this->objectName);
$cols = count($rows[0]) * 2 + 1; $cols = count($rows[0]) * 2 + 1;
if ($action != 'ShowDuplicates') { if ($action != 'ShowDuplicates') {
$duplicateLabel = string_format($app_strings['MSG_DUPLICATE'], array(strtolower($this->objectName), $this->moduleName)); $duplicateLabel = string_format($app_strings['MSG_DUPLICATE'], array(strtolower($this->objectName), $this->moduleName));
$form = '<table width="100%"><tr><td>'.$duplicateLabel.'</td></tr><tr><td height="20"></td></tr></table>'; $form = '<table width="100%"><tr><td>' . $duplicateLabel . '</td></tr><tr><td height="20"></td></tr></table>';
$form .= "<form action='index.php' method='post' name='dup{$this->moduleName}'><input type='hidden' name='selected{$this->objectName}' value=''>"; $form .= "<form action='index.php' method='post' name='dup{$this->moduleName}'><input type='hidden' name='selected{$this->objectName}' value=''>";
$form .= getPostToForm('/emailAddress(PrimaryFlag|OptOutFlag|InvalidFlag)?[0-9]*?$/', true); $form .= getPostToForm('/emailAddress(PrimaryFlag|OptOutFlag|InvalidFlag)?[0-9]*?$/', true);
} else { } else {
$duplicateLabel = string_format($app_strings['MSG_SHOW_DUPLICATES'], array(strtolower($this->objectName), $this->moduleName)); $duplicateLabel = string_format($app_strings['MSG_SHOW_DUPLICATES'], array(strtolower($this->objectName), $this->moduleName));
$form = '<table width="100%"><tr><td>'.$duplicateLabel.'</td></tr><tr><td height="20"></td></tr></table>'; $form = '<table width="100%"><tr><td>' . $duplicateLabel . '</td></tr><tr><td height="20"></td></tr></table>';
} }
$form .= "<table width='100%' cellpadding='0' cellspacing='0' class='list view' border='0'><tr class='pagination'><td colspan='$cols'><table width='100%' cellspacing='0' cellpadding='0' border='0'><tr><td>"; $form .= "<table width='100%' cellpadding='0' cellspacing='0' class='list view' border='0'><tr class='pagination'><td colspan='$cols'><table width='100%' cellspacing='0' cellpadding='0' border='0'><tr><td>";
if ($action == 'ShowDuplicates') { if ($action == 'ShowDuplicates') {
$form .= "<input title='${app_strings['LBL_SAVE_BUTTON_TITLE']}' accessKey='${app_strings['LBL_SAVE_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='Save';\" type='submit' name='button' value=' ${app_strings['LBL_SAVE_BUTTON_LABEL']} '>\n"; $form .= "<input title='${app_strings['LBL_SAVE_BUTTON_TITLE']}' accessKey='${app_strings['LBL_SAVE_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='Save';\" type='submit' name='button' value=' ${app_strings['LBL_SAVE_BUTTON_LABEL']} '>\n";
if (!empty($_REQUEST['return_module']) && !empty($_REQUEST['return_action']) && !empty($_REQUEST['return_id'])) { if (!empty($_REQUEST['return_module']) && !empty($_REQUEST['return_action']) && !empty($_REQUEST['return_id'])) {
$form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='".$_REQUEST['return_module']."';this.form.action.value='".$_REQUEST['return_action']."';this.form.record.value='".$_REQUEST['return_id']."'\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>"; $form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='" . $_REQUEST['return_module'] . "';this.form.action.value='" . $_REQUEST['return_action'] . "';this.form.record.value='" . $_REQUEST['return_id'] . "'\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>";
} } //Bug 1074, if the action is detailview and the id is empty, then do not show detailview
//Bug 1074, if the action is detailview and the id is empty, then do not show detailview
else { else {
if (!empty($_POST['return_module']) && !empty($_POST['return_action']) &&(($_POST['return_action'] == "DetailView" && !empty($_REQUEST['return_id'])) || $_POST['return_action'] != "DetailView")) { if (!empty($_POST['return_module']) && !empty($_POST['return_action']) && (($_POST['return_action'] == "DetailView" && !empty($_REQUEST['return_id'])) || $_POST['return_action'] != "DetailView")) {
$form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='".$_POST['return_module']."';this.form.action.value='". $_POST['return_action']."';\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>"; $form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='" . $_POST['return_module'] . "';this.form.action.value='" . $_POST['return_action'] . "';\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>";
} else { } else {
$form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='ListView';\" type='submit' type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>"; $form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='ListView';\" type='submit' type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>";
} }
@ -126,9 +124,9 @@ abstract class PersonFormBase extends FormBase
$form .= getPostToForm(); $form .= getPostToForm();
if (isset($rows[0])) { if (isset($rows[0])) {
foreach ($rows[0] as $key=>$value) { foreach ($rows[0] as $key => $value) {
if ($key != 'id') { if ($key != 'id') {
$form .= "<td scope='col' >". $mod_strings[$mod_strings['db_'.$key]]. "</td>"; $form .= "<td scope='col' >" . $mod_strings[$mod_strings['db_' . $key]] . "</td>";
} }
} }
$form .= "</tr>"; $form .= "</tr>";
@ -136,23 +134,34 @@ abstract class PersonFormBase extends FormBase
$rowColor = 'oddListRowS1'; $rowColor = 'oddListRowS1';
require_once 'include/portability/RouteConverter.php';
$routeConverter = new RouteConverter();
foreach ($rows as $row) { foreach ($rows as $row) {
$form .= "<tr class='$rowColor'>"; $form .= "<tr class='$rowColor'>";
if ($action != 'ShowDuplicates') { if ($action != 'ShowDuplicates') {
$form .= "<td width='1%' nowrap='nowrap'><a href='#' onClick=\"document.forms['dup{$this->moduleName}'].selected{$this->objectName}.value='${row['id']}';document.forms['dup{$this->moduleName}'].submit() \">[{$app_strings['LBL_SELECT_BUTTON_LABEL']}]</a>&nbsp;&nbsp;</td>\n"; $form .= "<td width='1%' nowrap='nowrap'><a href='#' onClick=\"document.forms['dup{$this->moduleName}'].selected{$this->objectName}.value='${row['id']}';document.forms['dup{$this->moduleName}'].submit() \">[{$app_strings['LBL_SELECT_BUTTON_LABEL']}]</a>&nbsp;&nbsp;</td>\n";
} }
$wasSet = false; $wasSet = false;
foreach ($row as $key=>$value) { foreach ($row as $key => $value) {
if ($key != 'id') { if ($key != 'id') {
if (isset($_POST['popup']) && $_POST['popup']==true) { if (isset($_POST['popup']) && $_POST['popup'] == true) {
$form .= "<td scope='row'><a href='#' onclick=\"window.opener.location='index.php?module={$this->moduleName}&action=DetailView&record=${row['id']}'\">$value</a></td>\n"; $form .= "<td scope='row'><a href='#' onclick=\"window.opener.location='index.php?module={$this->moduleName}&action=DetailView&record=${row['id']}'\">$value</a></td>\n";
} else { } else {
$link = 'index.php?module=' . $this->moduleName . '&action=DetailView&record=' . $row['id'];
if ($routeConverter->isLegacyRoute($link)) {
$link = $routeConverter->generateUiLink($link);
}
if (!$wasSet) { if (!$wasSet) {
$form .= "<td scope='row'><a target='_blank' href='index.php?module={$this->moduleName}&action=DetailView&record=${row['id']}'>$value</a></td>\n";
$form .= "<td scope='row'><a target='_blank' href='{$link}'>$value</a></td>\n";
$wasSet = true; $wasSet = true;
} else { } else {
$form .= "<td><a target='_blank' href='index.php?module={$this->moduleName}&action=DetailView&record=${row['id']}'>$value</a></td>\n"; $form .= "<td><a target='_blank' href='{$link}'>$value</a></td>\n";
} }
} }
} }
@ -169,10 +178,10 @@ abstract class PersonFormBase extends FormBase
if ($action == 'ShowDuplicates') { if ($action == 'ShowDuplicates') {
$form .= "<input title='${app_strings['LBL_SAVE_BUTTON_TITLE']}' accessKey='${app_strings['LBL_SAVE_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='Save';\" type='submit' name='button' value=' ${app_strings['LBL_SAVE_BUTTON_LABEL']} '>\n"; $form .= "<input title='${app_strings['LBL_SAVE_BUTTON_TITLE']}' accessKey='${app_strings['LBL_SAVE_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='Save';\" type='submit' name='button' value=' ${app_strings['LBL_SAVE_BUTTON_LABEL']} '>\n";
if (!empty($_REQUEST['return_module']) && !empty($_REQUEST['return_action']) && !empty($_REQUEST['return_id'])) { if (!empty($_REQUEST['return_module']) && !empty($_REQUEST['return_action']) && !empty($_REQUEST['return_id'])) {
$form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='".$_REQUEST['return_module']."';this.form.action.value='".$_REQUEST['return_action']."';this.form.record.value='".$_REQUEST['return_id']."';\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>"; $form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='" . $_REQUEST['return_module'] . "';this.form.action.value='" . $_REQUEST['return_action'] . "';this.form.record.value='" . $_REQUEST['return_id'] . "';\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>";
} else { } else {
if (!empty($_POST['return_module']) && !empty($_POST['return_action'])) { if (!empty($_POST['return_module']) && !empty($_POST['return_action'])) {
$form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='".$_POST['return_module']."';this.form.action.value='". $_POST['return_action']."';\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>"; $form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.module.value='" . $_POST['return_module'] . "';this.form.action.value='" . $_POST['return_action'] . "';\" type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>";
} else { } else {
$form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='ListView';\" type='submit' type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>"; $form .= "<input title='${app_strings['LBL_CANCEL_BUTTON_TITLE']}' accessKey='${app_strings['LBL_CANCEL_BUTTON_KEY']}' class='button' onclick=\"this.form.action.value='ListView';\" type='submit' type='submit' name='button' value=' ${app_strings['LBL_CANCEL_BUTTON_LABEL']} '>";
} }
@ -194,7 +203,7 @@ abstract class PersonFormBase extends FormBase
* @param $prefix String value of any prefix to the form input names * @param $prefix String value of any prefix to the form input names
* @return $rows Array of matching Leads entries found; null if none found * @return $rows Array of matching Leads entries found; null if none found
*/ */
public function checkForDuplicates($prefix='') public function checkForDuplicates($prefix = '')
{ {
require_once('include/formbase.php'); require_once('include/formbase.php');
require_once('include/MVC/SugarModule.php'); require_once('include/MVC/SugarModule.php');
@ -214,7 +223,7 @@ abstract class PersonFormBase extends FormBase
//Loop through the results and store //Loop through the results and store
while (($row = $db->fetchByAssoc($result)) != null) { while (($row = $db->fetchByAssoc($result)) != null) {
if (!isset($rows[$row['id']])) { if (!isset($rows[$row['id']])) {
$rows[]=$row; $rows[] = $row;
} }
} }
@ -229,9 +238,9 @@ abstract class PersonFormBase extends FormBase
if (!empty($emailStr)) { if (!empty($emailStr)) {
$emailStr = substr($emailStr, 1); $emailStr = substr($emailStr, 1);
$query = 'SELECT DISTINCT er.bean_id AS id FROM email_addr_bean_rel er, ' . $query = 'SELECT DISTINCT er.bean_id AS id FROM email_addr_bean_rel er, ' .
'email_addresses ea WHERE ea.id = er.email_address_id ' . 'email_addresses ea WHERE ea.id = er.email_address_id ' .
'AND ea.deleted = 0 AND er.deleted = 0 AND er.bean_module = \'' . $this->moduleName . '\' ' . 'AND ea.deleted = 0 AND er.deleted = 0 AND er.bean_module = \'' . $this->moduleName . '\' ' .
'AND email_address_caps IN (' . $emailStr . ')'; 'AND email_address_caps IN (' . $emailStr . ')';
$result = $db->query($query); $result = $db->query($query);
while (($row = $db->fetchByAssoc($result)) != null) { while (($row = $db->fetchByAssoc($result)) != null) {
@ -240,7 +249,7 @@ abstract class PersonFormBase extends FormBase
$result2 = $db->query($query2); $result2 = $db->query($query2);
$r = $db->fetchByAssoc($result2); $r = $db->fetchByAssoc($result2);
if (isset($r['id'])) { if (isset($r['id'])) {
$rows[]=$r; $rows[] = $r;
} }
} //if } //if
} }
@ -256,12 +265,12 @@ abstract class PersonFormBase extends FormBase
* This is the function that subclasses should extend and return a SQL query used for the initial duplicate * This is the function that subclasses should extend and return a SQL query used for the initial duplicate
* check sequence. * check sequence.
* *
* @see checkForDuplicates (method), ContactFormBase.php, LeadFormBase.php, ProspectFormBase.php
* @param $focus sugarbean * @param $focus sugarbean
* @param $prefix String value of prefix that may be present in $_POST variables * @param $prefix String value of prefix that may be present in $_POST variables
* @return SQL String of the query that should be used for the initial duplicate lookup check * @return SQL String of the query that should be used for the initial duplicate lookup check
* @see checkForDuplicates (method), ContactFormBase.php, LeadFormBase.php, ProspectFormBase.php
*/ */
public function getDuplicateQuery($focus, $prefix='') public function getDuplicateQuery($focus, $prefix = '')
{ {
return null; return null;
} }

View file

@ -75,7 +75,6 @@ class Basic extends SugarBean
public function getEmailAddressFromEmailField($emailField) public function getEmailAddressFromEmailField($emailField)
{ {
$this->validateSugarEmailAddressField($emailField); $this->validateSugarEmailAddressField($emailField);
$configurator = new Configurator();
/** @var EmailAddress $emailAddressBean */ /** @var EmailAddress $emailAddressBean */
$emailAddressBean = BeanFactory::getBean('EmailAddresses'); $emailAddressBean = BeanFactory::getBean('EmailAddresses');
@ -84,11 +83,6 @@ class Basic extends SugarBean
$emailAddressId = $this->getEmailAddressId($emailField); $emailAddressId = $this->getEmailAddressId($emailField);
$emailAddressBean->retrieve($emailAddressId); $emailAddressBean->retrieve($emailAddressId);
if (!empty($emailAddressBean->id) && $configurator->getConfirmOptInEnumValue() === SugarEmailAddress::COI_STAT_DISABLED) {
$log = LoggerManager::getLogger();
$log->warn('Confirm Opt In is not enabled.');
$emailAddressBean->setConfirmedOptInState(SugarEmailAddress::COI_STAT_CONFIRMED_OPT_IN);
}
return $emailAddressBean; return $emailAddressBean;
} }

View file

@ -69,7 +69,7 @@ class SugarPHPMailer extends PHPMailer
* @var string * @var string
*/ */
public $Body_html; public $Body_html;
private static $FromNameOrigin = null; private static $FromNameOrigin = null;
/** /**
@ -97,7 +97,7 @@ class SugarPHPMailer extends PHPMailer
$this->oe = new OutboundEmail(); $this->oe = new OutboundEmail();
$this->oe->getUserMailerSettings($current_user); $this->oe->getUserMailerSettings($current_user);
$this->setLanguage('en', 'vendor/phpmailer/phpmailer/language/'); $this->setLanguage('en', './../../vendor/phpmailer/phpmailer/language/');
$this->Mailer = 'smtp'; $this->Mailer = 'smtp';
// cn: i18n // cn: i18n
$this->CharSet = $locale->getPrecedentPreference('default_email_charset'); $this->CharSet = $locale->getPrecedentPreference('default_email_charset');
@ -221,9 +221,9 @@ class SugarPHPMailer extends PHPMailer
eoq; eoq;
$this->Body = $head . $this->Body . '</body></html>'; $this->Body = $head . $this->Body . '</body></html>';
} }
$fromName = $this->FromName; $fromName = $this->FromName;
// checking if username already set for phpmailer and // checking if username already set for phpmailer and
// using that as username instead fromname // using that as username instead fromname
if ($this->FromName == self::$FromNameOrigin && !empty($this->Username)) { if ($this->FromName == self::$FromNameOrigin && !empty($this->Username)) {
@ -441,10 +441,10 @@ eoq;
//$this->Sender = 'me@here.com'; //$this->Sender = 'me@here.com';
//$this->Password = 'wrong'; //$this->Password = 'wrong';
//$GLOBALS['log']->debug("PHPMailer Send Function: { FromName: $this->FromName From: $this->From Host: $this->Host UserName: $this->Username }"); //$GLOBALS['log']->debug("PHPMailer Send Function: { FromName: $this->FromName From: $this->From Host: $this->Host UserName: $this->Username }");
$ret = null; $ret = null;
$this->fullSmtpLog=''; $this->fullSmtpLog='';
$phpMailerExceptionMsg=''; $phpMailerExceptionMsg='';

View file

@ -63,7 +63,7 @@ class SuiteMozaik
public function __construct() public function __construct()
{ {
$this->vendorPath = 'vendor/'; $this->vendorPath = './../../vendor/';
if ($this->autoInsertThumbnails) { if ($this->autoInsertThumbnails) {
if (count($this->getThumbs())==0 || self::$devMode) { if (count($this->getThumbs())==0 || self::$devMode) {
$ord = 0; $ord = 0;

View file

@ -60,7 +60,7 @@ if (empty($GLOBALS['installing']) && !file_exists('config.php')) {
} }
$BASE_DIR = realpath(dirname(__DIR__)); $BASE_DIR = realpath(dirname(__DIR__));
$autoloader = $BASE_DIR.'/vendor/autoload.php'; $autoloader = $BASE_DIR . '/../../vendor/autoload.php';
if (file_exists($autoloader)) { if (file_exists($autoloader)) {
require_once $autoloader; require_once $autoloader;
} else { } else {

View file

@ -5,7 +5,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
* *
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 SalesAgility Ltd. * Copyright (C) 2011 - 2021 SalesAgility Ltd.
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the * the terms of the GNU Affero General Public License version 3 as published by the
@ -38,6 +38,8 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/ */
use SuiteCRM\CleanCSV;
if (!defined('sugarEntry') || !sugarEntry) { if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point'); die('Not A Valid Entry Point');
} }
@ -314,7 +316,8 @@ function export($type, $records = null, $members = false, $sample=false)
} }
// Keep as $key => $value for post-processing // Keep as $key => $value for post-processing
$new_arr[$key] = preg_replace("/\"/", "\"\"", cleanCSV($value)); $cleanCSV = new CleanCSV();
$new_arr[$key] = preg_replace("/\"/", "\"\"", $cleanCSV->escapeField($value));
} }
// Use Bean ID as key for records // Use Bean ID as key for records

View file

@ -50,7 +50,7 @@
{else} {else}
{if $other_text && $is_min_max == false} {if $other_text && $is_min_max == false}
<td width="20"><img height="1" width="20" src="{$blankImageURL}" alt=""></td> <td width="20"><img height="1" width="20" src="{$blankImageURL}" alt=""></td>
<td valign="middle" nowrap width="100%">{$other_text}</td> <td valign="middle" nowrap width="100%" class="action-button">{$other_text}</td>
{else} {else}
<td width="100%"><img height="1" width="1" src="{$blankImageURL}" alt=""></td> <td width="100%"><img height="1" width="1" src="{$blankImageURL}" alt=""></td>
{/if} {/if}

View file

@ -627,6 +627,7 @@ $app_list_strings = array(
'Radio' => 'Radio', 'Radio' => 'Radio',
'Television' => 'Television', 'Television' => 'Television',
'NewsLetter' => 'Newsletter', 'NewsLetter' => 'Newsletter',
'Survey' => 'Survey',
), ),
'newsletter_frequency_dom' => array( 'newsletter_frequency_dom' => array(
@ -1423,6 +1424,8 @@ $app_strings = array(
'ERR_INVALID_FILE_REFERENCE' => 'Invalid File Reference', 'ERR_INVALID_FILE_REFERENCE' => 'Invalid File Reference',
'ERR_NO_HEADER_ID' => 'This feature is unavailable in this theme.', 'ERR_NO_HEADER_ID' => 'This feature is unavailable in this theme.',
'ERR_NOT_ADMIN' => 'Unauthorized access to administration.', 'ERR_NOT_ADMIN' => 'Unauthorized access to administration.',
'ERR_UNAUTHORIZED_PAGE_ACCESS' => 'You are not authorized to view this page. Please contact your system administrator.',
'ERR_UNAUTHORIZED_PAGE_ACCESS_TO_HOME_PAGE' => 'You are not authorized to view this page. Redirecting to Home Page...',
'ERR_MISSING_REQUIRED_FIELDS' => 'Missing required field:', 'ERR_MISSING_REQUIRED_FIELDS' => 'Missing required field:',
'ERR_INVALID_REQUIRED_FIELDS' => 'Invalid required field:', 'ERR_INVALID_REQUIRED_FIELDS' => 'Invalid required field:',
'ERR_INVALID_VALUE' => 'Invalid Value:', 'ERR_INVALID_VALUE' => 'Invalid Value:',
@ -1592,7 +1595,6 @@ $app_strings = array(
'LBL_NEW_BUTTON_KEY' => 'N', 'LBL_NEW_BUTTON_KEY' => 'N',
'LBL_NEW_BUTTON_LABEL' => 'Create', 'LBL_NEW_BUTTON_LABEL' => 'Create',
'LBL_NEW_BUTTON_TITLE' => 'Create', 'LBL_NEW_BUTTON_TITLE' => 'Create',
'LBL_NEW' => 'New',
'LBL_EDIT' => 'Edit', 'LBL_EDIT' => 'Edit',
'LBL_NEXT_BUTTON_LABEL' => 'Next', 'LBL_NEXT_BUTTON_LABEL' => 'Next',
'LBL_NONE' => '--None--', 'LBL_NONE' => '--None--',
@ -1782,6 +1784,7 @@ $app_strings = array(
'LNK_REMOVE' => 'Remove', 'LNK_REMOVE' => 'Remove',
'LNK_RESUME' => 'Resume', 'LNK_RESUME' => 'Resume',
'LNK_VIEW_CHANGE_LOG' => 'View Change Log', 'LNK_VIEW_CHANGE_LOG' => 'View Change Log',
'LBL_CHANGE_LOG' => 'Change Log',
'NTC_CLICK_BACK' => 'Please click the browser back button and fix the error.', 'NTC_CLICK_BACK' => 'Please click the browser back button and fix the error.',
'NTC_DATE_FORMAT' => '(yyyy-mm-dd)', 'NTC_DATE_FORMAT' => '(yyyy-mm-dd)',
@ -2100,12 +2103,20 @@ $app_strings = array(
'LBL_BULK_ACTION_BUTTON_LABEL_MOBILE' => 'ACTION', 'LBL_BULK_ACTION_BUTTON_LABEL_MOBILE' => 'ACTION',
'LBL_TOO_FEW_SELECTED' => 'Invalid number of records selected. You must select a minimum of {min} records.', 'LBL_TOO_FEW_SELECTED' => 'Invalid number of records selected. You must select a minimum of {min} records.',
'LBL_TOO_MANY_SELECTED' => 'Invalid number of records selected. You must select a maximum of {max} records.', 'LBL_TOO_MANY_SELECTED' => 'Invalid number of records selected. You must select a maximum of {max} records.',
'LBL_SELECT_ALL_NOT_ALLOWED' => 'Selecting all records is not available for this action. Please select individual records.',
'LBL_MISSING_HANDLER_DATA' => 'Unexpected error. Missing bulk action handler data from response', 'LBL_MISSING_HANDLER_DATA' => 'Unexpected error. Missing bulk action handler data from response',
'LBL_MISSING_HANDLER' => 'Unexpected error. No handler defined for the select bulk action', 'LBL_MISSING_HANDLER' => 'Unexpected error. No handler defined for the select bulk action',
'LBL_MISSING_HANDLER_DATA_ROUTE' => 'Unexpected error. Missing bulk action route', 'LBL_MISSING_HANDLER_DATA_ROUTE' => 'Unexpected error. Missing bulk action route',
'LBL_ACTION_ERROR' => 'Unexpected error when calling action', 'LBL_ACTION_ERROR' => 'Unexpected error when calling action',
'LBL_BULK_ACTION_ERROR' => 'Unexpected error when calling Bulk Action', 'LBL_BULK_ACTION_ERROR' => 'Unexpected error when calling Bulk Action',
'LBL_BULK_ACTION_DELETE_SUCCESS' => 'Record(s) deleted successfully', 'LBL_BULK_ACTION_DELETE_SUCCESS' => 'Record(s) deleted successfully',
'LBL_BULK_ACTION_MASS_UPDATE_CONFIRMATION' => 'Are you sure you want to update the selected record(s)?',
'LBL_BULK_ACTION_MASS_UPDATE_SUCCESS' => 'All Record(s) updated successfully',
'LBL_BULK_ACTION_MASS_UPDATE_PARTIAL_SUCCESS' => 'Partial success. Some records were not updated. please check log',
'LBL_BULK_ACTION_MASS_UPDATE_NO_FIELDS' => 'No fields to update',
'LBL_BULK_ACTION_MASS_UPDATE_NO_RECORDS' => 'No records to update',
'LBL_BULK_ACTION_MASS_UPDATE_NO_ACLS' => 'Insufficient Privilege, Save action not allowed',
'LBL_UNEXPECTED_ERROR' => 'Unexpected error. No able to perform action.',
'LBL_RECORD_DELETE_SUCCESS' => 'Record deleted successfully', 'LBL_RECORD_DELETE_SUCCESS' => 'Record deleted successfully',
'LBL_ERROR_SAVING' => 'Error occurred while saving record', 'LBL_ERROR_SAVING' => 'Error occurred while saving record',
'LBL_SAVE_BUTTON_KEY' => 'a', 'LBL_SAVE_BUTTON_KEY' => 'a',
@ -2197,6 +2208,14 @@ $app_strings = array(
'LBL_CONTACT_HAS_NO_PRIMARY_EMAIL' => 'Confirm Opt In Email sending is not possible because the Contact has not Primary Email Address', 'LBL_CONTACT_HAS_NO_PRIMARY_EMAIL' => 'Confirm Opt In Email sending is not possible because the Contact has not Primary Email Address',
'LBL_CONFIRM_EMAIL_SENDING_FAILED' => 'Confirm Opt In Email sending failed', 'LBL_CONFIRM_EMAIL_SENDING_FAILED' => 'Confirm Opt In Email sending failed',
'LBL_CONFIRM_EMAIL_SENT' => 'Confirm Opt In Email sent successfully', 'LBL_CONFIRM_EMAIL_SENT' => 'Confirm Opt In Email sent successfully',
//List View Column Selector Modal
'LBL_COLUMN_SELECTOR_DISPLAYED_COLS' => 'DISPLAYED',
'LBL_COLUMN_SELECTOR_HIDDEN_COLS' => 'HIDDEN',
'LBL_COLUMN_SELECTOR_CLOSE_BUTTON' => 'Close',
'LBL_COLUMN_SELECTOR_SAVE_BUTTON' => 'Save Changes',
'LBL_COLUMN_SELECTOR_MODAL_TITLE' => 'Choose Columns'
); );
$app_list_strings['moduleList']['Library'] = 'Library'; $app_list_strings['moduleList']['Library'] = 'Library';
@ -2951,15 +2970,10 @@ $app_strings['LBL_LISTVIEW_OPTION_CURRENT'] = 'Select This Page';
$app_strings['LBL_LISTVIEW_OPTION_ENTIRE'] = 'Select All'; $app_strings['LBL_LISTVIEW_OPTION_ENTIRE'] = 'Select All';
$app_strings['LBL_LISTVIEW_NONE'] = 'Deselect All'; $app_strings['LBL_LISTVIEW_NONE'] = 'Deselect All';
//aod
$app_list_strings['moduleList']['AOD_IndexEvent'] = 'Index Event';
$app_list_strings['moduleList']['AOD_Index'] = 'Index';
$app_list_strings['moduleList']['AOP_Case_Events'] = 'Case Events'; $app_list_strings['moduleList']['AOP_Case_Events'] = 'Case Events';
$app_list_strings['moduleList']['AOP_Case_Updates'] = 'Case Updates'; $app_list_strings['moduleList']['AOP_Case_Updates'] = 'Case Updates';
$app_strings['LBL_AOP_EMAIL_REPLY_DELIMITER'] = '========== Please reply above this line =========='; $app_strings['LBL_AOP_EMAIL_REPLY_DELIMITER'] = '========== Please reply above this line ==========';
//aop //aop
$app_list_strings['case_state_default_key'] = 'Open'; $app_list_strings['case_state_default_key'] = 'Open';
$app_list_strings['case_state_dom'] = $app_list_strings['case_state_dom'] =
@ -3729,6 +3743,10 @@ $app_strings['LBL_GOOGLE_SYNC_ERR'] = 'SuiteCRM Google Sync - ERROR';
$app_strings['LBL_THERE_WAS_AN_ERR'] = 'There was an error: '; $app_strings['LBL_THERE_WAS_AN_ERR'] = 'There was an error: ';
$app_strings['LBL_CLICK_HERE'] = 'Click here'; $app_strings['LBL_CLICK_HERE'] = 'Click here';
$app_strings['LBL_TO_CONTINUE'] = ' to continue.'; $app_strings['LBL_TO_CONTINUE'] = ' to continue.';
$app_strings['LBL_OPT_OUT'] = 'Opt Out';
$app_strings['LBL_INVALID_EMAIL'] = 'Invalid';
$app_strings['LBL_PRIMARY'] = 'Primary';
$app_strings['LBL_EMAIL_ADDRESS'] = 'Email Address';
$app_strings['IMAP_HANDLER_ERROR'] = 'ERROR: {error}; key was: "{key}".'; $app_strings['IMAP_HANDLER_ERROR'] = 'ERROR: {error}; key was: "{key}".';
$app_strings['IMAP_HANDLER_SUCCESS'] = 'OK: test settings changed to "{key}"'; $app_strings['IMAP_HANDLER_SUCCESS'] = 'OK: test settings changed to "{key}"';
@ -3788,6 +3806,9 @@ $app_strings['LBL_VALIDATION_ERROR_EMAIL_FORMAT'] = "Invalid email format. Expec
$app_strings['LBL_VALIDATION_ERROR_PHONE_FORMAT'] = "Invalid phone format."; $app_strings['LBL_VALIDATION_ERROR_PHONE_FORMAT'] = "Invalid phone format.";
$app_strings['LBL_VALIDATION_ERROR_MIN'] = "Invalid value. Value must greater or equal to '{{context.min}}'"; $app_strings['LBL_VALIDATION_ERROR_MIN'] = "Invalid value. Value must greater or equal to '{{context.min}}'";
$app_strings['LBL_VALIDATION_ERROR_MAX'] = "Invalid value. Value must smaller or equal to '{{context.max}}'"; $app_strings['LBL_VALIDATION_ERROR_MAX'] = "Invalid value. Value must smaller or equal to '{{context.max}}'";
$app_strings['LBL_MULTIPLE_PRIMARY_EMAIL_VALIDATION_ERROR'] = "Only one email address can be marked as primary";
$app_strings['LBL_DUPLICATE_EMAIL_VALIDATION_ERROR'] = "Duplicate email addresses are not allowed";
$app_strings['LBL_NO_PRIMARY_EMAIL_VALIDATION_ERROR'] = "One email address should be marked as primary";
$app_strings['LBL_VALIDATION_ERRORS'] = 'There are validation errors, unable to perform action.'; $app_strings['LBL_VALIDATION_ERRORS'] = 'There are validation errors, unable to perform action.';
$app_strings['LBL_TYPE_TO_SEARCH'] = 'Type to search...'; $app_strings['LBL_TYPE_TO_SEARCH'] = 'Type to search...';
$app_strings['LBL_SEARCHING'] = 'searching...'; $app_strings['LBL_SEARCHING'] = 'searching...';
@ -3824,7 +3845,50 @@ $app_strings['AOS_Quotes'] = 'Quotes';
$app_strings['AOS_Invoices'] = 'Invoices'; $app_strings['AOS_Invoices'] = 'Invoices';
$app_strings['LBL_PHOTO'] = 'Photo'; $app_strings['LBL_PHOTO'] = 'Photo';
$app_strings['LBL_CASE_UPDATES'] = 'Case Updates'; $app_strings['LBL_CASE_UPDATES'] = 'Case Updates';
$app_strings['LBL_CASE_UPDATE_SUBMITTED'] = 'Case Update Submitted';
$app_strings['LBL_SUMMARY_DEFAULT'] = "{{fields.name.value}}"; $app_strings['LBL_SUMMARY_DEFAULT'] = "{{fields.name.value}}";
$app_strings['LBL_CREATE'] = 'Create';
$app_strings['LBL_SAVED_FILTER_SAVED'] = 'Filter successfully saved';
$app_strings['LBL_FILTER_ID_NOT_DEFINED'] = 'Filter id not defined';
$app_strings['LBL_GENERIC_CONFIRMATION'] = 'Do you want to proceed with action?';
$app_strings['LBL_SHOW_MORE'] = 'Show more';
$app_strings['LBL_SHOW_LESS'] = 'Show less';
$app_strings['LBL_LOAD_MORE'] = 'Load more';
$app_strings['LBL_EMPTY'] = '-- Empty -- ';
$app_strings['LBL_OPERATOR'] = 'Operator';
$app_strings['LBL_START'] = 'Start';
$app_strings['LBL_END'] = 'End';
$app_strings['LBL_LINE_ITEMS_FIELD_CONFIG'] = 'Bad config';
$app_strings['LBL_ACTION_SUCCESS'] = 'Action successful';
$app_strings['LBL_YES'] = 'Yes';
$app_strings['LBL_NO'] = 'No';
$app_list_strings['sort_order'] = [];
$app_list_strings['sort_order']['asc'] = 'Ascending';
$app_list_strings['sort_order']['desc'] = 'Descending';
// Labels used by subpanel unlink relationship process
$app_strings['LBL_LINK'] = 'Link';
$app_strings['LBL_UNLINK_RECORD'] = 'Unlink Record';
$app_strings['LBL_UNLINK_RELATIONSHIP_CONFIRM'] = 'Are you sure you want to unlink this record? Only the relationship will be unlinked. The record will not be deleted.';
$app_strings['LBL_UNLINK_RELATIONSHIP_SUCCESS'] = 'Record unlinked successfully.';
$app_strings['LBL_UNLINK_RELATIONSHIP_FAILED'] = 'There was an error unlinking this record.';
$app_strings['LBL_LINK_RELATIONSHIP_SUCCESS'] = 'Relationship linked successfully.';
$app_strings['LBL_LINK_RELATIONSHIP_FAILED'] = 'There was an error linking this Relationship.';
$app_strings['LBL_MODULE_NOT_FOUND'] = 'Module not found.';
$app_strings['LBL_RECORD_NOT_FOUND'] = 'Unable to load record';
$app_strings['LBL_RELATIONSHIP_LOAD_ERROR'] = 'Unable to load relationship';
$app_strings['LBL_NOT_LINKED'] = 'Unable to unlink. Records are not linked';
$app_strings['LBL_ACCESS_DENIED'] = 'Access Denied';
$app_strings['LBL_ADD_RECORDS_TO_TARGET_LIST_SUCCESS'] = 'Records added to target list successfully.';
$app_strings['LBL_ADD_RECORDS_TO_TARGET_LIST_FAILED'] = 'There was an error adding records to target list.';
$app_strings['LBL_ADD_CONTACTS_TO_TARGET_LIST_SUCCESS'] = 'Contacts added to target list successfully.';
$app_strings['LBL_ADD_CONTACTS_TO_TARGET_LIST_FAILED'] = 'There was an error adding contacts to target list.';
$app_strings['LBL_CHANGED_TO_TEXT'] = 'changed to';
$app_strings['LBL_RECORD_CHANGED'] = 'Record Updated';
$app_strings['LBL_CREATE'] = "Create"; $app_strings['LBL_CREATE'] = "Create";
$app_strings['LBL_USE_ADVANCED_SEARCH'] = 'Use Advanced Search'; $app_strings['LBL_USE_ADVANCED_SEARCH'] = 'Use Advanced Search';
$app_strings['LBL_USE_BASIC_SEARCH'] = 'Use Basic Search'; $app_strings['LBL_USE_BASIC_SEARCH'] = 'Use Basic Search';

View file

@ -395,17 +395,6 @@ $beanList['FP_Event_Locations'] = 'FP_Event_Locations';
$beanFiles['FP_Event_Locations'] = 'modules/FP_Event_Locations/FP_Event_Locations.php'; $beanFiles['FP_Event_Locations'] = 'modules/FP_Event_Locations/FP_Event_Locations.php';
$moduleList[] = 'FP_Event_Locations'; $moduleList[] = 'FP_Event_Locations';
$beanList['AOD_IndexEvent'] = 'AOD_IndexEvent';
$beanFiles['AOD_IndexEvent'] = 'modules/AOD_IndexEvent/AOD_IndexEvent.php';
$modules_exempt_from_availability_check['AOD_IndexEvent'] = 'AOD_IndexEvent';
$report_include_modules['AOD_IndexEvent'] = 'AOD_IndexEvent';
$modInvisList[] = 'AOD_IndexEvent';
$beanList['AOD_Index'] = 'AOD_Index';
$beanFiles['AOD_Index'] = 'modules/AOD_Index/AOD_Index.php';
$modules_exempt_from_availability_check['AOD_Index'] = 'AOD_Index';
$report_include_modules['AOD_Index'] = 'AOD_Index';
$modInvisList[] = 'AOD_Index';
$beanList['AOP_Case_Events'] = 'AOP_Case_Events'; $beanList['AOP_Case_Events'] = 'AOP_Case_Events';
$beanFiles['AOP_Case_Events'] = 'modules/AOP_Case_Events/AOP_Case_Events.php'; $beanFiles['AOP_Case_Events'] = 'modules/AOP_Case_Events/AOP_Case_Events.php';
$modules_exempt_from_availability_check['AOP_Case_Events'] = 'AOP_Case_Events'; $modules_exempt_from_availability_check['AOP_Case_Events'] = 'AOP_Case_Events';

View file

@ -25,13 +25,18 @@
* the words "Supercharged by SuiteCRM". * the words "Supercharged by SuiteCRM".
*/ */
/* @noinspection PhpIncludeInspection */ require_once __DIR__ . '/FieldMappers/AssignedUserMapper.php';
require_once 'include/portability/ApiBeanMapper/FieldMappers/AssignedUserMapper.php'; require_once __DIR__ . '/LinkMappers/LinkMapperInterface.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/FullNameMapper.php'; require_once __DIR__ . '/LinkMappers/EmailAddressLinkMapper.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/DateMapper.php'; require_once __DIR__ . '/TypeMappers/FullNameMapper.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/DateTimeMapper.php'; require_once __DIR__ . '/TypeMappers/DateMapper.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/MultiEnumMapper.php'; require_once __DIR__ . '/TypeMappers/DateTimeMapper.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/BooleanMapper.php'; require_once __DIR__ . '/TypeMappers/DateTimeComboMapper.php';
require_once __DIR__ . '/TypeMappers/MultiEnumMapper.php';
require_once __DIR__ . '/TypeMappers/BooleanMapper.php';
require_once __DIR__ . '/ApiBeanModuleMappers.php';
require_once __DIR__ . '/ModuleMappers/SavedSearch/SavedSearchMappers.php';
require_once __DIR__ . '/ModuleMappers/AOP_Case_Updates/CaseUpdatesMappers.php';
class ApiBeanMapper class ApiBeanMapper
{ {
@ -46,6 +51,16 @@ class ApiBeanMapper
*/ */
protected $typeMappers = []; protected $typeMappers = [];
/**
* @var LinkMapperInterface[][]
*/
protected $linkMappers = [];
/**
* @var ApiBeanModuleMappers[]
*/
protected $moduleMappers = [];
public function __construct() public function __construct()
{ {
$this->fieldMappers[AssignedUserMapper::getField()] = new AssignedUserMapper(); $this->fieldMappers[AssignedUserMapper::getField()] = new AssignedUserMapper();
@ -55,13 +70,18 @@ class ApiBeanMapper
$this->typeMappers[MultiEnumMapper::getType()] = new MultiEnumMapper(); $this->typeMappers[MultiEnumMapper::getType()] = new MultiEnumMapper();
$this->typeMappers[BooleanMapper::getType()] = new BooleanMapper(); $this->typeMappers[BooleanMapper::getType()] = new BooleanMapper();
$this->typeMappers['boolean'] = $this->typeMappers[BooleanMapper::getType()]; $this->typeMappers['boolean'] = $this->typeMappers[BooleanMapper::getType()];
$this->moduleMappers[SavedSearchMappers::getModule()] = new SavedSearchMappers();
$this->typeMappers[DateTimeComboMapper::getType()] = new DateTimeMapper();
$this->linkMappers[EmailAddressLinkMapper::getRelateModule()] = [];
$this->linkMappers[EmailAddressLinkMapper::getRelateModule()]['all'] = new EmailAddressLinkMapper();
$this->moduleMappers[CaseUpdatesMappers::getModule()] = new CaseUpdatesMappers();
} }
/** /**
* @param SugarBean $bean * @param SugarBean $bean
* @return array * @return array
*/ */
public function toArray(SugarBean $bean): array public function toApi(SugarBean $bean): array
{ {
$arr = []; $arr = [];
@ -69,7 +89,6 @@ class ApiBeanMapper
$arr['object_name'] = $bean->object_name ?? ''; $arr['object_name'] = $bean->object_name ?? '';
foreach ($bean->field_defs as $field => $definition) { foreach ($bean->field_defs as $field => $definition) {
if ($this->isSensitiveField($definition)) { if ($this->isSensitiveField($definition)) {
continue; continue;
} }
@ -79,6 +98,12 @@ class ApiBeanMapper
} }
if ($this->isLinkField($definition)) { if ($this->isLinkField($definition)) {
if (!$this->hasLinkMapper($bean->module_name, $definition)) {
continue;
}
$this->mapLinkFieldToApi($bean, $arr, $definition);
continue; continue;
} }
@ -93,6 +118,58 @@ class ApiBeanMapper
return $arr; return $arr;
} }
/**
* @param SugarBean $bean
* @param array $values
* @return void
*/
public function toBean(SugarBean $bean, array $values): void
{
require_once __DIR__ . '/../../../include/SugarFields/SugarFieldHandler.php';
foreach ($bean->field_defs as $field => $properties) {
if (!isset($values[$field])) {
continue;
}
$this->toBeanMap($bean, $values, $properties, $field);
if ($this->isLinkField($properties)) {
if (!$this->hasLinkMapper($bean->module_name, $properties)) {
continue;
}
$this->mapLinkFieldToBean($bean, $values, $properties);
}
$bean->$field = $values[$field];
}
foreach ($bean->relationship_fields as $field => $link) {
if (!empty($values[$field])) {
$bean->$field = $values[$field];
}
}
}
/**
* @param SugarBean $bean
* @param array $values
* @return void
*/
public function toBeanAttributes(SugarBean $bean, array &$values): void
{
require_once __DIR__ . '/../../../include/SugarFields/SugarFieldHandler.php';
foreach ($bean->field_defs as $field => $properties) {
if (!isset($values[$field])) {
continue;
}
$this->toBeanMap($bean, $values, $properties, $field);
}
}
/** /**
* @param $definition * @param $definition
* @return bool * @return bool
@ -111,6 +188,7 @@ class ApiBeanMapper
return isset($definition['type']) && $definition['type'] === 'link'; return isset($definition['type']) && $definition['type'] === 'link';
} }
/** /**
* @param $fieldDefinition * @param $fieldDefinition
* @return bool * @return bool
@ -236,29 +314,186 @@ class ApiBeanMapper
array &$arr, array &$arr,
array $definition, array $definition,
string $alternativeName = '' string $alternativeName = ''
): void ): void {
{
$name = $field; $name = $field;
if (!empty($alternativeName)) { if (!empty($alternativeName)) {
$name = $alternativeName; $name = $alternativeName;
} }
$fieldMapper = $this->fieldMappers[$field] ?? null; $fieldMapper = $this->getFieldMapper($bean->module_name, $field);
if ($fieldMapper !== null) { if (null !== $fieldMapper) {
$fieldMapper->run($bean, $arr, $name); $fieldMapper->toApi($bean, $arr, $name);
return; return;
} }
$type = $definition['type'] ?? ''; $type = $definition['type'] ?? '';
$typeMapper = $this->typeMappers[$type] ?? null; $typeMapper = $this->getTypeMappers($bean->module_name, $type);
if ($typeMapper !== null) { if (null !== $typeMapper) {
$typeMapper->run($bean, $arr, $field, $name); $typeMapper->toApi($bean, $arr, $field, $name);
return; return;
} }
$arr[$name] = html_entity_decode($bean->$field ?? '', ENT_QUOTES); $arr[$name] = html_entity_decode($bean->$field ?? '', ENT_QUOTES);
} }
/**
* @param SugarBean $bean
* @param array $container
* @param array $definition
*/
protected function mapLinkFieldToApi(SugarBean $bean, array &$container, array $definition): void
{
$module = $bean->module_name ?? '';
$relateModule = $definition['module'] ?? '';
$name = $definition['name'] ?? '';
$linkMapper = $this->getLinkMapper($module, $relateModule, $name);
if ($linkMapper === null) {
return;
}
$linkMapper->toApi($bean, $container, $name);
}
/**
* @param SugarBean $bean
* @param array $container
* @param array $definition
*/
protected function mapLinkFieldToBean(SugarBean $bean, array &$container, array $definition): void
{
$module = $bean->module_name ?? '';
$relateModule = $definition['module'] ?? '';
$name = $definition['name'] ?? '';
$linkMapper = $this->getLinkMapper($module, $relateModule, $name);
if ($linkMapper === null) {
return;
}
$linkMapper->toBean($bean, $container, $name);
}
/**
* @param string $module
* @param string $field
* @return FieldMapperInterface
*/
protected function getFieldMapper(string $module, string $field): ?FieldMapperInterface
{
$moduleMappers = $this->moduleMappers[$module] ?? null;
if ($moduleMappers !== null && $moduleMappers->hasFieldMapper($field)) {
return $moduleMappers->getFieldMappers()[$field];
}
return $this->fieldMappers[$field] ?? null;
}
/**
* @param string $module
* @param string $relateModule
* @param string $field
* @return LinkMapperInterface
*/
protected function getLinkMapper(string $module, string $relateModule, string $field): ?LinkMapperInterface
{
if ($module === '' || $relateModule === '' || $field === '') {
return null;
}
$moduleMappers = $this->moduleMappers[$module] ?? null;
if ($moduleMappers !== null && $moduleMappers->hasLinkMapper($relateModule, $field)) {
return $moduleMappers->getLinkMapper($relateModule, $field);
}
$moduleLinkMappers = $this->linkMappers[$relateModule] ?? [];
return $moduleLinkMappers[$field] ?? $moduleLinkMappers['all'] ?? null;
}
/**
* @param $definition
* @return bool
*/
protected function hasLinkMapper($module, $definition): bool
{
$relateModule = $definition['module'] ?? '';
$name = $definition['name'] ?? '';
if ($relateModule === '' || $name === '') {
return false;
}
return $this->getLinkMapper($module, $relateModule, $name) !== null;
}
/**
* @param string $module
* @param string $type
* @return TypeMapperInterface
*/
protected function getTypeMappers(string $module, string $type): ?TypeMapperInterface
{
$moduleMappers = $this->moduleMappers[$module] ?? null;
if ($moduleMappers !== null && $moduleMappers->hasTypeMapper($type)) {
return $moduleMappers->getTypeMappers()[$type];
}
return $this->typeMappers[$type] ?? null;
}
/**
* @param SugarBean $bean
* @param array $values
* @param $properties
* @param $field
*/
protected function toBeanMap(SugarBean $bean, array &$values, $properties, $field): void
{
$type = $properties['type'] ?? '';
if ($type === 'relate' && isset($bean->field_defs[$field])) {
$idName = $bean->field_defs[$field]['id_name'] ?? '';
if ($idName !== $field) {
$idValue = $values[$field]['id'] ?? '';
if (empty($values[$idName]) && !empty($idValue)) {
$values[$idName] = $idValue;
}
$rName = $bean->field_defs[$field]['rname'] ?? '';
$value = $values[$field][$rName] ?? '';
$values[$field] = $value;
}
}
if (!empty($properties['isMultiSelect']) || $type === 'multienum') {
$multiSelectValue = $values[$field];
if (!is_array($values[$field])) {
$multiSelectValue = [];
}
$values[$field] = encodeMultienumValue($multiSelectValue);
}
$fieldMapper = $this->getFieldMapper($bean->module_name, $field);
if (null !== $fieldMapper) {
$fieldMapper->toBean($bean, $values, $field);
}
$typeMapper = $this->getTypeMappers($bean->module_name, $type);
if (null !== $typeMapper) {
$typeMapper->toBean($bean, $values, $field, $field);
}
}
} }

View file

@ -0,0 +1,155 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/TypeMappers/TypeMapperInterface.php';
require_once __DIR__ . '/FieldMappers/FieldMapperInterface.php';
require_once __DIR__ . '/LinkMappers/LinkMapperInterface.php';
class ApiBeanModuleMappers
{
public const MODULE = '';
/**
* @var FieldMapperInterface[]
*/
protected $fieldMappers = [];
/**
* @var TypeMapperInterface[]
*/
protected $typeMappers = [];
/**
* @var LinkMapperInterface[][]
*/
protected $linkMappers = [];
/**
* @return string
*/
public static function getModule(): string
{
return self::MODULE;
}
/**
* @return FieldMapperInterface[]
*/
public function getFieldMappers(): array
{
return $this->fieldMappers;
}
/**
* @param FieldMapperInterface[] $fieldMappers
* @return ApiBeanModuleMappers
*/
public function setFieldMappers(array $fieldMappers): ApiBeanModuleMappers
{
$this->fieldMappers = $fieldMappers;
return $this;
}
/**
* @param string $field
* @return bool
*/
public function hasFieldMapper(string $field): bool
{
return isset($this->fieldMappers[$field]);
}
/**
* @return TypeMapperInterface[]
*/
public function getTypeMappers(): array
{
return $this->typeMappers;
}
/**
* @param TypeMapperInterface[] $typeMappers
* @return ApiBeanModuleMappers
*/
public function setTypeMappers(array $typeMappers): ApiBeanModuleMappers
{
$this->typeMappers = $typeMappers;
return $this;
}
/**
* @param string $type
* @return bool
*/
public function hasTypeMapper(string $type): bool
{
return isset($this->typeMappers[$type]);
}
/**
* @return LinkMapperInterface[][]
*/
public function getLinkMappers(): array
{
return $this->linkMappers;
}
/**
* @param string $relateModule
* @param string $field
* @return LinkMapperInterface|null
*/
public function getLinkMapper(string $relateModule, string $field): ?LinkMapperInterface
{
$moduleLinkMappers = $this->linkMappers[$relateModule] ?? [];
return $moduleLinkMappers[$field] ?? $moduleLinkMappers['all'] ?? null;
}
/**
* @param LinkMapperInterface[][] $linkMappers
* @return ApiBeanModuleMappers
*/
public function setLinkMappers(array $linkMappers): ApiBeanModuleMappers
{
$this->linkMappers = $linkMappers;
return $this;
}
/**
* @param string $relateModule
* @param string $field
* @return bool
*/
public function hasLinkMapper(string $relateModule, string $field): bool
{
return $this->getLinkMapper($relateModule, $field) !== null;
}
}

View file

@ -25,9 +25,7 @@
* the words "Supercharged by SuiteCRM". * the words "Supercharged by SuiteCRM".
*/ */
/* @noinspection PhpIncludeInspection */ require_once __DIR__ .'/FieldMapperInterface.php';
require_once 'include/portability/ApiBeanMapper/FieldMappers/FieldMapperInterface.php';
class AssignedUserMapper implements FieldMapperInterface class AssignedUserMapper implements FieldMapperInterface
{ {
@ -44,7 +42,7 @@ class AssignedUserMapper implements FieldMapperInterface
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function run(SugarBean $bean, array &$container, string $alternativeName = ''): void public function toApi(SugarBean $bean, array &$container, string $alternativeName = ''): void
{ {
$name = self::FIELD_NAME; $name = self::FIELD_NAME;
@ -60,4 +58,26 @@ class AssignedUserMapper implements FieldMapperInterface
$container[$name] = get_assigned_user_name($bean->assigned_user_id); $container[$name] = get_assigned_user_name($bean->assigned_user_id);
} }
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
if (empty($container)) {
return;
}
$fieldName = self::getField();
if (!empty($alternativeName)) {
$fieldName = $alternativeName;
}
$assignedUserName = $container[$fieldName] ?? [];
if (is_string($assignedUserName)) {
$container[$alternativeName] = $assignedUserName;
}
$container[$alternativeName] = $assignedUserName['user_name'] ?? '';
}
} }

View file

@ -33,7 +33,6 @@ interface FieldMapperInterface
*/ */
public static function getField(): string; public static function getField(): string;
/** /**
* Map the field and add it to the container * Map the field and add it to the container
* @param SugarBean $bean * @param SugarBean $bean
@ -41,5 +40,14 @@ interface FieldMapperInterface
* @param string $alternativeName * @param string $alternativeName
* @return mixed * @return mixed
*/ */
public function run(SugarBean $bean, array &$container, string $alternativeName = ''): void; public function toApi(SugarBean $bean, array &$container, string $alternativeName = ''): void;
/**
* Map the field to bean format and add it to the container
* @param SugarBean $bean
* @param array $container
* @param string $alternativeName
* @return mixed
*/
public function toBean(SugarBean $bean, array &$container, string $alternativeName = ''): void;
} }

View file

@ -0,0 +1,121 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/LineItemMapper.php';
class EmailAddressLinkMapper extends LineItemMapper
{
public const MODULE = 'EmailAddress';
/**
* @inheritDoc
*/
public static function getField(): string
{
return 'all';
}
/**
* @inheritDoc
*/
public static function getRelateModule(): string
{
return self::MODULE;
}
/**
* @inheritDoc
*/
public static function getModule(): string
{
return 'default';
}
/**
* @inheritDoc
*/
protected function getItemBeans(SugarBean $bean, array $definition): array
{
$addresses = $bean->emailAddress->addresses ?? [];
/** @var SugarBean[] $beans */
$beans = [];
foreach ($addresses as $address) {
$itemBean = new EmailAddress();
if ($itemBean === null) {
continue;
}
$itemBean->populateFromRow($address);
$itemBean->primary_address = (bool)($address['primary_address'] ?? false);
$itemBean->reply_to_address = (bool)($address['reply_to_address'] ?? false);
$beans[] = $itemBean;
}
return $beans;
}
/**
* @inheritDoc
*/
protected function isLineItem(SugarBean $bean, string $name): bool
{
return true;
}
/**
* @inheritDoc
*/
protected function mapItem(SugarBean $itemBean): array
{
$attributes = parent::mapItem($itemBean);
$attributes['primary_address'] = $itemBean->primary_address;
$attributes['reply_to_address'] = $itemBean->reply_to_address;
return $attributes;
}
/**
* @inheritDoc
*/
protected function buildItemBean(string $module, $item)
{
$itemBean = new EmailAddress();
$id = $item['attributes']['id'] ?? '';
if (!empty($id)) {
$itemBean->retrieve($id);
}
$itemBean->primary_address = $item['attributes']['primary_address'] ?? false;
$itemBean->reply_to_address = $item['attributes']['reply_to_address'] ?? false;
return $itemBean;
}
}

View file

@ -0,0 +1,162 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/LinkMapperInterface.php';
abstract class LineItemMapper implements LinkMapperInterface
{
/**
* @inheritDoc
*/
public function toApi(SugarBean $bean, array &$container, string $name): void
{
$newName = $name;
$definition = $this->getDefinition($bean, $name);
$isLineItem = $this->isLineItem($bean, $name);
if (!$isLineItem) {
return;
}
$container[$newName] = [];
$itemBeans = $this->getItemBeans($bean, $definition);
foreach ($itemBeans as $itemBean) {
$attributes = $this->mapItem($itemBean);
$itemModule = $itemBean->module_name ?? '';
$record = [
'id' => $attributes['id'],
'module' => $itemModule,
'attributes' => $attributes
];
$container[$newName][] = $record;
}
}
/**
* Get relate field definition
* @param SugarBean $bean
* @param string $name
* @return array|mixed
*/
protected function getDefinition(SugarBean $bean, string $name)
{
return $bean->field_defs[$name] ?? [];
}
/**
* Check if it is a line Item
* @param SugarBean $bean
* @param string $name
* @return bool
*/
protected function isLineItem(SugarBean $bean, string $name): bool
{
$definition = $this->getDefinition($bean, $name);
return (bool)($definition['line-item'] ?? false);
}
/**
* @param SugarBean $bean
* @param array $definition
* @return SugarBean[]
*/
protected function getItemBeans(SugarBean $bean, array $definition): array
{
$relationship = $definition['relationship'] ?? false;
$linkName = $definition['name'] ?? false;
$bean->load_relationship($relationship);
/** @var Link2 $link */
$link = $bean->$linkName;
return $link->getBeans();
}
/**
* @param SugarBean $itemBean
* @return array
*/
protected function mapItem(SugarBean $itemBean): array
{
$mapper = new ApiBeanMapper();
return $mapper->toApi($itemBean);
}
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
$items = $container[$name] ?? null;
if (empty($items)) {
return;
}
$definition = $this->getDefinition($bean, $name);
$module = $definition['module'] ?? '';
$isLineItem = $this->isLineItem($bean, $name);
if (!$isLineItem || $module === '') {
return;
}
$bean->line_item_entries[$name] = [];
foreach ($items as $item) {
$mapper = new ApiBeanMapper();
$itemBean = $this->buildItemBean($module, $item);
$mapper->toBean($itemBean, $item['attributes']);
$bean->line_item_entries[$name][] = $itemBean;
}
}
/**
* @param string $module
* @param $item
* @return bool|SugarBean
*/
protected function buildItemBean(string $module, $item)
{
$itemBean = BeanFactory::newBean($module);
$id = $item['attributes']['id'] ?? '';
if (!empty($id)) {
$itemBean = BeanFactory::getBean($module, $id);
}
return $itemBean;
}
}

View file

@ -0,0 +1,65 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
interface LinkMapperInterface
{
/**
* The field to map
* @return string
*/
public static function getField(): string;
/**
* The module to map
* @return string
*/
public static function getRelateModule(): string;
/**
* The module to map
* @return string
*/
public static function getModule(): string;
/**
* Map the field and add it to the container
* @param SugarBean $bean
* @param array $container
* @param string $name
* @return mixed
*/
public function toApi(SugarBean $bean, array &$container, string $name): void;
/**
* Map the field to bean format and add it to the container
* @param SugarBean $bean
* @param array $container
* @param string $name
* @return mixed
*/
public function toBean(SugarBean $bean, array &$container, string $name): void;
}

View file

@ -0,0 +1,90 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../../../ApiBeanMapper/FieldMappers/FieldMapperInterface.php';
require_once __DIR__ . '/../../../ModuleNameMapper.php';
class CaseUpdatesAuthorMapper implements FieldMapperInterface
{
public const FIELD_NAME = 'author';
/**
* @var ModuleNameMapper
*/
protected $moduleNameMapper;
/**
* RouteConverter constructor.
*/
public function __construct()
{
$this->moduleNameMapper = new ModuleNameMapper();
}
/**
* {@inheritDoc}
*/
public static function getField(): string
{
return self::FIELD_NAME;
}
/**
* {@inheritDoc}
*/
public function toApi(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$name = self::FIELD_NAME;
$contactId = $bean->contact_id ?? '';
if ($contactId !== '') {
$contact = $bean->get_linked_beans('contact')[0];
$container[$name] = $contact->name;
return;
}
$assignedUserId = $bean->assigned_user_id ?? '';
$assignedUserName = $bean->assigned_user_name ?? '';
if ($assignedUserId !== '' && $assignedUserName !== '') {
$container[$name] = $assignedUserName;
return;
}
$container[$name] = '[external]';
}
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
}
}

View file

@ -0,0 +1,73 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../../../ApiBeanMapper/FieldMappers/FieldMapperInterface.php';
require_once __DIR__ . '/../../../ModuleNameMapper.php';
class CaseUpdatesDescriptionMapper implements FieldMapperInterface
{
public const FIELD_NAME = 'description';
/**
* @var ModuleNameMapper
*/
protected $moduleNameMapper;
/**
* RouteConverter constructor.
*/
public function __construct()
{
$this->moduleNameMapper = new ModuleNameMapper();
}
/**
* {@inheritDoc}
*/
public function toApi(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$name = self::FIELD_NAME;
$container[$name] = html_entity_decode($bean->$name ?? '', ENT_QUOTES);
}
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$contents = $container[self::getField()] ?? [];
$container[self::getField()] = nl2br($contents);
}
/**
* {@inheritDoc}
*/
public static function getField(): string
{
return self::FIELD_NAME;
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/CaseUpdatesDescriptionMapper.php';
require_once __DIR__ . '/CaseUpdatesAuthorMapper.php';
require_once __DIR__ . '/CaseUpdatesSourceMapper.php';
require_once __DIR__ . '/../../ApiBeanModuleMappers.php';
class CaseUpdatesMappers extends ApiBeanModuleMappers
{
/**
* @var string
*/
public const MODULE = 'AOP_Case_Updates';
public function __construct()
{
$this->fieldMappers[CaseUpdatesDescriptionMapper::getField()] = new CaseUpdatesDescriptionMapper();
$this->fieldMappers[CaseUpdatesAuthorMapper::getField()] = new CaseUpdatesAuthorMapper();
$this->fieldMappers[CaseUpdatesSourceMapper::getField()] = new CaseUpdatesSourceMapper();
}
/**
* @return string
*/
public static function getModule(): string
{
return self::MODULE;
}
}

View file

@ -0,0 +1,88 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../../../ApiBeanMapper/FieldMappers/FieldMapperInterface.php';
require_once __DIR__ . '/../../../ModuleNameMapper.php';
class CaseUpdatesSourceMapper implements FieldMapperInterface
{
public const FIELD_NAME = 'source';
/**
* @var ModuleNameMapper
*/
protected $moduleNameMapper;
/**
* RouteConverter constructor.
*/
public function __construct()
{
$this->moduleNameMapper = new ModuleNameMapper();
}
/**
* {@inheritDoc}
*/
public static function getField(): string
{
return self::FIELD_NAME;
}
/**
* {@inheritDoc}
*/
public function toApi(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$name = self::FIELD_NAME;
$contactId = $bean->contact_id ?? '';
if ($contactId !== '') {
$container[$name] = 'contact';
return;
}
$assignedUserId = $bean->assigned_user_id ?? '';
$assignedUserName = $bean->assigned_user_name ?? '';
if ($assignedUserId !== '' && $assignedUserName !== '') {
$container[$name] = 'internal';
return;
}
$container[$name] = 'external';
}
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
}
}

View file

@ -0,0 +1,189 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ .'/../../../ApiBeanMapper/FieldMappers/FieldMapperInterface.php';
require_once __DIR__ . '/../../../ModuleNameMapper.php';
require_once __DIR__ . '/../../../FilterMapper/FilterMapper.php';
class FilterContentMapper implements FieldMapperInterface
{
public const FIELD_NAME = 'contents';
/**
* @var ModuleNameMapper
*/
protected $moduleNameMapper;
/**
* @var FilterMapper
*/
protected $filterMapper;
/**
* RouteConverter constructor.
*/
public function __construct()
{
$this->moduleNameMapper = new ModuleNameMapper();
$this->filterMapper = new FilterMapper();
}
/**
* {@inheritDoc}
*/
public static function getField(): string
{
return self::FIELD_NAME;
}
/**
* {@inheritDoc}
*/
public function toApi(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$name = self::FIELD_NAME;
if (!empty($alternativeName)) {
$name = $alternativeName;
}
if ('SavedSearch' !== $bean->object_name) {
$container[$name] = [];
return;
}
if (empty($bean->contents)) {
$container[$name] = [];
return;
}
$contents = $this->parseContent($bean->name, $bean->contents);
$container[$name] = $contents;
$container['orderBy'] = $contents['orderBy'] ?? '';
$container['sortOrder'] = $contents['sortOrder'] ?? '';
}
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$contents = $container[self::getField()] ?? [];
$legacyContents = [
'searchFormTab' => 'advanced',
'query' => '',
'search_module' => '',
'saved_search_action' => '',
'displayColumns' => '',
'hideTabs' => '',
'orderBy' => '',
'sortOrder' => '',
'advanced' => ''
];
if (!empty($bean->contents)) {
$legacyContents = unserialize(base64_decode($bean->contents), ['allowed_classes' => true]);
}
if (empty($contents) || empty($contents['filters'])) {
$container[self::getField()] = $this->encode($legacyContents);
return;
}
$mappedFilters = $this->filterMapper->toLegacy($contents, 'advanced');
$legacyContents = array_merge($legacyContents, $mappedFilters);
$legacyContents['orderBy'] = strtoupper($contents['orderBy'] ?? '');
$legacyContents['sortOrder'] = strtoupper($contents['sortOrder'] ?? '');
$module = $contents['searchModule'] ?? ($container['search_module'] ?? '');
if (!empty($module)) {
$legacyContents['search_module'] = $this->moduleNameMapper->toLegacy($module);
}
$container[self::getField()] = $this->encode($legacyContents);
}
/**
* Parse base64 encoded contents and convert to api format
* @param string $filterName
* @param string $serializedContents
* @return array
*/
public function parseContent(string $filterName, string $serializedContents): array
{
$contents = unserialize(base64_decode($serializedContents), ['allowed_classes' => true]);
$newContents = [
'name' => $filterName,
'filters' => [],
'searchModule' => '',
'orderBy' => strtolower($contents['orderBy'] ?? ''),
'sortOrder' => strtolower($contents['sortOrder'] ?? '')
];
if (!empty($contents['search_module'])) {
$newContents['searchModule'] = $this->moduleNameMapper->toFrontEnd($contents['search_module']);
}
unset(
$contents['searchFormTab'],
$contents['query'],
$contents['search_module'],
$contents['saved_search_action'],
$contents['displayColumns'],
$contents['hideTabs'],
$contents['orderBy'],
$contents['sortOrder'],
$contents['advanced']
);
$filters = $this->filterMapper->toApi($contents);
$newContents['filters'] = $filters;
return $newContents;
}
/**
* Encode criteria
* @param array $content
* @return string
*/
public function encode(array $content): string
{
if (empty($content)) {
return '';
}
return base64_encode(serialize($content));
}
}

View file

@ -0,0 +1,52 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/FilterContentMapper.php';
require_once __DIR__ . '/SearchModuleMapper.php';
require_once __DIR__ . '/../../ApiBeanModuleMappers.php';
class SavedSearchMappers extends ApiBeanModuleMappers
{
/**
* @var string
*/
public const MODULE = 'SavedSearch';
public function __construct()
{
$this->fieldMappers[FilterContentMapper::getField()] = new FilterContentMapper();
$this->fieldMappers[SearchModuleMapper::getField()] = new SearchModuleMapper();
}
/**
* @return string
*/
public static function getModule(): string
{
return self::MODULE;
}
}

View file

@ -0,0 +1,93 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../../../ApiBeanMapper/FieldMappers/FieldMapperInterface.php';
require_once __DIR__ . '/../../../ModuleNameMapper.php';
class SearchModuleMapper implements FieldMapperInterface
{
public const FIELD_NAME = 'search_module';
/**
* @var ModuleNameMapper
*/
protected $moduleNameMapper;
/**
* RouteConverter constructor.
*/
public function __construct()
{
$this->moduleNameMapper = new ModuleNameMapper();
}
/**
* @inheritDoc
*/
public static function getField(): string
{
return self::FIELD_NAME;
}
/**
* @inheritDoc
*/
public function toApi(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$name = self::FIELD_NAME;
if (!empty($alternativeName)) {
$name = $alternativeName;
}
if (empty($bean->search_module)) {
$container[$name] = '';
return;
}
$container[$name] = $this->moduleNameMapper->toFrontEnd($bean->search_module);
}
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $alternativeName = ''): void
{
$name = self::getField();
if (!empty($alternativeName)) {
$name = $alternativeName;
}
if (empty($container[$name])) {
return;
}
$container[self::getField()] = $this->moduleNameMapper->toLegacy($container[$name]);
}
}

View file

@ -25,8 +25,7 @@
* the words "Supercharged by SuiteCRM". * the words "Supercharged by SuiteCRM".
*/ */
/* @noinspection PhpIncludeInspection */ require_once __DIR__ .'/TypeMapperInterface.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/TypeMapperInterface.php';
class BooleanMapper implements TypeMapperInterface class BooleanMapper implements TypeMapperInterface
{ {
@ -41,7 +40,7 @@ class BooleanMapper implements TypeMapperInterface
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function run(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void public function toApi(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{ {
$newName = $name; $newName = $name;
@ -65,6 +64,13 @@ class BooleanMapper implements TypeMapperInterface
$container[$newName] = $value; $container[$newName] = $value;
} }
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
}
/** /**
* @param $value * @param $value
* @return bool * @return bool

View file

@ -25,9 +25,8 @@
* the words "Supercharged by SuiteCRM". * the words "Supercharged by SuiteCRM".
*/ */
/* @noinspection PhpIncludeInspection */ require_once __DIR__ .'/../../Services/DateTime/DateFormatService.php';
require_once 'include/portability/Services/DateTime/DateFormatService.php'; require_once __DIR__ .'/TypeMapperInterface.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/TypeMapperInterface.php';
class DateMapper implements TypeMapperInterface class DateMapper implements TypeMapperInterface
{ {
@ -53,7 +52,7 @@ class DateMapper implements TypeMapperInterface
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function run(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void public function toApi(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{ {
$newName = $name; $newName = $name;
@ -77,4 +76,11 @@ class DateMapper implements TypeMapperInterface
$container[$newName] = $dbDate; $container[$newName] = $dbDate;
} }
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
}
} }

View file

@ -0,0 +1,86 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ .'/../../Services/DateTime/DateFormatService.php';
require_once __DIR__ .'/TypeMapperInterface.php';
class DateTimeComboMapper implements TypeMapperInterface
{
/**
* @var DateFormatService
*/
protected $dateFormatService;
public function __construct()
{
$this->dateFormatService = new DateFormatService();
}
/**
* @inheritDoc
*/
public static function getType(): string
{
return 'datetimecombo';
}
/**
* @inheritDoc
*/
public function toApi(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
$newName = $name;
if (!empty($alternativeName)) {
$newName = $alternativeName;
}
if (empty($bean->$name)) {
$container[$newName] = '';
return;
}
$dbDate = $this->dateFormatService->toDBDateTime($bean->$name);
if (empty($dbDate)) {
$container[$newName] = '';
return;
}
$container[$newName] = $dbDate;
}
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
}
}

View file

@ -25,9 +25,8 @@
* the words "Supercharged by SuiteCRM". * the words "Supercharged by SuiteCRM".
*/ */
/* @noinspection PhpIncludeInspection */ require_once __DIR__ .'/../../Services/DateTime/DateFormatService.php';
require_once 'include/portability/Services/DateTime/DateFormatService.php'; require_once __DIR__ .'/TypeMapperInterface.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/TypeMapperInterface.php';
class DateTimeMapper implements TypeMapperInterface class DateTimeMapper implements TypeMapperInterface
{ {
@ -53,7 +52,7 @@ class DateTimeMapper implements TypeMapperInterface
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function run(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void public function toApi(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{ {
$newName = $name; $newName = $name;
@ -77,4 +76,11 @@ class DateTimeMapper implements TypeMapperInterface
$container[$newName] = $dbDate; $container[$newName] = $dbDate;
} }
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
}
} }

View file

@ -25,8 +25,7 @@
* the words "Supercharged by SuiteCRM". * the words "Supercharged by SuiteCRM".
*/ */
/* @noinspection PhpIncludeInspection */ require_once __DIR__ .'/TypeMapperInterface.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/TypeMapperInterface.php';
class FullNameMapper implements TypeMapperInterface class FullNameMapper implements TypeMapperInterface
{ {
@ -41,7 +40,7 @@ class FullNameMapper implements TypeMapperInterface
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function run(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void public function toApi(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{ {
$newName = $name; $newName = $name;
@ -79,4 +78,11 @@ class FullNameMapper implements TypeMapperInterface
$container[$newName] = implode(' ', $fullNameFormat); $container[$newName] = implode(' ', $fullNameFormat);
} }
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
}
} }

View file

@ -25,8 +25,7 @@
* the words "Supercharged by SuiteCRM". * the words "Supercharged by SuiteCRM".
*/ */
/* @noinspection PhpIncludeInspection */ require_once __DIR__ .'/TypeMapperInterface.php';
require_once 'include/portability/ApiBeanMapper/TypeMappers/TypeMapperInterface.php';
class MultiEnumMapper implements TypeMapperInterface class MultiEnumMapper implements TypeMapperInterface
{ {
@ -41,7 +40,7 @@ class MultiEnumMapper implements TypeMapperInterface
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function run(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void public function toApi(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{ {
$newName = $name; $newName = $name;
@ -86,4 +85,11 @@ class MultiEnumMapper implements TypeMapperInterface
return explode('^,^', $string); return explode('^,^', $string);
} }
/**
* @inheritDoc
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void
{
}
} }

View file

@ -42,6 +42,15 @@ interface TypeMapperInterface
* @param string $alternativeName * @param string $alternativeName
* @return mixed * @return mixed
*/ */
public function run(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void; public function toApi(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void;
/**
* Map the field to bean format and add it to the container
* @param SugarBean $bean
* @param array $container
* @param string $name
* @param string $alternativeName
* @return mixed
*/
public function toBean(SugarBean $bean, array &$container, string $name, string $alternativeName = ''): void;
} }

View file

@ -0,0 +1,227 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/FilterMappers.php';
require_once __DIR__ . '/FilterMapperInterface.php';
class FilterMapper
{
/**
* @var array
*/
private $filterOperatorMap;
/**
* @var FilterMappers
*/
private $mappers;
/**
* LegacyFilterMapper constructor.
*/
public function __construct()
{
$filter_operator_map = [];
require 'filter_operator_map.php';
$this->filterOperatorMap = $filter_operator_map;
$this->mappers = new FilterMappers();
}
/**
* Map filter to api
* @param array $contents
* @return array
*/
public function toApi(array $contents): array
{
$filters = [];
foreach ($contents as $key => $value) {
if (empty($contents[$key])) {
continue;
}
$filter = [
'field' => '',
'operator' => '=',
'values' => '',
'start' => '',
'end' => '',
'target' => ''
];
$isRange = preg_match('/(.*)_advanced_range_choice/', $key);
if ($isRange) {
$fieldKey = str_replace('_advanced_range_choice', '', $key);
$filter['field'] = $fieldKey;
$filter['operator'] = $value;
$filter['start'] = $contents["start_range_${fieldKey}_advanced"] ?? '';
$filter['end'] = $contents["end_range_${fieldKey}_advanced"] ?? '';
$filter['target'] = $contents["range_${fieldKey}_advanced"] ?? '';
$filter['fieldType'] = $contents["field_type_${fieldKey}"] ?? '';
$filters[$fieldKey] = $filter;
continue;
}
$isRangeValue = preg_match('/range_(.*)_advanced/', $key);
if ($isRangeValue) {
continue;
}
$isFieldType = preg_match('/field_type_(.*)/', $key);
if ($isFieldType) {
continue;
}
$isRegularValue = preg_match('/(.*)_advanced/', $key);
if ($isRegularValue) {
$fieldKey = str_replace('_advanced', '', $key);
$filter['field'] = $fieldKey;
$values = [];
if (is_string($value)) {
$values = [$value];
}
$filter['values'] = $values;
$filter['fieldType'] = $contents["field_type_${fieldKey}"] ?? '';
$filters[$fieldKey] = $filter;
continue;
}
}
return $filters;
}
/**
* Map Filters to legacy
* @param array $criteria
* @param string $type
* @return array
*/
public function toLegacy(array $criteria, string $type): array
{
$mapped = [];
if (empty($criteria['filters'])) {
return $mapped;
}
foreach ($criteria['filters'] as $key => $item) {
if (empty($item['operator'])) {
continue;
}
$fieldType = $item['fieldType'] ?? '';
$operator = $item['operator'] ?? '';
$typeConfig = $this->filterOperatorMap[$fieldType] ?? [];
$mergedConfig = array_merge($this->filterOperatorMap['default'], $typeConfig);
$mapConfig = $mergedConfig[$operator];
if (empty($mapConfig)) {
continue;
}
foreach ($mapConfig as $mappedKey => $mappedValue) {
$legacyKey = $this->mapFilterKey($type, $key, $mappedKey);
$legacyValue = $this->mapFilterValue($mappedValue, $item);
$mapped[$legacyKey] = $legacyValue;
}
$mapped['field_type_' . $key] = $fieldType;
}
return $mapped;
}
/**
* Map Filter key to legacy
* @param string $type
* @param string $key
* @param string $mappedKey
* @return string
*/
protected function mapFilterKey(string $type, string $key, string $mappedKey): string
{
return str_replace(array('{field}', '{type}'), array($key, $type), $mappedKey);
}
/**
* Map Filter value to legacy
* @param string $mappedValue
* @param array $item
* @return mixed|string|string[]
*/
protected function mapFilterValue(string $mappedValue, array $item)
{
$fieldType = $item['fieldType'] ?? '';
if ($mappedValue === 'values') {
if ($this->mappers->hasMapper($fieldType)) {
return $this->mappers->get($fieldType)->mapValue($mappedValue, $item);
}
return $this->mappers->get('default')->mapValue($mappedValue, $item);
}
$operator = $item['operator'] ?? '';
$start = $item['start'] ?? '';
$end = $item['end'] ?? '';
$target = $item['target'] ?? '';
return str_replace(
['{operator}', '{start}', '{end}', '{target}'],
[$operator, $start, $end, $target],
$mappedValue
);
}
/**
* Get order by
* @param array $sort
* @return string
*/
public function getOrderBy(array $sort): string
{
return $sort['orderBy'] ?? 'date_entered';
}
/**
* Get sort order
* @param array $sort
* @return string
*/
public function getSortOrder(array $sort): string
{
return $sort['sortOrder'] ?? 'DESC';
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
interface FilterMapperInterface
{
/**
* Get the field type it applies to
* @return string
*/
public function getType(): string;
/**
* Map value
* @param string $mappedValue
* @param array $criteriaItem
* @return mixed|string|string[]
*/
public function mapValue(string $mappedValue, array $criteriaItem);
}

View file

@ -0,0 +1,81 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/FilterMapperInterface.php';
class FilterMappers
{
protected const MSG_HANDLER_NOT_FOUND = 'Filter mapper is not defined';
/**
* @var FilterMapperInterface[]
*/
protected $registry = [];
/**
* FilterMappers constructor.
*/
public function __construct()
{
/**
* @var FilterMapperInterface[]
*/
$filter_mappers = [];
require 'filter_mappers.php';
foreach ($filter_mappers as $handler) {
$type = $handler->getType();
$this->registry[$type] = $handler;
}
}
/**
* Get the mapper for field type
* @param string $type
* @return FilterMapperInterface
*/
public function get(string $type): FilterMapperInterface
{
if (empty($this->registry[$type])) {
throw new RuntimeException(self::MSG_HANDLER_NOT_FOUND);
}
return $this->registry[$type];
}
/**
* Has mapper for the given type
* @param string $type
* @return bool
*/
public function hasMapper(string $type): bool
{
return !(empty($this->registry[$type]));
}
}

View file

@ -0,0 +1,82 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../FilterMapperInterface.php';
require_once __DIR__ . '/../../Services/DateTime/DateFormatService.php';
class DateFilterMapper implements FilterMapperInterface
{
/**
* @var DateFormatService
*/
private $dateTimeHandler;
/**
* DateFilterMapper constructor.
*/
public function __construct()
{
$this->dateTimeHandler = new DateFormatService();
}
/**
* @inheritDoc
*/
public function getType(): string
{
return 'date';
}
/**
* @inheritDoc
*/
public function mapValue(string $mappedValue, array $criteriaItem)
{
/** @var array */
$values = $criteriaItem['values'] ?? [];
if (empty($values)) {
return [];
}
$mapped = [];
foreach ($values as $value) {
if (empty($value)) {
continue;
}
$mapped[] = $this->dateTimeHandler->toUserDate($value);
}
$legacyValue = $mapped;
if (count($mapped) === 1) {
$legacyValue = $mapped[0];
}
return $legacyValue;
}
}

View file

@ -0,0 +1,82 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../FilterMapperInterface.php';
require_once __DIR__ . '/../../Services/DateTime/DateFormatService.php';
class DateTimeFilterMapper implements FilterMapperInterface
{
/**
* @var DateFormatService
*/
private $dateTimeHandler;
/**
* DateFilterMapper constructor.
*/
public function __construct()
{
$this->dateTimeHandler = new DateFormatService();
}
/**
* @inheritDoc
*/
public function getType(): string
{
return 'datetime';
}
/**
* @inheritDoc
*/
public function mapValue(string $mappedValue, array $criteriaItem)
{
/** @var array */
$values = $criteriaItem['values'] ?? [];
if (empty($values)) {
return [];
}
$mapped = [];
foreach ($values as $value) {
if (empty($value)) {
continue;
}
$mapped[] = $this->dateTimeHandler->toDBDateTime($value);
}
$legacyValue = $mapped;
if (count($mapped) === 1) {
$legacyValue = $mapped[0];
}
return $legacyValue;
}
}

View file

@ -0,0 +1,59 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../FilterMapperInterface.php';
class DefaultFilterMapper implements FilterMapperInterface
{
/**
* @inheritDoc
*/
public function getType(): string
{
return 'default';
}
/**
* @inheritDoc
*/
public function mapValue(string $mappedValue, array $criteriaItem)
{
/** @var array */
$values = $criteriaItem['values'] ?? [];
if (empty($values)) {
return [];
}
$legacyValue = $values;
if (count($values) === 1) {
$legacyValue = $values[0];
}
return $legacyValue;
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../FilterMapperInterface.php';
class MultiEnumFilterMapper implements FilterMapperInterface
{
/**
* @inheritDoc
*/
public function getType(): string
{
return 'multienum';
}
/**
* @inheritDoc
*/
public function mapValue(string $mappedValue, array $criteriaItem)
{
/** @var array */
$values = $criteriaItem['values'] ?? [];
if (empty($values)) {
return [];
}
return $criteriaItem['values'];
}
}

View file

@ -0,0 +1,44 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a)=>FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/Mappers/DateFilterMapper.php';
require_once __DIR__ . '/Mappers/DateTimeFilterMapper.php';
require_once __DIR__ . '/Mappers/DefaultFilterMapper.php';
require_once __DIR__ . '/Mappers/MultiEnumFilterMapper.php';
$filter_mappers = [
'default' => new DefaultFilterMapper(),
'date' => new DateFilterMapper(),
'datetime' => new DateTimeFilterMapper(),
'multienum' => new MultiEnumFilterMapper()
];
$extensionPath = 'custom/application/Ext/FilterMappers/filter_mappers.ext.php';
if (file_exists($extensionPath)) {
include($extensionPath);
}

View file

@ -0,0 +1,130 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a)=>FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
$filter_operator_map = [
'default' => [
'=' => [
'{field}_{type}' => 'values'
],
'not_equal' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '{target}'
],
'between' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '{start}',
'end_range_{field}_{type}' => '{end}'
],
'greater_than' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '{target}'
],
'less_than' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '{target}'
],
'last_7_days' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'next_7_days' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'last_30_days' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'next_30_days' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'last_month' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'this_month' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '[{operator}]',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'next_month' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'last_year' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'this_year' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
'next_year' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '',
'start_range_{field}_{type}' => '',
'end_range_{field}_{type}' => ''
],
],
'date' => [
'=' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '{target}'
],
'datetime' => [
'=' => [
'{field}_{type}_range_choice' => '{operator}',
'range_{field}_{type}' => '{target}'
],
]
]
];
$extensionPath = 'custom/application/Ext/FilterOperatorMap/filter_operator_map.ext.php';
if (file_exists($extensionPath)) {
include($extensionPath);
}

View file

@ -0,0 +1,78 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../SaveHandlers/BeanSaveHandlerInterface.php';
require_once __DIR__ . '/LineItemsSaveHandlers.php';
class BeanLineItemSaveHandler implements BeanSaveHandlerInterface
{
/**
* @inheritDoc
*/
public function getModule(): string
{
return 'default';
}
/**
* @inheritDoc
*/
public function save(SugarBean $bean): void
{
$module = $bean->module_name ?? '';
if ($module === '') {
return;
}
$registry = LineItemsSaveHandlers::getInstance();
/** @var SugarBean[][] */
$lineItemFields = $bean->line_item_entries ?? [];
foreach ($lineItemFields as $key => $entries) {
if (empty($entries)) {
continue;
}
$moduleName = $entries[0]->module_name ?? '';
if (empty($moduleName)) {
continue;
}
$handler = $registry->get($module, $moduleName, $key);
if ($handler === null) {
continue;
}
$handler->save($bean, $key);
}
}
}

View file

@ -0,0 +1,182 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/LineItemsSaveHandlerInterface.php';
class DefaultLineItemsSaveHandler implements LineItemsSaveHandlerInterface
{
/**
* @inheritDoc
*/
public function getModule(): string
{
return 'default';
}
/**
* @inheritDoc
*/
public function getRelateModule(): string
{
return 'default';
}
/**
* @inheritDoc
*/
public function getField(): string
{
return 'all';
}
/**
* @inheritDoc
*/
public function save(SugarBean $bean, string $field): void
{
/** @var SugarBean[] */
$entries = $bean->line_item_entries[$field] ?? [];
if (empty($entries)) {
return;
}
$lineItemDefinition = $bean->field_defs[$field] ?? [];
$removalType = $lineItemDefinition['removal-type'] ?? 'unlink';
$relationship = $lineItemDefinition['relationship'] ?? '';
$joinFieldsDefinitions = $this->getJoinFieldDefinitions($bean, $relationship);
if ($relationship === '' || !$bean->load_relationship($relationship)) {
return;
}
foreach ($entries as $entry) {
if (empty($entry)) {
continue;
}
if ($entry->deleted) {
$this->remove($bean, $entry, $relationship, $removalType);
continue;
}
$this->add($bean, $entry, $relationship, $joinFieldsDefinitions);
}
}
/**
* Remove Line Item
* @param SugarBean $bean
* @param SugarBean $entry
* @param string $relationship
* @param string $removalType
*/
protected function remove(SugarBean $bean, SugarBean $entry, string $relationship, string $removalType): void
{
if ($removalType === 'delete') {
$entry->mark_deleted($entry->id);
return;
}
/** @var Link2 $link */
$link = $bean->$relationship;
$link->remove([$entry]);
}
/**
* Add line item
* @param SugarBean $bean
* @param SugarBean $entry
* @param string $relationship
* @param array $joinFieldsDefinitions
*/
protected function add(SugarBean $bean, SugarBean $entry, string $relationship, array $joinFieldsDefinitions): void
{
$joinFields = $this->getJoinFields($bean, $joinFieldsDefinitions);
/** @var Link2 $link */
$link = $bean->$relationship;
$link->add([$entry], $joinFields);
}
/**
* Get join fields definitions
* @param SugarBean $bean
* @param string $relationship
* @return array
*/
protected function getJoinFieldDefinitions(SugarBean $bean, string $relationship): array
{
if (empty($bean->field_defs)) {
return [];
}
$joinFields = [];
foreach ($bean->field_defs as $definition) {
$fieldRelationship = $definition['relationship'] ?? '';
$isJoinField = $definition['join-field'] ?? false;
if ($fieldRelationship === $relationship && $isJoinField) {
$joinFields[] = $definition;
}
}
return $joinFields;
}
/**
* Get join fields
* @param SugarBean|null $bean
* @param array $definitions
* @return array
*/
protected function getJoinFields(?SugarBean $bean, array $definitions): array
{
if ($bean === null || empty($definitions)) {
return [];
}
$joinFields = [];
foreach ($definitions as $definition) {
$name = $definition['name'] ?? '';
if ($name === '') {
continue;
}
$joinFields[$name] = $bean->$name;
}
return $joinFields;
}
}

View file

@ -0,0 +1,150 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/LineItemsSaveHandlerInterface.php';
class EmailAddressLineItemsSaveHandler implements LineItemsSaveHandlerInterface
{
public const MODULE = 'EmailAddresses';
/**
* @inheritDoc
*/
public function getModule(): string
{
return 'default';
}
/**
* @inheritDoc
*/
public function getRelateModule(): string
{
return self::MODULE;
}
/**
* @inheritDoc
*/
public function getField(): string
{
return 'all';
}
/**
* @inheritDoc
*/
public function save(SugarBean $bean, string $field): void
{
/** @var SugarBean[] */
$entries = $bean->line_item_entries[$field] ?? [];
/** @var SugarEmailAddress $emailAddress */
$emailAddress = $bean->emailAddress ?? null;
if (empty($entries) || $emailAddress === null) {
return;
}
$emailAddress->addresses = [];
foreach ($entries as $entry) {
if (empty($entry)) {
continue;
}
if ($entry->deleted) {
$this->remove($bean, $entry, 'unlink');
continue;
}
$this->add($bean, $entry);
}
$emailAddress->saveEmail(
$bean->id,
$bean->module_dir,
'',
'',
'',
'',
'',
$bean->in_workflow
);
}
/**
* Remove Line Item
* @param SugarBean $bean
* @param SugarBean $entry
* @param string $removalType
*/
protected function remove(SugarBean $bean, SugarBean $entry, string $removalType): void
{
if (empty($entry->id)) {
return;
}
if ($removalType === 'delete') {
$entry->mark_deleted($entry->id);
}
}
/**
* Add line item
* @param SugarBean $bean
* @param SugarBean $entry
*/
protected function add(SugarBean $bean, SugarBean $entry): void
{
/** @var EmailAddress $address */
$address = $entry;
/** @var SugarEmailAddress $emailAddress */
$emailAddress = $bean->emailAddress;
$emailAddress->addAddress(
$address->email_address ?? '',
$this->isTrue($address->primary_address ?? false),
$this->isTrue($address->reply_to_address ?? false),
$this->isTrue($address->invalid_email ?? false),
$this->isTrue($address->opt_out ?? false),
$address->id ?? null,
$address->confirm_opt_in ?? null
);
}
/**
* @param $value
* @return bool
*/
protected function isTrue($value): bool
{
return in_array($value, [true, 'true', '1', 1], true);
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
interface LineItemsSaveHandlerInterface
{
/**
* Get Module
* @return string
*/
public function getModule(): string;
/**
* Get Relate Module
* @return string
*/
public function getRelateModule(): string;
/**
* Get field
* @return string
*/
public function getField(): string;
/**
* @param SugarBean $bean
* @param string $field
*/
public function save(SugarBean $bean, string $field): void ;
}

View file

@ -0,0 +1,110 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/LineItemsSaveHandlerInterface.php';
require_once __DIR__ . '/DefaultLineItemsSaveHandler.php';
require_once __DIR__ . '/EmailAddressLineItemsSaveHandler.php';
class LineItemsSaveHandlers
{
/**
* @var LineItemsSaveHandlerInterface[][]
*/
protected $registry = [];
/**
* @var LineItemsSaveHandlers
*/
private static $instance;
/**
* LineItemsSaveHandlers constructor.
* Singleton
*/
private function __construct()
{
$this->add(new DefaultLineItemsSaveHandler());
$this->add(new EmailAddressLineItemsSaveHandler());
}
/**
* @return LineItemsSaveHandlers
*/
public static function getInstance(): LineItemsSaveHandlers
{
if (empty(self::$instance)) {
self::$instance = new LineItemsSaveHandlers();
}
return self::$instance;
}
/**
* Add save handler
* @param LineItemsSaveHandlerInterface $handler
*/
public function add(LineItemsSaveHandlerInterface $handler): void
{
$module = $handler->getModule() ?? 'default';
$field = $handler->getField() ?? 'all';
$relateModule = $handler->getRelateModule() ?? '';
if ($relateModule === '') {
return;
}
$moduleHandlers = $this->registry[$module] ?? $this->registry['default'] ?? [];
$relateModuleHandlers = $moduleHandlers[$relateModule] ?? [];
$relateModuleHandlers[$field] = $handler;
$moduleHandlers[$relateModule] = $relateModuleHandlers;
$this->registry[$module] = $moduleHandlers;
}
/**
* Get save handler
* @param string $module
* @param string $relateModule
* @param string $field
* @return LineItemsSaveHandlerInterface|null
*/
public function get(string $module, string $relateModule, string $field): ?LineItemsSaveHandlerInterface
{
if (!$module || !$field) {
return null;
}
$handlers = $this->registry[$module] ?? $this->registry['default'] ?? [];
$moduleHandlers = $handlers[$relateModule] ?? null;
if (empty($moduleHandlers)) {
return null;
}
return $moduleHandlers[$field] ?? $moduleHandlers['all'] ?? null;
}
}

View file

@ -145,7 +145,7 @@ class ListViewDataPort extends ListViewData
$this->enforceAssignedUserId($temp); $this->enforceAssignedUserId($temp);
$this->addTagInfo($id_field, $idIndex, $row, $dataIndex, $temp, $pageData); $this->addTagInfo($id_field, $idIndex, $row, $dataIndex, $temp, $pageData);
$data[$dataIndex] = $this->apiBeanMapper->toArray($temp); $data[$dataIndex] = $this->apiBeanMapper->toApi($temp);
$this->addACLInfo($temp, $pageData, $dataIndex); $this->addACLInfo($temp, $pageData, $dataIndex);
} }

View file

@ -0,0 +1,41 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
interface BeanSaveHandlerInterface
{
/**
* Get Module
* @return string
*/
public function getModule(): string;
/**
* @param SugarBean $bean
*/
public function save(SugarBean $bean): void;
}

View file

@ -0,0 +1,135 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/BeanSaveHandlerInterface.php';
require_once __DIR__ . '/../LineItems/BeanLineItemSaveHandler.php';
class BeanSaveHandlers
{
public const TYPE_BEFORE = 'before';
public const TYPE_AFTER = 'after';
public const MODULE_DEFAULT = 'default';
/**
* @var BeanSaveHandlerInterface[][]
*/
protected $beforeSaveRegistry = [];
/**
* @var BeanSaveHandlerInterface[][]
*/
protected $afterSaveRegistry = [];
/**
* @var BeanSaveHandlers
*/
private static $instance;
/**
* BeanSaveHandlers constructor.
* Singleton
*/
private function __construct()
{
$this->add(self::TYPE_BEFORE, new BeanLineItemSaveHandler());
}
/**
* @return BeanSaveHandlers
*/
public static function getInstance(): BeanSaveHandlers
{
if (empty(self::$instance)) {
self::$instance = new BeanSaveHandlers();
}
return self::$instance;
}
/**
* Add save handler
* @param string $type
* @param BeanSaveHandlerInterface $handler
*/
public function add(string $type, BeanSaveHandlerInterface $handler): void
{
if ($type !== self::TYPE_BEFORE && $type !== self::TYPE_AFTER) {
return;
}
$registry = $this->getRegistry($type);
$module = $handler->getModule() ?? self::MODULE_DEFAULT;
$moduleHandlers = $registry[$module] ?? [];
$moduleHandlers[] = $handler;
$registry[$module] = $moduleHandlers;
$this->setRegistry($type, $registry);
}
/**
* Get save handler
* @param string $module
* @param string $type
* @return BeanSaveHandlerInterface[]
*/
public function get(string $module, string $type): array
{
if (!$module || ($type !== self::TYPE_BEFORE && $type !== self::TYPE_AFTER)) {
return [];
}
$registry = $this->getRegistry($type);
return $registry[$module] ?? $registry['default'] ?? [];
}
/**
* Get Registry
* @param string $type
* @return BeanSaveHandlerInterface[][]
*/
protected function getRegistry(string $type): array
{
return $type === self::TYPE_BEFORE ? $this->beforeSaveRegistry : $this->afterSaveRegistry;
}
/**
* Set Registry
* @param string $type
* @param BeanSaveHandlerInterface[][] $registry
*/
protected function setRegistry(string $type, array $registry): void
{
if ($type === self::TYPE_BEFORE) {
$this->beforeSaveRegistry = $registry;
}
$this->afterSaveRegistry = $registry;
}
}

View file

@ -0,0 +1,88 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/BeanSaveHandlers.php';
class BeanSaveHandlersManager
{
public const TYPE_BEFORE = BeanSaveHandlers::TYPE_BEFORE;
public const TYPE_AFTER = BeanSaveHandlers::TYPE_AFTER;
/**
* @var BeanSaveHandlersManager
*/
private static $instance;
/**
* BeanSaveHandlersManager constructor.
* Singleton
*/
private function __construct()
{
}
/**
* @return BeanSaveHandlersManager
*/
public static function getInstance(): BeanSaveHandlersManager
{
if (empty(self::$instance)) {
self::$instance = new BeanSaveHandlersManager();
}
return self::$instance;
}
/**
* Run save handlers
* @param SugarBean $bean
* @param string $type
*/
public function run(SugarBean $bean, string $type): void
{
$module = $bean->module_name ?? '';
if ($module === '') {
return;
}
$handlers = BeanSaveHandlers::getInstance()->get($module, $type);
if (empty($handlers)) {
return;
}
foreach ($handlers as $handler) {
if ($handler === null) {
continue;
}
$handler->save($bean);
}
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
/**
* This Class handles/controls the User Access against the available ACL privileges to the user
*
* Class UserACLService
* Port of ACLController.php
*/
class UserACLService
{
/**
* Check User ACL against the following parameters
* @param string $routeModule
* @param string $routeURL
* @param string $routeAction
* @return array with feedback
*/
public function run(string $routeModule, string $routeURL, string $routeAction): array
{
if (empty($routeModule)) {
return [
'status' => false,
'message' => 'LBL_MODULE_NOT_FOUND'
];
}
if (!$routeURL && !$this->handleAclRoles($routeModule, $routeAction)) {
return [
'status' => false,
'message' => 'ERR_UNAUTHORIZED_PAGE_ACCESS_TO_HOME_PAGE'
];
}
if (!$this->handleAclRoles($routeModule, $routeAction)) {
return [
'status' => false,
'message' => 'ERR_UNAUTHORIZED_PAGE_ACCESS'
];
}
return [
'status' => true,
'message' => ''
];
}
/**
* Handle User Acl roles
* @param string $beanName
* @param string $routeAction
* @return bool
*/
protected function handleAclRoles(string $beanName, string $routeAction): bool
{
$routeAction = $routeAction ?: 'view';
return ACLController::checkAccess($beanName, $routeAction, true, 'module', true);
}
}

View file

@ -0,0 +1,507 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
require_once __DIR__ . '/../../../MassUpdate.php';
require_once __DIR__ . '/../../Services/DateTime/DateFormatService.php';
/**
* Class MassUpdatePort
* Port of SugarController::action_massupdate and MassUpdate
*/
class MassUpdatePort extends MassUpdate
{
/**
* @var SugarBean
*/
public $sugarbean;
/**
* @var DateFormatService
*/
protected $dateFormatService;
public function __construct()
{
$this->dateFormatService = new DateFormatService();
}
/**
* @param array $inputs
* @return array
*/
public function run(array $inputs): array
{
$seed = BeanFactory::newBean($inputs['module']);
$this->setSugarBean($seed);
if (!$this->sugarbean->ACLAccess('save')) {
return [
'success' => false,
'messages' => ['LBL_BULK_ACTION_MASS_UPDATE_NO_ACLS'],
'debug' => ["No acls to save record for module '" . $inputs['module'] . "'"]
];
}
if (empty($this->sugarbean)) {
return [
'success' => false,
'messages' => ['LBL_UNEXPECTED_ERROR'],
'debug' => ["Bean not loaded properly '" . $inputs['module'] . "'"]
];
}
// Taken from SugarController::action_massupdate
set_time_limit(0);
DBManagerFactory::getInstance()::setQueryLimit(0);
return $this->runMassUpdate($inputs);
}
/**
* Executes the massupdate form
* @param array $inputs to display in the popup window
* @return array feedback
*/
public function runMassUpdate(array $inputs): array
{
require_once __DIR__ . '/../../../formbase.php';
global $current_user, $db, $disable_date_format;
$this->parseInputs($inputs);
$feedback = [
'success' => true,
'messages' => [],
'debug' => [],
'updated' => []
];
$updateRecords = [];
//We need to disable_date_format so that date values for the beans remain in database format
//notice we make this call after the above section since the calls to TimeDate class there could wind up
//making it's way to the UserPreferences objects in which case we want to enable the global date formatting
//to correctly retrieve the user's date format preferences
$old_value = $disable_date_format;
$disable_date_format = true;
$this->setIdsToUpdate($inputs, $db);
if (!isset($inputs['mass']) || !is_array($inputs['mass'])) {
$feedback['messages'][] = 'LBL_BULK_ACTION_MASS_UPDATE_NO_RECORDS';
$feedback['debug'][] = ['No records to update'];
$feedback['success'] = false;
return $feedback;
}
$count = 0;
foreach ($inputs['mass'] as $id) {
if (empty($id)) {
continue;
}
if (isset($inputs['Delete'])) {
$this->sugarbean->retrieve($id);
if ($this->sugarbean->ACLAccess('Delete')) {
$this->sugarbean->mark_deleted($id);
}
continue;
}
$this->handleContactsSync($inputs, $id, $feedback);
if ($count++ !== 0) {
//Create a new instance to clear values and handle additional updates to bean's 2,3,4...
$className = get_class($this->sugarbean);
$this->sugarbean = new $className();
}
$this->sugarbean->retrieve($id);
if (!$this->sugarbean->ACLAccess('Save')) {
$feedback['debug'][] = "No save acls for '$id'. not updating";
continue;
}
$inputs['record'] = $id;
$newbean = $this->sugarbean;
$check_notify = false;
if (isset($this->sugarbean->assigned_user_id)) {
$old_assigned_user_id = $this->sugarbean->assigned_user_id;
if (!empty($inputs['assigned_user_id'])
&& ($old_assigned_user_id != $inputs['assigned_user_id'])
&& ($inputs['assigned_user_id'] != $current_user->id)
) {
$check_notify = true;
}
}
//Call include/formbase.php, but do not call retrieve again
$this->populateFromInputs($inputs, '', $newbean);
$newbean->save_from_post = false;
if (!isset($inputs['parent_id'])) {
$newbean->parent_type = null;
}
$this->updateDynamicEnums($newbean);
$updateRecords[] = $newbean->id;
$newbean->save($check_notify);
$this->updateEmailAddress($inputs);
}
$disable_date_format = $old_value;
$feedback['updated'] = $updateRecords;
$feedback['messages'] = ['LBL_BULK_ACTION_MASS_UPDATE_PARTIAL_SUCCESS'];
if (count($updateRecords) === count($inputs['mass'])) {
$feedback['messages'] = ['LBL_BULK_ACTION_MASS_UPDATE_SUCCESS'];
}
return $feedback;
}
/**
* @param $inputs
*/
protected function parseInputs(&$inputs): void
{
foreach ($inputs as $field => $value) {
$definition = $this->sugarbean->field_defs[$field] ?? [];
$type = $definition['type'] ?? '';
$customType = $definition['custom_type'] ?? '';
$dbType = $definition['dbType'] ?? '';
if (is_array($value) && empty($value)) {
unset($inputs[$field]);
} elseif ($value === '') {
if ($type === 'radioenum' && isset($inputs[$field])) {
$inputs[$field] = '';
} else {
unset($inputs[$field]);
}
}
if (!is_string($value) || empty($definition)) {
continue;
}
if ($type === 'bool' || $customType === 'bool') {
if (strcmp($value, '2') === 0) {
$inputs[$field] = 0;
}
if (strcmp($dbType, 'varchar') === 0) {
if (strcmp($value, '1') === 0) {
$inputs[$field] = 'on';
}
if (strcmp($value, '2') === 0) {
$inputs[$field] = 'off';
}
}
}
if (
($type === 'radioenum' && isset($inputs[$field]) && $value === '') ||
($type === 'enum' && $value === '__SugarMassUpdateClearField__') // Set to '' if it's an explicit clear
) {
$inputs[$field] = '';
}
if ($type === 'bool') {
$this->checkClearField($field, $value);
}
if ($type === 'date' && !empty($value)) {
$inputs[$field] = $this->dateFormatService->toDBDate($value);
}
if ($type === 'datetime' && !empty($value)) {
$inputs[$field] = $this->dateFormatService->toDBDateTime($value);
}
if ($type === 'datetimecombo' && !empty($value)) {
$inputs[$field] = $this->dateFormatService->toDBDateTime($value);
}
}
}
/**
* Calculate and set upds to update;
* @param array $inputs
* @param DBManager $db
*/
protected function setIdsToUpdate(array &$inputs, DBManager $db): void
{
if (!empty($inputs['uid'])) {
$inputs['mass'] = explode(',', $inputs['uid']);
return;
} // coming from listview
if (isset($inputs['entire']) && empty($inputs['mass'])) {
$order_by = '';
// TODO: define filter array here to optimize the query
// by not joining the unneeded tables
$query = $this->sugarbean->create_new_list_query(
$order_by,
$this->where_clauses,
array(),
array(),
0,
'',
false,
$this,
true,
true
);
$result = $db->query($query, true);
$new_arr = array();
while ($val = $db->fetchByAssoc($result, false)) {
$new_arr[] = $val['id'];
}
$inputs['mass'] = $new_arr;
}
}
/**
* Handle contact sync flag
* @param array $inputs
* @param string $id
* @param array $feedback
*/
protected function handleContactsSync(array $inputs, string $id, array &$feedback): void
{
global $current_user;
if ($this->sugarbean->object_name !== 'Contact' || !isset($inputs['Sync'])) {
return;
}
$this->sugarbean->retrieve($id);
if (!$this->sugarbean->ACLAccess('Save')) {
$feedback['debug'][] = 'No save acls for saving';
}
if ($inputs['Sync']) {
$feedback['debug'][] = 'Sync set to true. Updating sync. saving';
$this->sugarbean->contacts_users_id = $current_user->id;
$this->sugarbean->save(false);
return;
}
$users = $this->sugarbean->users;
if (isset($users)) {
$this->sugarbean->load_relationship('user_sync');
}
$this->sugarbean->contacts_users_id = null;
$this->sugarbean->user_sync->delete($this->sugarbean->id, $current_user->id);
$feedback['debug'][] = "Sync set to false. Deleted user sync. Unset 'contacts_users_id'";
}
/**
* Populating inputs
*
* @param array $inputs of name of fields
* @param string $prefix of name of fields
* @param SugarBean $focus bean
*/
protected function populateFromInputs(array $inputs, string $prefix, SugarBean $focus): void
{
global $current_user, $log;
if (!empty($inputs['assigned_user_id']) &&
($focus->assigned_user_id !== $inputs['assigned_user_id']) &&
($inputs['assigned_user_id'] !== $current_user->id)) {
$GLOBALS['check_notify'] = true;
}
require_once __DIR__ . '/../../../SugarFields/SugarFieldHandler.php';
$sfh = new SugarFieldHandler();
foreach ($focus->field_defs as $field => $def) {
if ($field === 'id' && !empty($focus->id)) {
// Don't try and overwrite the ID
continue;
}
$type = !empty($def['custom_type']) ? $def['custom_type'] : $def['type'];
$sf = $sfh::getSugarField($type);
if ($sf !== null) {
$sf->save($focus, $inputs, $field, $def, $prefix);
} else {
$log->fatal("Field '$field' does not have a SugarField handler");
}
}
foreach ($focus->additional_column_fields as $field) {
$key = $prefix . $field;
if (isset($inputs[$key])) {
$value = $inputs[$key];
$focus->$field = $value;
}
}
}
/**
* Update dynamic enums
* @param SugarBean $newbean
*/
protected function updateDynamicEnums(SugarBean $newbean): void
{
global $app_list_strings;
// Mass update the cases, and change the state value from open to close,
// Status value can still display New, Assigned, Pending Input (even though it should not)
foreach ($newbean->field_name_map as $field_name) {
$type = $field_name['type'] ?? '';
$parentenum = $field_name['parentenum'] ?? '';
if ($type !== 'dynamicenum' || $parentenum === '') {
continue;
}
$parentenum_name = $field_name['parentenum'];
// Updated parent field value.
$parentenum_value = $newbean->$parentenum_name;
$dynamic_field_name = $field_name['name'];
// Dynamic field set value.
[$dynamic_field_value] = explode('_', $newbean->$dynamic_field_name);
if ($parentenum_value !== $dynamic_field_value) {
// Change to the default value of the correct value set.
$defaultValue = '';
foreach ($app_list_strings[$field_name['options']] as $key => $value) {
if (strpos($key, $parentenum_value) === 0) {
$defaultValue = $key;
break;
}
}
$newbean->$dynamic_field_name = $defaultValue;
}
}
}
/**
* Update email address
* @param array $inputs
*/
protected function updateEmailAddress(array $inputs): void
{
// get primary address id
$email_address_id = $this->getPrimaryEmailAddressId();
if (empty($email_address_id)) {
return;
}
[$setOptOutPrimaryEmailAddress, $optout_flag_value] = $this->getOptout($inputs);
/** @var EmailAddress $primaryEmailAddress */
$primaryEmailAddress = BeanFactory::getBean('EmailAddresses', $email_address_id);
if ($setOptOutPrimaryEmailAddress) {
$primaryEmailAddress->opt_out = (bool)$optout_flag_value;
}
[$setOptInPrimaryEmailAddress, $optin_flag_value] = $this->getOptin($inputs);
if ($setOptInPrimaryEmailAddress) {
if ($optin_flag_value === true) {
$primaryEmailAddress->OptIn();
} else {
$primaryEmailAddress->resetOptIn();
}
}
$primaryEmailAddress->save();
}
/**
* Get primary address id
* @return string|null
*/
protected function getPrimaryEmailAddressId(): ?string
{
$emailAddressId = '';
$emailAddress = $this->sugarbean->emailAddress ?? null;
if (!empty($emailAddress)) {
foreach ($this->sugarbean->emailAddress->addresses as $emailAddressRow) {
if ($emailAddressRow['primary_address'] === '1') {
$emailAddressId = $emailAddressRow['email_address_id'];
break;
}
}
}
return $emailAddressId;
}
/**
* Get optout info
* @param array $inputs
* @return array
*/
protected function getOptout(array $inputs): array
{
$setOptOutPrimaryEmailAddress = false;
$optout_flag_value = false;
if (!empty($inputs['optout_primary'])) {
$setOptOutPrimaryEmailAddress = true;
$optout_flag_value = true;
}
return [$setOptOutPrimaryEmailAddress, $optout_flag_value];
}
/**
* Get optin info
* @param array $inputs
* @return array
*/
protected function getOptin(array $inputs): array
{
$setOptInPrimaryEmailAddress = false;
$optin_flag_value = false;
if (!empty($inputs['optin_primary'])) {
$setOptInPrimaryEmailAddress = true;
$optin_flag_value = true;
}
return [$setOptInPrimaryEmailAddress, $optin_flag_value];
}
}

View file

@ -0,0 +1,123 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
/**
* Class AddContactsToTargetListService
*/
class AddContactsToTargetListService
{
/**
* Add contacts to target list
* @param string $baseModule - module name
* @param array $baseIds - selected record ids
* @param string $modalModule - modal module name
* @param string $modalId - modal selected record id
* @return array with feedback
*/
public function run(
string $baseModule,
array $baseIds,
string $modalModule,
string $modalId
): array
{
global $beanList;
if (empty($baseIds) || empty($modalModule) || empty($modalId)) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
if (empty($baseModule) || empty($beanList[$baseModule])) {
return [
'success' => false,
'message' => 'LBL_MODULE_NOT_FOUND'
];
}
$bean = BeanFactory::newBean($baseModule);
if (!$bean) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
$result = $this->linkContactsToTargetList($bean, $baseIds, $modalModule, $modalId);
if ($result === false) {
return [
'success' => false,
'message' => 'LBL_ADD_CONTACTS_TO_TARGET_LIST_FAILED'
];
}
return [
'success' => true,
'message' => 'LBL_ADD_CONTACTS_TO_TARGET_LIST_SUCCESS'
];
}
/**
* Link contacts to target list
* @param SugarBean|null $bean - bean object of base module
* @param array $baseIds
* @param string $modalModule
* @param string $modalId
* @return bool
*/
protected function linkContactsToTargetList(
SugarBean $bean,
array $baseIds,
string $modalModule,
string $modalId
): bool
{
$result = true;
$sanitizedModuleName = str_replace('-', '_', $modalModule);
foreach ($baseIds as $id) {
$bean->retrieve($id);
$contacts = $bean->get_linked_beans('contacts', 'Contacts3');
foreach ($contacts as $contact) {
$relationship = $contact->load_relationship($sanitizedModuleName);
if (!$relationship) {
return false;
}
$result = $contact->{$sanitizedModuleName}->add($modalId);
$contact->save();
}
}
return $result;
}
}

View file

@ -0,0 +1,129 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
/**
* Class AddRecordsToTargetListService
*/
class AddRecordsToTargetListService
{
/**
* Add records to target list
* @param string $baseModule - module name
* @param array $baseIds - selected record ids
* @param string $modalModule - modal module name
* @param string $modalId - modal selected record id
* @return array with feedback
*/
public function run(
string $baseModule,
array $baseIds,
string $modalModule,
string $modalId
): array
{
global $beanList;
if (empty($baseIds) || empty($modalModule) || empty($modalId)) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
if (empty($baseModule) || empty($beanList[$baseModule])) {
return [
'success' => false,
'message' => 'LBL_MODULE_NOT_FOUND'
];
}
$bean = BeanFactory::newBean($baseModule);
if (!$bean) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
$result = $this->linkRecordsToTargetList($bean, $baseIds, $modalModule, $modalId);
if ($result === false) {
return [
'success' => false,
'message' => 'LBL_ADD_RECORDS_TO_TARGET_LIST_FAILED'
];
}
return [
'success' => true,
'message' => 'LBL_ADD_RECORDS_TO_TARGET_LIST_SUCCESS'
];
}
/**
* Link records to target list
* @param SugarBean|null $bean - bean object of base module
* @param array $beanIds
* @param string $modalModule
* @param string $modalId
* @return bool
*/
protected function linkRecordsToTargetList(
SugarBean $bean,
array $beanIds,
string $modalModule,
string $modalId
): bool
{
$result = true;
$relationship = '';
foreach ($bean->get_linked_fields() as $field => $def) {
if ($bean->load_relationship($field) && $bean->$field->getRelatedModuleName() === $modalModule) {
$relationship = $field;
break;
}
}
if (empty($relationship)) {
return false;
}
foreach ($beanIds as $id) {
$bean->retrieve($id);
$bean->load_relationship($relationship);
$result = $bean->{$relationship}->add($modalId);
$bean->save();
}
return $result;
}
}

View file

@ -0,0 +1,120 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
/**
* Class LinkService
* Port of include/generic/Save2.php
* Accessing the above file directly is not possible
*/
class LinkService
{
/**
* Link related records for link field
* @param string $module
* @param string $record
* @param string $linkField
* @param string $linkedId
* @return array with feedback
*/
public function run(string $module, string $record, string $linkField, string $linkedId): array
{
global $beanList;
//TODO handle special scenarios that are handled by Save2.php for Campaigns, target lists, documents etc
if (empty($record) || empty($linkField) || empty($linkedId)) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
if (empty($module) || empty($beanList[$module])) {
return [
'success' => false,
'message' => 'LBL_MODULE_NOT_FOUND'
];
}
$bean = BeanFactory::newBean($module);
if (!$bean) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
$bean = $bean->retrieve($record);
if (!$bean) {
return [
'success' => false,
'message' => 'LBL_RELATIONSHIP_LOAD_ERROR'
];
}
if (!$bean->load_relationship($linkField)) {
return [
'success' => false,
'message' => 'LBL_RELATIONSHIP_LOAD_ERROR'
];
}
$result = $this->link($bean, $linkField, $linkedId);
if ($result === false) {
return [
'success' => false,
'message' => 'LBL_LINK_RELATIONSHIP_FAILED'
];
}
return [
'success' => true,
'message' => 'LBL_LINK_RELATIONSHIP_SUCCESS'
];
}
/**
* Link record for relationship link
* @param SugarBean|null $bean
* @param string $linkField
* @param $linkedId
* @return bool
*/
protected function link(SugarBean $bean, string $linkField, string $linkedId): bool
{
$result = $bean->$linkField->add($linkedId);
$bean->save();
return $result === true;
}
}

View file

@ -0,0 +1,265 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
/**
* Class UnlinkService
* Port of include/generic/DeleteRelationship.php
* Accessing the above file directly is not possible
*/
class UnlinkService
{
/**
* Unlink related records for link field
* @param string $module
* @param string $record
* @param string $linkField
* @param string $linkedId
* @return array with feedback
*/
public function run(string $module, string $record, string $linkField, string $linkedId): array
{
global $beanList;
if (empty($record) || empty($linkField) || empty($linkedId)) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
if (empty($module) || empty($beanList[$module])) {
return [
'success' => false,
'message' => 'LBL_MODULE_NOT_FOUND'
];
}
$beanName = $beanList[$module];
$bean = BeanFactory::newBean($module);
if (!$bean) {
return [
'success' => false,
'message' => 'LBL_RECORD_NOT_FOUND'
];
}
$bean = $bean->retrieve($record);
if (!$bean) {
return [
'success' => false,
'message' => 'LBL_RELATIONSHIP_LOAD_ERROR'
];
}
if (!$this->handleAclRoles($linkField, $beanName)) {
return [
'success' => false,
'message' => 'LBL_ACCESS_DENIED'
];
}
if (!$bean->load_relationship($linkField)) {
return [
'success' => false,
'message' => 'LBL_RELATIONSHIP_LOAD_ERROR'
];
}
$ids = $bean->$linkField->get();
if (!in_array($linkedId, $ids, true)) {
return [
'success' => false,
'message' => 'LBL_NOT_LINKED'
];
}
$result = $this->unlink($bean, $linkField, $record, $linkedId);
if ($result === false) {
return [
'success' => false,
'message' => 'LBL_UNLINK_RELATIONSHIP_FAILED'
];
}
$this->handleCampaignProspectLists($bean, $beanName, $linkField, $record, $linkedId);
$this->handleAccountsLeads($bean, $beanName, $record, $linkField, $linkedId);
$this->handleMeetings($bean, $beanName, $record, $linkedId);
$this->handleUsersEapm($beanName, $linkField, $linkedId);
return [
'success' => true,
'message' => 'LBL_UNLINK_RELATIONSHIP_SUCCESS'
];
}
/**
* Unlink records for relationship link
* @param SugarBean|null $bean
* @param string $linkField
* @param $record
* @param $linkedId
* @return bool
*/
protected function unlink(SugarBean $bean, string $linkField, string $record, string $linkedId): bool
{
if ($bean->$linkField->_relationship->relationship_name === 'quotes_contacts_shipto') {
unset($bean->$linkField->_relationship->relationship_role_column);
}
return $bean->$linkField->delete($record, $linkedId);
}
/**
* Handle campaigns prospects special scenario
* @param SugarBean $bean
* @param $beanName
* @param string $linkField
* @param $record
* @param $linkedId
*/
protected function handleCampaignProspectLists(
SugarBean $bean,
$beanName,
string $linkField,
$record,
$linkedId
): void {
if ($beanName !== 'Campaign' || $linkField !== 'prospectlists') {
return;
}
$query = "SELECT email_marketing_prospect_lists.id from email_marketing_prospect_lists ";
$query .= " left join email_marketing on email_marketing.id=email_marketing_prospect_lists.email_marketing_id";
$query .= " where email_marketing.campaign_id='$record'";
$query .= " and email_marketing_prospect_lists.prospect_list_id='$linkedId'";
$result = $bean->db->query($query);
while (($row = $bean->db->fetchByAssoc($result)) != null) {
$del_query = " update email_marketing_prospect_lists set email_marketing_prospect_lists.deleted=1, email_marketing_prospect_lists.date_modified=" . $bean->db->convert(
"'" . TimeDate::getInstance()->nowDb() . "'",
'datetime'
);
$del_query .= " WHERE email_marketing_prospect_lists.id='{$row['id']}'";
$bean->db->query($del_query);
}
$bean->db->query($query);
}
/**
* Handle Accounts Leads special scenario
* @param SugarBean $bean
* @param string $beanName
* @param string $record
* @param string $linkField
* @param string $linkedId
*/
protected function handleAccountsLeads(
SugarBean $bean,
string $beanName,
string $record,
string $linkField,
string $linkedId
): void {
if ($beanName !== "Account" || $linkField !== 'leads') {
return;
}
// for Accounts-Leads non-standard relationship, after clearing account_id form Lead's bean, clear also account_name
$bean->retrieve($record);
$lead = BeanFactory::newBean('Leads');
$lead->retrieve($linkedId);
if ($bean->name === $lead->account_name) {
$lead->account_name = '';
}
$lead->save();
unset($lead);
}
/**
* HandleMeetings special scenario
* @param SugarBean $bean
* @param string $beanName
* @param string $record
* @param string $linkedId
*/
protected function handleMeetings(SugarBean $bean, string $beanName, string $record, string $linkedId): void
{
if ($beanName !== "Meeting") {
return;
}
$bean->retrieve($record);
$user = BeanFactory::newBean('Users');
$user->retrieve($linkedId);
//make sure that record exists. we may have a contact on our hands.
if (!empty($user->id) && $bean->update_vcal) {
vCal::cache_sugar_vcal($user);
}
}
/**
* Handle Users / EAPM relationship special scenario
* @param string $beanName
* @param string $linkField
* @param string $linkedId
*/
protected function handleUsersEapm(string $beanName, string $linkField, string $linkedId): void
{
if ($beanName !== "User" || $linkField !== 'eapm') {
return;
}
$eapm = BeanFactory::newBean('EAPM');
$eapm->mark_deleted($linkedId);
}
/**
* Handle Acl roles special scenario
* @param string $linkedField
* @param string $beanName
* @return bool
*/
protected function handleAclRoles(string $linkedField, string $beanName): bool
{
if ($linkedField !== 'aclroles') {
return true;
}
if (!ACLController::checkAccess($beanName, 'edit', true)) {
return false;
}
return true;
}
}

View file

@ -38,26 +38,62 @@ class SubpanelCustomQueryPort
/* @noinspection PhpIncludeInspection */ /* @noinspection PhpIncludeInspection */
require_once 'include/SubPanel/SubPanelDefinitions.php'; require_once 'include/SubPanel/SubPanelDefinitions.php';
$queries = [];
$spd = new SubPanelDefinitions($bean); $spd = new SubPanelDefinitions($bean);
$subpanel_def = $spd->load_subpanel($subpanel); $subpanel_def = $spd->load_subpanel($subpanel);
$subpanel_list = [];
if (method_exists($subpanel_def, 'isCollection')) { if (method_exists($subpanel_def, 'isCollection')) {
if ($subpanel_def->isCollection()) {
if ($subpanel_def->load_sub_subpanels() === false) { if (method_exists($subpanel_def, 'isDatasourceFunction')
$subpanel_list = []; && $subpanel_def->isDatasourceFunction()) {
$shortcut_function_name = $subpanel_def->get_data_source_name();
$parameters = $subpanel_def->get_function_parameters();
if (!empty($parameters)) {
//if the import file function is set, then import the file to call the custom function from
if (is_array($parameters) && isset($parameters['import_function_file'])) {
//this call may happen multiple times, so only require if function does not exist
if (!function_exists($shortcut_function_name)) {
require_once($parameters['import_function_file']);
}
//call function from required file
$func_query = $shortcut_function_name($parameters);
} else {
//call function from parent bean
$func_query = $bean->$shortcut_function_name($parameters);
}
} else { } else {
$subpanel_list = $subpanel_def->sub_subpanels; $func_query = $bean->$shortcut_function_name();
} }
$countAlias = 'value';
$countQuery = $bean->create_list_count_query($func_query, $countAlias);
$queries['isDatasourceFunction'] = [
'query' => $func_query,
'countQuery' => $countQuery
];
} else { } else {
$subpanel_list[] = $subpanel_def; $subpanel_list = [];
if ($subpanel_def->isCollection()) {
if ($subpanel_def->load_sub_subpanels() === false) {
$subpanel_list = [];
} else {
$subpanel_list = $subpanel_def->sub_subpanels;
}
} else {
$subpanel_list[] = $subpanel_def;
}
$queries = SugarBean::getUnionRelatedListQueries($subpanel_list, $subpanel_def, $bean, '');
} }
} else { } else {
$GLOBALS['log']->fatal('Subpanel definition should be an aSubPanel'); $GLOBALS['log']->fatal('Subpanel definition should be an aSubPanel');
} }
return $queries;
return SugarBean::getUnionRelatedListQueries($subpanel_list, $subpanel_def, $bean, '');
} }
/** /**

View file

@ -58,7 +58,8 @@ class SubpanelDataPort
int $limit = -1, int $limit = -1,
string $orderBy = '', string $orderBy = '',
string $sortOrder = '' string $sortOrder = ''
): array { ): array
{
/* @noinspection PhpIncludeInspection */ /* @noinspection PhpIncludeInspection */
require_once 'include/SubPanel/SubPanelDefinitions.php'; require_once 'include/SubPanel/SubPanelDefinitions.php';
@ -88,7 +89,7 @@ class SubpanelDataPort
$mappedBeans = []; $mappedBeans = [];
foreach ($beanList as $beanData) { foreach ($beanList as $beanData) {
$mappedBeans[] = $this->apiBeanMapper->toArray($beanData); $mappedBeans[] = $this->apiBeanMapper->toApi($beanData);
} }
$row_count = $response['row_count']; $row_count = $response['row_count'];
@ -124,4 +125,53 @@ class SubpanelDataPort
]; ];
} }
/**
* @param SugarBean $bean
* @param string $subpanel
* @param int $offset
* @param int $limit
* @param string $orderBy
* @param string $sortOrder
* @param array $selectColumns
* @return array|null
* @noinspection NullPointerExceptionInspection
*/
public function fetchFinalQuery(
SugarBean $bean,
string $subpanel = '',
int $offset = -1,
int $limit = -1,
string $orderBy = '',
string $sortOrder = '',
array $selectColumns = []
): ?array
{
/* @noinspection PhpIncludeInspection */
require_once 'include/SubPanel/SubPanelDefinitions.php';
$spd = new SubPanelDefinitions($bean);
$aSubPanelObject = $spd->load_subpanel($subpanel);
try {
$response = SugarBean::get_union_related_list_query_params(
$bean,
$orderBy,
$sortOrder,
'',
$offset,
-1,
$limit,
0,
$aSubPanelObject,
$selectColumns
);
return $response;
} catch (Exception $ex) {
LoggerManager::getLogger()->fatal('[' . __METHOD__ . "] . {$ex->getMessage()}");
return null;
}
}
} }

View file

@ -0,0 +1,774 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SALESAGILITY, SALESAGILITY DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\portability\System\Upgrade;
use Administration;
use BeanFactory;
use DBManager;
use DBManagerFactory;
use LoggerManager;
use RepairAndClear;
use SugarBean;
use Throwable;
use TrackerManager;
use UpgradeHistory;
if (!defined('sugarEntry')) {
define('sugarEntry', true);
}
class PostUpgrade
{
/**
* @var string[]
*/
protected $debug = [];
/**
* Run post upgrade steps
* @return array
*/
public function run(): array
{
$this->debug = [];
ini_set('memory_limit', -1);
set_time_limit(0);
global $sugar_config;
global $ACLActions, $beanList, $beanFiles;
global $dictionary;
global $cwd;
$GLOBALS['log'] = LoggerManager::getLogger();
$cwd = getcwd(); // default to current, assumed to be in a valid SuiteCRM root dir.
require_once __DIR__ . '/../../../../modules/UpgradeWizard/uw_utils.php';
require_once __DIR__ . '/../../../../include/utils/php_zip_utils.php';
require_once __DIR__ . '/../../../../include/utils/sugar_file_utils.php';
require_once __DIR__ . '/../../../../include/SugarObjects/SugarConfig.php';
include __DIR__ . '/../../../../modules/ACLActions/actiondefs.php';
include __DIR__ . '/../../../../include/modules.php';
require __DIR__ . '/../../../../sugar_version.php';
require __DIR__ . '/../../../../config.php';
try {
ob_start();
$_SESSION['schema_change'] = 'sugar'; // we force-run all SQL
$_SESSION['silent_upgrade'] = true;
$_SESSION['step'] = 'silent'; // flag to NOT try redirect to 4.5.x upgrade wizard
$_REQUEST['silent'] = true;
$_REQUEST = [];
$_REQUEST['addTaskReminder'] = 'remind';
$this->checkConfigForPermissions();
$this->checkLoggerSettings();
$this->checkLeadConversionSettings();
$this->checkResourceSettings();
if (!write_array_to_file('sugar_config', $sugar_config, 'config.php')) {
$this->log('*** ERROR: could not write config.php! - upgrade will fail!');
$errors[] = 'Could not write config.php!';
}
//TODO call viewdefs merge
//$this->registerUpgrade($errors, $path, $install_file, $zip_from_dir, $manifest, $suitecrm_version, $db);
$this->cleanModulesCache();
$this->cleanThemeCache();
//ob_start();
//@$this->createMissingRels();
//ob_end_clean();
$this->deleteCache();
//$this->addReminders($errors, $skippedFiles, $path);
$this->setAdminWizardSetting();
$errors = [];
$this->injectLanguageStrings();
$this->loadAdminUser();
$this->pauseTrackers();
$this->upgradeRelationships();
$this->upgradeUserPreferences();
$this->clearThemeCache();
$this->minifyJS();
$this->deleteCache();
$this->repairDatabase($beanFiles);
$this->rebuildRelationships();
$this->mergeConfigSettings('');
$this->upgradeConnectors();
$this->rebuildSprites();
//Don't think this runs
//$this->upgradeHistoryTable($sugar_version);
$this->clearLanguageCache();
$this->rebuildHTAccess();
$phpErrors = ob_get_clean();
$this->log("Potential PHP generated error messages: {$phpErrors}");
} catch (Throwable $t) {
$response = [
'success' => false,
'messages' => [
'Unexpected error running Legacy Post Upgrade'
],
'debug' => $this->debug
];
$this->debug = [];
return $response;
}
if (count($errors) > 0) {
foreach ($errors as $error) {
$this->log("Upgrade ERROR: {$error}");
}
$response = [
'success' => false,
'messages' => [
'Post Upgrade process complete with errors. Please check the upgrade log'
],
'debug' => $this->debug
];
$this->debug = [];
return $response;
}
$this->log("Upgrade completed successfully.");
$response = [
'success' => true,
'messages' => [
'Post Upgrade process complete'
],
'debug' => $this->debug
];
$this->debug = [];
return $response;
}
/**
* Check permissions
*/
protected function checkConfigForPermissions(): void
{
$this->log('begin check default permissions .');
global $sugar_config;
if (!isset($sugar_config['default_permissions'])) {
$sugar_config['default_permissions'] = [
'dir_mode' => 02770,
'file_mode' => 0660,
'user' => '',
'group' => '',
];
ksort($sugar_config);
if (is_writable('config.php')) {
write_array_to_file("sugar_config", $sugar_config, 'config.php');
}
}
$this->log('end check default permissions .');
}
/**
* @param string $message
*/
protected function log(string $message): void
{
logThis($message, __DIR__ . '/../../../../../../logs/upgrade.log');
$this->debug[] = $message;
}
/**
* Check logger settings
*/
protected function checkLoggerSettings(): void
{
$this->log('begin check logger settings .');
global $sugar_config;
if (!isset($sugar_config['logger'])) {
$sugar_config['logger'] = [
'level' => 'fatal',
'file' => [
'ext' => '.log',
'name' => 'suitecrm',
'dateFormat' => '%c',
'maxSize' => '10MB',
'maxLogs' => 10,
'suffix' => '', // bug51583, change default suffix to blank for backwards comptability
],
];
ksort($sugar_config);
if (is_writable('config.php')) {
write_array_to_file("sugar_config", $sugar_config, 'config.php');
}
}
$this->log('begin check logger settings .');
}
/**
* Check lead conversion settings
*/
protected function checkLeadConversionSettings(): void
{
$this->log('begin check lead conversion settings .');
global $sugar_config;
if (!isset($sugar_config['lead_conv_activity_opt'])) {
$sugar_config['lead_conv_activity_opt'] = 'copy';
ksort($sugar_config);
if (is_writable('config.php')) {
write_array_to_file('sugar_config', $sugar_config, 'config.php');
}
}
$this->log('end check lead conversion settings .');
}
/**
* Check resource settings
*/
protected function checkResourceSettings(): void
{
$this->log('begin check resource settings .');
global $sugar_config;
if (!isset($sugar_config['resource_management'])) {
$sugar_config['resource_management'] = [
'special_query_limit' => 50000,
'special_query_modules' =>
[
0 => 'AOR_Reports',
1 => 'Export',
2 => 'Import',
3 => 'Administration',
4 => 'Sync',
],
'default_limit' => 1000,
];
ksort($sugar_config);
if (is_writable('config.php')) {
write_array_to_file('sugar_config', $sugar_config, 'config.php');
}
}
$this->log('begin check resource settings .');
}
/**
* Clean modules cache
*/
protected function cleanModulesCache(): void
{
//Clean modules from cache
$cachedir = sugar_cached('smarty');
if (is_dir($cachedir)) {
$allModFiles = array();
$allModFiles = findAllFiles($cachedir, $allModFiles);
foreach ($allModFiles as $file) {
if (file_exists($file)) {
unlink($file);
}
}
}
//Clean modules from cache
$cachedir = sugar_cached('modules');
if (is_dir($cachedir)) {
$allModFiles = [];
$allModFiles = findAllFiles($cachedir, $allModFiles);
foreach ($allModFiles as $file) {
if (file_exists($file)) {
unlink($file);
}
}
}
}
/**
* Clean theme cache
*/
protected function cleanThemeCache(): void
{
$cachedir = sugar_cached('themes');
if (is_dir($cachedir)) {
$allModFiles = [];
$allModFiles = findAllFiles($cachedir, $allModFiles);
foreach ($allModFiles as $file) {
if (file_exists($file)) {
unlink($file);
}
}
}
}
/**
* Delete cache
*/
protected function deleteCache(): void
{
//Add the cache cleaning here.
if (function_exists('deleteCache')) {
$this->log('Call deleteCache');
@deleteCache();
}
}
protected function setAdminWizardSetting(): void
{
require_once __DIR__ . '/../../../../modules/Administration/Administration.php';
/** @var Administration $admin */
$admin = BeanFactory::newBean('Administration');
$admin->saveSetting('system', 'adminwizard', 1);
}
/**
* Inject language strings
*/
protected function injectLanguageStrings(): void
{
global $mod_strings, $app_list_strings;
$UWstrings = return_module_language('en_us', 'UpgradeWizard', true);
$adminStrings = return_module_language('en_us', 'Administration', true);
$app_list_strings = return_app_list_strings_language('en_us');
$mod_strings = array_merge($mod_strings, $adminStrings, $UWstrings);
}
/**
* Load admin user
*/
protected function loadAdminUser(): void
{
global $current_user;
$current_user->retrieve(1);
}
/**
* Pause trackers
*/
protected function pauseTrackers(): void
{
require_once __DIR__ . '/../../../../modules/Trackers/TrackerManager.php';
$trackerManager = TrackerManager::getInstance();
$trackerManager->pause();
$trackerManager->unsetMonitors();
}
/**
* Upgrade relationships
*/
protected function upgradeRelationships(): void
{
require_once __DIR__ . '/../../../../modules/Administration/upgrade_custom_relationships.php';
upgrade_custom_relationships();
}
/**
* Upgrade User preferences
*/
protected function upgradeUserPreferences(): void
{
$this->log('Upgrading user preferences start .');
if (function_exists('upgradeUserPreferences')) {
upgradeUserPreferences();
}
$this->log('Upgrading user preferences finish .');
}
/**
* Clean theme chache
*/
protected function clearThemeCache(): void
{
// clear out the theme cache
if (is_dir($GLOBALS['sugar_config']['cache_dir'] . 'themes')) {
$allModFiles = [];
$allModFiles = findAllFiles($GLOBALS['sugar_config']['cache_dir'] . 'themes', $allModFiles);
foreach ($allModFiles as $file) {
if (file_exists($file)) {
unlink($file);
}
}
}
}
/**
* Minify js
*/
protected function minifyJS(): void
{
// re-minify the JS source files
$_REQUEST['root_directory'] = getcwd();
$_REQUEST['js_rebuild_concat'] = 'rebuild';
require_once __DIR__ . '/../../../../jssource/minify.php';
}
/**
* Repair database
* @param array $beanFiles
*/
protected function repairDatabase(array $beanFiles): void
{
//First repair the databse to ensure it is up to date with the new vardefs/tabledefs
$this->log('About to repair the database.');
//Use Repair and rebuild to update the database.
global $dictionary;
require_once __DIR__ . '/../../../../modules/Administration/QuickRepairAndRebuild.php';
$rac = new RepairAndClear();
$rac->clearVardefs();
$rac->rebuildExtensions();
//bug: 44431 - defensive check to ensure the method exists since upgrades to 6.2.0 may not have this method define yet.
if (method_exists($rac, 'clearExternalAPICache')) {
$rac->clearExternalAPICache();
}
$repairedTables = [];
foreach ($beanFiles as $bean => $file) {
if (file_exists($file)) {
unset($GLOBALS['dictionary'][$bean]);
require_once $file;
$focus = new $bean();
if (empty($focus->table_name) || isset($repairedTables[$focus->table_name])) {
continue;
}
if ($focus instanceof SugarBean) {
if (!isset($repairedTables[$focus->table_name])) {
$sql = DBManagerFactory::getInstance()->repairTable($focus, true);
if (trim($sql) !== '') {
$this->log('Running sql:' . $sql);
}
$repairedTables[$focus->table_name] = true;
}
//Check to see if we need to create the audit table
if ($focus->is_AuditEnabled() && !$focus->db->tableExists($focus->get_audit_table_name())) {
$this->log('Creating audit table:' . $focus->get_audit_table_name());
$focus->create_audit_table();
}
}
}
}
$dictionary = [];
include __DIR__ . '/../../../../modules/TableDictionary.php';
foreach ($dictionary as $meta) {
$tablename = $meta['table'];
if (isset($repairedTables[$tablename])) {
continue;
}
$fielddefs = $meta['fields'];
$indices = $meta['indices'];
$sql = DBManagerFactory::getInstance()->repairTableParams($tablename, $fielddefs, $indices, true);
if (!empty($sql)) {
$this->log($sql);
$repairedTables[$tablename] = true;
}
}
$this->log('database repaired');
}
/**
* Rebuild relationships
*/
protected function rebuildRelationships(): void
{
$this->log('Start rebuild relationships.');
$_REQUEST['silent'] = true;
include __DIR__ . '/../../../../modules/Administration/RebuildRelationship.php';
$_REQUEST['upgradeWizard'] = true;
include __DIR__ . '/../../../../modules/ACL/install_actions.php';
$this->log('End rebuild relationships.');
}
/**
* Merge config si settings
* @param string $path
*/
protected function mergeConfigSettings(string $path): void
{
//bug: 37214 - merge config_si.php settings if available
$this->log('Begin merge_config_si_settings');
merge_config_si_settings(true, '', '', $path);
$this->log('End merge_config_si_settings');
}
/**
* Upgrade Connectors
*/
protected function upgradeConnectors(): void
{
$this->log('Begin upgrade_connectors');
upgrade_connectors();
$this->log('End upgrade_connectors');
}
/**
* Rebuild Sprites
*/
protected function rebuildSprites(): void
{
if (function_exists('rebuildSprites') && function_exists('imagecreatetruecolor')) {
rebuildSprites(true);
}
}
/**
* Clean Language cache
*/
protected function clearLanguageCache(): void
{
// Clear language cache
$repair = new RepairAndClear();
$repair->clearJsLangFiles();
$repair->clearLanguageCache();
}
/**
* Rebuild htaccess
*/
protected function rebuildHTAccess(): void
{
require_once __DIR__ . '/../../../../install/install_utils.php';
handleHtaccess();
}
/**
* Register upgrade in the db
* @param $install_file
* @param $zip_from_dir
* @param $manifest
* @param $suitecrm_version
*/
protected function registerUpgrade(
$install_file,
$zip_from_dir,
$manifest,
$suitecrm_version
): void {
$db = DBManagerFactory::getInstance();
$this->log('Registering upgrade with UpgradeHistory');
if (!didThisStepRunBefore('commit', 'upgradeHistory')) {
set_upgrade_progress('commit', 'in_progress', 'upgradeHistory', 'in_progress');
$file_action = 'copied';
// if error was encountered, script should have died before now
$new_upgrade = new UpgradeHistory();
$new_upgrade->filename = $install_file;
$new_upgrade->md5sum = md5_file($install_file);
$new_upgrade->name = $zip_from_dir;
$new_upgrade->description = $manifest['description'];
$new_upgrade->type = 'patch';
$new_upgrade->version = $suitecrm_version;
$new_upgrade->status = 'installed';
$new_upgrade->manifest = (!empty($_SESSION['install_manifest']) ? $_SESSION['install_manifest'] : '');
if ($new_upgrade->description === null) {
$new_upgrade->description = 'Silent Upgrade was used to upgrade the instance';
} else {
$new_upgrade->description .= ' Silent Upgrade was used to upgrade the instance.';
}
// Running db insert query as bean save will throw logic hook errors due to dependencies that are not set yet
$customID = create_guid();
$new_upgrade->date_entered = $GLOBALS['timedate']->nowDb();
$customIDQuoted = $db->quoted($customID);
$fileNameQuoted = $db->quoted($new_upgrade->filename);
$md5Quoted = $db->quoted($new_upgrade->md5sum);
$typeQuoted = $db->quoted($new_upgrade->type);
$statusQuoted = $db->quoted($new_upgrade->status);
$versionQuoted = $db->quoted($new_upgrade->version);
$nameQuoted = $db->quoted($new_upgrade->name);
$descriptionQuoted = $db->quoted($new_upgrade->description);
$manifestQuoted = $db->quoted($new_upgrade->manifest);
$dateQuoted = $db->quoted($new_upgrade->date_entered);
$upgradeHistoryInsert = "INSERT INTO upgrade_history (id, filename, md5sum, type, status, version, name, description, id_name, manifest, date_entered, enabled)
VALUES ($customIDQuoted, $fileNameQuoted, $md5Quoted, $typeQuoted, $statusQuoted, $versionQuoted, $nameQuoted, $descriptionQuoted, NULL, $manifestQuoted, $dateQuoted, '1')";
$result = $db->query($upgradeHistoryInsert, true, "Error writing upgrade history");
set_upgrade_progress('commit', 'in_progress', 'upgradeHistory', 'done');
set_upgrade_progress('commit', 'done', 'commit', 'done');
}
}
/**
* Upgrade history table
* @param bool|null $sugar_version
*/
protected function upgradeHistoryTable(?bool $sugar_version): void
{
//Run repairUpgradeHistoryTable
if (version_compare($sugar_version, '6.5.0', '<') && function_exists('repairUpgradeHistoryTable')) {
repairUpgradeHistoryTable();
}
}
/**
* Create missing relationships
*/
protected function createMissingRels()
{
$relForObjects = ['leads' => 'Leads', 'campaigns' => 'Campaigns', 'prospects' => 'Prospects'];
foreach ($relForObjects as $relObjName => $relModName) {
//assigned_user
$guid = create_guid();
$query = "SELECT id FROM relationships WHERE relationship_name = '{$relObjName}_assigned_user'";
$result = DBManagerFactory::getInstance()->query($query, true);
$a = null;
$a = DBManagerFactory::getInstance()->fetchByAssoc($result);
if (!isset($a['id']) && empty($a['id'])) {
$qRel = "INSERT INTO relationships (id,relationship_name, lhs_module, lhs_table, lhs_key, rhs_module, rhs_table, rhs_key, join_table, join_key_lhs, join_key_rhs, relationship_type, relationship_role_column, relationship_role_column_value, reverse, deleted)
VALUES ('{$guid}', '{$relObjName}_assigned_user','Users','users','id','{$relModName}','{$relObjName}','assigned_user_id',NULL,NULL,NULL,'one-to-many',NULL,NULL,'0','0')";
DBManagerFactory::getInstance()->query($qRel);
}
//modified_user
$guid = create_guid();
$query = "SELECT id FROM relationships WHERE relationship_name = '{$relObjName}_modified_user'";
$result = DBManagerFactory::getInstance()->query($query, true);
$a = null;
$a = DBManagerFactory::getInstance()->fetchByAssoc($result);
if (!isset($a['id']) && empty($a['id'])) {
$qRel = "INSERT INTO relationships (id,relationship_name, lhs_module, lhs_table, lhs_key, rhs_module, rhs_table, rhs_key, join_table, join_key_lhs, join_key_rhs, relationship_type, relationship_role_column, relationship_role_column_value, reverse, deleted)
VALUES ('{$guid}', '{$relObjName}_modified_user','Users','users','id','{$relModName}','{$relObjName}','modified_user_id',NULL,NULL,NULL,'one-to-many',NULL,NULL,'0','0')";
DBManagerFactory::getInstance()->query($qRel);
}
//created_by
$guid = create_guid();
$query = "SELECT id FROM relationships WHERE relationship_name = '{$relObjName}_created_by'";
$result = DBManagerFactory::getInstance()->query($query, true);
$a = null;
$a = DBManagerFactory::getInstance()->fetchByAssoc($result);
if (!isset($a['id']) && empty($a['id'])) {
$qRel = "INSERT INTO relationships (id,relationship_name, lhs_module, lhs_table, lhs_key, rhs_module, rhs_table, rhs_key, join_table, join_key_lhs, join_key_rhs, relationship_type, relationship_role_column, relationship_role_column_value, reverse, deleted)
VALUES ('{$guid}', '{$relObjName}_created_by','Users','users','id','{$relModName}','{$relObjName}','created_by',NULL,NULL,NULL,'one-to-many',NULL,NULL,'0','0')";
DBManagerFactory::getInstance()->query($qRel);
}
$guid = create_guid();
$query = "SELECT id FROM relationships WHERE relationship_name = '{$relObjName}_team'";
$result = DBManagerFactory::getInstance()->query($query, true);
$a = null;
$a = DBManagerFactory::getInstance()->fetchByAssoc($result);
if (!isset($a['id']) && empty($a['id'])) {
$qRel = "INSERT INTO relationships (id,relationship_name, lhs_module, lhs_table, lhs_key, rhs_module, rhs_table, rhs_key, join_table, join_key_lhs, join_key_rhs, relationship_type, relationship_role_column, relationship_role_column_value, reverse, deleted)
VALUES ('{$guid}', '{$relObjName}_team','Teams','teams','id','{$relModName}','{$relObjName}','team_id',NULL,NULL,NULL,'one-to-many',NULL,NULL,'0','0')";
DBManagerFactory::getInstance()->query($qRel);
}
}
//Also add tracker perf relationship
$guid = create_guid();
$query = "SELECT id FROM relationships WHERE relationship_name = 'tracker_monitor_id'";
$result = DBManagerFactory::getInstance()->query($query, true);
$a = null;
$a = DBManagerFactory::getInstance()->fetchByAssoc($result);
if (!isset($a['id']) && empty($a['id'])) {
$qRel = "INSERT INTO relationships (id,relationship_name, lhs_module, lhs_table, lhs_key, rhs_module, rhs_table, rhs_key, join_table, join_key_lhs, join_key_rhs, relationship_type, relationship_role_column, relationship_role_column_value, reverse, deleted)
VALUES ('{$guid}', 'tracker_monitor_id','TrackerPerfs','tracker_perf','monitor_id','Trackers','tracker','monitor_id',NULL,NULL,NULL,'one-to-many',NULL,NULL,'0','0')";
DBManagerFactory::getInstance()->query($qRel);
}
}
/**
* Add reminders
* @param $errors
* @param $skippedFiles
*/
protected function addReminders($errors, $skippedFiles): void
{
if (empty($errors)) {
commitHandleReminders($skippedFiles);
}
}
/**
* Reload the db instance
* @return DBManager
*/
protected function reloadDbInstance(): DBManager
{
if (isset($_SESSION['current_db_version'], $_SESSION['target_db_version']) && version_compare(
$_SESSION['current_db_version'],
$_SESSION['target_db_version'],
'='
)) {
$_REQUEST['upgradeWizard'] = true;
ob_start();
include __DIR__ . '/../../../../include/Smarty/internals/core.write_file.php';
ob_end_clean();
$db =& DBManagerFactory::getInstance();
}
return $db;
}
}

View file

@ -338,14 +338,6 @@ $module_name_map = [
'frontend' => 'address-cache', 'frontend' => 'address-cache',
'core' => 'AddressCache' 'core' => 'AddressCache'
], ],
'AOD_IndexEvent' => [
'frontend' => 'index-event',
'core' => 'IndexEvent'
],
'AOD_Index' => [
'frontend' => 'index',
'core' => 'index'
],
'AOP_Case_Events' => [ 'AOP_Case_Events' => [
'frontend' => 'case-events', 'frontend' => 'case-events',
'core' => 'CaseEvents' 'core' => 'CaseEvents'

View file

@ -1029,20 +1029,6 @@ function clean($string, $maxLength)
return escapeshellcmd($string); return escapeshellcmd($string);
} }
/**
* @param $string
* @return string
*/
function cleanCSV($string)
{
$check = '/^[=@]/';
if (!is_numeric($string)) {
$check = '/^[=@+-]/';
}
return preg_replace($check, "", $string);
}
/** /**
* Copy the specified request variable to the member variable of the specified object. * Copy the specified request variable to the member variable of the specified object.
* Do no copy if the member variable is already set. * Do no copy if the member variable is already set.
@ -1304,6 +1290,38 @@ function return_application_language($language)
return $return_value; return $return_value;
} }
/**
* load install languages
* @param string $language
* @return array
*/
function load_install_language(string $language): array
{
global $current_language;
$default_lang = 'en_us';
$current_language = $language ?? $default_lang;
$mod_strings = [];
if (file_exists(__DIR__ . "/../install/language/{$current_language}.lang.php")) {
include(__DIR__ . "/../install/language/{$current_language}.lang.php");
} else {
include(__DIR__ . "/../install/language/{$default_lang}.lang.php");
}
if ($current_language !== 'en_us') {
$my_mod_strings = $mod_strings;
include(__DIR__ . '/../install/language/en_us.lang.php');
$mod_strings = sugarLangArrayMerge($mod_strings, $my_mod_strings);
}
if(empty($mod_strings) || !is_array($mod_strings)){
return [];
}
return $mod_strings;
}
/** /**
* This function retrieves a module's language file and returns the array of strings included. * This function retrieves a module's language file and returns the array of strings included.
* *

View file

@ -43,6 +43,7 @@ if (!defined('sugarEntry') || !sugarEntry) {
} }
$mod_strings = array( $mod_strings = array(
'LBL_BASIC' => 'BASIC',
'LBL_BASIC_SEARCH' => 'Quick Filter', 'LBL_BASIC_SEARCH' => 'Quick Filter',
'LBL_ADVANCED_SEARCH' => 'Advanced Filter', 'LBL_ADVANCED_SEARCH' => 'Advanced Filter',
'LBL_BASIC_TYPE' => 'Basic Type', 'LBL_BASIC_TYPE' => 'Basic Type',
@ -85,7 +86,7 @@ $mod_strings = array(
'ERR_DB_ADMIN' => 'The provided database administrator username and/or password is invalid, and a connection to the database could not be established. Please enter a valid user name and password. (Error: ', 'ERR_DB_ADMIN' => 'The provided database administrator username and/or password is invalid, and a connection to the database could not be established. Please enter a valid user name and password. (Error: ',
'ERR_DB_ADMIN_MSSQL' => 'The provided database administrator username and/or password is invalid, and a connection to the database could not be established. Please enter a valid user name and password.', 'ERR_DB_ADMIN_MSSQL' => 'The provided database administrator username and/or password is invalid, and a connection to the database could not be established. Please enter a valid user name and password.',
'ERR_DB_EXISTS_NOT' => 'The specified database does not exist.', 'ERR_DB_EXISTS_NOT' => 'The specified database does not exist.',
'ERR_DB_EXISTS_WITH_CONFIG' => 'Database already exists with config data. To run an install with the chosen database, please re-run the install and choose: "Drop and recreate existing SuiteCRM tables?". To upgrade, use the Upgrade Wizard in the Admin Console. Please read the upgrade documentation located <a href="https://suitecrm.com/wiki/index.php/Upgrade" target="_new">here</a>.', 'ERR_DB_EXISTS_WITH_CONFIG' => 'Database already exists with config data. To run an install with the chosen database, please re-run the install and choose: "Drop and recreate existing SuiteCRM tables?". To upgrade, use the Upgrade Wizard in the Admin Console. Please read the upgrade documentation located <a href="https://docs.suitecrm.com/admin/installation-guide/upgrading/" target="_new">here</a>.',
'ERR_DB_EXISTS' => 'The provided Database Name already exists -- cannot create another one with the same name.', 'ERR_DB_EXISTS' => 'The provided Database Name already exists -- cannot create another one with the same name.',
'ERR_DB_EXISTS_PROCEED' => 'The provided Database Name already exists. You can<br>1. hit the back button and choose a new database name <br>2. click next and continue but all existing tables on this database will be dropped. <strong>This means your tables and data will be blown away.</strong>', 'ERR_DB_EXISTS_PROCEED' => 'The provided Database Name already exists. You can<br>1. hit the back button and choose a new database name <br>2. click next and continue but all existing tables on this database will be dropped. <strong>This means your tables and data will be blown away.</strong>',
'ERR_DB_HOSTNAME' => 'Host name cannot be blank.', 'ERR_DB_HOSTNAME' => 'Host name cannot be blank.',
@ -123,7 +124,7 @@ $mod_strings = array(
'ERR_PERFORM_HTACCESS_1' => 'Cannot write to the ', 'ERR_PERFORM_HTACCESS_1' => 'Cannot write to the ',
'ERR_PERFORM_HTACCESS_2' => ' file.', 'ERR_PERFORM_HTACCESS_2' => ' file.',
'ERR_PERFORM_HTACCESS_3' => 'If you want to secure your log file from being accessible via browser, create an .htaccess file in your log directory with the line:', 'ERR_PERFORM_HTACCESS_3' => 'If you want to secure your log file from being accessible via browser, create an .htaccess file in your log directory with the line:',
'ERR_PERFORM_NO_TCPIP' => '<b>We could not detect an Internet connection.</b> When you do have a connection, please visit <a href="http://www.suitecrm.com/">http://www.suitecrm.com/</a> to register with SuiteCRM. By letting us know a little bit about how your company plans to use SuiteCRM, we can ensure we are always delivering the right application for your business needs.', 'ERR_PERFORM_NO_TCPIP' => '<b>We could not detect an Internet connection.</b> When you do have a connection, please visit <a href="https://www.suitecrm.com/">https://www.suitecrm.com/</a> to register with SuiteCRM. By letting us know a little bit about how your company plans to use SuiteCRM, we can ensure we are always delivering the right application for your business needs.',
'ERR_SESSION_DIRECTORY_NOT_EXISTS' => 'Session directory provided is not a valid directory.', 'ERR_SESSION_DIRECTORY_NOT_EXISTS' => 'Session directory provided is not a valid directory.',
'ERR_SESSION_DIRECTORY' => 'Session directory provided is not a writable directory.', 'ERR_SESSION_DIRECTORY' => 'Session directory provided is not a writable directory.',
'ERR_SESSION_PATH' => 'Session path is required if you wish to specify your own.', 'ERR_SESSION_PATH' => 'Session path is required if you wish to specify your own.',
@ -322,6 +323,7 @@ $mod_strings = array(
'LBL_STEP2' => 'Step 2 of 2 - Configuration', 'LBL_STEP2' => 'Step 2 of 2 - Configuration',
'LBL_STEP' => 'Step', 'LBL_STEP' => 'Step',
'LBL_TITLE_WELCOME' => 'Welcome to the SuiteCRM ', 'LBL_TITLE_WELCOME' => 'Welcome to the SuiteCRM ',
'LBL_WELCOME' => 'Welcome to SuiteCRM',
//welcome page variables //welcome page variables
'LBL_TITLE_ARE_YOU_READY' => 'Are you ready to install?', 'LBL_TITLE_ARE_YOU_READY' => 'Are you ready to install?',
'REQUIRED_SYS_COMP' => 'Required System Components', 'REQUIRED_SYS_COMP' => 'Required System Components',

View file

@ -1,53 +0,0 @@
<?php
function install_aod()
{
require_once('modules/Administration/Administration.php');
global $sugar_config;
$sugar_config['aod']['enable_aod'] = false;
ksort($sugar_config);
write_array_to_file('sugar_config', $sugar_config, 'config.php');
installAODHooks();
}
function installAODHooks()
{
require_once('ModuleInstall/ModuleInstaller.php');
$hooks = array(
array(
'module' => '',
'hook' => 'after_save',
'order' => 1,
'description' => 'AOD Index Changes',
'file' => 'modules/AOD_Index/AOD_LogicHooks.php',
'class' => 'AOD_LogicHooks',
'function' => 'saveModuleChanges',
),
array(
'module' => '',
'hook' => 'after_delete',
'order' => 1,
'description' => 'AOD Index changes',
'file' => 'modules/AOD_Index/AOD_LogicHooks.php',
'class' => 'AOD_LogicHooks',
'function' => 'saveModuleDelete',
),
array(
'module' => '',
'hook' => 'after_restore',
'order' => 1,
'description' => 'AOD Index changes',
'file' => 'modules/AOD_Index/AOD_LogicHooks.php',
'class' => 'AOD_LogicHooks',
'function' => 'saveModuleRestore',
),
);
foreach ($hooks as $hook) {
check_logic_hook_file($hook['module'], $hook['hook'], array($hook['order'], $hook['description'], $hook['file'], $hook['class'], $hook['function']));
}
}

View file

@ -28,9 +28,6 @@ install_aos();
require_once('install/suite_install/AdvancedOpenPortal.php'); require_once('install/suite_install/AdvancedOpenPortal.php');
install_aop(); install_aop();
require_once('install/suite_install/AdvancedOpenDiscovery.php');
install_aod();
require_once('install/suite_install/AdvancedOpenEvents.php'); require_once('install/suite_install/AdvancedOpenEvents.php');
install_aoe(); install_aoe();

View file

@ -38,7 +38,7 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/ */
include_once __DIR__ . '/../../../vendor/autoload.php'; include_once __DIR__ . '/../../../../../vendor/autoload.php';
// Prevent errors from being echoed out to the client // Prevent errors from being echoed out to the client
// We MUST use the exceptions instead to pass the errors object // We MUST use the exceptions instead to pass the errors object

View file

@ -48,6 +48,7 @@ use SuiteCRM\Exception\InvalidArgumentException;
use SuiteCRM\Search\SearchEngine; use SuiteCRM\Search\SearchEngine;
use SuiteCRM\Search\SearchQuery; use SuiteCRM\Search\SearchQuery;
use SuiteCRM\Search\SearchResults; use SuiteCRM\Search\SearchResults;
use SuiteCRM\Search\SearchWrapper;
/** /**
* SearchEngine that use Elasticsearch index for performing almost real-time search. * SearchEngine that use Elasticsearch index for performing almost real-time search.
@ -56,8 +57,6 @@ class ElasticSearchEngine extends SearchEngine
{ {
/** @var Client */ /** @var Client */
private $client; private $client;
/** @var string */
private $index = 'main';
/** /**
* ElasticSearchEngine constructor. * ElasticSearchEngine constructor.
@ -66,12 +65,7 @@ class ElasticSearchEngine extends SearchEngine
*/ */
public function __construct(Client $client = null) public function __construct(Client $client = null)
{ {
global $sugar_config;
$this->client = $client ?? ElasticSearchClientBuilder::getClient(); $this->client = $client ?? ElasticSearchClientBuilder::getClient();
if (!empty($sugar_config['search']['ElasticSearch']['index'])) {
$this->index = $sugar_config['search']['ElasticSearch']['index'];
}
} }
/** /**
@ -88,7 +82,7 @@ class ElasticSearchEngine extends SearchEngine
$end = microtime(true); $end = microtime(true);
$searchTime = ($end - $start); $searchTime = ($end - $start);
return new SearchResults($results, true, $searchTime, $hits['hits']['total']); return new SearchResults($results, true, $searchTime, $hits['hits']['total']['value']);
} }
/** /**
@ -110,6 +104,8 @@ class ElasticSearchEngine extends SearchEngine
private function createSearchParams(SearchQuery $query): array private function createSearchParams(SearchQuery $query): array
{ {
$searchStr = $query->getSearchString(); $searchStr = $query->getSearchString();
$searchModules = SearchWrapper::getModules();
$indexes = implode(',', array_map('strtolower', $searchModules));
// Wildcard character required for Elasticsearch // Wildcard character required for Elasticsearch
$wildcardBe = "*"; $wildcardBe = "*";
@ -134,7 +130,7 @@ class ElasticSearchEngine extends SearchEngine
} }
return [ return [
'index' => $this->index, 'index' => $indexes,
'body' => [ 'body' => [
'stored_fields' => [], 'stored_fields' => [],
'from' => $query->getFrom(), 'from' => $query->getFrom(),
@ -176,28 +172,22 @@ class ElasticSearchEngine extends SearchEngine
{ {
$hitsArray = $hits['hits']['hits']; $hitsArray = $hits['hits']['hits'];
$results = []; $initialResults = [];
foreach ($hitsArray as $hit) { foreach ($hitsArray as $hit) {
$results[$hit['_type']][] = $hit['_id']; $recordModule = $hit['_index'];
$initialResults[$recordModule][] = $hit['_id'];
} }
return $results; $searchResults = [];
}
/** foreach ($initialResults as $index => $hit) {
* @return string $params = ['index' => $index];
*/ $meta = $this->client->indices()->getMapping($params);
public function getIndex(): string $moduleName = $meta[$index]['mappings']['_meta']['module_name'];
{ $searchResults[$moduleName] = $hit;
return $this->index; }
}
/** return $searchResults;
* @param string $index
*/
public function setIndex(string $index): void
{
$this->index = $index;
} }
} }

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
* *
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 SalesAgility Ltd. * Copyright (C) 2011 - 2021 SalesAgility Ltd.
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the * the terms of the GNU Affero General Public License version 3 as published by the
@ -43,19 +43,20 @@ if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point'); die('Not A Valid Entry Point');
} }
use SugarBean;
use BeanFactory;
use Carbon\Carbon; use Carbon\Carbon;
use Monolog\Logger;
use Elasticsearch\Client; use Elasticsearch\Client;
use Elasticsearch\Common\Exceptions\Missing404Exception;
use Exception;
use JsonSchema\Exception\RuntimeException; use JsonSchema\Exception\RuntimeException;
use LoggerManager;
use Monolog\Logger;
use SugarBean;
use SuiteCRM\Search\Index\AbstractIndexer; use SuiteCRM\Search\Index\AbstractIndexer;
use SuiteCRM\Search\Index\IndexingLockFileTrait;
use Symfony\Component\Yaml\Parser as YamlParser;
use SuiteCRM\Search\Index\IndexingSchedulerTrait;
use SuiteCRM\Search\Index\IndexingStatisticsTrait;
use SuiteCRM\Search\Index\Documentify\AbstractDocumentifier; use SuiteCRM\Search\Index\Documentify\AbstractDocumentifier;
use SuiteCRM\Search\Index\Documentify\SearchDefsDocumentifier; use SuiteCRM\Search\Index\Documentify\SearchDefsDocumentifier;
use SuiteCRM\Search\Index\IndexingLockFileTrait;
use SuiteCRM\Search\Index\IndexingSchedulerTrait;
use SuiteCRM\Search\Index\IndexingStatisticsTrait;
/** /**
* Class ElasticSearchIndexer takes care of creating a search index for the database. * Class ElasticSearchIndexer takes care of creating a search index for the database.
@ -67,9 +68,9 @@ class ElasticSearchIndexer extends AbstractIndexer
use IndexingSchedulerTrait; use IndexingSchedulerTrait;
/** @var string The name of the Elasticsearch index to use. */ /** @var string The name of the Elasticsearch index to use. */
private $index = 'main'; private $index;
/** @var Client */ /** @var Client */
private $client = null; private $client;
/** @var int the size of the batch to be sent to the Elasticsearch while batch indexing */ /** @var int the size of the batch to be sent to the Elasticsearch while batch indexing */
private $batchSize = 1000; private $batchSize = 1000;
/** @var Carbon|false the timestamp of the last indexing. false if unknown */ /** @var Carbon|false the timestamp of the last indexing. false if unknown */
@ -82,14 +83,9 @@ class ElasticSearchIndexer extends AbstractIndexer
*/ */
public function __construct(Client $client = null) public function __construct(Client $client = null)
{ {
global $sugar_config;
parent::__construct(); parent::__construct();
$this->client = $client !== null ? $client : ElasticSearchClientBuilder::getClient(); $this->client = $client ?? ElasticSearchClientBuilder::getClient();
if (!empty($sugar_config['search']['ElasticSearch']['index'])) {
$this->index = $sugar_config['search']['ElasticSearch']['index'];
}
} }
/** /**
@ -97,15 +93,16 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* @return bool * @return bool
*/ */
public static function isEnabled() public static function isEnabled(): ?bool
{ {
/** @noinspection PhpVariableNamingConventionInspection */ /** @noinspection PhpVariableNamingConventionInspection */
global $sugar_config; global $sugar_config;
try { try {
return $sugar_config['search']['ElasticSearch']['enabled']; return $sugar_config['search']['ElasticSearch']['enabled'];
} catch (\Exception $exception) { } catch (Exception $exception) {
\LoggerManager::getLogger()->fatal("Failed to retrieve ElasticSearch options"); LoggerManager::getLogger()->fatal("Failed to retrieve ElasticSearch options");
return false; return false;
} }
} }
@ -123,22 +120,31 @@ class ElasticSearchIndexer extends AbstractIndexer
$this->lastRunTimestamp = $this->readLockFile(); $this->lastRunTimestamp = $this->readLockFile();
} }
$modules = $this->getModulesToIndex();
$start = microtime(true);
if ($this->differentialIndexing()) { if ($this->differentialIndexing()) {
$this->logger->debug('A differential indexing will be performed'); $this->logger->debug('A differential indexing will be performed');
} else { } else {
$this->logger->debug('A full indexing will be performed'); $this->logger->debug('A full indexing will be performed');
$this->removeIndex();
$this->createIndex($this->index, $this->getDefaultMapParams()); foreach ($modules as $module) {
try {
$lowercaseModule = strtolower($module);
$this->removeIndex($lowercaseModule);
$this->createIndex($lowercaseModule);
} catch (Exception $exception) {
$message = "Failed to create index $module! Exception details follow";
$this->logger->error($message);
$this->logger->error($exception);
}
}
} }
$modules = $this->getModulesToIndex();
$start = microtime(true);
foreach ($modules as $module) { foreach ($modules as $module) {
try { try {
$this->indexModule($module); $this->indexModule($module);
} catch (\Exception $exception) { } catch (Exception $exception) {
$message = "Failed to index module $module! Exception details follow"; $message = "Failed to index module $module! Exception details follow";
$this->logger->error($message); $this->logger->error($message);
$this->logger->error($exception); $this->logger->error($exception);
@ -157,18 +163,10 @@ class ElasticSearchIndexer extends AbstractIndexer
} }
/** /**
* {@inheritdoc} * @param string $index
*
* The current index (this::getIndex()) is removed if no index is specified.
*
* @param null $index
*/ */
public function removeIndex($index = null) public function removeIndex(string $index): void
{ {
if (empty($index)) {
$index = $this->index;
}
$params = ['index' => $index]; $params = ['index' => $index];
$params['client'] = ['ignore' => [404]]; $params['client'] = ['ignore' => [404]];
@ -182,10 +180,10 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* The optional $body can be used to set up the index settings, mappings, etc. * The optional $body can be used to set up the index settings, mappings, etc.
* *
* @param string $index name of the index * @param string $index name of the index
* @param array|null $body options of the index * @param array|null $body options of the index
*/ */
public function createIndex($index, array $body = null) public function createIndex(string $index, array $body = null): void
{ {
$params = ['index' => $index]; $params = ['index' => $index];
@ -219,17 +217,23 @@ class ElasticSearchIndexer extends AbstractIndexer
} catch (RuntimeException $exception) { } catch (RuntimeException $exception) {
$this->logger->error("Failed to index module $module"); $this->logger->error("Failed to index module $module");
$this->logger->error($exception); $this->logger->error($exception);
return; return;
} }
if ($dataPuller->recordsPulled === 0) { if ($dataPuller->recordsPulled === 0) {
if (!$isDifferential) { if (!$isDifferential) {
$this->logger->notice(sprintf('Skipped %s because $beans was null. The table is probably empty', $module)); $this->logger->notice(sprintf('Skipped %s because $beans was null. The table is probably empty',
$module));
} }
return; return;
} }
$this->putMeta($module, ['last_index' => $beanTime]); $this->putMeta($module, [
'last_index' => $beanTime,
'module_name' => $module
]);
$this->indexedModulesCount++; $this->indexedModulesCount++;
} }
@ -241,13 +245,13 @@ class ElasticSearchIndexer extends AbstractIndexer
* @param string $module * @param string $module
* @return void * @return void
*/ */
protected function buildWhereClause($dataPuller, $isDifferential, $module) protected function buildWhereClause($dataPuller, $isDifferential, $module): void
{ {
if ($isDifferential) { if ($isDifferential) {
try { try {
$datetime = $this->getModuleLastIndexed($module); $datetime = $this->getModuleLastIndexed($module);
$dataPuller->setLastIndexTime($datetime)->setShowDeleted(-1); $dataPuller->setLastIndexTime($datetime)->setShowDeleted(-1);
} catch (\Exception $exception) { } catch (Exception $exception) {
$this->logger->notice("Time metadata not found for $module, performing full index for this module"); $this->logger->notice("Time metadata not found for $module, performing full index for this module");
$dataPuller->setDifferential(false); $dataPuller->setDifferential(false);
} }
@ -268,13 +272,13 @@ class ElasticSearchIndexer extends AbstractIndexer
} }
/** Removes all the indexes from Elasticsearch, effectively nuking all data. */ /** Removes all the indexes from Elasticsearch, effectively nuking all data. */
public function removeAllIndices() public function removeAllIndices(): void
{ {
$this->logger->debug("Deleting all indices"); $this->logger->debug("Deleting all indices");
try { try {
$this->client->indices()->delete(['index' => '_all']); $this->client->indices()->delete(['index' => '_all']);
} /** @noinspection PhpRedundantCatchClauseInspection */ } /** @noinspection PhpRedundantCatchClauseInspection */
catch (\Elasticsearch\Common\Exceptions\Missing404Exception $ignore) { catch (Missing404Exception $ignore) {
// Index not there, not big deal since we meant to delete it anyway. // Index not there, not big deal since we meant to delete it anyway.
$this->logger->warn('Index not found, no index has been deleted.'); $this->logger->warn('Index not found, no index has been deleted.');
} }
@ -334,64 +338,70 @@ class ElasticSearchIndexer extends AbstractIndexer
if ($status === false) { if ($status === false) {
$this->logger->error("Failed to ping server"); $this->logger->error("Failed to ping server");
return false; return false;
} }
$this->logger->debug("Ping performed in $elapsed µs"); $this->logger->debug("Ping performed in $elapsed µs");
return $elapsed; return $elapsed;
} }
/** /**
* Writes the metadata fields for one index type. * Writes the metadata fields for one index.
* *
* @param string $module name of the module/type * @param string $module name of the module
* @param array $meta an associative array with the fields to populate * @param array $meta an associative array with the fields to populate
*/ */
public function putMeta($module, $meta) public function putMeta(string $module, array $meta): void
{ {
$params = [ $params = [
'index' => $this->index, 'index' => strtolower($module),
'type' => $module,
'body' => ['_meta' => $meta], 'body' => ['_meta' => $meta],
'ignore_unavailable' => true
]; ];
$this->client->indices()->putMapping($params); $this->client->indices()->putMapping($params);
} }
/** /**
* Returns the metadata fields for one index type. * Returns the metadata fields for one index.
* *
* @param string $module name of the module/type * @param string $module name of the module
* *
* @return array an associative array with the metadata * @return array an associative array with the metadata
*/ */
public function getMeta($module) public function getMeta(string $module): ?array
{ {
$params = ['index' => $this->index, 'filter_path' => "$this->index.mappings.$module._meta"]; $lowercaseModule = strtolower($module);
$params = ['index' => $lowercaseModule];
$results = $this->client->indices()->getMapping($params); $results = $this->client->indices()->getMapping($params);
if (!isset($results[$this->index])) { if (!isset($results[$lowercaseModule])) {
return null; return null;
} }
$meta = $results[$this->index]['mappings'][$module]['_meta']; return $results[$lowercaseModule]['mappings']['_meta'];
return $meta;
} }
/** @return int */ /**
public function getBatchSize() * @return int
*/
public function getBatchSize(): int
{ {
return $this->batchSize; return $this->batchSize;
} }
/** @param int $batchSize */ /**
public function setBatchSize($batchSize) * @param int $batchSize
*/
public function setBatchSize(int $batchSize): void
{ {
$this->batchSize = $batchSize; $this->batchSize = $batchSize;
} }
/** @return string */ /** @return string */
public function getIndex() public function getIndex(): string
{ {
return $this->index; return $this->index;
} }
@ -401,7 +411,7 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* @param string $index * @param string $index
*/ */
public function setIndex($index) public function setIndex(string $index): void
{ {
$this->logger->debug("Setting index to $index"); $this->logger->debug("Setting index to $index");
$this->index = $index; $this->index = $index;
@ -414,17 +424,17 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* Additionally, Beans marked as deleted will be remove from the index. * Additionally, Beans marked as deleted will be remove from the index.
* *
* @param string $module * @param string $module
* @param SugarBean[] $beans * @param SugarBean[] $beans
* *
* @see batchSize * @see batchSize
*/ */
private function indexBatch($module, array $beans) private function indexBatch(string $module, array $beans): void
{ {
$params = ['body' => []]; $params = ['body' => []];
foreach ($beans as $key => $bean) { foreach ($beans as $key => $bean) {
$head = ['_index' => $this->index, '_type' => $module, '_id' => $bean->id]; $head = ['_index' => strtolower($module), '_id' => $bean->id];
if ($bean->deleted) { if ($bean->deleted) {
$params['body'][] = ['delete' => $head]; $params['body'][] = ['delete' => $head];
@ -454,28 +464,11 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* @return bool * @return bool
*/ */
private function differentialIndexing() private function differentialIndexing(): bool
{ {
return $this->differentialIndexing && $this->lastRunTimestamp !== false; return $this->differentialIndexing && $this->lastRunTimestamp !== false;
} }
/**
* Retrieves the default params to set up an optimised default index for Elasticsearch.
*
* @return array
*/
private function getDefaultMapParams()
{
$file = __DIR__ . '/defaultParams.yml';
$this->logger->debug("Loading mapping file $file");
$parse = new YamlParser();
$parsed = $parse->parseFile($file);
return ['mappings' => $parsed['mappings']];
}
/** /**
* Creates the body of a Elasticsearch request for a given bean. * Creates the body of a Elasticsearch request for a given bean.
* *
@ -486,7 +479,7 @@ class ElasticSearchIndexer extends AbstractIndexer
* @return array * @return array
* @see AbstractDocumentifier * @see AbstractDocumentifier
*/ */
private function makeIndexParamsBodyFromBean(SugarBean $bean) private function makeIndexParamsBodyFromBean(SugarBean $bean): array
{ {
return $this->documentifier->documentify($bean); return $this->documentifier->documentify($bean);
} }
@ -498,7 +491,7 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* @param array $params * @param array $params
*/ */
private function sendBatch(array &$params) private function sendBatch(array &$params): void
{ {
// sends the batch over to the server // sends the batch over to the server
$responses = $this->client->bulk($params); $responses = $this->client->bulk($params);
@ -535,10 +528,11 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* @return array * @return array
*/ */
private function makeIndexParamsFromBean(SugarBean $bean) private function makeIndexParamsFromBean(SugarBean $bean): array
{ {
$args = $this->makeParamsHeaderFromBean($bean); $args = $this->makeParamsHeaderFromBean($bean);
$args['body'] = $this->makeIndexParamsBodyFromBean($bean); $args['body'] = $this->makeIndexParamsBodyFromBean($bean);
return $args; return $args;
} }
@ -549,15 +543,12 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* @return array * @return array
*/ */
private function makeParamsHeaderFromBean(SugarBean $bean) private function makeParamsHeaderFromBean(SugarBean $bean): array
{ {
$args = [ return [
'index' => $this->index, 'index' => $bean->module_name,
'type' => $bean->module_name,
'id' => $bean->id, 'id' => $bean->id,
]; ];
return $args;
} }
/** /**
@ -567,7 +558,7 @@ class ElasticSearchIndexer extends AbstractIndexer
* *
* @return string a datetime string * @return string a datetime string
*/ */
private function getModuleLastIndexed($module) private function getModuleLastIndexed(string $module): string
{ {
$meta = $this->getMeta($module); $meta = $this->getMeta($module);
@ -579,15 +570,14 @@ class ElasticSearchIndexer extends AbstractIndexer
} }
/** /**
*
* @param bool $differential * @param bool $differential
* @param int $searchdefs * @param int $searchdefs
*/ */
public static function repairElasticsearchIndex($differential = true, $searchdefs = 0) public static function repairElasticsearchIndex(bool $differential = true, int $searchdefs = 0): void
{ {
$indexer = new ElasticSearchIndexer(); $indexer = new ElasticSearchIndexer();
if ( ! $indexer->isEnabled()) { if (!$indexer::isEnabled()) {
return 0 ; return;
} }
$indexer->setDifferentialIndexing($differential); $indexer->setDifferentialIndexing($differential);
if ($searchdefs) { if ($searchdefs) {

View file

@ -1,20 +0,0 @@
fields: &fields
keyword:
type: keyword
ignore_above: 256
name_fields: &name_fields
type: text
copy_to: named
fields: *fields
mappings:
_default_:
properties:
name:
properties:
name: *name_fields
first: *name_fields
last: *name_fields
named:
type: text
fields: *fields

View file

@ -161,9 +161,11 @@ abstract class AbstractIndexer
/** /**
* Deletes all the records from the index. * Deletes all the records from the index.
* *
* @param string $index
*
* @return void * @return void
*/ */
abstract public function removeIndex(); abstract public function removeIndex(string $index);
/** /**
* Returns whether the next indexing should be performed differentially or not. * Returns whether the next indexing should be performed differentially or not.

View file

@ -98,16 +98,11 @@ class SearchConfigurator
} }
$searchController = 'UnifiedSearch'; $searchController = 'UnifiedSearch';
$enableAod = false;
switch ($engine) { switch ($engine) {
case 'BasicSearchEngine': case 'BasicSearchEngine':
// Only basic search // Only basic search
break; break;
case 'BasicAndAodEngine':
// Basic search and AOD
$enableAod = true;
break;
default: default:
// SearchWrapper with a specific engine // SearchWrapper with a specific engine
$searchController = 'Search'; $searchController = 'Search';
@ -115,7 +110,6 @@ class SearchConfigurator
$this->configurator->config['search']['controller'] = $searchController; $this->configurator->config['search']['controller'] = $searchController;
$this->configurator->config['search']['defaultEngine'] = $engine; $this->configurator->config['search']['defaultEngine'] = $engine;
$this->configurator->config['aod']['enable_aod'] = $enableAod;
return $this; return $this;
} }

View file

@ -1,14 +1,11 @@
<?php <?php
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/** /**
* *
* SugarCRM Community Edition is a customer relationship management program developed by * SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
* *
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 SalesAgility Ltd. * Copyright (C) 2011 - 2021 SalesAgility Ltd.
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the * the terms of the GNU Affero General Public License version 3 as published by the
@ -41,48 +38,58 @@ if (!defined('sugarEntry') || !sugarEntry) {
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/ */
$dictionary['users_password_link'] = array( if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
$dictionary['users_password_link'] = [
'table' => 'users_password_link', 'table' => 'users_password_link',
'fields' => array( 'fields' => [
'id' => array( 'id' => [
'name' => 'id', 'name' => 'id',
'vname' => 'LBL_ID', 'vname' => 'LBL_ID',
'type' => 'id', 'type' => 'id',
'required' => true, 'required' => true,
) , ],
'username' => array( 'user_id' => [
'name' => 'user_id',
'vname' => 'LBL_USER_ID',
'type' => 'varchar',
'len' => 36,
],
'username' => [
'name' => 'username', 'name' => 'username',
'vname' => 'LBL_USERNAME', 'vname' => 'LBL_USERNAME',
'type' => 'varchar', 'type' => 'varchar',
'len' => 36, 'len' => 36,
) , ],
'date_generated' => array( 'date_generated' => [
'name' => 'date_generated', 'name' => 'date_generated',
'vname' => 'LBL_DATE_ENTERED', 'vname' => 'LBL_DATE_ENTERED',
'type' => 'datetime', 'type' => 'datetime',
) , ],
'deleted' => array( 'deleted' => [
'name' => 'deleted', 'name' => 'deleted',
'vname' => 'LBL_DELETED', 'vname' => 'LBL_DELETED',
'type' => 'bool', 'type' => 'bool',
'required' => false, 'required' => false,
'reportable' => false, 'reportable' => false,
) , ],
) , ],
'indices' => array( 'indices' => [
array( [
'name' => 'users_password_link_pk', 'name' => 'users_password_link_pk',
'type' => 'primary', 'type' => 'primary',
'fields' => array( 'fields' => [
'id' 'id'
) ]
) , ],
array( [
'name' => 'idx_username', 'name' => 'idx_username',
'type' => 'index', 'type' => 'index',
'fields' => array( 'fields' => [
'username' 'username'
) ]
) ]
) , ],
); ];

View file

@ -1,14 +1,11 @@
<?php <?php
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/** /**
* *
* SugarCRM Community Edition is a customer relationship management program developed by * SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
* *
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd. * SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 SalesAgility Ltd. * Copyright (C) 2011 - 2021 SalesAgility Ltd.
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the * the terms of the GNU Affero General Public License version 3 as published by the
@ -41,33 +38,28 @@ if (!defined('sugarEntry') || !sugarEntry) {
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/ */
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
global $current_user, $beanList, $mod_strings;
global $current_user,$beanList, $beanFiles, $mod_strings;
$installed_classes = array(); $installed_classes = array();
$ACLbeanList=$beanList;
if (is_admin($current_user)) { if (is_admin($current_user)) {
foreach ($ACLbeanList as $module=>$class) { foreach ($beanList as $module => $class) {
if (empty($installed_classes[$class]) && isset($beanFiles[$class]) && file_exists($beanFiles[$class])) { if (empty($installed_classes[$class]) && $class !== 'Tracker') {
if ($class == 'Tracker') { $bean = BeanFactory::newBean($module);
} else { if ($bean) {
require_once($beanFiles[$class]); $GLOBALS['log']->debug("ACL Processing: $class");
$mod = new $class(); if (empty($bean->acl_display_only) && $bean->bean_implements('ACL')) {
$GLOBALS['log']->debug("DOING: $class"); if (!defined('SUGARCRM_IS_INSTALLING') && !isset($_REQUEST['upgradeWizard'])) {
if ($mod->bean_implements('ACL') && empty($mod->acl_display_only)) { echo translate('LBL_ADDING', 'ACL', '') . $bean->module_dir . '<br>';
// BUG 10339: do not display messages for upgrade wizard
if (!isset($_REQUEST['upgradeWizard'])) {
echo translate('LBL_ADDING', 'ACL', '') . $mod->module_dir . '<br>';
} }
if (!empty($mod->acltype)) { if (!empty($bean->acltype)) {
ACLAction::addActions($mod->getACLCategory(), $mod->acltype); ACLAction::addActions($bean->getACLCategory(), $bean->acltype);
} else { } else {
ACLAction::addActions($mod->getACLCategory()); ACLAction::addActions($bean->getACLCategory());
} }
$installed_classes[$class] = true; $installed_classes[$class] = true;

View file

@ -38,6 +38,8 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/ */
echo '<div class="role-manager">';
if (!defined('sugarEntry') || !sugarEntry) { if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point'); die('Not A Valid Entry Point');
} }
@ -76,3 +78,5 @@ require_once __DIR__ . '/../../include/SubPanel/SubPanelTiles.php';
$subPanel = new SubPanelTiles($role, 'ACLRoles'); $subPanel = new SubPanelTiles($role, 'ACLRoles');
echo $subPanel->display(); echo $subPanel->display();
echo '</div>';

View file

@ -47,16 +47,14 @@
<div class="actionsContainer"> <div class="actionsContainer">
<form action="index.php" method="post" name="DetailView" id="form"> <form action="index.php" method="post" name="DetailView" id="form">
<input type="hidden" name="module" value="ACLRoles">
<input type="hidden" name="module" value="ACLRoles"> <input type="hidden" name="user_id" value="">
<input type="hidden" name="user_id" value=""> <input type="hidden" name="record" value="{$ROLE.id}">
<input type="hidden" name="record" value="{$ROLE.id}"> <input type="hidden" name="isDuplicate" value=''>
<input type="hidden" name="isDuplicate" value=''> <input type='hidden' name='return_record' value='{$RETURN.record}'>
<input type='hidden' name='return_record' value='{$RETURN.record}'> <input type='hidden' name='return_action' value='{$RETURN.action}'>
<input type='hidden' name='return_action' value='{$RETURN.action}'> <input type='hidden' name='return_module' value='{$RETURN.module}'>
<input type='hidden' name='return_module' value='{$RETURN.module}'> <input type="hidden" name="action">
<input type="hidden" name="action">
{php} {php}
$APP = $this->get_template_vars('APP'); $APP = $this->get_template_vars('APP');
$this->append('buttons', $this->append('buttons',
@ -79,15 +77,16 @@ EOD
</form> </form>
</p> </p>
</div> </div>
<p> <p>
<TABLE width='100%' class='detail view' border='0' cellpadding=0 cellspacing = 1 > <TABLE width='100%' class='detail view' border='0' cellpadding=0 cellspacing = 1 >
<TR> <TR>
<td valign='top' width='15%' align='right'><b>{$MOD.LBL_NAME}:</b></td><td width='85%' colspan='3'>{$ROLE.name}</td> <td valign='top' width='15%' align='right'><b>{$MOD.LBL_NAME}:</b></td><td width='85%' colspan='3'>{$ROLE.name}</td>
</tr </tr>
><TR> <TR>
<td valign='top' width='15%' align='right'><b>{$MOD.LBL_DESCRIPTION}:</b></td><td colspan='3' valign='top' width='85%' align='left'>{$ROLE.description | nl2br}</td> <td valign='top' width='15%' align='right'><b>{$MOD.LBL_DESCRIPTION}:</b></td><td colspan='3' valign='top' width='85%' align='left'>{$ROLE.description | nl2br}</td>
</tr></table> </tr>
</table>
</p> </p>
<p>
<p class="heading-text">
{include file="modules/ACLRoles/EditViewBody.tpl" } {include file="modules/ACLRoles/EditViewBody.tpl" }

Some files were not shown because too many files have changed in this diff Show more