Spaces:
No application file
No application file
| namespace Mautic\ConfigBundle\Controller; | |
| use Mautic\ConfigBundle\ConfigEvents; | |
| use Mautic\ConfigBundle\Event\ConfigBuilderEvent; | |
| use Mautic\ConfigBundle\Event\ConfigEvent; | |
| use Mautic\ConfigBundle\Form\Type\ConfigType; | |
| use Mautic\ConfigBundle\Mapper\ConfigMapper; | |
| use Mautic\CoreBundle\Configurator\Configurator; | |
| use Mautic\CoreBundle\Controller\FormController; | |
| use Mautic\CoreBundle\Helper\BundleHelper; | |
| use Mautic\CoreBundle\Helper\CacheHelper; | |
| use Mautic\CoreBundle\Helper\EncryptionHelper; | |
| use Mautic\CoreBundle\Helper\PathsHelper; | |
| use Mautic\UserBundle\Entity\User; | |
| use Symfony\Component\Form\FormError; | |
| use Symfony\Component\HttpFoundation\JsonResponse; | |
| use Symfony\Component\HttpFoundation\Request; | |
| use Symfony\Component\HttpFoundation\Response; | |
| use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; | |
| class ConfigController extends FormController | |
| { | |
| /** | |
| * Controller action for editing the application configuration. | |
| * | |
| * @return JsonResponse|Response | |
| */ | |
| public function editAction(Request $request, BundleHelper $bundleHelper, Configurator $configurator, CacheHelper $cacheHelper, PathsHelper $pathsHelper, ConfigMapper $configMapper, TokenStorageInterface $tokenStorage) | |
| { | |
| // admin only allowed | |
| if (!$this->user->isAdmin()) { | |
| return $this->accessDenied(); | |
| } | |
| $event = new ConfigBuilderEvent($bundleHelper); | |
| $dispatcher = $this->dispatcher; | |
| $dispatcher->dispatch($event, ConfigEvents::CONFIG_ON_GENERATE); | |
| $fileFields = $event->getFileFields(); | |
| $formThemes = $event->getFormThemes(); | |
| $formConfigs = $configMapper->bindFormConfigsWithRealValues($event->getForms()); | |
| $this->mergeParamsWithLocal($formConfigs, $pathsHelper); | |
| // Create the form | |
| $action = $this->generateUrl('mautic_config_action', ['objectAction' => 'edit']); | |
| $form = $this->formFactory->create( | |
| ConfigType::class, | |
| $formConfigs, | |
| [ | |
| 'action' => $action, | |
| 'fileFields' => $fileFields, | |
| ] | |
| ); | |
| $originalNormData = $form->getNormData(); | |
| $isWritable = $configurator->isFileWritable(); | |
| $openTab = null; | |
| // Check for a submitted form and process it | |
| if ('POST' == $request->getMethod()) { | |
| if (!$cancelled = $this->isFormCancelled($form)) { | |
| $isValid = false; | |
| if ($isWritable && $isValid = $this->isFormValid($form)) { | |
| // Bind request to the form | |
| $post = $request->request; | |
| /** @var mixed[] $formData */ | |
| $formData = $form->getData(); | |
| // Dispatch pre-save event. Bundles may need to modify some field values like passwords before save | |
| $configEvent = new ConfigEvent($formData, $post); | |
| $configEvent | |
| ->setOriginalNormData($originalNormData) | |
| ->setNormData($form->getNormData()); | |
| $dispatcher->dispatch($configEvent, ConfigEvents::CONFIG_PRE_SAVE); | |
| $formValues = $configEvent->getConfig(); | |
| $errors = $configEvent->getErrors(); | |
| $fieldErrors = $configEvent->getFieldErrors(); | |
| if ($errors || $fieldErrors) { | |
| foreach ($errors as $message => $messageVars) { | |
| $form->addError( | |
| new FormError($this->translator->trans($message, $messageVars, 'validators')) | |
| ); | |
| } | |
| foreach ($fieldErrors as $key => $fields) { | |
| foreach ($fields as $field => $fieldError) { | |
| $form[$key][$field]->addError( | |
| new FormError($this->translator->trans($fieldError[0], $fieldError[1], 'validators')) | |
| ); | |
| } | |
| } | |
| $isValid = false; | |
| } else { | |
| // Prevent these from getting overwritten with empty values | |
| $unsetIfEmpty = $configEvent->getPreservedFields(); | |
| $unsetIfEmpty = array_merge($unsetIfEmpty, $fileFields); | |
| // Merge each bundle's updated configuration into the local configuration | |
| foreach ($formValues as $object) { | |
| $checkThese = array_intersect(array_keys($object), $unsetIfEmpty); | |
| foreach ($checkThese as $checkMe) { | |
| if (empty($object[$checkMe])) { | |
| unset($object[$checkMe]); | |
| } | |
| } | |
| $configurator->mergeParameters($object); | |
| } | |
| try { | |
| // Ensure the config has a secret key | |
| $params = $configurator->getParameters(); | |
| if (empty($params['secret_key'])) { | |
| $configurator->mergeParameters(['secret_key' => EncryptionHelper::generateKey()]); | |
| } | |
| $configurator->write(); | |
| $dispatcher->dispatch($configEvent, ConfigEvents::CONFIG_POST_SAVE); | |
| $this->addFlashMessage('mautic.config.config.notice.updated'); | |
| $cacheHelper->refreshConfig(); | |
| if ($isValid && !empty($formData['coreconfig']['last_shown_tab'])) { | |
| $openTab = $formData['coreconfig']['last_shown_tab']; | |
| } | |
| } catch (\RuntimeException $exception) { | |
| $this->addFlashMessage('mautic.config.config.error.not.updated', ['%exception%' => $exception->getMessage()], 'error'); | |
| } | |
| $this->setLocale($request, $tokenStorage, $params); | |
| } | |
| } elseif (!$isWritable) { | |
| $form->addError( | |
| new FormError( | |
| $this->translator->trans('mautic.config.notwritable') | |
| ) | |
| ); | |
| } | |
| } | |
| // If the form is saved or cancelled, redirect back to the dashboard | |
| if ($cancelled || $isValid) { | |
| if (!$cancelled && $this->isFormApplied($form)) { | |
| $redirectParameters = ['objectAction' => 'edit']; | |
| if ($openTab) { | |
| $redirectParameters['tab'] = $openTab; | |
| } | |
| return $this->delegateRedirect($this->generateUrl('mautic_config_action', $redirectParameters)); | |
| } else { | |
| return $this->delegateRedirect($this->generateUrl('mautic_dashboard_index')); | |
| } | |
| } | |
| } | |
| $tmpl = $request->isXmlHttpRequest() ? $request->get('tmpl', 'index') : 'index'; | |
| return $this->delegateView( | |
| [ | |
| 'viewParameters' => [ | |
| 'tmpl' => $tmpl, | |
| 'security' => $this->security, | |
| 'form' => $form->createView(), | |
| 'formThemes' => $formThemes, | |
| 'formConfigs' => $formConfigs, | |
| 'isWritable' => $isWritable, | |
| ], | |
| 'contentTemplate' => '@MauticConfig/Config/form.html.twig', | |
| 'passthroughVars' => [ | |
| 'activeLink' => '#mautic_config_index', | |
| 'mauticContent' => 'config', | |
| 'route' => $this->generateUrl('mautic_config_action', ['objectAction' => 'edit']), | |
| ], | |
| ] | |
| ); | |
| } | |
| /** | |
| * @return array|JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|Response | |
| */ | |
| public function downloadAction(Request $request, BundleHelper $bundleHelper, $objectId) | |
| { | |
| // admin only allowed | |
| if (!$this->user->isAdmin()) { | |
| return $this->accessDenied(); | |
| } | |
| $event = new ConfigBuilderEvent($bundleHelper); | |
| $dispatcher = $this->dispatcher; | |
| $dispatcher->dispatch($event, ConfigEvents::CONFIG_ON_GENERATE); | |
| // Extract and base64 encode file contents | |
| $fileFields = $event->getFileFields(); | |
| if (!in_array($objectId, $fileFields)) { | |
| return $this->accessDenied(); | |
| } | |
| $content = $this->coreParametersHelper->get($objectId); | |
| $filename = $request->get('filename', $objectId); | |
| if ($decoded = base64_decode($content)) { | |
| $response = new Response($decoded); | |
| $response->headers->set('Content-Type', 'application/force-download'); | |
| $response->headers->set('Content-Type', 'application/octet-stream'); | |
| $response->headers->set('Content-Disposition', 'attachment; filename="'.$filename); | |
| $response->headers->set('Expires', '0'); | |
| $response->headers->set('Cache-Control', 'must-revalidate'); | |
| $response->headers->set('Pragma', 'public'); | |
| return $response; | |
| } | |
| return $this->notFound(); | |
| } | |
| /** | |
| * @return array|JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|Response | |
| */ | |
| public function removeAction(BundleHelper $bundleHelper, Configurator $configurator, CacheHelper $cacheHelper, $objectId) | |
| { | |
| // admin only allowed | |
| if (!$this->user->isAdmin()) { | |
| return $this->accessDenied(); | |
| } | |
| $success = 0; | |
| $event = new ConfigBuilderEvent($bundleHelper); | |
| $dispatcher = $this->dispatcher; | |
| $dispatcher->dispatch($event, ConfigEvents::CONFIG_ON_GENERATE); | |
| // Extract and base64 encode file contents | |
| $fileFields = $event->getFileFields(); | |
| if (in_array($objectId, $fileFields)) { | |
| $configurator->mergeParameters([$objectId => null]); | |
| try { | |
| $configurator->write(); | |
| $cacheHelper->refreshConfig(); | |
| $success = 1; | |
| } catch (\Exception) { | |
| } | |
| } | |
| return new JsonResponse(['success' => $success]); | |
| } | |
| /** | |
| * Merges default parameters from each subscribed bundle with the local (real) params. | |
| */ | |
| private function mergeParamsWithLocal(array &$forms, PathsHelper $pathsHelper): void | |
| { | |
| $doNotChange = $this->coreParametersHelper->get('mautic.security.restrictedConfigFields'); | |
| $localConfigFile = $pathsHelper->getLocalConfigurationFile(); | |
| // Import the current local configuration, $parameters is defined in this file | |
| $parameters = []; | |
| include $localConfigFile; | |
| /** @var mixed[] $parameters */ | |
| $localParams = $parameters; | |
| foreach ($forms as &$form) { | |
| // Merge the bundle params with the local params | |
| foreach ($form['parameters'] as $key => $value) { | |
| if (in_array($key, $doNotChange)) { | |
| unset($form['parameters'][$key]); | |
| } elseif (array_key_exists($key, $localParams)) { | |
| $paramValue = $localParams[$key]; | |
| $form['parameters'][$key] = $paramValue; | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * @param array<string, string> $params | |
| */ | |
| private function setLocale(Request $request, TokenStorageInterface $tokenStorage, array $params): void | |
| { | |
| $me = $tokenStorage->getToken()->getUser(); | |
| assert($me instanceof User); | |
| $locale = $me->getLocale(); | |
| if (empty($locale)) { | |
| $locale = $params['locale'] ?? $this->coreParametersHelper->get('locale'); | |
| } | |
| $request->getSession()->set('_locale', $locale); | |
| } | |
| } | |