Initial commit
This commit is contained in:
193
application/Espo/Core/Upgrades/Migrations/V7_2/AfterUpgrade.php
Normal file
193
application/Espo/Core/Upgrades/Migrations/V7_2/AfterUpgrade.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V7_2;
|
||||
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\Portal;
|
||||
use Espo\Entities\Preferences;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Modules\Crm\Entities\KnowledgeBaseArticle;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\Core\Utils\Config;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
private EntityManager $entityManager,
|
||||
private Config $config,
|
||||
private Config\ConfigWriter $configWriter
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateEventMetadata();
|
||||
$this->updateTheme();
|
||||
$this->updateKbArticles();
|
||||
}
|
||||
|
||||
private function updateEventMetadata(): void
|
||||
{
|
||||
$metadata = $this->metadata;
|
||||
|
||||
$defs = $metadata->get(['scopes']);
|
||||
|
||||
$toSave = false;
|
||||
|
||||
foreach ($defs as $entityType => $item) {
|
||||
$isCustom = $item['isCustom'] ?? false;
|
||||
$type = $item['type'] ?? false;
|
||||
|
||||
if (!$isCustom || $type !== 'Event') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$toSave = true;
|
||||
|
||||
$metadata->set('recordDefs', $entityType, [
|
||||
'beforeUpdateHookClassNameList' => [
|
||||
"__APPEND__",
|
||||
"Espo\\Classes\\RecordHooks\\Event\\BeforeUpdatePreserveDuration"
|
||||
]
|
||||
]);
|
||||
|
||||
$metadata->set('clientDefs', $entityType, [
|
||||
'forcePatchAttributeDependencyMap' => [
|
||||
"dateEnd" => ["dateStart"],
|
||||
"dateEndDate" => ["dateStartDate"]
|
||||
]
|
||||
]);
|
||||
|
||||
if ($metadata->get(['entityDefs', $entityType, 'fields', 'isAllDay'])) {
|
||||
$metadata->set('entityDefs', $entityType, [
|
||||
'fields' => [
|
||||
'isAllDay' => [
|
||||
'readOnly' => false,
|
||||
],
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($toSave) {
|
||||
$metadata->save();
|
||||
}
|
||||
}
|
||||
|
||||
private function updateTheme(): void
|
||||
{
|
||||
$themeList = [
|
||||
'EspoVertical',
|
||||
'HazyblueVertical',
|
||||
'VioletVertical',
|
||||
'SakuraVertical',
|
||||
'DarkVertical',
|
||||
];
|
||||
|
||||
$theme = $this->config->get('theme');
|
||||
$navbar = 'top';
|
||||
|
||||
if (in_array($theme, $themeList)) {
|
||||
$theme = substr($theme, 0, -8);
|
||||
$navbar = 'side';
|
||||
}
|
||||
|
||||
$this->configWriter->set('theme', $theme);
|
||||
$this->configWriter->set('themeParams', (object) ['navbar' => $navbar]);
|
||||
$this->configWriter->save();
|
||||
|
||||
$userList = $this->entityManager->getRDBRepository(User::ENTITY_TYPE)
|
||||
->where([
|
||||
'type' => ['regular', 'admin']
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($userList as $user) {
|
||||
$preferences = $this->entityManager->getEntityById(Preferences::ENTITY_TYPE, $user->getId());
|
||||
|
||||
if (!$preferences) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$theme = $preferences->get('theme');
|
||||
$navbar = 'top';
|
||||
|
||||
if (!$theme) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($theme, $themeList)) {
|
||||
$theme = substr($theme, 0, -8);
|
||||
$navbar = 'side';
|
||||
}
|
||||
|
||||
$preferences->set('theme', $theme);
|
||||
$preferences->set('themeParams', (object) ['navbar' => $navbar]);
|
||||
|
||||
$this->entityManager->saveEntity($preferences);
|
||||
}
|
||||
|
||||
$portalList = $this->entityManager
|
||||
->getRDBRepository(Portal::ENTITY_TYPE)
|
||||
->where([
|
||||
'theme!=' => null,
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($portalList as $portal) {
|
||||
$theme = $portal->get('theme');
|
||||
$navbar = 'top';
|
||||
|
||||
if (in_array($theme, $themeList)) {
|
||||
$theme = substr($theme, 0, -8);
|
||||
$navbar = 'side';
|
||||
}
|
||||
|
||||
$portal->set('theme', $theme);
|
||||
$portal->set('themeParams', (object) ['navbar' => $navbar]);
|
||||
|
||||
$this->entityManager->saveEntity($portal);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateKbArticles(): void
|
||||
{
|
||||
$query = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->update()
|
||||
->in(KnowledgeBaseArticle::ENTITY_TYPE)
|
||||
->where(['type' => null])
|
||||
->set(['type' => 'Article'])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($query);
|
||||
}
|
||||
}
|
||||
118
application/Espo/Core/Upgrades/Migrations/V7_4/AfterUpgrade.php
Normal file
118
application/Espo/Core/Upgrades/Migrations/V7_4/AfterUpgrade.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V7_4;
|
||||
|
||||
use Espo\Core\ORM\Type\FieldType;
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Core\Templates\Entities\Event;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateMetadata();
|
||||
}
|
||||
|
||||
private function updateMetadata(): void
|
||||
{
|
||||
$this->metadata->set('app', 'recordId', [
|
||||
'length' => 24,
|
||||
]);
|
||||
|
||||
$this->fixParent();
|
||||
$this->updateEventMetadata();
|
||||
|
||||
$this->metadata->save();
|
||||
}
|
||||
|
||||
private function fixParent(): void
|
||||
{
|
||||
$metadata = $this->metadata;
|
||||
|
||||
foreach ($metadata->get(['entityDefs']) as $scope => $defs) {
|
||||
foreach ($metadata->get(['entityDefs', $scope, 'fields']) as $field => $fieldDefs) {
|
||||
$custom = $metadata->getCustom('entityDefs', $scope);
|
||||
|
||||
if (!$custom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
($fieldDefs['type'] ?? null) === FieldType::LINK_PARENT &&
|
||||
($fieldDefs['notStorable'] ?? false)
|
||||
) {
|
||||
if ($custom->fields?->$field?->notStorable) {
|
||||
$metadata->delete('entityDefs', $scope, "fields.$field.notStorable");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function updateEventMetadata(): void
|
||||
{
|
||||
$metadata = $this->metadata;
|
||||
|
||||
$defs = $metadata->get(['scopes']);
|
||||
|
||||
foreach ($defs as $entityType => $item) {
|
||||
$isCustom = $item['isCustom'] ?? false;
|
||||
$type = $item['type'] ?? false;
|
||||
|
||||
if (!$isCustom || $type !== Event::TEMPLATE_TYPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_string($metadata->get(['entityDefs', $entityType, 'fields', 'duration', 'select']))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$metadata->delete('entityDefs', $entityType, 'fields.duration.orderBy');
|
||||
|
||||
$metadata->set('entityDefs', $entityType, [
|
||||
'fields' => [
|
||||
'duration' => [
|
||||
'select' => [
|
||||
'select' => "TIMESTAMPDIFF_SECOND:(dateStart, dateEnd)"
|
||||
],
|
||||
'order' => [
|
||||
'order' => [["TIMESTAMPDIFF_SECOND:(dateStart, dateEnd)", "{direction}"]]
|
||||
],
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V7_5;
|
||||
|
||||
use Espo\Core\Templates\Entities\Event;
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\File\Manager;
|
||||
use Espo\Core\Utils\Json;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
private Manager $fileManger
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateEventMetadata();
|
||||
}
|
||||
|
||||
private function updateEventMetadata(): void
|
||||
{
|
||||
$metadata = $this->metadata;
|
||||
$fileManager = $this->fileManger;
|
||||
|
||||
$defs = $metadata->get(['scopes']);
|
||||
|
||||
$path1 = "application/Espo/Core/Templates/Metadata/Event/selectDefs.json";
|
||||
$contents1 = $fileManager->getContents($path1);
|
||||
$data1 = Json::decode($contents1, true);
|
||||
|
||||
$primaryFilterClassNameMap = (object) $data1['primaryFilterClassNameMap'];
|
||||
|
||||
foreach ($defs as $entityType => $item) {
|
||||
$isCustom = $item['isCustom'] ?? false;
|
||||
$type = $item['type'] ?? false;
|
||||
|
||||
if (!$isCustom || $type !== Event::TEMPLATE_TYPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data1 = $metadata->getCustom('selectDefs', $entityType) ?? (object) [];
|
||||
$data1->primaryFilterClassNameMap = $primaryFilterClassNameMap;
|
||||
|
||||
$metadata->saveCustom('selectDefs', $entityType, $data1);
|
||||
|
||||
$data2 = $metadata->getCustom('scopes', $entityType) ?? (object) [];
|
||||
$data2->completedStatusList = ['Held'];
|
||||
$data2->canceledStatusList = ['Not Held'];
|
||||
|
||||
$metadata->saveCustom('scopes', $entityType, $data2);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
application/Espo/Core/Upgrades/Migrations/V7_5/Prepare.php
Normal file
53
application/Espo/Core/Upgrades/Migrations/V7_5/Prepare.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V7_5;
|
||||
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Name\Attribute;
|
||||
use Espo\ORM\Query\DeleteBuilder;
|
||||
|
||||
class Prepare implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManager $entityManager
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$query = DeleteBuilder::create()
|
||||
->from(User::ENTITY_TYPE)
|
||||
->where([Attribute::DELETED => true])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($query);
|
||||
}
|
||||
}
|
||||
120
application/Espo/Core/Upgrades/Migrations/V8_0/AfterUpgrade.php
Normal file
120
application/Espo/Core/Upgrades/Migrations/V8_0/AfterUpgrade.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V8_0;
|
||||
|
||||
use Espo\Core\Container;
|
||||
use Espo\Core\Name\Field;
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\Role;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\Part\Expression;
|
||||
use Espo\ORM\Query\UpdateBuilder;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private Container $container
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateRoles(
|
||||
$this->container->getByClass(EntityManager::class)
|
||||
);
|
||||
|
||||
$this->updateMetadata(
|
||||
$this->container->getByClass(Metadata::class)
|
||||
);
|
||||
}
|
||||
|
||||
private function updateRoles(EntityManager $entityManager): void
|
||||
{
|
||||
$query = UpdateBuilder::create()
|
||||
->in(Role::ENTITY_TYPE)
|
||||
->set(['messagePermission' => Expression::column('assignmentPermission')])
|
||||
->build();
|
||||
|
||||
$entityManager->getQueryExecutor()->execute($query);
|
||||
}
|
||||
|
||||
private function updateMetadata(Metadata $metadata): void
|
||||
{
|
||||
$defs = $metadata->get(['scopes']);
|
||||
|
||||
foreach ($defs as $entityType => $item) {
|
||||
$isCustom = $item['isCustom'] ?? false;
|
||||
$type = $item['type'] ?? false;
|
||||
|
||||
if (!$isCustom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type === 'Event') {
|
||||
$metadata->set('entityDefs', $entityType, [
|
||||
'fields' => [
|
||||
'dateEnd' => [
|
||||
'suppressValidationList' => ['required'],
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$metadata->save();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!in_array($type, [
|
||||
'BasePlus',
|
||||
'Base',
|
||||
'Company',
|
||||
'Person',
|
||||
])
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$recordDefs = $metadata->getCustom('recordDefs', $entityType) ?? (object) [];
|
||||
$scopes = $metadata->getCustom('scopes', $entityType) ?? (object) [];
|
||||
|
||||
$recordDefs->duplicateWhereBuilderClassName = "Espo\\Classes\\DuplicateWhereBuilders\\General";
|
||||
|
||||
$scopes->duplicateCheckFieldList = [];
|
||||
|
||||
if ($type === 'Company' || $type === 'Person') {
|
||||
$scopes->duplicateCheckFieldList = [Field::NAME, 'emailAddress'];
|
||||
}
|
||||
|
||||
$metadata->saveCustom('recordDefs', $entityType, $recordDefs);
|
||||
$metadata->saveCustom('scopes', $entityType, $scopes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V8_1;
|
||||
|
||||
use Espo\Core\Container;
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Utils\Config;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private Container $container
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$config = $this->container->getByClass(Config::class);
|
||||
|
||||
$configWriter = $this->container->getByClass(InjectableFactory::class)
|
||||
->create(Config\ConfigWriter::class);
|
||||
|
||||
$configWriter->setMultiple([
|
||||
'phoneNumberNumericSearch' => false,
|
||||
'phoneNumberInternational' => false,
|
||||
]);
|
||||
|
||||
if ($config->get('pdfEngine') === 'Tcpdf') {
|
||||
$configWriter->set('pdfEngine', 'Dompdf');
|
||||
}
|
||||
|
||||
$configWriter->save();
|
||||
}
|
||||
}
|
||||
125
application/Espo/Core/Upgrades/Migrations/V8_2/AfterUpgrade.php
Normal file
125
application/Espo/Core/Upgrades/Migrations/V8_2/AfterUpgrade.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V8_2;
|
||||
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\InjectableFactory;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\Template;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\Tools\Pdf\Template as PdfTemplate;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private InjectableFactory $injectableFactory,
|
||||
private Config $config,
|
||||
private EntityManager $entityManager,
|
||||
private Metadata $metadata
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$configWriter = $this->injectableFactory->create(Config\ConfigWriter::class);
|
||||
|
||||
$configWriter->setMultiple([
|
||||
'jobForceUtc' => true,
|
||||
]);
|
||||
|
||||
$configWriter->save();
|
||||
|
||||
$em = $this->entityManager;
|
||||
$config = $this->config;
|
||||
|
||||
$this->updateTemplates($em, $config);
|
||||
$this->updateTargetList($this->metadata);
|
||||
}
|
||||
|
||||
private function updateTemplates(EntityManager $entityManager, Config $config): void
|
||||
{
|
||||
if ($config->get('pdfEngine') !== 'Dompdf') {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var iterable<Template> $templates */
|
||||
$templates = $entityManager->getRDBRepositoryByClass(Template::class)
|
||||
->sth()
|
||||
->where(['pageFormat' => PdfTemplate::PAGE_FORMAT_CUSTOM])
|
||||
->find();
|
||||
|
||||
foreach ($templates as $template) {
|
||||
$width = $template->get('pageWidth') ?? 0.0;
|
||||
$height = $template->get('pageHeight') ?? 0.0;
|
||||
|
||||
$template->setMultiple([
|
||||
'pageWidth' => $width / 2.83465,
|
||||
'pageHeight' => $height / 2.83465,
|
||||
]);
|
||||
|
||||
$entityManager->saveEntity($template);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateTargetList(Metadata $metadata): void
|
||||
{
|
||||
$links = $metadata->get('entityDefs.TargetList.links') ?? [];
|
||||
|
||||
$toSave = false;
|
||||
|
||||
foreach ($links as $link => $defs) {
|
||||
if (empty($defs['isCustom'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$metadata->get("clientDefs.TargetList.relationshipPanels.$link.massSelect")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$metadata->set('recordDefs', 'TargetList', [
|
||||
'relationships' => [
|
||||
$link => [
|
||||
'massLink' => true,
|
||||
'linkRequiredForeignAccess' => 'read',
|
||||
'mandatoryAttributeList' => ['targetListIsOptedOut'],
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$toSave = true;
|
||||
}
|
||||
|
||||
if (!$toSave) {
|
||||
return;
|
||||
}
|
||||
|
||||
$metadata->save();
|
||||
}
|
||||
}
|
||||
147
application/Espo/Core/Upgrades/Migrations/V8_3/AfterUpgrade.php
Normal file
147
application/Espo/Core/Upgrades/Migrations/V8_3/AfterUpgrade.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V8_3;
|
||||
|
||||
use Doctrine\DBAL\Exception as DbalException;
|
||||
use Espo\Core\Templates\Entities\Event;
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Database\Helper;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\AuthenticationProvider;
|
||||
use Espo\Entities\Role;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\Part\Expression;
|
||||
use Espo\ORM\Query\UpdateBuilder;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private Metadata $metadata,
|
||||
private Config $config,
|
||||
private Helper $helper
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @throws DbalException
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateRoles();
|
||||
$this->updateMetadata();
|
||||
$this->updateAuthenticationProviders();
|
||||
$this->renameSubscription();
|
||||
}
|
||||
|
||||
private function updateRoles(): void
|
||||
{
|
||||
$query = UpdateBuilder::create()
|
||||
->in(Role::ENTITY_TYPE)
|
||||
->set(['mentionPermission' => Expression::column('assignmentPermission')])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($query);
|
||||
}
|
||||
|
||||
private function updateMetadata(): void
|
||||
{
|
||||
$defs = $this->metadata->get(['scopes']);
|
||||
|
||||
foreach ($defs as $entityType => $item) {
|
||||
$isCustom = $item['isCustom'] ?? false;
|
||||
$type = $item['type'] ?? false;
|
||||
|
||||
if (!$isCustom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($type !== Event::TEMPLATE_TYPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$clientDefs = $this->metadata->getCustom('clientDefs', $entityType) ?? (object) [];
|
||||
|
||||
$clientDefs->viewSetupHandlers ??= (object) [];
|
||||
|
||||
$clientDefs->viewSetupHandlers->{'record/detail'} = [
|
||||
"__APPEND__",
|
||||
"crm:handlers/event/reminders-handler"
|
||||
];
|
||||
|
||||
$clientDefs->viewSetupHandlers->{'record/edit'} = [
|
||||
"__APPEND__",
|
||||
"crm:handlers/event/reminders-handler"
|
||||
];
|
||||
|
||||
if (isset($clientDefs->dynamicLogic->fields->reminders)) {
|
||||
unset($clientDefs->dynamicLogic->fields->reminders);
|
||||
}
|
||||
|
||||
$this->metadata->saveCustom('clientDefs', $entityType, $clientDefs);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateAuthenticationProviders(): void
|
||||
{
|
||||
$collection = $this->entityManager->getRDBRepositoryByClass(AuthenticationProvider::class)
|
||||
->where(['method' => 'Oidc'])
|
||||
->find();
|
||||
|
||||
foreach ($collection as $entity) {
|
||||
$entity->set('oidcAuthorizationPrompt', $this->config->get('oidcAuthorizationPrompt'));
|
||||
|
||||
$this->entityManager->saveEntity($entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws DbalException
|
||||
*/
|
||||
private function renameSubscription(): void
|
||||
{
|
||||
$connection = $this->helper->getDbalConnection();
|
||||
$schemaManager = $connection->createSchemaManager();
|
||||
|
||||
if (!$schemaManager->tablesExist('subscription')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($schemaManager->tablesExist('stream_subscription')) {
|
||||
try {
|
||||
$schemaManager->dropTable('stream_subscription');
|
||||
} catch (DbalException) {
|
||||
$schemaManager->renameTable('stream_subscription', 'stream_subscription_waste');
|
||||
}
|
||||
}
|
||||
|
||||
$schemaManager->renameTable('subscription', 'stream_subscription');
|
||||
}
|
||||
}
|
||||
102
application/Espo/Core/Upgrades/Migrations/V8_4/AfterUpgrade.php
Normal file
102
application/Espo/Core/Upgrades/Migrations/V8_4/AfterUpgrade.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V8_4;
|
||||
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\ORM\Defs\Params\RelationParam;
|
||||
use Espo\ORM\Type\RelationType;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private Metadata $metadata,
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateMetadata();
|
||||
}
|
||||
|
||||
private function updateMetadata(): void
|
||||
{
|
||||
$defs = $this->metadata->get(['entityDefs']);
|
||||
|
||||
$toSave = false;
|
||||
|
||||
foreach ($defs as $entityType => $item) {
|
||||
if (!isset($item['links'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($item['links'] as $link => $linkDefs) {
|
||||
$type = $linkDefs['type'] ?? null;
|
||||
$foreignEntityType = $linkDefs['entity'] ?? null;
|
||||
$midKeys = $linkDefs[RelationParam::MID_KEYS] ?? null;
|
||||
$isCustom = $linkDefs['isCustom'] ?? false;
|
||||
|
||||
if ($type !== RelationType::HAS_MANY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($foreignEntityType !== $entityType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$midKeys) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$isCustom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($linkDefs['_keysSwappedAfterUpgrade'] ?? false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->metadata->set('entityDefs', $entityType, [
|
||||
'links' => [
|
||||
$link => [
|
||||
RelationParam::MID_KEYS => array_reverse($midKeys),
|
||||
'_keysSwappedAfterUpgrade' => true,
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$toSave = true;
|
||||
}
|
||||
|
||||
if ($toSave) {
|
||||
$this->metadata->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
205
application/Espo/Core/Upgrades/Migrations/V9_0/AfterUpgrade.php
Normal file
205
application/Espo/Core/Upgrades/Migrations/V9_0/AfterUpgrade.php
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V9_0;
|
||||
|
||||
use Espo\Core\ORM\Repository\Option\SaveOption;
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Entities\Preferences;
|
||||
use Espo\Entities\Role;
|
||||
use Espo\Entities\ScheduledJob;
|
||||
use Espo\Entities\User;
|
||||
use Espo\Modules\Crm\Entities\Account;
|
||||
use Espo\Modules\Crm\Entities\Contact;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\Part\Expression;
|
||||
use Espo\ORM\Query\UpdateBuilder;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private Metadata $metadata,
|
||||
private Config $config,
|
||||
private Config\ConfigWriter $configWriter,
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateRoles();
|
||||
$this->setReactionNotifications();
|
||||
$this->createScheduledJob();
|
||||
$this->setAclLinks();
|
||||
$this->fixTimezone();
|
||||
}
|
||||
|
||||
private function updateRoles(): void
|
||||
{
|
||||
$query = UpdateBuilder::create()
|
||||
->in(Role::ENTITY_TYPE)
|
||||
->set(['userCalendarPermission' => Expression::column('userPermission')])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($query);
|
||||
}
|
||||
|
||||
private function createScheduledJob(): void
|
||||
{
|
||||
$found = $this->entityManager
|
||||
->getRDBRepositoryByClass(ScheduledJob::class)
|
||||
->where(['job' => 'SendScheduledEmails'])
|
||||
->findOne();
|
||||
|
||||
if ($found) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->entityManager->createEntity(ScheduledJob::ENTITY_TYPE, [
|
||||
'name' => 'Send Scheduled Emails',
|
||||
'job' => 'SendScheduledEmails',
|
||||
'status' => ScheduledJob::STATUS_ACTIVE,
|
||||
'scheduling' => '*/10 * * * *',
|
||||
], [SaveOption::SKIP_ALL => true]);
|
||||
}
|
||||
|
||||
private function setReactionNotifications(): void
|
||||
{
|
||||
$users = $this->entityManager
|
||||
->getRDBRepositoryByClass(User::class)
|
||||
->sth()
|
||||
->where([
|
||||
'isActive' => true,
|
||||
'type' => [
|
||||
User::TYPE_ADMIN,
|
||||
User::TYPE_REGULAR,
|
||||
User::TYPE_PORTAL,
|
||||
]
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$preferences = $this->entityManager->getRepositoryByClass(Preferences::class)->getById($user->getId());
|
||||
|
||||
if (!$preferences) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$preferences->set('reactionNotifications', true);
|
||||
$this->entityManager->saveEntity($preferences);
|
||||
}
|
||||
}
|
||||
|
||||
private function setAclLinks(): void
|
||||
{
|
||||
/** @var array<string, array<string, mixed>> $scopes */
|
||||
$scopes = $this->metadata->get('scopes', []);
|
||||
|
||||
foreach ($scopes as $scope => $defs) {
|
||||
if (($defs['entity'] ?? false) && ($defs['isCustom'] ?? false)) {
|
||||
$this->setAclLinksForEntityType($scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function setAclLinksForEntityType(string $entityType): void
|
||||
{
|
||||
$relations = $this->entityManager
|
||||
->getDefs()
|
||||
->getEntity($entityType)
|
||||
->getRelationList();
|
||||
|
||||
$contactLink = null;
|
||||
$accountLink = null;
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
if (
|
||||
$relation->getName() === 'contact' &&
|
||||
$relation->tryGetForeignEntityType() === Contact::ENTITY_TYPE
|
||||
) {
|
||||
$contactLink = $relation->getName();
|
||||
}
|
||||
}
|
||||
|
||||
if (!$contactLink) {
|
||||
foreach ($relations as $relation) {
|
||||
if (
|
||||
$relation->getName() === 'contacts' &&
|
||||
$relation->tryGetForeignEntityType() === Contact::ENTITY_TYPE
|
||||
) {
|
||||
$contactLink = $relation->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
if (
|
||||
$relation->getName() === 'account' &&
|
||||
$relation->tryGetForeignEntityType() === Account::ENTITY_TYPE
|
||||
) {
|
||||
$accountLink = $relation->getName();
|
||||
}
|
||||
}
|
||||
|
||||
if (!$accountLink) {
|
||||
foreach ($relations as $relation) {
|
||||
if (
|
||||
$relation->getName() === 'accounts' &&
|
||||
$relation->tryGetForeignEntityType() === Account::ENTITY_TYPE
|
||||
) {
|
||||
$accountLink = $relation->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->metadata->set('aclDefs', $entityType, ['contactLink' => $contactLink]);
|
||||
$this->metadata->set('aclDefs', $entityType, ['accountLink' => $accountLink]);
|
||||
|
||||
$this->metadata->save();
|
||||
}
|
||||
|
||||
private function fixTimezone(): void
|
||||
{
|
||||
$map = [
|
||||
'Europe/Kiev' => 'Europe/Kyiv',
|
||||
'Europe/Uzhgorod' => 'Europe/Uzhhorod',
|
||||
'Europe/Zaporozhye' => 'Europe/Zaporozhye',
|
||||
];
|
||||
|
||||
$timeZone = $this->config->get('timeZone');
|
||||
|
||||
if (in_array($timeZone, array_keys($map))) {
|
||||
$timeZone = $map[$timeZone];
|
||||
|
||||
$this->configWriter->set('timeZone', $timeZone);
|
||||
$this->configWriter->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
180
application/Espo/Core/Upgrades/Migrations/V9_1/AfterUpgrade.php
Normal file
180
application/Espo/Core/Upgrades/Migrations/V9_1/AfterUpgrade.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V9_1;
|
||||
|
||||
use Espo\Core\ORM\Repository\Option\SaveOption;
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Crypt;
|
||||
use Espo\Core\Utils\Metadata;
|
||||
use Espo\Core\Utils\ObjectUtil;
|
||||
use Espo\Core\Utils\SystemUser;
|
||||
use Espo\Entities\InboundEmail;
|
||||
use Espo\Modules\Crm\Entities\KnowledgeBaseArticle;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\Part\Condition;
|
||||
use Espo\ORM\Query\Part\Expression;
|
||||
use Espo\Tools\Email\Util;
|
||||
use stdClass;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private Metadata $metadata,
|
||||
private Config $config,
|
||||
private Config\ConfigWriter $configWriter,
|
||||
private Crypt $crypt,
|
||||
private SystemUser $systemUser,
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->processKbArticles();
|
||||
$this->processDynamicLogicMetadata();
|
||||
$this->processGroupEmailAccount();
|
||||
}
|
||||
|
||||
private function processKbArticles(): void
|
||||
{
|
||||
if (!str_starts_with(php_sapi_name(), 'cli')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$articles = $this->entityManager
|
||||
->getRDBRepositoryByClass(KnowledgeBaseArticle::class)
|
||||
->sth()
|
||||
->select([
|
||||
'id',
|
||||
'body',
|
||||
'bodyPlain',
|
||||
])
|
||||
->limit(0, 3000)
|
||||
->find();
|
||||
|
||||
foreach ($articles as $article) {
|
||||
$plain = Util::stripHtml($article->getBody() ?? '') ?: null;
|
||||
|
||||
$article->set('bodyPlain', $plain);
|
||||
|
||||
$this->entityManager->saveEntity($article, [SaveOption::SKIP_HOOKS => true]);
|
||||
}
|
||||
}
|
||||
|
||||
private function processDynamicLogicMetadata(): void
|
||||
{
|
||||
/** @var string[] $scopes */
|
||||
$scopes = array_keys($this->metadata->get('clientDefs', []));
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
$customClientDefs = $this->metadata->getCustom('clientDefs', $scope);
|
||||
|
||||
if (!$customClientDefs instanceof stdClass) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!property_exists($customClientDefs, 'dynamicLogic') ||
|
||||
!$customClientDefs->dynamicLogic instanceof stdClass
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->metadata->saveCustom('logicDefs', $scope, $customClientDefs->dynamicLogic);
|
||||
|
||||
$customClientDefs = ObjectUtil::clone($customClientDefs);
|
||||
unset($customClientDefs->dynamicLogic);
|
||||
|
||||
$this->metadata->saveCustom('clientDefs', $scope, $customClientDefs);
|
||||
}
|
||||
}
|
||||
|
||||
private function processGroupEmailAccount(): void
|
||||
{
|
||||
if (!$this->config->get('smtpServer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$outboundEmailFromAddress = $this->config->get('outboundEmailFromAddress');
|
||||
|
||||
if (!$outboundEmailFromAddress) {
|
||||
return;
|
||||
}
|
||||
|
||||
$groupAccount = $this->entityManager
|
||||
->getRDBRepositoryByClass(InboundEmail::class)
|
||||
->where([
|
||||
'status' => InboundEmail::STATUS_ACTIVE,
|
||||
'useSmtp' => true,
|
||||
])
|
||||
->where(
|
||||
Condition::equal(
|
||||
Expression::lowerCase(
|
||||
Expression::column('emailAddress')
|
||||
),
|
||||
strtolower($outboundEmailFromAddress)
|
||||
)
|
||||
)
|
||||
->findOne();
|
||||
|
||||
$this->configWriter->set('smtpServer', null);
|
||||
|
||||
if ($groupAccount) {
|
||||
$this->configWriter->save();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$password = $this->config->get('smtpPassword');
|
||||
|
||||
$groupAccount = $this->entityManager->getRDBRepositoryByClass(InboundEmail::class)->getNew();
|
||||
|
||||
$groupAccount->setMultiple([
|
||||
'emailAddress' => $outboundEmailFromAddress,
|
||||
'name' => $outboundEmailFromAddress . ' (system)',
|
||||
'useImap' => false,
|
||||
'useSmtp' => true,
|
||||
'smtpHost' => $this->config->get('smtpServer'),
|
||||
'smtpPort' => $this->config->get('smtpPort'),
|
||||
'smtpAuth' => $this->config->get('smtpAuth'),
|
||||
'smtpAuthMechanism' => $this->config->get('smtpAuthMechanism') ?? 'login',
|
||||
'fromName' => $this->config->get('outboundEmailFromName'),
|
||||
'smtpUsername' => $this->config->get('smtpUsername'),
|
||||
'smtpPassword' => $password !== null ? $this->crypt->encrypt($password) : null,
|
||||
]);
|
||||
|
||||
$this->entityManager->saveEntity($groupAccount, [
|
||||
SaveOption::SKIP_HOOKS => true,
|
||||
SaveOption::CREATED_BY_ID => $this->systemUser->getId(),
|
||||
]);
|
||||
|
||||
$this->configWriter->save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://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 Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Upgrades\Migrations\V9_2;
|
||||
|
||||
use Espo\Core\Upgrades\Migration\Script;
|
||||
use Espo\Entities\Note;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\UpdateBuilder;
|
||||
|
||||
class AfterUpgrade implements Script
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
) {}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->updateNotes();
|
||||
}
|
||||
|
||||
private function updateNotes(): void
|
||||
{
|
||||
$update = UpdateBuilder::create()
|
||||
->in(Note::ENTITY_TYPE)
|
||||
->set([
|
||||
'type' => Note::TYPE_UPDATE,
|
||||
])
|
||||
->where(['type' => 'Status'])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($update);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user