mirror of
https://github.com/espocrm/espocrm.git
synced 2026-03-10 03:37:02 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
814f79d53b | ||
|
|
0d6482374e | ||
|
|
427e3d466a | ||
|
|
ae72768f8c | ||
|
|
bd4e92d892 | ||
|
|
afc17ac54c | ||
|
|
52dda066cd | ||
|
|
29bec8fcd6 | ||
|
|
5c4fd344e4 | ||
|
|
e936ad907b | ||
|
|
bc59dab9ec | ||
|
|
48652e35ee | ||
|
|
381a51b836 | ||
|
|
a9f36a352d | ||
|
|
6c8a0bbb66 | ||
|
|
b21b69eed5 | ||
|
|
ef0d3febd8 | ||
|
|
2d6db7570c | ||
|
|
a7804742e7 | ||
|
|
09301e9d7c | ||
|
|
5d10da3b78 | ||
|
|
dcc4cce872 | ||
|
|
02fbc20838 | ||
|
|
6641075043 | ||
|
|
6624b178c0 | ||
|
|
4ec6708cb4 | ||
|
|
f9752eab02 | ||
|
|
3de816e03a | ||
|
|
b854ebab43 | ||
|
|
ffab7c3e6b |
@@ -181,7 +181,7 @@ class Application
|
||||
}
|
||||
}
|
||||
$processList = array_values($processList);
|
||||
if (count($runningCount) >= $maxProcessNumber) {
|
||||
if ($runningCount >= $maxProcessNumber) {
|
||||
$toSkip = true;
|
||||
}
|
||||
if (!$toSkip) {
|
||||
|
||||
@@ -69,7 +69,13 @@ class ClientManager
|
||||
$externalAccountEntity = $this->clientMap[$hash]['externalAccountEntity'];
|
||||
$externalAccountEntity->set('accessToken', $data['accessToken']);
|
||||
$externalAccountEntity->set('tokenType', $data['tokenType']);
|
||||
$this->getEntityManager()->saveEntity($externalAccountEntity, ['isTokenRenewal' => true]);
|
||||
|
||||
$copy = $this->getEntityManager()->getEntity('ExternalAccount', $externalAccountEntity->id);
|
||||
if ($copy) {
|
||||
$copy->set('accessToken', $data['accessToken']);
|
||||
$copy->set('tokenType', $data['tokenType']);
|
||||
$this->getEntityManager()->saveEntity($copy, ['isTokenRenewal' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?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\Formula\Functions\EntityGroup;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class GetLinkColumnType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('entityManager');
|
||||
}
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
$args = $item->value ?? [];
|
||||
|
||||
if (!is_array($args)) throw new Error();
|
||||
if (count($args) < 3) throw new Error("Formula: entity\\isRelated: no argument.");
|
||||
|
||||
$link = $this->evaluate($args[0]);
|
||||
$id = $this->evaluate($args[1]);
|
||||
$column = $this->evaluate($args[2]);
|
||||
|
||||
$entityType = $this->getEntity()->getEntityType($entityType);
|
||||
$repository = $this->getInjection('entityManager')->getRepository($entityType);
|
||||
|
||||
return $repository->getRelationColumn($this->getEntity(), $link, $id, $column);
|
||||
}
|
||||
}
|
||||
@@ -819,14 +819,23 @@ class Base
|
||||
|
||||
$this->applyAdditional($params, $result);
|
||||
|
||||
if (empty($result['orderBy'])) {
|
||||
$result['orderBy'] = $this->getMetadata()->get(['entityDefs', $this->entityType, 'collection', 'orderBy']);
|
||||
if (empty($result['order']) && !is_array($result['orderBy'])) {
|
||||
$result['order'] = $this->getMetadata()->get(['entityDefs', $this->entityType, 'collection', 'order']) ?? null;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function applyDefaultOrder(array &$result)
|
||||
{
|
||||
$orderBy = $this->getMetadata()->get(['entityDefs', $this->entityType, 'collection', 'orderBy']);
|
||||
$order = $result['order'] ?? null;
|
||||
|
||||
if (!$order && !is_array($orderBy)) {
|
||||
$order = $this->getMetadata()->get(['entityDefs', $this->entityType, 'collection', 'order']) ?? null;
|
||||
}
|
||||
|
||||
return $result;
|
||||
if ($orderBy) {
|
||||
$this->applyOrder($orderBy, $order, $result);
|
||||
} else {
|
||||
$result['order'] = $order;
|
||||
}
|
||||
}
|
||||
|
||||
public function checkWhere(array $where, bool $checkWherePermission = true, bool $forbidComplexExpressions = false)
|
||||
@@ -1624,11 +1633,12 @@ class Base
|
||||
break;
|
||||
|
||||
case 'isNotLinked':
|
||||
if (!$result) break;
|
||||
$alias = $attribute . 'IsNotLinkedFilter' . strval(rand(10000, 99999));
|
||||
$part[$alias . '.id'] = null;
|
||||
$this->setDistinct(true, $result);
|
||||
$this->addLeftJoin([$attribute, $alias], $result);
|
||||
$part['id!=s'] = [
|
||||
'selectParams' => [
|
||||
'select' => ['id'],
|
||||
'joins' => [$attribute],
|
||||
]
|
||||
];
|
||||
break;
|
||||
|
||||
case 'isLinked':
|
||||
@@ -1718,6 +1728,8 @@ class Base
|
||||
case 'arrayNoneOf':
|
||||
case 'arrayIsEmpty':
|
||||
case 'arrayIsNotEmpty':
|
||||
if (!$result) break;
|
||||
|
||||
$arrayValueAlias = 'arrayFilter' . strval(rand(10000, 99999));
|
||||
$arrayAttribute = $attribute;
|
||||
$arrayEntityType = $this->getEntityType();
|
||||
@@ -1727,7 +1739,16 @@ class Base
|
||||
list($arrayAttributeLink, $arrayAttribute) = explode('.', $attribute);
|
||||
$seed = $this->getSeed();
|
||||
$arrayEntityType = $seed->getRelationParam($arrayAttributeLink, 'entity');
|
||||
$idPart = $arrayAttributeLink . '.id';
|
||||
|
||||
$arrayLinkAlias = $arrayAttributeLink . 'Filter' . strval(rand(10000, 99999));
|
||||
$idPart = $arrayLinkAlias . '.id';
|
||||
|
||||
$this->addLeftJoin([$arrayAttributeLink, $arrayLinkAlias], $result);
|
||||
|
||||
$relationType = $seed->getRelationType($arrayAttributeLink);
|
||||
if ($relationType === 'manyMany' || $relationType === 'hasMany') {
|
||||
$this->setDistinct(true, $result);
|
||||
}
|
||||
}
|
||||
|
||||
if ($type === 'arrayAnyOf') {
|
||||
|
||||
@@ -560,14 +560,23 @@ class Converter
|
||||
|
||||
protected function applyIndexes(&$ormMetadata, $entityType)
|
||||
{
|
||||
if (!isset($ormMetadata[$entityType]['indexes'])) {
|
||||
return;
|
||||
if (isset($ormMetadata[$entityType]['indexes'])) {
|
||||
foreach ($ormMetadata[$entityType]['indexes'] as $indexName => &$indexData) {
|
||||
if (!isset($indexData['key'])) {
|
||||
$indexType = SchemaUtils::getIndexTypeByIndexDefs($indexData);
|
||||
$indexData['key'] = SchemaUtils::generateIndexName($indexName, $indexType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ormMetadata[$entityType]['indexes'] as $indexName => &$indexData) {
|
||||
if (!isset($indexData['key'])) {
|
||||
$indexType = SchemaUtils::getIndexTypeByIndexDefs($indexData);
|
||||
$indexData['key'] = SchemaUtils::generateIndexName($indexName, $indexType);
|
||||
if (isset($ormMetadata[$entityType]['relations'])) {
|
||||
foreach ($ormMetadata[$entityType]['relations'] as $relationName => &$relationData) {
|
||||
if (isset($relationData['indexes'])) {
|
||||
foreach ($relationData['indexes'] as $indexName => &$indexData) {
|
||||
$indexType = SchemaUtils::getIndexTypeByIndexDefs($indexData);
|
||||
$indexData['key'] = SchemaUtils::generateIndexName($indexName, $indexType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace Espo\Core\Utils\Database\Orm\Relations;
|
||||
|
||||
class EntityTeam extends Base
|
||||
{
|
||||
protected function load($linkName, $entityName)
|
||||
protected function load($linkName, $entityType)
|
||||
{
|
||||
$linkParams = $this->getLinkParams();
|
||||
$foreignEntityName = $this->getForeignEntityName();
|
||||
|
||||
return [
|
||||
$entityName => [
|
||||
$entityType => [
|
||||
'relations' => [
|
||||
$linkName => [
|
||||
'type' => 'manyMany',
|
||||
@@ -45,21 +45,21 @@ class EntityTeam extends Base
|
||||
'relationName' => lcfirst($linkParams['relationName']),
|
||||
'midKeys' => [
|
||||
'entityId',
|
||||
'teamId'
|
||||
'teamId',
|
||||
],
|
||||
'conditions' => [
|
||||
'entityType' => $entityName
|
||||
'entityType' => $entityType,
|
||||
],
|
||||
'additionalColumns' => [
|
||||
'entityType' => [
|
||||
'type' => 'varchar',
|
||||
'len' => 100
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
'len' => 100,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +340,8 @@ class Converter
|
||||
}
|
||||
|
||||
if (!empty($uniqueIndex)) {
|
||||
$table->addUniqueIndex($uniqueIndex, SchemaUtils::generateIndexName($columnName, 'unique'));
|
||||
$uniqueIndexName = implode('_', $uniqueIndex);
|
||||
$table->addUniqueIndex($uniqueIndex, SchemaUtils::generateIndexName($uniqueIndexName, 'unique'));
|
||||
}
|
||||
//END: add unique indexes
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class Utils
|
||||
if (isset($entityParams['indexes']) && is_array($entityParams['indexes'])) {
|
||||
foreach ($entityParams['indexes'] as $indexName => $indexParams) {
|
||||
$indexType = static::getIndexTypeByIndexDefs($indexParams);
|
||||
$tableIndexName = static::generateIndexName($indexName, $indexType);
|
||||
$tableIndexName = isset($indexParams['key']) ? $indexParams['key'] : static::generateIndexName($indexName, $indexType);
|
||||
|
||||
if (isset($indexParams['flags']) && is_array($indexParams['flags'])) {
|
||||
$skipIndex = false;
|
||||
|
||||
@@ -50,7 +50,7 @@ class EntityManager
|
||||
|
||||
private $container;
|
||||
|
||||
private $reservedWordList = ['__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'common'];
|
||||
private $reservedWordList = ['__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'common', 'fn'];
|
||||
|
||||
private $linkForbiddenNameList = ['posts', 'stream', 'subscription', 'followers', 'action', 'null', 'false', 'true'];
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ return [
|
||||
'outboundEmailFromName' => 'EspoCRM',
|
||||
'outboundEmailFromAddress' => '',
|
||||
'smtpServer' => '',
|
||||
'smtpPort' => 25,
|
||||
'smtpPort' => 587,
|
||||
'smtpAuth' => true,
|
||||
'smtpSecurity' => '',
|
||||
'smtpSecurity' => 'TLS',
|
||||
'smtpUsername' => '',
|
||||
'smtpPassword' => '',
|
||||
'languageList' => [
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Espo\Entities;
|
||||
|
||||
class Integration extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
public function get($name, $params = array())
|
||||
public function get($name, $params = [])
|
||||
{
|
||||
if ($name == 'id') {
|
||||
return $this->id;
|
||||
@@ -100,6 +100,13 @@ class Integration extends \Espo\Core\ORM\Entity
|
||||
}
|
||||
}
|
||||
|
||||
public function isAttributeChanged($name)
|
||||
{
|
||||
if ($name === 'data') return true;
|
||||
|
||||
return parent::isAttributeChanged($name);
|
||||
}
|
||||
|
||||
public function populateFromArray(array $arr, $onlyAccessible = true, $reset = false)
|
||||
{
|
||||
if ($reset) {
|
||||
|
||||
@@ -438,6 +438,59 @@ abstract class Mapper implements IMapper
|
||||
}
|
||||
}
|
||||
|
||||
public function getRelationColumn(IEntity $entity, string $relationName, string $id, string $column)
|
||||
{
|
||||
$type = $entity->getRelationType($entityType, $relationName);
|
||||
|
||||
if (!$type === IEntity::MANY_MANY) return null;
|
||||
|
||||
$relDefs = $entity->relations[$relationName];
|
||||
|
||||
$relTable = $this->toDb($relDefs['relationName']);
|
||||
|
||||
$keySet = $this->query->getKeys($entity, $relationName);
|
||||
$key = $keySet['key'];
|
||||
$foreignKey = $keySet['foreignKey'];
|
||||
$nearKey = $keySet['nearKey'];
|
||||
$distantKey = $keySet['distantKey'];
|
||||
|
||||
$additionalColumns = $entity->getRelationParam($relationName, 'additionalColumns') ?? [];
|
||||
|
||||
if (!isset($additionalColumns[$column])) return null;
|
||||
|
||||
$columnType = $additionalColumns[$column]['type'] ?? 'string';
|
||||
|
||||
$columnAlias = $this->query->sanitizeSelectAlias($column);
|
||||
|
||||
$sql =
|
||||
"SELECT " . $this->toDb($this->query->sanitize($column)) . " AS `{$columnAlias}` FROM `{$relTable}` " .
|
||||
"WHERE ";
|
||||
|
||||
$wherePart =
|
||||
$this->toDb($nearKey) . " = " . $this->pdo->quote($entity->id) . " ".
|
||||
"AND " . $this->toDb($distantKey) . " = " . $this->pdo->quote($id) . " AND deleted = 0";
|
||||
|
||||
$sql .= $wherePart;
|
||||
|
||||
$ps = $this->pdo->query($sql);
|
||||
if ($ps) {
|
||||
foreach ($ps as $row) {
|
||||
$value = $row[$columnAlias];
|
||||
if ($columnType == 'bool') {
|
||||
$value = boolval($value);
|
||||
} else if ($columnType == 'int') {
|
||||
$value = intval($value);
|
||||
} else if ($columnType == 'float') {
|
||||
$value = floatval($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function massRelate(IEntity $entity, $relationName, array $params = [])
|
||||
{
|
||||
if (!$entity) {
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class Base
|
||||
'customHaving',
|
||||
'skipTextColumns',
|
||||
'maxTextColumnsLength',
|
||||
'useIndexList',
|
||||
'useIndex',
|
||||
];
|
||||
|
||||
protected static $sqlOperators = [
|
||||
@@ -310,13 +310,15 @@ abstract class Base
|
||||
|
||||
if (!empty($params['additionalColumns']) && is_array($params['additionalColumns']) && !empty($params['relationName'])) {
|
||||
foreach ($params['additionalColumns'] as $column => $field) {
|
||||
$selectPart .= ", `" . $this->toDb($this->sanitize($params['relationName'])) . "`." . $this->toDb($this->sanitize($column)) . " AS `{$field}`";
|
||||
$itemAlias = $this->sanitizeSelectAlias($field);
|
||||
$selectPart .= ", `" . $this->toDb($this->sanitize($params['relationName'])) . "`." . $this->toDb($this->sanitize($column)) . " AS `{$itemAlias}`";
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['additionalSelectColumns']) && is_array($params['additionalSelectColumns'])) {
|
||||
foreach ($params['additionalSelectColumns'] as $column => $field) {
|
||||
$selectPart .= ", " . $column . " AS `{$field}`";
|
||||
$itemAlias = $this->sanitizeSelectAlias($field);
|
||||
$selectPart .= ", " . $column . " AS `{$itemAlias}`";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,9 +386,14 @@ abstract class Base
|
||||
}
|
||||
|
||||
$indexKeyList = null;
|
||||
if (!empty($params['useIndexList']) && $this->metadata) {
|
||||
$indexList = $params['useIndex'] ?? null;
|
||||
|
||||
if (!empty($indexList) && $this->metadata) {
|
||||
$indexKeyList = [];
|
||||
foreach ($params['useIndexList'] as $indexName) {
|
||||
if (is_string($indexList)) {
|
||||
$indexList = [$indexList];
|
||||
}
|
||||
foreach ($indexList as $indexName) {
|
||||
$indexKey = $this->metadata->get($entityType, ['indexes', $indexName, 'key']);
|
||||
if ($indexKey) {
|
||||
$indexKeyList[] = $indexKey;
|
||||
@@ -864,7 +871,7 @@ abstract class Base
|
||||
$part = str_replace('{alias}', $alias, $part);
|
||||
}
|
||||
} else {
|
||||
$part = $this->toDb($entity->getEntityType()) . '.' . $this->toDb($attribute);
|
||||
$part = $this->toDb($entity->getEntityType()) . '.' . $this->toDb($this->sanitize($attribute));
|
||||
if ($type === 'orderBy') {
|
||||
$part .= ' {direction}';
|
||||
}
|
||||
@@ -1019,6 +1026,8 @@ abstract class Base
|
||||
|
||||
if (!$alias) {
|
||||
$alias = $this->getAlias($entity, $relationName);
|
||||
} else {
|
||||
$alias = $this->sanitizeSelectAlias($alias);
|
||||
}
|
||||
|
||||
if ($alias) {
|
||||
@@ -1613,14 +1622,19 @@ abstract class Base
|
||||
protected function getJoins(IEntity $entity, array $joins, $isLeft = false, $joinConditions = [])
|
||||
{
|
||||
$joinSqlList = [];
|
||||
|
||||
foreach ($joins as $item) {
|
||||
$itemConditions = [];
|
||||
$params = [];
|
||||
if (is_array($item)) {
|
||||
$relationName = $item[0];
|
||||
if (count($item) > 1) {
|
||||
$alias = $item[1];
|
||||
$alias = $item[1] ?? $relationName;
|
||||
if (count($item) > 2) {
|
||||
$itemConditions = $item[2];
|
||||
$itemConditions = $item[2] ?? [];
|
||||
}
|
||||
if (count($item) > 3) {
|
||||
$params = $item[3] ?? [];
|
||||
}
|
||||
} else {
|
||||
$alias = $relationName;
|
||||
@@ -1636,7 +1650,7 @@ abstract class Base
|
||||
foreach ($itemConditions as $left => $right) {
|
||||
$conditions[$left] = $right;
|
||||
}
|
||||
if ($sql = $this->getJoin($entity, $relationName, $isLeft, $conditions, $alias)) {
|
||||
if ($sql = $this->getJoin($entity, $relationName, $isLeft, $conditions, $alias, $params)) {
|
||||
$joinSqlList[] = $sql;
|
||||
}
|
||||
}
|
||||
@@ -1752,13 +1766,15 @@ abstract class Base
|
||||
}
|
||||
}
|
||||
|
||||
protected function getJoin(IEntity $entity, $name, $isLeft = false, $conditions = [], $alias = null)
|
||||
protected function getJoin(IEntity $entity, $name, $isLeft = false, $conditions = [], $alias = null, array $params = [])
|
||||
{
|
||||
$prefix = ($isLeft) ? 'LEFT ' : '';
|
||||
|
||||
if (!$entity->hasRelation($name)) {
|
||||
if (!$alias) {
|
||||
$alias = $this->sanitize($name);
|
||||
} else {
|
||||
$alias = $this->sanitizeSelectAlias($alias);
|
||||
}
|
||||
$table = $this->toDb($this->sanitize($name));
|
||||
|
||||
@@ -1808,8 +1824,34 @@ abstract class Base
|
||||
|
||||
$midAlias = $alias . 'Middle';
|
||||
|
||||
$indexKeyList = null;
|
||||
$indexList = $params['useIndex'] ?? null;
|
||||
|
||||
if ($indexList && $this->metadata) {
|
||||
$indexKeyList = [];
|
||||
if (is_string($indexList)) {
|
||||
$indexList = [$indexList];
|
||||
}
|
||||
foreach ($indexList as $indexName) {
|
||||
$indexKey = $this->metadata->get($entity->getEntityType(), ['relations', $relationName, 'indexes', $indexName, 'key']);
|
||||
if ($indexKey) {
|
||||
$indexKeyList[] = $indexKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$indexPart = '';
|
||||
|
||||
if ($indexKeyList && count($indexKeyList)) {
|
||||
$sanitizedIndexList = [];
|
||||
foreach ($indexKeyList as $indexKey) {
|
||||
$sanitizedIndexList[] = '`' . $this->sanitizeIndexName($indexKey) . '`';
|
||||
}
|
||||
$indexPart = " USE INDEX (".implode(', ', $sanitizedIndexList).")";
|
||||
}
|
||||
|
||||
$sql =
|
||||
"{$prefix}JOIN `{$relTable}` AS `{$midAlias}` ON {$this->toDb($entity->getEntityType())}." . $this->toDb($key) . " = {$midAlias}." . $this->toDb($nearKey)
|
||||
"{$prefix}JOIN `{$relTable}` AS `{$midAlias}`{$indexPart} ON {$this->toDb($entity->getEntityType())}." . $this->toDb($key) . " = {$midAlias}." . $this->toDb($nearKey)
|
||||
. " AND "
|
||||
. "{$midAlias}.deleted = " . $this->pdo->quote(0);
|
||||
|
||||
@@ -1821,9 +1863,13 @@ abstract class Base
|
||||
$sql .= " AND " . implode(" AND ", $joinSqlList);
|
||||
}
|
||||
|
||||
$sql .= " {$prefix}JOIN `{$distantTable}` AS `{$alias}` ON {$alias}." . $this->toDb($foreignKey) . " = {$midAlias}." . $this->toDb($distantKey)
|
||||
. " AND "
|
||||
. "{$alias}.deleted = " . $this->pdo->quote(0) . "";
|
||||
$onlyMiddle = $params['onlyMiddle'] ?? false;
|
||||
|
||||
if (!$onlyMiddle) {
|
||||
$sql .= " {$prefix}JOIN `{$distantTable}` AS `{$alias}` ON {$alias}." . $this->toDb($foreignKey) . " = {$midAlias}." . $this->toDb($distantKey)
|
||||
. " AND "
|
||||
. "{$alias}.deleted = " . $this->pdo->quote(0) . "";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
|
||||
|
||||
@@ -396,6 +396,11 @@ class RDB extends \Espo\ORM\Repository
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getRelationColumn(Entity $entity, string $relationName, string $foreignId, string $column)
|
||||
{
|
||||
return $this->getMapper()->getRelationColumn($entity, $relationName, $foreignId, $column);
|
||||
}
|
||||
|
||||
protected function beforeRelate(Entity $entity, $relationName, $foreign, $data = null, array $options = [])
|
||||
{
|
||||
}
|
||||
|
||||
@@ -188,6 +188,7 @@
|
||||
"inlineEditDisabled": "Disable Inline Edit",
|
||||
"allowCustomOptions": "Allow Custom Options",
|
||||
"displayAsLabel": "Display as Label",
|
||||
"displayAsList": "Display as List",
|
||||
"maxCount": "Max Item Count",
|
||||
"accept": "Accept",
|
||||
"displayRawText": "Display raw text (no markdown)"
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
"type": "int",
|
||||
"min": 0,
|
||||
"max": 9999,
|
||||
"default": 25
|
||||
"default": 587
|
||||
},
|
||||
"smtpAuth": {
|
||||
"type": "bool",
|
||||
@@ -100,6 +100,7 @@
|
||||
},
|
||||
"smtpSecurity": {
|
||||
"type": "enum",
|
||||
"default": "TLS",
|
||||
"options": ["", "SSL", "TLS"]
|
||||
},
|
||||
"smtpUsername": {
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
"type": "int",
|
||||
"min": 0,
|
||||
"max": 9999,
|
||||
"default": 25
|
||||
"default": 587
|
||||
},
|
||||
"smtpAuth": {
|
||||
"type": "bool",
|
||||
@@ -108,6 +108,7 @@
|
||||
},
|
||||
"smtpSecurity": {
|
||||
"type": "enum",
|
||||
"default": "TLS",
|
||||
"options": ["", "SSL", "TLS"]
|
||||
},
|
||||
"smtpUsername": {
|
||||
|
||||
@@ -101,7 +101,8 @@
|
||||
"type": "int",
|
||||
"min": 0,
|
||||
"max": 9999,
|
||||
"default": 25
|
||||
"required": true,
|
||||
"default": 587
|
||||
},
|
||||
"smtpAuth": {
|
||||
"type": "bool",
|
||||
@@ -109,6 +110,7 @@
|
||||
},
|
||||
"smtpSecurity": {
|
||||
"type": "enum",
|
||||
"default": "TLS",
|
||||
"options": ["", "SSL", "TLS"]
|
||||
},
|
||||
"smtpUsername": {
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
"name":"displayAsLabel",
|
||||
"type":"bool"
|
||||
},
|
||||
{
|
||||
"name": "displayAsList",
|
||||
"type":"bool"
|
||||
},
|
||||
{
|
||||
"name":"audited",
|
||||
"type":"bool"
|
||||
|
||||
@@ -71,12 +71,12 @@ class Email extends \Espo\Core\SelectManagers\Base
|
||||
$skipIndex = true;
|
||||
}
|
||||
if (!$skipIndex) {
|
||||
$result['useIndexList'] = ['dateSent'];
|
||||
$result['useIndex'] = 'dateSent';
|
||||
}
|
||||
}
|
||||
|
||||
if ($folderId === 'drafts') {
|
||||
$result['useIndexList'] = ['createdById'];
|
||||
$result['useIndex'] = 'createdById';
|
||||
}
|
||||
|
||||
if ($folderId !== 'drafts') {
|
||||
|
||||
@@ -253,7 +253,7 @@ class Email extends Record
|
||||
}
|
||||
}
|
||||
|
||||
$message = null;
|
||||
$message = new \Zend\Mail\Message();
|
||||
|
||||
$this->validateEmailAddresses($entity);
|
||||
|
||||
|
||||
@@ -102,6 +102,8 @@ class Language extends \Espo\Core\Services\Base
|
||||
unset($data['Global']['scopeNames'][$scope]);
|
||||
unset($data['Global']['scopeNamesPlural'][$scope]);
|
||||
} else {
|
||||
if (in_array($scope, ['EmailAccount', 'InboundEmail'])) continue;
|
||||
|
||||
foreach ($this->getAcl()->getScopeForbiddenFieldList($scope) as $field) {
|
||||
if (isset($data[$scope]['fields'])) unset($data[$scope]['fields'][$field]);
|
||||
if (isset($data[$scope]['options'])) unset($data[$scope]['options'][$field]);
|
||||
|
||||
@@ -327,12 +327,16 @@ class LeadCapture extends Record
|
||||
}
|
||||
}
|
||||
|
||||
$isContactOptedIn = false;
|
||||
|
||||
if ($leadCapture->get('subscribeToTargetList') && $leadCapture->get('targetListId')) {
|
||||
$isAlreadyOptedIn = false;
|
||||
|
||||
if ($contact) {
|
||||
if ($leadCapture->get('subscribeContactToTargetList')) {
|
||||
$isAlreadyOptedIn = $this->isTargetOptedIn($contact, $leadCapture->get('targetListId'));
|
||||
$isContactOptedIn = $isAlreadyOptedIn;
|
||||
|
||||
if (!$isAlreadyOptedIn) {
|
||||
$this->getEntityManager()->getRepository('Contact')->relate($contact, 'targetLists', $leadCapture->get('targetListId'), [
|
||||
'optedOut' => false,
|
||||
@@ -351,15 +355,6 @@ class LeadCapture extends Record
|
||||
'leadCaptureId' => $leadCapture->id,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->getInjection('hookManager')->process('LeadCapture', 'afterLeadCapture', $leadCapture, [], [
|
||||
'targetId' => $contact->id,
|
||||
'targetType' => 'Contact',
|
||||
]);
|
||||
|
||||
$this->getInjection('hookManager')->process('Contact', 'afterLeadCapture', $contact, [], [
|
||||
'leadCaptureId' => $leadCapture->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,6 +371,16 @@ class LeadCapture extends Record
|
||||
}
|
||||
}
|
||||
|
||||
if ($contact && (!$isContactOptedIn || !$leadCapture->get('subscribeToTargetList'))) {
|
||||
$this->getInjection('hookManager')->process('LeadCapture', 'afterLeadCapture', $leadCapture, [], [
|
||||
'targetId' => $contact->id,
|
||||
'targetType' => 'Contact',
|
||||
]);
|
||||
$this->getInjection('hookManager')->process('Contact', 'afterLeadCapture', $contact, [], [
|
||||
'leadCaptureId' => $leadCapture->id,
|
||||
]);
|
||||
}
|
||||
|
||||
$isNew = !$duplicate && !$contact;
|
||||
|
||||
if (!$contact || !$leadCapture->get('subscribeContactToTargetList')) {
|
||||
@@ -408,12 +413,13 @@ class LeadCapture extends Record
|
||||
'leadCaptureId' => $leadCapture->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($toRelateLead || !$leadCapture->get('subscribeToTargetList')) {
|
||||
$this->getInjection('hookManager')->process('LeadCapture', 'afterLeadCapture', $leadCapture, [], [
|
||||
'targetId' => $targetLead->id,
|
||||
'targetType' => 'Lead',
|
||||
]);
|
||||
|
||||
$this->getInjection('hookManager')->process('Lead', 'afterLeadCapture', $targetLead, [], [
|
||||
'leadCaptureId' => $leadCapture->id,
|
||||
]);
|
||||
|
||||
@@ -64,6 +64,7 @@ class Metadata extends \Espo\Core\Services\Base
|
||||
if (!$this->getUser()->isAdmin()) {
|
||||
$scopeList = array_keys($this->getMetadata()->get(['scopes'], []));
|
||||
foreach ($scopeList as $scope) {
|
||||
if (in_array($scope, ['Reminder'])) continue;
|
||||
if (!$this->getAcl()->check($scope)) {
|
||||
unset($data->entityDefs->$scope);
|
||||
unset($data->clientDefs->$scope);
|
||||
|
||||
@@ -1064,7 +1064,13 @@ class Record extends \Espo\Core\Services\Base
|
||||
|
||||
protected function getSelectParams($params)
|
||||
{
|
||||
$selectParams = $this->getSelectManager($this->entityType)->getSelectParams($params, true, true, true);
|
||||
$selectManager = $this->getSelectManager($this->entityType);
|
||||
|
||||
$selectParams = $selectManager->getSelectParams($params, true, true, true);
|
||||
|
||||
if (empty($selectParams['orderBy'])) {
|
||||
$selectManager->applyDefaultOrder($selectParams);
|
||||
}
|
||||
|
||||
return $selectParams;
|
||||
}
|
||||
@@ -1345,7 +1351,13 @@ class Record extends \Espo\Core\Services\Base
|
||||
}
|
||||
}
|
||||
|
||||
$selectParams = $this->getSelectManager($foreignEntityType)->getSelectParams($params, !$skipAcl, true);
|
||||
$selectManager = $this->getSelectManager($foreignEntityType);
|
||||
|
||||
$selectParams = $selectManager->getSelectParams($params, !$skipAcl, true);
|
||||
|
||||
if (empty($selectParams['orderBy'])) {
|
||||
$selectManager->applyDefaultOrder($selectParams);
|
||||
}
|
||||
|
||||
if (array_key_exists($link, $this->linkSelectParams)) {
|
||||
$selectParams = array_merge($selectParams, $this->linkSelectParams[$link]);
|
||||
|
||||
@@ -194,9 +194,7 @@ class RecordTree extends Record
|
||||
public function getLastChildrenIdList($parentId = null)
|
||||
{
|
||||
$selectParams = $this->getSelectManager($this->entityType)->getSelectParams([], true, true);
|
||||
$selectParams['whereClause'][] = array(
|
||||
'parentId' => $parentId
|
||||
);
|
||||
$selectParams['whereClause'][] = ['parentId' => $parentId];
|
||||
|
||||
$idList = [];
|
||||
|
||||
@@ -205,12 +203,12 @@ class RecordTree extends Record
|
||||
$includingRecords = true;
|
||||
}
|
||||
|
||||
$collection = $this->getRepository()->find($selectParams);
|
||||
$collection = $this->getRepository()->select(['id'])->find($selectParams);
|
||||
|
||||
foreach ($collection as $entity) {
|
||||
$selectParams2 = $this->getSelectManager($this->entityType)->getSelectParams([], true, true);
|
||||
$selectParams2['whereClause'][] = array(
|
||||
'parentId' => $entity->id
|
||||
);
|
||||
$selectParams2['whereClause'][] = ['parentId' => $entity->id];
|
||||
|
||||
if (!$this->getRepository()->count($selectParams2)) {
|
||||
$idList[] = $entity->id;
|
||||
} else {
|
||||
|
||||
@@ -386,7 +386,7 @@ class Stream extends \Espo\Core\Services\Base
|
||||
'orderBy' => 'number',
|
||||
'order' => 'DESC',
|
||||
'limit' => $sqLimit,
|
||||
'useIndexList' => ['createdByNumber'],
|
||||
'useIndex' => 'createdByNumber',
|
||||
];
|
||||
|
||||
if ($user->isPortal()) {
|
||||
@@ -484,7 +484,7 @@ class Stream extends \Espo\Core\Services\Base
|
||||
'orderBy' => 'number',
|
||||
'order' => 'DESC',
|
||||
'limit' => $sqLimit,
|
||||
'useIndexList' => ['createdByNumber'],
|
||||
'useIndex' => 'createdByNumber',
|
||||
];
|
||||
|
||||
if ($user->isPortal()) {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('crm:views/meeting/fields/reminders', 'views/fields/base', function (Dep) {
|
||||
define('crm:views/meeting/fields/reminders', 'views/fields/base', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -76,8 +76,8 @@ Espo.define('crm:views/meeting/fields/reminders', 'views/fields/base', function
|
||||
this.reminderList = this.model.get(this.name) || [];
|
||||
}, this);
|
||||
|
||||
this.typeList = this.getMetadata().get('entityDefs.Reminder.fields.type.options');
|
||||
this.secondsList = this.getMetadata().get('entityDefs.Reminder.fields.seconds.options');
|
||||
this.typeList = this.getMetadata().get('entityDefs.Reminder.fields.type.options') || [];
|
||||
this.secondsList = this.getMetadata().get('entityDefs.Reminder.fields.seconds.options') || [];
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
|
||||
@@ -26,29 +26,73 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/admin/outbound-emails', 'views/settings/record/edit', function (Dep) {
|
||||
define('views/admin/outbound-emails', 'views/settings/record/edit', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
layoutName: 'outboundEmails',
|
||||
|
||||
dependencyDefs: {
|
||||
'smtpAuth': {
|
||||
map: {
|
||||
true: [
|
||||
{
|
||||
action: 'show',
|
||||
fields: ['smtpUsername', 'smtpPassword']
|
||||
}
|
||||
]
|
||||
},
|
||||
default: [
|
||||
{
|
||||
action: 'hide',
|
||||
fields: ['smtpUsername', 'smtpPassword']
|
||||
dynamicLogicDefs: {
|
||||
fields: {
|
||||
smtpUsername: {
|
||||
visible: {
|
||||
conditionGroup: [
|
||||
{
|
||||
type: 'isNotEmpty',
|
||||
attribute: 'smtpServer',
|
||||
},
|
||||
{
|
||||
type: 'isTrue',
|
||||
attribute: 'smtpAuth',
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
smtpPassword: {
|
||||
visible: {
|
||||
conditionGroup: [
|
||||
{
|
||||
type: 'isNotEmpty',
|
||||
attribute: 'smtpServer',
|
||||
},
|
||||
{
|
||||
type: 'isTrue',
|
||||
attribute: 'smtpAuth',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
smtpPort: {
|
||||
visible: {
|
||||
conditionGroup: [
|
||||
{
|
||||
type: 'isNotEmpty',
|
||||
attribute: 'smtpServer',
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
smtpSecurity: {
|
||||
visible: {
|
||||
conditionGroup: [
|
||||
{
|
||||
type: 'isNotEmpty',
|
||||
attribute: 'smtpServer',
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
smtpAuth: {
|
||||
visible: {
|
||||
conditionGroup: [
|
||||
{
|
||||
type: 'isNotEmpty',
|
||||
attribute: 'smtpServer',
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
|
||||
@@ -136,36 +136,29 @@ define('views/detail', 'views/main', function (Dep) {
|
||||
},
|
||||
|
||||
actionFollow: function () {
|
||||
$el = this.$el.find('[data-action="follow"]');
|
||||
$el.addClass('disabled');
|
||||
$.ajax({
|
||||
url: this.model.name + '/' + this.model.id + '/subscription',
|
||||
type: 'PUT',
|
||||
success: function () {
|
||||
$el.remove();
|
||||
this.disableMenuItem('follow');
|
||||
|
||||
Espo.Ajax.putRequest(this.model.name + '/' + this.model.id + '/subscription')
|
||||
.then(function () {
|
||||
this.removeMenuItem('follow', true);
|
||||
this.model.set('isFollowed', true);
|
||||
}.bind(this),
|
||||
error: function () {
|
||||
$el.removeClass('disabled');
|
||||
}.bind(this)
|
||||
});
|
||||
}.bind(this))
|
||||
.fail(function () {
|
||||
this.enableMenuItem('follow');
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
actionUnfollow: function () {
|
||||
$el = this.$el.find('[data-action="unfollow"]');
|
||||
$el.addClass('disabled');
|
||||
$.ajax({
|
||||
url: this.model.name + '/' + this.model.id + '/subscription',
|
||||
type: 'DELETE',
|
||||
success: function () {
|
||||
$el.remove();
|
||||
this.model.set('isFollowed', false);
|
||||
}.bind(this),
|
||||
error: function () {
|
||||
$el.removeClass('disabled');
|
||||
}.bind(this)
|
||||
});
|
||||
this.disableMenuItem('unfollow');
|
||||
|
||||
Espo.Ajax.deleteRequest(this.model.name + '/' + this.model.id + '/subscription')
|
||||
.then(function () {
|
||||
this.removeMenuItem('unfollow', true);
|
||||
this.model.set('isFollowed', false);
|
||||
}.bind(this))
|
||||
.fail(function () {
|
||||
this.enableMenuItem('unfollow');
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getHeader: function () {
|
||||
|
||||
@@ -395,7 +395,12 @@ define('views/fields/array', ['views/fields/base', 'lib!Selectize'], function (D
|
||||
|
||||
if (this.displayAsList) {
|
||||
if (!list.length) return '';
|
||||
return '<div>' + list.join('</div><div>') + '</div>';
|
||||
var itemClassName = 'multi-enum-item-container';
|
||||
if (this.displayAsLabel) {
|
||||
itemClassName += ' multi-enum-item-label-container';
|
||||
}
|
||||
return '<div class="'+itemClassName+'">' +
|
||||
list.join('</div><div class="'+itemClassName+'">') + '</div>';
|
||||
} else if (this.displayAsLabel) {
|
||||
return list.join(' ');
|
||||
} else {
|
||||
|
||||
@@ -191,6 +191,10 @@ define('views/main', 'view', function (Dep) {
|
||||
if (!doNotReRender && this.isRendered()) {
|
||||
this.getView('header').reRender();
|
||||
}
|
||||
|
||||
if (doNotReRender && this.isRendered()) {
|
||||
this.$el.find('.header .header-buttons [data-name="'+name+'"]').remove();
|
||||
}
|
||||
},
|
||||
|
||||
disableMenuItem: function (name) {
|
||||
|
||||
@@ -394,14 +394,13 @@ Espo.define('views/modals/detail', 'views/modal', function (Dep) {
|
||||
} else {
|
||||
var initialCount = collection.length;
|
||||
|
||||
this.listenToOnce(collection, 'sync', function () {
|
||||
var model = collection.at(indexOfRecord);
|
||||
this.switchToModelByIndex(indexOfRecord);
|
||||
}, this);
|
||||
collection.fetch({
|
||||
more: true,
|
||||
remove: false,
|
||||
});
|
||||
}).then(function () {
|
||||
var model = collection.at(indexOfRecord);
|
||||
this.switchToModelByIndex(indexOfRecord);
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -975,6 +975,8 @@ define('views/record/detail', ['views/record/base', 'view-record-helper'], funct
|
||||
},
|
||||
|
||||
actionPrevious: function () {
|
||||
this.model.abortLastFetch();
|
||||
|
||||
var collection;
|
||||
if (!this.model.collection) {
|
||||
collection = this.collection;
|
||||
@@ -992,6 +994,8 @@ define('views/record/detail', ['views/record/base', 'view-record-helper'], funct
|
||||
},
|
||||
|
||||
actionNext: function () {
|
||||
this.model.abortLastFetch();
|
||||
|
||||
var collection;
|
||||
if (!this.model.collection) {
|
||||
collection = this.collection;
|
||||
@@ -1011,14 +1015,13 @@ define('views/record/detail', ['views/record/base', 'view-record-helper'], funct
|
||||
} else {
|
||||
var initialCount = collection.length;
|
||||
|
||||
this.listenToOnce(collection, 'sync', function () {
|
||||
var model = collection.at(indexOfRecord);
|
||||
this.switchToModelByIndex(indexOfRecord);
|
||||
}, this);
|
||||
collection.fetch({
|
||||
more: true,
|
||||
remove: false,
|
||||
});
|
||||
}).then(function () {
|
||||
var model = collection.at(indexOfRecord);
|
||||
this.switchToModelByIndex(indexOfRecord);
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1041,6 +1041,13 @@ ul.dropdown-menu > li.checkbox:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.multi-enum-item-label-container {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.multi-enum-item-label-container:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.filter > .form-group .field {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "espocrm",
|
||||
"version": "5.7.0",
|
||||
"version": "5.7.2",
|
||||
"description": "",
|
||||
"main": "index.php",
|
||||
"repository": {
|
||||
|
||||
@@ -320,4 +320,30 @@ class FormulaTest extends \tests\integration\Core\BaseTestCase
|
||||
|
||||
$this->assertTrue($result1 !== $result);
|
||||
}
|
||||
|
||||
public function testEntityGetLinkColumn()
|
||||
{
|
||||
$fm = $this->getContainer()->get('formulaManager');
|
||||
$em = $this->getContainer()->get('entityManager');
|
||||
|
||||
$lead = $em->createEntity('Lead', []);
|
||||
$targetList = $em->createEntity('TargetList', []);
|
||||
|
||||
$em->getRepository('Lead')->relate($lead, 'targetLists', $targetList->id, [
|
||||
'optedOut' => true,
|
||||
]);
|
||||
|
||||
$script = "entity\\getLinkColumn('targetLists', '{$targetList->id}', 'optedOut')";
|
||||
|
||||
$result = $fm->run($script, $lead);
|
||||
$this->assertTrue($result);
|
||||
|
||||
|
||||
$em->getRepository('Lead')->relate($lead, 'targetLists', $targetList->id, [
|
||||
'optedOut' => false,
|
||||
]);
|
||||
|
||||
$result = $fm->run($script, $lead);
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,6 +308,22 @@ class QueryTest extends \PHPUnit\Framework\TestCase
|
||||
$this->assertEquals($expectedSql, $sql);
|
||||
}
|
||||
|
||||
|
||||
public function testJoinOnlyMiddle()
|
||||
{
|
||||
$sql = $this->query->createSelectQuery('Post', [
|
||||
'select' => ['id'],
|
||||
'leftJoins' => [['tags', null, null, ['onlyMiddle' => true]]]
|
||||
]);
|
||||
|
||||
$expectedSql =
|
||||
"SELECT post.id AS `id` FROM `post` " .
|
||||
"LEFT JOIN `post_tag` AS `tagsMiddle` ON post.id = tagsMiddle.post_id AND tagsMiddle.deleted = '0' " .
|
||||
"WHERE post.deleted = '0'";
|
||||
|
||||
$this->assertEquals($expectedSql, $sql);
|
||||
}
|
||||
|
||||
public function testWhereNotValue1()
|
||||
{
|
||||
$sql = $this->query->createSelectQuery('Post', [
|
||||
|
||||
Reference in New Issue
Block a user