Squashed 'public/legacy/' changes from f058c4c306..2aaee3c558

2aaee3c558 Implement PDFEngine
bf78e964fd Fix PDF_Lib constructors
cfe6e2a1e0 Replace deprecated fzaninotto/faker with fakerphp/faker
7f8d18b8fb Move test namespaces into autoload-dev
1778603d07 Upgrade nesbot/carbon to v2.x
171ef65335 Update Travis config to use composer v2.x
7a4d0007af Upgrade composer-merge-plugin to v2.x
0461d8f4ba Fix PHPUnit 9 deprecations and warnings
15906ef6a5 Fix test case class not matching filename deprecation warnings
b92a9dcdbd Replace abandoned leafo/scssphp with scssphp/scssphp
9a0fea7c9e Upgrade Robo to v3.x
5462b82a22 Update composer.json
77d3575052 Fix missing default config values
1d4a0e7421 Consolidate global search settings
e75e0f4add Remove duplicate "Global Search" link in the adminpanel
1bfa51fa73 Implement search engine selection
d5a33281e1 Deprecate UnifiedSearchAdvanced
fcce848d4c Unify search engines
c8c02c5398 Remove new/legacy search engine labels
e34cad759d Add codeception 4.1.x dependencies to composer
cc3a504997 Migrate PHPUnit schema for 9.5.x
ce5a63be20 Upgrade PHPUnit to 9.5.x
f52dc24e61 Remove codeception
420303758e Fix tests remove incompletes
c93e654768 Fix tests deprecated asserts
4feebbab22 Fix tests define return type hints
abd327d267 Update test namespaces for PSR-4/PSR-8
f464e2a829 Fix tests redundant noinspection
5b74cc4d2c Fix tests misordered assert arguments
03a83246f4 Fix tests use appropriate asserts
a04c048c18 Fix tests one-time use variables
683533e2b6 Fix tests method invocations
7e44ec9583 Update PHPUnit schema
2181ad7f3d Update Travis config to remove PHP 7.2
480a87c03a Update minimum required PHP to v7.3.0
200c6deb61 Update composer.lock

git-subtree-dir: public/legacy
git-subtree-split: 2aaee3c5581c025abca1114276e2d20c709f2812
This commit is contained in:
Dillon-Brown 2021-07-29 16:52:11 +01:00
parent 2473298dc6
commit 9c71e8c884
324 changed files with 18517 additions and 13877 deletions

2
.gitignore vendored
View file

@ -16,6 +16,8 @@ custom/modules/unified_search_modules_display.php
# Ignore AOD indexes
modules/AOD_Index/Index/*
install/status.json
# Ignore PDF Fonts
modules/AOS_PDF_Templates/PDF_Lib/ttfontdata/
# Configuration files should be ignored.
/config.php
/config_override.php

View file

@ -4,20 +4,20 @@ os: linux
matrix:
fast_finish: true
include:
- name: "PHP 7.2 / MySQL 5.7"
php: "7.2"
- name: "PHP 7.3 / MySQL 5.7"
php: "7.3"
dist: xenial
- name: "PHP 7.4 / MySQL 5.7"
php: "7.4"
dist: xenial
# Run composer validate to make sure the composer.json and composer.lock are in sync.
- name: "composer validate"
php: "7.2"
php: "7.3"
dist: xenial
before_script: composer install
script: composer validate
- name: "code coverage"
php: "7.3"
php: "7.4"
dist: xenial
script: ./vendor/bin/codecept run install --env travis-ci-hub -f --ext DotReporter; ./vendor/bin/robo code:coverage --ci; cat codeception.dist.yml; bash <(curl -s https://codecov.io/bash) -f tests/_output/coverage.xml
@ -45,7 +45,7 @@ before_install:
install:
- phpenv config-add travis.php.ini
- composer self-update --1 && composer --version
- composer self-update --stable && composer --version
before_script:
# Set up MySQL

View file

@ -4,8 +4,11 @@
"homepage": "https://suitecrm.com",
"type": "project",
"license": "GPL-3.0",
"authors": [],
"minimum-stability": "dev",
"authors": [
{
"name": "SalesAgility Ltd"
}
],
"support": {
"issues": "https://github.com/salesagility/SuiteCRM/issues",
"wiki": "https://docs.suitecrm.com",
@ -16,7 +19,7 @@
"config": {
"vendor-dir": "vendor",
"platform": {
"php": "7.2.9"
"php": "7.3.0"
},
"optimize-autoloader": true,
"sort-packages": true,
@ -24,8 +27,10 @@
"elasticsearch/elasticsearch": "dist"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=7.2.9",
"php": ">=7.3.0",
"ext-curl": "*",
"ext-gd": "*",
"ext-imap": "*",
@ -42,7 +47,7 @@
"league/oauth2-server": "^5.1",
"league/uri": "^4.2.3",
"monolog/monolog": "^1.23",
"nesbot/carbon": "^1.31",
"nesbot/carbon": "^2.0.0",
"onelogin/php-saml": "3.4.1",
"paragonie/random_compat": "^2.0",
"phpmailer/phpmailer": "^6.0",
@ -51,13 +56,15 @@
"slim/slim": "^3.8",
"smarty/smarty": "^2.6",
"soundasleep/html2text": "~0.5",
"symfony/yaml": "^3.4",
"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": "^1.4",
"wikimedia/composer-merge-plugin": "^2.0",
"zbateson/mail-mime-parser": "^1.1",
"zf1/zend-gdata": "^1.12",
"zf1/zend-loader": "^1.12",
@ -69,24 +76,22 @@
"require-dev": {
"consolidation/robo": "^1.4",
"browserstack/browserstack-local": "^1.1",
"codeception/codeception": "^3.0",
"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",
"fzaninotto/faker": "^1.6",
"jeroendesloovere/vcard": "v1.5",
"leafo/scssphp": "^0.7.7",
"mikey179/vfsstream": "1.6.*",
"mockery/mockery": "^1.1.0",
"phpunit/phpunit": "^8.5"
"phpunit/phpunit": "^9.5",
"scssphp/scssphp": "^1.5"
},
"scripts": {
"post-install-cmd": [
"rm -Rf vendor/elasticsearch/elasticsearch/tests/Elasticsearch/Tests",
"Google\\Task\\Composer::cleanup"
]
},
"prefer-stable": true,
"autoload": {
"files": [
"deprecated.php"
@ -94,9 +99,7 @@
"psr-4": {
"SuiteCRM\\": [
"lib/",
"include/",
"tests/SuiteCRM/",
"tests/unit/phpunit/lib/SuiteCRM/"
"include/"
],
"SuiteCRM\\Custom\\": [
"custom/lib"
@ -109,6 +112,23 @@
"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": [

5423
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -3826,3 +3826,5 @@ $app_strings['LBL_PHOTO'] = 'Photo';
$app_strings['LBL_CASE_UPDATES'] = 'Case Updates';
$app_strings['LBL_SUMMARY_DEFAULT'] = "{{fields.name.value}}";
$app_strings['LBL_CREATE'] = "Create";
$app_strings['LBL_USE_ADVANCED_SEARCH'] = 'Use Advanced Search';
$app_strings['LBL_USE_BASIC_SEARCH'] = 'Use Basic Search';

View file

@ -5,7 +5,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2020 SalesAgility Ltd.
* Copyright (C) 2011 - 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
@ -269,18 +269,15 @@ function make_sugar_config(&$sugar_config)
}
/**
* Used for getting base values for array style config.php
* @return array
* @throws Exception
*/
function get_sugar_config_defaults()
function get_sugar_config_defaults(): array
{
global $locale;
/*
* used for getting base values for array style config.php. used by the
* installer and to fill in new entries on upgrades. see also:
* sugar_config_union
*/
$sugar_config_defaults = array(
$sugar_config_defaults = [
'disableAjaxUI' => true,
'admin_export_only' => false,
'export_delimiter' => ',',
@ -289,7 +286,7 @@ function get_sugar_config_defaults()
'calculate_response_time' => true,
'create_default_user' => false,
'chartEngine' => 'Jit',
'date_formats' => array(
'date_formats' => [
'Y-m-d' => '2010-12-23',
'm-d-Y' => '12-23-2010',
'd-m-Y' => '23-12-2010',
@ -299,8 +296,8 @@ function get_sugar_config_defaults()
'Y.m.d' => '2010.12.23',
'd.m.Y' => '23.12.2010',
'm.d.Y' => '12.23.2010',
),
'name_formats' => array(
],
'name_formats' => [
's f l' => 's f l',
'f l' => 'f l',
's l' => 's l',
@ -309,20 +306,22 @@ function get_sugar_config_defaults()
's l, f' => 's l, f',
'l s f' => 'l s f',
'l f s' => 'l f s',
),
'dbconfigoption' => array(
],
'dbconfigoption' => [
'persistent' => true,
'autofree' => false,
'debug' => 0,
'ssl' => false,
),
],
'default_action' => 'index',
'default_charset' => return_session_value_or_default('default_charset', 'UTF-8'),
'default_currency_name' => return_session_value_or_default('default_currency_name', 'US Dollar'),
'default_currency_symbol' => return_session_value_or_default('default_currency_symbol', '$'),
'default_currency_iso4217' => return_session_value_or_default('default_currency_iso4217', 'USD'),
'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits', 2),
'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator', ','),
'default_currency_significant_digits' => return_session_value_or_default('default_currency_significant_digits',
2),
'default_number_grouping_seperator' => return_session_value_or_default('default_number_grouping_seperator',
','),
'default_decimal_seperator' => return_session_value_or_default('default_decimal_seperator', '.'),
'default_date_format' => 'm/d/Y',
'default_locale_name_format' => 's f l',
@ -330,18 +329,23 @@ function get_sugar_config_defaults()
'default_language' => return_session_value_or_default('default_language', 'en_us'),
'default_module' => 'Home',
'default_password' => '',
'default_permissions' => array(
'default_permissions' => [
'dir_mode' => 02770,
'file_mode' => 0755,
'user' => '',
'group' => '',
),
],
'default_theme' => return_session_value_or_default('site_default_theme', 'SuiteP'),
'default_time_format' => 'h:ia',
'default_user_is_admin' => false,
'default_user_name' => '',
'disable_export' => false,
'disable_persistent_connections' => return_session_value_or_default('disable_persistent_connections', 'false'),
'disable_persistent_connections' => return_session_value_or_default('disable_persistent_connections', false),
'default_module_favicon' => false,
'dashlet_auto_refresh_min' => 30,
'stack_trace_errors' => false,
'developerMode' => false,
'stackTrace' => false,
'display_email_template_variable_chooser' => false,
'display_inbound_email_buttons' => false,
'dump_slow_queries' => false,
@ -352,8 +356,8 @@ function get_sugar_config_defaults()
'email_warning_notifications' => true,
'email_enable_auto_send_opt_in' => false,
'email_enable_confirm_opt_in' => SugarEmailAddress::COI_STAT_DISABLED,
'filter_module_fields' => array(
'Users' => array(
'filter_module_fields' => [
'Users' => [
'show_on_employees',
'portal_only',
'is_group',
@ -368,8 +372,8 @@ function get_sugar_config_defaults()
'password',
'last_login',
'oauth_tokens',
),
'Employees' => array(
],
'Employees' => [
'show_on_employees',
'portal_only',
'is_group',
@ -384,14 +388,14 @@ function get_sugar_config_defaults()
'password',
'last_login',
'oauth_tokens',
)
),
]
],
'google_auth_json' => '',
'history_max_viewed' => 50,
'installer_locked' => true,
'import_max_records_per_file' => 100,
'import_max_records_total_limit' => '',
'languages' => array('en_us' => 'English (US)'),
'languages' => ['en_us' => 'English (US)'],
'large_scale_test' => false,
'list_max_entries_per_page' => 20,
'list_max_entries_per_subpanel' => 10,
@ -399,11 +403,11 @@ function get_sugar_config_defaults()
'log_memory_usage' => false,
'oauth2_encryption_key' => base64_encode(random_bytes(32)),
'portal_view' => 'single_user',
'resource_management' => array(
'resource_management' => [
'special_query_limit' => 50000,
'special_query_modules' => array('AOR_Reports', 'Export', 'Import', 'Administration', 'Sync'),
'special_query_modules' => ['AOR_Reports', 'Export', 'Import', 'Administration', 'Sync'],
'default_limit' => 1000,
),
],
'require_accounts' => true,
'rss_cache_time' => return_session_value_or_default('rss_cache_time', '10800'),
'save_query' => 'all',
@ -411,7 +415,7 @@ function get_sugar_config_defaults()
'showThemePicker' => true,
'slow_query_time_msec' => '100',
'sugarbeet' => true,
'time_formats' => array(
'time_formats' => [
'H:i' => '23:00',
'h:ia' => '11:00pm',
'h:iA' => '11:00PM',
@ -422,10 +426,10 @@ function get_sugar_config_defaults()
'h.iA' => '11.00PM',
'h.i a' => '11.00 pm',
'h.i A' => '11.00 PM',
),
],
'tracker_max_display_length' => 15,
'translation_string_prefix' => return_session_value_or_default('translation_string_prefix', false),
'upload_badext' => array(
'upload_badext' => [
'php',
'php3',
'php4',
@ -440,7 +444,7 @@ function get_sugar_config_defaults()
'html',
'htm',
'phtml',
),
],
'upload_maxsize' => 30000000,
'import_max_execution_time' => 3600,
// 'use_php_code_json' => returnPhpJsonStatus(),
@ -452,7 +456,7 @@ function get_sugar_config_defaults()
'lock_subpanels' => false,
'max_dashlets_homepage' => '15',
'default_max_tabs' => 8,
'dashlet_display_row_options' => array('1', '3', '5', '10'),
'dashlet_display_row_options' => ['1', '3', '5', '10'],
'default_subpanel_tabs' => true,
'default_subpanel_links' => false,
'default_swap_last_viewed' => false,
@ -462,7 +466,7 @@ function get_sugar_config_defaults()
'use_common_ml_dir' => false,
'common_ml_dir' => '',
'vcal_time' => '2',
'calendar' => array(
'calendar' => [
'default_view' => 'week',
'show_calls_by_default' => true,
'show_tasks_by_default' => true,
@ -475,8 +479,8 @@ function get_sugar_config_defaults()
'items_resizable' => true,
'enable_repeat' => true,
'max_repeat_count' => 1000,
),
'passwordsetting' => empty($passwordsetting) ? array(
],
'passwordsetting' => empty($passwordsetting) ? [
'SystemGeneratedPasswordON' => '',
'generatepasswordtmpl' => '',
'lostpasswordtmpl' => '',
@ -489,22 +493,22 @@ function get_sugar_config_defaults()
'systexpirationtime' => '7',
'systexpirationtype' => '1',
'systexpirationlogin' => '',
) : $passwordsetting,
] : $passwordsetting,
'use_real_names' => true,
'search_wildcard_infront' => false,
'search_wildcard_char' => '%',
'jobs' => array(
'jobs' => [
'min_retry_interval' => 30, // 30 seconds minimal job retry
'max_retries' => 5, // how many times to retry the job
'timeout' => 86400, // how long a job may spend as running before being force-failed
),
'cron' => array(
],
'cron' => [
'max_cron_jobs' => 10, // max jobs per cron schedule run
'max_cron_runtime' => 30, // max runtime for cron jobs
'min_cron_interval' => 30, // minimal interval between cron jobs
),
],
'strict_id_validation' => false,
);
];
if (!is_object($locale)) {
$locale = new Localization();

View file

@ -0,0 +1,52 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\PDF\Exceptions;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
* Class SearchEngineNotFoundException
* @package SuiteCRM\PDF\Exceptions
*/
class PDFEngineNotFoundException extends PDFException
{
}

View file

@ -1,9 +1,10 @@
/*
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -36,18 +37,18 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
$(function () {
var checkBox = $("#search-wrapper-enabled");
var select = $("#search-engine");
namespace SuiteCRM\PDF\Exceptions;
function toggle() {
var enabled = checkBox.prop("checked");
select.prop("disabled", !enabled);
}
use RuntimeException;
checkBox.change(function () {
toggle();
});
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
toggle();
});
/**
* Class PDFException
* @package SuiteCRM\PDF\Exceptions
*/
class PDFException extends RuntimeException
{
}

161
lib/PDF/MPDF/MPDFEngine.php Normal file
View file

@ -0,0 +1,161 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\PDF\MPDF;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
use mPDF;
use SuiteCRM\PDF\PDFEngine;
require_once __DIR__ . '/../../../modules/AOS_PDF_Templates/PDF_Lib/mpdf.php';
/**
* Class MPDFEngine
* @package SuiteCRM\PDF\MPDF
*/
class MPDFEngine extends PDFEngine
{
/**
* @var mPDF
*/
public $pdf;
/**
* MPDFEngine constructor.
* @param mPDF|null $pdf
*/
public function __construct(mPDF $pdf = null)
{
@$this->pdf = $pdf ?? new mPDF();
}
/**
* @param string $html
* @param int $section 0=default; 1=headerCSS; 2=HTML body; 3=HTML parses; 4=HTML headers;
* @param bool $init Leaves buffers, etc, in current state so that it can continue a block.
* @param bool $close Clears and sets buffers to top level block.
* @return void
*/
public function writeHTML(string $html, int $section = 0, bool $init = true, bool $close = true): void
{
@$this->pdf->WriteHTML($html, $section, $init, $close);
if ($section === 1) {
@$this->pdf->SetDefaultBodyCSS('background-color', '#FFFFFF');
unset($this->pdf->cssmgr->CSS['INPUT']['FONT-SIZE']);
}
}
/**
* @param string $name
* @param string $destination
* @return void|string
*/
public function outputPDF(string $name, string $destination): ?string
{
@$output = $this->pdf->Output($name, $destination);
if (is_string($output)) {
return $output;
}
}
/**
* @param string|array $html
* @return void
*/
public function writeHeader(string $html): void
{
@$this->pdf->setHeader($html);
}
/**
* @param string|array $html
* @return void
*/
public function writeFooter(string $html): void
{
@$this->pdf->setFooter($html);
}
public function writeBlankPage(): void
{
@$this->pdf->AddPage();
}
/**
* @param array $options
* @return void
*/
public function configurePDF(array $options): void
{
$configOptions = [
'mode' => $options['mode'] ?? '',
'page_size' => $options['page_size'] ?? 'A4',
'default_font_size' => $options['fontSize'] ?? 0,
'default_font' => $options['font'] ?? '',
'mgl' => $options['mgl'] ?? 15,
'mgr' => $options['mgr'] ?? 15,
'mgt' => $options['mgt'] ?? 16,
'mgb' => $options['mgb'] ?? 16,
'mgh' => $options['mgh'] ?? 9,
'mgf' => $options['mgf'] ?? 9,
'orientation' => $options['orientation'] ?? 'P'
];
@$this->pdf = new mPDF(
$configOptions['mode'],
$configOptions['page_size'],
$configOptions['default_font_size'],
$configOptions['default_font'],
$configOptions['mgl'],
$configOptions['mgr'],
$configOptions['mgt'],
$configOptions['mgb'],
$configOptions['mgh'],
$configOptions['mgf'],
$configOptions['orientation'],
);
@$this->pdf->SetAutoFont();
}
}

87
lib/PDF/PDFEngine.php Normal file
View file

@ -0,0 +1,87 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\PDF;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
* Class PDFEngine
* @package SuiteCRM\PDF
*/
abstract class PDFEngine
{
/**
* @param string $html
* @return void
*/
abstract public function writeHTML(string $html): void;
/**
* @param string|array $html
* @return void
*/
abstract public function writeFooter(string $html): void;
/**
* @param string|array $html
* @return void
*/
abstract public function writeHeader(string $html): void;
/**
* @return void
*/
abstract public function writeBlankPage(): void;
/**
* @param string $name
* @param string $destination
* @return string|void
*/
abstract public function outputPDF(string $name, string $destination): ?string;
/**
* @param array $options
* @return void
*/
abstract public function configurePDF(array $options): void;
}

175
lib/PDF/PDFWrapper.php Normal file
View file

@ -0,0 +1,175 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\PDF;
use SuiteCRM\PDF\Exceptions\PDFEngineNotFoundException;
use SuiteCRM\PDF\MPDF\MPDFEngine;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
* Class PDFWrapper
* @package SuiteCRM\PDF
*/
class PDFWrapper
{
/**
* @var array stores an associative array matching the PDF engine class name with the file it is stored in.
*/
private static $engines = [
'MPDFEngine' => [
'name' => 'MPDFEngine',
'FQN' => MPDFEngine::class,
'filepath' => 'lib/PDF/MPDF/MPDFEngine.php'
],
];
/** @var string Path to the folder where to load custom engines from */
private static $customEnginePath = __DIR__ . '/../../custom/Extension/PDFEngines/';
/**
* @param string $engineName
* @param string $file
* @param string $fqn
*/
public static function addEngine(string $engineName, string $file, string $fqn): void
{
self::$engines[$engineName] = [
'name' => $engineName,
'FQN' => $fqn,
'filepath' => $file,
];
}
/**
* @return PDFEngine
*/
public static function getPDFEngine(): PDFEngine
{
$defaultEngine = self::getDefaultEngine();
return self::fetchEngine($defaultEngine);
}
/**
* Retrieves the available PDF engine class names.
*
* @return string[]
*/
public static function getEngines(): array
{
$default = array_keys(self::$engines);
$custom = [];
foreach (glob(self::$customEnginePath . '*.php', GLOB_NOSORT) as $file) {
$file = pathinfo($file);
$custom[] = $file['filename'];
}
return array_merge($default, $custom);
}
/**
* @return string
*/
public static function getDefaultEngine(): string
{
$config = self::getPDFConfig('defaultEngine');
return $config ?? key(self::$engines);
}
/**
* @param string|PDFEngine $engineName
* @return PDFEngine
* @throws PDFEngineNotFoundException
*/
private static function fetchEngine($engineName): PDFEngine
{
if (is_subclass_of($engineName, PDFEngine::class, false)) {
return $engineName;
}
$customEnginePath = self::$customEnginePath . $engineName . '.php';
if (isset(self::$engines[$engineName])) {
$engine = self::$engines[$engineName];
} elseif (isset($customEnginePath)) {
self::addEngine($engineName, $customEnginePath, $engineName);
$engine = self::$engines[$engineName];
} else {
throw new PDFEngineNotFoundException(
"PDF engine not found for engine '$engineName''."
);
}
$filename = $engine['filepath'];
if (!is_file($filename)) {
throw new PDFEngineNotFoundException(
"Unable to find PDF file '$filename'' for engine '$engineName''."
);
}
/** @noinspection PhpIncludeInspection */
require_once $filename;
if (!is_subclass_of($engine['FQN'], PDFEngine::class)) {
throw new PDFEngineNotFoundException(
"The provided class '$engineName' is not a subclass of PDFEngine"
);
}
/** @var PDFEngine */
return new $engine['FQN']();
}
/**
* @param $key
* @return mixed|null
*/
private static function getPDFConfig($key)
{
global $sugar_config;
return $sugar_config['pdf'][$key] ?? null;
}
}

View file

@ -40,13 +40,13 @@
namespace SuiteCRM\Robo\Plugin\Commands;
use Robo\Tasks;
use RuntimeException;
use SuiteCRM\Utility\OperatingSystem;
use SuiteCRM\Robo\Traits\RoboTrait;
use Robo\Task\Base\loadTasks;
class BuildCommands extends \Robo\Tasks
class BuildCommands extends Tasks
{
use loadTasks;
use RoboTrait;
// define public methods as commands
@ -57,7 +57,7 @@ class BuildCommands extends \Robo\Tasks
* @param array $opts optional command line arguments
* theme - The name of the theme you want to compile css
* color-scheme - set which color scheme you wish to build
* @throws \RuntimeException
* @throws RuntimeException
*/
public function buildTheme(array $opts = ['theme' => '', 'color-scheme' => ''])
{
@ -97,7 +97,7 @@ class BuildCommands extends \Robo\Tasks
* Build SuiteP theme
* @param array $opts optional command line arguments
* color-scheme - set which color scheme you wish to build
* @throws \RuntimeException
* @throws RuntimeException
*/
public function buildSuiteP(array $opts = ['color-scheme' => ''])
{
@ -107,7 +107,7 @@ class BuildCommands extends \Robo\Tasks
/**
* @param string $colorScheme eg Dawn
* @param string $location eg Directory to work from
* @throws \RuntimeException
* @throws RuntimeException
*/
private function buildColorScheme($colorScheme, $location)
{

View file

@ -40,13 +40,13 @@
namespace SuiteCRM\Robo\Plugin\Commands;
use Robo\Tasks;
use RuntimeException;
use SuiteCRM\Utility\OperatingSystem;
use SuiteCRM\Robo\Traits\RoboTrait;
use Robo\Task\Base\loadTasks;
class CodeCoverageCommands extends \Robo\Tasks
class CodeCoverageCommands extends Tasks
{
use loadTasks;
use RoboTrait;
/**
@ -63,7 +63,7 @@ class CodeCoverageCommands extends \Robo\Tasks
if ($this->isEnvironmentTravisCI()) {
$range = $this->getCommitRangeForTravisCi();
} else {
throw new \RuntimeException('Unable to detect continuous integration environment');
throw new RuntimeException('Unable to detect continuous integration environment');
}
}
$this->generateCodeCoverageFile();

View file

@ -40,13 +40,12 @@
namespace SuiteCRM\Robo\Plugin\Commands;
use Robo\Task\Base\loadTasks;
use Robo\Tasks;
use SuiteCRM\Robo\Traits\RoboTrait;
use SuiteCRM\Utility\Paths;
class CodingStandardCommands extends \Robo\Tasks
class CodingStandardCommands extends Tasks
{
use loadTasks;
use RoboTrait;
/**

View file

@ -40,7 +40,7 @@
namespace SuiteCRM\Robo\Plugin\Commands;
use BeanFactory;
use Robo\Task\Base\loadTasks;
use Robo\Tasks;
use SuiteCRM\Robo\Traits\CliRunnerTrait;
use SuiteCRM\Robo\Traits\RoboTrait;
use SuiteCRM\Search\ElasticSearch\ElasticSearchIndexer;
@ -56,9 +56,8 @@ use SuiteCRM\Utility\BeanJsonSerializer;
*
* @package SuiteCRM\Robo\Plugin\Commands
*/
class ElasticSearchCommands extends \Robo\Tasks
class ElasticSearchCommands extends Tasks
{
use loadTasks;
use RoboTrait;
use CliRunnerTrait;

View file

@ -40,12 +40,11 @@
namespace SuiteCRM\Robo\Plugin\Commands;
use Robo\Task\Base\loadTasks;
use Robo\Tasks;
use SuiteCRM\Robo\Traits\RoboTrait;
class UpgradeCommands extends \Robo\Tasks
class UpgradeCommands extends Tasks
{
use loadTasks;
use RoboTrait;
/**

View file

@ -0,0 +1,178 @@
<?php
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Search\AOD;
use ACLController;
use BeanFactory;
use SecurityGroup;
use stdClass;
use SugarBean;
use SuiteCRM\Exception\Exception;
use SuiteCRM\Search\SearchEngine;
use SuiteCRM\Search\SearchQuery;
use SuiteCRM\Search\SearchResults;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
* Class LuceneSearchEngine
* @package SuiteCRM\Search\AOD
*/
class LuceneSearchEngine extends SearchEngine
{
/** @var bool|SugarBean */
private $index;
public function __construct()
{
$this->index = BeanFactory::getBean("AOD_Index")->getIndex();
}
/**
* Search function run when user goes to Show All and runs a search again. This outputs the search results
* calling upon the various listview display functions for each module searched on.
*
* @param SearchQuery $query
*
* @return SearchResults
* @throws Exception
*/
public function search(SearchQuery $query): SearchResults
{
$queryString = $query->getSearchString();
$start = microtime(true);
$hits = $this->runLucene($queryString);
$results = $this->parseHits($hits);
$end = microtime(true);
$elapsed = $end - $start;
return new SearchResults($results['modules'], true, $elapsed, count($results['hits']));
}
/**
*
* @param string $queryString
* @return array
*/
private function runLucene(string $queryString): array
{
$cachePath = 'cache/modules/AOD_Index/QueryCache/' . md5($queryString);
if (is_file($cachePath)) {
$mTime = filemtime($cachePath);
if ($mTime > (time() - 5 * 60)) {
$hits = unserialize(sugar_file_get_contents($cachePath));
}
}
if (!isset($hits)) {
$hits = $this->newHit($queryString);
}
return $hits;
}
/**
* @param string $queryString
* @return array
*/
private function newHit(string $queryString): array
{
global $current_user;
$tmphits = $this->index->find($queryString);
$hits = [];
foreach ($tmphits as $hit) {
$bean = BeanFactory::getBean($hit->record_module, $hit->record_id);
if (empty($bean)) {
continue;
}
if ($bean->bean_implements('ACL') && !is_admin($current_user)) {
$in_group = SecurityGroup::groupHasAccess($bean->module_dir, $bean->id, 'list');
$is_owner = $bean->isOwner($current_user->id);
$access = ACLController::checkAccess($bean->module_dir, 'list', $is_owner, 'module', $in_group);
if (!$access) {
continue;
}
}
$newHit = new stdClass;
$newHit->record_module = $hit->record_module;
$newHit->record_id = $hit->record_id;
$hits[] = $newHit;
}
$this->cacheQuery($queryString, $hits);
return $hits;
}
/**
* @param mixed $hits
* @return array
*/
private function parseHits(array $hits): array
{
$searchResults = [];
foreach ($hits as $hit) {
$recordModule = $hit->record_module;
$searchResults[$recordModule][] = $hit->record_id;
}
return [
'hits' => $hits,
'modules' => $searchResults
];
}
/**
* @param string $queryString
* @param array $resArray
*/
private function cacheQuery(string $queryString, array $resArray): void
{
$file = create_cache_directory('modules/AOD_Index/QueryCache/' . md5($queryString));
$out = serialize($resArray);
sugar_file_put_contents_atomic($file, $out);
}
}

View file

@ -0,0 +1,247 @@
<?php
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
/** @noinspection PhpUndefinedFieldInspection */
namespace SuiteCRM\Search\BasicSearch;
use BeanFactory;
use DBManagerFactory;
use JsonSchema\Exception\RuntimeException;
use ListViewData;
use LoggerManager;
use SuiteCRM\Exception\Exception;
use SuiteCRM\Search\SearchEngine;
use SuiteCRM\Search\SearchQuery;
use SuiteCRM\Search\SearchResults;
use VardefManager;
use SuiteCRM\Search\SearchModules;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
* Class BasicAndAodEngine
*/
class BasicSearchEngine extends SearchEngine
{
/* path to search form */
public $searchFormPath = 'include/SearchForm/SearchForm2.php';
/*search form class name*/
public $searchFormClass = 'SearchForm';
/**
* Search function run when user goes to Show All and runs a search again. This outputs the search results
* calling upon the various listview display functions for each module searched on.
*
* @param SearchQuery $query
*
* @return SearchResults
* @throws Exception
*/
public function search(SearchQuery $query): SearchResults
{
$modulesToSearch = $this->getSearchModules();
$start = microtime(true);
$results = $this->searchModules($modulesToSearch, $query->getSearchString());
$end = microtime(true);
$elapsed = $end - $start;
return new SearchResults($results['modules'], true, $elapsed, count($results['hits']));
}
/**
* @return array
*/
protected function getSearchModules(): array
{
$unifiedSearchModuleDisplay = SearchModules::getUnifiedSearchModulesDisplay();
require_once 'include/ListView/ListViewSmarty.php';
global $beanList, $current_user;
$users_modules = $current_user->getPreference('globalSearch', 'search');
$modulesToSearch = [];
if (!empty($users_modules)) {
// Use user's previous selections
foreach ($users_modules as $key => $value) {
if (isset($unifiedSearchModuleDisplay[$key]) && !empty($unifiedSearchModuleDisplay[$key]['visible'])) {
$modulesToSearch[$key] = $beanList[$key];
}
}
} else {
foreach ($unifiedSearchModuleDisplay as $module => $data) {
if (!empty($data['visible'])) {
$modulesToSearch[$module] = $beanList[$module];
}
}
}
$current_user->setPreference('globalSearch', $modulesToSearch, 'search');
return $modulesToSearch;
}
/**
*
* @param array $modulesToSearch
* @param string $searchQuery
* @return array
* @noinspection DisconnectedForeachInstructionInspection
* @noinspection PhpIncludeInspection
*/
private function searchModules(array $modulesToSearch, string $searchQuery): array
{
global $beanFiles;
$unifiedSearchModules = SearchModules::getUnifiedSearchModules();
$moduleResults = [];
$moduleCounts = [];
$listViewDefs = [];
if (!empty($searchQuery)) {
foreach ($modulesToSearch as $moduleName => $beanName) {
require_once $beanFiles[$beanName];
$seed = new $beanName();
$listViewData = new ListViewData();
// Retrieve the original list view defs and store for processing in case of custom layout changes
require(__DIR__ . '/../../../modules/' . $seed->module_dir . '/metadata/listviewdefs.php');
$origListViewDefs = $listViewDefs;
if (file_exists('custom/modules/' . $seed->module_dir . '/metadata/listviewdefs.php')) {
require('custom/modules/' . $seed->module_dir . '/metadata/listviewdefs.php');
}
if (!isset($listViewDefs[$seed->module_dir])) {
continue;
}
$unifiedSearchFields = [];
$innerJoins = [];
foreach ($unifiedSearchModules[$moduleName]['fields'] as $field => $def) {
$listViewCheckField = strtoupper($field);
// Check to see if the field is in listview defs
// Check to see if field is in original list view defs (in case we are using custom layout defs)
if (empty($listViewDefs[$seed->module_dir][$listViewCheckField]['default']) &&
!empty($origListViewDefs[$seed->module_dir][$listViewCheckField]['default'])) {
// If we are here then the layout has been customized, but the field is still needed for query
// creation
$listViewDefs[$seed->module_dir][$listViewCheckField] = $origListViewDefs[$seed->module_dir][$listViewCheckField];
}
if (!empty($def['innerjoin'])) {
if (empty($def['db_field'])) {
continue;
}
$def['innerjoin'] = str_replace('INNER', 'LEFT', $def['innerjoin']);
}
if (isset($seed->field_defs[$field]['type'])) {
$type = $seed->field_defs[$field]['type'];
if ($type === 'int' && !is_numeric($searchQuery)) {
continue;
}
}
$unifiedSearchFields[$moduleName] [$field] = $def;
$unifiedSearchFields[$moduleName] [$field]['value'] = $searchQuery;
}
/*
* Use searchForm2->generateSearchWhere() to create the search query, as it can generate SQL for the full set of comparisons required
* generateSearchWhere() expects to find the search conditions for a field in the 'value' parameter of the searchFields entry for that field
*/
require_once $beanFiles[$beanName];
$seed = new $beanName();
require_once $this->searchFormPath;
$searchForm = new $this->searchFormClass($seed, $moduleName);
$searchForm->setup(
[$moduleName => []],
$unifiedSearchFields,
'',
'saved_views'
);
$whereClauses = $searchForm->generateSearchWhere();
//add inner joins back into the where clause
$params = ['custom_select' => ""];
foreach ($innerJoins as $field => $def) {
if (isset($def['db_field'])) {
foreach ($def['db_field'] as $dbfield) {
$whereClauses[] = $dbfield . " LIKE '" . DBManagerFactory::getInstance()->quote($searchQuery) . "%'";
}
$params['custom_select'] .= ", $dbfield";
$params['distinct'] = true;
}
}
if (!empty($whereClauses)) {
$where = '((' . implode(' ) OR ( ', $whereClauses) . '))';
} else {
$where = '';
}
$listData = $listViewData->getListViewData($seed, $where, 0, -1, [], $params);
$moduleCounts[$moduleName] = $listData['pageData']['offsets']['total'];
foreach ($listData['data'] as $hit) {
$moduleResults[$moduleName][] = $hit['ID'];
}
}
}
return [
'hits' => $moduleCounts,
'modules' => $moduleResults
];
}
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -37,14 +37,14 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Search\ElasticSearch;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
use Elasticsearch\Client;
use Elasticsearch\Common\Exceptions\BadRequest400Exception;
use SuiteCRM\Search\ElasticSearch\ElasticSearchClientBuilder;
use SuiteCRM\Search\Exceptions\SearchInvalidRequestException;
use SuiteCRM\Exception\InvalidArgumentException;
use SuiteCRM\Search\SearchEngine;
use SuiteCRM\Search\SearchQuery;
use SuiteCRM\Search\SearchResults;
@ -67,7 +67,7 @@ class ElasticSearchEngine extends SearchEngine
public function __construct(Client $client = null)
{
global $sugar_config;
$this->client = $client === null ? ElasticSearchClientBuilder::getClient() : $client;
$this->client = $client ?? ElasticSearchClientBuilder::getClient();
if (!empty($sugar_config['search']['ElasticSearch']['index'])) {
$this->index = $sugar_config['search']['ElasticSearch']['index'];
@ -76,8 +76,9 @@ class ElasticSearchEngine extends SearchEngine
/**
* @inheritdoc
* @throws InvalidArgumentException
*/
public function search(SearchQuery $query)
public function search(SearchQuery $query): SearchResults
{
$this->validateQuery($query);
$params = $this->createSearchParams($query);
@ -90,26 +91,10 @@ class ElasticSearchEngine extends SearchEngine
return new SearchResults($results, true, $searchTime, $hits['hits']['total']);
}
/**
* @return string
*/
public function getIndex()
{
return $this->index;
}
/**
* @param string $index
*/
public function setIndex($index)
{
$this->index = $index;
}
/**
* @param SearchQuery $query
*/
protected function validateQuery(SearchQuery &$query)
protected function validateQuery(SearchQuery $query): void
{
$query->trim();
$query->convertEncoding();
@ -122,7 +107,7 @@ class ElasticSearchEngine extends SearchEngine
*
* @return array
*/
private function createSearchParams($query)
private function createSearchParams(SearchQuery $query): array
{
$searchStr = $query->getSearchString();
@ -174,15 +159,9 @@ class ElasticSearchEngine extends SearchEngine
*
* @return array
*/
private function runElasticSearch($params)
private function runElasticSearch(array $params): array
{
try {
$results = $this->client->search($params);
} /** @noinspection PhpRedundantCatchClauseInspection */ catch (BadRequest400Exception $exception) {
throw new SearchInvalidRequestException('The query was not valid.');
}
return $results;
return $this->client->search($params);
}
/**
@ -193,7 +172,7 @@ class ElasticSearchEngine extends SearchEngine
*
* @return array
*/
private function parseHits($hits)
private function parseHits(array $hits): array
{
$hitsArray = $hits['hits']['hits'];
@ -205,4 +184,20 @@ class ElasticSearchEngine extends SearchEngine
return $results;
}
/**
* @return string
*/
public function getIndex(): string
{
return $this->index;
}
/**
* @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.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -77,7 +77,7 @@ class SearchConfigurator
*
* @return SearchConfigurator
*/
public static function make()
public static function make(): SearchConfigurator
{
return new self();
}
@ -91,16 +91,12 @@ class SearchConfigurator
*
* @return SearchConfigurator
*/
public function setEngine($engine)
public function setEngine(string $engine): SearchConfigurator
{
if (empty($engine)) {
throw new InvalidArgumentException('$engine cannot be empty');
}
if (!is_string($engine)) {
throw new InvalidArgumentException('$engine must be a string');
}
$searchController = 'UnifiedSearch';
$enableAod = false;
@ -129,7 +125,7 @@ class SearchConfigurator
*
* @return SearchConfigurator
*/
public function save()
public function save(): SearchConfigurator
{
$this->configurator->saveConfig();

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -59,7 +59,7 @@ abstract class SearchEngine
*
* @return SearchResults
*/
abstract public function search(SearchQuery $query);
abstract public function search(SearchQuery $query): SearchResults;
/**
* Performs a search using the given query and shows a search view.
@ -68,7 +68,7 @@ abstract class SearchEngine
*
* @param SearchQuery $query
*/
public function searchAndDisplay(SearchQuery $query)
public function searchAndDisplay(SearchQuery $query): void
{
$this->validateQuery($query);
$this->displayForm($query);
@ -84,7 +84,7 @@ abstract class SearchEngine
*
* @param SearchQuery $query
*/
public function displayForm(SearchQuery $query)
public function displayForm(SearchQuery $query): void
{
$controller = new SearchFormController($query);
$controller->display();
@ -93,10 +93,10 @@ abstract class SearchEngine
/**
* Shows the default search results for the given search query and results.
*
* @param SearchQuery $query
* @param SearchQuery $query
* @param SearchResults $results
*/
public function displayResults(SearchQuery $query, SearchResults $results)
public function displayResults(SearchQuery $query, SearchResults $results): void
{
$controller = new SearchResultsController($query, $results);
$controller->display();
@ -114,7 +114,7 @@ abstract class SearchEngine
*
* @throws SearchInvalidRequestException if the query is not valid
*/
protected function validateQuery(SearchQuery &$query)
protected function validateQuery(SearchQuery $query): void
{
$query->trim();
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -39,6 +39,12 @@
namespace SuiteCRM\Search;
use LoggerManager;
use RuntimeException;
use UnifiedSearchAdvanced;
use BeanFactory;
use VardefManager;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
@ -47,8 +53,6 @@ require_once __DIR__ . '/../../modules/Home/UnifiedSearchAdvanced.php';
/**
* Class SearchModules fetches the search modules.
*
* This class currently depends on the Unified Advanced Search to find the modules.
*/
class SearchModules
{
@ -59,7 +63,7 @@ class SearchModules
*
* @return string[]
*/
public static function getModulesList()
public static function getModulesList(): array
{
$allModules = self::getAllModules();
$allModules = array_merge($allModules['enabled'], $allModules['disabled']);
@ -78,7 +82,7 @@ class SearchModules
*
* @return string[]
*/
public static function getEnabledModules()
public static function getEnabledModules(): array
{
$allModules = self::getAllModules();
$enabledModules = $allModules['enabled'];
@ -93,12 +97,246 @@ class SearchModules
}
/**
* saveGlobalSearchSettings
* This method handles the administrator's request to save the searchable modules selected and stores
* the results in the unified_search_modules_display.php file
*
*/
public static function saveGlobalSearchSettings(): void
{
if (isset($_REQUEST['enabled_modules'])) {
$unified_search_modules_display = self::getUnifiedSearchModulesDisplay();
$new_unified_search_modules_display = [];
foreach (explode(',', $_REQUEST['enabled_modules']) as $module) {
$new_unified_search_modules_display[$module]['visible'] = true;
}
foreach ($unified_search_modules_display as $module => $data) {
if (!isset($new_unified_search_modules_display[$module])) {
$new_unified_search_modules_display[$module]['visible'] = false;
}
}
self::writeUnifiedSearchModulesDisplayFile($new_unified_search_modules_display);
}
}
/**
* getUnifiedSearchModulesDisplay
*
* Returns the value of the $unified_search_modules_display variable which is based on the $unified_search_modules
* entries that have been selected to be allowed for searching.
*
* @return array $unified_search_modules_display Array value of modules that have enabled for searching
*/
public static function getUnifiedSearchModulesDisplay(): array
{
$unified_search_modules_display = [];
if (!file_exists(__DIR__ . '/../../custom/modules/unified_search_modules_display.php')) {
$unified_search_modules = self::getUnifiedSearchModules();
if (!empty($unified_search_modules)) {
foreach ($unified_search_modules as $module => $data) {
$unified_search_modules_display[$module]['visible'] = (!empty($data['default']));
}
}
self::writeUnifiedSearchModulesDisplayFile($unified_search_modules_display);
}
include(__DIR__ . '/../../custom/modules/unified_search_modules_display.php');
return $unified_search_modules_display;
}
/**
* getUnifiedSearchModules
*
* Returns the value of the $unified_search_modules variable based on the module's vardefs.php file
* and which fields are marked with the unified_search attribute.
*
* @return array metadata module definitions along with their fields
*/
public static function getUnifiedSearchModules(): array
{
// Make directory if it doesn't exist
$cachedir = sugar_cached('modules');
if (!file_exists($cachedir)) {
mkdir_recursive($cachedir);
}
$unified_search_modules = [];
// Load unified_search_modules.php file
$cachedFile = sugar_cached('modules/unified_search_modules.php');
if (!is_file($cachedFile)) {
self::buildCache();
}
/** @noinspection PhpIncludeInspection */
include $cachedFile;
return $unified_search_modules;
}
/**
* writeUnifiedSearchModulesDisplayFile
* Private method to handle writing the unified_search_modules_display value to file
*
* @param mixed $unified_search_modules_display The array of the unified search modules and their display attributes
* @return bool value indication whether or not file was successfully written
*/
private static function writeUnifiedSearchModulesDisplayFile($unified_search_modules_display): bool
{
if (is_null($unified_search_modules_display) || empty($unified_search_modules_display)) {
return false;
}
if (!write_array_to_file(
'unified_search_modules_display',
$unified_search_modules_display,
'custom/modules/unified_search_modules_display.php'
)) {
global $app_strings;
$msg = string_format($app_strings['ERR_FILE_WRITE'], ['custom/modules/unified_search_modules_display.php']);
LoggerManager::getLogger()->error($msg);
throw new RuntimeException($msg);
}
return true;
}
/** @noinspection PhpIncludeInspection */
public static function buildCache(): void
{
global $beanList, $beanFiles, $dictionary;
$supportedModules = [];
$metafiles = [];
$searchFields = [];
foreach ($beanList as $moduleName => $beanName) {
if (!isset($beanFiles[$beanName])) {
continue;
}
$beanName = BeanFactory::getObjectName($moduleName);
VardefManager::loadVardef($moduleName, $beanName);
// Obtain the field definitions used by generateSearchWhere (duplicate code in view.list.php)
if (file_exists('custom/modules/' . $moduleName . '/metadata/metafiles.php')) {
require('custom/modules/' . $moduleName . '/metadata/metafiles.php');
} elseif (file_exists('modules/' . $moduleName . '/metadata/metafiles.php')) {
require('modules/' . $moduleName . '/metadata/metafiles.php');
}
if (!empty($metafiles[$moduleName]['searchfields'])) {
/** @noinspection PhpIncludeInspection */
require $metafiles[$moduleName]['searchfields'];
} elseif (is_file("modules/{$moduleName}/metadata/SearchFields.php")) {
require "modules/{$moduleName}/metadata/SearchFields.php";
}
// Load custom SearchFields.php if it exists
if (is_file("custom/modules/{$moduleName}/metadata/SearchFields.php")) {
require "custom/modules/{$moduleName}/metadata/SearchFields.php";
}
// If there are $searchFields are empty, just continue, there are no search fields defined for the module
if (empty($searchFields[$moduleName])) {
continue;
}
$isCustomModule = preg_match('/^([a-z0-9]{1,5})_([a-z0-9_]+)$/i', $moduleName);
// If the bean supports unified search or if it's a custom module bean and unified search is not defined
if (!empty($dictionary[$beanName]['unified_search']) || $isCustomModule) {
$fields = [];
foreach ($dictionary [$beanName]['fields'] as $field => $def) {
// We cannot enable or disable unified_search for email in the vardefs as we don't actually have a vardef entry for 'email'
// the searchFields entry for 'email' doesn't correspond to any vardef entry. Instead it contains SQL to directly perform the search.
// So as a proxy we allow any field in the vardefs that has a name starting with 'email...' to be tagged with the 'unified_search' parameter
if (str_contains($field, 'email')) {
$field = 'email';
}
if (str_contains($field, 'phone')) {
$field = 'phone';
}
if (!empty($def['unified_search']) && isset($searchFields [$moduleName] [$field])) {
$fields [$field] = $searchFields [$moduleName] [$field];
}
}
foreach ($searchFields[$moduleName] as $field => $def) {
if (!empty($def['force_unifiedsearch'])) {
$fields[$field] = $def;
}
}
if (!empty($fields)) {
$supportedModules[$moduleName]['fields'] = $fields;
if (isset($dictionary[$beanName]['unified_search_default_enabled']) && $dictionary[$beanName]['unified_search_default_enabled'] === true) {
$supportedModules[$moduleName]['default'] = true;
} else {
$supportedModules[$moduleName]['default'] = false;
}
}
}
}
$cacheSearch = sugar_cached('modules/unified_search_modules.php');
ksort($supportedModules);
write_array_to_file('unified_search_modules', $supportedModules, $cacheSearch);
}
/**
* Retrieve the enabled and disabled modules used for global search.
* @return array
*/
private static function getAllModules()
public static function getAllModules(): array
{
$unifiedSearch = new \UnifiedSearchAdvanced();
$allModules = $unifiedSearch->retrieveEnabledAndDisabledModules();
return $allModules;
global $app_list_strings;
$unified_search_modules_display = self::getUnifiedSearchModulesDisplay();
$json_enabled = [];
$json_disabled = [];
foreach ($unified_search_modules_display as $module=>$data) {
$label = $app_list_strings['moduleList'][$module] ?? $module;
if ($data['visible'] === true) {
$json_enabled[] = ["module" => $module, 'label' => $label];
} else {
$json_disabled[] = ["module" => $module, 'label' => $label];
}
}
$cacheSearch = sugar_cached('modules/unified_search_modules.php');
if (!file_exists($cacheSearch)) {
self::buildCache();
}
include($cacheSearch);
//Now add any new modules that may have since been added to unified_search_modules.php
foreach ($unified_search_modules as $module=>$data) {
if (!isset($unified_search_modules_display[$module])) {
$label = $app_list_strings['moduleList'][$module] ?? $module;
if ($data['default']) {
$json_enabled[] = ["module" => $module, 'label' => $label];
} else {
$json_disabled[] = ["module" => $module, 'label' => $label];
}
}
}
return ['enabled' => $json_enabled, 'disabled' => $json_disabled];
}
}

View file

@ -1,10 +1,11 @@
<?php
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -39,6 +40,8 @@
namespace SuiteCRM\Search;
use JsonSerializable;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
@ -63,9 +66,9 @@ if (!defined('sugarEntry') || !sugarEntry) {
* @see fromArray()
* @author Vittorio Iocolano
*/
class SearchQuery implements \JsonSerializable
class SearchQuery implements JsonSerializable
{
const DEFAULT_SEARCH_SIZE = 10;
public const DEFAULT_SEARCH_SIZE = 10;
/** @var string Search query string */
private $query;
@ -76,25 +79,25 @@ class SearchQuery implements \JsonSerializable
/** @var null|string Optional parameter to specify the SearchEngine (unqualified class name) to use. */
private $engine;
/** @var array Structure containing additional search parameters */
private $options = [];
private $options;
/**
* SearchQuery constructor.
*
* @param string $searchString Search query
* @param string|null $engine Name of the search engine to use. `null` will use the default as specified by
* the config
* @param int $size Number of results
* @param int $from Offset of the search. Used for pagination
* @param array $options [optional] used for additional options by SearchEngines.
* @param string $searchString Search query
* @param string|null $engine Name of the search engine to use. `null` will use the default as specified by the
* config
* @param null $size Number of results
* @param int $from Offset of the search. Used for pagination
* @param array $options [optional] used for additional options by SearchEngines.
*/
private function __construct($searchString, $engine = null, $size = null, $from = 0, array $options = [])
private function __construct(string $searchString, $engine = null, $size = null, $from = 0, array $options = [])
{
$this->query = strval($searchString);
$this->size = $size ? intval($size) : $this->getDefaultSearchSize();
$this->from = intval($from);
$this->query = $searchString;
$this->size = $size ? (int)$size : $this->getDefaultSearchSize();
$this->from = (int)$from;
$this->options = $options;
$this->engine = $engine !== null ? strval($engine) : null;
$this->engine = $engine ? (string)$engine : $this->getDefaultEngine();
}
/**
@ -102,16 +105,21 @@ class SearchQuery implements \JsonSerializable
*
* `$size` and `$from` are for pagination.
*
* @param string $searchString A string containing the search query.
* @param int $size The number of results
* @param int $from The results offset (for pagination)
* @param string|null $engine Name of the search engine to use. Use default if `null`
* @param array|null $options Array with options (optional)
* @param string $searchString A string containing the search query.
* @param int $size The number of results
* @param int $from The results offset (for pagination)
* @param string|null $engine Name of the search engine to use. Use default if `null`
* @param array|null $options Array with options (optional)
*
* @return SearchQuery a fully built query
*/
public static function fromString($searchString, $size = 50, $from = 0, $engine = null, array $options = [])
{
public static function fromString(
string $searchString,
$size = 50,
$from = 0,
$engine = null,
array $options = []
): SearchQuery {
return new self($searchString, $engine, $size, $from, $options);
}
@ -127,7 +135,7 @@ class SearchQuery implements \JsonSerializable
*
* @return SearchQuery
*/
public static function fromRequestArray(array $request)
public static function fromRequestArray(array $request): SearchQuery
{
$searchQuery = self::filterArray($request, 'search-query-string', '', FILTER_SANITIZE_STRING);
$searchQueryAlt = self::filterArray($request, 'query_string', '', FILTER_SANITIZE_STRING);
@ -153,10 +161,10 @@ class SearchQuery implements \JsonSerializable
/**
* Makes a Query from a GET request.
*
* @see fromRequestArray
* @return SearchQuery
* @see fromRequestArray
*/
public static function fromGetRequest()
public static function fromGetRequest(): SearchQuery
{
return self::fromRequestArray($_GET);
}
@ -164,10 +172,10 @@ class SearchQuery implements \JsonSerializable
/**
* Validates and filters values from an array.
*
* @param array $array The array to filter
* @param string $key The key of the array to load
* @param mixed $default The default value in case the array value is empty
* @param null|string $filter Optional filter to be used. e.g. FILTER_SANITIZE_STRING
* @param array $array The array to filter
* @param string $key The key of the array to load
* @param mixed $default The default value in case the array value is empty
* @param null|string $filter Optional filter to be used. e.g. FILTER_SANITIZE_STRING
*
* @return mixed
*/
@ -191,9 +199,9 @@ class SearchQuery implements \JsonSerializable
*
* @return int
*/
public function getFrom()
public function getFrom(): int
{
return (int)$this->from;
return $this->from;
}
/**
@ -201,12 +209,42 @@ class SearchQuery implements \JsonSerializable
*
* @return int
*/
public function getSize()
public function getSize(): int
{
if ((int)$this->size < 0) {
if ($this->size < 0) {
$this->size = 1;
}
return (int)$this->size;
return $this->size;
}
/**
* Get the default engine by checking the config
*
* @return string
*/
public function getDefaultEngine(): string
{
global $sugar_config;
if (!empty($sugar_config['search']['defaultEngine'])) {
$defaultEngine = $sugar_config['search']['defaultEngine'];
if ($defaultEngine === 'BasicAndAodEngine') {
$luceneSearch = !empty($sugar_config['aod']['enable_aod']);
if (array_key_exists('showGSDiv', $_REQUEST) || !empty($_REQUEST['search_fallback'])) {
// Search from vanilla sugar search or request for the same
$luceneSearch = false;
}
return $luceneSearch ? 'LuceneSearchEngine' : 'BasicSearchEngine';
}
return (string)$sugar_config['search']['defaultEngine'];
}
return 'BasicSearchEngine';
}
/**
@ -214,25 +252,25 @@ class SearchQuery implements \JsonSerializable
*
* @return int
*/
public function getDefaultSearchSize()
public function getDefaultSearchSize(): int
{
global $sugar_config;
if(isset($sugar_config['search']['query_size'])){
return (int) $sugar_config['search']['query_size'];
if (isset($sugar_config['search']['query_size'])) {
return (int)$sugar_config['search']['query_size'];
}
if(isset($sugar_config['search']['pagination']['min'])){
return (int) $sugar_config['search']['pagination']['min'];
if (isset($sugar_config['search']['pagination']['min'])) {
return (int)$sugar_config['search']['pagination']['min'];
}
return static::DEFAULT_SEARCH_SIZE;
}
/**
* @return null|string
* @return string
*/
public function getEngine()
public function getEngine(): string
{
return $this->engine;
}
@ -250,7 +288,7 @@ class SearchQuery implements \JsonSerializable
/**
* @return array
*/
public function getOptions()
public function getOptions(): array
{
return $this->options;
}
@ -260,7 +298,7 @@ class SearchQuery implements \JsonSerializable
*
* @return bool
*/
public function isEmpty()
public function isEmpty(): bool
{
return empty($this->query);
}
@ -272,7 +310,7 @@ class SearchQuery implements \JsonSerializable
*
* @return string
*/
public function getSearchString()
public function getSearchString(): string
{
return $this->query;
}
@ -280,7 +318,7 @@ class SearchQuery implements \JsonSerializable
/**
* Makes the search string lowercase.
*/
public function toLowerCase()
public function toLowerCase(): void
{
$this->query = strtolower($this->query);
}
@ -288,7 +326,7 @@ class SearchQuery implements \JsonSerializable
/**
* Trims the search string.
*/
public function trim()
public function trim(): void
{
$this->query = trim($this->query);
}
@ -299,7 +337,7 @@ class SearchQuery implements \JsonSerializable
* @param $what
* @param $with
*/
public function replace($what, $with)
public function replace($what, $with): void
{
$this->query = str_replace($what, $with, $this->query);
}
@ -307,7 +345,7 @@ class SearchQuery implements \JsonSerializable
/**
* Removes forward facing slashes used for escaping in the query string.
*/
public function stripSlashes()
public function stripSlashes(): void
{
$this->query = stripslashes($this->query);
}
@ -315,7 +353,7 @@ class SearchQuery implements \JsonSerializable
/**
* Escapes regular expressions so that they are not recognised as such in the query string.
*/
public function escapeRegex()
public function escapeRegex(): void
{
$this->query = preg_quote($this->query, '/');
}
@ -323,7 +361,7 @@ class SearchQuery implements \JsonSerializable
/**
* Removes HTML entities and converts them in UTF-8 characters.
*/
public function convertEncoding()
public function convertEncoding(): void
{
$this->query = mb_convert_encoding($this->query, 'UTF-8', 'HTML-ENTITIES');
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -39,11 +39,11 @@
namespace SuiteCRM\Search;
use SugarBean;
use BeanFactory;
use LoggerManager;
use RuntimeException;
use SugarBean;
use SuiteCRM\Exception\Exception;
use SuiteCRM\Exception\InvalidArgumentException;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
@ -72,15 +72,22 @@ class SearchResults
/**
* SearchResults constructor.
*
* @param array $hits Contains the results ids
* @param bool $groupedByModule Flag specifying if the (nested) hits are grouped by the modules
* @param float $searchTime The number of seconds it took to perform the search
* @param int $total The number of total hits (without pagination)
* @param array $scores Contains the scores of each hit. This should match in structure with $hits
* @param array $options Similar to scores, but customisable by the search engine
* @param array $hits Contains the results ids
* @param bool $groupedByModule Flag specifying if the (nested) hits are grouped by the modules
* @param float|null $searchTime The number of seconds it took to perform the search
* @param int|null $total The number of total hits (without pagination)
* @param array|null $scores Contains the scores of each hit. This should match in structure with $hits
* @param array|null $options Similar to scores, but customisable by the search engine
* @throws InvalidArgumentException
*/
public function __construct(array $hits, $groupedByModule = true, $searchTime = null, $total = null, array $scores = null, array $options = null)
{
public function __construct(
array $hits,
$groupedByModule = true,
float $searchTime = null,
int $total = null,
array $scores = null,
array $options = null
) {
$this->hits = $hits;
$this->scores = $scores;
$this->options = $options;
@ -88,8 +95,8 @@ class SearchResults
$this->searchTime = $searchTime;
$this->total = $total;
if ($this->scores != null && count($hits) != count($scores)) {
throw new RuntimeException('The sizes of $hits and $scores must match.');
if ($this->scores !== null && count($hits) !== count($scores)) {
throw new InvalidArgumentException('The sizes of $hits and $scores must match.');
}
}
@ -100,7 +107,7 @@ class SearchResults
*
* @return array
*/
public function getHits()
public function getHits(): array
{
return $this->hits;
}
@ -108,15 +115,16 @@ class SearchResults
/**
* Fetches the results (originally just module->id) as Beans.
*
* @see getHits()
* @return array
* @throws Exception
* @see getHits()
*/
public function getHitsAsBeans()
public function getHitsAsBeans(): array
{
$hits = $this->hits;
$searchHits = $this->hits;
$parsed = [];
foreach ($hits as $module => $beans) {
foreach ($searchHits as $module => $beans) {
foreach ((array)$beans as $bean) {
$obj = BeanFactory::getBean($module, $bean);
@ -129,12 +137,12 @@ class SearchResults
}
if (!$obj) {
throw new Exception('Error retrieveing bean: ' . $module . ' [' . $bean . ']');
throw new Exception('Error retrieving bean: ' . $module . ' [' . $bean . ']');
}
$obj->load_relationships();
$fieldDefs = $obj->getFieldDefinitions();
$objUpdatedLinks = $this->updateFieldDefLinks($obj, $fieldDefs);
$parsed[$module][] = $objUpdatedLinks;
$parsed[$module][] = $this->updateFieldDefLinks($obj, $fieldDefs);
}
}
@ -147,13 +155,14 @@ class SearchResults
* @param array $fieldDefs
* @return SugarBean
*/
protected function updateFieldDefLinks(SugarBean $obj, $fieldDefs)
protected function updateFieldDefLinks(SugarBean $obj, array $fieldDefs): SugarBean
{
foreach ($fieldDefs as &$fieldDef) {
foreach ($fieldDefs as $fieldDef) {
if (isset($obj->{$fieldDef['name']})) {
$obj = $this->updateObjLinks($obj, $fieldDef);
}
}
return $obj;
}
@ -164,35 +173,43 @@ class SearchResults
* @param array $fieldDef
* @return SugarBean
*/
protected function updateObjLinks(SugarBean $obj, &$fieldDef)
protected function updateObjLinks(SugarBean $obj, array $fieldDef): SugarBean
{
if ($fieldDef['type'] == 'relate' && isset($fieldDef['link']) && isset($fieldDef['id_name']) && $fieldDef['id_name']) {
if (isset($fieldDef['link']) && !empty($fieldDef['id_name']) && $fieldDef['type'] === 'relate') {
$relId = $this->getRelatedId($obj, $fieldDef['id_name'], $fieldDef['link']);
if (!empty($relId)) {
$obj->{$fieldDef['name']} = $this->getLink($obj->{$fieldDef['name']}, $fieldDef['module'], $relId,
'DetailView');
$obj->{$fieldDef['name']} = $this->getLink(
$obj->{$fieldDef['name']},
$fieldDef['module'],
$relId,
'DetailView'
);
}
} elseif ($fieldDef['name'] == 'name') {
$obj->{$fieldDef['name']} = $this->getLink($obj->{$fieldDef['name']}, $obj->module_name, $obj->id, 'DetailView');
} elseif ($fieldDef['name'] === 'name') {
$obj->{$fieldDef['name']} = $this->getLink(
$obj->{$fieldDef['name']},
$obj->module_name,
$obj->id,
'DetailView'
);
}
return $obj;
}
/**
* resolve related record ID
*
* @param SugarBean $obj
* @param string $idName
* @param string $link
* @return null|string
*/
protected function getRelatedId(SugarBean $obj, $idName, $link)
protected function getRelatedId(SugarBean $obj, string $idName, string $link): string
{
$relId = $obj->id;
$relField = $idName;
if (isset($obj->$link)) {
$link2 = $obj->$link;
$link2Focus = $link2->getFocus();
$relId = $link2Focus->$relField;
$relId = $obj->$link->getFocus()->$relField;
if (is_object($relId)) {
if (method_exists($relId, "getFocus")) {
$relId = $relId->getFocus()->id;
@ -204,25 +221,26 @@ class SearchResults
$relId = $obj->$relField;
} else {
$relId = null;
LoggerManager::getLogger()->warn('Unresolved related ID for field: '. $relField);
LoggerManager::getLogger()->warn('Unresolved related ID for field: ' . $relField);
}
return $relId;
}
/**
*
* @global array $sugar_config
* @param string $label
* @param string $module
* @param string $record
* @param string $action
* @return string
* @global array $sugar_config
*/
protected function getLink($label, $module, $record, $action)
protected function getLink(string $label, string $module, string $record, string $action): string
{
global $sugar_config;
$link = "<a href=\"{$sugar_config['site_url']}/index.php?action={$action}&module={$module}&record={$record}&offset=1\"><span>{$label}</span></a>";
return $link;
return "<a href=\"{$sugar_config['site_url']}/index.php?action={$action}&module={$module}&record={$record}&offset=1\"><span>{$label}</span></a>";
}
/**
@ -230,7 +248,7 @@ class SearchResults
*
* @return array
*/
public function getScores()
public function getScores(): ?array
{
return $this->scores;
}
@ -240,7 +258,7 @@ class SearchResults
*
* @return int
*/
public function getTotal()
public function getTotal(): ?int
{
return $this->total;
}
@ -248,7 +266,7 @@ class SearchResults
/**
* @return array
*/
public function getOptions()
public function getOptions(): ?array
{
return $this->options;
}
@ -258,7 +276,7 @@ class SearchResults
*
* @return array
*/
public function getOption($key)
public function getOption(string $key): array
{
return $this->options[$key];
}
@ -268,7 +286,7 @@ class SearchResults
*
* @return float
*/
public function getSearchTime()
public function getSearchTime(): ?float
{
return $this->searchTime;
}
@ -276,7 +294,7 @@ class SearchResults
/**
* @return bool
*/
public function isGroupedByModule()
public function isGroupedByModule(): bool
{
return $this->groupedByModule;
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -43,6 +43,9 @@ if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
use SuiteCRM\Search\AOD\LuceneSearchEngine;
use SuiteCRM\Search\BasicSearch\BasicSearchEngine;
use SuiteCRM\Search\ElasticSearch\ElasticSearchEngine;
use SuiteCRM\Search\Exceptions\SearchEngineNotFoundException;
/**
@ -56,7 +59,21 @@ class SearchWrapper
* @var array stores an associative array matching the search engine class name with the file it is stored in.
*/
private static $engines = [
'ElasticSearchEngine' => 'lib/Search/ElasticSearch/ElasticSearchEngine.php',
'ElasticSearchEngine' => [
'name' => 'ElasticSearchEngine',
'FQN' => ElasticSearchEngine::class,
'filepath' => 'lib/Search/ElasticSearch/ElasticSearchEngine.php'
],
'BasicSearchEngine' => [
'name' => 'BasicSearchEngine',
'FQN' => BasicSearchEngine::class,
'filepath' => 'lib/Search/BasicSearch/BasicSearchEngine.php'
],
'LuceneSearchEngine' => [
'name' => 'LuceneSearchEngine',
'FQN' => LuceneSearchEngine::class,
'filepath' => 'lib/Search/AOD/LuceneSearchEngine.php'
],
];
/** @var string Path to the folder where to load custom engines from */
@ -69,7 +86,7 @@ class SearchWrapper
*
* @param SearchQuery $query
*/
public static function searchAndDisplay(SearchQuery $query)
public static function searchAndDisplay(SearchQuery $query): void
{
$engine = $query->getEngine() ?: self::getDefaultEngine();
@ -83,26 +100,31 @@ class SearchWrapper
* Results are grouped by module.
*
* @param string|SearchEngine $engine
* @param SearchQuery $query
* @param SearchQuery $query
*
* @return SearchResults
*/
public static function search($engine, SearchQuery $query)
public static function search($engine, SearchQuery $query): SearchResults
{
$engine = self::fetchEngine($engine);
$results = $engine->search($query);
return $results;
return $engine->search($query);
}
/**
* Binds a class name / engine name to a file.
*
* @param string $className
* @param string $engineName
* @param string $file
* @param $fqn
*/
public static function addEngine($className, $file)
public static function addEngine(string $engineName, string $file, $fqn): void
{
self::$engines[$className] = $file;
self::$engines[$engineName] = [
'name' => $engineName,
'FQN' => $fqn,
'filepath' => $file,
];
}
/**
@ -110,14 +132,15 @@ class SearchWrapper
*
* @return string[]
*/
public static function getEngines()
public static function getEngines(): array
{
$default = array_keys(self::$engines);
$custom = [];
foreach (glob(self::$customEnginePath . '*.php') as $file) {
foreach (glob(self::$customEnginePath . '*.php', GLOB_NOSORT) as $file) {
$file = pathinfo($file);
$custom[] = $file['filename'];
}
return array_merge($default, $custom);
}
@ -128,13 +151,11 @@ class SearchWrapper
*
* @return string
*/
public static function getDefaultEngine()
public static function getDefaultEngine(): string
{
$config = self::getSearchConfig('defaultEngine');
return $config === null
? key(self::$engines) // first engine in the array
: $config;
return $config ?? key(self::$engines);
}
/**
@ -144,7 +165,7 @@ class SearchWrapper
*
* @return string|null
*/
public static function getController()
public static function getController(): ?string
{
return self::getSearchConfig('controller');
}
@ -154,7 +175,7 @@ class SearchWrapper
*
* @return array|null
*/
public static function getModules()
public static function getModules(): ?array
{
return SearchModules::getEnabledModules();
}
@ -167,42 +188,41 @@ class SearchWrapper
*
* @param string|SearchEngine $engineName
*
* @throws SearchEngineNotFoundException
* @return SearchEngine
* @throws SearchEngineNotFoundException
*/
private static function fetchEngine($engineName)
private static function fetchEngine($engineName): SearchEngine
{
if (is_subclass_of($engineName, SearchEngine::class, false)) {
return $engineName;
}
if (!is_string($engineName)) {
throw new SearchEngineNotFoundException('$engineName should either be a string or a SearchEngine');
$customEnginePath = self::$customEnginePath . $engineName . '.php';
if (isset(self::$engines[$engineName])) {
$engine = self::$engines[$engineName];
} elseif (isset($customEnginePath)) {
self::addEngine($engineName, $customEnginePath, $engineName);
$engine = self::$engines[$engineName];
} else {
throw new SearchEngineNotFoundException("Search engine not found for engine '$engineName''.");
}
if (!preg_match("/^[a-zA-Z0-9_]*$/", $engineName)) {
throw new SearchEngineNotFoundException("'$engineName' is not a valid class name. Only letters, digits and underscores are allowed.");
}
$filename = $engine['filepath'];
$filename = isset(self::$engines[$engineName])
? self::$engines[$engineName]
: self::$customEnginePath . $engineName . '.php';
if (!file_exists($filename)) {
if (!is_file($filename)) {
throw new SearchEngineNotFoundException("Unable to find search file '$filename'' for engine '$engineName''.");
}
/** @noinspection PhpIncludeInspection */
require_once $filename;
if (!is_subclass_of($engineName, SearchEngine::class)) {
if (!is_subclass_of($engine['FQN'], SearchEngine::class)) {
throw new SearchEngineNotFoundException("The provided class '$engineName' is not a subclass of SearchEngine");
}
/** @var SearchEngine $engineName */
$engineName = new $engineName();
return $engineName;
/** @var SearchEngine */
return new $engine['FQN']();
}
/**
@ -219,10 +239,6 @@ class SearchWrapper
/** @noinspection PhpVariableNamingConventionInspection */
global $sugar_config;
if (!isset($sugar_config['search'][$key])) {
return null;
}
return $sugar_config['search'][$key];
return $sugar_config['search'][$key] ?? null;
}
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -37,10 +37,15 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Search\SqlSearch;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
use BeanFactory;
use DBManagerFactory;
use SuiteCRM\Exception\InvalidArgumentException;
use SuiteCRM\Search\SearchEngine;
use SuiteCRM\Search\SearchQuery;
use SuiteCRM\Search\SearchResults;
@ -59,8 +64,9 @@ class SimpleSqlSearchEngine extends SearchEngine
* @param SearchQuery $query
*
* @return SearchResults
* @throws InvalidArgumentException
*/
public function search(SearchQuery $query)
public function search(SearchQuery $query): SearchResults
{
$modules = SearchWrapper::getModules();
@ -83,16 +89,16 @@ class SimpleSqlSearchEngine extends SearchEngine
*
* @return array
*/
protected function filterTableStructure(array $fields)
protected function filterTableStructure(array $fields): array
{
$filteredFields = [];
foreach ($fields as $name => $type) {
if (strpos($type, 'varchar') == 0) {
if (strpos($type, 'varchar') === 0) {
$filteredFields[$name] = 'varchar';
}
if (strpos($type, 'text') == 0) {
if (strpos($type, 'text') === 0) {
$filteredFields[$name] = 'text';
}
}
@ -103,13 +109,12 @@ class SimpleSqlSearchEngine extends SearchEngine
/**
* Uses the DBManager getTableDescription method to retrieve the structure of the table in a name->type format.
*
* @see \DBManager::getTableDescription()
*
* @param string $table
*
* @return array
* @see \DBManager::getTableDescription()
*/
protected function getTableStructure($table)
protected function getTableStructure(string $table): array
{
$descriptions = DBManagerFactory::getInstance()->getTableDescription($table);
@ -123,7 +128,7 @@ class SimpleSqlSearchEngine extends SearchEngine
}
/** @inheritdoc */
protected function validateQuery(SearchQuery &$query)
protected function validateQuery(SearchQuery $query): void
{
parent::validateQuery($query);
$query->convertEncoding();
@ -133,14 +138,13 @@ class SimpleSqlSearchEngine extends SearchEngine
* Performs a search in a single module table and returns a list of ids.
*
* @param SearchQuery $query
* @param string $module
* @param string $module
*
* @return array
*/
private function searchModule(SearchQuery $query, $module)
private function searchModule(SearchQuery $query, string $module): array
{
$seed = BeanFactory::getBean($module);
$table = $seed->table_name;
$table = BeanFactory::getBean($module)->table_name;
$fields = $this->filterTableStructure($this->getTableStructure($table));
@ -150,10 +154,12 @@ class SimpleSqlSearchEngine extends SearchEngine
$db = DBManagerFactory::getInstance();
$result = $db->query($sql);
if (isset($db)) {
$result = $db->query($sql);
while ($row = $db->fetchRow($result)) {
$hits [] = $row['id'];
while ($row = $db->fetchRow($result)) {
$hits [] = $row['id'];
}
}
return $hits;
@ -163,12 +169,12 @@ class SimpleSqlSearchEngine extends SearchEngine
* Makes the search SQL query.
*
* @param SearchQuery $query
* @param string $table
* @param array $fields
* @param string $table
* @param array $fields
*
* @return string
*/
private function makeSearchQuery(SearchQuery $query, $table, array $fields)
private function makeSearchQuery(SearchQuery $query, string $table, array $fields): string
{
$sql = 'SELECT id FROM %s WHERE %s AND deleted=0';
@ -182,7 +188,6 @@ class SimpleSqlSearchEngine extends SearchEngine
$wheres[] = sprintf("%s LIKE '%s'", $name, $slashedString);
}
$sql = sprintf($sql, $table, implode(' OR ', $wheres));
return $sql;
return sprintf($sql, $table, implode(' OR ', $wheres));
}
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -39,6 +39,9 @@
namespace SuiteCRM\Search\UI\MVC;
use JsonException;
use LoggerManager;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
@ -66,11 +69,12 @@ abstract class Controller
*
* Always falls back to the 'display' method.
*/
public function handle()
public function handle(): void
{
if ($this->isActionRequest()) {
$methodName = $this->getActionName();
$this->$methodName();
return;
}
@ -80,7 +84,7 @@ abstract class Controller
/**
* Echoes the view.
*/
public function display()
public function display(): void
{
$this->view->preDisplay();
$this->view->display();
@ -91,7 +95,7 @@ abstract class Controller
*
* @param string $location
*/
public function redirect($location)
public function redirect(string $location): void
{
header("Location: $location");
exit;
@ -102,9 +106,9 @@ abstract class Controller
*
* @return bool
*/
public function isAjax()
public function isAjax(): bool
{
return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
}
/**
@ -112,11 +116,15 @@ abstract class Controller
*
* @param array $data
*/
public function yieldJson(array $data)
public function yieldJson(array $data): void
{
ob_clean(); // deletes the rest of the html previous to this.
ob_clean();
header('Content-Type: application/json');
echo json_encode($data);
try {
echo json_encode($data, JSON_THROW_ON_ERROR);
} catch (JSONException $e) {
LoggerManager::getLogger()->warn('Search UI JSON encoding failed: ' . $e->getMessage());
}
exit;
}
@ -125,7 +133,7 @@ abstract class Controller
*
* @return bool
*/
private function isActionRequest()
private function isActionRequest(): bool
{
return method_exists($this, $this->getActionName());
}
@ -135,7 +143,7 @@ abstract class Controller
*
* @return string
*/
private function getActionName()
private function getActionName(): string
{
return 'do' . filter_input(INPUT_GET, 'do', FILTER_SANITIZE_STRING);
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -60,7 +60,7 @@ abstract class View
*
* @param string $file
*/
public function __construct($file)
public function __construct(string $file)
{
$this->smarty = new Sugar_Smarty();
$this->templateFile = $file;
@ -69,7 +69,7 @@ abstract class View
/**
* @return Sugar_Smarty
*/
public function getTemplate()
public function getTemplate(): Sugar_Smarty
{
return $this->smarty;
}
@ -77,14 +77,14 @@ abstract class View
/**
* Where to assign vars to the template.
*/
public function preDisplay()
public function preDisplay(): void
{
}
/**
* Renders the template.
*/
public function display()
public function display(): void
{
$this->smarty->display($this->templateFile);
}
@ -92,7 +92,7 @@ abstract class View
/**
* @return string
*/
public function getTemplateFile()
public function getTemplateFile(): string
{
return $this->templateFile;
}
@ -100,7 +100,7 @@ abstract class View
/**
* @param string $templateFile
*/
public function setTemplateFile($templateFile)
public function setTemplateFile(string $templateFile): void
{
$this->templateFile = $templateFile;
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -58,18 +58,23 @@ class SearchFormController extends Controller
*
* @param SearchQuery $query
*/
public function __construct($query)
public function __construct(SearchQuery $query)
{
parent::__construct(new SearchFormView());
$this->query = $query;
}
public function display()
public function display(): void
{
$this->view->getTemplate()->assign('searchQueryString', htmlspecialchars($this->query->getSearchString(), ENT_COMPAT | ENT_XHTML, 'UTF-8'));
$this->view->getTemplate()->assign('searchQuerySize', $this->query->getSize());
$this->view->getTemplate()->assign('searchQueryFrom', $this->query->getFrom());
$this->view->getTemplate()->assign('searchQueryEngine', $this->query->getEngine());
$smarty = $this->view->getTemplate();
$smarty->assign(
'searchQueryString',
htmlspecialchars($this->query->getSearchString(), ENT_COMPAT | ENT_XHTML, 'UTF-8')
);
$smarty->assign('searchQuerySize', $this->query->getSize());
$smarty->assign('searchQueryFrom', $this->query->getFrom());
$smarty->assign('searchQueryEngine', $this->query->getEngine());
parent::display();
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -60,7 +60,7 @@ class SearchFormView extends View
}
/** @inheritdoc */
public function display()
public function display(): void
{
$sizes = $this->makeSizesFromConfig();
$engines = [];
@ -80,25 +80,25 @@ class SearchFormView extends View
*
* @return array
*/
protected function makeSizesFromConfig()
protected function makeSizesFromConfig(): ?array
{
global $sugar_config;
if (!isset($sugar_config['search']['pagination']['min'])) {
LoggerManager::getLogger()->warn('Configuration does not contains value for search pagination min');
}
if (!isset($sugar_config['search']['pagination']['step'])) {
LoggerManager::getLogger()->warn('Configuration does not contains value for search pagination step');
}
if (!isset($sugar_config['search']['pagination']['max'])) {
LoggerManager::getLogger()->warn('Configuration does not contains value for search pagination max');
}
$min = isset($sugar_config['search']['pagination']['min']) ? $sugar_config['search']['pagination']['min'] : null;
$step = isset($sugar_config['search']['pagination']['step']) ? $sugar_config['search']['pagination']['step'] : null;
$max = isset($sugar_config['search']['pagination']['max']) ? $sugar_config['search']['pagination']['max'] : null;
$min = $sugar_config['search']['pagination']['min'] ?? null;
$step = $sugar_config['search']['pagination']['step'] ?? null;
$max = $sugar_config['search']['pagination']['max'] ?? null;
try {
return $this->makeSizes($min, $step, $max);
@ -110,32 +110,31 @@ class SearchFormView extends View
/**
* Makes an array with the page size from the given parameters.
*
* @param int $min
* @param int $step
* @param int $max
*
* @throws InvalidArgumentException in case of failure
* @param int|null $min
* @param int|null $step
* @param int|null $max
*
* @return array
* @throws InvalidArgumentException in case of failure
*/
protected function makeSizes($min, $step, $max)
protected function makeSizes(?int $min, ?int $step, ?int $max): array
{
$min = intval($min);
$step = intval($step);
$max = intval($max);
$min = (int)$min;
$step = (int)$step;
$max = (int)$max;
if (!is_integer($min) || !is_integer($step) || !is_integer($max)) {
if (!is_int($min) || !is_int($step) || !is_int($max)) {
throw new InvalidArgumentException('Arguments must be integers');
}
if ($max === 0 || $step === 0 || $min === 0) {
throw new InvalidArgumentException('Arguments cannot be zero');
}
if ($min > $max) {
throw new InvalidArgumentException('$min must be smaller than $max');
}
if ($max == 0 || $min == 0 || $min == 0) {
throw new InvalidArgumentException('Arguments cannot be zero');
}
$sizes = [];
for ($it = $min; $it <= $max; $it += $step) {

View file

@ -1,11 +1,10 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -46,7 +45,9 @@ if (!defined('sugarEntry') || !sugarEntry) {
use BeanFactory;
use Exception;
use LoggerManager;
use SugarBean;
use SuiteCRM\ErrorMessageException;
use SuiteCRM\LangText;
use SuiteCRM\Search\Exceptions\SearchException;
use SuiteCRM\Search\SearchQuery;
@ -75,7 +76,7 @@ class SearchResultsController extends Controller
/**
* SearchResultsController constructor.
*
* @param SearchQuery $query
* @param SearchQuery $query
* @param SearchResults $results
*/
public function __construct(SearchQuery $query, SearchResults $results)
@ -85,9 +86,15 @@ class SearchResultsController extends Controller
$this->results = $results;
}
public function display()
public function display(): void
{
$headers = $this->getListViewHeaders();
$headers = [];
try {
$headers = $this->getListViewHeaders();
} catch (Exception $e) {
LoggerManager::getLogger()->warn('Failed to fetch list-view headers: ' . $e->getMessage());
}
$total = $this->results->getTotal();
if ($total > 1) {
@ -99,7 +106,7 @@ class SearchResultsController extends Controller
$page = (int)($from / $size) + 1;
$prev = $page > 1;
$next = $total - $from > $size;
$last = (int)($total / $size) + ($total%$size === 0 ? 0 : 1);
$last = (int)($total / $size) + ($total % $size === 0 ? 0 : 1);
$this->view->getTemplate()->assign('pagination', [
'prev' => $prev,
@ -115,11 +122,16 @@ class SearchResultsController extends Controller
throw new SearchException('Search Size can not be Zero.', SearchException::ZERO_SIZE);
}
}
$this->view->getTemplate()->assign('total', $total);
$this->view->getTemplate()->assign('headers', $headers);
$this->view->getTemplate()->assign('results', $this->results);
$this->view->getTemplate()->assign('resultsAsBean', $this->results->getHitsAsBeans());
$smarty = $this->view->getTemplate();
$smarty->assign('total', $total);
$smarty->assign('headers', $headers);
$smarty->assign('results', $this->results);
try {
$smarty->assign('resultsAsBean', $this->results->getHitsAsBeans());
} catch (\SuiteCRM\Exception\Exception $e) {
LoggerManager::getLogger()->fatal("Failed to retrieve ElasticSearch options");
}
parent::display();
}
@ -127,25 +139,30 @@ class SearchResultsController extends Controller
/**
*
* @return array of header info
* @throws Exception
* @throws SearchException
*/
protected function getListViewHeaders()
protected function getListViewHeaders(): array
{
$headers = [];
$listViewDefs = $this->getListViewDefs();
foreach ($listViewDefs as $module => $listViewDef) {
foreach ($this->getListViewDefs() as $module => $listViewDef) {
$bean = BeanFactory::getBean($module);
if (!$bean) {
throw new Exception('Module bean not found for search results: ' . $module);
throw new SearchException('Module bean not found for search results: ' . $module);
}
foreach ($listViewDef as $fieldKey => $fieldValue) {
if (isset($fieldValue['default']) && $fieldValue['default']) {
$header = $this->getListViewHeader($bean, $fieldKey, $fieldValue);
if (!empty($fieldValue['default'])) {
$header = [];
try {
$header = $this->getListViewHeader($bean, $fieldKey, $fieldValue);
} catch (ErrorMessageException $e) {
LoggerManager::getLogger()->warn('Failed to fetch list-view headers: ' . $e->getMessage());
}
$headers[$module][$fieldKey] = array_merge($fieldValue, $header);
}
}
}
return $headers;
}
@ -153,20 +170,21 @@ class SearchResultsController extends Controller
*
* @return array of list view definitions
*/
protected function getListViewDefs()
protected function getListViewDefs(): array
{
$listViewDefs = [];
if ($this->results->isGroupedByModule()) {
$modules = array_keys($this->results->getHits());
foreach ($modules as $module) {
foreach (array_keys($this->results->getHits()) as $module) {
$viewList = new ViewList();
$viewList->type = 'list';
$viewList->module = $module;
$metaDataFile = $viewList->getMetaDataFile();
/** @noinspection PhpIncludeInspection */
require($metaDataFile);
}
}
return $listViewDefs;
}
@ -176,16 +194,17 @@ class SearchResultsController extends Controller
* @param string $fieldKey
* @param string $fieldValue
* @return array of header
* @throws ErrorMessageException
*/
protected function getListViewHeader(SugarBean $bean, $fieldKey, $fieldValue)
protected function getListViewHeader(SugarBean $bean, string $fieldKey, $fieldValue): array
{
$fieldDef = $bean->getFieldDefinition(strtolower($fieldKey));
$header = [
return [
'label' => $this->getListViewHeaderLabel($bean, $fieldValue, $fieldDef),
'comment' => isset($fieldDef['comment']) ? $fieldDef['comment'] : null,
'comment' => $fieldDef['comment'] ?? null,
'field' => $fieldDef['name'],
];
return $header;
}
/**
@ -193,9 +212,10 @@ class SearchResultsController extends Controller
* @param SugarBean $bean
* @param array $fieldValue
* @param array $fieldDef
* @return array of label
* @return string|null of label
* @throws ErrorMessageException
*/
protected function getListViewHeaderLabel(SugarBean $bean, $fieldValue, $fieldDef)
protected function getListViewHeaderLabel(SugarBean $bean, $fieldValue, $fieldDef): ?string
{
$label = isset($fieldValue['label']) ?
LangText::get(
@ -212,6 +232,7 @@ class SearchResultsController extends Controller
LangText::get($fieldDef['vname'], null, LangText::USING_ALL_STRINGS, true, false, $bean->module_name) :
null;
}
return $label;
}
}

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -44,6 +44,7 @@ if (!defined('sugarEntry') || !sugarEntry) {
}
use Elasticsearch\Common\Exceptions\NoNodesAvailableException;
use Exception;
use SuiteCRM\Search\Exceptions\SearchEngineNotFoundException;
use SuiteCRM\Search\Exceptions\SearchException;
use SuiteCRM\Search\Exceptions\SearchInvalidRequestException;
@ -71,10 +72,10 @@ class SearchThrowableHandler
/**
* SearchThrowableHandler constructor.
*
* @param Throwable $throwable
* @param Throwable $throwable
* @param SearchQuery $query
*/
public function __construct($throwable, SearchQuery $query)
public function __construct(Throwable $throwable, SearchQuery $query)
{
$this->throwable = $throwable;
$this->query = $query;
@ -85,7 +86,7 @@ class SearchThrowableHandler
*
* If developer mode is enabled, a full exception page will be shown.
*/
public function handle()
public function handle(): void
{
global $sugar_config;
@ -97,6 +98,7 @@ class SearchThrowableHandler
if ($sugar_config['developerMode'] === true) {
$this->printStackTrace();
return;
}
@ -108,30 +110,37 @@ class SearchThrowableHandler
*
* @return string
*/
private function getFriendlyMessage()
private function getFriendlyMessage(): string
{
global $mod_strings;
switch (get_class($this->throwable)) {
case SearchUserFriendlyException::class:
return $this->throwable->getMessage();
$message = $this->throwable->getMessage();
break;
case SearchInvalidRequestException::class:
return $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_SEARCH_INVALID_REQUEST'];
$message = $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_SEARCH_INVALID_REQUEST'];
break;
case SearchEngineNotFoundException::class:
return $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_SEARCH_ENGINE_NOT_FOUND'];
$message = $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_SEARCH_ENGINE_NOT_FOUND'];
break;
case NoNodesAvailableException::class:
return $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_NO_NODES_AVAILABLE'];
$message = $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_NO_NODES_AVAILABLE'];
break;
case SearchException::class:
return $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_SEARCH'];
$message = $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_SEARCH'];
break;
default:
return $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_DEFAULT'];
$message = $mod_strings['LBL_ELASTIC_SEARCH_EXCEPTION_DEFAULT'];
}
return $message;
}
/**
* Cancels the current output and prints a full screen detailed exception page
*/
private function printStackTrace()
private function printStackTrace(): void
{
$whoops = new Run;
$handler = new PrettyPageHandler;
@ -142,7 +151,7 @@ class SearchThrowableHandler
$whoops->pushHandler($handler);
$whoops->register();
$whoops->handleException($this->throwable);
echo $whoops->handleException($this->throwable);
}
/**
@ -150,7 +159,7 @@ class SearchThrowableHandler
*
* @return array
*/
private function getSearchWrapperStatus()
private function getSearchWrapperStatus(): ?array
{
try {
return [
@ -159,7 +168,7 @@ class SearchThrowableHandler
'Default Search Engine' => SearchWrapper::getDefaultEngine(),
'Friendly Error Message' => $this->getFriendlyMessage(),
];
} catch (\Exception $exception) {
} catch (Exception $exception) {
return ['error' => 'failed to get SearchWrapper status'];
}
}
@ -167,7 +176,7 @@ class SearchThrowableHandler
/**
* Prints the error on the page.
*/
private function printFriendlyMessage()
private function printFriendlyMessage(): void
{
global $mod_strings;

View file

@ -3,7 +3,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -44,54 +44,53 @@
{*hidden input to handle actions*}
{search_controller}
<table width="600" cellspacing="1" border="0">
<tbody>
<tr style="padding-bottom: 10px">
<td class="submitButtons" colspan="8" nowrap="">
<label for="searchFieldMain" class="text-muted hide">{$APP.LBL_SEARCH_QUERY}</label>
<input id="searchFieldMain" title="{$APP.LBL_SEARCH_TEXT_FIELD_TITLE_ATTR}" class="searchField" type="text" size="80" name="search-query-string" value="{$searchQueryString}" autofocus>
<input type="submit" onclick="searchForm.onSubmitClick(this);" title="{$APP.LBL_SEARCH_SUBMIT_FIELD_TITLE_ATTR}" class="button primary" value="{$APP.LBL_SEARCH_SUBMIT_FIELD_VALUE}">&nbsp;
</td>
<tr>
<tr height="5">
<td></td>
</tr>
<tr style="padding-top: 10px;">
<td colspan="6" style="padding-left: 20px;" nowrap="">
<div id="inlineGlobalSearch">
<table style="margin-bottom:0px;" cellspacing="0" cellpadding="0" border="0">
<tbody>
<td>
<label for="search-query-size" class="text-muted">{$APP.LBL_SEARCH_RESULTS_PER_PAGE}</label>
{html_options options=$sizeOptions selected=$searchQuerySize id="search-query-size" name="search-query-size"}
&nbsp;&nbsp;
<input type="hidden" name="search-query-from" value="{$searchQueryFrom}">
<table>
<tbody>
<tr style="padding-bottom: 10px">
<td class="submitButtons" colspan="8" nowrap="">
<label for="searchFieldMain" class="text-muted hide">{$APP.LBL_SEARCH_QUERY}</label>
<input id="searchFieldMain" title="{$APP.LBL_SEARCH_TEXT_FIELD_TITLE_ATTR}" class="searchField"
type="text" size="80" name="search-query-string" value="{$searchQueryString}" autofocus>
<input type="submit" onclick="searchForm.onSubmitClick(this);"
title="{$APP.LBL_SEARCH_SUBMIT_FIELD_TITLE_ATTR}" class="button primary"
value="{$APP.LBL_SEARCH_SUBMIT_FIELD_VALUE}">&nbsp;
</td>
<tr>
<tr style="padding-top: 10px;">
<td colspan="6" style="padding-left: 20px;" nowrap="">
<div id="inlineGlobalSearch">
<table style="margin-bottom:0;">
<tbody>
<label for="search-query-size"
class="text-muted">{$APP.LBL_SEARCH_RESULTS_PER_PAGE}</label>
{html_options options=$sizeOptions selected=$searchQuerySize id="search-query-size" name="search-query-size"}
&nbsp;&nbsp;
<input type="hidden" name="search-query-from" value="{$searchQueryFrom}">
{if $engineOptions|@count gt 1}
<label for="search-query-size" class="text-muted">{$APP.LBL_SEARCH_ENGINE}</label>
{html_options options=$engineOptions selected=$searchQueryEngine id="search-engine" name="search-engine"}
{else}
{assign var=firstRow value=$engineOptions|@key}
<input type="hidden" name="search-engine" value="{$firstRow}" />
{/if}
</td>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
{if $engineOptions|@count gt 1}
<label for="search-query-size" class="text-muted">{$APP.LBL_SEARCH_ENGINE}</label>
{html_options options=$engineOptions selected=$searchQueryEngine id="search-engine" name="search-engine"}
{else}
{assign var=firstRow value=$engineOptions|@key}
<input type="hidden" name="search-engine" value="{$firstRow}" />
{/if}
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</form>
<script>
{literal}
var searchForm = {
onSubmitClick: function(e) {
// jump to the first page on new results list
$('input[name="search-query-from"]').val(0);
return true;
}
};
var searchForm = {
onSubmitClick: function (e) {
// jump to the first page on new results list
$('input[name="search-query-from"]').val(0);
return true;
}
};
{/literal}
</script>
</div>

View file

@ -1,5 +1,4 @@
<?php
/**
* Advanced OpenReports, SugarCRM Reporting.
* @package Advanced OpenReports for SugarCRM
@ -23,10 +22,15 @@
* @author SalesAgility <info@salesagility.com>
*/
use SuiteCRM\PDF\Exceptions\PDFException;
use SuiteCRM\PDF\PDFWrapper;
require_once("modules/AOW_WorkFlow/aow_utils.php");
require_once("modules/AOR_Reports/aor_utils.php");
require_once __DIR__ . '/../../modules/AOW_WorkFlow/aow_utils.php';
require_once __DIR__ . '/../../modules/AOR_Reports/aor_utils.php';
/**
* Class AOR_ReportsController
*/
class AOR_ReportsController extends SugarController
{
protected function action_getModuleFields()
@ -172,7 +176,7 @@ class AOR_ReportsController extends SugarController
set_time_limit(0);
if (!$this->bean->ACLAccess('Export')) {
SugarApplication::appendErrorMessage(translate('LBL_NO_ACCESS', 'ACL'));
SugarApplication::redirect("index.php?module=AOR_Reports&action=DetailView&record=".$this->bean->id);
SugarApplication::redirect("index.php?module=AOR_Reports&action=DetailView&record=" . $this->bean->id);
sugar_die('');
}
$this->bean->user_parameters = requestToUserParameters($this->bean);
@ -180,48 +184,45 @@ class AOR_ReportsController extends SugarController
die;
}
protected function action_downloadPDF()
/**
* @throws Exception
* @noinspection PhpMethodParametersCountMismatchInspection
*/
protected function action_downloadPDF(): void
{
if (!$this->bean->ACLAccess('Export')) {
SugarApplication::appendErrorMessage(translate('LBL_NO_ACCESS', 'ACL'));
SugarApplication::redirect("index.php?module=AOR_Reports&action=DetailView&record=".$this->bean->id);
SugarApplication::redirect('index.php?module=AOR_Reports&action=DetailView&record=' . $this->bean->id);
sugar_die('');
}
$errorLevelStored = error_reporting();
error_reporting(0);
require_once('modules/AOS_PDF_Templates/PDF_Lib/mpdf.php');
error_reporting($errorLevelStored);
$d_image = explode('?', SugarThemeRegistry::current()->getImageURL('company_logo.png'));
$d_image = explode('?', SugarThemeRegistry::current()->getImageURL('company_logo.png'), 2);
$graphs = $_POST["graphsForPDF"];
$graphHtml = "<div class='reportGraphs' style='width:100%; text-align:center;'>";
$chartsPerRow = $this->bean->graphs_per_row;
$countOfCharts = count($graphs);
if ($countOfCharts > 0) {
$width = ((int)100 / $chartsPerRow);
if (is_countable($graphs)) {
$countOfCharts = count($graphs);
}
if (!empty($countOfCharts) && $countOfCharts > 0) {
$width = (100 / $chartsPerRow);
$modulusRemainder = $countOfCharts % $chartsPerRow;
if ($modulusRemainder > 0) {
$modulusWidth = ((int)100 / $modulusRemainder);
$modulusWidth = (100 / $modulusRemainder);
$itemsWithModulus = $countOfCharts - $modulusRemainder;
}
for ($x = 0; $x < $countOfCharts; $x++) {
foreach ($graphs as $x => $xValue) {
if (is_null($itemsWithModulus) || $x < $itemsWithModulus) {
$graphHtml .= "<img src='.$graphs[$x].' style='width:$width%;' />";
$graphHtml .= "<img src='.$xValue.' style='width:$width%;' />";
} else {
$graphHtml .= "<img src='.$graphs[$x].' style='width:$modulusWidth%;' />";
$graphHtml .= "<img src='.$xValue.' style='width:$modulusWidth%;' />";
}
}
/* foreach($graphs as $g)
{
$graphHtml.="<img src='.$g.' style='width:$width%;' />";
}*/
$graphHtml .= "</div>";
}
@ -249,25 +250,23 @@ class AOR_ReportsController extends SugarController
</table><br />' . $graphHtml;
$this->bean->user_parameters = requestToUserParameters($this->bean);
$printable = $this->bean->build_group_report(-1, false);
$stylesheet = file_get_contents(SugarThemeRegistry::current()->getCSSURL('style.css', false));
ob_clean();
try {
$pdf = new mPDF('en', 'A4', '', 'DejaVuSansCondensed');
$pdf->SetAutoFont();
$pdf->setFooter('{PAGENO}');
$pdf->WriteHTML($stylesheet, 1);
$pdf->SetDefaultBodyCSS('background-color', '#FFFFFF');
unset($pdf->cssmgr->CSS['INPUT']['FONT-SIZE']);
$pdf->WriteHTML($head, 2);
$pdf->WriteHTML($printable, 3);
$pdf->Output($this->bean->name . '.pdf', "D");
} catch (mPDF_exception $e) {
echo $e;
}
die;
try {
$pdf = PDFWrapper::getPDFEngine();
$pdf->configurePDF([
'mode' => 'en',
'font' => 'DejaVuSansCondensed',
]);
$pdf->writeFooter('{PAGENO}');
$pdf->writeHTML($stylesheet, 1);
$pdf->writeHTML($head, 2);
$pdf->writeHTML($printable, 3);
$pdf->outputPDF($this->bean->name . '.pdf', 'D');
} catch (PDFException $e) {
LoggerManager::getLogger()->warn('PDFException: ' . $e->getMessage());
}
}
protected function action_getModuleFunctionField()
@ -282,9 +281,9 @@ class AOR_ReportsController extends SugarController
if ($view == 'EditView') {
echo "<select type='text' style='width:100px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . get_select_options_with_id(
$app_list_strings['aor_function_list'],
$value
) . "</select>";
$app_list_strings['aor_function_list'],
$value
) . "</select>";
} else {
echo $app_list_strings['aor_function_list'][$value];
}
@ -383,9 +382,9 @@ class AOR_ReportsController extends SugarController
$app_list_strings['aor_operator_list'];
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . get_select_options_with_id(
$app_list_strings['aor_operator_list'],
$value
) . "</select>";
$app_list_strings['aor_operator_list'],
$value
) . "</select>";
} else {
echo $app_list_strings['aor_operator_list'][$value];
}
@ -465,9 +464,9 @@ class AOR_ReportsController extends SugarController
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . get_select_options_with_id(
$app_list_strings['aor_condition_type_list'],
$value
) . "</select>";
$app_list_strings['aor_condition_type_list'],
$value
) . "</select>";
} else {
echo $app_list_strings['aor_condition_type_list'][$value];
}
@ -547,9 +546,9 @@ class AOR_ReportsController extends SugarController
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . get_select_options_with_id(
$app_list_strings['aor_action_type_list'],
$value
) . "</select>";
$app_list_strings['aor_action_type_list'],
$value
) . "</select>";
} else {
echo $app_list_strings['aor_action_type_list'][$value];
}
@ -589,10 +588,10 @@ class AOR_ReportsController extends SugarController
}
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . getModuleFields(
$module,
$view,
$value
) . "</select>";
$module,
$view,
$value
) . "</select>";
} else {
echo getModuleFields($module, $view, $value);
}
@ -606,9 +605,9 @@ class AOR_ReportsController extends SugarController
case 'Period':
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . getDropdownList(
'date_time_period_list',
$_REQUEST['aor_value']
) . "</select>";
'date_time_period_list',
$_REQUEST['aor_value']
) . "</select>";
} else {
echo getDropdownList('date_time_period_list', $_REQUEST['aor_value']);
}
@ -649,10 +648,10 @@ class AOR_ReportsController extends SugarController
}
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . getModuleFields(
$module,
$view,
$value
) . "</select>";
$module,
$view,
$value
) . "</select>";
} else {
echo getModuleFields($module, $view, $value);
}
@ -725,10 +724,10 @@ class AOR_ReportsController extends SugarController
}
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . getModuleFields(
$module,
$view,
$value
) . "</select>";
$module,
$view,
$value
) . "</select>";
} else {
echo getModuleFields($module, $view, $value);
}
@ -784,9 +783,9 @@ class AOR_ReportsController extends SugarController
if ($view == 'EditView') {
echo "<select type='text' style='width:178px;' name='$aor_field' id='$aor_field' title='' tabindex='116'>" . get_select_options_with_id(
$app_list_strings['aor_rel_action_type_list'],
$value
) . "</select>";
$app_list_strings['aor_rel_action_type_list'],
$value
) . "</select>";
} else {
echo $app_list_strings['aor_rel_action_type_list'][$value];
}

View file

@ -4,12 +4,10 @@ class bmp
{
public $mpdf = null;
var $mpdf = null;
function __construct(&$mpdf) {
$this->mpdf = $mpdf;
}
public function __construct(&$mpdf)
{
$this->mpdf = $mpdf;
}
public function _getBMPimage($data, $file)
{

View file

@ -12,16 +12,16 @@ class cssmgr
public $listCSSlvl;
function __construct(&$mpdf) {
$this->mpdf = $mpdf;
$this->tablecascadeCSS = array();
$this->listcascadeCSS = array();
$this->CSS=array();
$this->cascadeCSS = array();
$this->tbCSSlvl = 0;
$this->listCSSlvl = 0;
}
public function __construct(&$mpdf)
{
$this->mpdf = $mpdf;
$this->tablecascadeCSS = array();
$this->listcascadeCSS = array();
$this->CSS = array();
$this->cascadeCSS = array();
$this->tbCSSlvl = 0;
$this->listCSSlvl = 0;
}
public function ReadDefaultCSS($CSSstr)

View file

@ -4,11 +4,10 @@ class directw
{
public $mpdf = null;
var $mpdf = null;
function __construct(&$mpdf) {
$this->mpdf = $mpdf;
}
public function __construct(&$mpdf)
{
$this->mpdf = $mpdf;
}
public function Write($h, $txt, $currentx=0, $link='', $directionality='ltr', $align='')

View file

@ -49,7 +49,7 @@ class form
// FORMS
public $textarea_lineheight;
function __construct(&$mpdf) {
public function __construct(&$mpdf) {
$this->mpdf = $mpdf;
// ACTIVE FORMS

View file

@ -42,7 +42,7 @@ class CGIFLZW
///////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR
function __construct()
public function __construct()
{
$this->MAX_LZW_BITS = 12;
unSet($this->Next);
@ -255,7 +255,7 @@ class CGIFCOLORTABLE
///////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR
function __construct()
public function __construct()
{
unSet($this->m_nColors);
unSet($this->m_arColors);
@ -342,7 +342,7 @@ class CGIFFILEHEADER
///////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR
function __construct()
public function __construct()
{
unSet($this->m_lpVer);
unSet($this->m_nWidth);
@ -418,7 +418,7 @@ class CGIFIMAGEHEADER
///////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR
function __construct()
public function __construct()
{
unSet($this->m_nLeft);
unSet($this->m_nTop);
@ -488,7 +488,7 @@ class CGIFIMAGE
///////////////////////////////////////////////////////////////////////////
function __construct()
public function __construct()
{
unSet($this->m_disp);
unSet($this->m_bUser);
@ -662,7 +662,7 @@ class CGIF
///////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR
function __construct()
public function __construct()
{
$this->m_gfh = new CGIFFILEHEADER();
$this->m_img = new CGIFIMAGE();

View file

@ -4,11 +4,10 @@ class grad
{
public $mpdf = null;
var $mpdf = null;
function __construct(&$mpdf) {
$this->mpdf = $mpdf;
}
public function __construct(&$mpdf)
{
$this->mpdf = $mpdf;
}
// mPDF 5.3.A1
public function CoonsPatchMesh($x, $y, $w, $h, $patch_array=array(), $x_min=0, $x_max=1, $y_min=0, $y_max=1, $colspace='RGB', $return=false)

View file

@ -2,9 +2,10 @@
class indic {
function __construct() {
public function __construct()
{
}
}
public function substituteIndic($earr, $lang, $font)

View file

@ -31,25 +31,7 @@ class SVG
public $kp; // mPDF 4.4.003 convert pixels to PDF units
public $pathBBox; // mPDF 5.0.039
var $svg_gradient; // array - contient les infos sur les gradient fill du svg class<73> par id du svg
var $svg_shadinglist; // array - contient les ids des objet shading
var $svg_info; // array contenant les infos du svg voulue par l'utilisateur
var $svg_attribs; // array - holds all attributes of root <svg> tag
var $svg_style; // array contenant les style de groupes du svg
var $svg_string; // String contenant le tracage du svg en lui m<>me.
var $txt_data; // array - holds string info to write txt to image
var $txt_style; // array - current text style
var $mpdf_ref;
var $xbase; // mPDF 4.4.003
var $ybase; // mPDF 4.4.003
var $svg_error; // mPDF 4.4.003
var $subPathInit; // mPDF 4.4.003
var $spxstart; // mPDF 4.4.003
var $spystart; // mPDF 4.4.003
var $kp; // mPDF 4.4.003 convert pixels to PDF units
var $pathBBox; // mPDF 5.0.039
function __construct(&$mpdf){
public function __construct(&$mpdf){
$this->svg_gradient = array();
$this->svg_shadinglist = array();
$this->txt_data = array();

View file

@ -29,39 +29,13 @@ class tocontents
public $TOC_page_selector;
public $m_TOC;
var $mpdf = null;
var $_toc;
var $TOCmark;
var $TOCoutdent; // mPDF 5.6.31
var $TOCpreHTML;
var $TOCpostHTML;
var $TOCbookmarkText;
var $TOCusePaging;
var $TOCuseLinking;
var $TOCorientation;
var $TOC_margin_left;
var $TOC_margin_right;
var $TOC_margin_top;
var $TOC_margin_bottom;
var $TOC_margin_header;
var $TOC_margin_footer;
var $TOC_odd_header_name;
var $TOC_even_header_name;
var $TOC_odd_footer_name;
var $TOC_even_footer_name;
var $TOC_odd_header_value;
var $TOC_even_header_value;
var $TOC_odd_footer_value;
var $TOC_even_footer_value;
var $TOC_page_selector;
var $m_TOC;
function __construct(&$mpdf) {
$this->mpdf = $mpdf;
$this->_toc=array();
$this->TOCmark = 0;
$this->m_TOC=array();
}
public function __construct(&$mpdf)
{
$this->mpdf = $mpdf;
$this->_toc = array();
$this->TOCmark = 0;
$this->m_TOC = array();
}
public function TOCpagebreak($tocfont='', $tocfontsize='', $tocindent='', $TOCusePaging=true, $TOCuseLinking='', $toc_orientation='', $toc_mgl='', $toc_mgr='', $toc_mgt='', $toc_mgb='', $toc_mgh='', $toc_mgf='', $toc_ohname='', $toc_ehname='', $toc_ofname='', $toc_efname='', $toc_ohvalue=0, $toc_ehvalue=0, $toc_ofvalue=0, $toc_efvalue=0, $toc_preHTML='', $toc_postHTML='', $toc_bookmarkText='', $resetpagenum='', $pagenumstyle='', $suppress='', $orientation='', $mgl='', $mgr='', $mgt='', $mgb='', $mgh='', $mgf='', $ohname='', $ehname='', $ofname='', $efname='', $ohvalue=0, $ehvalue=0, $ofvalue=0, $efvalue=0, $toc_id=0, $pagesel='', $toc_pagesel='', $sheetsize='', $toc_sheetsize='', $tocoutdent='')
{ // mPDF 5.6.19

View file

@ -83,48 +83,7 @@ class TTFontFile
public $maxUniChar;
public $kerninfo;
var $unAGlyphs; // mPDF 5.4.05
var $panose;
var $maxUni;
var $sFamilyClass;
var $sFamilySubClass;
var $sipset;
var $smpset;
var $_pos;
var $numTables;
var $searchRange;
var $entrySelector;
var $rangeShift;
var $tables;
var $otables;
var $filename;
var $fh;
var $glyphPos;
var $charToGlyph;
var $ascent;
var $descent;
var $name;
var $familyName;
var $styleName;
var $fullName;
var $uniqueFontID;
var $unitsPerEm;
var $bbox;
var $capHeight;
var $stemV;
var $italicAngle;
var $flags;
var $underlinePosition;
var $underlineThickness;
var $charWidths;
var $defaultWidth;
var $maxStrLenRead;
var $numTTCFonts;
var $TTCFonts;
var $maxUniChar;
var $kerninfo;
function __construct() {
public function __construct() {
$this->maxStrLenRead = 200000; // Maximum size of glyf table to read in as string (otherwise reads each glyph from file)
}

View file

@ -5,12 +5,10 @@ class wmf
public $mpdf = null;
public $gdiObjectArray;
var $mpdf = null;
var $gdiObjectArray;
function __construct(&$mpdf) {
$this->mpdf = $mpdf;
}
public function __construct(&$mpdf)
{
$this->mpdf = $mpdf;
}
public function _getWMFimage($data)

View file

@ -839,7 +839,7 @@ public $aliasNbPgHex;
// **********************************
// **********************************
function __construct($mode='',$format='A4',$default_font_size=0,$default_font='',$mgl=15,$mgr=15,$mgt=16,$mgb=16,$mgh=9,$mgf=9, $orientation='P') {
public function __construct($mode='',$format='A4',$default_font_size=0,$default_font='',$mgl=15,$mgr=15,$mgt=16,$mgb=16,$mgh=9,$mgf=9, $orientation='P') {
/*-- BACKGROUNDS --*/
if (!class_exists('grad', false)) {

View file

@ -61,7 +61,7 @@ class fpdi_pdf_parser extends pdf_parser
* @param string $filename Source-Filename
* @param object $fpdi Object of type fpdi
*/
function __construct($filename,&$fpdi) {
public function __construct($filename,&$fpdi) {
$this->fpdi =& $fpdi;
$this->filename = $filename;

View file

@ -28,7 +28,7 @@ class pdf_context
// Constructor
function __construct($f) {
public function __construct($f) {
$this->file = $f;
$this->reset();
}

View file

@ -94,7 +94,7 @@ class pdf_parser
*
* @param string $filename Source-Filename
*/
function __construct($filename) {
public function __construct($filename) {
$this->filename = $filename;
// mPDF 4.0
$this->success = true;

View file

@ -38,7 +38,9 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
require_once('modules/AOS_PDF_Templates/PDF_Lib/mpdf.php');
use SuiteCRM\PDF\Exceptions\PDFException;
use SuiteCRM\PDF\PDFWrapper;
require_once('modules/AOS_PDF_Templates/templateParser.php');
require_once('modules/AOS_PDF_Templates/AOS_PDF_Templates.php');
@ -77,13 +79,44 @@ if (!$template) {
$file_name = str_replace(" ", "_", $template->name) . ".pdf";
$format = $template->page_size . ($template->orientation === 'Landscape' ? '-L' : '');
$pdf = new mPDF('en', $format, '', 'DejaVuSansCondensed', $template->margin_left, $template->margin_right, $template->margin_top, $template->margin_bottom, $template->margin_header, $template->margin_footer);
try {
$pdf = PDFWrapper::getPDFEngine();
$pdf->configurePDF([
'mode' => 'en',
'page_size' => $template->page_size,
'font' => 'DejaVuSansCondensed',
'mgl' => $template->margin_left,
'mgr' => $template->margin_right,
'mgt' => $template->margin_top,
'mgb' => $template->margin_bottom,
'mgh' => $template->margin_header,
'mgf' => $template->margin_footer,
'orientation' => $template->orientation
]);
} catch (PDFException $e) {
LoggerManager::getLogger()->warn('PDFException: ' . $e->getMessage());
}
foreach ($recordIds as $recordId) {
$bean->retrieve($recordId);
$pdf_history = new mPDF('en', $format, '', 'DejaVuSansCondensed', $template->margin_left, $template->margin_right, $template->margin_top, $template->margin_bottom, $template->margin_header, $template->margin_footer);
try {
$pdfHistory = PDFWrapper::getPDFEngine();
$pdfHistory->configurePDF([
'mode' => 'en',
'page_size' => $template->page_size,
'font' => 'DejaVuSansCondensed',
'mgl' => $template->margin_left,
'mgr' => $template->margin_right,
'mgt' => $template->margin_top,
'mgb' => $template->margin_bottom,
'mgh' => $template->margin_header,
'mgf' => $template->margin_footer,
'orientation' => $template->orientation
]);
} catch (PDFException $e) {
LoggerManager::getLogger()->warn('PDFException: ' . $e->getMessage());
}
$object_arr = array();
$object_arr[$bean->module_dir] = $bean->id;
@ -92,7 +125,8 @@ foreach ($recordIds as $recordId) {
$object_arr['Accounts'] = $bean->account_id;
}
$search = array('@<script[^>]*?>.*?</script>@si', // Strip out javascript
$search = array(
'@<script[^>]*?>.*?</script>@si', // Strip out javascript
'@<[\/\!]*?[^<>]*?>@si', // Strip out HTML tags
'@([\r\n])[\s]+@', // Strip out white space
'@&(quot|#34);@i', // Replace HTML entities
@ -104,7 +138,8 @@ foreach ($recordIds as $recordId) {
'@<address[^>]*?>@si'
);
$replace = array('',
$replace = array(
'',
'',
'\1',
'"',
@ -133,7 +168,6 @@ foreach ($recordIds as $recordId) {
$printable = str_replace("\n", "<br />", $converted);
ob_clean();
try {
$note = BeanFactory::newBean('Notes');
$note->modified_user_id = $current_user->id;
@ -153,22 +187,20 @@ foreach ($recordIds as $recordId) {
$fp = fopen($sugar_config['upload_dir'] . 'nfile.pdf', 'wb');
fclose($fp);
$pdf_history->SetAutoFont();
$pdf_history->SetHTMLHeader($header);
$pdf_history->SetHTMLFooter($footer);
$pdf_history->WriteHTML($printable);
$pdf_history->Output($sugar_config['upload_dir'] . 'nfile.pdf', 'F');
$pdfHistory->writeHeader($header);
$pdfHistory->writeFooter($footer);
$pdfHistory->writeHTML($printable);
$pdfHistory->outputPDF($sugar_config['upload_dir'] . 'nfile.pdf', 'F');
$pdf->SetHTMLHeader($header);
$pdf->AddPage();
$pdf->setAutoFont();
$pdf->SetHTMLFooter($footer);
$pdf->writeHeader($header);
$pdf->writeBlankPage();
$pdf->writeFooter($footer);
$pdf->writeHTML($printable);
rename($sugar_config['upload_dir'] . 'nfile.pdf', $sugar_config['upload_dir'] . $note->id);
} catch (mPDF_exception $e) {
echo $e;
} catch (PDFException $e) {
LoggerManager::getLogger()->warn('PDFException: ' . $e->getMessage());
}
}
$pdf->Output($file_name, "D");
$pdf->outputPDF($file_name, 'D');

View file

@ -5,7 +5,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -38,17 +38,16 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use SuiteCRM\PDF\Exceptions\PDFException;
use SuiteCRM\PDF\PDFWrapper;
if (!isset($_REQUEST['uid']) || empty($_REQUEST['uid']) || !isset($_REQUEST['templateID']) || empty($_REQUEST['templateID'])) {
die('Error retrieving record. This record may be deleted or you may not be authorized to view it.');
}
$errorLevelStored = error_reporting();
error_reporting(0);
require_once('modules/AOS_PDF_Templates/PDF_Lib/mpdf.php');
require_once('modules/AOS_PDF_Templates/templateParser.php');
require_once('modules/AOS_PDF_Templates/sendEmail.php');
require_once('modules/AOS_PDF_Templates/AOS_PDF_Templates.php');
error_reporting($errorLevelStored);
global $mod_strings, $sugar_config;
@ -139,28 +138,39 @@ $footer = templateParser::parse_template($footer, $object_arr);
$printable = str_replace("\n", "<br />", $converted);
if ($task == 'pdf' || $task == 'emailpdf') {
if ($task === 'pdf' || $task === 'emailpdf') {
$file_name = $mod_strings['LBL_PDF_NAME'] . "_" . str_replace(" ", "_", $bean->name) . ".pdf";
ob_clean();
try {
$orientation = ($template->orientation == "Landscape") ? "-L" : "";
$pdf = new mPDF('en', $template->page_size . $orientation, '', 'DejaVuSansCondensed', $template->margin_left, $template->margin_right, $template->margin_top, $template->margin_bottom, $template->margin_header, $template->margin_footer);
$pdf->SetAutoFont();
$pdf->SetHTMLHeader($header);
$pdf->SetHTMLFooter($footer);
$pdf->WriteHTML($printable);
if ($task == 'pdf') {
$pdf->Output($file_name, "D");
$pdf = PDFWrapper::getPDFEngine();
$pdf->configurePDF([
'mode' => 'en',
'page_size' => $template->page_size,
'font' => 'DejaVuSansCondensed',
'mgl' => $template->margin_left,
'mgr' => $template->margin_right,
'mgt' => $template->margin_top,
'mgb' => $template->margin_bottom,
'mgh' => $template->margin_header,
'mgf' => $template->margin_footer,
'orientation' => $template->orientation
]);
$pdf->writeHeader($header);
$pdf->writeFooter($footer);
$pdf->writeHTML($printable);
if ($task === 'pdf') {
$pdf->outputPDF($file_name, "D");
} else {
$fp = fopen($sugar_config['upload_dir'] . 'attachfile.pdf', 'wb');
fclose($fp);
$pdf->Output($sugar_config['upload_dir'] . 'attachfile.pdf', 'F');
$pdf->outputPDF($sugar_config['upload_dir'] . 'attachfile.pdf', 'F');
$sendEmail = new sendEmail();
$sendEmail->send_email($bean, $bean->module_dir, '', $file_name, true);
}
} catch (mPDF_exception $e) {
echo $e;
} catch (PDFException $e) {
LoggerManager::getLogger()->warn('PDFException: ' . $e->getMessage());
}
} elseif ($task == 'email') {
$sendEmail = new sendEmail();

View file

@ -1,107 +0,0 @@
<?php
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
global $current_user, $sugar_config;
global $mod_strings;
global $app_list_strings;
global $app_strings;
global $theme;
if (!is_admin($current_user)) {
sugar_die("Unauthorized access to administration.");
}
require_once('modules/Configurator/Configurator.php');
echo getClassicModuleTitle(
"Administration",
array(
"<a href='index.php?module=Administration&action=index'>" . translate('LBL_MODULE_NAME', 'Administration') . "</a>",
$mod_strings['LBL_AOD_ADMIN_MANAGE_AOD'],
),
false
);
$cfg = new Configurator();
$sugar_smarty = new Sugar_Smarty();
$errors = array();
if (!array_key_exists('aod', $cfg->config)) {
$cfg->config['aod'] = array(
'enable_aod' => '',
);
}
if (isset($_REQUEST['do']) && $_REQUEST['do'] == 'save') {
$cfg->config['aod']['enable_aod'] = !empty($_REQUEST['enable_aod']);
$cfg->saveConfig();
header('Location: index.php?module=Administration&action=index');
exit();
}
$sugar_smarty->assign('MOD', $mod_strings);
$sugar_smarty->assign('APP', $app_strings);
$sugar_smarty->assign('APP_LIST', $app_list_strings);
$sugar_smarty->assign('LANGUAGES', get_languages());
$sugar_smarty->assign("JAVASCRIPT", get_set_focus_js());
$sugar_smarty->assign('config', $cfg->config['aod']);
$sugar_smarty->assign('error', $errors);
$buttons = <<<EOQ
<input title="{$app_strings['LBL_SAVE_BUTTON_TITLE']}"
accessKey="{$app_strings['LBL_SAVE_BUTTON_KEY']}"
class="button primary"
type="submit"
name="save"
onclick="return check_form('ConfigureSettings');"
value=" {$app_strings['LBL_SAVE_BUTTON_LABEL']} " >
&nbsp;<input title="{$mod_strings['LBL_CANCEL_BUTTON_TITLE']}" onclick="document.location.href='index.php?module=Administration&action=index'" class="button" type="button" name="cancel" value=" {$app_strings['LBL_CANCEL_BUTTON_LABEL']} " >
EOQ;
$sugar_smarty->assign("BUTTONS", $buttons);
$sugar_smarty->display('modules/Administration/AODAdmin.tpl');
$javascript = new javascript();
$javascript->setFormName('ConfigureSettings');
echo $javascript->getScript();

View file

@ -1,31 +0,0 @@
<form id="ConfigureSettings" name="ConfigureSettings" enctype='multipart/form-data' method="POST"
action="index.php?module=Administration&action=AODAdmin&do=save">
<span class='error'>{$error.main}</span>
<table width="100%" cellpadding="0" cellspacing="0" border="0" class="actionsContainer">
<tr>
<td>
{$BUTTONS}
</td>
</tr>
</table>
<table width="100%" border="0" cellspacing="1" cellpadding="0" class="edit view">
<tr><th align="left" scope="row" colspan="4"><h4>{$MOD.LBL_GENERAL_SETTINGS}</h4></th>
</tr>
<tr>
<td scope="row" width="200">{$MOD.LBL_AOD_ENABLE}: </td>
<td >
<input type='checkbox' id='enable_aod' name='enable_aod' {if $config.enable_aod}checked='checked'{/if} >
</td>
</tr>
</table>
<div style="padding-top: 2px;">
{$BUTTONS}
</div>
{$JAVASCRIPT}
</form>

View file

@ -40,15 +40,18 @@
namespace SuiteCRM\Modules\Administration\Search;
use SuiteCRM\Search\SearchConfigurator;
use SuiteCRM\Modules\Administration\Search\MVC\Controller as AbstractController;
use Configurator;
use Exception;
use SuiteCRM\Search\SearchModules;
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
* Class Controller handles the the actions for the search settings.
*/
class Controller extends MVC\Controller
class Controller extends AbstractController
{
public function __construct()
{
@ -59,19 +62,43 @@ class Controller extends MVC\Controller
* Saves the configuration from a POST request.
*
* If called from ajax it will return a json.
* @throws Exception
*/
public function doSave()
public function doSave(): void
{
$searchEngine = filter_input(INPUT_POST, 'search-engine', FILTER_SANITIZE_STRING);
$aod = $searchEngine === 'BasicAndAodEngine';
SearchConfigurator::make()
->setEngine($searchEngine)
->save();
SearchModules::saveGlobalSearchSettings();
$this->doSaveAODConfig($aod);
if ($this->isAjax()) {
$this->yieldJson(['status' => 'success']);
}
$this->redirect('index.php?module=Administration&action=index');
}
/**
* Saves the configuration getting data from POST.
* @param bool $enabled
*/
public function doSaveAODConfig(bool $enabled): void
{
$cfg = new Configurator();
if (!array_key_exists('aod', $cfg->config)) {
$cfg->config['aod'] = [
'enable_aod' => '',
];
}
$cfg->config['aod']['enable_aod'] = $enabled;
$cfg->saveConfig();
}
}

View file

@ -76,7 +76,7 @@ class Controller extends AbstractController
/**
* Shows the view.
*/
public function display()
public function display(): void
{
$this->view->getTemplate()->assign('schedulers', $this->getSchedulers());
parent::display();
@ -184,6 +184,7 @@ class Controller extends AbstractController
$where = "schedulers.job='function::runElasticSearchIndexerScheduler'";
/** @var Scheduler[]|null $schedulers */
$schedulers = BeanFactory::getBean('Schedulers')->get_full_list(null, $where);
return $schedulers;
}

View file

@ -58,7 +58,7 @@ class View extends AbstractView
parent::__construct(__DIR__ . '/view.tpl');
}
public function preDisplay()
public function preDisplay(): void
{
parent::preDisplay();
@ -67,9 +67,9 @@ class View extends AbstractView
if (!isset($sugar_config['search']['ElasticSearch']) || $sugar_config['search']['ElasticSearch']) {
LoggerManager::getLogger()->warn('Configuration does not contains Elasticsearch default settings.');
}
$elasticsearchConfig = isset($sugar_config['search']['ElasticSearch']) ? $sugar_config['search']['ElasticSearch'] : null;
$this->smarty->assign('config', $elasticsearchConfig);
}
}

View file

@ -5,7 +5,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -37,17 +37,10 @@
* reasonably feasible for technical reasons, the Appropriate Legal Notices must
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
*}
<h1>{$MOD.LBL_SEARCH_MODULES}</h1>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td colspan="100">
<h2> {$MOD.LBL_SEARCH_MODULES}</h2>
</td>
</tr>
<tr>
<td colspan="100">{$MOD.LBL_SEARCH_MODULES_HELP}</td>
</tr>
<tr>
<td>
<br>
@ -58,40 +51,28 @@
<script type="text/javascript" src="{sugar_getjspath file='cache/include/javascript/sugar_grp_yui_widgets.js'}"></script>
<link rel="stylesheet" type="text/css" href="{sugar_getjspath file='modules/Connectors/tpls/tabs.css'}"/>
<form name="GlobalSearchSettings" method="POST" class="search-module-selector">
<input type="hidden" name="module" value="Administration">
<input type="hidden" name="action" value="saveGlobalSearchSettings">
<input type="hidden" name="enabled_modules" value="">
<div class='add_table' style='margin-bottom: 10px'>
<table id="GlobalSearchSettings" class="GlobalSearchSettings edit view" style='margin-bottom:0px;' border="0" cellspacing="0" cellpadding="0">
<tr>
<td width='1%'>
<div id="enabled_div"></div>
</td>
<td>
<div id="disabled_div"></div>
</td>
</tr>
</table>
<div class="search-module-selector">
<div class="panel panel-primary">
<div class="panel-heading">{$MOD.LBL_SEARCH_MODULES}</div>
<p class="text-muted" style="margin-top: 10px; margin-left: 15px">{$MOD.LBL_SEARCH_MODULES_HELP}</p>
<div class="panel-body tab-content text-center">
<div class='add_table' style='margin-bottom: 10px'>
<table id="GlobalSearchSettings" class="GlobalSearchSettings edit view"
style='margin-bottom:0;'>
<tr>
<td width='1%'>
<div id="enabled_div"></div>
</td>
<td>
<div id="disabled_div"></div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<table border="0" cellspacing="1" cellpadding="1" class="settings-buttons">
<tr>
<td>
<input title="{$APP.LBL_SAVE_BUTTON_LABEL}" class="button primary" onclick="SUGAR.saveGlobalSearchSettings();" type="button" name="button" value="{$APP.LBL_SAVE_BUTTON_LABEL}">
<input title="{$MOD.LBL_SAVE_SCHED_BUTTON}" class="button primary schedFullSystemIndex" onclick="SUGAR.FTS.schedFullSystemIndex();" style="{if !$showSchedButton}display:none;{/if}text-decoration: none;" id='schedFullSystemIndex' type="button" name="button" value="{$MOD.LBL_SAVE_SCHED_BUTTON}">
<input title="{$APP.LBL_CANCEL_BUTTON_LABEL}" class="button" onclick="document.GlobalSearchSettings.action.value='';" type="submit" name="button" value="{$APP.LBL_CANCEL_BUTTON_LABEL}">
</td>
</tr>
</table>
</form>
<div id='selectFTSModules' class="yui-hidden">
<div style="background-color: white; padding: 20px;">
<div id='selectFTSModulesTable' ></div>
<div style="padding-top: 10px"><input type="checkbox" name="clearDataOnIndex" id="clearDataOnIndex" >&nbsp;{$MOD.LBL_DELETE_FTS_DATA}</div>
</div>
</div>
<script type="text/javascript">
(function(){ldelim}
var Connect = YAHOO.util.Connect;
@ -131,80 +112,26 @@
SUGAR.globalSearchEnabledTable.render();
SUGAR.globalSearchDisabledTable.render();
SUGAR.getEnabledModules = function()
{
var enabledTable = SUGAR.globalSearchEnabledTable;
var modules = "";
for(var i=0; i < enabledTable.getRecordSet().getLength(); i++)
{
var data = enabledTable.getRecord(i).getData();
if (data.module && data.module != '')
modules += "," + data.module;
}
return modules;
}
SUGAR.getEnabledModulesForFTSSched = function()
{
var enabledTable = SUGAR.FTS.selectedDataTable;
var modules = [];
var selectedIDs = enabledTable.getSelectedRows();
for(var i=0; i < selectedIDs.length; i++)
{
var data = enabledTable.getRecord(selectedIDs[i]).getData();
modules.push(data.module);
}
return modules;
}
SUGAR.getTranslatedEnabledModules = function()
{
var enabledTable = SUGAR.globalSearchEnabledTable;
var modules = [{module:'', label: SUGAR.language.get('Administration', 'LBL_ALL')}];
for(var i=0; i < enabledTable.getRecordSet().getLength(); i++)
{
var data = enabledTable.getRecord(i).getData();
if (data.module && data.module != '')
{
var tmp = {'module' : data.module,};
modules.push(tmp);
}
}
return modules;
}
SUGAR.saveGlobalSearchSettings = function()
SUGAR.getEnabledModules = function()
{
var enabledTable = SUGAR.globalSearchEnabledTable;
var modules = "";
for(var i=0; i < enabledTable.getRecordSet().getLength(); i++)
{
var data = enabledTable.getRecord(i).getData();
if (data.module && data.module != '')
modules += "," + data.module;
}
return modules;
}
SUGAR.saveGlobalSearchSettings = function()
{
var modules = SUGAR.getEnabledModules();
modules = modules == "" ? modules : modules.substr(1);
ajaxStatus.showStatus(SUGAR.language.get('Administration', 'LBL_SAVING'));
Connect.asyncRequest(
Connect.method,
Connect.url,
{success: SUGAR.saveCallBack},
SUGAR.util.paramsToUrl({
module: "Administration",
action: "saveglobalsearchsettings",
enabled_modules: modules
}) + "to_pdf=1"
);
return true;
}
SUGAR.saveCallBack = function(o)
{
ajaxStatus.flashStatus(SUGAR.language.get('app_strings', 'LBL_DONE'));
if (o.responseText == "true")
{
window.location.assign('index.php?module=Administration&action=index');
} else {
YAHOO.SUGAR.MessageBox.show({msg:o.responseText});
}
document.forms['SearchSettings'].elements['enabled_modules'].value = modules;
}
})();
{/literal}
</script>
<script type="text/javascript">
</script>

View file

@ -58,7 +58,7 @@ abstract class View extends BaseView
*
* Extend to assign more variable.
*/
public function preDisplay()
public function preDisplay(): void
{
global $mod_strings;
global $app_list_strings;
@ -74,10 +74,10 @@ abstract class View extends BaseView
$this->smarty->assign('error', $errors);
$this->smarty->assign('BUTTONS', $this->getButtons());
if (!isset($sugar_config['search']) || !$sugar_config['search']) {
if (!empty($sugar_config['search'])) {
LoggerManager::getLogger()->warn('Configuration does not contains default search settings.');
}
$search = isset($sugar_config['search']) ? $sugar_config['search'] : null;
$search = $sugar_config['search'] ?? null;
$this->smarty->assign('config', $search);
}
@ -86,7 +86,7 @@ abstract class View extends BaseView
*
* @return string
*/
protected function getButtons()
protected function getButtons(): string
{
global $mod_strings;
global $app_strings;
@ -113,7 +113,7 @@ EOQ;
*
* @return array
*/
protected function getEngines()
protected function getEngines(): array
{
$engines = [];

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -43,30 +43,61 @@ if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
use SuiteCRM\Search\SearchModules;
use SuiteCRM\Search\SearchWrapper;
use SuiteCRM\Modules\Administration\Search\MVC\View as AbstractView;
/**
* Class View renders the Search settings.
*/
class View extends MVC\View
class View extends AbstractView
{
public function __construct()
{
parent::__construct(__DIR__ . '/view.tpl');
}
public function preDisplay()
public function preDisplay(): void
{
parent::preDisplay();
$this->smarty->assign('selectedController', SearchWrapper::getController());
$this->smarty->assign('selectedEngine', SearchWrapper::getDefaultEngine());
$legacyEngines = [
'BasicSearchEngine' => translate('LBL_BASIC_SEARCH_ENGINE'),
'BasicAndAodEngine' => translate('LBL_BASIC_AND_AOD_ENGINE'),
];
$engines = $this->getEngines();
$engines = array_merge($legacyEngines, $engines);
unset($engines['LuceneSearchEngine']);
$this->smarty->assign('engines', [
translate('LBL_LEGACY_SEARCH_ENGINES') => [
'BasicSearchEngine' => translate('LBL_BASIC_SEARCH_ENGINE'),
'BasicAndAodEngine' => translate('LBL_BASIC_AND_AOD_ENGINE'),
],
translate('LBL_SEARCH_WRAPPER_ENGINES') => $this->getEngines(),
translate('LBL_SEARCH_WRAPPER_ENGINES') => $engines
]);
}
/**
* @see SugarView::display()
*/
public function display(): void
{
global $mod_strings, $app_strings;
$this->smarty->assign('APP', $app_strings);
$this->smarty->assign('MOD', $mod_strings);
$modules = SearchModules::getAllModules();
$this->smarty->assign('enabled_modules', json_encode($modules['enabled'], JSON_THROW_ON_ERROR));
$this->smarty->assign('disabled_modules', json_encode($modules['disabled'], JSON_THROW_ON_ERROR));
$template = $this->templateFile;
if (file_exists('custom/' . $this->templateFile)) {
$template = 'custom/' . $this->templateFile;
}
$this->smarty->display($template);
}
}

View file

@ -3,7 +3,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -42,46 +42,48 @@
class="detail-view"
enctype='multipart/form-data'
method="POST"
action="index.php?module=Administration&action=SearchSettings&do=Save">
action="index.php?module=Administration&action=SearchSettings&do=Save"
onsubmit="SUGAR.saveGlobalSearchSettings();">
<table class="edit view" width="100%" cellspacing="1" cellpadding="0" border="0">
<tr>
<th scope="row" colspan="4" align="left">
<h4>{sugar_translate label="LBL_SEARCH_INTERFACE"}</h4>
</th>
</tr>
<input type="hidden" name="module" value="Administration">
<input type='hidden' name='enabled_modules' value=''>
<tr>
{*search engine*}
<td>
<div class="td-container">
<div>
<label for="search-engine">{sugar_translate label="LBL_SEARCH_ENGINE"}</label>
{sugar_help text=$MOD.LBL_SEARCH_ENGINE_TOOLTIP}
</div>
<div>
<small class="form-text text-muted">{sugar_translate label="LBL_SEARCH_ENGINE_HELP"}</small>
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">{$MOD.LBL_SEARCH_INTERFACE}</div>
<div class="panel-body tab-content text-center">
<div class="col-md-6">
<div class="form-check">
<div class="td-container">
<div>
<label for="search-engine">{sugar_translate label="LBL_SEARCH_ENGINE"}</label>
{sugar_help text=$MOD.LBL_SEARCH_ENGINE_TOOLTIP}
</div>
<div>
<small class="form-text text-muted">{sugar_translate label="LBL_SEARCH_ENGINE_HELP"}</small>
</div>
</div>
</div>
</div>
</td>
<td scope="row" style="vertical-align: middle">
{html_options
options=$engines
selected=$selectedEngine
id="search-engine"
name="search-engine"
class="form-control"
}
</td>
</tr>
</table>
<div class="col-md-6">
{html_options
options=$engines
selected=$selectedEngine
id="search-engine"
name="search-engine"
class="form-control"
}
</div>
</div>
</div>
</div>
{include file='modules/Administration/Search/GlobalSearchSettings.tpl'}
{$JAVASCRIPT}
<div class="settings-buttons">
{$BUTTONS}
</div>
{$JAVASCRIPT}
<script src="modules/Administration/Search/ajaxSubmit.js"></script>
</form>

View file

@ -860,10 +860,6 @@ $mod_strings = array(
'LBL_AOP_ADD_STATUS' => 'Add',
'LBL_AOP_REMOVE_STATUS' => 'Remove',
'LBL_AOD_ADMIN_MANAGE_AOD' => 'Advanced OpenDiscovery Settings',
'LBL_AOD_ENABLE' => 'Enable AOD',
'LBL_AOD_SETTINGS' => 'AOD Settings',
'LBL_AOS_ADMIN_CONTRACT_SETTINGS' => 'Contract Settings',
'LBL_AOS_ADMIN_CONTRACT_RENEWAL_REMINDER' => 'Renewal Reminder period',
'LBL_AOS_ADMIN_MANAGE_AOS' => 'Advanced OpenSales Settings',
@ -961,13 +957,13 @@ $mod_strings = array(
'LBL_SEARCH_ENGINE' => 'Search Engine',
'LBL_SEARCH_ENGINE_HELP' => 'Configure the default search engine used by the search.',
'LBL_SEARCH_ENGINE_TOOLTIP' => 'Select a search engine for the Global Search.',
'LBL_SEARCH_GENERAL' => 'General',
'LBL_SEARCH_MODULES' => 'Search Modules',
'LBL_SEARCH_MODULES_HELP' => 'Select the module(s) that users will be able to search against using the Global Search.',
// Search Engines Translations
'LBL_LEGACY_SEARCH_ENGINES' => 'Legacy Search',
'LBL_SEARCH_WRAPPER_ENGINES' => 'Search Engines (new)',
'LBL_SEARCH_WRAPPER_ENGINES' => 'Search Engines',
'LBL_BASIC_SEARCH_ENGINE' => 'Basic Search',
'LBL_BASIC_AND_AOD_ENGINE' => 'Basic + Advanced Search',
'LBL_ELASTIC_SEARCH_ENGINE' => 'Elasticsearch Engine',

View file

@ -71,8 +71,6 @@ $admin_option_defs['Administration']['languages']= array('Currencies','LBL_MANAG
$admin_option_defs['Administration']['repair']= array('Repair','LBL_UPGRADE_TITLE','LBL_UPGRADE','./index.php?module=Administration&action=Upgrade', 'repair');
$admin_option_defs['Administration']['global_search']=array('icon_SearchForm','LBL_GLOBAL_SEARCH_SETTINGS','LBL_GLOBAL_SEARCH_SETTINGS_DESC','./index.php?module=Administration&action=GlobalSearchSettings', 'global-search');
if (!isset($GLOBALS['sugar_config']['hide_admin_diagnostics']) || !$GLOBALS['sugar_config']['hide_admin_diagnostics']) {
$admin_option_defs['Administration']['diagnostic']= array('Diagnostic','LBL_DIAGNOSTIC_TITLE','LBL_DIAGNOSTIC_DESC','./index.php?module=Administration&action=Diagnostic', 'diagnostic');
}
@ -227,13 +225,6 @@ $admin_option_defs['Administration']['aos'] = array(
'aos-settings'
);
$admin_option_defs['Administration']['aod'] = array(
'AOD',
'LBL_AOD_SETTINGS',
'LBL_CHANGE_SETTINGS_AOD',
'./index.php?module=Administration&action=AODAdmin',
'aod-settings'
);
$admin_option_defs['Administration']['aop'] = array(
'AOP',
'LBL_AOP_SETTINGS',
@ -269,14 +260,6 @@ $admin_option_defs['Administration']['search_wrapper'] = [
'global-search'
];
$admin_option_defs['Administration']['global_search'] = [
'icon_SearchForm',
'LBL_SEARCH_MODULES',
'LBL_SEARCH_MODULES_HELP',
'./index.php?module=Administration&action=GlobalSearchSettings',
'global-search'
];
$admin_option_defs['Administration']['elastic_search'] = [
'ElasticSearchIndexerSettings',
'LBL_ELASTIC_SEARCH_SETTINGS',

View file

@ -4,7 +4,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -62,7 +62,7 @@ try {
* @param Throwable $throwable
* @param SearchQuery $query
*/
function handleThrowable($throwable, SearchQuery $query)
function handleThrowable(Throwable $throwable, SearchQuery $query)
{
$handler = new SearchThrowableHandler($throwable, $query);
$handler->handle();

View file

@ -5,7 +5,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -38,281 +38,4 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
$queryString = ! empty($_REQUEST['query_string']) ? $_REQUEST['query_string'] : '';
$luceneSearch = !empty($sugar_config['aod']['enable_aod']);
if (array_key_exists('showGSDiv', $_REQUEST) || !empty($_REQUEST['search_fallback'])) {
//Search from vanilla sugar search or request for the same
$luceneSearch = false;
}
if (!$luceneSearch) {
if (!empty($sugar_config['aod']['enable_aod'])) {
echo "<a href='index.php?action=UnifiedSearch&module=Home&query_string=".urlencode($queryString)."'>".translate("LBL_USE_AOD_SEARCH", "AOD_Index")."</a>";
}
require_once('modules/Home/UnifiedSearchAdvanced.php');
global $mod_strings, $modListHeader, $app_strings, $beanList, $beanFiles;
$usa = new UnifiedSearchAdvanced();
$usa->search();
return;
}
require_once('include/utils.php');
echo "<a href='index.php?action=UnifiedSearch&module=Home&search_fallback=1&query_string=".urlencode($queryString)."'>".translate("LBL_USE_VANILLA_SEARCH", "AOD_Index")."</a>";
$index = BeanFactory::getBean("AOD_Index")->getIndex();
$hits = array();
$start = 0;
$amount = 20;
$total = 0;
if (!empty($_REQUEST['start'])) {
$start = $_REQUEST['start'];
}
if (!empty($_REQUEST['total'])) {
$total = $_REQUEST['total'];
}
if (array_key_exists('listViewStartButton', $_REQUEST)) {
$start = 0;
} elseif (array_key_exists('listViewPrevButton', $_REQUEST)) {
$start = max($start - $amount, 0);
} elseif (array_key_exists('listViewNextButton', $_REQUEST)) {
$start = min($start + $amount, $total);
} elseif (array_key_exists('listViewEndButton', $_REQUEST)) {
$start = floor($total / $amount) * $amount;
}
if ($queryString) {
$res = doSearch($index, $queryString, $start, $amount);
$total = $res['total'];
$hits = $res['hits'];
}
?>
<form name='UnifiedSearchAdvancedMain' action='index.php' method='POST' class="search_form">
<input type='hidden' name='query_string' value='test'>
<input type='hidden' name='action' value='UnifiedSearch'>
<input id='searchFieldMain' class='searchField' type='text' size='80' name='query_string' placeholder='<?php echo translate("LBL_SEARCH_QUERY_PLACEHOLDER", "AOD_Index");?>' value='<?php echo $queryString;?>'>
<input type="submit" class="button primary" value="<?php echo translate("LBL_SEARCH_BUTTON", "AOD_Index");?>">&nbsp;
</form>
<?php if ($hits) { ?>
<table cellpadding='0' cellspacing='0' width='100%' border='0' class='list View'>
<?php getPaginateHTML($queryString, $start, $amount, $total); ?>
<thead>
<tr height='20'>
<th scope='col' width='10%'data-hide="phone">
<span sugar="sugar1">
<div style='white-space: nowrap; width:100%; text-align:left;'>
<?php echo translate("LBL_SEARCH_RESULT_MODULE", "AOD_Index"); ?>
</div>
</span sugar='sugar1'>
</th>
<th scope='col' width='30%' data-toggle="true">
<span sugar="sugar1">
<div style='white-space: nowrap; width:100%; text-align:left;'>
<?php echo translate("LBL_SEARCH_RESULT_NAME", "AOD_Index"); ?>
</div>
</span sugar='sugar1'>
</th>
<th scope='col' width='30%' data-hide="phone">
<span sugar="sugar1">
<div style='white-space: nowrap; width:100%; text-align:left;'>
<?php echo translate("LBL_SEARCH_RESULT_SUMMARY", "AOD_Index"); ?>
</div>
</span sugar='sugar1'>
</th>
<th scope='col' width='25%' data-hide="phone,phonelandscape">
<div style='white-space: nowrap; width:100%; text-align:left;'>
<?php echo translate("LBL_SEARCH_RESULT_DATE_CREATED", "AOD_Index"); ?>
</div>
</th>
<th scope='col' width='25%' data-hide="phone,phonelandscape">
<div style='white-space: nowrap; width:100%; text-align:left;'>
<?php echo translate("LBL_SEARCH_RESULT_DATE_MODIFIED", "AOD_Index"); ?>
</div>
</th>
<th scope='col' width='10%'>
<div style='white-space: nowrap; width:100%; text-align:left;'>
<?php echo translate("LBL_SEARCH_RESULT_SCORE", "AOD_Index"); ?>
</div>
</th>
</tr>
</thead>
<?php
foreach ($hits as $hit) {
echo "<tr>"
."<td>".$hit->label."</td>"
."<td><a href='index.php?module=".$hit->record_module."&action=DetailView&record=".$hit->record_id."'>".$hit->name."</a></td>"
."<td>".$hit->summary."</td>"
."<td>".$hit->date_entered."</td>"
."<td>".$hit->date_modified."</td>"
."<td>".getScoreDisplay($hit)."</td>"
."</tr>";
}
?>
</table>
<?php
} else {
echo "<p>".translate("LBL_SEARCH_RESULT_EMPTY", "AOD_Index")."</p>";
}
?>
<?php
function getRecordSummary(SugarBean $bean)
{
global $listViewDefs;
if (!isset($listViewDefs) || !isset($listViewDefs[$bean->module_dir])) {
if (file_exists('custom/modules/'.$bean->module_dir.'/metadata/listviewdefs.php')) {
require('custom/modules/'.$bean->module_dir.'/metadata/listviewdefs.php');
} else {
if (file_exists('modules/'.$bean->module_dir.'/metadata/listviewdefs.php')) {
require('modules/'.$bean->module_dir.'/metadata/listviewdefs.php');
}
}
}
if (!isset($listViewDefs) || !isset($listViewDefs[$bean->module_dir])) {
return $bean->get_summary_text();
}
$summary = array();
;
foreach ($listViewDefs[$bean->module_dir] as $key => $entry) {
if (empty($entry['default'])) {
continue;
}
$key = strtolower($key);
if (in_array($key, array('date_entered','date_modified','name'))) {
continue;
}
$summary[] = $bean->$key;
}
$summary = array_filter($summary);
return implode(' || ', $summary);
}
function getScoreDisplay($hit)
{
return number_format(100*$hit->score, 2);
}
function unCamelCase($input, $sep = " ")
{
$output = preg_replace(array('/(?<=[^A-Z])([A-Z])/', '/(?<=[^0-9])([0-9])/'), $sep.'$0', $input);
return ucwords($output);
}
function getModuleLabel($module)
{
return translate('LBL_MODULE_NAME', $module);
}
function cacheQuery($queryString, $resArray)
{
$file = create_cache_directory('modules/AOD_Index/QueryCache/' . md5($queryString));
$out = serialize($resArray);
sugar_file_put_contents_atomic($file, $out);
}
function getCorrectMTime($filePath)
{
$time = filemtime($filePath);
$isDST = (date('I', $time) == 1);
$systemDST = (date('I') == 1);
$adjustment = 0;
if ($isDST == false && $systemDST == true) {
$adjustment = 3600;
} elseif ($isDST == true && $systemDST == false) {
$adjustment = -3600;
} else {
$adjustment = 0;
}
return ($time + $adjustment);
}
function doSearch($index, $queryString, $start = 0, $amount = 20)
{
global $current_user;
$cachePath = 'cache/modules/AOD_Index/QueryCache/' . md5($queryString);
if (is_file($cachePath)) {
$mTime = getCorrectMTime($cachePath);
if ($mTime > (time() - 5*60)) {
$hits = unserialize(sugar_file_get_contents($cachePath));
}
}
if (!isset($hits)) {
$tmphits = $index->find($queryString);
$hits = array();
foreach ($tmphits as $hit) {
$bean = BeanFactory::getBean($hit->record_module, $hit->record_id);
if (empty($bean)) {
continue;
}
if ($bean->bean_implements('ACL') && !is_admin($current_user)) {
//Annoyingly can't use the following as it always passes true for is_owner checks on list
//$bean->ACLAccess('list');
$in_group = SecurityGroup::groupHasAccess($bean->module_dir, $bean->id, 'list');
$is_owner = $bean->isOwner($current_user->id);
$access = ACLController::checkAccess($bean->module_dir, 'list', $is_owner, 'module', $in_group);
if (!$access) {
continue;
}
}
$newHit = new stdClass;
$newHit->record_module = $hit->record_module;
$newHit->record_id = $hit->record_id;
$newHit->score = $hit->score;
$newHit->label = getModuleLabel($bean->module_name);
$newHit->name = $bean->get_summary_text();
$newHit->summary = getRecordSummary($bean);
$newHit->date_entered = $bean->date_entered;
$newHit->date_modified = $bean->date_modified;
$hits[] = $newHit;
}
//Cache results so pagination is nice and snappy.
cacheQuery($queryString, $hits);
}
$total = count($hits);
$hits = array_slice($hits, $start, $amount);
$res = array('total'=>$total,'hits' => $hits);
return $res;
}
function getPaginateHTML($queryString, $start, $amount, $total)
{
$first = !$start;
$last = ($start + $amount) > $total;
if ($first) {
$startImage = SugarThemeRegistry::current()->getImageURL('start_off.gif');
$prevImage = SugarThemeRegistry::current()->getImageURL('previous_off.gif');
} else {
$startImage = SugarThemeRegistry::current()->getImageURL('start.gif');
$prevImage = SugarThemeRegistry::current()->getImageURL('previous.gif');
}
if ($last) {
$endImage = SugarThemeRegistry::current()->getImageURL('end_off.gif');
$nextImage = SugarThemeRegistry::current()->getImageURL('next_off.gif');
} else {
$endImage = SugarThemeRegistry::current()->getImageURL('end.gif');
$nextImage = SugarThemeRegistry::current()->getImageURL('next.gif');
} ?>
<td class="paginationChangeButtons" align="right" nowrap="nowrap" width="1%">
<form action='index.php'>
<input type="hidden" name="action" value="UnifiedSearch">
<input type="hidden" name="module" value="Home">
<input type="hidden" name="start" value="<?php echo $start; ?>">
<input type="hidden" name="total" value="<?php echo $total; ?>">
<input type="hidden" name="query_string" value="<?php echo $queryString; ?>">
<button type="submit" id="listViewStartButton_top" name="listViewStartButton" title="Start" class="button" <?php echo $first ? 'disabled="disabled"' : ''?>>
<span class='suitepicon suitepicon-action-first'></span>
</button>
<button type="submit" id="listViewPrevButton_top" name="listViewPrevButton" class="button" title="Previous" <?php echo $first ? 'disabled="disabled"' : ''?>>
<span class='suitepicon suitepicon-action-left'></span>
</button>
<span class="pageNumbers">(<?php echo $total ? $start+1 : 0; ?> - <?php echo min($start + $amount, $total); ?> of <?php echo $total; ?>)</span>
<button type="submit" id="listViewNextButton_top" name="listViewNextButton" title="Next" class="button" <?php echo $last ? 'disabled="disabled"' : ''?>>
<span class='suitepicon suitepicon-action-right'></span>
</button>
<button type="submit" id="listViewEndButton_top" name="listViewEndButton" title="End" class="button" <?php echo $last ? 'disabled="disabled"' : ''?>>
<span class='suitepicon suitepicon-action-last'></span>
</button>
</form>
</td>
<?php
}
require_once __DIR__ . '/Search.php';

View file

@ -1,14 +1,11 @@
<?php
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -41,22 +38,34 @@ if (!defined('sugarEntry') || !sugarEntry) {
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
/**
* @deprecated since v7.12.0
* Class UnifiedSearchAdvanced
*/
class UnifiedSearchAdvanced
{
public $query_string = '';
/* path to search form */
public $searchFormPath = 'include/SearchForm/SearchForm2.php';
/*search form class name*/
public $searchFormClass = 'SearchForm';
/**
* @deprecated since v7.12.0
* UnifiedSearchAdvanced constructor.
*/
public function __construct()
{
LoggerManager::getLogger()->deprecated(
'UnifiedSearchAdvanced is deprecated since v7.12.0, please use Search.php instead'
);
if (!empty($_REQUEST['query_string'])) {
$query_string = trim($_REQUEST['query_string']);
if (!empty($query_string)) {
@ -67,6 +76,11 @@ class UnifiedSearchAdvanced
$this->cache_display = sugar_cached('modules/unified_search_modules_display.php');
}
/**
* @deprecated since v7.12.0
* @param string $tpl
* @return string
*/
public function getDropDownDiv($tpl = 'modules/Home/UnifiedSearchAdvanced.tpl')
{
global $app_list_strings, $app_strings;
@ -153,6 +167,7 @@ class UnifiedSearchAdvanced
/**
* @deprecated since v7.12.0
* search
*
* Search function run when user goes to Show All and runs a search again. This outputs the search results
@ -281,7 +296,7 @@ class UnifiedSearchAdvanced
*/
require_once $beanFiles[$beanName] ;
$seed = new $beanName();
require_once $this->searchFormPath;
$searchForm = new $this->searchFormClass($seed, $moduleName) ;
@ -359,6 +374,9 @@ class UnifiedSearchAdvanced
}
}
/**
* @deprecated since v7.12.0
*/
public function buildCache()
{
global $beanList, $beanFiles, $dictionary;
@ -449,6 +467,7 @@ class UnifiedSearchAdvanced
}
/**
* @deprecated since v7.12.0
* Retrieve the enabled and disabled modules used for global search.
*
* @return array
@ -494,6 +513,7 @@ class UnifiedSearchAdvanced
/**
* @deprecated since v7.12.0
* saveGlobalSearchSettings
* This method handles the administrator's request to save the searchable modules selected and stores
* the results in the unified_search_modules_display.php file
@ -520,7 +540,9 @@ class UnifiedSearchAdvanced
}
}
/**
* @deprecated since v7.12.0
*/
public static function unlinkUnifiedSearchModulesFile()
{
//clear the unified_search_module.php file
@ -530,9 +552,10 @@ class UnifiedSearchAdvanced
unlink($cache_search);
}
}
/**
* @deprecated since v7.12.0
* getUnifiedSearchModules
*
* Returns the value of the $unified_search_modules variable based on the module's vardefs.php file
@ -560,6 +583,7 @@ class UnifiedSearchAdvanced
/**
* @deprecated since v7.12.0
* getUnifiedSearchModulesDisplay
*
* Returns the value of the $unified_search_modules_display variable which is based on the $unified_search_modules
@ -587,7 +611,8 @@ class UnifiedSearchAdvanced
return $unified_search_modules_display;
}
/*
/**
* @deprecated since v7.12.0
* writeUnifiedSearchModulesDisplayFile
* Private method to handle writing the unified_search_modules_display value to file
*
@ -613,10 +638,15 @@ class UnifiedSearchAdvanced
}
}
/**
* @deprecated since v7.12.0
* @param $a
* @param $b
* @return int
*/
function unified_search_modules_cmp($a, $b)
{
if (!isset($a['translated']) || !isset($b['translated'])) {
if (!isset($a['translated'], $b['translated'])) {
return 0;
}

View file

@ -1,10 +1,51 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Enumerator;
/**
* Class DatabaseDriver
* @package SuiteCRM\Tests\SuiteCRM\Enumerator
*/
class DatabaseDriver
{
const NO_DRIVER = 'NO_DRIVER';
const MYSQL = 'MYSQL';
const MSSQL = 'MSSQL';
public const NO_DRIVER = 'NO_DRIVER';
public const MYSQL = 'MYSQL';
public const MSSQL = 'MSSQL';
}

View file

@ -1,11 +1,52 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Enumerator;
/**
* Class DesignBreakPoint
* @package SuiteCRM\Tests\SuiteCRM\Enumerator
*/
class DesignBreakPoint
{
const xs = 'xs';
const sm = 'sm';
const md = 'md';
const lg = 'lg';
public const xs = 'xs';
public const sm = 'sm';
public const md = 'md';
public const lg = 'lg';
}

View file

@ -1,13 +1,54 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Enumerator;
/**
* Class SugarObjectType
* @package SuiteCRM\Tests\SuiteCRM\Enumerator
*/
abstract class SugarObjectType
{
const basic = 'basic';
const company = 'company';
const file = 'file';
const issue = 'issue';
const person = 'person';
const sale = 'sale';
public const basic = 'basic';
public const company = 'company';
public const file = 'file';
public const issue = 'issue';
public const person = 'person';
public const sale = 'sale';
}

View file

@ -1,10 +1,51 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Test;
use \SugarBean;
use SugarBean;
use SuiteCRM\Exception\Exception;
/**
* Class BeanFactoryTestCase
* @package SuiteCRM\Tests\SuiteCRM\Test
*/
class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
{
/**
@ -39,10 +80,11 @@ class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
parent::tearDown();
}
/**
* @return array
*/
public function moduleConfigProvider()
public function moduleConfigProvider(): array
{
$this->refreshModuleGlobals();
@ -92,7 +134,7 @@ class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
/**
* @return array
*/
protected function getModuleList()
protected function getModuleList(): array
{
global $beanList;
@ -107,7 +149,7 @@ class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
* @param $moduleClass
* @return bool
*/
protected function shouldSkipModule($moduleClass)
protected function shouldSkipModule($moduleClass): bool
{
global $beanFiles;
@ -126,7 +168,7 @@ class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
/**
* @return void
*/
public function compileIncludeExtFiles()
public function compileIncludeExtFiles(): void
{
$extensionContents = '<?php' . PHP_EOL;
$compiledIncludePath = 'custom/application/Ext/Include';
@ -154,16 +196,14 @@ class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
mkdir_recursive($compiledIncludePath, true);
}
$this->assertTrue(is_writable($compiledIncludePath), 'Not writable: ' . $compiledIncludePath);
self::assertTrue(is_writable($compiledIncludePath), 'Not writable: ' . $compiledIncludePath);
if (is_writable($compiledIncludePath) && !$noExtensions) {
if (!$noExtensions && is_writable($compiledIncludePath)) {
file_put_contents("$compiledIncludePath/modules.ext.php", $extensionContents);
}
if ($noExtensions) {
if (file_exists("$compiledIncludePath/modules.ext.php")) {
unlink("$compiledIncludePath/modules.ext.php");
}
if ($noExtensions && file_exists("$compiledIncludePath/modules.ext.php")) {
unlink("$compiledIncludePath/modules.ext.php");
}
}
@ -172,7 +212,7 @@ class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
* @param $path
* @return bool
*/
protected function shouldSkipFileEntry($file, $path)
protected function shouldSkipFileEntry($file, $path): bool
{
if ($file === '.' || $file === '..' || strtolower(substr($file, -4)) !== '.php') {
return true;
@ -190,7 +230,7 @@ class BeanFactoryTestCase extends SuitePHPUnitFrameworkTestCase
* @param string $className
* @return void
*/
public function addCoreModuleExtension($moduleName, $className)
public function addCoreModuleExtension(string $moduleName, string $className): void
{
$extIncludePath = 'custom/Extension/application/Ext/Include';
$customClassPath = "custom/modules/$moduleName";
@ -214,7 +254,7 @@ EOT;
mkdir_recursive($extIncludePath, true);
}
$this->assertTrue(is_writable($extIncludePath), 'Directory not writable: ' . $extIncludePath);
self::assertTrue(is_writable($extIncludePath), 'Directory not writable: ' . $extIncludePath);
if (is_writable($extIncludePath)) {
file_put_contents("$extIncludePath/ZzzTestCustom$moduleName.php", $extIncludeContents);
@ -224,7 +264,7 @@ EOT;
mkdir_recursive($customClassPath, true);
}
$this->assertTrue(is_writable($customClassPath), 'Directory not writable: ' . $customClassPath);
self::assertTrue(is_writable($customClassPath), 'Directory not writable: ' . $customClassPath);
if (is_writable($customClassPath)) {
file_put_contents("$customClassPath/TestCustom$className.php", $classContents);
@ -238,7 +278,7 @@ EOT;
* @param string $className
* @return void
*/
public function removeCoreModuleExtension($moduleName, $className)
public function removeCoreModuleExtension(string $moduleName, string $className): void
{
if (file_exists("custom/Extension/application/Ext/Include/ZzzTestCustom$moduleName.php")) {
unlink("custom/Extension/application/Ext/Include/ZzzTestCustom$moduleName.php");
@ -254,11 +294,9 @@ EOT;
/**
* @return void
*/
public function removeCoreModuleAllExtension()
public function removeCoreModuleAllExtension(): void
{
$modulesConfig = $this->moduleConfigProvider();
foreach ($modulesConfig as $moduleName => $moduleConfig) {
foreach ($this->moduleConfigProvider() as $moduleName => $moduleConfig) {
if (file_exists("custom/Extension/application/Ext/Include/ZzzTestCustom$moduleName.php")) {
unlink("custom/Extension/application/Ext/Include/ZzzTestCustom$moduleName.php");
}
@ -274,7 +312,7 @@ EOT;
/**
* @return void
*/
public function refreshModuleGlobals()
public function refreshModuleGlobals(): void
{
$beanList = $customBeanList = $objectList = $customObjectList = $beanFiles = $customBeanFiles = [];

View file

@ -1,8 +1,51 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Test\Driver;
class PhpBrowserDriver extends \Codeception\Module\PhpBrowser
use Codeception\Module\PhpBrowser;
/**
* Class PhpBrowserDriver
* @package SuiteCRM\Test\Driver
*/
class PhpBrowserDriver extends PhpBrowser
{
public function _initialize()
{

View file

@ -1,10 +1,50 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Test\Driver;
use Exception;
use Helper\WebDriverHelper;
/**
* Class WebDriver
* @package SuiteCRM\Test\Driver
*/
class WebDriver extends \Codeception\Module\WebDriver
{
public function _initialize()
@ -19,8 +59,8 @@ class WebDriver extends \Codeception\Module\WebDriver
protected function initialWindowSize()
{
$config = $this->_getConfig();
$width = isset($config['width']) ? $config['width'] : 1920;
$height = isset($config['height']) ? $config['height'] : 1080;
$width = $config['width'] ?? 1920;
$height = $config['height'] ?? 1080;
$this->resizeWindow($width, $height);
}

View file

@ -1,4 +1,41 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Test;
@ -11,7 +48,7 @@ use SuiteCRM\TestCaseAbstract;
/**
* Class SuitePHPUnitFrameworkTestCase
* @package SuiteCRM\Test
* @package SuiteCRM\Tests\SuiteCRM\Test
*/
abstract class SuitePHPUnitFrameworkTestCase extends TestCaseAbstract
{
@ -50,6 +87,10 @@ abstract class SuitePHPUnitFrameworkTestCase extends TestCaseAbstract
$db->checkConnection();
}
/**
* @throws Exception
* @noinspection UnusedFunctionResultInspection
*/
protected function setUp(): void
{
parent::setUp();

View file

@ -1,8 +1,47 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Test;
/**
* Class TestLogger
* @package SuiteCRM\Tests\SuiteCRM\Test
*/
class TestLogger
{
@ -32,22 +71,22 @@ class TestLogger
public function __call($name, $arguments)
{
$this->calls[$name][] = $arguments;
$this->notes[] = array(
$this->notes[] = [
'entry_date' => date('Y-m-d H:i:s'),
'level' => $name,
'message' => array_shift($arguments),
'arguments' => $arguments,
'backtrace' => debug_backtrace(),
);
];
}
/**
* @param string|string[] $levels
* @return array
*/
public function getNotes($levels = 'fatal')
public function getNotes($levels = 'fatal'): array
{
$results = array();
$results = [];
if (is_string($levels)) {
$levels = explode(',', $levels);
foreach ($levels as &$level) {
@ -59,15 +98,13 @@ class TestLogger
$results[] = $note;
}
}
return $results;
}
/**
*
*/
public function reset()
public function reset(): void
{
$this->calls = array();
$this->notes = array();
$this->calls = [];
$this->notes = [];
}
}

View file

@ -1,4 +1,41 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace Helper;
@ -7,18 +44,20 @@ namespace Helper;
use Codeception\Exception\ModuleException;
use Codeception\Module;
use PHPUnit_Framework_AssertionFailedError;
use PHPUnit\Framework\AssertionFailedError;
use SuiteCRM\Test\Driver\WebDriver;
/**
* Class Acceptance
* @package Helper
*/
class Acceptance extends Module
{
public function seePageHas($text, $selector = null)
public function seePageHas($text, $selector = null): bool
{
try {
$this->getModule(WebDriver::class)->see($text, $selector);
} catch (PHPUnit_Framework_AssertionFailedError $f) {
return false;
} catch (ModuleException $e) {
} catch (AssertionFailedError | ModuleException $f) {
return false;
}
@ -40,7 +79,7 @@ class Acceptance extends Module
}
// Clean up any files left behind by module builder tests.
private function deleteModulesHelper()
private function deleteModulesHelper(): void
{
$modules = [
'BasicTestModule',
@ -56,7 +95,7 @@ class Acceptance extends Module
try {
$this->deleteModuleFiles($module);
} catch (ModuleException $e) {
return false;
return;
}
}
}
@ -67,7 +106,7 @@ class Acceptance extends Module
* @param string $module
* @throws ModuleException
*/
private function deleteModuleFiles($module)
private function deleteModuleFiles(string $module): void
{
$directories = [
"custom/modulebuilder/builds/{$module}",
@ -80,14 +119,14 @@ class Acceptance extends Module
"custom/Extension/application/Ext/Include/{$module}.php"
];
foreach ($directories as $_index => $directory) {
foreach ($directories as $directory) {
if (is_dir($directory)) {
$this->getModule('Filesystem')->deleteDir($directory);
}
}
foreach ($files as $_index => $file) {
if (file_exists($file)) {
foreach ($files as $file) {
if (is_file($file)) {
unlink($file);
}
}

View file

@ -1,4 +1,41 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace Helper;

View file

@ -1,4 +1,41 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Codeception\Actor;
use Codeception\Lib\Friend;

View file

@ -1,9 +1,45 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace Page;
use \AcceptanceTester as Tester;
use AcceptanceTester as Tester;
use Codeception\Module;
use SuiteCRM\Enumerator\DesignBreakPoint;
@ -26,9 +62,9 @@ class Design extends Module
/**
* @return string
* @see \SuiteCRM\Enumerator\DesignBreakPoint
* @see DesignBreakPoint
*/
public function getBreakpointString()
public function getBreakpointString(): ?string
{
$browserWidth = $this->getBrowserWidth();
$breakpoint = null;

View file

@ -1,35 +1,53 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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.
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM 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.
* 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* 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".
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace Step\Acceptance;
use InvalidArgumentException;
use AcceptanceTester;
use Codeception\Scenario;
class AccountsTester extends \AcceptanceTester
/**
* Class AccountsTester
* @package Step\Acceptance
*/
class AccountsTester extends AcceptanceTester
{
/**
* Create an account
@ -37,7 +55,7 @@ class AccountsTester extends \AcceptanceTester
* @param string $name
* @return string Account ID
*/
public function createAccount($name)
public function createAccount(string $name): string
{
global $db;
$id = create_guid();
@ -49,14 +67,15 @@ class AccountsTester extends \AcceptanceTester
$accountType,
date('Y-m-d H:i:s')
));
return $id;
}
/**
* Creates accounts that can be indexed by elasticsearch
* @param $name
* @param string $name
*/
public function createAccountForElasticSearch($name)
public function createAccountForElasticSearch(string $name): void
{
$I = new EditView($this->getScenario());
$DetailView = new DetailView($this->getScenario());
@ -76,10 +95,9 @@ class AccountsTester extends \AcceptanceTester
}
/**
*
* @return Scenario
*/
public function getPublicScenario()
public function getPublicScenario(): Scenario
{
return $this->getScenario();
}

View file

@ -11,7 +11,7 @@ class ModuleBuilder extends Administration
* @param string $moduleType
* @see SugarObjectType
*/
public function createModule($packageName, $moduleName, $moduleType)
public function createModule($packageName, $moduleName, $moduleType): void
{
$I = $this;
@ -86,7 +86,7 @@ class ModuleBuilder extends Administration
/**
* @param string $packageName
*/
public function selectPackage($packageName)
public function selectPackage($packageName): void
{
$I = $this;
@ -103,7 +103,7 @@ class ModuleBuilder extends Administration
* @param string $packageName
* @param string $moduleName
*/
public function selectModule($packageName, $moduleName)
public function selectModule($packageName, $moduleName): void
{
$I = $this;
@ -118,7 +118,7 @@ class ModuleBuilder extends Administration
$I->waitForElementVisible(['name' => 'savebtn']);
}
public function closePopupSuccess()
public function closePopupSuccess(): void
{
$I = $this;
$I->wait(1);
@ -132,7 +132,7 @@ class ModuleBuilder extends Administration
* @param boolean $packageExists
*
*/
public function deployPackage($packageName, $packageExists = false)
public function deployPackage($packageName, $packageExists = false): void
{
$I = $this;

View file

@ -1,33 +1,45 @@
<?php
/**
* SuiteCRM is a customer relationship management program developed by SalesAgility Ltd.
* Copyright (C) 2021 SalesAgility Ltd.
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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.
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM 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.
* 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* 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".
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace Step\Acceptance;
use \AcceptanceTester as Tester;
use AcceptanceTester as Tester;
use Page\Design;
use SuiteCRM\Enumerator\DesignBreakPoint;
@ -36,11 +48,10 @@ class NavigationBarTester extends Tester
/**
* Click on the home buton / navbar brand
*/
public function clickHome()
public function clickHome(): void
{
$I = $this;
$design = new Design($I);
$breakpoint = $design->getBreakpointString();
$breakpoint = (new Design($I))->getBreakpointString();
switch ($breakpoint) {
// The home button is only available on the large desktop
// We need to select the home module from the all menu for tablet and mobile.
@ -67,11 +78,10 @@ class NavigationBarTester extends Tester
* $I->clickUserMenuItem('Admin')
* $I->clickUserMenuItem('#admin_link')
*/
public function clickUserMenuItem($link)
public function clickUserMenuItem($link): void
{
$I = $this;
$design = new Design($I);
$breakpoint = $design->getBreakpointString();
$breakpoint = (new Design($I))->getBreakpointString();
switch ($breakpoint) {
case DesignBreakPoint::lg:
$I->moveMouseOver('.desktop-bar #toolbar .globalLinks-desktop');
@ -105,11 +115,10 @@ class NavigationBarTester extends Tester
* Also:
* the non filter navigation is not supported by this method
*/
public function clickAllMenuItem($link)
public function clickAllMenuItem($link): void
{
$I = $this;
$design = new Design($I);
$breakpoint = $design->getBreakpointString();
$breakpoint = (new Design($I))->getBreakpointString();
switch ($breakpoint) {
case DesignBreakPoint::lg:
$allMenuButton = '#toolbar.desktop-toolbar > ul.nav.navbar-nav > li.topnav.all';
@ -159,11 +168,10 @@ class NavigationBarTester extends Tester
* Also:
* the non filter navigation is not supported by this method
*/
public function clickCurrentMenuItem($link)
public function clickCurrentMenuItem($link): void
{
$I = $this;
$design = new Design($I);
$breakpoint = $design->getBreakpointString();
$breakpoint = (new Design($I))->getBreakpointString();
switch ($breakpoint) {
case DesignBreakPoint::lg:
$I->moveMouseOver('//*[@id="toolbar"]/ul/li[2]/span[2]/a');

View file

@ -1,7 +1,48 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Faker\Generator;
use SuiteCRM\Enumerator\SugarObjectType;
/**
* Class BasicModuleCest
*/
class BasicModuleCest
{
/**
@ -54,7 +95,7 @@ class BasicModuleCest
$moduleBuilder->createModule(
\Page\BasicModule::$PACKAGE_NAME,
\Page\BasicModule::$NAME,
\SuiteCRM\Enumerator\SugarObjectType::basic
SugarObjectType::basic
);
$repair->clickQuickRepairAndRebuild();

View file

@ -1,6 +1,44 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Faker\Generator;
use SuiteCRM\Enumerator\SugarObjectType;
class CompanyModuleCest
{
@ -17,7 +55,7 @@ class CompanyModuleCest
/**
* @param AcceptanceTester $I
*/
public function _before(AcceptanceTester $I)
public function _before(AcceptanceTester $I): void
{
if (!$this->fakeData) {
$this->fakeData = Faker\Factory::create();
@ -32,7 +70,7 @@ class CompanyModuleCest
/**
* @param AcceptanceTester $I
*/
public function _after(AcceptanceTester $I)
public function _after(AcceptanceTester $I): void
{
}
@ -48,14 +86,14 @@ class CompanyModuleCest
public function testScenarioCreateCompanyModule(
\AcceptanceTester $I,
\Step\Acceptance\ModuleBuilder $moduleBuilder
) {
): void {
$I->wantTo('Create a company module for testing');
$I->loginAsAdmin();
$moduleBuilder->createModule(
\Page\CompanyModule::$PACKAGE_NAME,
\Page\CompanyModule::$NAME,
\SuiteCRM\Enumerator\SugarObjectType::company
SugarObjectType::company
);
}
@ -71,7 +109,7 @@ class CompanyModuleCest
\AcceptanceTester $I,
\Step\Acceptance\NavigationBarTester $navigationBar,
\Step\Acceptance\ListView $listView
) {
): void {
$I->wantTo('View Company Test Module');
$I->loginAsAdmin();
@ -98,7 +136,7 @@ class CompanyModuleCest
\Step\Acceptance\ListView $listView,
\Step\Acceptance\EditView $editView,
\Step\Acceptance\DetailView $detailView
) {
): void {
$I->wantTo('Create Company Test Module Record');
$I->loginAsAdmin();
@ -147,7 +185,7 @@ class CompanyModuleCest
\Step\Acceptance\NavigationBarTester $navigationBar,
\Step\Acceptance\ListView $listView,
\Step\Acceptance\DetailView $detailView
) {
): void {
$I->wantTo('Select Record from list view');
$I->loginAsAdmin();
@ -185,7 +223,7 @@ class CompanyModuleCest
\Step\Acceptance\ListView $listView,
\Step\Acceptance\DetailView $detailView,
\Step\Acceptance\EditView $editView
) {
): void {
$I->wantTo('Edit Company Test Module Record from detail view');
$I->loginAsAdmin();
@ -230,7 +268,7 @@ class CompanyModuleCest
\Step\Acceptance\ListView $listView,
\Step\Acceptance\DetailView $detailView,
\Step\Acceptance\EditView $editView
) {
): void {
$I->wantTo('Duplicate Company Test Module Record from detail view');
$I->loginAsAdmin();
@ -278,7 +316,7 @@ class CompanyModuleCest
\Step\Acceptance\NavigationBarTester $navigationBar,
\Step\Acceptance\ListView $listView,
\Step\Acceptance\DetailView $detailView
) {
): void {
$I->wantTo('Delete Company Test Module Record from detail view');
$I->loginAsAdmin();

View file

@ -1,6 +1,44 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Faker\Generator;
use SuiteCRM\Enumerator\SugarObjectType;
class FileModuleCest
{
@ -53,7 +91,7 @@ class FileModuleCest
$moduleBuilder->createModule(
\Page\FileModule::$PACKAGE_NAME,
\Page\FileModule::$NAME,
\SuiteCRM\Enumerator\SugarObjectType::file
SugarObjectType::file
);
}
@ -120,7 +158,7 @@ class FileModuleCest
$editView->clickSaveButton();
$detailview->waitForDetailViewVisible();
$detailview->see($fileName, '#uploadfile');
$I->deleteFile($fileDir.$fileName);
}
@ -139,7 +177,7 @@ class FileModuleCest
\Step\Acceptance\DetailView $detailView
) {
$I->wantTo('Select Record from list view');
$I->loginAsAdmin();
// Go to File Test Module

View file

@ -1,6 +1,44 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Faker\Generator;
use SuiteCRM\Enumerator\SugarObjectType;
class IssueModuleCest
{
@ -52,7 +90,7 @@ class IssueModuleCest
$moduleBuilder->createModule(
\Page\IssueModule::$PACKAGE_NAME,
\Page\IssueModule::$NAME,
\SuiteCRM\Enumerator\SugarObjectType::issue
SugarObjectType::issue
);
}

View file

@ -1,6 +1,44 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Faker\Generator;
use SuiteCRM\Enumerator\SugarObjectType;
/**
* Class ModuleFieldsCest
@ -57,7 +95,7 @@ class ModuleBuilderFieldsCest
$moduleBuilder->createModule(
\Page\ModuleFields::$PACKAGE_NAME,
\Page\ModuleFields::$NAME,
\SuiteCRM\Enumerator\SugarObjectType::basic
SugarObjectType::basic
);
}

View file

@ -1,7 +1,45 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Faker\Generator;
use JeroenDesloovere\VCard\VCard;
use SuiteCRM\Enumerator\SugarObjectType;
class PersonModuleCest
{
@ -54,7 +92,7 @@ class PersonModuleCest
$moduleBuilder->createModule(
\Page\PersonModule::$PACKAGE_NAME,
\Page\PersonModule::$NAME,
\SuiteCRM\Enumerator\SugarObjectType::person
SugarObjectType::person
);
}

View file

@ -1,6 +1,44 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Faker\Generator;
use SuiteCRM\Enumerator\SugarObjectType;
class SaleModuleCest
{
@ -54,7 +92,7 @@ class SaleModuleCest
$moduleBuilder->createModule(
\Page\SaleModule::$PACKAGE_NAME,
\Page\SaleModule::$NAME,
\SuiteCRM\Enumerator\SugarObjectType::sale
SugarObjectType::sale
);
}

View file

@ -5,7 +5,7 @@
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* 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
* the terms of the GNU Affero General Public License version 3 as published by the
@ -38,36 +38,32 @@
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use Facebook\WebDriver\Exception\UnexpectedAlertOpenException;
use Codeception\Exception\ModuleException;
use Helper\WebDriverHelper;
use Step\Acceptance\AccountsTester;
use Step\Acceptance\NavigationBarTester;
/**
* ElasticsearchCest
*
* Class ElasticsearchCest
* @author gyula
*/
class ElasticsearchCest
{
/**
*
* @param AcceptanceTester $I
* @param WebDriverHelper $helper
* @throws ModuleException
*/
public function testSearchSetup(AcceptanceTester $I, WebDriverHelper $helper)
{
// login..
public function testSearchSetup(AcceptanceTester $I, WebDriverHelper $helper): void
{
$I->loginAsAdmin();
// setup elasticsearch..
$I->click('admin');
// Click on Admin menu:
// TODO: Page css selector error: I found element #admin_link at 3 times. Html tag should have uniqe ID.
$I->click('.navbar.navbar-inverse.navbar-fixed-top .container-fluid .desktop-bar #toolbar #globalLinks .dropdown-menu.user-dropdown.user-menu #admin_link');
$I->click('Search Settings');
$I->selectOption('#search-engine', 'Elasticsearch Engine');
$I->click('Save');
@ -83,7 +79,7 @@ class ElasticsearchCest
$I->wait(1);
$I->seeInPopup('A full indexing has been scheduled and will start in the next 60 seconds. Search results might be inconsistent until the process is complete.');
$I->acceptPopup();
$I->click('Schedule partial indexing');
$I->wait(1);
$I->seeInPopup('A partial indexing has been scheduled and will start in the next 60 seconds.');
@ -96,68 +92,60 @@ class ElasticsearchCest
$I->click('Save');
}
/**
*
* @param AcceptanceTester $I
*/
public function testSearchNotFound(AcceptanceTester $I)
public function testSearchNotFound(AcceptanceTester $I): void
{
// login..
$I->loginAsAdmin();
// lets try out elasticsearch..
// TODO [Selenium browser Logs] 12:47:10.930 SEVERE - http://localhost/SuiteCRM/index.php?action=Login&module=Users - [DOM] Found 2 elements with non-unique id #form: (More info: https://goo.gl/9p2vKq)
$I->fillField('div.desktop-bar ul#toolbar li #searchform .input-group #query_string', 'I_bet_there_is_nothing_to_contains_this');
$I->fillField('div.desktop-bar ul#toolbar li #searchform .input-group #query_string',
'I_bet_there_is_nothing_to_contains_this');
// click on search icon: TODO: search icon ID is not unique:
$I->click('.desktop-bar #searchform > div > span > button');
$I->see('SEARCH');
$I->see('Results');
$I->see('No results matching your search criteria. Try broadening your search.');
$I->fillField('div.desktop-bar ul#toolbar li #searchform .input-group #query_string', 'acc');
$I->click('#search-wrapper-form > table > tbody > tr:nth-child(1) > td > input.button.primary');
$I->see('SEARCH');
$I->see('Results');
$I->see('No results matching your search criteria. Try broadening your search.');
$I->see('Search performed in');
}
/**
*
* @param AccountsTester $accounts
* @param type $max
* @param int $max
* @param int $from
*/
protected function createTestAccounts(AccountsTester $accounts, $max, $from = 0)
protected function createTestAccounts(AccountsTester $accounts, int $max, int $from = 0): void
{
$navi = new NavigationBarTester($accounts->getPublicScenario());
$navi->clickAllMenuItem('Accounts');
for ($i=$from; $i<$max; $i++) {
for ($i = $from; $i < $max; $i++) {
$accounts->createAccountForElasticSearch('acc_for_test ' . $i);
// waiting few second to elasticsearch indexer makes the job done:
// Wait for ElasticSearch indexer:
$accounts->wait(3);
}
// waiting few second to elasticsearch indexer makes the job done:
// Wait for ElasticSearch indexer:
$accounts->wait(5);
}
/**
*
* @param AcceptanceTester $I
* @param AccountsTester $accounts
* @param type $max
* @param int $max
* @throws ModuleException
*/
protected function deleteTestAccounts(AcceptanceTester $I, AccountsTester $accounts, $max)
protected function deleteTestAccounts(AcceptanceTester $I, AccountsTester $accounts, int $max): void
{
$navi = new NavigationBarTester($accounts->getPublicScenario());
$navi->clickAllMenuItem('Accounts');
for ($i=0; $i<$max; $i++) {
for ($i = 0; $i < $max; $i++) {
$I->waitForElementVisible('//*[@id="MassUpdate"]/div[3]/table/tbody/tr[1]/td[3]/b/a');
$I->click('//*[@id="MassUpdate"]/div[3]/table/tbody/tr[1]/td[3]/b/a');
$I->waitForElementVisible('//*[@id="tab-actions"]/a');
@ -168,66 +156,54 @@ class ElasticsearchCest
$I->acceptPopup();
}
}
/**
*
* @param AcceptanceTester $I
* @param AccountsTester $accounts
* @throws ModuleException
*/
public function testSearchFounds(AcceptanceTester $I, AccountsTester $accounts)
public function testSearchFounds(AcceptanceTester $I, AccountsTester $accounts): void
{
$max = 15;
// login..
$I->loginAsAdmin();
// adding some account..
$max = 15;
$this->createTestAccounts($accounts, $max);
// search for them..
$I->fillField('div.desktop-bar ul#toolbar li #searchform .input-group #query_string', 'acc_for_test');
$I->click('.desktop-bar #searchform > div > span > button');
$I->see('SEARCH');
$I->see('Results');
// $I->see('Total result(s): ' . $max);
$I->see('Search performed in');
$I->see('Page 1 of 2');
$I->click('Next');
$I->see('SEARCH');
$I->see('Results');
// $I->see('Total result(s): ' . $max);
$I->see('Search performed in');
$I->see('Page 2 of 2');
$I->fillField('div.desktop-bar ul#toolbar li #searchform .input-group #query_string', '11');
$I->see('SEARCH');
$I->see('Results');
//sometimes elasticsearch indexer randomly broken in travis, so the next check randomly failing:
// $I->see('Total result(s): 1');
$I->see('Search performed in');
$I->see('Accounts');
$I->see('Account Name');
$I->see('acc_for_test 11');
// add few more until end of the last page
$end = 20;
$this->createTestAccounts($accounts, $end, $max);
$I->fillField('div.desktop-bar ul#toolbar li #searchform .input-group #query_string', 'acc_for_test');
$I->click('.desktop-bar #searchform > div > span > button');
$I->see('SEARCH');
$I->see('Results');
//sometimes elasticsearch indexer randomly broken in travis, so the next check randomly failing:
//$I->see('Total result(s): ' . $end);
$I->see('Search performed in');
$I->see('Page 1 of 2');
// clean up test accounts
$this->deleteTestAccounts($I, $accounts, $end);
}
}

1616
tests/api/v8/ModulesCest.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,17 +1,16 @@
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation = "http://schema.phpunit.de/3.7/phpunit.xsd"
backupGlobals = "true"
backupStaticAttributes = "false"
colors = "true"
convertNoticesToExceptions = "true"
convertWarningsToExceptions = "true"
convertErrorsToExceptions = "true"
processIsolation = "false"
stopOnFailure = "false"
stopOnError = "false"
syntaxCheck = "true"
bootstrap = "bootstrap.php">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
backupGlobals="true"
backupStaticAttributes="false"
colors="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
convertErrorsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
stopOnError="false"
bootstrap="bootstrap.php">
<testsuites>
<testsuite name="AllTests">
@ -19,19 +18,27 @@
</testsuite>
</testsuites>
<filter>
<whitelist>
<coverage cacheDirectory="./_output"
includeUncoveredFiles="true"
processUncoveredFiles="true"
pathCoverage="false"
ignoreDeprecatedCodeUnits="true"
disableCodeCoverageIgnore="false">
<include>
<directory suffix=".php">../</directory>
<exclude>
<directory>../.git</directory>
<directory>../.github</directory>
<directory>../XTemplate</directory>
<directory>../cache</directory>
<directory>../vendor</directory>
<directory>../tests</directory>
</exclude>
</whitelist>
</filter>
</include>
<exclude>
<directory>../.git</directory>
<directory>../.github</directory>
<directory>../XTemplate</directory>
<directory>../cache</directory>
<directory>../vendor</directory>
<directory>../tests</directory>
</exclude>
</coverage>
<php>
<ini name="display_errors" value="true"/>

View file

@ -49,53 +49,53 @@ use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
*/
class CustomLoaderTest extends SuitePHPUnitFrameworkTestCase
{
public function testArrayMerge()
public function testArrayMerge(): void
{
$result = CustomLoader::arrayMerge([
['first' => ['one.1', 'one.2', 'one.3'], 'second' => 'two', 'third' => 'three'],
['first' => ['one.4', 'one.5'], 'foo' => ['bar', 'bazz']]
]);
$this->assertEquals([
self::assertEquals([
'first' => ['one.1', 'one.2', 'one.3', 'one.4', 'one.5'],
'second' => 'two',
'third' => 'three',
'foo' => ['bar', 'bazz'],
], $result);
}
public function testMergeCustomArray()
public function testMergeCustomArray(): void
{
$result = CustomLoader::mergeCustomArray(['one', 'two', 'three'], 'testCustom.php');
$this->assertEquals(CustomLoader::ERR_FILE_NOT_FOUND, CustomLoader::getLastError());
$this->assertEquals(['one', 'two', 'three'], $result);
self::assertEquals(CustomLoader::ERR_FILE_NOT_FOUND, CustomLoader::getLastError());
self::assertEquals(['one', 'two', 'three'], $result);
CustomLoader::setCustomPath(__DIR__ . DIRECTORY_SEPARATOR);
$result = CustomLoader::mergeCustomArray(['foo', 'bar'], 'testArray.php');
$this->assertEquals(CustomLoader::ERR_NO_ERROR, CustomLoader::getLastError());
$this->assertEquals(['foo', 'bar', 'bazz', 1, 2, 3], $result);
self::assertEquals(CustomLoader::ERR_NO_ERROR, CustomLoader::getLastError());
self::assertEquals(['foo', 'bar', 'bazz', 1, 2, 3], $result);
try {
$result = CustomLoader::mergeCustomArray(['foo', 'bar'], 'testArrayWrong.php');
$this->assertTrue(false, 'It should throws an exception because the customization is not an array.');
self::assertTrue(false, 'It should throws an exception because the customization is not an array.');
} catch (Exception $e) {
$this->assertEquals(CustomLoader::ERR_WRONG_CUSTOM_FORMAT, $e->getCode());
self::assertEquals(CustomLoader::ERR_WRONG_CUSTOM_FORMAT, $e->getCode());
}
// restore custom route
CustomLoader::setCustomPath();
}
public function testLoadCustomRoutes()
public function testLoadCustomRoutes(): void
{
$app = new App();
CustomLoader::loadCustomRoutes($app, 'testRoutes.php');
$this->assertEquals(CustomLoader::ERR_ROUTE_FILE_NOT_FOUND, CustomLoader::getLastError());
self::assertEquals(CustomLoader::ERR_ROUTE_FILE_NOT_FOUND, CustomLoader::getLastError());
CustomLoader::setCustomPath(__DIR__ . DIRECTORY_SEPARATOR);
CustomLoader::loadCustomRoutes($app, 'testRoutes.php');
$this->assertEquals(CustomLoader::ERR_NO_ERROR, CustomLoader::getLastError());
self::assertEquals(CustomLoader::ERR_NO_ERROR, CustomLoader::getLastError());
// restore custom route
CustomLoader::setCustomPath();
}

View file

@ -0,0 +1,60 @@
<?php
/**
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
namespace SuiteCRM\Tests\Unit;
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
/**
* Class ConfigTest
* @package SuiteCRM\Tests\unit\phpunit
*/
class ConfigTest extends SuitePHPUnitFrameworkTestCase
{
public function test_config(): void
{
global $sugar_config;
self::assertNotEmpty($sugar_config, 'SuiteCRM config is empty');
}
public function testFoo(): void
{
self::assertTrue(true);
}
}

View file

@ -1,17 +0,0 @@
<?php
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
class configTest extends SuitePHPUnitFrameworkTestCase
{
public function test_config()
{
global $sugar_config;
$this->assertNotEmpty($sugar_config, 'SuiteCRM config is empty');
}
public function testFoo()
{
$this->assertTrue(true);
}
}

View file

@ -1,4 +1,42 @@
<?php
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 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 SUGARCRM, SUGARCRM 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 or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* 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 "Powered by
* SugarCRM" logo and "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 "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
use SuiteCRM\Test\BeanFactoryTestCase;
@ -21,13 +59,13 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param array $moduleConfig
* @return void
*/
public function testNewBean($moduleName, $moduleConfig)
public function testNewBean($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$bean = BeanFactory::newBean($moduleName);
$this->assertNotFalse($bean, 'Unable to get core bean for module: ' . $moduleName);
$this->assertInstanceOf(
self::assertNotFalse($bean, 'Unable to get core bean for module: ' . $moduleName);
self::assertInstanceOf(
$moduleConfig['className'],
$bean,
'Loaded bean not instance of core class: ' . $moduleConfig['className']
@ -37,8 +75,8 @@ class BeanFactoryTest extends BeanFactoryTestCase
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$customBean = BeanFactory::newBean($moduleName);
$this->assertNotFalse($customBean, 'Unable to get custom bean for module: ' . $moduleName);
$this->assertInstanceOf(
self::assertNotFalse($customBean, 'Unable to get custom bean for module: ' . $moduleName);
self::assertInstanceOf(
$refreshedConfig['customClassName'],
$customBean,
'Loaded bean not instance of custom class: ' . $refreshedConfig['customClassName']
@ -56,13 +94,13 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param array $moduleConfig
* @return void
*/
public function testGetBean($moduleName, $moduleConfig)
public function testGetBean($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$bean = BeanFactory::getBean($moduleName);
$this->assertNotFalse($bean, 'Unable to get core test record bean for module: ' . $moduleName);
$this->assertInstanceOf(
self::assertNotFalse($bean, 'Unable to get core test record bean for module: ' . $moduleName);
self::assertInstanceOf(
$moduleConfig['className'],
$bean,
'Loaded bean not instance of core class: ' . $moduleConfig['className']
@ -72,8 +110,8 @@ class BeanFactoryTest extends BeanFactoryTestCase
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$customBean = BeanFactory::getBean($moduleName);
$this->assertNotFalse($customBean, 'Unable to get custom test record bean for module: ' . $moduleName);
$this->assertInstanceOf(
self::assertNotFalse($customBean, 'Unable to get custom test record bean for module: ' . $moduleName);
self::assertInstanceOf(
$refreshedConfig['customClassName'],
$customBean,
'Loaded bean not instance of custom class: ' . $refreshedConfig['customClassName']
@ -89,24 +127,24 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param array $moduleConfig
* @return void
*/
public function testGetBeanMeta($moduleName, $moduleConfig)
public function testGetBeanMeta($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$beanMeta = BeanFactory::getBeanMeta($moduleName);
$this->assertEquals($moduleConfig['className'], $beanMeta['beanName']);
$this->assertEquals($moduleConfig['className'], $beanMeta['beanClass']);
$this->assertEquals($moduleConfig['objectName'], $beanMeta['objectName']);
$this->assertEquals($moduleConfig['classFile'], $beanMeta['classFile']);
self::assertEquals($moduleConfig['className'], $beanMeta['beanName']);
self::assertEquals($moduleConfig['className'], $beanMeta['beanClass']);
self::assertEquals($moduleConfig['objectName'], $beanMeta['objectName']);
self::assertEquals($moduleConfig['classFile'], $beanMeta['classFile']);
$this->addCoreModuleExtension($moduleName, $moduleConfig['className']);
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$customBeanMeta = BeanFactory::getBeanMeta($moduleName);
$this->assertEquals($refreshedConfig['customClassName'], $customBeanMeta['customBeanName']);
$this->assertEquals($refreshedConfig['customClassName'], $customBeanMeta['beanClass']);
$this->assertEquals($refreshedConfig['customObjectName'], $customBeanMeta['customObjectName']);
$this->assertEquals($refreshedConfig['customClassFile'], $customBeanMeta['customClassFile']);
self::assertEquals($refreshedConfig['customClassName'], $customBeanMeta['customBeanName']);
self::assertEquals($refreshedConfig['customClassName'], $customBeanMeta['beanClass']);
self::assertEquals($refreshedConfig['customObjectName'], $customBeanMeta['customObjectName']);
self::assertEquals($refreshedConfig['customClassFile'], $customBeanMeta['customClassFile']);
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
}
@ -118,18 +156,18 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param array $moduleConfig
* @return void
*/
public function testGetBeanClass($moduleName, $moduleConfig)
public function testGetBeanClass($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$coreBeanClass = BeanFactory::getBeanClass($moduleName);
$this->assertEquals($moduleConfig['className'], $coreBeanClass);
self::assertEquals($moduleConfig['className'], $coreBeanClass);
$this->addCoreModuleExtension($moduleName, $moduleConfig['className']);
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$customBeanClass = BeanFactory::getBeanClass($moduleName);
$this->assertEquals($refreshedConfig['customClassName'], $customBeanClass);
self::assertEquals($refreshedConfig['customClassName'], $customBeanClass);
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
}
@ -139,20 +177,20 @@ class BeanFactoryTest extends BeanFactoryTestCase
*
* @param string $moduleName
* @param array $moduleConfig
* @return array
* @return void
*/
public function testGetBeanName($moduleName, $moduleConfig)
public function testGetBeanName($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$beanName = BeanFactory::getBeanName($moduleName);
$this->assertEquals($moduleConfig['className'], $beanName);
self::assertEquals($moduleConfig['className'], $beanName);
$this->addCoreModuleExtension($moduleName, $moduleConfig['className']);
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$beanName = BeanFactory::getBeanName($moduleName);
$this->assertNotEquals($refreshedConfig['customClassName'], $beanName);
self::assertNotEquals($refreshedConfig['customClassName'], $beanName);
$this->subTestGetCustomBeanName(compact('moduleName', 'refreshedConfig'));
}
@ -163,10 +201,10 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param array $meta
* @return void
*/
public function subTestGetCustomBeanName($meta)
public function subTestGetCustomBeanName($meta): void
{
$customBeanName = BeanFactory::getCustomBeanName($meta['moduleName']);
$this->assertEquals($meta['refreshedConfig']['customClassName'], $customBeanName);
self::assertEquals($meta['refreshedConfig']['customClassName'], $customBeanName);
$this->removeCoreModuleExtension($meta['moduleName'], $meta['refreshedConfig']['className']);
}
@ -176,20 +214,20 @@ class BeanFactoryTest extends BeanFactoryTestCase
*
* @param string $moduleName
* @param array $moduleConfig
* @return array
* @return void
*/
public function testGetObjectName($moduleName, $moduleConfig)
public function testGetObjectName($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$objectName = BeanFactory::getObjectName($moduleName);
$this->assertEquals($moduleConfig['objectName'], $objectName);
self::assertEquals($moduleConfig['objectName'], $objectName);
$this->addCoreModuleExtension($moduleName, $moduleConfig['className']);
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$objectName = BeanFactory::getObjectName($moduleName);
$this->assertNotEquals($refreshedConfig['customObjectName'], $objectName);
self::assertNotEquals($refreshedConfig['customObjectName'], $objectName);
$this->subTestGetCustomObjectName(compact('moduleName', 'refreshedConfig'));
}
@ -200,10 +238,10 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param array $meta
* @return void
*/
public function subTestGetCustomObjectName($meta)
public function subTestGetCustomObjectName($meta): void
{
$customObjectName = BeanFactory::getCustomObjectName($meta['moduleName']);
$this->assertEquals($meta['refreshedConfig']['customObjectName'], $customObjectName);
self::assertEquals($meta['refreshedConfig']['customObjectName'], $customObjectName);
$this->removeCoreModuleExtension($meta['moduleName'], $meta['refreshedConfig']['className']);
}
@ -214,20 +252,20 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param string $moduleName
* @param array $moduleConfig
*
* @return array
* @return void
*/
public function testGetBeanFile($moduleName, $moduleConfig)
public function testGetBeanFile($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$beanFile = BeanFactory::getBeanFile($moduleName);
$this->assertEquals($moduleConfig['classFile'], $beanFile);
self::assertEquals($moduleConfig['classFile'], $beanFile);
$this->addCoreModuleExtension($moduleName, $moduleConfig['className']);
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$beanFile = BeanFactory::getBeanFile($moduleName);
$this->assertNotEquals($refreshedConfig['customClassFile'], $beanFile);
self::assertNotEquals($refreshedConfig['customClassFile'], $beanFile);
$this->subTestGetCustomBeanFile(compact('moduleName', 'refreshedConfig'));
}
@ -238,10 +276,10 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param array $meta
* @return void
*/
public function subTestGetCustomBeanFile($meta)
public function subTestGetCustomBeanFile($meta): void
{
$customBeanFile = BeanFactory::getCustomBeanFile($meta['moduleName']);
$this->assertEquals($meta['refreshedConfig']['customClassFile'], $customBeanFile);
self::assertEquals($meta['refreshedConfig']['customClassFile'], $customBeanFile);
$this->removeCoreModuleExtension($meta['moduleName'], $meta['refreshedConfig']['className']);
}
@ -252,20 +290,20 @@ class BeanFactoryTest extends BeanFactoryTestCase
* @param string $moduleName
* @param array $moduleConfig
*/
public function testLoadBeanFile($moduleName, $moduleConfig)
public function testLoadBeanFile($moduleName, $moduleConfig): void
{
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
$coreFileLoaded = BeanFactory::loadBeanFile($moduleName);
$this->assertTrue($coreFileLoaded);
$this->assertTrue(class_exists($moduleConfig['className']));
self::assertTrue($coreFileLoaded);
self::assertTrue(class_exists($moduleConfig['className']));
$this->addCoreModuleExtension($moduleName, $moduleConfig['className']);
$refreshedConfig = $this->moduleConfigProvider()[$moduleName]['meta'];
$customFileLoaded = BeanFactory::loadBeanFile($moduleName);
$this->assertTrue($customFileLoaded);
$this->assertTrue(class_exists($refreshedConfig['customClassName']));
self::assertTrue($customFileLoaded);
self::assertTrue(class_exists($refreshedConfig['customClassName']));
$this->removeCoreModuleExtension($moduleName, $moduleConfig['className']);
}

View file

@ -8,7 +8,6 @@ class SugarBeanMock extends SugarBean
*/
public $foo;
/** @noinspection SenselessMethodDuplicationInspection */
/** @noinspection PhpMissingParentConstructorInspection */
/** @noinspection MagicMethodsValidityInspection */
@ -40,14 +39,12 @@ class SugarBeanMock extends SugarBean
}
//setup custom fields
/** @noinspection UnSafeIsSetOverArrayInspection */
if (!isset($this->custom_fields) &&
empty($this->disable_custom_fields)
) {
$this->setupCustomFields($this->module_dir);
}
/** @noinspection NotOptimalIfConditionsInspection */
if (isset($GLOBALS['dictionary'][$this->object_name]) && !$this->disable_vardefs) {
$this->field_name_map = $dictionary[$this->object_name]['fields'];
$this->field_defs = $dictionary[$this->object_name]['fields'];
@ -69,7 +66,6 @@ class SugarBeanMock extends SugarBean
$this->field_defs =& $loaded_definitions[$this->object_name]['field_defs'];
$this->added_custom_field_defs = true;
/** @noinspection UnSafeIsSetOverArrayInspection */
if (!isset($this->custom_fields) &&
empty($this->disable_custom_fields)
) {
@ -93,7 +89,7 @@ class SugarBeanMock extends SugarBean
* @return string
* @throws \Exception
*/
public function publicParseDateDefault($value, $time = false)
public function publicParseDateDefault($value, $time = false): string
{
return $this->parseDateDefault($value, $time);
}/** @noinspection MoreThanThreeArgumentsInspection */
@ -105,7 +101,7 @@ class SugarBeanMock extends SugarBean
* @param string $order_by
* @return array
*/
public static function publicBuildSubQueriesForUnion($subpanel_list, $subpanel_def, $parentbean, $order_by)
public static function publicBuildSubQueriesForUnion($subpanel_list, $subpanel_def, $parentbean, $order_by): array
{
return self::build_sub_queries_for_union($subpanel_list, $subpanel_def, $parentbean, $order_by);
}
@ -113,12 +109,12 @@ class SugarBeanMock extends SugarBean
/**
* @param mixed $testValue
*/
public function setLoadedRelationships($testValue)
public function setLoadedRelationships($testValue): void
{
$this->loaded_relationships = $testValue;
}
public function getEncryptKeyPublic()
public function getEncryptKeyPublic(): string
{
return parent::getEncryptKey();
}

View file

@ -7,7 +7,6 @@ include_once __DIR__ . '/../../../../modules/AM_ProjectTemplates/AM_ProjectTempl
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
use SuiteCRM\Utility\SuiteValidator;
/** @noinspection PhpUndefinedClassInspection */
class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
{
/**
@ -31,36 +30,35 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
* Store static field_defs per modules
* @param string $key
*/
protected function fieldDefsStore($key = 'base')
protected function fieldDefsStore($key = 'base'): void
{
$object = BeanFactory::newBean('Contacts');
$this->fieldDefsStore[$key]['Contact'] = $object->field_defs;
$this->fieldDefsStore[$key]['Contact'] = BeanFactory::newBean('Contacts')->field_defs;
}
/**
* Restore static field_defs per modules
* @param string $key
*/
protected function fieldDefsRestore($key = 'base')
protected function fieldDefsRestore($key = 'base'): void
{
$object = BeanFactory::newBean('Contacts');
$object->field_defs = $this->fieldDefsStore[$key]['Contact'];
}
public function testFactoryGetCachedDeleted()
public function testFactoryGetCachedDeleted(): void
{
// Create a lead and cache it
$lead = BeanFactory::newBean('Leads');
$lead->save();
$bean = BeanFactory::getBean($lead->module_dir, $lead->id);
$this->assertNotEmpty($bean);
self::assertNotEmpty($bean);
// Don't return a cached result if the bean was deleted
$lead->mark_deleted($lead->id);
$this->assertEmpty(BeanFactory::getBean($lead->module_dir, $lead->id));
self::assertEmpty(BeanFactory::getBean($lead->module_dir, $lead->id));
// Unless explicitly specified
$this->assertNotEmpty(BeanFactory::getBean($lead->module_dir, $lead->id, [], false));
self::assertNotEmpty(BeanFactory::getBean($lead->module_dir, $lead->id, [], false));
}
protected function getModuleBean($module)
@ -77,7 +75,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::__construct()
*/
public function testConstruct()
public function testConstruct(): void
{
global $dictionary;
@ -566,7 +564,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::setupCustomFields()
*/
public function testSetupCustomFields()
public function testSetupCustomFields(): void
{
$bean = BeanFactory::getBean('Users');
@ -582,19 +580,17 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::bean_implements()
*/
public function testBeanImplements()
public function testBeanImplements(): void
{
$bean = BeanFactory::getBean('Users');
// test
$results = $bean->bean_implements('test');
$results = BeanFactory::getBean('Users')->bean_implements('test');
self::assertEquals(false, $results);
}
/**
* @see SugarBean::populateDefaultValues()
*/
public function testPopulateDefaultValues()
public function testPopulateDefaultValues(): void
{
$testBean1 = BeanFactory::getBean('Users');
$origFieldDefs = $testBean1->field_defs;
@ -672,7 +668,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::parseDateDefault()
*/
public function testParseDateDefault()
public function testParseDateDefault(): void
{
$bean = new SugarBeanMock();
@ -684,7 +680,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
// test
$results = $bean->publicParseDateDefault('2015-05-05', true);
self::assertNotEquals('05/05/2015', $results);
self::assertEquals(1, preg_match('/05\/05\/2015 \d{2}:\d{2}/', $results));
self::assertMatchesRegularExpression('/05\/05\/2015 \d{2}:\d{2}/', $results);
// test
$results = $bean->publicParseDateDefault('2015-05-05 11:11', true);
@ -698,7 +694,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::removeRelationshipMeta()
*/
public function testRemoveRelationshipMeta()
public function testRemoveRelationshipMeta(): void
{
// test
$GLOBALS['log']->reset();
@ -728,7 +724,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::createRelationshipMeta()
*/
public function testCreateRelationshipMeta()
public function testCreateRelationshipMeta(): void
{
// test
$GLOBALS['log']->reset();
@ -770,7 +766,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
* @see SugarBean::get_union_related_list()
* @todo need more test coverage and less function complexity
*/
public function testGetUnionRelatedList()
public function testGetUnionRelatedList(): void
{
$request = $_REQUEST;
self::assertFalse(isset($_SESSION));
@ -853,7 +849,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::build_sub_queries_for_union()
*/
public function testBuildSubQueriesForUnion()
public function testBuildSubQueriesForUnion(): void
{
// test
$bean = new SugarBeanMock();
@ -924,7 +920,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::process_union_list_query()
*/
public function testProcessUnionListQuery()
public function testProcessUnionListQuery(): void
{
self::markTestIncomplete('environment dependency');
@ -1262,7 +1258,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::retrieve_parent_fields()
*/
public function testRetrieveParentFields()
public function testRetrieveParentFields(): void
{
$GLOBALS['log']->reset();
@ -1386,7 +1382,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getAuditEnabledFieldDefinitions()
*/
public function testGetAuditEnabledFieldDefinitions()
public function testGetAuditEnabledFieldDefinitions(): void
{
$GLOBALS['log']->reset();
@ -1483,7 +1479,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::isOwner()
*/
public function testIsOwner()
public function testIsOwner(): void
{
// test
$GLOBALS['log']->reset();
@ -1555,12 +1551,11 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::get_custom_table_name()
*/
public function testGetCustomTableName()
public function testGetCustomTableName(): void
{
// test
$GLOBALS['log']->reset();
$bean = BeanFactory::newBean('Contacts');
$result = $bean->get_custom_table_name();
$result = BeanFactory::newBean('Contacts')->get_custom_table_name();
self::assertEquals('contacts_cstm', $result);
self::assertFalse(isset($GLOBALS['log']->calls['fatal']));
}
@ -1568,7 +1563,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getTableName()
*/
public function testGetTableName()
public function testGetTableName(): void
{
// test
$GLOBALS['log']->reset();
@ -1594,7 +1589,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getObjectName()
*/
public function testGetObjectName()
public function testGetObjectName(): void
{
// test
$GLOBALS['log']->reset();
@ -1632,7 +1627,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getIndices()
*/
public function testGetIndices()
public function testGetIndices(): void
{
// test
$GLOBALS['log']->reset();
@ -1710,7 +1705,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getPrimaryFieldDefinition()
*/
public function testGetPrimaryFieldDefinition()
public function testGetPrimaryFieldDefinition(): void
{
// test
$GLOBALS['log']->reset();
@ -1758,7 +1753,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getFieldDefinition()
*/
public function testGetFieldDefinition()
public function testGetFieldDefinition(): void
{
// test
$GLOBALS['log']->reset();
@ -1808,7 +1803,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getFieldValue()
*/
public function testGetFieldValue()
public function testGetFieldValue(): void
{
// test
$GLOBALS['log']->reset();
@ -1846,7 +1841,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::unPopulateDefaultValues()
*/
public function testUnPopulateDefaultValues()
public function testUnPopulateDefaultValues(): void
{
// test
$bean = BeanFactory::newBean('Contacts');
@ -1877,7 +1872,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::__clone()
*/
public function testClone()
public function testClone(): void
{
// test
$GLOBALS['log']->reset();
@ -1895,7 +1890,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->setLoadedRelationships(array('foo'));
$clone = clone $bean;
self::assertEquals('bar', $bean->foo);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertNotTrue(isset($clone->foo));
unset($bean->foo);
self::assertEquals($bean, $clone);
@ -1904,7 +1898,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::get_linked_fields()
*/
public function testGetLinkedFields()
public function testGetLinkedFields(): void
{
// test
$GLOBALS['log']->reset();
@ -1950,7 +1944,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getFieldDefinitions()
*/
public function testGetFieldDefinitions()
public function testGetFieldDefinitions(): void
{
// test
$GLOBALS['log']->reset();
@ -1964,7 +1958,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::load_relationship()
*/
public function testLoadRelationship()
public function testLoadRelationship(): void
{
// test
$GLOBALS['log']->reset();
@ -2008,7 +2002,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$GLOBALS['log']->fatal('test');
$bean = BeanFactory::newBean('Contacts');
$bean->field_defs['testKey'] = array('type' => 'link');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testKey = 'testValue';
$results = $bean->load_relationship('testKey');
self::assertEquals(false, $results);
@ -2025,7 +2018,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
'link_class' => 'testClass',
'link_file' => 'testClass.php',
);
/** @noinspection PhpUndefinedFieldInspection */
$bean->testKey = 'testValue';
$results = $bean->load_relationship('testKey');
self::assertEquals(false, $results);
@ -2042,11 +2034,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
'link_class' => 'testClass',
'link_file' => 'modules/Campaigns/ProspectLink.php',
);
/** @noinspection PhpUndefinedFieldInspection */
$bean->testKey = 'testValue';
$results = $bean->load_relationship('testKey');
self::assertEquals(true, $results);
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('testValue', $bean->testKey);
self::assertCount(2, $GLOBALS['log']->calls['fatal']);
@ -2059,11 +2049,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
'link_class' => 'ProspectLink',
'link_file' => 'modules/Campaigns/ProspectLink.php',
);
/** @noinspection PhpUndefinedFieldInspection */
$bean->testKey = 'testValue';
$results = $bean->load_relationship('testKey');
self::assertEquals(true, $results);
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('testValue', $bean->testKey);
self::assertCount(2, $GLOBALS['log']->calls['fatal']);
@ -2078,7 +2066,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
'link_file' => 'modules/Campaigns/ProspectLink.php',
'relationship' => 'campaign_leads',
);
/** @noinspection PhpUndefinedFieldInspection */
$bean->testKey = 'testValue';
$results = $bean->load_relationship('testKey');
self::assertEquals(false, $results);
@ -2090,7 +2077,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::get_linked_beans()
*/
public function testGetLinkedBeans()
public function testGetLinkedBeans(): void
{
// test
$GLOBALS['log']->reset();
@ -2122,7 +2109,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$GLOBALS['log']->reset();
$GLOBALS['log']->fatal('test');
$bean = BeanFactory::newBean('Contacts');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testKey = new ProspectLink('test', $bean);
$results = $bean->get_linked_beans('testKey', 'Case', '', 0, 1);
self::assertEquals(array(), $results);
@ -2132,7 +2118,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::get_import_required_fields()
*/
public function testGetImportRequiredFields()
public function testGetImportRequiredFields(): void
{
// test
$GLOBALS['log']->reset();
@ -2147,7 +2133,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::get_importable_fields()
*/
public function testGetImportableFields()
public function testGetImportableFields(): void
{
// test
$GLOBALS['log']->reset();
@ -2162,7 +2148,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::create_tables()
*/
public function testCreateTables()
public function testCreateTables(): void
{
// test
$bean = BeanFactory::newBean('Contacts');
@ -2179,7 +2165,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getACLCategory()
*/
public function testGetACLCategory()
public function testGetACLCategory(): void
{
// test
$bean = BeanFactory::newBean('Contacts');
@ -2190,7 +2176,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::is_AuditEnabled()
*/
public function testIsAuditEnabled()
public function testIsAuditEnabled(): void
{
// test
$bean = new SugarBeanMock();
@ -2206,34 +2192,32 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::get_audit_table_name()
*/
public function testGetAuditTableNames()
public function testGetAuditTableNames(): void
{
// test
$bean = BeanFactory::newBean('Contacts');
$results = $bean->get_audit_table_name();
$results = BeanFactory::newBean('Contacts')->get_audit_table_name();
self::assertEquals('contacts_audit', $results);
}
/**
* @see SugarBean::create_audit_table()
*/
public function testCreateAuditTable()
public function testCreateAuditTable(): void
{
$query = /** @lang sql */
'DROP TABLE contacts_audit;';
$this->db->query($query);
// test
$bean = BeanFactory::newBean('Contacts');
/** @noinspection PhpVoidFunctionResultUsedInspection */
$results = $bean->create_audit_table();
$results = BeanFactory::newBean('Contacts')->create_audit_table();
self::assertEquals(null, $results);
}
/**
* @see SugarBean::save()
*/
public function testSave()
public function testSave(): void
{
$userFieldDefs = BeanFactory::getBean('Users')->field_defs;
$contactFieldDefs = BeanFactory::getBean('Contacts')->field_defs;
@ -2259,7 +2243,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals($current_user->user_name, $bean->modified_by_name);
self::assertEquals(0, $bean->deleted);
self::assertEquals($bean->date_modified, $bean->date_entered);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
self::assertEquals($bean, $bean->custom_fields->bean);
@ -2285,7 +2268,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals($current_user->user_name, $bean->modified_by_name);
self::assertEquals(0, $bean->deleted);
self::assertEquals($bean->date_modified, $bean->date_entered);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
self::assertFalse($isValidator->isValidId($bean->id));
self::assertEquals($bean, $bean->custom_fields->bean);
@ -2311,7 +2293,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals(0, $bean->deleted);
self::assertEquals($bean->date_modified, $bean->date_entered);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
self::assertFalse($isValidator->isValidId($bean->id));
self::assertEquals($bean, $bean->custom_fields->bean);
@ -2337,9 +2318,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals($current_user->id, $bean->modified_user_id);
self::assertEquals(0, $bean->deleted);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertFalse(isset($bean->date_entered));
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
$GLOBALS['sugar_config']['strict_id_validation'] = false;
@ -2380,11 +2359,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals($current_user->id, $bean->modified_user_id);
self::assertEquals($current_user->user_name, null);
self::assertEquals(null, $current_user->user_name);
self::assertEquals(0, $bean->deleted);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertFalse(isset($bean->date_entered));
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
self::assertFalse($isValidator->isValidId($bean->id));
self::assertEquals($bean, $bean->custom_fields->bean);
@ -2404,9 +2381,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
'type' => 'email',
),
);
/** @noinspection PhpUndefinedFieldInspection */
$bean->emailAddress = BeanFactory::newBean('EmailAddresses');
/** @noinspection PhpUndefinedFieldInspection */
$bean->email_addresses_non_primary = array(true);
$results = null;
try {
@ -2420,11 +2395,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals($current_user->id, $bean->modified_user_id);
self::assertEquals($current_user->user_name, null);
self::assertEquals(null, $current_user->user_name);
self::assertEquals(0, $bean->deleted);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertFalse(isset($bean->date_entered));
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
self::assertFalse($isValidator->isValidId($bean->id));
self::assertEquals($bean, $bean->custom_fields->bean);
@ -2445,9 +2418,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
'type' => 'email',
),
);
/** @noinspection PhpUndefinedFieldInspection */
$bean->emailAddress = BeanFactory::newBean('EmailAddresses');
/** @noinspection PhpUndefinedFieldInspection */
$bean->email_addresses_non_primary = array(true);
$results = null;
try {
@ -2461,11 +2432,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals($current_user->id, $bean->modified_user_id);
self::assertEquals($current_user->user_name, null);
self::assertEquals(null, $current_user->user_name);
self::assertEquals(0, $bean->deleted);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertFalse(isset($bean->date_entered));
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
self::assertFalse($isValidator->isValidId($bean->id));
self::assertEquals($bean, $bean->custom_fields->bean);
@ -2487,9 +2456,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
'type' => 'email',
),
));
/** @noinspection PhpUndefinedFieldInspection */
$bean->emailAddress = BeanFactory::newBean('EmailAddresses');
/** @noinspection PhpUndefinedFieldInspection */
$bean->email_addresses_non_primary = array('testbean1@email.com');
$results = null;
try {
@ -2504,9 +2471,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
self::assertEquals($current_user->id, $bean->modified_user_id);
self::assertEquals($current_user->user_name, $bean->modified_by_name);
self::assertEquals(0, $bean->deleted);
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertFalse(isset($bean->date_entered));
/** @noinspection UnSafeIsSetOverArrayInspection */
self::assertEquals(isset($current_user) ? $current_user->id : '', $bean->created_by);
self::assertFalse($isValidator->isValidId($bean->id));
self::assertEquals($bean, $bean->custom_fields->bean);
@ -2531,7 +2496,7 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::cleanBean()
*/
public function testCleanBean()
public function testCleanBean(): void
{
// test
$bean = BeanFactory::newBean('Contacts');
@ -2539,14 +2504,13 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField = '<p>test <b>html</b> value</p>';
$bean->cleanBean();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('&lt;p&gt;test &lt;b&gt;html&lt;/b&gt; value&lt;/p&gt;', $bean->testField);
}
/**
* @see SugarBean::fixUpFormatting()
*/
public function testFixUpFormatting()
public function testFixUpFormatting(): void
{
// test
$bean = BeanFactory::newBean('Contacts');
@ -2562,7 +2526,6 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'NULL';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('', $bean->testField1);
@ -2571,10 +2534,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'datetime');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'invalid-format';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('', $bean->testField1);
@ -2583,10 +2544,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'date');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'NULL';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('', $bean->testField1);
// test
@ -2594,10 +2553,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'date');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'invalid-format';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('', $bean->testField1);
@ -2606,10 +2563,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'time');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'NULL';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('', $bean->testField1);
@ -2618,10 +2573,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'time');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'invalid-format';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('invalid-format', $bean->testField1);
// test
@ -2629,10 +2582,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'time');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'am';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('am', $bean->testField1);
@ -2641,10 +2592,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'float');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'NULL';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('NULL', $bean->testField1);
@ -2653,10 +2602,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'int');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'NULL';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('NULL', $bean->testField1);
@ -2665,10 +2612,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'int');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'a string here..';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals(0, $bean->testField1);
@ -2677,12 +2622,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = true;
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
// test
@ -2690,12 +2632,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 1;
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
@ -2704,12 +2643,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'true';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
// test
@ -2717,12 +2653,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'TRUE';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
@ -2731,12 +2664,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'on';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
@ -2745,12 +2675,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = false;
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertFalse($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
@ -2759,12 +2686,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = '';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertFalse($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
// test
@ -2772,12 +2696,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 0;
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertFalse($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
@ -2786,12 +2707,9 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = '0';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertFalse($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotNull($bean->testField1);
@ -2800,14 +2718,10 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = null;
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotFalse($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNull($bean->testField1);
@ -2816,10 +2730,8 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'bool');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'NULL';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertTrue($bean->testField1);
@ -2828,14 +2740,10 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'encrypt');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = '';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotFalse($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertEquals('', $bean->testField1);
// test
@ -2843,21 +2751,17 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
$bean->id = 'test_contact_10';
$bean->fetched_row['id'] = 'test_contact_10';
$bean->field_defs['testField1'] = array('type' => 'encrypt');
/** @noinspection PhpUndefinedFieldInspection */
$bean->testField1 = 'a test string value';
$bean->fixUpFormatting();
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotTrue($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotFalse($bean->testField1);
/** @noinspection PhpUndefinedFieldInspection */
self::assertNotEquals('', $bean->testField1);
}
/**
* @see SugarBean::encrpyt_before_save()
*/
public function testEncrpytBeforeSave()
public function testEncrpytBeforeSave(): void
{
$bean = BeanFactory::newBean('Contacts');
@ -2870,17 +2774,16 @@ class SugarBeanTest extends SuitePHPUnitFrameworkTestCase
/**
* @see SugarBean::getEncryptKey()
*/
public function testGetEncryptKey()
public function testGetEncryptKey(): void
{
$bean = new SugarBeanMock();
$results = $bean->getEncryptKeyPublic();
$results = (new SugarBeanMock())->getEncryptKeyPublic();
self::assertEquals(blowfishGetKey('encrypt_field'), $results);
}
/**
* @see SugarBean::has_been_modified_since()
*/
public function testHasBeenModifiedSince()
public function testHasBeenModifiedSince(): void
{
// test
$bean = BeanFactory::newBean('Contacts');

View file

@ -1,18 +0,0 @@
<?php
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
class ControllerFactoryTest extends SuitePHPUnitFrameworkTestCase
{
public function testgetController()
{
//execute the method with invalid input
$controller = ControllerFactory::getController('');
$this->assertInstanceOf('SugarController', $controller);
//execute the method with valid input and check if it returns correct instance
$controller = ControllerFactory::getController('Users');
$this->assertInstanceOf('UsersController', $controller);
$this->assertInstanceOf('SugarController', $controller);
}
}

View file

@ -1,61 +0,0 @@
<?php
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
class SugarModuleTest extends SuitePHPUnitFrameworkTestCase
{
public function testconstructor()
{
//test for invalid input
$sugarmodule = new SugarModule('');
$this->assertAttributeEquals(null, '_moduleName', $sugarmodule);
//test for valid input
$sugarmodule_user = SugarModule::get('User');
$this->assertAttributeEquals('User', '_moduleName', $sugarmodule_user);
}
public function testget()
{
//test for invalid input
$sugarmodule = SugarModule::get('');
$this->assertInstanceOf('SugarModule', $sugarmodule);
$this->assertAttributeEquals(null, '_moduleName', $sugarmodule);
//test for valid input
$sugarmodule_user = SugarModule::get('User');
$this->assertInstanceOf('SugarModule', $sugarmodule_user);
$this->assertAttributeEquals('User', '_moduleName', $sugarmodule_user);
}
public function testmoduleImplements()
{
//test for invalid input
$sugarmodule = new SugarModule('');
$result = $sugarmodule->moduleImplements('Basic');
$this->assertEquals(false, $result);
//test for invalid input
$sugarmodule_user = new SugarModule('Users');
$result = $sugarmodule_user->moduleImplements('SugarModule');
$this->assertFalse($result);
//test for valid input
$sugarmodule_user = new SugarModule('Users');
$result = $sugarmodule_user->moduleImplements('Basic');
$this->assertEquals(true, $result);
}
public function testloadBean()
{
//test for invalid input
$sugarmodule = new SugarModule('');
$result = $sugarmodule->loadBean();
$this->assertFalse($result);
//test for valid input
$sugarmodule_user = new SugarModule('Users');
$result = $sugarmodule_user->loadBean();
$this->assertInstanceOf('User', $result);
}
}

View file

@ -1,278 +0,0 @@
<?php
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
class SugarViewTest extends SuitePHPUnitFrameworkTestCase
{
protected function setUp(): void
{
parent::setUp();
global $current_user;
get_sugar_config_defaults();
$current_user = BeanFactory::newBean('Users');
}
public function testinit()
{
//error_reporting(E_ERROR | E_WARNING | E_PARSE);
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
try {
$SugarView->init();
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
$this->assertTrue(true);
}
public function testprocess()
{
// test
$SugarView = new SugarView();
$SugarView->module = 'Users';
$GLOBALS['app'] = new SugarApplication();
//execute the method and check if it works and doesn't throws an exception
//secondly check if it outputs any content to browser
try {
ob_start();
$SugarView->process();
$renderedContent = ob_get_contents();
ob_end_clean();
$this->assertGreaterThan(0, strlen($renderedContent));
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
}
public function testdisplayErrors()
{
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
try {
$errors = $SugarView->displayErrors();
$this->assertEmpty($errors, print_r($SugarView, true));
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
$this->assertTrue(true);
}
public function testpreDisplay()
{
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
try {
$SugarView->preDisplay();
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
$this->assertTrue(true);
}
public function testdisplay()
{
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
try {
$SugarView->display();
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
$this->assertTrue(true);
}
public function testdisplayHeader()
{
$SugarView = new SugarView();
$SugarView->module = 'Users';
$GLOBALS['app'] = new SugarApplication();
//execute the method and check if it works and doesn't throws an exception
//secondly check if it outputs any content to browser
try {
ob_start();
$SugarView->displayHeader();
$renderedContent = ob_get_contents();
ob_end_clean();
$this->assertGreaterThan(0, strlen($renderedContent));
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
}
public function testgetModuleMenuHTML()
{
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
try {
$SugarView->getModuleMenuHTML();
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
$this->assertTrue(true);
}
public function testincludeClassicFile()
{
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
//use any valid file path, we just need to avoid failing require_once
try {
$SugarView->includeClassicFile('config.php');
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
$this->assertTrue(true);
}
public function testgetJavascriptValidation()
{
//check if it returns any text i-e JS code
$js = SugarView::getJavascriptValidation();
$this->assertGreaterThan(0, strlen($js));
}
public function testdisplayFooter()
{
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
//secondly check if it outputs any content to browser
try {
ob_start();
$SugarView->displayFooter();
$renderedContent = ob_get_contents();
ob_end_clean();
$this->assertGreaterThan(0, strlen($renderedContent));
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
}
public function testrenderJavascript()
{
$SugarView = new SugarView();
//execute the method and check if it works and doesn't throws an exception
//secondly check if it outputs any content to browser
try {
ob_start();
$SugarView->renderJavascript();
$renderedContent = ob_get_contents();
ob_end_clean();
$this->assertGreaterThan(0, strlen($renderedContent));
} catch (Exception $e) {
$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
}
}
public function testgetMenu()
{
////error_reporting(E_ALL);
$SugarView = new SugarView();
//execute the method and check if it works and throws an exception if no module is provided
//it creates memory Fatal errors which causes PHPunit to crash so we will skip this scenario
/*
try {
//check first with invalid value and test if it throws an exception
$menu = $SugarView->getMenu();
//$this->assertTrue(is_array($menu));
} catch (Exception $e) {
$this->assertTrue(TRUE);
//$this->fail($e->getMessage() . "\nTrace:\n" . $e->getTraceAsString());
} */
//check with valid value and check if it returns an array.
$menu = $SugarView->getMenu('Users');
$this->assertTrue(is_array($menu));
}
public function testgetModuleTitle()
{
$SugarView = new SugarView();
//first execute the method with default value
$moduleTitle = $SugarView->getModuleTitle();
$this->assertGreaterThan(0, strlen($moduleTitle));
//second execute the method with true value
$moduleTitle = $SugarView->getModuleTitle(true);
$this->assertGreaterThan(0, strlen($moduleTitle));
//third execute the method with false value
$moduleTitle = $SugarView->getModuleTitle(false);
$this->assertGreaterThan(0, strlen($moduleTitle));
}
public function testgetMetaDataFile()
{
$SugarView = new SugarView();
//first execute the method with missing attributes. it should return Null.
$metaDataFile = $SugarView->getMetaDataFile();
$this->assertEquals(null, $metaDataFile);
//second execute the method with valid attributes set. it should return a file path string.
$SugarView->type = 'detail';
$SugarView->module = 'Users';
$metaDataFile = $SugarView->getMetaDataFile();
$this->assertGreaterThan(0, strlen($metaDataFile));
}
public function testgetBrowserTitle()
{
$SugarView = new SugarView();
//execute the method. it should return a title string.
$browserTitle = $SugarView->getBrowserTitle();
$this->assertGreaterThan(0, strlen($browserTitle));
}
public function testgetBreadCrumbSymbol()
{
$SugarView = new SugarView();
//execute the method. it should return a string.
$breadCrumbSymbol = $SugarView->getBreadCrumbSymbol();
$this->assertGreaterThan(0, strlen($breadCrumbSymbol));
}
public function testcheckPostMaxSizeError()
{
$SugarView = new SugarView();
//execute the method. it should return False because Request parameters are not available.
$postMaxSizeError = $SugarView->checkPostMaxSizeError();
$this->assertFalse($postMaxSizeError);
}
}

View file

@ -1,71 +0,0 @@
<?php
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;
class ViewFactoryTest extends SuitePHPUnitFrameworkTestCase
{
public function testloadView()
{
//check with invalid input. must return sugaview instance
$view = ViewFactory::loadView('default', '');
$this->assertInstanceOf('SugarView', $view);
//check with a valid module without a specific view, must return sugarview instance
$view = ViewFactory::loadView('default', 'Users');
$this->assertInstanceOf('SugarView', $view);
//check with a valid module and specific view, must reutern speciifc view instance
$view = ViewFactory::loadView('list', 'Users');
$this->assertInstanceOf('UsersViewList', $view);
}
public function test_loadConfig()
{
//check with a invalid module, method must not change the view options.
$view = ViewFactory::loadView('default', '');
$options = $view->options;
ViewFactory::_loadConfig($view, 'default');
$this->assertSame($options, $view->options);
//check with a valid module which does not implement it's own view config. method must not change the view options.
$view = ViewFactory::loadView('detail', 'Users');
$options = $view->options;
ViewFactory::_loadConfig($view, 'detail');
$this->assertSame($options, $view->options);
//check with a valid module which implement it's own view config. method still must not change the view options because it needs.
$view = ViewFactory::loadView('area_detail_map', 'jjwg_Areas');
$view->module = 'jjwg_Areas';
$options = $view->options;
ViewFactory::_loadConfig($view, 'area_detail_map');
$this->assertSame($options, $view->options);
}
public function test_buildFromFile()
{
//check with valid values and test if it returns correct view instance
$type = 'list';
$target_module = 'Users';
$bean = null;
$view = ViewFactory::_buildFromFile('modules/'.$target_module.'/views/view.'.$type.'.php', $bean, array(), $type, $target_module);
$this->assertInstanceOf('UsersViewList', $view);
//check with valid values and test if it returns correct view instance
$type = 'detail';
$target_module = 'Users';
$bean = null;
$view = ViewFactory::_buildFromFile('modules/'.$target_module.'/views/view.'.$type.'.php', $bean, array(), $type, $target_module);
$this->assertInstanceOf('UsersViewDetail', $view);
}
public function test_buildClass()
{
//check with valid values and test if it returns correct view instance
$view = ViewFactory::_buildClass('UsersViewList', null, array());
$this->assertInstanceOf('UsersViewList', $view);
//check with valid values and test if it returns correct view instance
$view = ViewFactory::_buildClass('UsersViewDetail', null, array());
$this->assertInstanceOf('UsersViewDetail', $view);
}
}

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