Compare commits

..

61 Commits

Author SHA1 Message Date
yuri e9208602f6 css fix 2019-09-19 12:00:03 +03:00
yuri e1d7733848 meeting/call do not show send invitees if only own user and accepted 2019-09-18 11:07:10 +03:00
yuri b08f7de0cb email address fix double escaping 2019-09-18 10:48:12 +03:00
yuri d83f02010a fix inbound email from address 2019-09-18 10:26:10 +03:00
yuri 88bc592fcd Merge branch 'hotfix/5.6.14' of ssh://172.20.0.1/var/git/espo/backend into hotfix/5.6.14 2019-09-17 17:35:54 +03:00
Taras Machyshyn 9c2a125365 Field Manager fix 2019-09-17 17:04:36 +03:00
yuri e79e75c0d5 text field remove default rows param 2019-09-16 12:32:14 +03:00
yuri 2187073e2b css fix side navbar tab 2019-09-16 10:45:54 +03:00
yuri 3c36e81502 add ouath-callback to build 2019-09-16 10:34:39 +03:00
yuri f8bafa5221 fix orm order 2019-09-13 12:58:44 +03:00
yuri 00a0cb1394 fix test 2019-09-13 12:58:31 +03:00
yuri 3a37f8421d fix action handler 2019-09-13 12:25:50 +03:00
yuri 2dbde4e2c8 fix detail action label 2019-09-13 11:58:04 +03:00
yuri 98084e9314 formula addLinkMultipleId do not throw error 2019-09-13 11:37:55 +03:00
yuri 2946969e3a detail custom actions 2019-09-13 11:36:01 +03:00
yuri 75c3891654 action history user type 2019-09-12 17:21:51 +03:00
yuri c0866c8fea fix email template insert 2019-09-12 16:57:19 +03:00
yuri 5d3a785a49 v 2019-09-12 16:41:20 +03:00
yuri 4bcf88dcee fix mail sender 2019-09-12 16:39:32 +03:00
yuri 022d9a42ec transfromMarkdownText 2019-09-12 11:06:57 +03:00
yuri ac80f67533 fix view helper 2019-09-11 15:55:02 +03:00
yuri 83fa22852a lang no quote escaping 2019-09-10 16:52:42 +03:00
yuri 7ffd8a54a1 v 2019-09-10 11:07:44 +03:00
yuri 739cb5e98f emailFoldersDisabled param 2019-09-10 11:04:13 +03:00
yuri f5e1b7175e utils checkActionAvailability 2019-09-10 11:03:56 +03:00
yuri 81cb2aaeb8 fix navbar tpl 2019-09-09 13:28:53 +03:00
yuri 01ba132a62 field manager fix 2019-09-06 16:19:49 +03:00
yuri 4b31173355 multi enum fix 2019-09-06 15:21:39 +03:00
yuri 34cd265fc1 afterRelate hook for link multiple save 2019-09-04 11:27:27 +03:00
yuri 93f8ef9daa Merge branch 'hotfix/5.6.12' of ssh://172.20.0.1/var/git/espo/backend into hotfix/5.6.12 2019-09-03 11:04:15 +03:00
Taras Machyshyn 81ffbc8e6d Merge branch 'hotfix/5.6.12' of ssh://172.20.0.1/var/git/espo/backend into hotfix/5.6.12 2019-09-02 18:18:40 +03:00
Taras Machyshyn 061dda1a1e Fixed index name issue 2019-09-02 18:18:30 +03:00
yuri 41d8605e17 fix typo 2019-08-29 10:41:56 +03:00
yuri 13a2ba47e7 fix wysiwyg 2019-08-28 16:58:33 +03:00
yuri 4c598d19b5 link one empty filters 2019-08-28 12:13:27 +03:00
yuri 7d4227c98d Merge branch 'hotfix/5.6.12' of ssh://172.20.0.1/var/git/espo/backend into hotfix/5.6.12 2019-08-27 15:19:15 +03:00
Taras Machyshyn 1102e9f1e8 Added support PHPUnit 8 2019-08-27 14:57:31 +03:00
Taras Machyshyn 607ee9a080 Fix errors in a test 2019-08-26 17:13:33 +03:00
yuri e30838cf27 link fields empty name fix 2019-08-22 12:10:08 +03:00
yuri 790355fb63 lead converted at 2019-08-22 11:46:46 +03:00
yuri 371fbf9864 email skip index if filter 2019-08-21 16:35:45 +03:00
Taras Machyshyn e3ac8c3f67 Bug fixes for url params util 2019-08-20 13:58:37 +03:00
Taras Machyshyn 2087894c3a Added 'binary' option for a field 2019-08-19 17:21:00 +03:00
yuri 5c00a7ad43 fix email fitler duplicate 2019-08-19 11:44:25 +03:00
yuri fe0dcc5342 remove duplicate label 2019-08-19 11:24:34 +03:00
Taras Machyshyn f05381cc43 Corrected file permissions 2019-08-15 17:18:08 +03:00
yuri a9a30d7237 duplicate silent confict exception 2019-08-14 13:09:22 +03:00
yuri 5312c1d141 image original link 2019-08-14 12:07:51 +03:00
yuri a97d516c4f restrict common entity type name 2019-08-13 17:03:28 +03:00
Taras Machyshyn 16c24abb55 Integration tests: create database if not exists 2019-08-13 16:09:02 +03:00
Taras Machyshyn ed897e9b97 Util changes 2019-08-13 11:56:15 +03:00
Taras Machyshyn b4b222c1d7 Unit tests for sanitizeHtml() 2019-08-12 15:23:29 +03:00
yuri a68d711249 summernote fix fullscreen 2019-08-12 15:15:57 +03:00
Taras Machyshyn d6834f7f97 Installer changes 2019-08-12 14:53:11 +03:00
Taras Machyshyn 20818659e8 Installer changes 2019-08-12 14:49:25 +03:00
yuri 1c668ce983 signature toolbar 2019-08-12 11:39:59 +03:00
yuri a9dacd74c6 v 2019-08-12 10:56:29 +03:00
yuri b7c9ddc4e6 auth token secret fixes 2019-08-12 10:56:11 +03:00
yuri d5ee599f9f language fix 2019-08-12 10:25:12 +03:00
yuri 742f4e21b5 comment out auth token secret 2019-08-10 19:11:03 +03:00
yuri 78fc80a619 v 2019-08-10 19:08:57 +03:00
121 changed files with 883 additions and 325 deletions
+1
View File
@@ -190,6 +190,7 @@ module.exports = function (grunt) {
'extension.php',
'websocket.php',
'command.php',
'oauth-callback.php',
'index.php',
'LICENSE.txt',
'.htaccess',
@@ -121,6 +121,8 @@ class FieldManager extends \Espo\Core\Controllers\Base
$this->getContainer()->get('fieldManager')->resetToDefault($data->scope, $data->name);
$this->getContainer()->get('dataManager')->clearCache();
$this->getContainer()->get('dataManager')->rebuildMetadata();
return true;
@@ -0,0 +1,35 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2019 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
namespace Espo\Core\Exceptions;
class ConflictSilent extends Conflict
{
public $logLevel = 'notice';
}
@@ -65,7 +65,7 @@ class AddLinkMultipleIdType extends \Espo\Core\Formula\Functions\Base
}
} else {
if (!is_string($id)) {
throw new Error();
return;
}
$this->getEntity()->addLinkMultipleId($link, $id);
}
+1 -1
View File
@@ -172,7 +172,7 @@ class Sender
return $this;
}
public function send(Email $email, $params = [], &$message = null, $attachmentList = [])
public function send(Email $email, $params = [], $message = null, $attachmentList = [])
{
if (!$message) {
$message = new Message();
+35 -15
View File
@@ -197,10 +197,10 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
protected function afterMassRelate(Entity $entity, $relationName, array $params = [], array $options = [])
{
if (!$this->hooksDisabled && empty($options['skipHooks'])) {
$hookData = array(
$hookData = [
'relationName' => $relationName,
'relationParams' => $params
);
'relationParams' => $params,
];
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterMassRelate', $entity, $options, $hookData);
}
}
@@ -215,14 +215,24 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
{
parent::afterRelate($entity, $relationName, $foreign, $data, $options);
if ($foreign instanceof Entity) {
$foreignEntity = $foreign;
if (!$this->hooksDisabled && empty($options['skipHooks'])) {
$hookData = array(
if (!$this->hooksDisabled && empty($options['skipHooks'])) {
if (is_string($foreign)) {
$foreignId = $foreign;
$foreignEntityType = $entity->getRelationParam($relationName, 'entity');
if ($foreignEntityType) {
$foreign = $this->getEntityManager()->getEntity($foreignEntityType);
$foreign->id = $foreignId;
$foreign->setAsFetched();
}
}
if ($foreign instanceof Entity) {
$hookData = [
'relationName' => $relationName,
'relationData' => $data,
'foreignEntity' => $foreignEntity
);
'foreignEntity' => $foreign,
'foreignId' => $foreign->id,
];
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterRelate', $entity, $options, $hookData);
}
}
@@ -232,13 +242,23 @@ class RDB extends \Espo\ORM\Repositories\RDB implements Injectable
{
parent::afterUnrelate($entity, $relationName, $foreign, $options);
if ($foreign instanceof Entity) {
$foreignEntity = $foreign;
if (!$this->hooksDisabled && empty($options['skipHooks'])) {
$hookData = array(
if (!$this->hooksDisabled && empty($options['skipHooks'])) {
if (is_string($foreign)) {
$foreignId = $foreign;
$foreignEntityType = $entity->getRelationParam($relationName, 'entity');
if ($foreignEntityType) {
$foreign = $this->getEntityManager()->getEntity($foreignEntityType);
$foreign->id = $foreignId;
$foreign->setAsFetched();
}
}
if ($foreign instanceof Entity) {
$hookData = [
'relationName' => $relationName,
'foreignEntity' => $foreignEntity
);
'foreignEntity' => $foreign,
'foreignId' => $foreign->id,
];
$this->getEntityManager()->getHookManager()->process($this->entityType, 'afterUnrelate', $entity, $options, $hookData);
}
}
+29 -3
View File
@@ -144,6 +144,12 @@ class Auth
$createTokenSecret = $this->request->headers->get('Espo-Authorization-Create-Token-Secret') === 'true';
if ($createTokenSecret) {
if ($this->getConfig()->get('authTokenSecretDisabled')) {
$createTokenSecret = false;
}
}
if (!$isByTokenOnly) {
$this->checkFailedAttemptsLimit($username);
}
@@ -270,8 +276,7 @@ class Auth
if ($createTokenSecret) {
$secret = $this->generateToken();
$authToken->set('secret', $secret);
setcookie('auth-token-secret', $secret, strtotime('+1000 days'), '/; samesite=lax', '', false, true);
$this->setSecretInCookie($secret);
}
if ($this->isPortal()) {
@@ -353,10 +358,16 @@ class Auth
public function destroyAuthToken($token)
{
$authToken = $this->getEntityManager()->getRepository('AuthToken')->select(['id', 'isActive'])->where(['token' => $token])->findOne();
$authToken = $this->getEntityManager()->getRepository('AuthToken')->select(['id', 'isActive', 'secret'])->where(['token' => $token])->findOne();
if ($authToken) {
$authToken->set('isActive', false);
$this->getEntityManager()->saveEntity($authToken);
if ($authToken->get('secret')) {
$sentSecret = $_COOKIE['auth-token-secret'] ?? null;
if ($sentSecret === $authToken->get('secret')) {
setcookie('auth-token-secret', null, -1, '/');
}
}
return true;
}
}
@@ -398,4 +409,19 @@ class Auth
$authLogRecord->set('denialReason', $denialReason);
$this->getEntityManager()->saveEntity($authLogRecord);
}
protected function setSecretInCookie(string $secret)
{
if (version_compare(\PHP_VERSION, '7.3.0') < 0) {
setcookie('auth-token-secret', $secret, strtotime('+1000 days'), '/', '', false, true);
return;
}
setcookie('auth-token-secret', $secret, [
'expires' => strtotime('+1000 days'),
'path' => '/',
'httponly' => true,
'samesite' => 'Lax',
]);
}
}
@@ -31,7 +31,6 @@ namespace Espo\Core\Utils\Database\DBAL\Schema;
class Column extends \Doctrine\DBAL\Schema\Column
{
/**
* @var boolean
*/
@@ -42,6 +41,7 @@ class Column extends \Doctrine\DBAL\Schema\Column
*/
protected $_unique = false;
protected $_quoted = true;
/**
* @param boolean $unique
@@ -85,4 +85,4 @@ class Column extends \Doctrine\DBAL\Schema\Column
), $this->_platformOptions, $this->_customSchemaOptions);
}
}
}
@@ -30,6 +30,7 @@
namespace Espo\Core\Utils\Database\DBAL\Schema;
use Doctrine\DBAL\Schema\Index as DBALIndex;
use Doctrine\DBAL\Platforms\AbstractPlatform;
class Index extends \Doctrine\DBAL\Schema\Index
{
@@ -79,4 +80,16 @@ class Index extends \Doctrine\DBAL\Schema\Index
return false;
}
}
public function getQuotedColumns(AbstractPlatform $platform)
{
$columns = array();
foreach ($this->_columns as $column) {
$column->_quoted = true;
$columns[] = $column->getQuotedName($platform);
}
return $columns;
}
}
@@ -34,6 +34,8 @@ use Doctrine\DBAL\Schema\SchemaException;
class Table extends \Doctrine\DBAL\Schema\Table
{
protected $_quoted = true;
/**
* @param string $columnName
* @param string $typeName
@@ -81,4 +83,4 @@ class Table extends \Doctrine\DBAL\Schema\Table
return $this;
}
}
}
@@ -92,6 +92,7 @@ class Converter
'orderBy' => 'orderBy',
'where' => 'where',
'storeArrayValues' => 'storeArrayValues',
'binary' => 'binary',
);
protected $idParams = array(
@@ -408,9 +408,15 @@ class Converter
$dbFieldParams['unsigned'] = true;
}
if (isset($fieldParams['binary']) && $fieldParams['binary']) {
$dbFieldParams['platformOptions'] = array(
'collation' => 'utf8mb4_bin',
);
}
if (isset($fieldParams['utf8mb3']) && $fieldParams['utf8mb3']) {
$dbFieldParams['platformOptions'] = array(
'collation' => 'utf8_unicode_ci',
'collation' => (isset($fieldParams['binary']) && $fieldParams['binary']) ? 'utf8_bin' : 'utf8_unicode_ci',
);
}
@@ -54,7 +54,7 @@ class EntityManager
private $linkForbiddenNameList = ['posts', 'stream', 'subscription', 'followers', 'action', 'null', 'false', 'true'];
private $forbiddenEntityTypeNameList = ['PortalUser', 'ApiUser', 'Timeline', 'About', 'Admin', 'Null', 'False', 'True'];
private $forbiddenEntityTypeNameList = ['Common', 'PortalUser', 'ApiUser', 'Timeline', 'About', 'Admin', 'Null', 'False', 'True'];
public function __construct(Metadata $metadata, Language $language, File\Manager $fileManager, Config $config, Container $container = null)
{
+19 -28
View File
@@ -271,7 +271,7 @@ class FieldManager
$entityDefs = $this->normalizeDefs($scope, $name, $fieldDefs);
if (!empty($entityDefs)) {
if (!empty((array) $entityDefs)) {
$result &= $this->saveCustomEntityDefs($scope, $entityDefs);
$this->isChanged = true;
}
@@ -430,13 +430,15 @@ class FieldManager
return $this->getMetadata()->get('entityDefs'.'.'.$scope.'.fields.'.$name, $default);
}
protected function getCustomFieldDefs($scope, $name)
protected function getCustomFieldDefs($scope, $name, $default = null)
{
$customDefs = $this->getMetadata()->getCustom('entityDefs', $scope, (object) []);
if (isset($customDefs->fields->$name)) {
return (array) $customDefs->fields->$name;
}
return $default;
}
protected function saveCustomEntityDefs($scope, $newDefs)
@@ -529,43 +531,32 @@ class FieldManager
}
}
$actualCustomFieldDefs = $this->getCustomFieldDefs($scope, $name);
$actualCustomFieldDefs = $this->getCustomFieldDefs($scope, $name, []);
$actualFieldDefs = $this->getFieldDefs($scope, $name, []);
$permittedParamList = array_keys($params);
$filteredFieldDefs = $actualCustomFieldDefs ? $actualCustomFieldDefs : [];
$filteredFieldDefs = !empty($actualCustomFieldDefs) ? $actualCustomFieldDefs : [];
foreach ($fieldDefs as $paramName => $paramValue) {
if (in_array($paramName, $permittedParamList)) {
$defaultParamValue = null;
switch ($params[$paramName]['type']) {
case 'bool':
$fieldDefsDefaultValue = array_key_exists('default', $params[$paramName]) ? $params[$paramName]['default'] : false;
$actualValue = array_key_exists($paramName, $actualFieldDefs) ? $actualFieldDefs[$paramName] : $fieldDefsDefaultValue;
if (!Util::areValuesEqual($actualValue, $paramValue)) {
$filteredFieldDefs[$paramName] = $paramValue;
}
$defaultParamValue = false;
break;
}
default:
if (!array_key_exists('default', $params[$paramName]) && !array_key_exists($paramName, $actualFieldDefs)) {
$filteredFieldDefs[$paramName] = $paramValue;
break;
}
$actualValue = array_key_exists($paramName, $actualFieldDefs) ? $actualFieldDefs[$paramName] : $defaultParamValue;
if (array_key_exists('default', $params[$paramName])) {
$actualValue = $params[$paramName]['default'];
}
if (!array_key_exists($paramName, $actualCustomFieldDefs) && !Util::areValuesEqual($actualValue, $paramValue)) {
$filteredFieldDefs[$paramName] = $paramValue;
continue;
}
if (array_key_exists($paramName, $actualFieldDefs)) {
$actualValue = $actualFieldDefs[$paramName];
}
if (!Util::areValuesEqual($actualValue, $paramValue)) {
$filteredFieldDefs[$paramName] = $paramValue;
}
break;
if (array_key_exists($paramName, $actualCustomFieldDefs)) {
$filteredFieldDefs[$paramName] = $paramValue;
}
}
}
@@ -593,7 +584,7 @@ class FieldManager
* @param string $scope
* @param string $fieldName
* @param array $fieldDefs
* @return array
* @return object
*/
protected function normalizeDefs($scope, $fieldName, array $fieldDefs)
{
+4 -5
View File
@@ -354,7 +354,7 @@ class Language
$cacheFile = $this->getCacheFile($language);
if (!$this->useCache || !file_exists($cacheFile)) {
if (!$this->useCache || !file_exists($cacheFile) || $reload) {
$paths = $this->paths;
@@ -368,11 +368,12 @@ class Language
$data = $this->getUnifier()->unify('i18n', $paths, true);
if (is_array($data))
if (is_array($data)) {
$this->sanitizeData($data);
}
if ($language != $this->defaultLanguage) {
$data = Util::merge($this->getDefaultLanguageData(), $data);
$data = Util::merge($this->getDefaultLanguageData($reload), $data);
}
$this->data[$language] = $data;
@@ -399,11 +400,9 @@ class Language
if (is_array($subData)) {
$this->sanitizeData($subData);
} else {
$subData = htmlspecialchars($subData);
if (is_string($subData)) {
$subData = str_replace('<', '&lt;', $subData);
$subData = str_replace('>', '&gt;', $subData);
$subData = str_replace('"', '&quot;', $subData);
}
}
}
+76
View File
@@ -733,4 +733,80 @@ class Util
return mb_strtolower($firstChar) . $then;
}
/**
* Sanitize Html code
* @param string $text
* @param array $permittedHtmlTags - Allows only html tags without parameters like <p></p>, <br>, etc.
* @return string
*/
public static function sanitizeHtml($text, $permittedHtmlTags = ['p', 'br', 'b', 'strong', 'pre'])
{
if (is_array($text)) {
foreach ($text as $key => &$value) {
$value = self::sanitizeHtml($value, $permittedHtmlTags);
}
return $text;
}
$sanitized = htmlspecialchars($text, \ENT_QUOTES | \ENT_HTML5, 'UTF-8');
foreach ($permittedHtmlTags as $htmlTag) {
$sanitized = preg_replace('/&lt;(\/)?(' . $htmlTag . ')&gt;/i', '<$1$2>', $sanitized);
}
return $sanitized;
}
public static function urlAddParam($url, $paramName, $paramValue)
{
$urlQuery = parse_url($url, \PHP_URL_QUERY);
if (!$urlQuery) {
$params = [
$paramName => $paramValue
];
$url = trim($url);
$url = preg_replace('/\/\?$/', '', $url);
$url = preg_replace('/\/$/', '', $url);
return $url . '/?' . http_build_query($params);
}
parse_str($urlQuery, $params);
if (!isset($params[$paramName]) || $params[$paramName] != $paramValue) {
$params[$paramName] = $paramValue;
return str_replace($urlQuery, http_build_query($params), $url);
}
return $url;
}
public static function urlRemoveParam($url, $paramName, $suffix = '')
{
$urlQuery = parse_url($url, \PHP_URL_QUERY);
if ($urlQuery) {
parse_str($urlQuery, $params);
if (isset($params[$paramName])) {
unset($params[$paramName]);
$newUrl = str_replace($urlQuery, http_build_query($params), $url);
if (empty($params)) {
$newUrl = preg_replace('/\/\?$/', '', $newUrl);
$newUrl = preg_replace('/\/$/', '', $newUrl);
$newUrl .= $suffix;
}
return $newUrl;
}
}
return $url;
}
}
@@ -33,7 +33,17 @@ use Espo\ORM\Entity;
class Lead extends \Espo\Core\ORM\Repositories\RDB
{
public function afterSave(Entity $entity, array $options = array())
public function beforeSave(Entity $entity, array $options = [])
{
if (!$entity->get('convertedAt') && $entity->get('status') === 'Converted' && $entity->isAttributeChanged('status')) {
$convertedAt = date('Y-m-d H:i:s');
$entity->set('convertedAt', $convertedAt);
}
parent::beforeSave($entity, $options);
}
public function afterSave(Entity $entity, array $options = [])
{
parent::afterSave($entity, $options);
@@ -22,6 +22,7 @@
"createdAccount": "Account",
"createdContact": "Contact",
"createdOpportunity": "Opportunity",
"convertedAt": "Converted At",
"campaign": "Campaign",
"targetLists": "Target Lists",
"targetList": "Target List",
@@ -6,6 +6,11 @@
"recordViews":{
"detail":"crm:views/lead/record/detail"
},
"defaultSidePanelFieldList": [
":assignedUser",
"teams",
"convertedAt"
],
"sidePanels":{
"detail":[
{
@@ -132,6 +137,26 @@
}
]
}
},
"convertedAt": {
"visible": {
"conditionGroup": [
{
"type": "and",
"value": [
{
"type": "equals",
"attribute": "status",
"value": "Converted"
},
{
"type": "isNotEmpty",
"attribute": "convertedAt"
}
]
}
]
}
}
},
"panels": {
@@ -100,6 +100,12 @@
"description": {
"type": "text"
},
"convertedAt": {
"type": "datetime",
"layoutDetailDisabled": true,
"layoutMassUpdateDisabled": true,
"readOnly": true
},
"createdAt": {
"type": "datetime",
"readOnly": true
@@ -739,7 +739,7 @@ class Activities extends \Espo\Core\Services\Base
$orderBy = null;
$order = null;
if (!empty($selectParams['orderBy'])) {
$order = $selectParams['order'];
$order = $selectParams['order'] ?? null;
$orderBy = $selectParams['orderBy'];
}
+6 -2
View File
@@ -1082,7 +1082,7 @@ abstract class Base
if (!empty($item[1])) {
$orderInternal = $item[1];
}
$arr[] = $this->getOrderPart($entity, $orderByInternal, $orderInternal, false, $params);
$arr[] = $this->getOrderPart($entity, $orderByInternal, $orderInternal, $useColumnAlias, $params);
}
}
return implode(", ", $arr);
@@ -1090,7 +1090,11 @@ abstract class Base
if (strpos($orderBy, 'LIST:') === 0) {
list($l, $field, $list) = explode(':', $orderBy);
$fieldPath = $this->getFieldPathForOrderBy($entity, $field, $params);
if ($useColumnAlias) {
$fieldPath = '`'. $this->sanitizeSelectAlias($field) . '`';
} else {
$fieldPath = $this->getFieldPathForOrderBy($entity, $field, $params);
}
$listQuoted = [];
$list = array_reverse(explode(',', $list));
foreach ($list as $i => $listItem) {
@@ -4,6 +4,7 @@
"action": "Action",
"createdAt": "Date",
"user": "User",
"userType": "User Type",
"target": "Target",
"targetType": "Target Type",
"authToken": "Auth Token",
@@ -91,7 +91,6 @@
"massEmailOpenTracking": "Email Open Tracking",
"activitiesEntityList": "Activities Entity List",
"historyEntityList": "History Entity List",
"b2cMode": "B2C Mode",
"currencyFormat": "Currency Format",
"currencyDecimalPlaces": "Currency Decimal Places",
"aclStrictMode": "ACL Strict Mode",
@@ -3,5 +3,6 @@
"target",
"createdAt",
"ipAddress",
"user"
"user",
"userType"
]
@@ -15,15 +15,7 @@
[{"name": "exportDelimiter"}, {"name":"autoFollowEntityTypeList"}],
[
{
"name": "signature",
"params": {
"toolbar": [
["style", ["bold", "italic", "underline", "clear"]],
["color", ["color"]],
["height", ["height"]],
["misc",["codeview"]]
]
}
"name": "signature"
},
{
"name": "defaultReminders"
@@ -45,7 +45,8 @@
},
{
"label":"Folders",
"link":"#EmailFolder"
"link":"#EmailFolder",
"configCheck": "!emailFoldersDisabled"
},
{
"label":"Filters",
@@ -26,6 +26,13 @@
"user": {
"type": "link"
},
"userType": {
"type": "foreign",
"link": "user",
"field": "type",
"view": "views/fields/foreign-enum",
"notStorable": true
},
"ipAddress": {
"type": "varchar",
"maxLength": "39"
@@ -121,7 +121,7 @@
},
"signature": {
"type": "wysiwyg",
"view": "views/fields/wysiwyg"
"view": "views/preferences/fields/signature"
},
"defaultReminders": {
"type": "jsonArray",
@@ -21,7 +21,6 @@
{
"name": "rows",
"type": "int",
"default": 30,
"min": 1
},
{
+1 -1
View File
@@ -51,7 +51,7 @@ class Email extends \Espo\Core\SelectManagers\Base
$skipIndex = true;
break;
} else {
if (isset($item['attribute']) && $this->getSeed()->getAttributeParam($item['attribute'], 'type') === 'foreignId') {
if (isset($item['attribute'])) {
$skipIndex = true;
break;
}
@@ -41,5 +41,10 @@ class EmailFilter extends Record
if (!$this->getAcl()->check($entity, 'edit')) {
throw new Forbidden();
}
if ($entity->get('isGlobal')) {
$entity->set('parentId', null);
$entity->set('parentType', null);
}
}
}
+6 -3
View File
@@ -155,7 +155,7 @@ class InboundEmail extends \Espo\Services\Record
'isActive' => true,
'teamsMiddle.teamId' => $teamIdList
),
'distrinct' => true,
'distinct' => true,
'joins' => ['teams']
));
foreach ($userList as $user) {
@@ -922,7 +922,7 @@ class InboundEmail extends \Espo\Services\Record
public function getSmtpParamsFromAccount(\Espo\Entities\InboundEmail $emailAccount)
{
$smtpParams = array();
$smtpParams = [];
$smtpParams['server'] = $emailAccount->get('smtpHost');
if ($smtpParams['server']) {
$smtpParams['port'] = $emailAccount->get('smtpPort');
@@ -933,7 +933,10 @@ class InboundEmail extends \Espo\Services\Record
if ($emailAccount->get('fromName')) {
$smtpParams['fromName'] = $emailAccount->get('fromName');
}
if (array_key_exists('password', $smtpParams)) {
if ($emailAccount->get('emailAddress')) {
$smtpParams['fromAddress'] = $emailAccount->get('emailAddress');
}
if (array_key_exists('password', $smtpParams) && is_string($smtpParams['password'])) {
$smtpParams['password'] = $this->getCrypt()->decrypt($smtpParams['password']);
}
return $smtpParams;
+2 -1
View File
@@ -38,6 +38,7 @@ use \Espo\Core\Exceptions\Conflict;
use \Espo\Core\Exceptions\NotFound;
use \Espo\Core\Exceptions\NotFoundSilent;
use \Espo\Core\Exceptions\ForbiddenSilent;
use \Espo\Core\Exceptions\ConflictSilent;
use \Espo\Core\Utils\Util;
@@ -830,7 +831,7 @@ class Record extends \Espo\Core\Services\Base
'reason' => 'Duplicate',
'data' => $data
];
throw new Conflict(json_encode($reason));
throw new ConflictSilent(json_encode($reason));
}
}
}
@@ -154,6 +154,8 @@ Espo.define('crm:views/contact/fields/accounts', 'views/fields/link-multiple-wit
},
addLinkHtml: function (id, name) {
name = name || id;
if (this.mode == 'search') {
return Dep.prototype.addLinkHtml.call(this, id, name);
}
@@ -43,8 +43,7 @@ Espo.define('crm:views/lead/record/panels/converted-to', 'views/record/panels/si
if (this.getAcl().check('Opportunity') && !this.getMetadata().get('scopes.Opportunity.disabled')) {
this.fieldList.push('createdOpportunity');
}
}
},
});
});
@@ -98,6 +98,12 @@ Espo.define('crm:views/meeting/detail', 'views/detail', function (Dep) {
if (!contactIdList.length && !leadIdList.length && !userIdList.length) {
show = false;
} else if (
userIdList.length === 1 && userIdList[0] === this.getUser().id
&&
this.model.getLinkMultipleColumn('users', 'status', this.getUser().id) === 'Accepted'
) {
show = false;
}
}
@@ -2,8 +2,6 @@
<img src="{{url}}" style="max-width: 100%;">
</div>
{{#if size}}
<div class="margin">
{{translate 'Original'}}: <a href="{{originalUrl}}" target="_blank">{{name}}</a>
<div class="original-link-container margin{{#unless showOriginalLink}} hidden{{/unless}}">
<a href="{{originalUrl}}" target="_blank">{{translate 'Original'}}</a>
</div>
{{/if}}
+1 -1
View File
@@ -10,7 +10,7 @@
<ul class="dropdown-menu pull-left">
{{#each dropdownItemList}}
{{#if this}}
<li class="{{#if hidden}}hidden{{/if}}"><a href="javascript:" class="action" data-action="{{name}}">{{#if html}}{{{html}}}{{else}}{{translate label scope=../../../entityType}}{{/if}}</a></li>
<li class="{{#if hidden}}hidden{{/if}}"><a href="javascript:" class="action" data-action="{{name}}" {{#each data}} data-{{@key}}="{{./this}}"{{/each}}>{{#if html}}{{{html}}}{{else}}{{translate label scope=../../../entityType}}{{/if}}</a></li>
{{else}}
{{#unless @first}}
{{#unless @last}}
+1 -1
View File
@@ -1,6 +1,6 @@
<div class="navbar navbar-inverse" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-action="toggleCollapsable"">
<button type="button" class="navbar-toggle" data-action="toggleCollapsable">
<span class="fas fa-bars"></span>
</button>
<div class="navbar-logo-container"><a class="navbar-brand nav-link" href="#"><img src="{{logoSrc}}" class="logo"></span></a></div>
+3 -2
View File
@@ -116,7 +116,8 @@ define('language', ['ajax'], function (Ajax) {
},
load: function (callback, disableCache, loadDefault) {
this.once('sync', callback);
if (callback)
this.once('sync', callback);
if (!disableCache) {
if (this.loadFromCache(loadDefault)) {
@@ -129,7 +130,7 @@ define('language', ['ajax'], function (Ajax) {
},
fetch: function (disableCache, loadDefault) {
Ajax.getRequest(this.url, {default: loadDefault}).then(function (data) {
return Ajax.getRequest(this.url, {default: loadDefault}).then(function (data) {
this.data = data;
if (!disableCache) {
this.storeToCache(loadDefault);
+6 -3
View File
@@ -46,19 +46,22 @@ define('metadata', [], function () {
load: function (callback, disableCache, sync) {
var sync = (typeof sync == 'undefined') ? false: sync;
this.off('sync');
this.once('sync', callback);
if (callback)
this.once('sync', callback);
if (!disableCache) {
if (this.loadFromCache()) {
this.trigger('sync');
return;
}
}
this.fetch(sync);
return this.fetch(sync);
},
fetch: function (sync) {
var self = this;
this.ajax({
return this.ajax({
url: this.url,
type: 'GET',
dataType: 'JSON',
+36
View File
@@ -33,22 +33,58 @@ define('utils', [], function () {
handleAction: function (viewObject, e) {
var $target = $(e.currentTarget);
var action = $target.data('action');
var fired = false;
if (action) {
var data = $target.data();
var method = 'action' + Espo.Utils.upperCaseFirst(action);
if (typeof viewObject[method] == 'function') {
viewObject[method].call(viewObject, data, e);
e.preventDefault();
e.stopPropagation();
fired = true;
} else if (data.handler) {
e.preventDefault();
e.stopPropagation();
fired = true;
require(data.handler, function (Handler) {
var handler = new Handler(viewObject);
handler[method].call(handler, data, e);
});
}
if (fired) {
var $dropdown = $target.closest('.dropdown-menu');
if ($dropdown.length) {
var $dropdownToggle = $dropdown.parent().find('[data-toggle="dropdown"]');
if ($dropdownToggle.length) {
$dropdownToggle.dropdown('toggle');
}
}
}
}
},
checkActionAvailability: function (helper, item) {
var config = helper.config;
if (item.configCheck) {
var configCheck = item.configCheck;
var opposite = false;
if (configCheck.substr(0, 1) === '!') {
opposite = true;
configCheck = configCheck.substr(1);
}
var configCheckResult = config.getByPath(configCheck.split('.'));
if (opposite) {
configCheckResult = !configCheckResult;
}
if (!configCheckResult) return false;
}
return true;
},
checkActionAccess: function (acl, obj, item, isPrecise) {
var hasAccess = true;
if (item.acl) {
+3 -1
View File
@@ -314,13 +314,15 @@ define('view-helper', ['lib!client/lib/purify.min.js'], function () {
text = text.replace(item.regex, item.value);
});
options = options || {};
if (options.inline) {
text = marked.inlineLexer(text, []);
} else {
text = marked(text);
}
text = DOMPurify.sanitize(text);
text = DOMPurify.sanitize(text).toString();
text = text.replace(/<a href="mailto:(.*)"/gm, '<a href="javascript:" data-email-address="$1" data-action="mailTo"');
+4 -3
View File
@@ -424,8 +424,9 @@ Espo.define('views/admin/field-manager/edit', ['view', 'model'], function (Dep,
}.bind(this)),
new Promise(function (resolve) {
this.getLanguage().load(function () {
this.getLanguage().storeToCache();
resolve();
}, true);
}.bind(this), true);
}.bind(this))
]).then(function () {
this.trigger('after:save');
@@ -501,6 +502,7 @@ Espo.define('views/admin/field-manager/edit', ['view', 'model'], function (Dep,
}.bind(this)),
new Promise(function (resolve) {
this.getLanguage().load(function () {
this.getLanguage().storeToCache();
resolve();
}.bind(this), true);
}.bind(this))
@@ -513,8 +515,7 @@ Espo.define('views/admin/field-manager/edit', ['view', 'model'], function (Dep,
}.bind(this));
}, this);
}
},
});
});
@@ -45,6 +45,8 @@ Espo.define('views/email-template/record/detail', 'views/record/detail', functio
if (!bodyView) return;
if (this.model.get('isHtml')) {
var $anchor = $(window.getSelection().anchorNode);
if (!$anchor.closest('.note-editing-area').length) return;
bodyView.$summernote.summernote('insertText', tag);
} else {
var $body = bodyView.$element;
@@ -203,10 +203,6 @@ Espo.define('views/email/fields/email-address-varchar', ['views/fields/varchar',
},
addAddress: function (address, name, type, id) {
if (name) {
name = this.getHelper().escapeString(name);
}
if (this.justAddedAddress) {
this.deleteAddress(this.justAddedAddress);
}
+8 -3
View File
@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('views/email/list', 'views/list', function (Dep) {
define('views/email/list', 'views/list', function (Dep) {
return Dep.extend({
@@ -65,13 +65,18 @@ Espo.define('views/email/list', 'views/list', function (Dep) {
}
this.foldersDisabled = this.foldersDisabled ||
this.getMetadata().get(['scopes', this.folderScope, 'disabled']) ||
!this.getAcl().checkScope(this.folderScope);
this.getConfig().get('emailFoldersDisabled') ||
this.getMetadata().get(['scopes', this.folderScope, 'disabled']) ||
!this.getAcl().checkScope(this.folderScope);
var params = this.options.params || {};
this.selectedFolderId = params.folder || this.defaultFolderId;
if (this.foldersDisabled) {
this.selectedFolderId = null;
}
this.applyFolder();
},
@@ -106,7 +106,7 @@ Espo.define('views/fields/link-multiple-with-columns', 'views/fields/link-multip
},
getDetailLinkHtml: function (id, name) {
name = name || this.nameHash[id];
name = name || this.nameHash[id] || id;
var roleHtml = '';
@@ -123,6 +123,8 @@ Espo.define('views/fields/link-multiple-with-primary', 'views/fields/link-multip
},
addLinkHtml: function (id, name) {
name = name || id;
if (this.mode == 'search') {
return Dep.prototype.addLinkHtml.call(this, id, name);
}
@@ -130,7 +132,7 @@ Espo.define('views/fields/link-multiple-with-primary', 'views/fields/link-multip
var $container = this.$el.find('.link-container');
var $el = $('<div class="form-inline list-group-item link-with-role clearfix link-group-item-with-primary">').addClass('link-' + id).attr('data-id', id);
var nameHtml = '<div>' + this.getHelper().escapeString(name) + '&nbsp;' + '</div>';
var nameHtml = '<div>' + this.getHelper().escapeString(name) || id + '&nbsp;' + '</div>';
var removeHtml = '<a href="javascript:" class="pull-right" data-id="' + id + '" data-action="clearLink"><span class="fas fa-times"></a>';
$left = $('<div>');
@@ -70,7 +70,7 @@ Espo.define('views/fields/link-multiple-with-role', 'views/fields/link-multiple'
},
getDetailLinkHtml: function (id, name) {
name = name || this.nameHash[id];
name = name || this.nameHash[id] || id;
if (!name && id) {
name = this.translate(this.foreignScope, 'scopeNames');
}
@@ -158,6 +158,8 @@ Espo.define('views/fields/link-multiple-with-role', 'views/fields/link-multiple'
},
addLinkHtml: function (id, name) {
name = name || id;
if (this.mode == 'search') {
return Dep.prototype.addLinkHtml.call(this, id, name);
}
+2
View File
@@ -307,6 +307,8 @@ Espo.define('views/fields/link-multiple', 'views/fields/base', function (Dep) {
},
addLinkHtml: function (id, name) {
name = name || id;
var $container = this.$el.find('.link-container');
var $el = $('<div />').addClass('link-' + id).addClass('list-group-item').attr('data-id', id);
$el.html(this.getHelper().escapeString(name || id) + '&nbsp');
+25 -7
View File
@@ -26,13 +26,13 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('views/fields/link-one', 'views/fields/link', function (Dep) {
define('views/fields/link-one', 'views/fields/link', function (Dep) {
return Dep.extend({
readOnly: true,
searchTypeList: ['is', 'isOneOf'],
searchTypeList: ['is', 'isEmpty', 'isNotEmpty', 'isOneOf'],
fetchSearch: function () {
var type = this.$el.find('select.search-type').val();
@@ -46,12 +46,12 @@ Espo.define('views/fields/link-one', 'views/fields/link', function (Dep) {
data: {
type: type,
oneOfIdList: this.searchData.oneOfIdList,
oneOfNameHash: this.searchData.oneOfNameHash
}
oneOfNameHash: this.searchData.oneOfNameHash,
},
};
return data;
} else {
} else if (type == 'is' || !type) {
if (!value) {
return false;
}
@@ -61,8 +61,26 @@ Espo.define('views/fields/link-one', 'views/fields/link', function (Dep) {
value: value,
data: {
type: type,
nameValue: this.$el.find('[data-name="' + this.nameName + '"]').val()
}
nameValue: this.$el.find('[data-name="' + this.nameName + '"]').val(),
},
};
return data;
} else if (type === 'isEmpty') {
var data = {
type: 'isNotLinked',
data: {
type: type,
},
};
return data;
} else if (type === 'isNotEmpty') {
var data = {
type: 'isLinked',
data: {
type: type,
},
};
return data;
}
+1 -1
View File
@@ -186,7 +186,7 @@ Espo.define('views/fields/link-parent', 'views/fields/base', function (Dep) {
},
select: function (model) {
this.$elementName.val(model.get('name'));
this.$elementName.val(model.get('name') || model.id);
this.$elementId.val(model.get('id'));
this.trigger('change');
},
+2 -2
View File
@@ -167,11 +167,11 @@ Espo.define('views/fields/link', 'views/fields/base', function (Dep) {
},
select: function (model) {
this.$elementName.val(model.get('name'));
this.$elementName.val(model.get('name') || model.id);
this.$elementId.val(model.get('id'));
if (this.mode === 'search') {
this.searchData.idValue = model.get('id');
this.searchData.nameValue = model.get('name');
this.searchData.nameValue = model.get('name') || model.id;
}
this.trigger('change');
},
+1 -1
View File
@@ -32,7 +32,7 @@ define('views/fields/multi-enum', ['views/fields/array', 'lib!Selectize'], funct
type: 'multiEnum',
listTemplate: 'fields//array/list',
listTemplate: 'fields/array/list',
detailTemplate: 'fields/array/detail',
+81 -4
View File
@@ -63,7 +63,7 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
this.useIframe = this.params.useIframe || this.useIframe;
this.toolbar = this.params.toolbar || [
this.toolbar = this.params.toolbar || this.toolbar || [
['style', ['style']],
['style', ['bold', 'italic', 'underline', 'clear']],
['fontsize', ['fontsize']],
@@ -71,7 +71,7 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
['para', ['ul', 'ol', 'paragraph']],
['height', ['height']],
['table', ['table', 'espoLink', 'espoImage', 'hr']],
['misc',['codeview', 'fullscreen']]
['misc', ['codeview', 'fullscreen']]
];
this.buttons = {};
@@ -110,8 +110,8 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
} else {
this.lastHtmlValue = this.model.get(this.name);
var value = this.htmlToPlain(this.model.get(this.name));
this.model.set(this.name, value, {skipReRender: true});
this.disableWysiwygMode();
this.model.set(this.name, value);
}
}
}
@@ -368,6 +368,8 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
keyMap.pc['CTRL+K'] = 'espoLink.show';
keyMap.mac['CMD+K'] = 'espoLink.show';
var toolbar = this.toolbar;
var options = {
espoView: this,
lang: this.getConfig().get('language'),
@@ -408,7 +410,7 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
onCreateLink: function (link) {
return link;
},
toolbar: this.toolbar,
toolbar: toolbar,
buttons: this.buttons,
dialogsInBody: this.$el,
codeviewFilter: true,
@@ -710,6 +712,81 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
}
},
'fullscreen': function (context) {
var ui = $.summernote.ui;
var options = context.options;
var self = options.espoView;
var lang = options.langInfo;
this.$window = $(window);
this.$scrollbar = $('html, body');
this.initialize = function () {
this.$editor = context.layoutInfo.editor;
this.$toolbar = context.layoutInfo.toolbar;
this.$editable = context.layoutInfo.editable;
this.$codable = context.layoutInfo.codable;
this.$modal = self.$el.closest('.modal');
this.isInModal = this.$modal.length > 0;
};
this.resizeTo = function (size) {
this.$editable.css('height', size.h);
this.$codable.css('height', size.h);
if (this.$codable.data('cmeditor')) {
this.$codable.data('cmeditor').setsize(null, size.h);
}
};
this.onResize = function () {
this.resizeTo({
h: this.$window.height() - this.$toolbar.outerHeight(),
});
};
this.isFullscreen = function () {
return this.$editor.hasClass('fullscreen');
};
this.destroy = function () {
this.$window.off('resize.summernote' + self.cid);
if (this.isInModal) {
this.$modal.css('overflow-y', '');
} else {
this.$scrollbar.css('overflow', '');
}
}
this.toggle = function () {
this.$editor.toggleClass('fullscreen');
if (this.isFullscreen()) {
this.$editable.data('orgHeight', this.$editable.css('height'));
this.$editable.data('orgMaxHeight', this.$editable.css('maxHeight'));
this.$editable.css('maxHeight', '');
this.$window.on('resize.summernote' + self.cid, this.onResize.bind(this)).trigger('resize');
if (this.isInModal) {
this.$modal.css('overflow-y', 'hidden');
} else {
this.$scrollbar.css('overflow', 'hidden');
}
this._isFullscreen = true;
} else {
this.$window.off('resize.summernote' + self.cid);
this.resizeTo({ h: this.$editable.data('orgHeight') });
this.$editable.css('maxHeight', this.$editable.css('orgMaxHeight'));
if (this.isInModal) {
this.$modal.css('overflow-y', '');
} else {
this.$scrollbar.css('overflow', '');
}
this._isFullscreen = false;
}
context.invoke('toolbar.updateFullscreen', this.isFullscreen());
};
},
});
},
});
+6 -6
View File
@@ -87,15 +87,15 @@ define('views/main', 'view', function (Dep) {
if (this.menu) {
['buttons', 'actions', 'dropdown'].forEach(function (type) {
(this.menu[type] || []).forEach(function (item) {
item = Espo.Utils.clone(item);
menu[type] = menu[type] || [];
if (item.configCheck) {
if (!this.getConfig().getByPath(item.configCheck.split('.'))) return;
}
if (Espo.Utils.checkActionAccess(this.getAcl(), this.model || this.scope, item)) {
menu[type].push(item);
}
if (!Espo.Utils.checkActionAvailability(this.getHelper(), item)) return;
if (!Espo.Utils.checkActionAccess(this.getAcl(), this.model || this.scope, item)) return;
item.name = item.name || item.action;
item.action = item.action || this.name;
menu[type].push(item);
}, this);
}, this);
}
+8 -2
View File
@@ -53,7 +53,7 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
name: this.options.name,
url: this.getImageUrl(),
originalUrl: this.getOriginalImageUrl(),
size: this.size
showOriginalLink: this.size,
};
},
@@ -99,7 +99,9 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
$img.on('load', function () {
var self = this;
EXIF.getData($img.get(0), function () {
var imgEl = $img.get(0);
EXIF.getData(imgEl, function () {
var orientation = EXIF.getTag(this, 'Orientation');
switch (orientation) {
case 2:
@@ -128,6 +130,10 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
break;
}
});
if (imgEl.naturalWidth > imgEl.clientWidth) {
this.$el.find('.original-link-container').removeClass('hidden');
}
}.bind(this));
if (this.navigationEnabled) {
@@ -0,0 +1,42 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2019 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* 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 General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/preferences/fields/signature', 'views/fields/wysiwyg', function (Dep) {
return Dep.extend({
toolbar: [
["style", ["bold", "italic", "underline", "clear"]],
["color", ["color"]],
["height", ["height"]],
['table', ['espoLink']],
["misc",["codeview", "fullscreen"]]
],
});
});
+51 -1
View File
@@ -254,6 +254,56 @@ define('views/record/detail', ['views/record/base', 'view-record-helper'], funct
name: 'viewFollowers'
});
}
if (this.type === 'detail') {
this.additionalActionsDefs = {};
var additionalActionList = [];
(this.getMetadata().get(['clientDefs', this.scope, this.type + 'ActionList']) || []).forEach(function (item) {
if (typeof item === 'string') {
item = {
name: item,
};
}
var item = Espo.Utils.clone(item);
var name = item.name;
if (!item.label) item.html = this.translate(name, 'actions', this.scope);
this.addDropdownItem(item);
if (!Espo.Utils.checkActionAvailability(this.getHelper(), item)) return;
additionalActionList.push(item);
var viewObject = this;
if (item.initFunction && item.data.handler) {
this.wait(new Promise(function (resolve) {
require(item.data.handler, function (Handler) {
var handler = new Handler(viewObject);
handler[item.initFunction].call(handler);
resolve();
});
}));
}
if (!Espo.Utils.checkActionAccess(this.getAcl(), this.model, item, true)) {
item.hidden = true;
}
}, this);
if (additionalActionList.length) {
this.listenTo(this.model, 'sync', function () {
additionalActionList.forEach(function (item) {
if (Espo.Utils.checkActionAccess(this.getAcl(), this.model, item, true)) {
this.showActionItem(item.name);
} else {
this.hideActionItem(item.name);
}
}, this);
}, this);
}
}
},
disableActionItems: function () {
@@ -1518,7 +1568,7 @@ define('views/record/detail', ['views/record/base', 'view-record-helper'], funct
}
this.getRouter().navigate(url, {trigger: true});
}
},
});
});
+8 -28
View File
@@ -908,20 +908,10 @@ define('views/record/list', 'view', function (Dep) {
(this.getMetadata().get(['clientDefs', this.scope, 'massActionList']) || []).forEach(function (item) {
var defs = this.getMetadata().get(['clientDefs', this.scope, 'massActionDefs', item]) || {};
var acl = defs.acl;
var aclScope = defs.aclScope;
if (acl || aclScope) {
if (!this.getAcl().check(aclScope || this.scope, acl)) {
return;
}
}
var configCheck = defs.configCheck;
if (configCheck) {
var arr = configCheck.split('.');
if (!this.getConfig().getByPath(arr)) {
return;
}
}
if (!Espo.Utils.checkActionAvailability(this.getHelper(), defs)) return;
if (!Espo.Utils.checkActionAccess(this.getAcl(), null, defs)) return;
this.massActionList.push(item);
}, this);
@@ -937,20 +927,10 @@ define('views/record/list', 'view', function (Dep) {
if (this.collection.url !== this.entityType) return;
if (~this.massActionList.indexOf(item)) {
var defs = this.getMetadata().get(['clientDefs', this.scope, 'massActionDefs', item]) || {};
var acl = defs.acl;
var aclScope = defs.aclScope;
if (acl || aclScope) {
if (!this.getAcl().check(aclScope || this.scope, acl)) {
return;
}
}
var configCheck = defs.configCheck;
if (configCheck) {
var arr = configCheck.split('.');
if (!this.getConfig().getByPath(arr)) {
return;
}
}
if (!Espo.Utils.checkActionAvailability(this.getHelper(), defs)) return;
if (!Espo.Utils.checkActionAccess(this.getAcl(), null, defs)) return;
this.checkAllResultMassActionList.push(item);
}
}, this);
+3 -5
View File
@@ -82,11 +82,9 @@ define('views/record/panels-container', 'view', function (Dep) {
applyAccessToActions: function (actionList) {
if (!actionList) return;
actionList.forEach(function (item) {
if (item.configCheck) {
if (!this.getConfig().getByPath(item.configCheck.split('.'))) {
item.hidden = true;
return;
}
if (!Espo.Utils.checkActionAvailability(this.getHelper(), item)) {
item.hidden = true;
return;
}
if (Espo.Utils.checkActionAccess(this.getAcl(), this.model, item, true)) {
if (item.isHiddenByAcl) {
+1 -1
View File
@@ -233,7 +233,7 @@
ul.tabs {
> li > a > span.full-label {
display: inline;
display: inline-block;
}
}
+4
View File
@@ -1179,6 +1179,10 @@ select[multiple].input-sm {
height: 90px !important;
}
optgroup {
font-weight: 600;
}
.input-group-btn > select.form-control {
position: relative;
display: inline-block;
+1 -1
View File
@@ -35,4 +35,4 @@ $smarty->assign('cronHelp', $cronMessage['command']);
$installer->setSuccess();
// clean session
session_unset();
session_unset();
-4
View File
@@ -98,8 +98,4 @@ service apache2 restart',
}
}',
],
'blog' => 'http://blog.espocrm.com',
'twitter' => 'https://twitter.com/espocrm',
'forum' => 'http://forum.espocrm.com',
];
+7 -4
View File
@@ -1,5 +1,6 @@
{
"labels": {
"headerTitle": "EspoCRM Installation",
"Main page title": "Welcome to EspoCRM",
"Main page header": "",
"Start page title": "License Agreement",
@@ -48,7 +49,9 @@
"Success": "Success",
"Fail": "Fail",
"is recommended": "is recommended",
"extension is missing": "extension is missing"
"extension is missing": "extension is missing",
"Crontab setup instructions": "Without running Scheduled jobs inbound emails, notifications and reminders will not be working. Here you can read {SETUP_INSTRUCTIONS}.",
"Setup instructions": "setup instructions"
},
"fields": {
"Choose your language": "Choose your language",
@@ -82,7 +85,7 @@
"smtpPassword": "Password"
},
"messages": {
"Bad init Permission": "Permission denied for \"{*}\" directory. Please set 775 for \"{*}\" or just execute this command in the terminal <pre><b>{C}</b></pre>\n\tOperation not permitted? Try this one: {CSU}",
"Bad init Permission": "Permission denied for \"{*}\" directory. Please set 775 for \"{*}\" or just execute this command in the terminal <pre><b>{C}</b></pre> Operation is not permitted? Try this one: {CSU}",
"Some errors occurred!": "Some errors occurred!",
"phpVersion": "Your PHP version is not supported by EspoCRM, please update to PHP {minVersion} at least",
"requiredMysqlVersion": "Your MySQL version is not supported by EspoCRM, please update to MySQL {minVersion} at least",
@@ -102,8 +105,8 @@
"Ajax failed": "An unexpected error occurred",
"Cannot create user": "Cannot create a user",
"Permission denied": "Permission denied",
"permissionInstruction": "<br>Run this in Terminal<pre><b>\"{C}\"</b></pre>",
"operationNotPermitted" : "Operation not permitted? Try this: <br>{CSU}",
"permissionInstruction": "<br>Run this command in Terminal:<pre><b>\"{C}\"</b></pre>",
"operationNotPermitted" : "Operation is not permitted? Try this one: <br><br>{CSU}",
"Permission denied to": "Permission denied",
"Can not save settings": "Can not save settings",
"Cannot save preferences": "Cannot save preferences",
+17 -29
View File
@@ -2,48 +2,36 @@
<form id="nav">
<div class="row">
<div class=" col-md-13">
<div class="panel-body" align="center">
<div class="message">
{$langs['labels']['Congratulation! Welcome to EspoCRM']}
</div>
<br>
<div class="panel-body">
<div class="likes">
<p>
{$langs['labels']['share']}
{$langs['labels']['Congratulation! Welcome to EspoCRM']}
</p>
<br>
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<div class="g-plusone" data-size="standard" data-count="true" data-href='http://www.espocrm.com'></div>
</div>
<div class="more-information">
{assign var="blogLink" value="<a target=\"_blank\" href=\"{$config['blog']}\">{$langs['labels']['blog']}</a>"}
{assign var="twitterLink" value="<a target=\"_blank\" href=\"{$config['twitter']}\">{$langs['labels']['twitter']}</a>"}
{assign var="forumLink" value="<a target=\"_blank\" href=\"{$config['forum']}\">{$langs['labels']['forum']}</a>"}
{if $cronHelp}
<div class="cron-help">
{$cronTitle}
<pre>
{$cronHelp}
</pre>
{assign var="message" value="{$langs['labels']['More Information']|replace:'{BLOG}':$blogLink}"}
{assign var="message" value="{$message|replace:'{TWITTER}':$twitterLink}"}
{assign var="message" value="{$message|replace:'{FORUM}':$forumLink}"}
<p>
{assign var="link" value="<a target=\"_blank\" href=\"https://www.espocrm.com/documentation/administration/server-configuration/#user-content-setup-a-crontab\">{$langs['labels']['Setup instructions']}</a>"}
{assign var="message" value="{$langs['labels']['Crontab setup instructions']|replace:'{SETUP_INSTRUCTIONS}':$link}"}
{$message}
</p>
{$message}
</div>
{/if}
</div>
</div>
</div>
</form>
</div>
{if $cronHelp}
<div class="cron-help">
&nbsp;{$cronTitle}
<pre>
{$cronHelp}
</pre>
</div>
{/if}
<footer class="modal-footer">
<button class="btn btn-primary" type="button" id="start">{$langs['labels']['Go to EspoCRM']}</button>
</footer>
@@ -56,4 +44,4 @@
var installScript = new InstallScript({action: 'finish', langs: langs});
})
{/literal}
</script>
</script>
+2 -1
View File
@@ -1,12 +1,13 @@
<!doctype html>
<html>
<head>
<title>EspoCRM Installation</title>
<title>{$langs['labels']['headerTitle']}</title>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script type="text/javascript" src="../client/lib/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="../client/lib/purify.min.js"></script>
<script type="text/javascript" src="js/install.js"></script>
<link href="../client/css/espo/hazyblue.css" rel="stylesheet">
+1 -2
View File
@@ -26,7 +26,7 @@
</div>
</div>
<div class="cell cell-website pull-right" align="right">
<a target="_blank" href="https://www.espocrm.com/documentation/administration/installation/" style="font-weight:bold;">{$langs['labels']['Installation Guide']}</a>
<a target="_blank" href="https://www.espocrm.com/documentation/administration/installation/" style="font-weight:600;">{$langs['labels']['Installation Guide']}</a>
</div>
</div>
@@ -44,4 +44,3 @@
})
{/literal}
</script>
+1 -1
View File
@@ -84,7 +84,7 @@
</table>
<div class="cell cell-website pull-right" align="right">
<a target="_blank" href="https://www.espocrm.com/documentation/administration/server-configuration/" style="font-weight:bold;">{$langs['labels']['Configuration Instructions']}</a>
<a target="_blank" href="https://www.espocrm.com/documentation/administration/server-configuration/" style="font-weight:600;">{$langs['labels']['Configuration Instructions']}</a>
</div>
</div>
</form>
+9 -4
View File
@@ -72,13 +72,19 @@ select[name="user-lang"] {
}
.cron-help {
margin: 20px;
margin-top: 40px;
color: #ad4846;
}
.cron-help pre {
margin-top: 15px;
padding-top: 15px;
padding-bottom: 0;
text-align: left;
}
.cron-help p {
color: #333;
}
.table {
@@ -107,7 +113,7 @@ select[name="user-lang"] {
span.remark {
color: #a94442;
font-weight: bold;
font-weight: 600;
}
span.ok {
color: #87c956;
@@ -115,8 +121,7 @@ span.ok {
.more-information {
line-height: 1.5;
font-size: 16px;
margin-top: 70px;
margin-top: 40px;
text-align: left;
}
+4 -3
View File
@@ -54,6 +54,7 @@ $userLang = (!empty($_SESSION['install']['user-lang']))? $_SESSION['install']['u
require_once 'core/Language.php';
$language = new Language();
$langs = $language->get($userLang);
$sanitizedLangs = \Espo\Core\Utils\Util::sanitizeHtml($langs);
//END: get user selected language
$config = include('core/config.php');
@@ -63,13 +64,13 @@ $systemHelper = new SystemHelper();
$systemConfig = include('application/Espo/Core/defaults/systemConfig.php');
if (isset($systemConfig['requiredPhpVersion']) && version_compare(PHP_VERSION, $systemConfig['requiredPhpVersion'], '<')) {
die(str_replace('{minVersion}', $systemConfig['requiredPhpVersion'], $langs['messages']['phpVersion']) . '.');
die(str_replace('{minVersion}', $systemConfig['requiredPhpVersion'], $sanitizedLangs['messages']['phpVersion']) . '.');
}
if (!$systemHelper->initWritable()) {
$dir = $systemHelper->getWritableDir();
$message = $langs['messages']['Bad init Permission'];
$message = $sanitizedLangs['messages']['Bad init Permission'];
$message = str_replace('{*}', $dir, $message);
$message = str_replace('{C}', $systemHelper->getPermissionCommands(array($dir, ''), '775'), $message);
$message = str_replace('{CSU}', $systemHelper->getPermissionCommands(array($dir, ''), '775', true), $message);
@@ -102,7 +103,7 @@ $smarty->caching = false;
$smarty->setTemplateDir('install/core/tpl');
$smarty->assign("version", $installer->getVersion());
$smarty->assign("langs", $langs);
$smarty->assign("langs", $sanitizedLangs);
$smarty->assign("langsJs", json_encode($langs));
// include actions and set tpl name
+30 -8
View File
@@ -79,6 +79,8 @@ var InstallScript = function(opt) {
];
this.checkIndex = 0;
this.checkError = false;
this.initSanitizeHtml();
}
InstallScript.prototype.main = function() {
@@ -542,15 +544,35 @@ InstallScript.prototype.getLang = function(key, type) {
InstallScript.prototype.showMsg = function(opt) {
this.hideMsg();
var msg = opt.msg || '';
var message = opt.msg || '';
var error = opt.error || false;
$('#msg-box').html(msg);
$('#msg-box').removeClass('hide');
$('#msg-box').removeClass('alert-success');
$('#msg-box').removeClass('alert-danger');
if (error) $('#msg-box').addClass('alert-danger');
else $('#msg-box').addClass('alert-success');
if (message) {
message = this.sanitizeHtml(message);
$('#msg-box').html(message);
$('#msg-box').removeClass('hide');
$('#msg-box').removeClass('alert-success');
$('#msg-box').removeClass('alert-danger');
}
if (error) {
$('#msg-box').addClass('alert-danger');
} else {
$('#msg-box').addClass('alert-success');
}
}
InstallScript.prototype.initSanitizeHtml = function() {
DOMPurify.addHook('afterSanitizeAttributes', function(node) {
if ('target' in node) {
node.setAttribute('target','_blank');
}
});
}
InstallScript.prototype.sanitizeHtml = function(html) {
return DOMPurify.sanitize(html);
}
InstallScript.prototype.hideMsg = function() {
@@ -638,7 +660,7 @@ InstallScript.prototype.checkAction = function(dataMain) {
// break next checking
var ajaxData = {
'success': false,
'errorMsg': ['Ajax failed']
'errorMsg': [self.getLang('Ajax failed', 'messages')]
}
self.callbackChecking(ajaxData);
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "espocrm",
"version": "5.6.10",
"version": "5.6.14",
"description": "",
"main": "index.php",
"repository": {
Executable → Regular
View File
Executable → Regular
View File
+2 -2
View File
@@ -114,7 +114,7 @@ abstract class BaseTestCase extends \PHPUnit\Framework\TestCase
return $this->espoTester->sendRequest($method, $action, $data);
}
protected function setUp()
protected function setUp() : void
{
$this->beforeSetUp();
@@ -134,7 +134,7 @@ abstract class BaseTestCase extends \PHPUnit\Framework\TestCase
$this->afterStartApplication();
}
protected function tearDown()
protected function tearDown() : void
{
$this->espoTester->terminate();
$this->espoTester = NULL;
+1
View File
@@ -191,6 +191,7 @@ class Tester
}
//remove and copy Espo files
Utils::checkCreateDatabase($configData['database']);
Utils::dropTables($configData['database']);
$fileManager->removeInDir($this->installPath);
$tt = $fileManager->copy($latestEspo, $this->installPath, true);
+14 -1
View File
@@ -124,6 +124,19 @@ class Utils
} /*END: SET UNDEFINED VARIABLES*/
}
public static function checkCreateDatabase(array $options)
{
if (!isset($options['dbname'])) {
throw new \Espo\Core\Exceptions\Error('Option "dbname" is not found.');
}
$dbname = $options['dbname'];
unset($options['dbname']);
$pdo = static::createPdoConnection($options);
$pdo->query("CREATE DATABASE IF NOT EXISTS `". $dbname ."`");
}
public static function dropTables(array $options)
{
$pdo = static::createPdoConnection($options);
@@ -145,4 +158,4 @@ class Utils
return $dbh;
}
}
}
@@ -73,22 +73,20 @@ class GeneralTest extends \tests\integration\Core\BaseTestCase
return $upgradeId;
}
/**
* @expectedException \Espo\Core\Exceptions\Error
*/
public function testUninstall()
{
$this->expectException('\\Espo\\Core\\Exceptions\\Error');
$upgradeId = $this->testInstall();
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
$upgradeManager->uninstall(array('id' => $upgradeId));
}
/**
* @expectedException \Espo\Core\Exceptions\Error
*/
public function testDelete()
{
$this->expectException('\\Espo\\Core\\Exceptions\\Error');
$upgradeId = $this->testInstall();
$upgradeManager = new \Espo\Core\UpgradeManager($this->getContainer());
+4 -6
View File
@@ -45,11 +45,10 @@ class AclTest extends \tests\integration\Core\BaseTestCase
$metadata->save();
}
/**
* @expectedException \Espo\Core\Exceptions\Forbidden
*/
public function testUserAccess()
{
$this->expectException('\\Espo\\Core\\Exceptions\\Forbidden');
$this->createUser('tester', array(
'assignmentPermission' => 'team',
'userPermission' => 'team',
@@ -86,11 +85,10 @@ class AclTest extends \tests\integration\Core\BaseTestCase
$result = $controllerManager->process('Account', 'create', $params, $data, $request);
}
/**
* @expectedException \Espo\Core\Exceptions\Forbidden
*/
public function testPortalUserAccess()
{
$this->expectException('\\Espo\\Core\\Exceptions\\Forbidden');
$newUser = $this->createUser(array(
'userName' => 'tester',
'lastName' => 'tester',
+2 -2
View File
@@ -39,7 +39,7 @@ class CronManagerTest extends \PHPUnit\Framework\TestCase
protected $filesPath= 'tests/unit/testData/EntryPoints';
protected function setUp()
protected function setUp() : void
{
$this->objects['container'] = $this->getMockBuilder('\\Espo\\Core\\Container')->disableOriginalConstructor()->getMock();
@@ -67,7 +67,7 @@ class CronManagerTest extends \PHPUnit\Framework\TestCase
$this->reflection = new ReflectionHelper($this->object);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -40,7 +40,7 @@ class EntryPointManagerTest extends \PHPUnit\Framework\TestCase
protected $filesPath= 'tests/unit/testData/EntryPoints';
protected function setUp()
protected function setUp() : void
{
$this->objects['container'] = $this->getMockBuilder('\\Espo\\Core\\Container')->disableOriginalConstructor()->getMock();
@@ -58,7 +58,7 @@ class EntryPointManagerTest extends \PHPUnit\Framework\TestCase
));
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -33,12 +33,12 @@ use \Espo\ORM\Entity;
class EvaluatorTest extends \PHPUnit\Framework\TestCase
{
protected function setUp()
protected function setUp() : void
{
$this->evaluator = new \Espo\Core\Formula\Evaluator();
}
protected function tearDown()
protected function tearDown() : void
{
$this->evaluator = null;
}
@@ -102,4 +102,4 @@ class EvaluatorTest extends \PHPUnit\Framework\TestCase
$actual = $this->evaluator->process($expression);
$this->assertEquals(2.5, $actual);
}
}
}
+3 -3
View File
@@ -34,7 +34,7 @@ use \Espo\ORM\Entity;
class FormulaTest extends \PHPUnit\Framework\TestCase
{
protected function setUp()
protected function setUp() : void
{
$container = $this->container = $this->getMockBuilder('\\Espo\\Core\\Container')->disableOriginalConstructor()->getMock();
@@ -77,7 +77,7 @@ class FormulaTest extends \PHPUnit\Framework\TestCase
]));
}
protected function tearDown()
protected function tearDown() : void
{
$this->container = null;
$this->functionFactory = null;
@@ -2862,4 +2862,4 @@ class FormulaTest extends \PHPUnit\Framework\TestCase
$this->assertEquals(5, $variables->counter);
$this->assertEquals('hello', $variables->test);
}
}
}
+3 -3
View File
@@ -33,12 +33,12 @@ use \Espo\ORM\Entity;
class ParserTest extends \PHPUnit\Framework\TestCase
{
protected function setUp()
protected function setUp() : void
{
$this->parser = new \Espo\Core\Formula\Parser();
}
protected function tearDown()
protected function tearDown() : void
{
$this->parser = null;
}
@@ -784,4 +784,4 @@ class ParserTest extends \PHPUnit\Framework\TestCase
];
$this->assertEquals($expected, $actual);
}
}
}
+3 -3
View File
@@ -39,7 +39,7 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
protected $filesPath = 'tests/unit/testData/Hooks';
protected function setUp()
protected function setUp() : void
{
$this->objects['container'] = $this->getMockBuilder('\\Espo\\Core\\Container')->disableOriginalConstructor()->getMock();
@@ -62,7 +62,7 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
$this->reflection = new ReflectionHelper($this->object);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
$this->reflection = NULL;
@@ -437,4 +437,4 @@ class HookManagerTest extends \PHPUnit\Framework\TestCase
'\\Espo\\Hooks\\Note\\Notifications',
);
}
}
}
@@ -41,7 +41,7 @@ class HtmlizerTest extends \PHPUnit\Framework\TestCase
protected $number;
protected function setUp()
protected function setUp() : void
{
date_default_timezone_set('UTC');
@@ -59,7 +59,9 @@ class HtmlizerTest extends \PHPUnit\Framework\TestCase
->expects($this->any())
->method('getPhpContents')
->will($this->returnCallback(function($fileName) use ($obj) {
$data = eval('?>' . $obj->contents . '<?php');
$obj->contents = str_replace('<?php ', '', $obj->contents);
$obj->contents = str_replace('?>', '', $obj->contents);
$data = eval($obj->contents . ';');
return $data;
}));
@@ -75,7 +77,7 @@ class HtmlizerTest extends \PHPUnit\Framework\TestCase
$this->htmlizer = new \Espo\Core\Htmlizer\Htmlizer($this->fileManager, $this->dateTime, $this->number);
}
protected function tearDown()
protected function tearDown() : void
{
unset($this->htmlizer);
unset($this->fileManager);
@@ -168,4 +170,3 @@ class HtmlizerTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('test', $html);
}
}
@@ -35,7 +35,7 @@ class FiltersMatcherTest extends \PHPUnit\Framework\TestCase
{
protected $object;
protected function setUp()
protected function setUp() : void
{
$this->object = new \Espo\Core\Mail\FiltersMatcher();
@@ -80,7 +80,7 @@ class FiltersMatcherTest extends \PHPUnit\Framework\TestCase
);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
+20 -10
View File
@@ -34,7 +34,7 @@ use \Espo\Entities\Email;
class ImporterTest extends \PHPUnit\Framework\TestCase
{
function setUp()
function setUp() : void
{
$GLOBALS['log'] = $this->getMockBuilder('\\Espo\\Core\\Utils\\Log')->disableOriginalConstructor()->getMock();
@@ -126,13 +126,18 @@ class ImporterTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('test 3', $email->get('name'));
$teamIdList = $email->getLinkMultipleIdList('teams');
$this->assertContains('teamTestId', $teamIdList);
$this->assertTrue(in_array('teamTestId', $teamIdList));
$userIdList = $email->getLinkMultipleIdList('users');
$this->assertContains('userTestId', $userIdList);
$this->assertTrue(in_array('userTestId', $userIdList));
$this->assertContains('<br>Admin Test', $email->get('body'));
$this->assertContains('Admin Test', $email->get('bodyPlain'));
if (method_exists($this, 'assertStringContainsString')) { /* PHPUnit 7+ */
$this->assertStringContainsString('<br>Admin Test', $email->get('body'));
$this->assertStringContainsString('Admin Test', $email->get('bodyPlain'));
} else { /* PHPUnit 6 */
$this->assertContains('<br>Admin Test', $email->get('body'));
$this->assertContains('Admin Test', $email->get('bodyPlain'));
}
$this->assertEquals('<e558c4dfc2a0f0d60f5ebff474c97ffc/1466410740/1950@espo>', $email->get('messageId'));
}
@@ -182,14 +187,19 @@ class ImporterTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('test 3', $email->get('name'));
$teamIdList = $email->getLinkMultipleIdList('teams');
$this->assertContains('teamTestId', $teamIdList);
$this->assertTrue(in_array('teamTestId', $teamIdList));
$userIdList = $email->getLinkMultipleIdList('users');
$this->assertContains('userTestId', $userIdList);
$this->assertTrue(in_array('userTestId', $userIdList));
$this->assertContains('<br>Admin Test', $email->get('body'));
$this->assertContains('Admin Test', $email->get('bodyPlain'));
if (method_exists($this, 'assertStringContainsString')) { /* PHPUnit 7+ */
$this->assertStringContainsString('<br>Admin Test', $email->get('body'));
$this->assertStringContainsString('Admin Test', $email->get('bodyPlain'));
} else { /* PHPUnit 6 */
$this->assertContains('<br>Admin Test', $email->get('body'));
$this->assertContains('Admin Test', $email->get('bodyPlain'));
}
$this->assertEquals('<e558c4dfc2a0f0d60f5ebff474c97ffc/1466410740/1950@espo>', $email->get('messageId'));
}
}
}
@@ -33,7 +33,7 @@ use \tests\unit\testData\Entities\Test2;
class BaseTest extends \PHPUnit\Framework\TestCase
{
protected function setUp()
protected function setUp() : void
{
$entity = $this->entity = new Test2();
@@ -74,7 +74,7 @@ class BaseTest extends \PHPUnit\Framework\TestCase
$this->user->id = 'test_id';
}
protected function tearDown()
protected function tearDown() : void
{
unset($this->entity);
unset($this->acl);
@@ -54,7 +54,7 @@ class ActionManagerTest extends \PHPUnit\Framework\TestCase
),
);
protected function setUp()
protected function setUp() : void
{
$this->objects['container'] = $this->getMockBuilder('\Espo\Core\Container')->disableOriginalConstructor()->getMock();
@@ -63,7 +63,7 @@ class ActionManagerTest extends \PHPUnit\Framework\TestCase
$this->reflection = new ReflectionHelper($this->object);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -56,7 +56,7 @@ class BaseTest extends \PHPUnit\Framework\TestCase
protected $currentVersion = '11.5.2';
protected function setUp()
protected function setUp() : void
{
$this->objects['container'] = $this->getMockBuilder('\Espo\Core\Container')->disableOriginalConstructor()->getMock();
$this->objects['actionManager'] = $this->getMockBuilder('\Espo\Core\Upgrades\ActionManager')->disableOriginalConstructor()->getMock();
@@ -98,7 +98,7 @@ class BaseTest extends \PHPUnit\Framework\TestCase
/* END */
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
+2 -2
View File
@@ -43,7 +43,7 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
protected $systemConfigPath = 'tests/unit/testData/Utils/Config/systemConfig.php';
protected function setUp()
protected function setUp() : void
{
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
@@ -60,7 +60,7 @@ class ConfigTest extends \PHPUnit\Framework\TestCase
$this->reflection->setProperty('systemConfigPath', $this->systemConfigPath);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -40,7 +40,7 @@ class HelperTest extends \PHPUnit\Framework\TestCase
protected $reflection;
protected function setUp()
protected function setUp() : void
{
$this->objects['config'] = $this->getMockBuilder('\\Espo\\Core\\Utils\\Config')->disableOriginalConstructor()->getMock();
@@ -58,7 +58,7 @@ class HelperTest extends \PHPUnit\Framework\TestCase
]));
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -39,7 +39,7 @@ class FieldManagerTest extends \PHPUnit\Framework\TestCase
protected $reflection;
protected function setUp()
protected function setUp() : void
{
$this->objects['container'] = $this->getMockBuilder('\\Espo\\Core\\Container')->disableOriginalConstructor()->getMock();
@@ -65,7 +65,7 @@ class FieldManagerTest extends \PHPUnit\Framework\TestCase
$this->reflection->setProperty('metadataHelper', $this->objects['metadataHelper']);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -403,4 +403,4 @@ class FieldManagerTest extends \PHPUnit\Framework\TestCase
);
$this->assertEquals($result, $this->reflection->invokeMethod('normalizeDefs', array('CustomEntity', $input1, $input2)));
}
}
}
@@ -41,7 +41,7 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
protected $reflection;
protected function setUp()
protected function setUp() : void
{
$this->objects['fileManager'] = new \Espo\Core\Utils\File\Manager();
$this->objects['config'] = $this->getMockBuilder('\Espo\Core\Utils\Config')->disableOriginalConstructor()->getMock();
@@ -52,7 +52,7 @@ class ClassParserTest extends \PHPUnit\Framework\TestCase
$this->reflection = new ReflectionHelper($this->object);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -42,7 +42,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
protected $reflection;
protected function setUp()
protected function setUp() : void
{
$this->objects['config'] = $this->getMockBuilder('\Espo\Core\Utils\Config')->disableOriginalConstructor()->getMock();
@@ -51,7 +51,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
$this->reflection = new ReflectionHelper($this->object);
}
protected function tearDown()
protected function tearDown() : void
{
$this->object = NULL;
}
@@ -506,4 +506,4 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
}
}
}
}

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