type fixes
This commit is contained in:
@@ -192,12 +192,18 @@ class AdminNotifications implements
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
|
||||
|
||||
/** @var string|false */
|
||||
$result = curl_exec($ch);
|
||||
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
if ($result === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if ($httpCode !== 200) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ class App
|
||||
];
|
||||
|
||||
foreach (($this->metadata->get(['app', 'appParams']) ?? []) as $paramKey => $item) {
|
||||
/** @var ?class-string */
|
||||
/** @var ?class-string<object> */
|
||||
$className = $item['className'] ?? null;
|
||||
|
||||
if (!$className) {
|
||||
@@ -172,7 +172,13 @@ class App
|
||||
}
|
||||
|
||||
try {
|
||||
$itemParams = $this->injectableFactory->create($className)->get();
|
||||
$obj = $this->injectableFactory->create($className);
|
||||
|
||||
if (!method_exists($obj, 'get')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$itemParams = $obj->get();
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->log->error("appParam {$paramKey}: " . $e->getMessage());
|
||||
@@ -241,6 +247,7 @@ class App
|
||||
if (!$this->user->isAdmin()) {
|
||||
$data = unserialize(serialize($data));
|
||||
|
||||
/** @var string[] */
|
||||
$scopeList = array_keys($this->metadata->get(['scopes'], []));
|
||||
|
||||
foreach ($scopeList as $scope) {
|
||||
@@ -427,6 +434,7 @@ class App
|
||||
*/
|
||||
public function jobPopulateArrayValues(): void
|
||||
{
|
||||
/** @var string[] */
|
||||
$scopeList = array_keys($this->metadata->get(['scopes']));
|
||||
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
|
||||
@@ -429,8 +429,15 @@ class Attachment extends Record
|
||||
|
||||
curl_setopt_array($ch, $opts);
|
||||
|
||||
/** @var string|false */
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
curl_close($ch);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$headerSize = curl_getinfo($ch, \CURLINFO_HEADER_SIZE);
|
||||
|
||||
$header = substr($response, 0, $headerSize);
|
||||
|
||||
@@ -38,6 +38,8 @@ use Espo\Entities\Attachment;
|
||||
use Espo\Entities\UserData;
|
||||
use Espo\Repositories\UserData as UserDataRepository;
|
||||
|
||||
use Espo\Core\Utils\Json;
|
||||
|
||||
use Espo\{
|
||||
ORM\Entity,
|
||||
Entities\User,
|
||||
@@ -332,7 +334,7 @@ class Email extends Record implements
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
|
||||
throw ErrorSilent::createWithBody('sendingFail', json_encode($errorData));
|
||||
throw ErrorSilent::createWithBody('sendingFail', Json::encode($errorData));
|
||||
}
|
||||
|
||||
$this->entityManager->saveEntity($entity, ['isJustSent' => true]);
|
||||
@@ -398,12 +400,13 @@ class Email extends Record implements
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var class-string<object> */
|
||||
$handlerClassName = $smtpHandlers->$emailAddress;
|
||||
|
||||
$handler = null;
|
||||
|
||||
try {
|
||||
$handler = $this->getInjection('injectableFactory')->create($handlerClassName);
|
||||
$handler = $this->injectableFactory->create($handlerClassName);
|
||||
}
|
||||
catch (Throwable $e) {
|
||||
$this->log->error(
|
||||
@@ -952,7 +955,7 @@ class Email extends Record implements
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
|
||||
throw ErrorSilent::createWithBody('sendingFail', json_encode($errorData));
|
||||
throw ErrorSilent::createWithBody('sendingFail', Json::encode($errorData));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -91,12 +91,11 @@ class ExternalAccount extends Record implements Di\HookManagerAware
|
||||
*/
|
||||
public function ping(string $integration, string $userId)
|
||||
{
|
||||
$entity = $this->getExternalAccountEntity($integration, $userId);
|
||||
|
||||
try {
|
||||
$client = $this->getClient($integration, $userId);
|
||||
|
||||
if ($client) {
|
||||
if ($client && method_exists($client, 'ping')) {
|
||||
/** @var @bool */
|
||||
return $client->ping();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ class GlobalSearch implements
|
||||
|
||||
$sth = $this->entityManager->getQueryExecutor()->execute($unionQuery);
|
||||
|
||||
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
|
||||
$rows = $sth->fetchAll(PDO::FETCH_ASSOC) ?: [];
|
||||
|
||||
$resultList = [];
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class Import extends Record
|
||||
->withSearchParams($searchParams)
|
||||
->build();
|
||||
|
||||
/** @var iterable<\Espo\ORM\Entity> */
|
||||
/** @var \Espo\ORM\Collection<\Espo\ORM\Entity> */
|
||||
$collection = $this->getImportRepository()->findResultRecords($entity, $link, $query);
|
||||
|
||||
$listLoadProcessor = $this->injectableFactory->create(ListLoadProcessor::class);
|
||||
|
||||
@@ -64,11 +64,13 @@ class Language
|
||||
// TODO use proxy
|
||||
protected function getDefaultLanguage(): LanguageUtil
|
||||
{
|
||||
/** @var LanguageUtil */
|
||||
return $this->container->get('defaultLanguage');
|
||||
}
|
||||
|
||||
protected function getLanguage(): LanguageUtil
|
||||
{
|
||||
/** @var LanguageUtil */
|
||||
return $this->container->get('language');
|
||||
}
|
||||
|
||||
@@ -120,6 +122,7 @@ class Language
|
||||
unset($data['Campaign']['presetFilters']);
|
||||
}
|
||||
else {
|
||||
/** @var string[] */
|
||||
$scopeList = array_keys($this->metadata->get(['scopes'], []));
|
||||
|
||||
foreach ($scopeList as $scope) {
|
||||
|
||||
@@ -38,6 +38,8 @@ use Espo\Core\{
|
||||
|
||||
use Espo\Entities\User;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
class LastViewed
|
||||
{
|
||||
private $metadata;
|
||||
@@ -105,7 +107,12 @@ class LastViewed
|
||||
$entity->set('id', Util::generateId());
|
||||
}
|
||||
|
||||
if ($maxSize && is_countable($collection) && count($collection) > $maxSize) {
|
||||
if (
|
||||
$maxSize &&
|
||||
is_countable($collection) &&
|
||||
count($collection) > $maxSize &&
|
||||
$collection instanceof ArrayAccess
|
||||
) {
|
||||
$total = -1;
|
||||
|
||||
unset($collection[count($collection) - 1]);
|
||||
|
||||
@@ -34,6 +34,7 @@ use Espo\Entities\LayoutRecord;
|
||||
use Espo\Core\{
|
||||
Exceptions\NotFound,
|
||||
Exceptions\Forbidden,
|
||||
Exceptions\Error,
|
||||
Acl,
|
||||
Acl\Exceptions\NotImplemented,
|
||||
Utils\Layout as LayoutUtil,
|
||||
@@ -223,6 +224,7 @@ class Layout
|
||||
$link = $item;
|
||||
|
||||
if (is_object($item)) {
|
||||
/** @var \stdClass $item */
|
||||
$link = $item->name ?? null;
|
||||
}
|
||||
|
||||
@@ -361,6 +363,10 @@ class Layout
|
||||
{
|
||||
$relationships = $this->getOriginal($scope, 'relationships') ?? [];
|
||||
|
||||
if (!is_array($relationships)) {
|
||||
throw new Error("Bad 'relationships' layout.");
|
||||
}
|
||||
|
||||
$result = (object) [];
|
||||
|
||||
foreach ($relationships as $i => $item) {
|
||||
@@ -374,6 +380,8 @@ class Layout
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var stdClass $item */
|
||||
|
||||
$item = clone $item;
|
||||
$item->index = 5 + 0.001 * $i;
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ class Metadata
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @var string[] */
|
||||
$scopeList = array_keys($this->metadata->get(['entityDefs'], []));
|
||||
|
||||
foreach ($scopeList as $scope) {
|
||||
@@ -151,6 +152,7 @@ class Metadata
|
||||
|
||||
unset($data->entityDefs->Settings);
|
||||
|
||||
/** @var string[] */
|
||||
$dashletList = array_keys($this->metadata->get(['dashlets'], []));
|
||||
|
||||
foreach ($dashletList as $item) {
|
||||
|
||||
@@ -78,6 +78,7 @@ class MysqlCharacter extends \Espo\Core\Services\Base
|
||||
$tableName = \Espo\Core\Utils\Util::toUnderScore($entityName);
|
||||
|
||||
// Get table columns params
|
||||
/** @phpstan-ignore-next-line */
|
||||
$query = "SHOW FULL COLUMNS FROM `". $tableName ."` WHERE `Collation` <> 'utf8mb4_unicode_ci'";
|
||||
|
||||
try {
|
||||
@@ -109,6 +110,7 @@ class MysqlCharacter extends \Espo\Core\Services\Base
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (!isset($columnParams[$columnName]) || empty($columnParams[$columnName]['Type'])) {
|
||||
continue;
|
||||
}
|
||||
@@ -120,10 +122,12 @@ class MysqlCharacter extends \Espo\Core\Services\Base
|
||||
case 'text':
|
||||
case 'jsonObject':
|
||||
case 'jsonArray':
|
||||
$query = "ALTER TABLE `".$tableName."`
|
||||
CHANGE COLUMN `". $columnName ."` `". $columnName ."` ". $columnParams[$columnName]['Type'] ."
|
||||
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
";
|
||||
/** @phpstan-ignore-next-line */
|
||||
$query = "ALTER TABLE `".$tableName."` ".
|
||||
/** @phpstan-ignore-next-line */
|
||||
"CHANGE COLUMN `". $columnName ."` `". $columnName ."` ". $columnParams[$columnName]['Type'] .
|
||||
/** @phpstan-ignore-next-line */
|
||||
" CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ use Espo\Entities\User;
|
||||
|
||||
use Espo\Tools\Stream\NoteAccessControl;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
/**
|
||||
* @extends Record<\Espo\Entities\Notification>
|
||||
*/
|
||||
@@ -151,6 +153,10 @@ class Notification extends \Espo\Services\Record
|
||||
->clone($query)
|
||||
->find();
|
||||
|
||||
if (!$collection instanceof ArrayAccess) {
|
||||
throw new Error("Collection is not instance of ArrayAccess.");
|
||||
}
|
||||
|
||||
$count = $this->entityManager
|
||||
->getRDBRepository('Notification')
|
||||
->clone($query)
|
||||
|
||||
@@ -256,7 +256,7 @@ class Pdf
|
||||
|
||||
$contents = $printer->printCollection($collection, $params, $idDataMap);
|
||||
|
||||
$entityTypeTranslated = $this->defaultLanguage->translate($entityType, 'scopeNamesPlural');
|
||||
$entityTypeTranslated = $this->defaultLanguage->translateLabel($entityType, 'scopeNamesPlural');
|
||||
|
||||
$filename = Util::sanitizeFileName($entityTypeTranslated) . '.pdf';
|
||||
|
||||
|
||||
@@ -344,6 +344,8 @@ class Record extends RecordService implements
|
||||
|
||||
$list = [];
|
||||
|
||||
assert(is_string($this->entityType));
|
||||
|
||||
foreach ($this->fieldUtil->getEntityTypeFieldList($this->entityType) as $field) {
|
||||
if (
|
||||
$this->metadata
|
||||
|
||||
@@ -46,6 +46,7 @@ use Espo\Core\{
|
||||
|
||||
use Espo\Core\Acl\Exceptions\NotImplemented;
|
||||
|
||||
use ArrayAccess;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
@@ -159,7 +160,10 @@ class RecordTree extends Record
|
||||
->clone($selectBuilder->build())
|
||||
->find();
|
||||
|
||||
if (!empty($params['onlyNotEmpty']) || $filterItems) {
|
||||
if (
|
||||
(!empty($params['onlyNotEmpty']) || $filterItems) &&
|
||||
$collection instanceof ArrayAccess
|
||||
) {
|
||||
foreach ($collection as $i => $entity) {
|
||||
if ($this->checkItemIsEmpty($entity)) {
|
||||
unset($collection[$i]);
|
||||
|
||||
@@ -222,6 +222,7 @@ class Settings
|
||||
{
|
||||
$entityTypeListParamList = $this->metadata->get(['app', 'config', 'entityTypeListParamList']) ?? [];
|
||||
|
||||
/** @var string[] */
|
||||
$scopeList = array_keys($this->metadata->get(['entityDefs'], []));
|
||||
|
||||
foreach ($scopeList as $scope) {
|
||||
|
||||
@@ -199,14 +199,18 @@ class Stream
|
||||
if (is_null($this->statusFields)) {
|
||||
$this->statusFields = [];
|
||||
|
||||
/** @var array<string,array<string,mixed>> */
|
||||
$scopes = $this->metadata->get('scopes', []);
|
||||
|
||||
foreach ($scopes as $scope => $data) {
|
||||
if (empty($data['statusField'])) {
|
||||
/** @var ?string */
|
||||
$statusField = $data['statusField'] ?? null;
|
||||
|
||||
if (!$statusField) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->statusFields[$scope] = $data['statusField'];
|
||||
$this->statusFields[$scope] = $statusField;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1204,7 +1208,7 @@ class Stream
|
||||
$countBuilder = clone $builder;
|
||||
|
||||
$builder
|
||||
->limit($params['offset'], $params['maxSize'])
|
||||
->limit($params['offset'] ?? 0, $params['maxSize'])
|
||||
->order('number', 'DESC');
|
||||
|
||||
/** @var iterable<NoteEntity> */
|
||||
@@ -1731,12 +1735,13 @@ class Stream
|
||||
return $this->auditedFieldsCache[$entityType];
|
||||
}
|
||||
|
||||
/** @var array<string,array<string,mixed>> */
|
||||
$fields = $this->metadata->get('entityDefs.' . $entityType . '.fields');
|
||||
|
||||
$auditedFields = [];
|
||||
|
||||
foreach ($fields as $field => $d) {
|
||||
if (empty($d['audited'])) {
|
||||
foreach ($fields as $field => $defs) {
|
||||
if (empty($defs['audited'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1744,6 +1749,13 @@ class Stream
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var ?string */
|
||||
$type = $defs['type'] ?? null;
|
||||
|
||||
if (!$type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$auditedFields[$field] = [];
|
||||
|
||||
$auditedFields[$field]['actualList'] =
|
||||
@@ -1752,7 +1764,7 @@ class Stream
|
||||
$auditedFields[$field]['notActualList'] =
|
||||
$this->fieldUtil->getNotActualAttributeList($entityType, $field);
|
||||
|
||||
$auditedFields[$field]['fieldType'] = $d['type'];
|
||||
$auditedFields[$field]['fieldType'] = $type;
|
||||
}
|
||||
|
||||
$this->auditedFieldsCache[$entityType] = $auditedFields;
|
||||
@@ -1953,6 +1965,7 @@ class Stream
|
||||
];
|
||||
|
||||
foreach ($userList as $user) {
|
||||
/** @var string */
|
||||
$id = $user->getId();
|
||||
|
||||
$data['idList'][] = $id;
|
||||
@@ -2238,7 +2251,7 @@ class Stream
|
||||
|
||||
if ($usersAttributeIsChanged || $forceProcessNoteNotifications) {
|
||||
if ($fieldDefs->getType() === 'linkMultiple') {
|
||||
$userIdList = $entity->getLinkMultipleIdList($ownerUserField);
|
||||
$userIdList = $entity->getLinkMultipleIdList($ownerUserField) ?? [];
|
||||
}
|
||||
else {
|
||||
$userId = $entity->get($ownerUserIdAttribute);
|
||||
@@ -2254,7 +2267,7 @@ class Stream
|
||||
}
|
||||
|
||||
if ($teamsAttributeIsChanged || $forceProcessNoteNotifications) {
|
||||
$teamIdList = $entity->getLinkMultipleIdList('teams');
|
||||
$teamIdList = $entity->getLinkMultipleIdList('teams') ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user