Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
class CanPublish extends Constraint
|
||||
{
|
||||
public string $message = 'mautic.lead_list.not_allowed_plugin_publish';
|
||||
|
||||
public string $integrationName;
|
||||
|
||||
public function getDefaultOption(): string
|
||||
{
|
||||
return 'integrationName';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Constraint;
|
||||
|
||||
use Mautic\PluginBundle\Event\PluginIsPublishedEvent;
|
||||
use Mautic\PluginBundle\PluginEvents;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
class CanPublishValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(private EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
}
|
||||
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (1 !== $value) {
|
||||
return;
|
||||
}
|
||||
if (!$constraint instanceof CanPublish) {
|
||||
throw new \Symfony\Component\Validator\Exception\UnexpectedTypeException($constraint, CanPublish::class);
|
||||
}
|
||||
$event = new PluginIsPublishedEvent($value, $constraint->integrationName);
|
||||
$event = $this->eventDispatcher->dispatch($event, PluginEvents::PLUGIN_IS_PUBLISHED_STATE_CHANGING);
|
||||
|
||||
if (!$event->isCanPublish()) {
|
||||
$this->context->buildViolation($event->getMessage())
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class CompanyFieldsType extends AbstractType
|
||||
{
|
||||
use FieldsTypeTrait;
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$this->buildFormFields($builder, $options, $options['integration_fields'], $options['mautic_fields'], 'company', $options['limit'], $options['start']);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$this->configureFieldOptions($resolver, 'company');
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'integration_company_fields';
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
$this->buildFieldView($view, $options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Mautic\CoreBundle\Form\Type\FormButtonsType;
|
||||
use Mautic\CoreBundle\Form\Type\StandAloneButtonType;
|
||||
use Mautic\CoreBundle\Form\Type\YesNoButtonGroupType;
|
||||
use Mautic\PluginBundle\Entity\Integration;
|
||||
use Mautic\PluginBundle\Form\Constraint\CanPublish;
|
||||
use Mautic\PluginBundle\Integration\AbstractIntegration;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<Integration>
|
||||
*/
|
||||
class DetailsType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->add('isPublished', YesNoButtonGroupType::class, [
|
||||
'constraints' => [
|
||||
new CanPublish($options['integration'] ?? ''),
|
||||
],
|
||||
]);
|
||||
|
||||
/** @var AbstractIntegration $integrationObject */
|
||||
$integrationObject = $options['integration_object'];
|
||||
/** @var Integration $integration */
|
||||
$integration = $options['data'];
|
||||
$formSettings = $integrationObject->getFormDisplaySettings();
|
||||
$decryptedKeys = $integrationObject->decryptApiKeys($integration->getApiKeys());
|
||||
$keys = $integrationObject->getRequiredKeyFields();
|
||||
|
||||
if (!empty($formSettings['hide_keys'])) {
|
||||
foreach ($formSettings['hide_keys'] as $key) {
|
||||
unset($keys[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$builder->add(
|
||||
'apiKeys',
|
||||
KeysType::class,
|
||||
[
|
||||
'label' => false,
|
||||
'integration_keys' => $keys,
|
||||
'data' => $decryptedKeys,
|
||||
'integration_object' => $integrationObject,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->addEventListener(
|
||||
FormEvents::PRE_SUBMIT,
|
||||
function (FormEvent $event) use ($keys, $decryptedKeys, $options): void {
|
||||
$data = $event->getData();
|
||||
$form = $event->getForm();
|
||||
|
||||
$form->add(
|
||||
'apiKeys',
|
||||
KeysType::class,
|
||||
[
|
||||
'label' => false,
|
||||
'integration_keys' => $keys,
|
||||
'data' => $decryptedKeys,
|
||||
'integration_object' => $options['integration_object'],
|
||||
'is_published' => (int) $data['isPublished'],
|
||||
]
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
if (!empty($formSettings['requires_authorization'])) {
|
||||
$label = ($integrationObject->isAuthorized()) ? 'reauthorize' : 'authorize';
|
||||
|
||||
$builder->add(
|
||||
'authButton',
|
||||
StandAloneButtonType::class,
|
||||
[
|
||||
'attr' => [
|
||||
'class' => 'btn btn-success btn-lg',
|
||||
'onclick' => 'Mautic.initiateIntegrationAuthorization()',
|
||||
'icon' => 'ri-key-2-line',
|
||||
],
|
||||
'label' => 'mautic.integration.form.'.$label,
|
||||
'disabled' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$features = $integrationObject->getSupportedFeatures();
|
||||
$tooltips = $integrationObject->getSupportedFeatureTooltips();
|
||||
if (!empty($features)) {
|
||||
// Check to see if the integration is a new entry and thus not configured
|
||||
$configured = null !== $integration->getId();
|
||||
$enabledFeatures = $integration->getSupportedFeatures();
|
||||
$data = ($configured) ? $enabledFeatures : $features;
|
||||
|
||||
$choices = [];
|
||||
foreach ($features as $f) {
|
||||
$choices['mautic.integration.form.feature.'.$f] = $f;
|
||||
}
|
||||
|
||||
$builder->add(
|
||||
'supportedFeatures',
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => $choices,
|
||||
'expanded' => true,
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'multiple' => true,
|
||||
'label' => 'mautic.integration.form.features',
|
||||
'required' => false,
|
||||
'data' => $data,
|
||||
'choice_attr' => function ($val) use ($tooltips): array {
|
||||
if (array_key_exists($val, $tooltips)) {
|
||||
return [
|
||||
'data-toggle' => 'tooltip',
|
||||
'title' => $tooltips[$val],
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$builder->add(
|
||||
'featureSettings',
|
||||
FeatureSettingsType::class,
|
||||
[
|
||||
'label' => 'mautic.integration.form.feature.settings',
|
||||
'required' => true,
|
||||
'data' => $integration->getFeatureSettings(),
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'integration' => $options['integration'],
|
||||
'integration_object' => $integrationObject,
|
||||
'lead_fields' => $options['lead_fields'],
|
||||
'company_fields' => $options['company_fields'],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add('name', HiddenType::class, ['data' => $options['integration']]);
|
||||
|
||||
$builder->add('in_auth', HiddenType::class, ['mapped' => false]);
|
||||
|
||||
$builder->add('buttons', FormButtonsType::class);
|
||||
|
||||
if (!empty($options['action'])) {
|
||||
$builder->setAction($options['action']);
|
||||
}
|
||||
|
||||
$integrationObject->modifyForm($builder, $options);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults(
|
||||
[
|
||||
'data_class' => Integration::class,
|
||||
]
|
||||
);
|
||||
|
||||
$resolver->setRequired(['integration', 'integration_object', 'lead_fields', 'company_fields']);
|
||||
$resolver->setAllowedTypes('integration_object', [AbstractIntegration::class]);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'integration_details';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class FeatureSettingsType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
protected RequestStack $requestStack,
|
||||
protected CoreParametersHelper $coreParametersHelper,
|
||||
protected LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormBuilderInterface<array<mixed>|null> $builder
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$integrationObject = $options['integration_object'];
|
||||
|
||||
// add custom feature settings
|
||||
$integrationObject->appendToForm($builder, $options['data'], 'features');
|
||||
$leadFields = $options['lead_fields'];
|
||||
$companyFields = $options['company_fields'];
|
||||
|
||||
$formModifier = function (FormInterface $form, $data, $method = 'get') use ($integrationObject, $leadFields, $companyFields): void {
|
||||
$integrationName = $integrationObject->getName();
|
||||
$session = $this->requestStack->getSession();
|
||||
$limit = $session->get(
|
||||
'mautic.plugin.'.$integrationName.'.lead.limit',
|
||||
$this->coreParametersHelper->get('default_pagelimit')
|
||||
);
|
||||
$page = $session->get('mautic.plugin.'.$integrationName.'.lead.page', 1);
|
||||
$companyPage = $session->get('mautic.plugin.'.$integrationName.'.company.page', 1);
|
||||
$settings = [
|
||||
'silence_exceptions' => false,
|
||||
'feature_settings' => $data,
|
||||
'ignore_field_cache' => (1 == $page && 'POST' !== strtoupper($method)) ? true : false,
|
||||
];
|
||||
|
||||
try {
|
||||
if (empty($fields)) {
|
||||
$fields = $integrationObject->getFormLeadFields($settings);
|
||||
$fields = $fields[0] ?? $fields;
|
||||
}
|
||||
|
||||
if (isset($settings['feature_settings']['objects']) and in_array('company', $settings['feature_settings']['objects'])) {
|
||||
if (empty($integrationCompanyFields)) {
|
||||
$integrationCompanyFields = $integrationObject->getFormCompanyFields($settings);
|
||||
}
|
||||
if (isset($integrationCompanyFields['company'])) {
|
||||
$integrationCompanyFields = $integrationCompanyFields['company'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($fields)) {
|
||||
$fields = [];
|
||||
}
|
||||
$error = '';
|
||||
} catch (\Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
$this->logger->error($e);
|
||||
|
||||
// Prevent pagination from confusing things by using the cache
|
||||
$page = 1;
|
||||
$fields = $integrationCompanyFields = [];
|
||||
}
|
||||
|
||||
$enableDataPriority = $integrationObject->getDataPriority();
|
||||
|
||||
$form->add(
|
||||
'leadFields',
|
||||
FieldsType::class,
|
||||
[
|
||||
'label' => 'mautic.integration.leadfield_matches',
|
||||
'required' => true,
|
||||
'mautic_fields' => $leadFields,
|
||||
'data' => $data,
|
||||
'integration_fields' => $fields,
|
||||
'enable_data_priority' => $enableDataPriority,
|
||||
'integration' => $integrationObject->getName(),
|
||||
'integration_object' => $integrationObject,
|
||||
'limit' => $limit,
|
||||
'page' => $page,
|
||||
'mapped' => false,
|
||||
'error_bubbling' => false,
|
||||
]
|
||||
);
|
||||
|
||||
if (!empty($integrationCompanyFields)) {
|
||||
$form->add(
|
||||
'companyFields',
|
||||
CompanyFieldsType::class,
|
||||
[
|
||||
'label' => 'mautic.integration.companyfield_matches',
|
||||
'required' => true,
|
||||
'mautic_fields' => $companyFields,
|
||||
'data' => $data,
|
||||
'integration_fields' => $integrationCompanyFields,
|
||||
'enable_data_priority' => $enableDataPriority,
|
||||
'integration' => $integrationObject->getName(),
|
||||
'integration_object' => $integrationObject,
|
||||
'limit' => $limit,
|
||||
'page' => $companyPage,
|
||||
'mapped' => false,
|
||||
'error_bubbling' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
if ('get' == $method && $error) {
|
||||
$form->addError(new FormError($error));
|
||||
}
|
||||
};
|
||||
|
||||
$builder->addEventListener(
|
||||
FormEvents::PRE_SET_DATA,
|
||||
function (FormEvent $event) use ($formModifier): void {
|
||||
$data = $event->getData();
|
||||
$formModifier($event->getForm(), $data);
|
||||
}
|
||||
);
|
||||
|
||||
$builder->addEventListener(
|
||||
FormEvents::PRE_SUBMIT,
|
||||
function (FormEvent $event) use ($formModifier): void {
|
||||
$data = $event->getData();
|
||||
$formModifier($event->getForm(), $data, 'post');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setRequired(['integration', 'integration_object', 'lead_fields', 'company_fields']);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'integration_featuresettings';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class FieldsType extends AbstractType
|
||||
{
|
||||
use FieldsTypeTrait;
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$this->buildFormFields($builder, $options, $options['integration_fields'], $options['mautic_fields'], '', $options['limit'], $options['start']);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$this->configureFieldOptions($resolver, 'lead');
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'integration_fields';
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
$this->buildFieldView($view, $options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Mautic\CoreBundle\Form\Type\ButtonGroupType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
trait FieldsTypeTrait
|
||||
{
|
||||
/**
|
||||
* @param string $fieldObject
|
||||
*/
|
||||
protected function buildFormFields(
|
||||
FormBuilderInterface $builder,
|
||||
array $options,
|
||||
array $integrationFields,
|
||||
array $mauticFields,
|
||||
$fieldObject,
|
||||
$limit,
|
||||
$start,
|
||||
) {
|
||||
$builder->addEventListener(
|
||||
FormEvents::PRE_SET_DATA,
|
||||
function (FormEvent $event) use ($options, $integrationFields, $mauticFields, $fieldObject, $limit, $start): void {
|
||||
$form = $event->getForm();
|
||||
$index = 0;
|
||||
$choices = [];
|
||||
$requiredFields = [];
|
||||
$optionalFields = [];
|
||||
$group = [];
|
||||
$fieldData = $event->getData();
|
||||
|
||||
foreach ($mauticFields as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$mauticFields[$key] = array_flip($value);
|
||||
}
|
||||
}
|
||||
|
||||
// First loop to build options
|
||||
foreach ($integrationFields as $field => $details) {
|
||||
$groupName = '0default';
|
||||
if (is_array($details)) {
|
||||
if (isset($details['group'])) {
|
||||
if (!isset($choices[$details['group']])) {
|
||||
$choices[$details['group']] = [];
|
||||
}
|
||||
$label = $details['optionLabel'] ?? $details['label'];
|
||||
$group[$field] = $groupName = $details['group'];
|
||||
$choices[$field] = $label;
|
||||
} else {
|
||||
$choices[$field] = $details['label'];
|
||||
}
|
||||
} else {
|
||||
$choices[$field] = $details;
|
||||
}
|
||||
|
||||
if (!isset($requiredFields[$groupName])) {
|
||||
$requiredFields[$groupName] = [];
|
||||
$optionalFields[$groupName] = [];
|
||||
}
|
||||
|
||||
if (is_array($details) && (!empty($details['required']) || 'Email' == $choices[$field])) {
|
||||
$requiredFields[$groupName][$field] = $details;
|
||||
} else {
|
||||
$optionalFields[$groupName][$field] = $details;
|
||||
}
|
||||
}
|
||||
|
||||
// Order the fields by label
|
||||
ksort($requiredFields, SORT_NATURAL);
|
||||
ksort($optionalFields, SORT_NATURAL);
|
||||
|
||||
$sortFieldsFunction = function ($a, $b): int {
|
||||
if (is_array($a)) {
|
||||
$aLabel = $a['optionLabel'] ?? $a['label'];
|
||||
} else {
|
||||
$aLabel = $a;
|
||||
}
|
||||
|
||||
if (is_array($b)) {
|
||||
$bLabel = $b['optionLabel'] ?? $b['label'];
|
||||
} else {
|
||||
$bLabel = $b;
|
||||
}
|
||||
|
||||
return strnatcasecmp($aLabel, $bLabel);
|
||||
};
|
||||
|
||||
$fields = [];
|
||||
foreach ($requiredFields as $groupedFields) {
|
||||
uasort($groupedFields, $sortFieldsFunction);
|
||||
|
||||
$fields = array_merge($fields, $groupedFields);
|
||||
}
|
||||
foreach ($optionalFields as $groupedFields) {
|
||||
uasort($groupedFields, $sortFieldsFunction);
|
||||
|
||||
$fields = array_merge($fields, $groupedFields);
|
||||
}
|
||||
|
||||
// Ensure that fields aren't hidden
|
||||
if ($start > count($fields) || 0 == $options['page']) {
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
$paginatedFields = array_slice($fields, $start, $limit);
|
||||
$fieldsName = 'leadFields';
|
||||
if ($fieldObject) {
|
||||
$fieldsName = $fieldObject.'Fields';
|
||||
}
|
||||
if (isset($fieldData[$fieldsName])) {
|
||||
$fieldData[$fieldsName] = $options['integration_object']->formatMatchedFields($fieldData[$fieldsName]);
|
||||
}
|
||||
|
||||
foreach ($paginatedFields as $field => $details) {
|
||||
$matched = isset($fieldData[$fieldsName][$field]);
|
||||
$required = (int) (!empty($integrationFields[$field]['required']) || 'Email' == $choices[$field]);
|
||||
++$index;
|
||||
$form->add(
|
||||
'label_'.$index,
|
||||
TextType::class,
|
||||
[
|
||||
'label' => false,
|
||||
'data' => $choices[$field],
|
||||
'attr' => [
|
||||
'class' => 'form-control integration-fields',
|
||||
'data-required' => $required,
|
||||
'data-label' => $choices[$field],
|
||||
'placeholder' => $group[$field] ?? '',
|
||||
'readonly' => true,
|
||||
],
|
||||
'by_reference' => true,
|
||||
'mapped' => false,
|
||||
]
|
||||
);
|
||||
if (isset($options['enable_data_priority']) and $options['enable_data_priority']) {
|
||||
$updateName = 'update_mautic';
|
||||
|
||||
if ($fieldObject) {
|
||||
$updateName .= '_'.$fieldObject;
|
||||
}
|
||||
|
||||
$forceDirection = false;
|
||||
$disabled = (isset($fieldData[$fieldsName][$field])) ? $options['integration_object']->isCompoundMauticField($fieldData[$fieldsName][$field]) : false;
|
||||
$data = isset($fieldData[$updateName][$field]) ? (int) $fieldData[$updateName][$field] : 1;
|
||||
|
||||
// Force to use just one way for certainly fields
|
||||
if (isset($fields[$field]['update_mautic'])) {
|
||||
$data = (bool) $fields[$field]['update_mautic'];
|
||||
$disabled = true;
|
||||
$forceDirection = true;
|
||||
}
|
||||
|
||||
$form->add(
|
||||
$updateName.$index,
|
||||
ButtonGroupType::class,
|
||||
[
|
||||
'choices' => [
|
||||
'<btn class="btn-nospin ri-arrow-left-circle-line"></btn>' => 0,
|
||||
'<btn class="btn-nospin ri-arrow-right-circle-line"></btn>' => 1,
|
||||
],
|
||||
'label' => false,
|
||||
'data' => $data,
|
||||
'placeholder' => false,
|
||||
'attr' => [
|
||||
'data-toggle' => 'tooltip',
|
||||
'title' => 'mautic.plugin.direction.data.update',
|
||||
'disabled' => $disabled,
|
||||
'forceDirection'=> $forceDirection,
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if (!$fieldObject) {
|
||||
$mauticFields['mautic.lead.report.contact_id'] = 'mauticContactId';
|
||||
$mauticFields['mautic.plugin.integration.contact.timeline.link'] = 'mauticContactTimelineLink';
|
||||
$mauticFields['mautic.plugin.integration.contact.donotcontact.email'] = 'mauticContactIsContactableByEmail';
|
||||
}
|
||||
|
||||
$form->add(
|
||||
'm_'.$index,
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => $mauticFields,
|
||||
'label' => false,
|
||||
'data' => $matched && isset($fieldData[$fieldsName][$field]) ? $fieldData[$fieldsName][$field] : '',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'field-selector',
|
||||
'data-placeholder' => ' ',
|
||||
'data-required' => $required,
|
||||
'data-value' => $matched && isset($fieldData[$fieldsName][$field]) ? $fieldData[$fieldsName][$field] : '',
|
||||
'data-choices' => $mauticFields,
|
||||
],
|
||||
]
|
||||
);
|
||||
$form->add(
|
||||
'i_'.$index,
|
||||
HiddenType::class,
|
||||
[
|
||||
'data' => $field,
|
||||
'attr' => [
|
||||
'data-required' => $required,
|
||||
'data-value' => $field,
|
||||
],
|
||||
]
|
||||
);
|
||||
$form->add(
|
||||
$field,
|
||||
HiddenType::class,
|
||||
[
|
||||
'data' => $index,
|
||||
'attr' => [
|
||||
'data-required' => $required,
|
||||
'data-value' => $index,
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected function configureFieldOptions(OptionsResolver $resolver, $object)
|
||||
{
|
||||
$resolver->setRequired(['integration_fields', 'mautic_fields', 'integration', 'integration_object', 'page']);
|
||||
$resolver->setDefined([('lead' === $object) ? 'update_mautic' : 'update_mautic_company']);
|
||||
$resolver->setDefaults(
|
||||
[
|
||||
'special_instructions' => function (Options $options) {
|
||||
[$specialInstructions, $alertType] = $options['integration_object']->getFormNotes('leadfield_match');
|
||||
|
||||
return $specialInstructions;
|
||||
},
|
||||
'alert_type' => function (Options $options) {
|
||||
[$specialInstructions, $alertType] = $options['integration_object']->getFormNotes('leadfield_match');
|
||||
|
||||
return $alertType;
|
||||
},
|
||||
'allow_extra_fields' => true,
|
||||
'enable_data_priority' => false,
|
||||
'totalFields' => fn (Options $options): int => count($options['integration_fields']),
|
||||
'fixedPageNum' => fn (Options $options): float => ceil($options['totalFields'] / $options['limit']),
|
||||
'limit' => 10,
|
||||
'start' => fn (Options $options): int => (1 === (int) $options['page']) ? 0 : ((int) $options['page'] - 1) * (int) $options['limit'],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function buildFieldView(FormView $view, array $options)
|
||||
{
|
||||
$view->vars['specialInstructions'] = $options['special_instructions'];
|
||||
$view->vars['alertType'] = $options['alert_type'];
|
||||
$view->vars['integration'] = $options['integration'];
|
||||
$view->vars['totalFields'] = $options['totalFields'];
|
||||
$view->vars['page'] = $options['page'];
|
||||
$view->vars['fixedPageNum'] = $options['fixedPageNum'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class IntegrationCampaignsType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->add(
|
||||
'campaign_member_status',
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => array_flip($options['campaignContactStatus']),
|
||||
'attr' => [
|
||||
'class' => 'form-control', ],
|
||||
'label' => 'mautic.plugin.integration.campaigns.member.status',
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults(
|
||||
['campaignContactStatus' => []]);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'integration_campaign_status';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>|mixed>
|
||||
*/
|
||||
class IntegrationConfigType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
if (null != $options['integration']) {
|
||||
$options['integration']->appendToForm($builder, $options['data'], 'integration');
|
||||
}
|
||||
|
||||
if (!empty($options['campaigns'])) {
|
||||
$builder->add(
|
||||
'campaigns',
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => array_flip($options['campaigns']),
|
||||
'attr' => [
|
||||
'class' => 'form-control', 'onchange' => 'Mautic.getIntegrationCampaignStatus(this);', ],
|
||||
'label' => 'mautic.plugin.integration.campaigns',
|
||||
'placeholder' => 'mautic.plugin.config.campaign.member.chooseone',
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setRequired(['integration']);
|
||||
$resolver->setDefaults([
|
||||
'label' => false,
|
||||
'campaigns' => [],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Mautic\PluginBundle\Helper\IntegrationHelper;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<mixed>
|
||||
*/
|
||||
class IntegrationsListType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
private IntegrationHelper $integrationHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$integrationObjects = $this->integrationHelper->getIntegrationObjects(null, $options['supported_features'], true);
|
||||
$integrations = ['' => ''];
|
||||
|
||||
foreach ($integrationObjects as $object) {
|
||||
$settings = $object->getIntegrationSettings();
|
||||
|
||||
if ($settings->isPublished()) {
|
||||
$pluginName = $settings->getPlugin()->getName();
|
||||
if (!isset($integrations[$pluginName])) {
|
||||
$integrations[$pluginName] = [];
|
||||
}
|
||||
$integrations[$pluginName][$object->getDisplayName()] = $object->getName();
|
||||
}
|
||||
}
|
||||
|
||||
$builder->add(
|
||||
'integration',
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => $integrations,
|
||||
'expanded' => false,
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'multiple' => false,
|
||||
'label' => 'mautic.integration.integration',
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'tooltip' => 'mautic.integration.integration.tooltip',
|
||||
'onchange' => 'Mautic.getIntegrationConfig(this);',
|
||||
],
|
||||
'required' => true,
|
||||
'constraints' => [
|
||||
new NotBlank(
|
||||
['message' => 'mautic.core.value.required']
|
||||
),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$formModifier = function (FormEvent $event) use ($integrationObjects): void {
|
||||
$data = $event->getData();
|
||||
$form = $event->getForm();
|
||||
$statusChoices = [];
|
||||
$campaignChoices = [];
|
||||
|
||||
if (!empty($data['integration'])) {
|
||||
$integrationObject = $this->integrationHelper->getIntegrationObject($data['integration']);
|
||||
if (method_exists($integrationObject, 'getCampaigns')) {
|
||||
$campaigns = $integrationObject->getCampaigns();
|
||||
|
||||
if (isset($campaigns['records']) && !empty($campaigns['records'])) {
|
||||
foreach ($campaigns['records'] as $campaign) {
|
||||
$campaignChoices[$campaign['Id']] = $campaign['Name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (method_exists($integrationObject, 'getCampaignMemberStatus') && isset($data['config']['campaigns'])) {
|
||||
$campaignStatus = $integrationObject->getCampaignMemberStatus($data['config']['campaigns']);
|
||||
|
||||
if (isset($campaignStatus['records']) && !empty($campaignStatus['records'])) {
|
||||
foreach ($campaignStatus['records'] as $campaignS) {
|
||||
$statusChoices[$campaignS['Label']] = $campaignS['Label'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$form->add(
|
||||
'config',
|
||||
IntegrationConfigType::class,
|
||||
[
|
||||
'label' => false,
|
||||
'attr' => [
|
||||
'class' => 'integration-config-container',
|
||||
],
|
||||
'integration' => isset($data['integration'], $integrationObjects[$data['integration']]) ? $integrationObjects[$data['integration']] : null,
|
||||
'campaigns' => $campaignChoices,
|
||||
'data' => $data['config'] ?? [],
|
||||
]
|
||||
);
|
||||
|
||||
$hideClass = (isset($data['campaign_member_status']) && !empty($data['campaign_member_status']['campaign_member_status'])) ? '' : ' hide';
|
||||
$form->add(
|
||||
'campaign_member_status',
|
||||
IntegrationCampaignsType::class,
|
||||
[
|
||||
'label' => false,
|
||||
'attr' => [
|
||||
'class' => 'integration-campaigns-status'.$hideClass,
|
||||
],
|
||||
'campaignContactStatus' => $statusChoices,
|
||||
'data' => $data['campaign_member_status'] ?? [],
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, $formModifier);
|
||||
|
||||
$builder->addEventListener(FormEvents::PRE_SUBMIT, $formModifier);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefined(['supported_features']);
|
||||
$resolver->setDefaults(
|
||||
[
|
||||
'supported_features' => 'push_lead',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'integration_list';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PluginBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class KeysType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$object = $options['integration_object'];
|
||||
$secretKeys = $object->getSecretKeys();
|
||||
$requiredKeys = $object->getRequiredKeyFields();
|
||||
|
||||
foreach ($options['integration_keys'] as $key => $label) {
|
||||
$isSecret = in_array($key, $secretKeys);
|
||||
$required = (isset($requiredKeys[$key]));
|
||||
|
||||
// Password fields are going to be blank even if a value exists so only require if a password is not already saved
|
||||
if ($isSecret && !empty($options['data'][$key])) {
|
||||
$required = false;
|
||||
}
|
||||
|
||||
$constraints = ($required)
|
||||
? [
|
||||
new Callback(
|
||||
function ($validateMe, ExecutionContextInterface $context) use ($options): void {
|
||||
if (empty($validateMe) && !empty($options['is_published'])) {
|
||||
$context->buildViolation('mautic.core.value.required')->addViolation();
|
||||
}
|
||||
}
|
||||
),
|
||||
] : [];
|
||||
|
||||
$type = ($isSecret) ? PasswordType::class : TextType::class;
|
||||
|
||||
$builder->add(
|
||||
$key,
|
||||
$type,
|
||||
[
|
||||
'label' => $label,
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => (PasswordType::class === $type) ? '**************' : '',
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
'required' => $required,
|
||||
'constraints' => $constraints,
|
||||
'error_bubbling' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
$object->appendToForm($builder, $options['data'], 'keys');
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setRequired(['integration_object', 'integration_keys']);
|
||||
$resolver->setDefined(['secret_keys']);
|
||||
$resolver->setDefaults(['secret_keys' => [], 'is_published' => true]);
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'integration_keys';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user