Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7af2d1d3ac | |||
| 63670e3245 | |||
| 389931bf22 | |||
| 76a67d15a3 | |||
| 8e65f2d375 | |||
| 56737f5d67 | |||
| 20f8fae2f0 | |||
| 17b5d77d33 | |||
| cbe32c88b6 | |||
| dee291f3f6 | |||
| 0b20c8e13f | |||
| c0af0173e9 | |||
| 79f4c4b5d2 | |||
| 31c8be2ee1 | |||
| 061b237032 | |||
| d3466e201d | |||
| c69c7d2194 | |||
| 05e1624e47 | |||
| 03e32412ca | |||
| 451a2376a8 | |||
| 167c774446 | |||
| 054262a002 | |||
| ecbc3c537f | |||
| d51bbfdfab | |||
| ae343cddbe |
@@ -99,7 +99,7 @@ class FieldManager
|
||||
$fieldManagerTool->create($scope, $name, get_object_vars($data));
|
||||
|
||||
try {
|
||||
$this->dataManager->rebuild($scope);
|
||||
$this->dataManager->rebuild([$scope]);
|
||||
}
|
||||
catch (Error $e) {
|
||||
$fieldManagerTool->delete($scope, $data->name);
|
||||
@@ -131,7 +131,7 @@ class FieldManager
|
||||
$fieldManagerTool->update($scope, $name, get_object_vars($data));
|
||||
|
||||
if ($fieldManagerTool->isChanged()) {
|
||||
$this->dataManager->rebuild($scope);
|
||||
$this->dataManager->rebuild([$scope]);
|
||||
} else {
|
||||
$this->dataManager->clearCache();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,11 @@ namespace Espo\Controllers;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
use Espo\Core\{
|
||||
Authentication\LDAP\Utils as LDAPUtils,
|
||||
Authentication\LDAP\Client as LDAPClient,
|
||||
};
|
||||
|
||||
class Settings extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
protected function getConfigData()
|
||||
@@ -86,11 +91,14 @@ class Settings extends \Espo\Core\Controllers\Base
|
||||
|
||||
$data = get_object_vars($data);
|
||||
|
||||
$ldapUtils = new \Espo\Core\Utils\Authentication\LDAP\Utils();
|
||||
$ldapUtils = new LDAPUtils();
|
||||
|
||||
$options = $ldapUtils->normalizeOptions($data);
|
||||
|
||||
$ldapClient = new \Espo\Core\Utils\Authentication\LDAP\Client($options);
|
||||
$ldapClient->bind(); //an exception if no connection
|
||||
$ldapClient = new LDAPClient($options);
|
||||
|
||||
//an exception if no connection
|
||||
$ldapClient->bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ class Application
|
||||
{
|
||||
if (!$className || !class_exists($className)) {
|
||||
$this->getLog()->error("Application runner '{$className}' does not exist.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,6 +162,7 @@ class Application
|
||||
protected function initAutoloads()
|
||||
{
|
||||
$autoload = $this->getInjectableFactory()->create(Autoload::class);
|
||||
|
||||
$autoload->register();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,10 +37,6 @@ class Utils
|
||||
|
||||
protected $options = null;
|
||||
|
||||
/**
|
||||
* Association between LDAP and Espo fields
|
||||
* @var array
|
||||
*/
|
||||
protected $fieldMap = [
|
||||
'host' => 'ldapHost',
|
||||
'port' => 'ldapPort',
|
||||
@@ -73,11 +69,6 @@ class Utils
|
||||
'portalUserRolesIds' => 'ldapPortalUserRolesIds',
|
||||
];
|
||||
|
||||
/**
|
||||
* Permitted Espo Options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permittedEspoOptions = [
|
||||
'createEspoUser',
|
||||
'userNameAttribute',
|
||||
@@ -96,9 +87,7 @@ class Utils
|
||||
];
|
||||
|
||||
/**
|
||||
* accountCanonicalForm Map between Espo and Laminas value
|
||||
*
|
||||
* @var array
|
||||
* accountCanonicalForm Map between Espo and Laminas value.
|
||||
*/
|
||||
protected $accountCanonicalFormMap = [
|
||||
'Dn' => 1,
|
||||
@@ -107,7 +96,6 @@ class Utils
|
||||
'Principal' => 4,
|
||||
];
|
||||
|
||||
|
||||
public function __construct(Config $config = null)
|
||||
{
|
||||
if (isset($config)) {
|
||||
@@ -121,7 +109,7 @@ class Utils
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Options from espo config according to $this->fieldMap
|
||||
* Get Options from espo config according to $this->fieldMap.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -131,10 +119,10 @@ class Utils
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
$options = array();
|
||||
$options = [];
|
||||
foreach ($this->fieldMap as $ldapName => $espoName) {
|
||||
|
||||
$option = $this->getConfig()->get($espoName);
|
||||
|
||||
if (isset($option)) {
|
||||
$options[$ldapName] = $option;
|
||||
}
|
||||
@@ -162,7 +150,7 @@ class Utils
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an ldap option
|
||||
* Get an ldap option.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $returns Return value
|
||||
@@ -182,7 +170,7 @@ class Utils
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Laminas options for using Laminas\Ldap
|
||||
* Get Laminas options for using Laminas\Ldap.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -193,5 +181,4 @@ class Utils
|
||||
|
||||
return $zendOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,8 +44,12 @@ use Espo\Core\{
|
||||
Utils\Language,
|
||||
ApplicationUser,
|
||||
Authentication\Result,
|
||||
Authentication\LDAP\Utils as LDAPUtils,
|
||||
Authentication\LDAP\Client as LDAPClient,
|
||||
};
|
||||
|
||||
use Exception;
|
||||
|
||||
class LDAP extends Espo
|
||||
{
|
||||
private $utils;
|
||||
@@ -76,12 +80,9 @@ class LDAP extends Espo
|
||||
|
||||
$this->isPortal = $isPortal;
|
||||
|
||||
$this->utils = new LDAP\Utils($config);
|
||||
$this->utils = new LDAPUtils($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* User field name => option name (LDAP attribute).
|
||||
*/
|
||||
protected $ldapFieldMap = [
|
||||
'userName' => 'userNameAttribute',
|
||||
'firstName' => 'userFirstNameAttribute',
|
||||
@@ -91,17 +92,11 @@ class LDAP extends Espo
|
||||
'phoneNumber' => 'userPhoneNumberAttribute',
|
||||
];
|
||||
|
||||
/**
|
||||
* User field name => option name.
|
||||
*/
|
||||
protected $userFieldMap = [
|
||||
'teamsIds' => 'userTeamsIds',
|
||||
'defaultTeamId' => 'userDefaultTeamId',
|
||||
];
|
||||
|
||||
/**
|
||||
* User field name => option name.
|
||||
*/
|
||||
protected $portalUserFieldMap = [
|
||||
'portalsIds' => 'portalUserPortalsIds',
|
||||
'portalRolesIds' => 'portalUserRolesIds',
|
||||
@@ -137,7 +132,8 @@ class LDAP extends Espo
|
||||
/* Login LDAP system user (ldapUsername, ldapPassword) */
|
||||
try {
|
||||
$ldapClient->bind();
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$options = $this->utils->getLdapClientOptions();
|
||||
$GLOBALS['log']->error('LDAP: Could not connect to LDAP server ['.$options['host'].'], details: ' . $e->getMessage());
|
||||
|
||||
@@ -152,7 +148,8 @@ class LDAP extends Espo
|
||||
if (!isset($adminUser)) {
|
||||
try {
|
||||
$userDn = $this->findLdapUserDnByUsername($username);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$GLOBALS['log']->error('Error while finding DN for ['.$username.'], details: ' . $e->getMessage() . '.');
|
||||
}
|
||||
|
||||
@@ -171,8 +168,11 @@ class LDAP extends Espo
|
||||
|
||||
try {
|
||||
$ldapClient->bind($userDn, $password);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
catch (
|
||||
Exception $e) {
|
||||
$GLOBALS['log']->error('LDAP: Authentication failed for user ['.$username.'], details: ' . $e->getMessage());
|
||||
|
||||
return Result::fail();
|
||||
}
|
||||
}
|
||||
@@ -187,6 +187,7 @@ class LDAP extends Espo
|
||||
if (!isset($user)) {
|
||||
if (!$this->utils->getOption('createEspoUser')) {
|
||||
$this->useSystemUser();
|
||||
|
||||
throw new Error($this->language->translate('ldapUserInEspoNotFound', 'messages', 'User'));
|
||||
}
|
||||
|
||||
@@ -212,8 +213,9 @@ class LDAP extends Espo
|
||||
$options = $this->utils->getLdapClientOptions();
|
||||
|
||||
try {
|
||||
$this->ldapClient = new LDAP\Client($options);
|
||||
} catch (\Exception $e) {
|
||||
$this->ldapClient = new LDAPClient($options);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$GLOBALS['log']->error('LDAP error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
@@ -222,12 +224,7 @@ class LDAP extends Espo
|
||||
}
|
||||
|
||||
/**
|
||||
* Login by authorization token
|
||||
*
|
||||
* @param string $username
|
||||
* @param \Espo\Entities\AuthToken $authToken
|
||||
*
|
||||
* @return \Espo\Entities\User | null
|
||||
* Login by authorization token.
|
||||
*/
|
||||
protected function loginByToken($username, AuthToken $authToken = null)
|
||||
{
|
||||
@@ -239,11 +236,14 @@ class LDAP extends Espo
|
||||
$user = $this->entityManager->getEntity('User', $userId);
|
||||
|
||||
$tokenUsername = $user->get('userName');
|
||||
|
||||
if (strtolower($username) != strtolower($tokenUsername)) {
|
||||
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
|
||||
|
||||
$GLOBALS['log']->alert(
|
||||
'Unauthorized access attempt for user ['.$username.'] from IP ['.$ip.']'
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -257,11 +257,7 @@ class LDAP extends Espo
|
||||
}
|
||||
|
||||
/**
|
||||
* Login user with administrator rights
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return \Espo\Entities\User | null
|
||||
* Login user with administrator rights.
|
||||
*/
|
||||
protected function adminLogin($username, $password)
|
||||
{
|
||||
@@ -279,12 +275,7 @@ class LDAP extends Espo
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Espo user with data gets from LDAP server
|
||||
*
|
||||
* @param array $userData LDAP entity data
|
||||
* @param boolean $isPortal Is portal user
|
||||
*
|
||||
* @return \Espo\Entities\User
|
||||
* Create Espo user with data gets from LDAP server.
|
||||
*/
|
||||
protected function createUser(array $userData, $isPortal = false)
|
||||
{
|
||||
@@ -320,17 +311,14 @@ class LDAP extends Espo
|
||||
|
||||
$user = $this->entityManager->getEntity('User');
|
||||
$user->set($data);
|
||||
|
||||
$this->entityManager->saveEntity($user);
|
||||
|
||||
return $this->entityManager->getEntity('User', $user->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find LDAP user DN by his username
|
||||
*
|
||||
* @param string $username
|
||||
*
|
||||
* @return string | null
|
||||
* Find LDAP user DN by his username.
|
||||
*/
|
||||
protected function findLdapUserDnByUsername($username)
|
||||
{
|
||||
@@ -338,12 +326,15 @@ class LDAP extends Espo
|
||||
$options = $this->utils->getOptions();
|
||||
|
||||
$loginFilterString = '';
|
||||
|
||||
if (!empty($options['userLoginFilter'])) {
|
||||
$loginFilterString = $this->convertToFilterFormat($options['userLoginFilter']);
|
||||
}
|
||||
|
||||
$searchString = '(&(objectClass='.$options['userObjectClass'].')('.$options['userNameAttribute'].'='.$username.')'.$loginFilterString.')';
|
||||
$result = $ldapClient->search($searchString, null, LDAP\Client::SEARCH_SCOPE_SUB);
|
||||
$searchString = '(&(objectClass='.$options['userObjectClass'].')('.$options['userNameAttribute'].'='.$username.')'.
|
||||
$loginFilterString.')';
|
||||
|
||||
$result = $ldapClient->search($searchString, null, LDAPClient::SEARCH_SCOPE_SUB);
|
||||
$GLOBALS['log']->debug('LDAP: user search string: "' . $searchString . '"');
|
||||
|
||||
foreach ($result as $item) {
|
||||
@@ -352,30 +343,25 @@ class LDAP extends Espo
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and convert filter item into LDAP format
|
||||
*
|
||||
* @param string $filter E.g. "memberof=CN=externalTesters,OU=groups,DC=espo,DC=local"
|
||||
*
|
||||
* @return string
|
||||
* Check and convert filter item into LDAP format.
|
||||
*/
|
||||
protected function convertToFilterFormat($filter)
|
||||
{
|
||||
$filter = trim($filter);
|
||||
|
||||
if (substr($filter, 0, 1) != '(') {
|
||||
$filter = '(' . $filter;
|
||||
}
|
||||
|
||||
if (substr($filter, -1) != ')') {
|
||||
$filter = $filter . ')';
|
||||
}
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load fields for a user
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return array
|
||||
* Load fields for a user.
|
||||
*/
|
||||
protected function loadFields($type)
|
||||
{
|
||||
@@ -384,6 +370,7 @@ class LDAP extends Espo
|
||||
$typeMap = $type . 'FieldMap';
|
||||
|
||||
$fields = [];
|
||||
|
||||
foreach ($this->$typeMap as $fieldName => $fieldValue) {
|
||||
if (isset($options[$fieldValue])) {
|
||||
$fields[$fieldName] = $options[$fieldValue];
|
||||
|
||||
@@ -72,9 +72,10 @@ class Upgrade implements Command
|
||||
{
|
||||
$params = $this->normalizeParams($options, $flagList, $argumentList);
|
||||
|
||||
$versionInfo = $this->getVersionInfo();
|
||||
|
||||
$fromVersion = $this->config->get('version');
|
||||
$toVersion = $params->toVersion ?? null;
|
||||
|
||||
$versionInfo = $this->getVersionInfo($toVersion);
|
||||
|
||||
$nextVersion = $versionInfo->nextVersion ?? null;
|
||||
$lastVersion = $infoData->lastVersion ?? null;
|
||||
@@ -189,10 +190,22 @@ class Upgrade implements Command
|
||||
$params->singleProcess = true;
|
||||
}
|
||||
|
||||
if (in_array('patch', $flagList)) {
|
||||
$currentVersion = $this->config->get('version');
|
||||
|
||||
if (preg_match('/^(.*)\.(.*)\..*$/', $currentVersion, $match)) {
|
||||
$options['toVersion'] = $match[1] . '.' . $match[2];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($options['step'])) {
|
||||
$params->step = $options['step'];
|
||||
}
|
||||
|
||||
if (!empty($options['toVersion'])) {
|
||||
$params->toVersion = $options['toVersion'];
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
@@ -343,12 +356,16 @@ class Upgrade implements Command
|
||||
return $phpExecutablePath;
|
||||
}
|
||||
|
||||
protected function getVersionInfo()
|
||||
protected function getVersionInfo($toVersion = null)
|
||||
{
|
||||
$url = 'https://s.espocrm.com/upgrade/next/';
|
||||
$url = $this->config->get('upgradeNextVersionUrl', $url);
|
||||
$url .= '?fromVersion=' . $this->config->get('version');
|
||||
|
||||
if ($toVersion) {
|
||||
$url .= '&toVersion=' . $toVersion;
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, \CURLOPT_SSL_VERIFYPEER, true);
|
||||
|
||||
@@ -69,6 +69,7 @@ abstract class BaseFunction
|
||||
if (!$this->entity) {
|
||||
throw new NotPassedEntity('function: ' . $this->name);
|
||||
}
|
||||
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
@@ -119,12 +120,15 @@ abstract class BaseFunction
|
||||
protected function throwBadArgumentType(?int $index = null, ?string $type = null)
|
||||
{
|
||||
$msg = 'function: ' . $this->name;
|
||||
|
||||
if ($index !== null) {
|
||||
$msg .= ', index: ' . $index;
|
||||
|
||||
if ($type) {
|
||||
$msg .= ', should be: ' . $type;
|
||||
}
|
||||
}
|
||||
|
||||
throw new BadArgumentType($msg);
|
||||
}
|
||||
|
||||
@@ -134,12 +138,15 @@ abstract class BaseFunction
|
||||
protected function throwBadArgumentValue(?int $index = null, ?string $msg = null)
|
||||
{
|
||||
$string = 'function: ' . $this->name;
|
||||
|
||||
if ($index !== null) {
|
||||
$string .= ', index: ' . $index;
|
||||
|
||||
if ($msg) {
|
||||
$string .= ', ' . $msg;
|
||||
}
|
||||
}
|
||||
|
||||
throw new BadArgumentValue($string);
|
||||
}
|
||||
|
||||
@@ -147,11 +154,13 @@ abstract class BaseFunction
|
||||
* Throw Error exception.
|
||||
*/
|
||||
protected function throwError(?string $msg = null)
|
||||
|
||||
{
|
||||
$string = 'function: ' . $this->name;
|
||||
if ($msg) {
|
||||
$string .= ', ' . $msg;
|
||||
}
|
||||
|
||||
throw new Error($string);
|
||||
}
|
||||
|
||||
@@ -160,7 +169,10 @@ abstract class BaseFunction
|
||||
*/
|
||||
protected function logBadArgumentType(int $index, string $type)
|
||||
{
|
||||
if (!$this->log) return;
|
||||
if (!$this->log) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->log->warning("Formula function: {$this->name}, argument {$index} should be '{$type}'.");
|
||||
}
|
||||
|
||||
@@ -169,7 +181,10 @@ abstract class BaseFunction
|
||||
*/
|
||||
protected function log(string $msg, string $level = 'notice')
|
||||
{
|
||||
if (!$this->log) return;
|
||||
if (!$this->log) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->log->log($level, 'Formula function: ' . $this->name . ', ' . $msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2020 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\Formula\Functions\JsonGroup;
|
||||
|
||||
use Espo\Core\Formula\{
|
||||
Functions\BaseFunction,
|
||||
ArgumentList,
|
||||
};
|
||||
|
||||
class RetrieveType extends BaseFunction
|
||||
{
|
||||
public function process(ArgumentList $args)
|
||||
{
|
||||
if (count($args) < 2) {
|
||||
$this->throwTooFewArguments();
|
||||
}
|
||||
|
||||
$jsonString = $this->evaluate($args[0]);
|
||||
$path = $this->evaluate($args[1]);
|
||||
|
||||
if (!is_string($jsonString)) {
|
||||
$this->throwBadArgumentType(1, 'string');
|
||||
}
|
||||
|
||||
if (!is_string($path)) {
|
||||
$this->throwBadArgumentType(2, 'string');
|
||||
}
|
||||
|
||||
if ($path === '') {
|
||||
$this->throwBadArgumentValue(2);
|
||||
}
|
||||
|
||||
$item = json_decode($jsonString);
|
||||
|
||||
$pathArray = $this->splitPath($path);
|
||||
|
||||
return $this->retrieveAttribute($item, $pathArray);
|
||||
}
|
||||
|
||||
private function splitPath(string $path) : array
|
||||
{
|
||||
$pathArray = preg_split('/(?<!\\\)\./', $path);
|
||||
|
||||
foreach ($pathArray as $i => $item) {
|
||||
$pathArray[$i] = str_replace('\.', '.', $item);
|
||||
}
|
||||
|
||||
return $pathArray;
|
||||
}
|
||||
|
||||
private function retrieveAttribute($item, array $path)
|
||||
{
|
||||
if (!count($path)) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
$key = array_shift($path);
|
||||
|
||||
if (is_array($item)) {
|
||||
$key = intval($key);
|
||||
|
||||
$subItem = $item[$key] ?? null;
|
||||
|
||||
if (is_null($subItem)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->retrieveAttribute($subItem, $path);
|
||||
}
|
||||
|
||||
if (is_object($item)) {
|
||||
$subItem = $item->$key ?? null;
|
||||
|
||||
if (is_null($subItem)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->retrieveAttribute($subItem, $path);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,9 @@ class Importer
|
||||
if ($duplicate = $this->findDuplicate($email)) {
|
||||
if ($duplicate->get('status') != 'Being Imported') {
|
||||
$duplicate = $this->entityManager->getEntity('Email', $duplicate->id);
|
||||
|
||||
$this->processDuplicate($duplicate, $assignedUserId, $userIdList, $folderData, $teamsIdList);
|
||||
|
||||
return $duplicate;
|
||||
}
|
||||
}
|
||||
@@ -197,6 +199,7 @@ class Importer
|
||||
if ($parser->checkMessageAttribute($message, 'date')) {
|
||||
try {
|
||||
$dt = new DateTime($parser->getMessageAttribute($message, 'date'));
|
||||
|
||||
if ($dt) {
|
||||
$dateSent = $dt->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
|
||||
$email->set('dateSent', $dateSent);
|
||||
@@ -209,6 +212,7 @@ class Importer
|
||||
if ($parser->checkMessageAttribute($message, 'delivery-Date')) {
|
||||
try {
|
||||
$dt = new DateTime($parser->getMessageAttribute($message, 'delivery-Date'));
|
||||
|
||||
if ($dt) {
|
||||
$deliveryDate = $dt->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
|
||||
$email->set('delivery-Date', $deliveryDate);
|
||||
@@ -222,7 +226,7 @@ class Importer
|
||||
$parser->fetchContentParts($email, $message, $inlineAttachmentList);
|
||||
|
||||
if ($this->filtersMatcher->match($email, $filterList)) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
$email->set('body', 'Not fetched. The email size exceeds the limit.');
|
||||
@@ -233,15 +237,24 @@ class Importer
|
||||
|
||||
$replied = null;
|
||||
|
||||
if ($parser->checkMessageAttribute($message, 'in-Reply-To') && $parser->getMessageAttribute($message, 'in-Reply-To')) {
|
||||
if (
|
||||
$parser->checkMessageAttribute($message, 'in-Reply-To') && $parser->getMessageAttribute($message, 'in-Reply-To')
|
||||
) {
|
||||
$arr = explode(' ', $parser->getMessageAttribute($message, 'in-Reply-To'));
|
||||
$inReplyTo = $arr[0];
|
||||
|
||||
if ($inReplyTo) {
|
||||
if ($inReplyTo[0] !== '<') $inReplyTo = '<' . $inReplyTo . '>';
|
||||
$replied = $this->entityManager->getRepository('Email')->where(array(
|
||||
'messageId' => $inReplyTo
|
||||
))->findOne();
|
||||
if ($inReplyTo[0] !== '<') {
|
||||
$inReplyTo = '<' . $inReplyTo . '>';
|
||||
}
|
||||
|
||||
$replied = $this->entityManager
|
||||
->getRepository('Email')
|
||||
->where([
|
||||
'messageId' => $inReplyTo
|
||||
])
|
||||
->findOne();
|
||||
|
||||
if ($replied) {
|
||||
$email->set('repliedId', $replied->id);
|
||||
$repliedTeamIdList = $replied->getLinkMultipleIdList('teams');
|
||||
@@ -255,6 +268,7 @@ class Importer
|
||||
if ($parser->checkMessageAttribute($message, 'references') && $parser->getMessageAttribute($message, 'references')) {
|
||||
$references = $parser->getMessageAttribute($message, 'references');
|
||||
$delimiter = ' ';
|
||||
|
||||
if (strpos($references, '>,')) {
|
||||
$delimiter = ',';
|
||||
}
|
||||
@@ -278,6 +292,7 @@ class Importer
|
||||
if (!empty($parentType) && !empty($parentId)) {
|
||||
if ($parentType == 'Lead') {
|
||||
$parent = $this->entityManager->getEntity('Lead', $parentId);
|
||||
|
||||
if ($parent && $parent->get('status') == 'Converted') {
|
||||
if ($parent->get('createdAccountId')) {
|
||||
$account = $this->entityManager->getEntity('Account', $parent->get('createdAccountId'));
|
||||
@@ -301,6 +316,7 @@ class Importer
|
||||
|
||||
$email->set('parentType', $parentType);
|
||||
$email->set('parentId', $parentId);
|
||||
|
||||
$parentFound = true;
|
||||
}
|
||||
}
|
||||
@@ -310,6 +326,7 @@ class Importer
|
||||
if (!$parentFound) {
|
||||
if ($replied && $replied->get('parentId') && $replied->get('parentType')) {
|
||||
$parentFound = $this->entityManager->getEntity($replied->get('parentType'), $replied->get('parentId'));
|
||||
|
||||
if ($parentFound) {
|
||||
$email->set('parentType', $replied->get('parentType'));
|
||||
$email->set('parentId', $replied->get('parentId'));
|
||||
@@ -318,6 +335,7 @@ class Importer
|
||||
}
|
||||
if (!$parentFound) {
|
||||
$from = $email->get('from');
|
||||
|
||||
if ($from) {
|
||||
$parentFound = $this->findParent($email, $from);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,12 @@ class Url
|
||||
{
|
||||
public static function detectPortalId() : ?string
|
||||
{
|
||||
$portalId = $_SERVER['ESPO_PORTAL_ID'] ?? null;
|
||||
|
||||
if ($portalId) {
|
||||
return $portalId;
|
||||
}
|
||||
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
|
||||
$portalId = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1] ?? null;
|
||||
@@ -41,57 +47,61 @@ class Url
|
||||
$portalId = null;
|
||||
}
|
||||
|
||||
if (!isset($portalId)) {
|
||||
$url = $_SERVER['REDIRECT_URL'];
|
||||
|
||||
$portalId = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1] ?? null;
|
||||
if ($portalId) {
|
||||
return $portalId;
|
||||
}
|
||||
|
||||
$url = $_SERVER['REDIRECT_URL'] ?? null;
|
||||
|
||||
if (!$url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$portalId = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1] ?? null;
|
||||
|
||||
return $portalId;
|
||||
}
|
||||
|
||||
public static function detectUrl() : string
|
||||
protected static function detectIsCustomUrl() : bool
|
||||
{
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
|
||||
$portalId = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1] ?? null;
|
||||
|
||||
if (strpos($url, '=') !== false) {
|
||||
$portalId = null;
|
||||
}
|
||||
|
||||
if (!isset($portalId)) {
|
||||
return $_SERVER['REDIRECT_URL'];
|
||||
}
|
||||
|
||||
return $url;
|
||||
return (bool) ($_SERVER['ESPO_PORTAL_IS_CUSTOM_URL'] ?? false);
|
||||
}
|
||||
|
||||
public static function normalizeUrl(string $url) : string
|
||||
public static function detectIsInPortalDir() : bool
|
||||
{
|
||||
$urlParts = explode('?', $url);
|
||||
$isCustomUrl = self::detectIsCustomUrl();
|
||||
|
||||
if (substr($urlParts[0], -1) === '/') {
|
||||
return $url;
|
||||
if ($isCustomUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = $urlParts[0] . '/';
|
||||
|
||||
if (count($urlParts) > 1) {
|
||||
$url .= '?' . $urlParts[1];
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public function detectIsInDir() : bool
|
||||
{
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
|
||||
$a = explode('?', $url);
|
||||
|
||||
$url = rtrim($a[0], '/');
|
||||
|
||||
return strpos($url, '/') !== false;
|
||||
return strpos($url, '/portal') !== false ;
|
||||
}
|
||||
|
||||
public static function detectIsInPortalWithId() : bool
|
||||
{
|
||||
if (!self::detectIsInPortalDir()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
|
||||
$a = explode('?', $url);
|
||||
|
||||
$url = rtrim($a[0], '/');
|
||||
|
||||
$folders = explode('/', $url);
|
||||
|
||||
if (count($folders) > 1 && $folders[count($folders) - 2] === 'portal') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,12 @@
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\{
|
||||
Exceptions\Error,
|
||||
Utils\File\Manager as FileManager,
|
||||
};
|
||||
|
||||
use Espo\Core\Utils\File\Manager as FileManager;
|
||||
use StdClass;
|
||||
|
||||
/**
|
||||
* Reads and writes the main config file.
|
||||
@@ -88,6 +91,7 @@ class Config
|
||||
$keys = explode('.', $name);
|
||||
|
||||
$lastBranch = $this->loadConfig();
|
||||
|
||||
foreach ($keys as $keyName) {
|
||||
if (isset($lastBranch[$keyName]) && (is_array($lastBranch) || is_object($lastBranch))) {
|
||||
if (is_array($lastBranch)) {
|
||||
@@ -111,6 +115,7 @@ class Config
|
||||
$keys = explode('.', $name);
|
||||
|
||||
$lastBranch = $this->loadConfig();
|
||||
|
||||
foreach ($keys as $keyName) {
|
||||
if (isset($lastBranch[$keyName]) && (is_array($lastBranch) || is_object($lastBranch))) {
|
||||
if (is_array($lastBranch)) {
|
||||
@@ -136,14 +141,16 @@ class Config
|
||||
}
|
||||
|
||||
if (!is_array($name)) {
|
||||
$name = array($name => $value);
|
||||
$name = [$name => $value];
|
||||
}
|
||||
|
||||
foreach ($name as $key => $value) {
|
||||
if (in_array($key, $this->associativeArrayAttributeList) && is_object($value)) {
|
||||
$value = (array) $value;
|
||||
}
|
||||
|
||||
$this->data[$key] = $value;
|
||||
|
||||
if (!$dontMarkDirty) {
|
||||
$this->changedData[$key] = $value;
|
||||
}
|
||||
@@ -157,7 +164,9 @@ class Config
|
||||
{
|
||||
if (array_key_exists($name, $this->data)) {
|
||||
unset($this->data[$name]);
|
||||
|
||||
$this->removeData[] = $name;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -180,10 +189,11 @@ class Config
|
||||
$configPath = $this->getConfigPath();
|
||||
|
||||
if (!file_exists($configPath)) {
|
||||
throw new Error('Config file ['. $configPath .'] is not found.');
|
||||
throw new Error("Config file '{$configPath}' is not found.");
|
||||
}
|
||||
|
||||
$data = include($configPath);
|
||||
|
||||
if (!is_array($data)) {
|
||||
$data = include($configPath);
|
||||
}
|
||||
@@ -201,7 +211,8 @@ class Config
|
||||
}
|
||||
|
||||
if (!is_array($data)) {
|
||||
$GLOBALS['log']->error('Invalid config data ['. var_export($data, true) .'] while saving to ['. $configPath .'].');
|
||||
$GLOBALS['log']->error("Invalid config data while saving to '{$configPath}'.");
|
||||
|
||||
throw new Error('Invalid config data while saving.');
|
||||
}
|
||||
|
||||
@@ -211,14 +222,16 @@ class Config
|
||||
|
||||
if ($result) {
|
||||
$reloadedData = include($configPath);
|
||||
|
||||
if (!is_array($reloadedData) || $microtime !== ($reloadedData['microtime'] ?? null)) {
|
||||
$result = $this->getFileManager()->putPhpContents($configPath, $data, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
$this->changedData = array();
|
||||
$this->removeData = array();
|
||||
$this->changedData = [];
|
||||
$this->removeData = [];
|
||||
|
||||
$this->loadConfig(true);
|
||||
}
|
||||
|
||||
@@ -244,6 +257,7 @@ class Config
|
||||
$this->data = $this->getFileManager()->getPhpContents($configPath);
|
||||
|
||||
$systemConfig = $this->getFileManager()->getPhpContents($this->systemConfigPath);
|
||||
|
||||
$this->data = Util::merge($systemConfig, $this->data);
|
||||
|
||||
return $this->data;
|
||||
@@ -252,7 +266,7 @@ class Config
|
||||
/**
|
||||
* Get all parameters.
|
||||
*/
|
||||
public function getAllData() : \StdClass
|
||||
public function getAllData() : StdClass
|
||||
{
|
||||
return (object) $this->loadConfig();
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ use Espo\Core\{
|
||||
Utils\Config,
|
||||
Portal\Application as PortalApplication,
|
||||
Portal\ApplicationRunners\Client,
|
||||
Portal\Utils\Url,
|
||||
Api\Request,
|
||||
Api\Response,
|
||||
};
|
||||
@@ -64,26 +65,14 @@ class Portal implements EntryPoint
|
||||
{
|
||||
$data = $data ?? (object) [];
|
||||
|
||||
$id = $request->get('id') ?? $data->id ?? null;
|
||||
$id = $data->id ?? Url::detectPortalId();
|
||||
|
||||
if (!$id) {
|
||||
$url = $_SERVER['REQUEST_URI'];
|
||||
$id = $this->config->get('defaultPortalId');
|
||||
}
|
||||
|
||||
$id = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
||||
|
||||
if (!isset($id)) {
|
||||
$url = $_SERVER['REDIRECT_URL'];
|
||||
|
||||
$id = explode('/', $url)[count(explode('/', $_SERVER['SCRIPT_NAME'])) - 1];
|
||||
}
|
||||
|
||||
if (!$id) {
|
||||
$id = $this->config->get('defaultPortalId');
|
||||
}
|
||||
|
||||
if (!$id) {
|
||||
throw new NotFound();
|
||||
}
|
||||
if (!$id) {
|
||||
throw new NotFound("Portal ID not detected.");
|
||||
}
|
||||
|
||||
$application = new PortalApplication($id);
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
},
|
||||
{
|
||||
"name":"maxLength",
|
||||
"type":"int"
|
||||
"type":"int",
|
||||
"default": 150,
|
||||
"min": 1,
|
||||
"max": 65535
|
||||
},
|
||||
{
|
||||
"name":"trim",
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
"layouts": false,
|
||||
"tab": true,
|
||||
"acl": true,
|
||||
"aclPortal": "recordAllAccountContactOwnNo",
|
||||
"aclPortal": true,
|
||||
"aclPortalLevelList": ["all", "account", "contact", "own", "no"],
|
||||
"aclPortalActionList": ["read"],
|
||||
"notifications": true,
|
||||
"object": true,
|
||||
"customizable": true,
|
||||
|
||||
@@ -716,7 +716,10 @@ class Email extends Record implements
|
||||
|
||||
$update = $this->entityManager->getQueryBuilder()->update()
|
||||
->in('EmailUser')
|
||||
->set(['folderId' => $folderId])
|
||||
->set([
|
||||
'folderId' => $folderId,
|
||||
'inTrash' => false,
|
||||
])
|
||||
->where([
|
||||
'deleted' => false,
|
||||
'userId' => $userId,
|
||||
|
||||
@@ -76,7 +76,7 @@ class Portal extends Record implements
|
||||
|
||||
protected function clearRolesCache()
|
||||
{
|
||||
$this->fileManager->removeInDir('data/cache/application/acl-portal');
|
||||
$this->fileManager->removeInDir('data/cache/application/aclPortal');
|
||||
$this->dataManager->updateCacheTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class PortalRole extends Record implements
|
||||
|
||||
protected function clearRolesCache()
|
||||
{
|
||||
$this->fileManager->removeInDir('data/cache/application/acl-portal');
|
||||
$this->fileManager->removeInDir('data/cache/application/aclPortal');
|
||||
$this->dataManager->updateCacheTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,7 +675,7 @@ class User extends Record implements
|
||||
|
||||
protected function clearPortalRolesCache()
|
||||
{
|
||||
$this->fileManager->removeInDir('data/cache/application/acl-portal');
|
||||
$this->fileManager->removeInDir('data/cache/application/aclPortal');
|
||||
$this->dataManager->updateCacheTimestamp();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ul class="list-group">
|
||||
<ul class="list-group no-side-margin">
|
||||
<li data-id="inbox" class="list-group-item">
|
||||
<a href="javascript:" data-action="selectFolder" data-id="inbox" class="side-link">{{translate 'inbox' category='presetFilters' scope='Email'}}</a>
|
||||
</li>
|
||||
|
||||
@@ -56,7 +56,7 @@ define('views/admin/formula/modals/add-function', ['views/modal', 'model'], func
|
||||
setup: function () {
|
||||
this.header = this.translate('Function');
|
||||
|
||||
this.documentationUrl = 'https://www.espocrm.com/documentation/administration/formula/';
|
||||
this.documentationUrl = 'https://docs.espocrm.com/administration/formula/';
|
||||
|
||||
this.functionDataList = this.getMetadata().get('app.formula.functionList') || [];
|
||||
},
|
||||
|
||||
@@ -93,9 +93,8 @@ define('views/email/record/row-actions/default', 'views/record/row-actions/defau
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers')) {
|
||||
if (!this.model.get('isImportant')) {
|
||||
if (!this.model.get('inTrash')) {
|
||||
@@ -117,17 +116,17 @@ define('views/email/record/row-actions/default', 'views/record/row-actions/defau
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers') && this.model.get('status') !== 'Draft') {
|
||||
if (!this.model.get('inTrash')) {
|
||||
list.push({
|
||||
action: 'moveToFolder',
|
||||
label: 'Move to Folder',
|
||||
data: {
|
||||
id: this.model.id
|
||||
}
|
||||
});
|
||||
}
|
||||
list.push({
|
||||
action: 'moveToFolder',
|
||||
label: 'Move to Folder',
|
||||
data: {
|
||||
id: this.model.id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (this.options.acl.delete) {
|
||||
list.push({
|
||||
action: 'quickRemove',
|
||||
@@ -137,6 +136,7 @@ define('views/email/record/row-actions/default', 'views/record/row-actions/defau
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
|
||||
@@ -165,9 +165,9 @@ define('views/settings/fields/dashboard-layout', ['views/fields/base', 'lib!grid
|
||||
},
|
||||
|
||||
removeDashlet: function (id) {
|
||||
var grid = this.$gridstack.data('gridstack');
|
||||
var $item = this.$gridstack.find('.grid-stack-item[data-id="'+id+'"]');
|
||||
grid.removeWidget($item, true);
|
||||
|
||||
this.grid.removeWidget($item, true);
|
||||
|
||||
var layout = this.dashboardLayout[this.currentTab].layout;
|
||||
|
||||
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "espocrm",
|
||||
"version": "6.0.0-beta1",
|
||||
"version": "6.0.0-beta2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "espocrm",
|
||||
"version": "6.0.0-beta1",
|
||||
"version": "6.0.0-beta2",
|
||||
"description": "",
|
||||
"main": "index.php",
|
||||
"repository": {
|
||||
|
||||
+2
-11
@@ -41,19 +41,10 @@ if (!$app->isInstalled()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$url = Url::detectUrl();
|
||||
$normalizedUrl = Url::normalizeUrl($url);
|
||||
|
||||
if ($url !== $normalizedUrl) {
|
||||
header("Location: " . $normalizedUrl);
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
if (Url::detectIsInDir()) {
|
||||
if (Url::detectIsInPortalDir()) {
|
||||
$basePath = '../';
|
||||
|
||||
if (Url::detectPortalId()) {
|
||||
if (Url::detectIsInPortalWithId()) {
|
||||
$basePath = '../../';
|
||||
}
|
||||
|
||||
|
||||
@@ -40,13 +40,13 @@ class Utils
|
||||
*/
|
||||
public static function getLatestBuildedPath($path)
|
||||
{
|
||||
$archives = array();
|
||||
$archives = [];
|
||||
|
||||
$buildDir = dir($path);
|
||||
while ($folderName = $buildDir->read()) {
|
||||
if ($folderName === '.'|| $folderName === '..' || empty($folderName)) continue;
|
||||
|
||||
$pattern = '/^EspoCRM-([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-((a|alpha|b|beta|pre|rc)(\.[0-9]+)?)?)?$/';
|
||||
$pattern = '/^EspoCRM-([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-((a|alpha|b|beta|pre|rc)([0-9]+)?)?)?$/';
|
||||
|
||||
if (preg_match($pattern, $folderName)) {
|
||||
$archives[] = $folderName;
|
||||
@@ -61,14 +61,14 @@ class Utils
|
||||
|
||||
protected static function sortVersions(& $existVersions)
|
||||
{
|
||||
usort($existVersions, array("\\tests\\integration\\Core\\Utils", "versionCmp"));
|
||||
usort($existVersions, ["\\tests\\integration\\Core\\Utils", "versionCmp"]);
|
||||
}
|
||||
|
||||
public static function versionCmp($a, $b)
|
||||
{
|
||||
$order = array('a' => 0, 'alpha' => 1, 'b' => 2, 'beta' => 3, 'pre' => 4, 'rc' => 5);
|
||||
$order = ['a' => 0, 'alpha' => 1, 'b' => 2, 'beta' => 3, 'pre' => 4, 'rc' => 5];
|
||||
|
||||
$ma = $mb = array();
|
||||
$ma = $mb = [];
|
||||
|
||||
$pattern = '/^EspoCRM-([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:-((a|alpha|b|beta|pre|rc)[0-9]+)?)?$/';
|
||||
|
||||
|
||||
@@ -319,4 +319,119 @@ class EvaluatorTest extends \PHPUnit\Framework\TestCase
|
||||
|
||||
$this->assertTrue(is_float($value));
|
||||
}
|
||||
|
||||
public function testJsonRetrieve1()
|
||||
{
|
||||
$value = (object) [
|
||||
'a' => 'test',
|
||||
];
|
||||
|
||||
$expression = "json\\retrieve(\$value, 'a')";
|
||||
|
||||
$result = $this->evaluator->process($expression, null, (object) [
|
||||
'value' => json_encode($value),
|
||||
]);
|
||||
|
||||
$this->assertEquals('test', $result);
|
||||
}
|
||||
|
||||
public function testJsonRetrieve2()
|
||||
{
|
||||
$value = [
|
||||
0 => 'test',
|
||||
];
|
||||
|
||||
$expression = "json\\retrieve(\$value, '0')";
|
||||
|
||||
$result = $this->evaluator->process($expression, null, (object) [
|
||||
'value' => json_encode($value),
|
||||
]);
|
||||
|
||||
$this->assertEquals('test', $result);
|
||||
}
|
||||
|
||||
public function testJsonRetrieve3()
|
||||
{
|
||||
$value = (object) [
|
||||
'a' => [
|
||||
'ab' => 'test'
|
||||
],
|
||||
];
|
||||
|
||||
$expression = "json\\retrieve(\$value, 'a.ab')";
|
||||
|
||||
$result = $this->evaluator->process($expression, null, (object) [
|
||||
'value' => json_encode($value),
|
||||
]);
|
||||
|
||||
$this->assertEquals('test', $result);
|
||||
}
|
||||
|
||||
public function testJsonRetrieve4()
|
||||
{
|
||||
$value = (object) [
|
||||
'a' => [
|
||||
'ab' => 'test'
|
||||
],
|
||||
];
|
||||
|
||||
$expression = "json\\retrieve(\$value, 'b.c')";
|
||||
|
||||
$result = $this->evaluator->process($expression, null, (object) [
|
||||
'value' => json_encode($value),
|
||||
]);
|
||||
|
||||
$this->assertEquals(null, $result);
|
||||
}
|
||||
|
||||
public function testJsonRetrieve5()
|
||||
{
|
||||
$value = (object) [
|
||||
'a' => [
|
||||
'ab' => 'test'
|
||||
],
|
||||
];
|
||||
|
||||
$expression = "json\\retrieve(\$value, '0')";
|
||||
|
||||
$result = $this->evaluator->process($expression, null, (object) [
|
||||
'value' => json_encode($value),
|
||||
]);
|
||||
|
||||
$this->assertEquals(null, $result);
|
||||
}
|
||||
|
||||
public function testJsonRetrieve6()
|
||||
{
|
||||
$value = [
|
||||
0 => (object) [
|
||||
'a' => 'test'
|
||||
],
|
||||
];
|
||||
|
||||
$expression = "json\\retrieve(\$value, '0.a')";
|
||||
|
||||
$result = $this->evaluator->process($expression, null, (object) [
|
||||
'value' => json_encode($value),
|
||||
]);
|
||||
|
||||
$this->assertEquals('test', $result);
|
||||
}
|
||||
|
||||
public function testJsonRetrieve7()
|
||||
{
|
||||
$value = (object) [
|
||||
'a.b' => (object) [
|
||||
'c' => 'test'
|
||||
],
|
||||
];
|
||||
|
||||
$expression = "json\\retrieve(\$value, 'a\\.b.c')";
|
||||
|
||||
$result = $this->evaluator->process($expression, null, (object) [
|
||||
'value' => json_encode($value),
|
||||
]);
|
||||
|
||||
$this->assertEquals('test', $result);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user