Spaces:
No application file
No application file
| namespace Mautic\PluginBundle\Controller; | |
| use Doctrine\ORM\EntityManagerInterface; | |
| use Mautic\CoreBundle\Controller\FormController; | |
| use Mautic\CoreBundle\Helper\InputHelper; | |
| use Mautic\PluginBundle\Event\PluginIntegrationAuthRedirectEvent; | |
| use Mautic\PluginBundle\Event\PluginIntegrationEvent; | |
| use Mautic\PluginBundle\Facade\ReloadFacade; | |
| use Mautic\PluginBundle\Form\Type\DetailsType; | |
| use Mautic\PluginBundle\Integration\AbstractIntegration; | |
| use Mautic\PluginBundle\Model\PluginModel; | |
| use Mautic\PluginBundle\PluginEvents; | |
| use Psr\Log\LoggerInterface; | |
| use Symfony\Component\Form\FormError; | |
| use Symfony\Component\HttpFoundation\JsonResponse; | |
| use Symfony\Component\HttpFoundation\RedirectResponse; | |
| use Symfony\Component\HttpFoundation\Request; | |
| use Symfony\Component\HttpFoundation\Response; | |
| class PluginController extends FormController | |
| { | |
| /** | |
| * @return JsonResponse|Response | |
| */ | |
| public function indexAction(Request $request) | |
| { | |
| if (!$this->security->isGranted('plugin:plugins:manage')) { | |
| return $this->accessDenied(); | |
| } | |
| /** @var PluginModel $pluginModel */ | |
| $pluginModel = $this->getModel('plugin'); | |
| // List of plugins for filter and to show as a single integration | |
| $plugins = $pluginModel->getEntities( | |
| [ | |
| 'filter' => [ | |
| 'force' => [ | |
| [ | |
| 'column' => 'p.isMissing', | |
| 'expr' => 'eq', | |
| 'value' => 0, | |
| ], | |
| ], | |
| ], | |
| 'hydration_mode' => 'hydrate_array', | |
| ] | |
| ); | |
| $session = $request->getSession(); | |
| $pluginFilter = $request->get('plugin', $session->get('mautic.integrations.filter', '')); | |
| $session->set('mautic.integrations.filter', $pluginFilter); | |
| /** @var \Mautic\PluginBundle\Helper\IntegrationHelper $integrationHelper */ | |
| $integrationHelper = $this->factory->getHelper('integration'); | |
| $integrationObjects = $integrationHelper->getIntegrationObjects(null, null, true); | |
| $integrations = $foundPlugins = []; | |
| foreach ($integrationObjects as $name => $object) { | |
| $settings = $object->getIntegrationSettings(); | |
| $plugin = $settings->getPlugin(); | |
| $pluginId = $plugin ? $plugin->getId() : $name; | |
| if (isset($plugins[$pluginId]) || $pluginId === $name) { | |
| $integrations[$name] = [ | |
| 'name' => $object->getName(), | |
| 'display' => $object->getDisplayName(), | |
| 'icon' => $integrationHelper->getIconPath($object), | |
| 'enabled' => $settings->isPublished(), | |
| 'plugin' => $pluginId, | |
| 'isBundle' => false, | |
| ]; | |
| } | |
| $foundPlugins[$pluginId] = true; | |
| } | |
| $nonIntegrationPlugins = array_diff_key($plugins, $foundPlugins); | |
| foreach ($nonIntegrationPlugins as $plugin) { | |
| $integrations[$plugin['name']] = [ | |
| 'name' => $plugin['bundle'], | |
| 'display' => $plugin['name'], | |
| 'icon' => $integrationHelper->getIconPath($plugin), | |
| 'enabled' => true, | |
| 'plugin' => $plugin['id'], | |
| 'description' => $plugin['description'], | |
| 'isBundle' => true, | |
| ]; | |
| } | |
| // sort by name | |
| uksort( | |
| $integrations, | |
| fn ($a, $b): int => strnatcasecmp($a, $b) | |
| ); | |
| $tmpl = $request->isXmlHttpRequest() ? $request->get('tmpl', 'index') : 'index'; | |
| if (!empty($pluginFilter)) { | |
| foreach ($plugins as $plugin) { | |
| if ($plugin['id'] == $pluginFilter) { | |
| $pluginName = $plugin['name']; | |
| $pluginId = $plugin['id']; | |
| break; | |
| } | |
| } | |
| } | |
| return $this->delegateView( | |
| [ | |
| 'viewParameters' => [ | |
| 'items' => $integrations, | |
| 'tmpl' => $tmpl, | |
| 'pluginFilter' => ($pluginFilter) ? ['id' => $pluginId, 'name' => $pluginName] : false, | |
| 'plugins' => $plugins, | |
| ], | |
| 'contentTemplate' => '@MauticPlugin/Integration/grid.html.twig', | |
| 'passthroughVars' => [ | |
| 'activeLink' => '#mautic_plugin_index', | |
| 'mauticContent' => 'integration', | |
| 'route' => $this->generateUrl('mautic_plugin_index'), | |
| ], | |
| ] | |
| ); | |
| } | |
| /** | |
| * @param string $name | |
| * | |
| * @return JsonResponse|Response | |
| */ | |
| public function configAction(Request $request, EntityManagerInterface $em, LoggerInterface $mauticLogger, $name, $activeTab = 'details-container', $page = 1) | |
| { | |
| if (!$this->security->isGranted('plugin:plugins:manage')) { | |
| return $this->accessDenied(); | |
| } | |
| if (!empty($request->get('activeTab'))) { | |
| $activeTab = $request->get('activeTab'); | |
| } | |
| $session = $request->getSession(); | |
| $integrationDetailsPost = $request->request->get('integration_details') ?? []; | |
| $authorize = empty($integrationDetailsPost['in_auth']) ? false : true; | |
| /** @var \Mautic\PluginBundle\Helper\IntegrationHelper $integrationHelper */ | |
| $integrationHelper = $this->factory->getHelper('integration'); | |
| /** @var AbstractIntegration $integrationObject */ | |
| $integrationObject = $integrationHelper->getIntegrationObject($name); | |
| // Verify that the requested integration exists | |
| if (empty($integrationObject)) { | |
| throw $this->createNotFoundException($this->translator->trans('mautic.core.url.error.404')); | |
| } | |
| $object = ('leadFieldsContainer' === $activeTab) ? 'lead' : 'company'; | |
| $limit = $this->coreParametersHelper->get('default_pagelimit'); | |
| $start = (1 === $page) ? 0 : (($page - 1) * $limit); | |
| if ($start < 0) { | |
| $start = 0; | |
| } | |
| $session->set('mautic.plugin.'.$name.'.'.$object.'.start', $start); | |
| $session->set('mautic.plugin.'.$name.'.'.$object.'.page', $page); | |
| /** @var PluginModel $pluginModel */ | |
| $pluginModel = $this->getModel('plugin'); | |
| $leadFields = $pluginModel->getLeadFields(); | |
| $companyFields = $pluginModel->getCompanyFields(); | |
| /** @var AbstractIntegration $integrationObject */ | |
| $entity = $integrationObject->getIntegrationSettings(); | |
| $form = $this->createForm( | |
| DetailsType::class, | |
| $entity, | |
| [ | |
| 'integration' => $entity->getName(), | |
| 'lead_fields' => $leadFields, | |
| 'company_fields' => $companyFields, | |
| 'integration_object' => $integrationObject, | |
| 'action' => $this->generateUrl('mautic_plugin_config', ['name' => $name]), | |
| ] | |
| ); | |
| if ('POST' == $request->getMethod()) { | |
| $valid = false; | |
| if (!$cancelled = $this->isFormCancelled($form)) { | |
| $currentKeys = $integrationObject->getDecryptedApiKeys($entity); | |
| $currentFeatureSettings = $entity->getFeatureSettings(); | |
| $valid = $this->isFormValid($form); | |
| if ($authorize || $valid) { | |
| $integration = $entity->getName(); | |
| if (isset($form['apiKeys'])) { | |
| $keys = $form['apiKeys']->getData(); | |
| // Prevent merged keys | |
| $secretKeys = $integrationObject->getSecretKeys(); | |
| foreach ($secretKeys as $secretKey) { | |
| if (empty($keys[$secretKey]) && !empty($currentKeys[$secretKey])) { | |
| $keys[$secretKey] = $currentKeys[$secretKey]; | |
| } | |
| } | |
| $integrationObject->encryptAndSetApiKeys($keys, $entity); | |
| } | |
| if (!$authorize) { | |
| $features = $entity->getSupportedFeatures(); | |
| if (in_array('public_profile', $features) || in_array('push_lead', $features)) { | |
| // Ungroup the fields | |
| $mauticLeadFields = []; | |
| foreach ($leadFields as $groupFields) { | |
| $mauticLeadFields = array_merge($mauticLeadFields, $groupFields); | |
| } | |
| $mauticCompanyFields = []; | |
| foreach ($companyFields as $groupFields) { | |
| $mauticCompanyFields = array_merge($mauticCompanyFields, $groupFields); | |
| } | |
| if ($missing = $integrationObject->cleanUpFields($entity, $mauticLeadFields, $mauticCompanyFields)) { | |
| if ($entity->getIsPublished()) { | |
| // Only fail validation if the integration is enabled | |
| if (!empty($missing['leadFields'])) { | |
| $valid = false; | |
| $form->get('featureSettings')->get('leadFields')->addError( | |
| new FormError( | |
| $this->translator->trans('mautic.plugin.field.required_mapping_missing', [], 'validators') | |
| ) | |
| ); | |
| } | |
| if (!empty($missing['companyFields'])) { | |
| $valid = false; | |
| $form->get('featureSettings')->get('companyFields')->addError( | |
| new FormError( | |
| $this->translator->trans('mautic.plugin.field.required_mapping_missing', [], 'validators') | |
| ) | |
| ); | |
| } | |
| } | |
| } | |
| } | |
| } else { | |
| // make sure they aren't overwritten because of API connection issues | |
| $entity->setFeatureSettings($currentFeatureSettings); | |
| } | |
| if ($valid || $authorize) { | |
| $dispatcher = $this->dispatcher; | |
| $mauticLogger->info('Dispatching integration config save event.'); | |
| if ($dispatcher->hasListeners(PluginEvents::PLUGIN_ON_INTEGRATION_CONFIG_SAVE)) { | |
| $mauticLogger->info('Event dispatcher has integration config save listeners.'); | |
| $event = new PluginIntegrationEvent($integrationObject); | |
| $dispatcher->dispatch($event, PluginEvents::PLUGIN_ON_INTEGRATION_CONFIG_SAVE); | |
| $entity = $event->getEntity(); | |
| } | |
| $em->persist($entity); | |
| $em->flush(); | |
| } | |
| if ($authorize) { | |
| // redirect to the oauth URL | |
| /** @var AbstractIntegration $integrationObject */ | |
| $event = $this->dispatcher->dispatch( | |
| new PluginIntegrationAuthRedirectEvent( | |
| $integrationObject, | |
| $integrationObject->getAuthLoginUrl() | |
| ), | |
| PluginEvents::PLUGIN_ON_INTEGRATION_AUTH_REDIRECT | |
| ); | |
| $oauthUrl = $event->getAuthUrl(); | |
| return new JsonResponse( | |
| [ | |
| 'integration' => $integration, | |
| 'authUrl' => $oauthUrl, | |
| 'authorize' => 1, | |
| 'popupBlockerMessage' => $this->translator->trans('mautic.core.popupblocked'), | |
| ] | |
| ); | |
| } | |
| } | |
| } | |
| if (($cancelled || ($valid && !$this->isFormApplied($form))) && !$authorize) { | |
| // Close the modal and return back to the list view | |
| return new JsonResponse( | |
| [ | |
| 'closeModal' => 1, | |
| 'enabled' => $entity->getIsPublished(), | |
| 'name' => $integrationObject->getName(), | |
| 'mauticContent' => 'integrationConfig', | |
| 'sidebar' => $this->get('twig')->render('@MauticCore/LeftPanel/index.html.twig'), | |
| ] | |
| ); | |
| } | |
| } | |
| $template = $integrationObject->getFormTemplate(); | |
| $objectTheme = $integrationObject->getFormTheme(); | |
| $themes = [ | |
| '@MauticPlugin/FormTheme/Integration/layout.html.twig', | |
| ]; | |
| if (is_array($objectTheme)) { | |
| $themes = array_merge($themes, $objectTheme); | |
| } elseif (is_string($objectTheme)) { | |
| $themes[] = $objectTheme; | |
| } | |
| $themes = array_unique($themes); | |
| $formSettings = $integrationObject->getFormSettings(); | |
| $callbackUrl = !empty($formSettings['requires_callback']) ? $integrationObject->getAuthCallbackUrl() : ''; | |
| $formNotes = []; | |
| $noteSections = ['authorization', 'features', 'feature_settings', 'custom']; | |
| foreach ($noteSections as $section) { | |
| if ('custom' === $section) { | |
| $formNotes[$section] = $integrationObject->getFormNotes($section); | |
| } else { | |
| [$specialInstructions, $alertType] = $integrationObject->getFormNotes($section); | |
| if (!empty($specialInstructions)) { | |
| $formNotes[$section] = [ | |
| 'note' => $specialInstructions, | |
| 'type' => $alertType, | |
| ]; | |
| } | |
| } | |
| } | |
| return $this->delegateView( | |
| [ | |
| 'viewParameters' => [ | |
| 'form' => $form->createView(), | |
| 'description' => $integrationObject->getDescription(), | |
| 'formSettings' => $formSettings, | |
| 'formNotes' => $formNotes, | |
| 'callbackUrl' => $callbackUrl, | |
| 'activeTab' => $activeTab, | |
| 'formThemes' => $themes, | |
| ], | |
| 'contentTemplate' => $template, | |
| 'passthroughVars' => [ | |
| 'activeLink' => '#mautic_plugin_index', | |
| 'mauticContent' => 'integrationConfig', | |
| 'route' => false, | |
| 'sidebar' => $this->get('twig')->render('@MauticCore/LeftPanel/index.html.twig'), | |
| ], | |
| ] | |
| ); | |
| } | |
| /** | |
| * @return array|JsonResponse|RedirectResponse|Response | |
| */ | |
| public function infoAction($name) | |
| { | |
| if (!$this->security->isGranted('plugin:plugins:manage')) { | |
| return $this->accessDenied(); | |
| } | |
| /** @var PluginModel $pluginModel */ | |
| $pluginModel = $this->getModel('plugin'); | |
| $bundle = $pluginModel->getRepository()->findOneBy( | |
| [ | |
| 'bundle' => InputHelper::clean($name), | |
| ] | |
| ); | |
| if (!$bundle) { | |
| return $this->accessDenied(); | |
| } | |
| /** @var \Mautic\PluginBundle\Helper\IntegrationHelper $integrationHelper */ | |
| $integrationHelper = $this->factory->getHelper('integration'); | |
| $bundle->splitDescriptions(); | |
| return $this->delegateView( | |
| [ | |
| 'viewParameters' => [ | |
| 'bundle' => $bundle, | |
| 'icon' => $integrationHelper->getIconPath($bundle), | |
| ], | |
| 'contentTemplate' => '@MauticPlugin/Integration/info.html.twig', | |
| 'passthroughVars' => [ | |
| 'activeLink' => '#mautic_plugin_index', | |
| 'mauticContent' => 'integration', | |
| 'route' => false, | |
| ], | |
| ] | |
| ); | |
| } | |
| /** | |
| * Scans the addon bundles directly and loads bundles which are not registered to the database. | |
| * | |
| * @return Response | |
| */ | |
| public function reloadAction(Request $request, ReloadFacade $reloadFacade) | |
| { | |
| if (!$this->security->isGranted('plugin:plugins:manage')) { | |
| return $this->accessDenied(); | |
| } | |
| $this->addFlashMessage( | |
| $reloadFacade->reloadPlugins() | |
| ); | |
| $viewParameters = [ | |
| 'page' => $request->getSession()->get('mautic.plugin.page'), | |
| ]; | |
| // Refresh the index contents | |
| return $this->postActionRedirect( | |
| [ | |
| 'returnUrl' => $this->generateUrl('mautic_plugin_index', $viewParameters), | |
| 'viewParameters' => $viewParameters, | |
| 'contentTemplate' => 'Mautic\PluginBundle\Controller\PluginController::indexAction', | |
| 'passthroughVars' => [ | |
| 'activeLink' => '#mautic_plugin_index', | |
| 'mauticContent' => 'plugin', | |
| ], | |
| ] | |
| ); | |
| } | |
| } | |