Spaces:
No application file
No application file
File size: 5,326 Bytes
d2897cd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Field;
use Doctrine\DBAL\Exception\DriverException;
use Mautic\CoreBundle\Doctrine\Helper\ColumnSchemaHelper;
use Mautic\CoreBundle\Exception\SchemaException;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Field\Dispatcher\FieldColumnDispatcher;
use Mautic\LeadBundle\Field\Exception\AbortColumnCreateException;
use Mautic\LeadBundle\Field\Exception\AbortColumnUpdateException;
use Mautic\LeadBundle\Field\Exception\CustomFieldLimitException;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class CustomFieldColumn
{
public function __construct(
private ColumnSchemaHelper $columnSchemaHelper,
private SchemaDefinition $schemaDefinition,
private LoggerInterface $logger,
private LeadFieldSaver $leadFieldSaver,
private CustomFieldIndex $customFieldIndex,
private FieldColumnDispatcher $fieldColumnDispatcher,
private TranslatorInterface $translator
) {
}
/**
* @throws AbortColumnCreateException
* @throws AbortColumnUpdateException
* @throws CustomFieldLimitException
* @throws \Doctrine\DBAL\Exception
* @throws DriverException
* @throws \Doctrine\DBAL\Schema\SchemaException
* @throws SchemaException
*/
public function createLeadColumn(LeadField $leadField): void
{
$leadsSchema = $this->columnSchemaHelper->setName($leadField->getCustomFieldObject());
// We have to check if the LeadField entity is new and the column already exists .
// In such case we must throw an exception to warn users that the column already exists.
try {
$columnExists = $leadsSchema->checkColumnExists($leadField->getAlias(), $leadField->isNew());
if ($columnExists && $this->customFieldIndex->isUpdatePending($leadField)) {
$this->fieldColumnDispatcher->dispatchPreUpdateColumnEvent($leadField);
$this->processUpdateLeadColumn($leadField);
}
if ($columnExists) {
return;
}
} catch (SchemaException) {
// We use slightly different error message if the column already exists in this case.
throw new SchemaException($this->translator->trans('mautic.lead.field.column.already.exists', ['%field%' => $leadField->getName()], 'validators'));
}
try {
$this->fieldColumnDispatcher->dispatchPreAddColumnEvent($leadField);
} catch (AbortColumnCreateException $e) {
// Save the field metadata and throw the exception again to stop column creation.
// As the column should be created by a background job.
$this->leadFieldSaver->saveLeadFieldEntityWithoutColumnCreated($leadField);
throw $e;
}
$this->processCreateLeadColumn($leadField);
}
/**
* Create the field as its own column in the leads table.
*
* @throws CustomFieldLimitException
* @throws DriverException
* @throws \Doctrine\DBAL\Schema\SchemaException
* @throws SchemaException
*/
public function processCreateLeadColumn(LeadField $leadField, bool $saveLeadField = true): void
{
$leadsSchema = $this->columnSchemaHelper->setName($leadField->getCustomFieldObject());
// Check if column do not exist. This method could be called from plugins too.
if ($leadsSchema->checkColumnExists($leadField->getAlias())) {
return;
}
$schemaDefinition = $this->schemaDefinition->getSchemaDefinitionNonStatic(
$leadField->getAlias(),
$leadField->getType(),
(bool) $leadField->getIsUniqueIdentifier(),
(int) $leadField->getCharLengthLimit()
);
$leadsSchema->addColumn($schemaDefinition);
try {
$leadsSchema->executeChanges();
} catch (DriverException $e) {
$this->logger->warning($e->getMessage());
if (1118 === $e->getCode() /* ER_TOO_BIG_ROWSIZE */) {
throw new CustomFieldLimitException('mautic.lead.field.max_column_error');
}
throw $e;
}
if ($saveLeadField) {
// $leadField is a new entity (this is not executed for update), it was successfully added to the lead table > save it
$this->leadFieldSaver->saveLeadFieldEntity($leadField, true);
}
if ($leadField->isIsIndex() || $leadField->getIsUniqueIdentifier()) {
$this->customFieldIndex->addIndexOnColumn($leadField);
}
}
/**
* Updates the field column in the leads table.
*
* @throws DriverException
* @throws \Doctrine\DBAL\Schema\SchemaException
* @throws SchemaException
*/
public function processUpdateLeadColumn(LeadField $leadField): void
{
$hasIndex = $this->customFieldIndex->hasIndex($leadField);
if ($leadField->isIsIndex() && !$hasIndex) {
$this->customFieldIndex->addIndexOnColumn($leadField);
} elseif (!$leadField->isIsIndex() && $hasIndex) {
$this->customFieldIndex->dropIndexOnColumn($leadField);
}
$this->customFieldIndex->updateUniqueIdentifierIndex($leadField);
}
}
|