Merge branch 'hotfix/7.0.9'

This commit is contained in:
Yuri Kuznetsov
2021-11-12 12:44:19 +02:00
63 changed files with 1013 additions and 288 deletions
@@ -40,8 +40,19 @@ use Espo\Core\{
*/
class TemplateEntityTypeList
{
/**
* @var Acl
*/
protected $acl;
/**
* @var SelectBuilderFactory
*/
protected $selectBuilderFactory;
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(Acl $acl, SelectBuilderFactory $selectBuilderFactory, EntityManager $entityManager)
@@ -51,7 +62,7 @@ class TemplateEntityTypeList
$this->entityManager = $entityManager;
}
public function get() : array
public function get(): array
{
if (!$this->acl->checkScope('Template')) {
return [];
@@ -69,7 +80,7 @@ class TemplateEntityTypeList
->build();
$templateCollection = $this->entityManager
->getRepository('Template')
->getRDBRepository('Template')
->clone($query)
->find();
@@ -40,8 +40,14 @@ use DateTimeZone;
class CheckNewVersion implements JobDataLess
{
/**
* @var Config
*/
protected $config;
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(Config $config, EntityManager $entityManager)
@@ -44,12 +44,16 @@ use Espo\{
class FromEquals implements ItemConverter
{
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var EmailAddressHelper
*/
protected $emailAddressHelper;
protected $randomStringGenerator;
public function __construct(
EntityManager $entityManager,
EmailAddressHelper $emailAddressHelper
@@ -45,10 +45,19 @@ use Espo\{
class InFolder implements ItemConverter
{
/**
* @var User
*/
protected $user;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var JoinHelper
*/
protected $joinHelper;
public function __construct(User $user, EntityManager $entityManager, JoinHelper $joinHelper)
@@ -186,7 +195,7 @@ class InFolder implements ItemConverter
protected function getEmailAddressIdList(): array
{
$emailAddressList = $this->entityManager
->getRepository('User')
->getRDBRepository('User')
->getRelation($this->user, 'emailAddresses')
->select(['id'])
->find();
@@ -194,7 +203,7 @@ class InFolder implements ItemConverter
$emailAddressIdList = [];
foreach ($emailAddressList as $emailAddress) {
$emailAddressIdList[] = $emailAddress->id;
$emailAddressIdList[] = $emailAddress->getId();
}
return $emailAddressIdList;
+29 -8
View File
@@ -33,8 +33,9 @@ use Espo\ORM\Entity;
use Espo\Entities\User;
use Espo\ORM\EntityManager;
use Espo\Core\{
ORM\EntityManager,
Acl,
Acl\GlobalRestricton,
Acl\OwnerUserFieldProvider,
@@ -97,18 +98,39 @@ class AclManager
Table::ACTION_STREAM => AccessStreamChecker::class,
];
/**
* @var AccessCheckerFactory|\Espo\Core\Portal\Acl\AccessChecker\AccessCheckerFactory
*/
protected $accessCheckerFactory;
/**
* @var OwnershipCheckerFactory|\Espo\Core\Portal\Acl\OwnershipChecker\OwnershipCheckerFactory
*/
protected $ownershipCheckerFactory;
protected $tableFactory;
/**
* @var TableFactory
*/
private $tableFactory;
protected $mapFactory;
/**
* @var MapFactory
*/
private $mapFactory;
/**
* @var GlobalRestricton
*/
protected $globalRestricton;
/**
* @var OwnerUserFieldProvider
*/
protected $ownerUserFieldProvider;
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(
@@ -582,11 +604,10 @@ class AclManager
if ($permission === Table::LEVEL_TEAM) {
$teamIdList = $user->getLinkMultipleIdList('teams');
if (
!$this->entityManager
->getRepository('User')
->checkBelongsToAnyOfTeams($userId, $teamIdList)
) {
/** @var \Espo\Repositories\User $userRepository */
$userRepository = $this->entityManager->getRepository('User');
if (!$userRepository->checkBelongsToAnyOfTeams($userId, $teamIdList)) {
return false;
}
}
@@ -52,17 +52,17 @@ use Espo\{
class ConvertCurrency implements Action
{
protected $acl;
private $acl;
protected $entityManager;
private $entityManager;
protected $fieldUtil;
private $fieldUtil;
protected $metadata;
private $metadata;
protected $configDataProvider;
private $configDataProvider;
protected $currencyConverter;
private $currencyConverter;
public function __construct(
Acl $acl,
@@ -125,7 +125,10 @@ class ConvertCurrency implements Action
}
protected function convertEntity(
Entity $entity, array $fieldList, string $targetCurrency, CurrencyRates $rates
Entity $entity,
array $fieldList,
string $targetCurrency,
CurrencyRates $rates
) {
foreach ($fieldList as $field) {
$amount = $entity->get($field);
@@ -96,6 +96,9 @@ class RecordBase extends Base implements Di\EntityManagerAware, Di\InjectableFac
*/
protected $recordServiceContainer;
/**
* @var Config
*/
protected $config;
/**
@@ -103,11 +106,13 @@ class RecordBase extends Base implements Di\EntityManagerAware, Di\InjectableFac
*/
protected $user;
/**
* @var Acl
*/
protected $acl;
/**
* @deprecated
*
* @var EntityManager
*/
protected $entityManager;
@@ -52,10 +52,19 @@ class ClientManager
*/
protected $entityManager;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var Config
*/
protected $config;
/**
* @var InjectableFactory|null
*/
protected $injectableFactory = null;
protected $clientMap = [];
@@ -53,18 +53,39 @@ use Espo\{
class MassConvertCurrency implements MassAction
{
/**
* @var QueryBuilder
*/
protected $queryBuilder;
/**
* @var Acl
*/
protected $acl;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var FieldUtil
*/
protected $fieldUtil;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var CurrencyConfigDataProvider
*/
protected $configDataProvider;
/**
* @var CurrencyConverter
*/
protected $currencyConverter;
public function __construct(
@@ -128,7 +149,7 @@ class MassConvertCurrency implements MassAction
$query = $this->queryBuilder->build($params);
$collection = $this->entityManager
->getRepository($entityType)
->getRDBRepository($entityType)
->clone($query)
->sth()
->find();
@@ -144,7 +165,7 @@ class MassConvertCurrency implements MassAction
$this->convertEntity($entity, $fieldList, $targetCurrency, $rates);
$ids[] = $entity->id;
$ids[] = $entity->getId();
$count++;
}
@@ -43,10 +43,19 @@ use Espo\Core\{
class MassDelete implements MassAction
{
/**
* @var QueryBuilder
*/
protected $queryBuilder;
/**
* @var Acl
*/
protected $acl;
/**
* @var RecordServiceContainer
*/
protected $recordServiceContainer;
/**
@@ -39,16 +39,23 @@ use Espo\Core\{
Exceptions\Forbidden,
};
use Espo\{
Entities\User,
};
use Espo\Entities\User;
class MassRecalculateFormula implements MassAction
{
/**
* @var QueryBuilder
*/
protected $queryBuilder;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var User
*/
protected $user;
public function __construct(
@@ -72,7 +79,7 @@ class MassRecalculateFormula implements MassAction
$query = $this->queryBuilder->build($params);
$collection = $this->entityManager
->getRepository($entityType)
->getRDBRepository($entityType)
->clone($query)
->sth()
->find();
@@ -84,7 +91,7 @@ class MassRecalculateFormula implements MassAction
foreach ($collection as $entity) {
$this->entityManager->saveEntity($entity);
$ids[] = $entity->id;
$ids[] = $entity->getId();
$count++;
}
@@ -50,10 +50,19 @@ use stdClass;
class MassUpdate implements MassAction
{
/**
* @var QueryBuilder
*/
protected $queryBuilder;
/**
* @var Acl
*/
protected $acl;
/**
* @var RecordServiceContainer
*/
protected $recordServiceContainer;
/**
@@ -61,6 +70,9 @@ class MassUpdate implements MassAction
*/
protected $entityManager;
/**
* @var FieldUtil
*/
protected $fieldUtil;
public function __construct(
@@ -41,10 +41,19 @@ use Espo\Core\Notification\AssignmentNotificator\Params;
class DefaultAssignmentNotificator implements AssignmentNotificator
{
/**
* @var User
*/
protected $user;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var UserEnabledChecker
*/
protected $userChecker;
public function __construct(User $user, EntityManager $entityManager, UserEnabledChecker $userChecker)
@@ -145,6 +145,10 @@ class EntityManagerFactory
->withSslCipher($config->get('database.sslCipher'))
->withSslVerifyDisabled($config->get('database.sslVerifyDisabled') ?? false);
if (!$databaseParams->getName()) {
throw new RuntimeException('No database name specified.');
}
if (!$databaseParams->getPlatform()) {
$driver = $config->get('database.driver');
@@ -48,10 +48,19 @@ class RepositoryFactory implements RepositoryFactoryInterface
{
protected $defaultClassName = DatabaseRepository::class;
/**
* @var EntityFactoryInteface
*/
protected $entityFactory;
/**
* @var InjectableFactory
*/
protected $injectableFactory;
/**
* @var ClassFinder
*/
protected $classFinder;
public function __construct(
+25 -7
View File
@@ -58,16 +58,34 @@ class Recovery
const REQUEST_LIFETIME = '3 hours';
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var Config
*/
protected $config;
/**
* @var EmailSender
*/
protected $emailSender;
/**
* @var HtmlizerFactory
*/
protected $htmlizerFactory;
/**
* @var TemplateFileManager
*/
protected $templateFileManager;
/**
* @var Log
*/
private $log;
public function __construct(
@@ -96,7 +114,7 @@ class Recovery
}
$request = $em
->getRepository('PasswordChangeRequest')
->getRDBRepository('PasswordChangeRequest')
->where([
'requestId' => $id,
])
@@ -119,7 +137,7 @@ class Recovery
$em = $this->entityManager;
$request = $em
->getRepository('PasswordChangeRequest')
->getRDBRepository('PasswordChangeRequest')
->where([
'requestId' => $id,
])
@@ -142,7 +160,7 @@ class Recovery
}
$user = $em
->getRepository('User')
->getRDBRepository('User')
->where([
'userName' => $userName,
'emailAddress' => $emailAddress,
@@ -196,9 +214,9 @@ class Recovery
}
$passwordChangeRequest = $em
->getRepository('PasswordChangeRequest')
->getRDBRepository('PasswordChangeRequest')
->where([
'userId' => $user->id,
'userId' => $user->getId(),
])
->findOne();
@@ -293,12 +311,12 @@ class Recovery
$siteUrl = $config->getSiteUrl();
if ($user->isPortal()) {
$portal = $em->getRepository('Portal')
$portal = $em->getRDBRepository('Portal')
->distinct()
->join('users')
->where([
'isActive' => true,
'users.id' => $user->id,
'users.id' => $user->getId(),
])
->findOne();
+19 -7
View File
@@ -66,11 +66,21 @@ class AclManager extends InternalAclManager
private $portal = null;
/**
* @var TableFactory
*/
private $portalTableFactory;
/**
* @var MapFactory
*/
private $portalMapFactory;
public function __construct(
AccessCheckerFactory $accessCheckerFactory,
OwnershipCheckerFactory $ownershipCheckerFactory,
TableFactory $tableFactory,
MapFactory $mapFactory,
TableFactory $portalTableFactory,
MapFactory $portalMapFactory,
GlobalRestricton $globalRestricton,
OwnerUserFieldProvider $ownerUserFieldProvider,
EntityManager $entityManager,
@@ -78,8 +88,8 @@ class AclManager extends InternalAclManager
) {
$this->accessCheckerFactory = $accessCheckerFactory;
$this->ownershipCheckerFactory = $ownershipCheckerFactory;
$this->tableFactory = $tableFactory;
$this->mapFactory = $mapFactory;
$this->portalTableFactory = $portalTableFactory;
$this->portalMapFactory = $portalMapFactory;
$this->globalRestricton = $globalRestricton;
$this->ownerUserFieldProvider = $ownerUserFieldProvider;
$this->entityManager = $entityManager;
@@ -109,7 +119,7 @@ class AclManager extends InternalAclManager
}
if (!array_key_exists($key, $this->tableHashMap)) {
$this->tableHashMap[$key] = $this->tableFactory->create($user, $this->getPortal());
$this->tableHashMap[$key] = $this->portalTableFactory->create($user, $this->getPortal());
}
return $this->tableHashMap[$key];
@@ -124,8 +134,10 @@ class AclManager extends InternalAclManager
}
if (!array_key_exists($key, $this->mapHashMap)) {
$this->mapHashMap[$key] = $this->mapFactory
->create($user, $this->getTable($user), $this->getPortal());
/** @var Table */
$table = $this->getTable($user);
$this->mapHashMap[$key] = $this->portalMapFactory->create($user, $table, $this->getPortal());
}
return $this->mapHashMap[$key];
@@ -29,9 +29,13 @@
namespace Espo\Core\Select\Applier\Appliers;
use Espo\Core\Acl;
use Espo\Core\AclManager;
use Espo\Core\Select\OrmSelectBuilder;
use Espo\Core\{
Exceptions\Error,
AclManager,
Select\SelectManager,
Select\AccessControl\FilterFactory as AccessControlFilterFactory,
Select\AccessControl\FilterResolverFactory as AccessControlFilterResolverFactory,
@@ -44,18 +48,36 @@ use Espo\{
class AccessControlFilter
{
/**
* @var Acl
*/
protected $acl;
protected $entityType;
/**
* @var User
*/
protected $user;
/**
* @var AccessControlFilterFactory
*/
protected $accessControlFilterFactory;
/**
* @var AccessControlFilterResolverFactory
*/
protected $accessControlFilterResolverFactory;
/**
* @var AclManager
*/
protected $aclManager;
/**
* @var SelectManager
*/
protected $selectManager;
public function __construct(
@@ -79,7 +101,10 @@ class AccessControlFilter
public function apply(QueryBuilder $queryBuilder): void
{
// For backward compatibility.
if ($this->selectManager->hasInheritedAccessMethod()) {
if (
$this->selectManager->hasInheritedAccessMethod() &&
$queryBuilder instanceof OrmSelectBuilder
) {
$this->selectManager->applyAccessToQueryBuilder($queryBuilder);
return;
@@ -97,7 +122,10 @@ class AccessControlFilter
}
// For backward compatibility.
if ($this->selectManager->hasInheritedAccessFilterMethod($filterName)) {
if (
$this->selectManager->hasInheritedAccessFilterMethod($filterName) &&
$queryBuilder instanceof OrmSelectBuilder
) {
$this->selectManager->applyAccessFilterToQueryBuilder($queryBuilder, $filterName);
return;
@@ -29,6 +29,8 @@
namespace Espo\Core\Select\Applier\Appliers;
use Espo\Core\Select\OrmSelectBuilder;
use Espo\Core\{
Exceptions\Error,
Select\SelectManager,
@@ -46,10 +48,19 @@ class BoolFilterList
{
protected $entityType;
/**
* @var User
*/
protected $user;
/**
* @var SelectManager
*/
protected $selectManager;
/**
* @var BoolFilterFactory
*/
protected $boolFilterFactory;
public function __construct(
@@ -86,13 +97,16 @@ class BoolFilterList
if ($this->boolFilterFactory->has($this->entityType, $filterName)) {
$filter = $this->boolFilterFactory->create($this->entityType, $this->user, $filterName);
$whereItem = $filter->apply($queryBuilder, $orGroupBuilder);
$filter->apply($queryBuilder, $orGroupBuilder);
return;
}
// For backward compatibility.
if ($this->selectManager->hasBoolFilter($filterName)) {
if (
$this->selectManager->hasBoolFilter($filterName) &&
$queryBuilder instanceof OrmSelectBuilder
) {
$rawWhereClause = $this->selectManager->applyBoolFilterToQueryBuilder($queryBuilder, $filterName);
$whereItem = WhereClause::fromRaw($rawWhereClause);
@@ -50,10 +50,19 @@ class Order
{
protected $entityType;
/**
* @var User
*/
protected $user;
/**
* @var MetadataProvider
*/
protected $metadataProvider;
/**
* @var ItemConverterFactory
*/
protected $itemConverterFactory;
public function __construct(
@@ -80,10 +89,8 @@ class Order
if ($params->forbidComplexExpressions() && $orderBy) {
if (
!is_string($orderBy)
||
strpos($orderBy, '.') !== false
||
!is_string($orderBy) ||
strpos($orderBy, '.') !== false ||
strpos($orderBy, ':') !== false
) {
throw new Forbidden("Complex expressions are forbidden in 'orderBy'.");
@@ -112,10 +119,10 @@ class Order
if (!$order) {
$order = $this->metadataProvider->getDefaultOrder($this->entityType);
if ($order === true || strtolower($order) === 'desc') {
if (strtolower($order) === 'desc') {
$order = SearchParams::ORDER_DESC;
}
else if ($order === false || strtolower($order) === 'asc') {
else if (strtolower($order) === 'asc') {
$order = SearchParams::ORDER_ASC;
}
else if ($order !== null) {
@@ -29,6 +29,8 @@
namespace Espo\Core\Select\Applier\Appliers;
use Espo\Core\Select\OrmSelectBuilder;
use Espo\Core\{
Exceptions\Error,
Select\SelectManager,
@@ -44,10 +46,19 @@ class PrimaryFilter
{
protected $entityType;
/**
* @var User
*/
protected $user;
/**
* @var SelectManager
*/
protected $selectManager;
/**
* @var FilterFactory
*/
protected $primaryFilterFactory;
public function __construct(
@@ -73,7 +84,10 @@ class PrimaryFilter
}
// For backward compatibility.
if ($this->selectManager->hasPrimaryFilter($filterName)) {
if (
$this->selectManager->hasPrimaryFilter($filterName) &&
$queryBuilder instanceof OrmSelectBuilder
) {
$this->selectManager->applyPrimaryFilterToQueryBuilder($queryBuilder, $filterName);
return;
@@ -57,10 +57,19 @@ class Select
protected $entityType;
/**
* @var User
*/
protected $user;
/**
* @var FieldUtil
*/
protected $fieldUtil;
/**
* @var MetadataProvider
*/
protected $metadataProvider;
public function __construct(
@@ -61,12 +61,24 @@ class TextFilter
private $entityType;
/**
* @var User
*/
private $user;
/**
* @var MetadataProvider
*/
private $metadataProvider;
/**
* @var FullTextSearchDataComposerFactory
*/
private $fullTextSearchDataComposerFactory;
/**
* @var FilterFactory
*/
private $filterFactory;
public function __construct(
@@ -45,10 +45,19 @@ class Where
{
protected $entityType;
/**
* @var User
*/
protected $user;
/**
* @var ConverterFactory
*/
protected $converterFactory;
/**
* @var CheckerFactory
*/
protected $checkerFactory;
public function __construct(
@@ -39,8 +39,14 @@ class FullTextSearchDataComposer
protected $entityType;
/**
* @var Config
*/
protected $config;
/**
* @var MetadataProvider
*/
protected $metadataProvider;
public function __construct(
@@ -45,28 +45,24 @@ use Espo\{
*/
class Converter
{
protected $entityType;
private $entityType;
protected $user;
private $itemConverter;
protected $itemConverter;
private $scanner;
protected $scanner;
private $randomStringGenerator;
protected $randomStringGenerator;
protected $ormDefs;
private $ormDefs;
public function __construct(
string $entityType,
User $user,
ItemConverter $itemConverter,
Scanner $scanner,
RandomStringGenerator $randomStringGenerator,
ORMDefs $ormDefs
) {
$this->entityType = $entityType;
$this->user = $user;
$this->itemConverter = $itemConverter;
$this->scanner = $scanner;
$this->randomStringGenerator = $randomStringGenerator;
@@ -94,7 +90,7 @@ class Converter
return WhereClause::fromRaw($whereClause);
}
protected function itemToList(Item $item): array
private function itemToList(Item $item): array
{
if ($item->getType() !== 'and') {
return [
@@ -111,7 +107,7 @@ class Converter
return $list;
}
protected function processItem(QueryBuilder $queryBuilder, Item $item): ?array
private function processItem(QueryBuilder $queryBuilder, Item $item): ?array
{
$type = $item->getType();
$attribute = $item->getAttribute();
@@ -136,7 +132,7 @@ class Converter
return $this->itemConverter->convert($queryBuilder, $item)->getRaw();
}
protected function applyInCategory(QueryBuilder $queryBuilder, string $attribute, $value): array
private function applyInCategory(QueryBuilder $queryBuilder, string $attribute, $value): array
{
$link = $attribute;
@@ -197,7 +193,7 @@ class Converter
throw new Error("Not supported link '{$link}' in where item.");
}
protected function applyIsUserFromTeams(QueryBuilder $queryBuilder, string $attribute, $value): array
private function applyIsUserFromTeams(QueryBuilder $queryBuilder, string $attribute, $value): array
{
$link = $attribute;
@@ -43,6 +43,9 @@ use DateInterval;
*/
class DateTimeItemTransformer
{
/**
* @var User
*/
protected $user;
private $config;
@@ -53,22 +53,49 @@ class ItemGeneralConverter implements ItemConverter
{
protected $entityType;
/**
* @var User
*/
protected $user;
/**
* @var DateTimeItemTransformer
*/
protected $dateTimeItemTransformer;
/**
* @var Scanner
*/
protected $scanner;
/**
* @var ItemConverterFactory
*/
protected $itemConverterFactory;
/**
* @var RandomStringGenerator
*/
protected $randomStringGenerator;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var ORMDefs
*/
protected $ormDefs;
/**
* @var Config
*/
protected $config;
/**
* @var Metadata
*/
protected $metadata;
public function __construct(
+105 -67
View File
@@ -39,8 +39,15 @@ use Doctrine\DBAL\{
Platforms\AbstractPlatform as DbalPlatform,
};
use Espo\ORM\{
DatabaseParams,
PDO\DefaultPDOProvider,
PDO\Options as PdoOptions,
};
use PDO;
use ReflectionClass;
use RuntimeException;
class Helper
{
@@ -50,6 +57,11 @@ class Helper
private $pdoConnection;
private $driverPlatformMap = [
'pdo_mysql' => 'Mysql',
'mysqli' => 'Mysql',
];
protected $dbalDrivers = [
'mysqli' => 'Doctrine\\DBAL\\Driver\\Mysqli\\Driver',
'pdo_mysql' => 'Espo\\Core\\Utils\\Database\\DBAL\\Driver\\PDO\\MySQL\\Driver',
@@ -95,46 +107,57 @@ class Helper
$this->pdoConnection = $pdoConnection;
}
public function createDbalConnection(array $params = null)
public function createDbalConnection(array $params = [])
{
if (!isset($params)) {
$config = $this->config;
if ($config) {
$params = $config->get('database');
}
if (empty($params) && isset($this->config)) {
$params = $this->config->get('database');
}
if (empty($params['dbname']) || empty($params['user'])) {
return null;
if (empty($params)) {
throw new RuntimeException('Params cannot be empty for Dbal connection.');
}
$driverName = isset($params['driver']) ? $params['driver'] : 'pdo_mysql';
$databaseParams = $this->createDatabaseParams($params);
unset($params['driver']);
if (!isset($this->dbalDrivers[$driverName])) {
throw new Error('Unknown database driver.');
}
$driverClass = $this->dbalDrivers[$driverName];
if (!class_exists($driverClass)) {
throw new Error('Unknown database class.');
}
$driver = new $driverClass();
$driver = $this->createDbalDriver($params);
$version = $this->getFullDatabaseVersion();
$platform = $driver->createDatabasePlatformForVersion($version);
$params['platform'] = $this->createDbalPlatform($platform);
return new DbalConnection($params, $driver);
return new DbalConnection(
[
'platform' => $this->createDbalPlatform($platform),
'host' => $databaseParams->getHost(),
'port' => $databaseParams->getPort(),
'dbname' => $databaseParams->getName(),
'charset' => $databaseParams->getCharset(),
'user' => $databaseParams->getUsername(),
'password' => $databaseParams->getPassword(),
'driverOptions' => PdoOptions::getOptionsFromDatabaseParams($databaseParams),
],
$driver
);
}
protected function createDbalPlatform(DbalPlatform $platform)
private function createDbalDriver(array $params)
{
$driverName = $params['driver'] ?? 'pdo_mysql';
if (!isset($this->dbalDrivers[$driverName])) {
throw new RuntimeException('Unknown database driver.');
}
$driverClass = $this->dbalDrivers[$driverName];
if (!class_exists($driverClass)) {
throw new RuntimeException('Unknown database class.');
}
return new $driverClass();
}
private function createDbalPlatform(DbalPlatform $platform)
{
$reflect = new ReflectionClass($platform);
@@ -155,51 +178,65 @@ class Helper
* @param array $params
* @return PDO|null
*/
public function createPdoConnection(array $params = null)
public function createPdoConnection(array $params = [])
{
if (!isset($params)) {
$config = $this->config;
$defaultParams = [
'driver' => 'pdo_mysql',
];
if ($config) {
$params = $config->get('database');
if (isset($this->config) && $this->config instanceof Config) {
$defaultParams = array_merge(
$defaultParams,
$this->config->get('database')
);
}
$params = array_merge(
$defaultParams,
$params
);
$pdoProvider = new DefaultPDOProvider(
$this->createDatabaseParams($params)
);
return $pdoProvider->get();
}
private function createDatabaseParams(array $params): DatabaseParams
{
$databaseParams = DatabaseParams::create()
->withHost($params['host'] ?? null)
->withPort(isset($params['host']) ? (int) $params['host'] : null)
->withName($params['dbname'] ?? null)
->withUsername($params['user'] ?? null)
->withPassword($params['password'] ?? null)
->withCharset($params['charset'] ?? 'utf8')
->withPlatform($params['platform'] ?? null)
->withSslCa($params['sslCA'] ?? null)
->withSslCert($params['sslCert'] ?? null)
->withSslKey($params['sslKey'] ?? null)
->withSslCaPath($params['sslCAPath'] ?? null)
->withSslCipher($params['sslCipher'] ?? null)
->withSslVerifyDisabled($params['sslVerifyDisabled'] ?? false);
if (!$databaseParams->getPlatform()) {
$driver = $params['driver'] ?? null;
if (!$driver) {
throw new RuntimeException('No database driver specified.');
}
$platform = $this->driverPlatformMap[$driver] ?? null;
if (!$platform) {
throw new RuntimeException("Database driver '{$driver}' is not supported.");
}
$databaseParams = $databaseParams->withPlatform($platform);
}
if (empty($params)) {
return null;
}
$platform = !empty($params['platform']) ? strtolower($params['platform']) : 'mysql';
$port = empty($params['port']) ? '' : ';port=' . $params['port'];
$dbname = empty($params['dbname']) ? '' : ';dbname=' . $params['dbname'];
$options = [];
if (isset($params['sslCA'])) {
$options[PDO::MYSQL_ATTR_SSL_CA] = $params['sslCA'];
}
if (isset($params['sslCert'])) {
$options[PDO::MYSQL_ATTR_SSL_CERT] = $params['sslCert'];
}
if (isset($params['sslKey'])) {
$options[PDO::MYSQL_ATTR_SSL_KEY] = $params['sslKey'];
}
if (isset($params['sslCAPath'])) {
$options[PDO::MYSQL_ATTR_SSL_CAPATH] = $params['sslCAPath'];
}
if (isset($params['sslCipher'])) {
$options[PDO::MYSQL_ATTR_SSL_CIPHER] = $params['sslCipher'];
}
$dsn = $platform . ':host='.$params['host'].$port.$dbname;
$dbh = new PDO($dsn, $params['user'], $params['password'], $options);
return $dbh;
return $databaseParams;
}
/**
@@ -304,6 +341,7 @@ class Helper
protected function getTableEngine($tableName = null, $default = null)
{
$connection = $this->getPdoConnection();
if (!$connection) {
return $default;
}
@@ -38,16 +38,34 @@ use Espo\Core\{
abstract class BaseRebuildActions
{
/**
* @var Metadata
*/
protected $metadata;
/**
* @var Config
*/
protected $config;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var Log
*/
protected $log;
/**
* @var \Doctrine\DBAL\Schema\Schema|null
*/
protected $currentSchema = null;
/**
* @var \Doctrine\DBAL\Schema\Schema|null
*/
protected $metadataSchema = null;
public function __construct(
@@ -62,17 +80,17 @@ abstract class BaseRebuildActions
$this->log = $log;
}
protected function getEntityManager()
protected function getEntityManager(): EntityManager
{
return $this->entityManager;
}
protected function getConfig()
protected function getConfig(): Config
{
return $this->config;
}
protected function getMetadata()
protected function getMetadata(): Metadata
{
return $this->metadata;
}
@@ -87,12 +105,12 @@ abstract class BaseRebuildActions
$this->metadataSchema = $metadataSchema;
}
protected function getCurrentSchema()
protected function getCurrentSchema(): ?\Doctrine\DBAL\Schema\Schema
{
return $this->currentSchema;
}
protected function getMetadataSchema()
protected function getMetadataSchema(): ?\Doctrine\DBAL\Schema\Schema
{
return $this->metadataSchema;
}
@@ -117,7 +117,8 @@ class SystemRequirements
$databaseTypeName = 'Mysql';
$databaseHelper = $this->databaseHelper;
$databaseParams = isset($additionalData['database']) ? $additionalData['database'] : null;
$databaseParams = $additionalData['database'] ?? [];
$pdoConnection = $databaseHelper->createPdoConnection($databaseParams);
if ($pdoConnection) {
@@ -254,7 +255,7 @@ class SystemRequirements
$databaseHelper = $this->databaseHelper;
$databaseParams = isset($additionalData['database']) ? $additionalData['database'] : null;
$databaseParams = $additionalData['database'] ?? [];
$pdo = $databaseHelper->createPdoConnection($databaseParams);
@@ -46,10 +46,13 @@ class ChangePassword implements EntryPoint
{
use NoAuth;
/** @var Config */
protected $config;
/** @var ClientManager */
protected $clientManager;
/** @var EntityManager */
protected $entityManager;
public function __construct(Config $config, ClientManager $clientManager, EntityManager $entityManager)
@@ -68,7 +71,7 @@ class ChangePassword implements EntryPoint
}
$passwordChangeRequest = $this->entityManager
->getRepository('PasswordChangeRequest')
->getRDBRepository('PasswordChangeRequest')
->where([
'requestId' => $requestId,
])
@@ -54,10 +54,13 @@ class Download implements EntryPoint
'application/msexcel',
];
/** @var FileStorageManager */
protected $fileStorageManager;
/** @var Acl */
protected $acl;
/** @var EntityManager */
protected $entityManager;
public function __construct(FileStorageManager $fileStorageManager, Acl $acl, EntityManager $entityManager)
+15 -1
View File
@@ -29,6 +29,8 @@
namespace Espo\EntryPoints;
use Espo\Repositories\Attachment as AttachmentRepository;
use Espo\Core\{
Exceptions\NotFound,
Exceptions\NotFoundSilent,
@@ -54,16 +56,22 @@ class Image implements EntryPoint
protected $allowedFieldList = null;
/** @var FileStorageManager */
protected $fileStorageManager;
/** @var Acl */
protected $acl;
/** @var EntityManager */
protected $entityManager;
/** @var FileManager */
protected $fileManager;
/** @var Config */
protected $config;
/** @var Metadata */
private $metadata;
public function __construct(
@@ -172,7 +180,7 @@ class Image implements EntryPoint
return $this->fileManager->getContents($cacheFilePath);
}
$filePath = $this->entityManager->getRepository('Attachment')->getFilePath($attachment);
$filePath = $this->getAttachmentRepository()->getFilePath($attachment);
if (!$this->fileManager->isFile($filePath)) {
throw new NotFound();
@@ -358,4 +366,10 @@ class Image implements EntryPoint
{
return $this->metadata->get(['app', 'image', 'sizes']) ?? [];
}
protected function getAttachmentRepository(): AttachmentRepository
{
/** @var AttachmentRepository */
return $this->entityManager->getRepository(Attachment::ENTITY_TYPE);
}
}
@@ -37,8 +37,14 @@ use Espo\Entities\Team;
class LeastBusy
{
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var Metadata
*/
protected $metadata;
public function __construct(EntityManager $entityManager, Metadata $metadata)
@@ -36,6 +36,9 @@ use Espo\ORM\EntityManager;
class RoundRobin
{
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(EntityManager $entityManager)
@@ -29,11 +29,19 @@
namespace Espo\Modules\Crm\Business\Distribution\Lead;
use Espo\ORM\EntityManager;
use Espo\Entities\User;
use Espo\Entities\Team;
class LeastBusy
{
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct($entityManager)
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
@@ -43,39 +51,52 @@ class LeastBusy
return $this->entityManager;
}
/**
* @param Team $team
* @param ?string $targetUserPosition
* @return User|null
*/
public function getUser($team, $targetUserPosition = null)
{
$params = array();
$params = [];
if (!empty($targetUserPosition)) {
$params['additionalColumnsConditions'] = array(
$params['additionalColumnsConditions'] = [
'role' => $targetUserPosition
);
];
}
$userList = $team->get('users', $params);
if (count($userList) == 0) {
return false;
return null;
}
$countHash = array();
$countHash = [];
foreach ($userList as $user) {
$where = array(
$where = [
'assignedUserId' => $user->id,
'status<>' => ['Converted', 'Recycled', 'Dead']
);
$count = $this->getEntityManager()->getRepository('Lead')->where($where)->count();
$countHash[$user->id] = $count;
];
$count = $this->entityManager
->getRDBRepository('Lead')
->where($where)
->count();
$countHash[$user->getId()] = $count;
}
$foundUserId = false;
$min = false;
foreach ($countHash as $userId => $count) {
if ($min === false) {
$min = $count;
$foundUserId = $userId;
} else {
}
else {
if ($count < $min) {
$min = $count;
$foundUserId = $userId;
@@ -84,8 +105,10 @@ class LeastBusy
}
if ($foundUserId !== false) {
return $this->getEntityManager()->getEntity('User', $foundUserId);
return $this->entityManager->getEntity('User', $foundUserId);
}
return null;
}
}
@@ -29,49 +29,64 @@
namespace Espo\Modules\Crm\Business\Distribution\Lead;
use Espo\ORM\EntityManager;
use Espo\Entities\User;
use Espo\Entities\Team;
class RoundRobin
{
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct($entityManager)
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
protected function getEntityManager()
{
return $this->entityManager;
}
/**
* @param Team $team
* @param ?string $targetUserPosition
* @return User|null
*/
public function getUser($team, $targetUserPosition = null)
{
$params = array();
$params = [];
if (!empty($targetUserPosition)) {
$params['additionalColumnsConditions'] = array(
$params['additionalColumnsConditions'] = [
'role' => $targetUserPosition
);
];
}
$userList = $team->get('users', $params);
if (count($userList) == 0) {
return false;
return null;
}
$userIdList = array();
$userIdList = [];
foreach ($userList as $user) {
$userIdList[] = $user->id;
$userIdList[] = $user->getId();
}
$lead = $this->getEntityManager()->getRepository('Lead')->where(array(
'assignedUserId' => $userIdList
))->order('createdAt', 'DESC')->findOne();
$lead = $this->entityManager
->getRDBRepository('Lead')
->where([
'assignedUserId' => $userIdList
])
->order('createdAt', 'DESC')
->findOne();
if (empty($lead)) {
$num = 0;
} else {
}
else {
$num = array_search($lead->get('assignedUserId'), $userIdList);
if ($num === false || $num == count($userIdList) - 1) {
$num = 0;
} else {
@@ -79,7 +94,6 @@ class RoundRobin
}
}
return $this->getEntityManager()->getEntity('User', $userIdList[$num]);
return $this->entityManager->getEntity('User', $userIdList[$num]);
}
}
@@ -30,6 +30,7 @@
namespace Espo\Modules\Crm\Business\Reminder;
use Espo\ORM\Entity;
use Espo\Core\ORM\Entity as CoreEntity;
use Espo\Core\Utils\Util;
@@ -44,18 +45,34 @@ use Espo\Core\{
class EmailReminder
{
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var EmailSender
*/
protected $emailSender;
/**
* @var Config
*/
protected $config;
protected $dateTime;
/**
* @var TemplateFileManager
*/
protected $templateFileManager;
/**
* @var Language
*/
protected $language;
/**
* @var HtmlizerFactory
*/
protected $htmlizerFactory;
public function __construct(
@@ -89,6 +106,10 @@ class EmailReminder
return;
}
if (!$entity instanceof CoreEntity) {
return;
}
if ($entity->hasLinkMultipleField('users')) {
$entity->loadLinkMultipleField('users', ['status' => 'acceptanceStatus']);
$status = $entity->getLinkMultipleColumn('users', 'status', $user->getId());
@@ -45,8 +45,14 @@ class CampaignTrackOpened implements EntryPoint
{
use NoAuth;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var Service
*/
protected $service;
public function __construct(EntityManager $entityManager, Service $service)
@@ -30,6 +30,7 @@
namespace Espo\Modules\Crm\EntryPoints;
use Espo\Modules\Crm\Services\Campaign as Service;
use Espo\Repositories\EmailAddress as EmailAddressRepository;
use Espo\{
Modules\Crm\Entities\EmailQueueItem,
@@ -54,16 +55,34 @@ class CampaignUrl implements EntryPoint
{
use NoAuth;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var Service
*/
protected $service;
/**
* @var Hasher
*/
protected $hasher;
/**
* @var HookManager
*/
protected $hookManager;
/**
* @var ClientManager
*/
protected $clientManager;
/**
* @var Metadata
*/
protected $metadata;
public function __construct(
@@ -180,7 +199,7 @@ class CampaignUrl implements EntryPoint
throw new NotFoundSilent();
}
$eaRepository = $this->entityManager->getRepository('EmailAddress');
$eaRepository = $this->getEmailAddressRepository();
$ea = $eaRepository->getByAddress($emailAddress);
@@ -229,4 +248,10 @@ class CampaignUrl implements EntryPoint
$this->clientManager->display($runScript);
}
private function getEmailAddressRepository(): EmailAddressRepository
{
/** @var EmailAddressRepository */
return $this->entityManager->getRepository('EmailAddress');
}
}
@@ -46,10 +46,19 @@ class EventConfirmation implements EntryPoint
{
use NoAuth;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var ClientManager
*/
protected $clientManager;
/**
* @var HookManager
*/
protected $hookManager;
public function __construct(EntityManager $entityManager, ClientManager $clientManager, HookManager $hookManager) {
@@ -71,7 +80,10 @@ class EventConfirmation implements EntryPoint
throw new BadRequest();
}
$uniqueId = $this->entityManager->getRepository('UniqueId')->where(['name' => $uid])->findOne();
$uniqueId = $this->entityManager
->getRDBRepository('UniqueId')
->where(['name' => $uid])
->findOne();
if (!$uniqueId) {
throw new NotFound();
@@ -111,18 +123,21 @@ class EventConfirmation implements EntryPoint
$data = (object) [
'status' => $status
];
$this->entityManager->getRepository($eventType)->updateRelation($event, $link, $invitee->id, $data);
$this->entityManager
->getRDBRepository($eventType)
->updateRelation($event, $link, $invitee->getId(), $data);
$actionData = [
'eventName' => $event->get('name'),
'eventType' => $event->getEntityType(),
'eventId' => $event->id,
'eventId' => $event->getId(),
'dateStart' => $event->get('dateStart'),
'action' => $action,
'status' => $status,
'link' => $link,
'inviteeType' => $invitee->getEntityType(),
'inviteeId' => $invitee->id
'inviteeId' => $invitee->getId(),
];
$this->hookManager->process($event->getEntityType(), $hookMethodName, $event, [], $actionData);
@@ -29,6 +29,8 @@
namespace Espo\Modules\Crm\EntryPoints;
use Espo\Repositories\EmailAddress as EmailAddressRepository;
use Espo\Core\{
Exceptions\NotFound,
Exceptions\BadRequest,
@@ -48,16 +50,34 @@ class SubscribeAgain implements EntryPoint
{
use NoAuth;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var ClientManager
*/
protected $clientManager;
/**
* @var HookManager
*/
protected $hookManager;
/**
* @var Config
*/
protected $config;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var Hasher
*/
protected $hasher;
public function __construct(
@@ -131,7 +151,7 @@ class SubscribeAgain implements EntryPoint
$emailAddress = $target->get('emailAddress');
if ($emailAddress) {
$ea = $this->entityManager->getRepository('EmailAddress')->getByAddress($emailAddress);
$ea = $this->getEmailAddressRepository()->getByAddress($emailAddress);
if ($ea) {
$ea->set('optOut', false);
@@ -155,14 +175,14 @@ class SubscribeAgain implements EntryPoint
if ($link) {
$targetListList = $this->entityManager
->getRepository('MassEmail')
->getRDBRepository('MassEmail')
->getRelation($massEmail, 'targetLists')
->find();
foreach ($targetListList as $targetList) {
$optedInResult = $this->entityManager
->getRepository('TargetList')
->updateRelation($targetList, $link, $target->id, ['optedOut' => false]);
->getRDBRepository('TargetList')
->updateRelation($targetList, $link, $target->getId(), ['optedOut' => false]);
if ($optedInResult) {
$hookData = [
@@ -171,7 +191,8 @@ class SubscribeAgain implements EntryPoint
'targetType' => $targetType,
];
$this->hookManager->process('TargetList', 'afterCancelOptOut', $targetList, [], $hookData);
$this->hookManager
->process('TargetList', 'afterCancelOptOut', $targetList, [], $hookData);
}
}
@@ -185,7 +206,7 @@ class SubscribeAgain implements EntryPoint
if ($campaign && $target) {
$logRecord = $this->entityManager
->getRepository('CampaignLogRecord')->where([
->getRDBRepository('CampaignLogRecord')->where([
'queueItemId' => $queueItemId,
'action' => 'Opted Out',
])
@@ -225,11 +246,12 @@ class SubscribeAgain implements EntryPoint
throw new NotFound();
}
$repository = $this->entityManager->getRepository('EmailAddress');
$repository = $this->getEmailAddressRepository();
$ea = $repository->getByAddress($emailAddress);
if ($ea) {
$entityList = $repository->getEntityListByAddressId($ea->id);
$entityList = $repository->getEntityListByAddressId($ea->getId());
if ($ea->get('optOut')) {
$ea->set('optOut', false);
@@ -250,4 +272,10 @@ class SubscribeAgain implements EntryPoint
throw new NotFound();
}
}
private function getEmailAddressRepository(): EmailAddressRepository
{
/** @var EmailAddressRepository */
return $this->entityManager->getRepository('EmailAddress');
}
}
@@ -30,6 +30,7 @@
namespace Espo\Modules\Crm\EntryPoints;
use Espo\Modules\Crm\Services\Campaign as Service;
use Espo\Repositories\EmailAddress as EmailAddressRepository;
use Espo\Core\{
Exceptions\NotFound,
@@ -50,18 +51,39 @@ class Unsubscribe implements EntryPoint
{
use NoAuth;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var ClientManager
*/
protected $clientManager;
/**
* @var HookManager
*/
protected $hookManager;
/**
* @var Config
*/
protected $config;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var Hasher
*/
protected $hasher;
/**
* @var Service
*/
protected $service;
public function __construct(
@@ -137,7 +159,7 @@ class Unsubscribe implements EntryPoint
$emailAddress = $target->get('emailAddress');
if ($emailAddress) {
$ea = $this->entityManager->getRepository('EmailAddress')->getByAddress($emailAddress);
$ea = $this->getEmailAddressRepository()->getByAddress($emailAddress);
if ($ea) {
$ea->set('optOut', true);
@@ -161,14 +183,14 @@ class Unsubscribe implements EntryPoint
if ($link) {
$targetListList = $this->entityManager
->getRepository('MassEmail')
->getRDBRepository('MassEmail')
->getRelation($massEmail, 'targetLists')
->find();
foreach ($targetListList as $targetList) {
$optedOutResult = $this->entityManager
->getRepository('TargetList')
->updateRelation($targetList, $link, $target->id, ['optedOut' => true]);
->getRDBRepository('TargetList')
->updateRelation($targetList, $link, $target->getId(), ['optedOut' => true]);
if ($optedOutResult) {
$hookData = [
@@ -228,7 +250,7 @@ class Unsubscribe implements EntryPoint
throw new NotFound();
}
$repository = $this->entityManager->getRepository('EmailAddress');
$repository = $this->getEmailAddressRepository();
$ea = $repository->getByAddress($emailAddress);
@@ -253,4 +275,10 @@ class Unsubscribe implements EntryPoint
throw new NotFound();
}
}
private function getEmailAddressRepository(): EmailAddressRepository
{
/** @var EmailAddressRepository */
return $this->entityManager->getRepository('EmailAddress');
}
}
@@ -36,6 +36,9 @@ use Espo\ORM\{
class Contacts
{
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(EntityManager $entityManager)
@@ -29,6 +29,9 @@ use Espo\Core\{
class ControlKnowledgeBaseArticleStatus implements JobDataLess
{
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(EntityManager $entityManager)
@@ -39,7 +42,7 @@ class ControlKnowledgeBaseArticleStatus implements JobDataLess
public function run(): void
{
$list = $this->entityManager
->getRepository('KnowledgeBaseArticle')
->getRDBRepository('KnowledgeBaseArticle')
->where([
'expirationDate<=' => date('Y-m-d'),
'status' => 'Published',
@@ -33,18 +33,19 @@ use Espo\ORM\Entity;
class TargetList extends \Espo\Core\Repositories\Database
{
protected $entityTypeLinkMap = array(
protected $entityTypeLinkMap = [
'Lead' => 'leads',
'Account' => 'accounts',
'Contact' => 'contacts',
'User' => 'users',
);
];
public function relateTarget(Entity $entity, Entity $target, $data = null)
{
if (empty($this->entityTypeLinkMap[$target->getEntityType()])) {
return;
}
$relation = $this->entityTypeLinkMap[$target->getEntityType()];
$this->relate($entity, $relation, $target, $data);
@@ -32,15 +32,14 @@ namespace Espo\Modules\Crm\Tools\MassEmail;
use Espo\Repositories\EmailAddress as EmailAddressRepository;
use Espo\Entities\EmailAddress;
use Espo\Modules\Crm\Entities\TargetList;
use Espo\Modules\Crm\Entities\MassEmail;
use Espo\Core\{
Exceptions\Error,
ORM\EntityManager,
};
use Espo\{
ORM\Entity,
};
class Queue
{
protected $targetsLinkList = [
@@ -50,6 +49,9 @@ class Queue
'users',
];
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(EntityManager $entityManager)
@@ -57,7 +59,7 @@ class Queue
$this->entityManager = $entityManager;
}
protected function cleanupQueueItems(Entity $massEmail): void
protected function cleanupQueueItems(MassEmail $massEmail): void
{
$delete = $this->entityManager
->getQueryBuilder()
@@ -72,7 +74,7 @@ class Queue
$this->entityManager->getQueryExecutor()->execute($delete);
}
public function create(Entity $massEmail, bool $isTest = false, iterable $additionalTargetList = []): void
public function create(MassEmail $massEmail, bool $isTest = false, iterable $additionalTargetList = []): void
{
if (!$isTest && $massEmail->get('status') !== 'Pending') {
throw new Error("Mass Email '" . $massEmail->getId() . "' should be 'Pending'.");
@@ -90,19 +92,20 @@ class Queue
if (!$isTest) {
$excludingTargetListList = $this->entityManager
->getRDBRepository('MassEmail')
->getRelation($massEmail, 'excludingTargetLists')
->find();
->getRDBRepository('MassEmail')
->getRelation($massEmail, 'excludingTargetLists')
->find();
foreach ($excludingTargetListList as $excludingTargetList) {
foreach ($this->targetsLinkList as $link) {
$excludingList = $em->getRepository('TargetList')->findRelated(
$excludingTargetList,
$link,
[
'select' => ['id', 'emailAddress'],
]
);
$excludingList = $em->getRDBRepository('TargetList')
->findRelated(
$excludingTargetList,
$link,
[
'select' => ['id', 'emailAddress'],
]
);
foreach ($excludingList as $excludingTarget) {
$hashId = $excludingTarget->getEntityType() . '-'. $excludingTarget->getId();
@@ -118,6 +121,7 @@ class Queue
}
}
/** @var iterable<TargetList> */
$targetListCollection = $em
->getRDBRepository('MassEmail')
->getRelation($massEmail, 'targetLists')
@@ -217,6 +221,7 @@ class Queue
private function getEmailAddressRepository(): EmailAddressRepository
{
/** @var EmailAddressRepository */
return $this->entityManager->getRepository(EmailAddress::ENTITY_TYPE);
}
}
@@ -38,6 +38,9 @@ use Espo\ORM\{
*/
class CollectionFactory
{
/**
* @var EntityManager
*/
protected $entityManager;
public function __construct(EntityManager $entityManager)
+27 -8
View File
@@ -61,20 +61,39 @@ class BaseMapper implements RDBMapper
protected $aliasesCache = [];
/**
* @var PDO
*/
protected $pdo;
protected $entityFactroy;
protected $collectionFactory;
protected $queryComposer;
/**
* @var EntityFactory
*/
protected $entityFactory;
/**
* @var CollectionFactory
*/
protected $collectionFactory;
/**
* @var QueryComposer
*/
protected $queryComposer;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var SqlExecutor
*/
protected $sqlExecutor;
/**
* @var Helper
*/
protected $helper;
public function __construct(
@@ -1237,7 +1256,7 @@ class BaseMapper implements RDBMapper
{
$id = $this->pdo->lastInsertId();
if ($id === '' || $id === null) {
if ($id === '' || $id === null) { /** @phpstan-ignore-line */
return;
}
@@ -1560,7 +1579,7 @@ class BaseMapper implements RDBMapper
$foreignEntity = $this->entityFactory->create($foreignEntityType);
$map = $foreignEntity->getRelationParam($foreign, 'columnAttributeMap') ?? [];
$map = $this->getRelationParam($foreignEntity, $foreign, 'columnAttributeMap') ?? [];
$select = [];
@@ -38,6 +38,9 @@ class DefaultPDOProvider implements PDOProvider
{
private $databaseParams;
/**
* @var ?PDO
*/
private $pdo = null;
public function __construct(DatabaseParams $databaseParams)
@@ -73,49 +76,21 @@ class DefaultPDOProvider implements PDOProvider
throw new RuntimeException("No 'host' parameter.");
}
if (!$dbname) {
throw new RuntimeException("No 'dbname' parameter.");
}
$dsn =
$platform . ':' .
'host=' . $host;
$dsn = $platform . ':' . 'host=' . $host;
if ($port) {
$dsn .= ';' . 'port=' . (string) $port;
}
$dsn .= ';' . 'dbname=' . $dbname;
if ($dbname) {
$dsn .= ';' . 'dbname=' . $dbname;
}
if ($charset) {
$dsn .= ';' . 'charset=' . $charset;
}
$options = [];
if ($this->databaseParams->getSslCa()) {
$options[PDO::MYSQL_ATTR_SSL_CA] = $this->databaseParams->getSslCa();
}
if ($this->databaseParams->getSslCert()) {
$options[PDO::MYSQL_ATTR_SSL_CERT] = $this->databaseParams->getSslCert();
}
if ($this->databaseParams->getSslKey()) {
$options[PDO::MYSQL_ATTR_SSL_KEY] = $this->databaseParams->getSslKey();
}
if ($this->databaseParams->getSslCaPath()) {
$options[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->databaseParams->getSslCaPath();
}
if ($this->databaseParams->getSslCipher()) {
$options[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->databaseParams->getSslCipher();
}
if ($this->databaseParams->isSslVerifyDisabled()) {
$options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
}
$options = Options::getOptionsFromDatabaseParams($this->databaseParams);
$this->pdo = new PDO($dsn, $username, $password, $options);
+71
View File
@@ -0,0 +1,71 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2021 Yurii Kuznietsov, Taras Machyshyn, Oleksii 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\ORM\PDO;
use Espo\ORM\DatabaseParams;
use PDO;
class Options
{
/**
* @return array<string, mixed>
*/
public static function getOptionsFromDatabaseParams(DatabaseParams $databaseParams): array
{
$options = [];
if ($databaseParams->getSslCa()) {
$options[PDO::MYSQL_ATTR_SSL_CA] = $databaseParams->getSslCa();
}
if ($databaseParams->getSslCert()) {
$options[PDO::MYSQL_ATTR_SSL_CERT] = $databaseParams->getSslCert();
}
if ($databaseParams->getSslKey()) {
$options[PDO::MYSQL_ATTR_SSL_KEY] = $databaseParams->getSslKey();
}
if ($databaseParams->getSslCaPath()) {
$options[PDO::MYSQL_ATTR_SSL_CAPATH] = $databaseParams->getSslCaPath();
}
if ($databaseParams->getSslCipher()) {
$options[PDO::MYSQL_ATTR_SSL_CIPHER] = $databaseParams->getSslCipher();
}
if ($databaseParams->isSslVerifyDisabled()) {
$options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
}
return $options;
}
}
@@ -144,12 +144,24 @@ abstract class BaseQueryComposer implements QueryComposer
protected $identifierQuoteCharacter = '`';
/**
* @var EntityFactory
*/
protected $entityFactory;
/**
* @var PDO
*/
protected $pdo;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var FunctionConverterFactory|null
*/
protected $functionConverterFactory;
protected $helper;
@@ -1070,7 +1082,7 @@ abstract class BaseQueryComposer implements QueryComposer
return $function . '(' . $part . ')';
}
private function getFunctionPartFromFactory(string $function, array $argumentPartList): ?string
private function getFunctionPartFromFactory(string $function, array $argumentPartList): string
{
$obj = $this->functionConverterFactory->create($function);
@@ -61,12 +61,19 @@ class RDBRepository implements Repository
*/
protected $entityManager;
/**
* @var EntityFactory
*/
protected $entityFactory;
protected $mapper;
/**
* @var HookMediator|null
*/
protected $hookMediator;
/**
* @var RDBTransactionManager
*/
protected $transactionManager;
public function __construct(
@@ -55,6 +55,9 @@ class Preferences implements Repository,
use Di\ConfigSetter;
use Di\EntityManagerSetter;
/**
* @var EntityFactory
*/
protected $entityFactory;
public function __construct(
@@ -76,6 +79,7 @@ class Preferences implements Repository,
public function getNew(): Entity
{
/** @var PreferencesEntity */
return $this->entityFactory->create('Preferences');
}
+10 -10
View File
@@ -254,7 +254,7 @@ class Attachment extends Record
}
}
public function getCopiedAttachment($data)
public function getCopiedAttachment(stdClass $data): AttachmentEntity
{
if (empty($data->id)) {
throw new BadRequest();
@@ -303,7 +303,7 @@ class Attachment extends Record
return $copied;
}
public function getAttachmentFromImageUrl($data)
public function getAttachmentFromImageUrl(stdClass $data): AttachmentEntity
{
$attachment = $this->getAttachmentRepository()->getNew();
@@ -331,14 +331,14 @@ class Attachment extends Record
$this->checkAttachmentField($relatedEntityType, $field);
$data = $this->getImageDataByUrl($url);
$imageData = $this->getImageDataByUrl($url);
if (!$data) {
if (!$imageData) {
throw new Error('Attachment::getAttachmentFromImageUrl: Bad image data.');
}
$type = $data['type'];
$contents = $data['contents'];
$type = $imageData->type;
$contents = $imageData->contents;
$size = mb_strlen($contents, '8bit');
@@ -378,7 +378,7 @@ class Attachment extends Record
return $attachment;
}
protected function getImageDataByUrl($url)
protected function getImageDataByUrl(string $url): ?stdClass
{
$type = null;
@@ -451,14 +451,14 @@ class Attachment extends Record
curl_close($ch);
if (!$type) {
return;
return null;
}
if (!in_array($type, $this->imageTypeList)) {
return;
return null;
}
return [
return (object) [
'type' => $type,
'contents' => $body,
];
+15 -3
View File
@@ -39,16 +39,28 @@ use Espo\{
Entities\User,
};
use StdClass;
use stdClass;
class Integration
{
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var User
*/
protected $user;
/**
* @var Config
*/
protected $config;
/**
* @var ConfigWriter
*/
protected $configWriter;
public function __construct(
@@ -83,7 +95,7 @@ class Integration
return $entity;
}
public function update(string $id, StdClass $data): Entity
public function update(string $id, stdClass $data): Entity
{
$this->processAccessCheck();
@@ -99,7 +111,7 @@ class Integration
$integrationsConfigData = $this->config->get('integrations') ?? (object) [];
if (!($integrationsConfigData instanceof StdClass)) {
if (!($integrationsConfigData instanceof stdClass)) {
$integrationsConfigData = (object) [];
}
+24 -3
View File
@@ -48,18 +48,39 @@ use Espo\{
class Layout
{
/**
* @var Acl
*/
protected $acl;
/**
* @var LayoutUtil
*/
protected $layout;
/**
* @var LayoutManager
*/
protected $layoutManager;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var DataManager
*/
protected $dataManager;
/**
* @var User
*/
protected $user;
public function __construct(
@@ -132,7 +153,7 @@ class Layout
if ($portalId) {
$portal = $em
->getRepository('Portal')
->getRDBRepository('Portal')
->select(['layoutSetId'])
->where(['id' => $portalId])
->findOne();
@@ -146,7 +167,7 @@ class Layout
if ($teamId) {
$team = $em
->getRepository('Team')
->getRDBRepository('Team')
->select(['layoutSetId'])
->where(['id' => $teamId])
->findOne();
@@ -245,7 +266,7 @@ class Layout
}
$layout = $em
->getRepository('LayoutRecord')
->getRDBRepository('LayoutRecord')
->where([
'layoutSetId' => $setId,
'name' => $fullName,
@@ -70,18 +70,39 @@ use RuntimeException;
*/
class Xlsx implements Processor
{
/**
* @var Config
*/
protected $config;
/**
* @var Metadata
*/
protected $metadata;
/**
* @var Language
*/
protected $language;
/**
* @var DateTimeUtil
*/
protected $dateTime;
/**
* @var EntityManager
*/
protected $entityManager;
/**
* @var FileStorageManager
*/
protected $fileStorageManager;
/**
* @var AddressFormatterFactory
*/
protected $addressFormatterFactory;
public function __construct(
@@ -87,10 +87,13 @@ class LeadCapture
/** @var Log */
protected $log;
/** @var CampaignService */
private $campaignService;
/** @var EmailTemplateService */
private $emailTemplateService;
/** @var InboundEmailService */
private $inboundEmailService;
public function __construct(
@@ -56,20 +56,26 @@ define('crm:views/mass-email/fields/smtp-account', 'views/fields/enum', function
if (!this.loadedOptionList) {
if (this.model.get('inboundEmailId')) {
var item = 'inboundEmail:' + this.model.get('inboundEmailId');
this.params.options.push(item);
this.translatedOptions[item] =
(this.model.get('inboundEmailName') || this.model.get('inboundEmailId')) + ' (' + this.translate('group', 'labels', 'MassEmail') + ')';
(this.model.get('inboundEmailName') || this.model.get('inboundEmailId')) +
' (' + this.translate('group', 'labels', 'MassEmail') + ')';
}
} else {
this.loadedOptionList.forEach(function (item) {
this.loadedOptionList.forEach((item) => {
this.params.options.push(item);
this.translatedOptions[item] =
(this.loadedOptionTranslations[item] || item) + ' (' + this.translate('group', 'labels', 'MassEmail') + ')';
}, this);
(this.loadedOptionTranslations[item] || item) +
' (' + this.translate('group', 'labels', 'MassEmail') + ')';
});
}
this.translatedOptions['system'] =
this.getConfig().get('outboundEmailFromAddress') + ' (' + this.translate('system', 'labels', 'MassEmail') + ')';
this.getConfig().get('outboundEmailFromAddress') +
' (' + this.translate('system', 'labels', 'MassEmail') + ')';
},
getValueForDisplay: function () {
@@ -91,35 +97,49 @@ define('crm:views/mass-email/fields/smtp-account', 'views/fields/enum', function
setup: function () {
Dep.prototype.setup.call(this);
if (this.getAcl().checkScope('MassEmail', 'create') || this.getAcl().checkScope('MassEmail', 'edit')) {
this.ajaxGetRequest(this.dataUrl).then(function (dataList) {
if (!dataList.length) return;
if (
this.getAcl().checkScope('MassEmail', 'create') ||
this.getAcl().checkScope('MassEmail', 'edit')
) {
this.ajaxGetRequest(this.dataUrl).then(dataList => {
if (!dataList.length) {
return;
}
this.loadedOptionList = [];
this.loadedOptionTranslations = {};
this.loadedOptionAddresses = {};
this.loadedOptionFromNames = {};
dataList.forEach(function (item) {
dataList.forEach(item => {
this.loadedOptionList.push(item.key);
this.loadedOptionTranslations[item.key] = item.emailAddress;
this.loadedOptionAddresses[item.key] = item.emailAddress;
this.loadedOptionFromNames[item.key] = item.fromName || '';
}, this);
});
this.setupOptions();
this.reRender();
}.bind(this));
});
}
},
fetch: function () {
var data = {};
var value = this.$element.val();
data[this.name] = value;
if (!value || value === 'system') {
data.inboundEmailId = null;
data.inboundEmailName = null;
} else {
}
else {
var arr = value.split(':');
if (arr.length > 1) {
data.inboundEmailId = arr[1];
data.inboundEmailName = this.translatedOptions[data.inboundEmailId] || data.inboundEmailId;
@@ -39,6 +39,8 @@ use Espo\Core\Exceptions\Error;
use PDO;
use RuntimeException;
class HelperTest extends \tests\integration\Core\BaseTestCase
{
protected $reflection;
@@ -80,7 +82,9 @@ class HelperTest extends \tests\integration\Core\BaseTestCase
{
$this->initTest(true);
$this->assertNull($this->helper->getDbalConnection());
$this->expectException(RuntimeException::class);
$this->helper->getDbalConnection();
}
public function testGetDbalConnectionWithConfig()
@@ -94,7 +98,9 @@ class HelperTest extends \tests\integration\Core\BaseTestCase
{
$this->initTest(true);
$this->assertNull($this->helper->getPdoConnection());
$this->expectException(RuntimeException::class);
$this->helper->getPdoConnection();
}
public function testGetPdoConnectionWithConfig()
@@ -114,7 +114,6 @@ class ConverterTest extends \PHPUnit\Framework\TestCase
$this->converter = new Converter(
$this->entityType,
$this->user,
$this->itemConverter,
$this->scanner,
$this->randomStringGenerator,