Skip to content

Commit

Permalink
Setup Mailer on install (#4191)
Browse files Browse the repository at this point in the history
* add mailer to install procedure

* improve start command

* do not persist most of mailer data
  • Loading branch information
craigh authored Mar 29, 2020
2 parents 4e0044f + 2ce359e commit 47c48c8
Show file tree
Hide file tree
Showing 12 changed files with 384 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,36 @@ abstract class AbstractCoreInstallerCommand extends Command
'locale' => [
'description' => 'The locale to use.',
'default' => 'en'
]
],
/* mailer settings */
'transport' => [
'description' => 'The mailer transport to use.',
'default' => 'test'
],
'mailer_id' => [
'description' => 'The ACCESS_KEY, USERNAME, ID or apikey for the selected transport.',
'default' => null
],
'mailer_key' => [
'description' => 'The SECRET_KEY, PASSWORD, ID or KEY for the selected transport.',
'default' => null
],
'host' => [
'description' => 'SMTP host server',
'default' => null
],
'port' => [
'description' => 'SMTP port',
'default' => null
],
'customParameters' => [
'description' => 'Use query parameters syntax, for example: <code>?param1=value1&amp;param2=value2</code>.',
'default' => null
],
'enableLogging' => [
'description' => 'Enable logging of sent mail.',
'default' => false
],
];

public function __construct(
Expand Down
102 changes: 76 additions & 26 deletions src/Zikula/CoreInstallerBundle/Command/Install/StartCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\StyleInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
Expand All @@ -30,6 +31,8 @@
use Zikula\Bundle\CoreInstallerBundle\Helper\ControllerHelper;
use Zikula\Bundle\CoreInstallerBundle\Helper\DbCredsHelper;
use Zikula\Bundle\CoreInstallerBundle\Helper\ParameterHelper;
use Zikula\MailerModule\Form\Type\MailTransportConfigType;
use Zikula\MailerModule\Helper\MailTransportHelper;
use Zikula\SettingsModule\Api\ApiInterface\LocaleApiInterface;

class StartCommand extends AbstractCoreInstallerCommand
Expand Down Expand Up @@ -117,34 +120,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

// get the settings from user input
$settings = $this->getHelper('form')->interactUsingForm(LocaleType::class, $input, $output, [
'choices' => $this->localeApi->getSupportedLocaleNames(),
'choice_loader' => null
]);
$data = $this->getHelper('form')->interactUsingForm(RequestContextType::class, $input, $output);
foreach ($data as $k => $v) {
$newKey = str_replace(':', '.', $k);
$data[$newKey] = $v;
unset($data[$k]);
$settings = $this->doLocale($input, $output, $io);
$settings = array_merge($settings, $this->doRequestContext($input, $output, $io));
if (!$this->doDBCreds($input, $output, $io)) {
$io->error($this->translator->trans('Cannot write database DSN to %file% file.', ['%file%' => '/.env.local']));
}
$settings = array_merge($settings, $data);
$data = $this->getHelper('form')->interactUsingForm(DbCredsType::class, $input, $output);

$dbCredsHelper = new DbCredsHelper();
$databaseUrl = $dbCredsHelper->buildDatabaseUrl($data);
try {
$vars = ['DATABASE_URL' => '!\'' . $databaseUrl . '\''];
$helper = new LocalDotEnvHelper($this->kernel->getProjectDir());
$helper->writeLocalEnvVars($vars);
} catch (IOExceptionInterface $exception) {
$io->error(sprintf('Cannot write to %s file.', $this->kernel->getProjectDir() . '/.env.local') . ' ' . $exception->getMessage());
if (!$this->doMailer($input, $output, $io)) {
$io->error($this->translator->trans('Cannot write mailer DSN to %file% file.', ['%file%' => '/.env.local']));
}

$data = $this->getHelper('form')->interactUsingForm(CreateAdminType::class, $input, $output);
foreach ($data as $k => $v) {
$data[$k] = base64_encode($v); // encode so values are 'safe' for json
}
$settings = array_merge($settings, $data);
$settings = array_merge($settings, $this->doAdmin($input, $output, $io));

if ($input->isInteractive()) {
$io->success($this->translator->trans('Configuration successful. Please verify your parameters below:'));
Expand All @@ -171,4 +155,70 @@ protected function execute(InputInterface $input, OutputInterface $output): int

return 0;
}

private function doLocale(InputInterface $input, OutputInterface $output, StyleInterface $io): array
{
$io->newLine();
$io->section($this->translator->trans('Locale'));

return $this->getHelper('form')->interactUsingForm(LocaleType::class, $input, $output, [
'choices' => $this->localeApi->getSupportedLocaleNames(),
'choice_loader' => null
]);
}

private function doRequestContext(InputInterface $input, OutputInterface $output, StyleInterface $io): array
{
$io->newLine();
$io->section($this->translator->trans('Request context'));
$data = $this->getHelper('form')->interactUsingForm(RequestContextType::class, $input, $output);
foreach ($data as $k => $v) {
$newKey = str_replace(':', '.', $k);
$data[$newKey] = $v;
unset($data[$k]);
}

return $data;
}

private function doDBCreds(InputInterface $input, OutputInterface $output, StyleInterface $io): bool
{
$io->newLine();
$io->section($this->translator->trans('Database information'));
$io->note($this->translator->trans('The database port can be left empty.'));
$data = $this->getHelper('form')->interactUsingForm(DbCredsType::class, $input, $output);
$dbCredsHelper = new DbCredsHelper();
$databaseUrl = $dbCredsHelper->buildDatabaseUrl($data);
try {
$vars = ['DATABASE_URL' => '!\'' . $databaseUrl . '\''];
$helper = new LocalDotEnvHelper($this->kernel->getProjectDir());
$helper->writeLocalEnvVars($vars);

return true;
} catch (IOExceptionInterface $exception) {
return false;
}
}

private function doMailer(InputInterface $input, OutputInterface $output, StyleInterface $io): bool
{
$io->newLine();
$io->section($this->translator->trans('Mailer transport'));
$io->note($this->translator->trans('Empty values are allowed for all except Mailer transport.'));
$data = $this->getHelper('form')->interactUsingForm(MailTransportConfigType::class, $input, $output);

return (new MailTransportHelper($this->kernel->getProjectDir()))->handleFormData($data);
}

private function doAdmin(InputInterface $input, OutputInterface $output, StyleInterface $io): array
{
$io->newLine();
$io->section($this->translator->trans('Create admin account'));
$data = $this->getHelper('form')->interactUsingForm(CreateAdminType::class, $input, $output);
foreach ($data as $k => $v) {
$data[$k] = base64_encode($v); // encode so values are 'safe' for json
}

return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ stages:
dbcreds:
class: Zikula\Bundle\CoreInstallerBundle\Stage\Install\DbCredsStage
order: 4
emailtransport:
class: Zikula\Bundle\CoreInstallerBundle\Stage\EmailTransportStage
order: 5
createadmin:
class: Zikula\Bundle\CoreInstallerBundle\Stage\Install\CreateAdminStage
order: 5
order: 6
ajaxinstaller:
class: Zikula\Bundle\CoreInstallerBundle\Stage\Install\AjaxInstallerStage
order: 6
order: 7
complete:
class: Zikula\Bundle\CoreInstallerBundle\Stage\Install\CompleteStage
order: 7
order: 8
installed:
class: Zikula\Bundle\CoreInstallerBundle\Stage\AlreadyInstalledStage
order: 8
order: 9
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{% extends '@ZikulaCoreInstaller/theme.html.twig' %}
{% block childjavascripts %}
<script src="{{ asset('bundles/core/js/bootstrap-zikula.js') }}"></script>
{% endblock %}

{% block title 'Zikula Core Installer :: Enter mailer transport information' %}

{% block content %}
<div class="card">
<div class="card-header">
<strong>{% trans %}Mailer transport information{% endtrans %}</strong>
</div>
<div class="card-body">

{{ form_start(form) }}
{{ form_errors(form) }}

<div class="form-group row">
{{ form_label(form.transport) }}
<div class="col-md-9">
{{ form_errors(form.transport) }}
{{ form_widget(form.transport) }}
</div>
</div>
<div class="form-group row">
{{ form_label(form.mailer_id) }}
<div class="col-sm-9">
{{ form_errors(form.mailer_id) }}
{{ form_widget(form.mailer_id) }}
{{ form_help(form.mailer_id) }}
</div>
</div>
<div class="form-group row">
{{ form_label(form.mailer_key) }}
<div class="col-sm-9">
{{ form_errors(form.mailer_key) }}
{{ form_widget(form.mailer_key) }}
{{ form_help(form.mailer_key) }}
</div>
</div>

<div data-switch="zikulamailermodule_config[transport]" data-switch-value="smtp">
<div class="alert alert-info">{% trans %}SMTP settings{% endtrans %}</div>
<div class="form-group row">
{{ form_label(form.host) }}
<div class="col-sm-9">
{{ form_errors(form.host) }}
{{ form_widget(form.host) }}
{{ form_help(form.host) }}
</div>
</div>
<div class="form-group row">
{{ form_label(form.port) }}
<div class="col-sm-9">
{{ form_errors(form.port) }}
{{ form_widget(form.port) }}
{{ form_help(form.port) }}
</div>
</div>
</div>

<div>
<div class="alert alert-info">{% trans %}Additional options{% endtrans %}</div>
<div class="form-group row">
{{ form_label(form.customParameters) }}
<div class="col-md-9">
{{ form_errors(form.customParameters) }}
{{ form_widget(form.customParameters) }}
{{ form_help(form.customParameters) }}
</div>
</div>
<div class="form-group row">
{{ form_label(form.enableLogging) }}
<div class="col-md-9">
{{ form_errors(form.enableLogging) }}
{{ form_widget(form.enableLogging) }}
</div>
</div>
</div>

<div class="form-group row">
<div class="col-md-9 offset-md-3">
<input type="submit" id="submit_button" value="{% trans %}Next{% endtrans %}" class="btn btn-success" />
</div>
</div>
{% do form.save.setRendered() %}
{% do form.cancel.setRendered() %}
{{ form_end(form) }}
</div>
</div>
<script>
$(document).ready(function() {
$('form:first *:input:text:first').focus();
});
</script>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@
<h2>{% trans %}Installer script{% endtrans %}</h2>
<ol class="wizard">
<li{% if currentstage == 'locale' %} class="active"{% endif %}>
<a href="{{ path('install', { 'stage': 'locale' }) }}">{% trans %}Select language{% endtrans %}</a>
{% trans %}Language{% endtrans %}
</li>
<li{% if currentstage == 'requirements' %} class="active"{% endif %}>
{% trans %}Check requirements{% endtrans %}
{% trans %}Requirements{% endtrans %}
</li>
<li{% if currentstage == 'dbcreds' %} class="active"{% endif %}>
{% trans %}Database information{% endtrans %}
{% trans %}Database{% endtrans %}
</li>
<li{% if currentstage == 'emailtransport' %} class="active"{% endif %}>
{% trans %}Email{% endtrans %}
</li>
<li{% if currentstage == 'createadmin' %} class="active"{% endif %}>
{% trans %}Create administrator's account{% endtrans %}
{% trans %}Create admin{% endtrans %}
</li>
<li{% if currentstage == 'ajaxinstaller' %} class="active"{% endif %}>
{% trans %}Install{% endtrans %}
</li>
</ol>
<p class="installguide">
Expand Down
77 changes: 77 additions & 0 deletions src/Zikula/CoreInstallerBundle/Stage/EmailTransportStage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Zikula package.
*
* Copyright Zikula Foundation - https://ziku.la/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zikula\Bundle\CoreInstallerBundle\Stage;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\FormInterface;
use Zikula\Component\Wizard\FormHandlerInterface;
use Zikula\Component\Wizard\InjectContainerInterface;
use Zikula\Component\Wizard\StageInterface;
use Zikula\MailerModule\Form\Type\MailTransportConfigType;
use Zikula\MailerModule\Helper\MailTransportHelper;

class EmailTransportStage implements StageInterface, FormHandlerInterface, InjectContainerInterface
{
/**
* @var ContainerInterface
*/
private $container;

public function __construct(ContainerInterface $container)
{
$this->container = $container;
}

public function getName(): string
{
return 'emailtransport';
}

public function getFormType(): string
{
return MailTransportConfigType::class;
}

public function getFormOptions(): array
{
return [];
}

public function getTemplateName(): string
{
return '@ZikulaCoreInstaller/Install/mailer.html.twig';
}

public function isNecessary(): bool
{
$mailerDsn = $_ENV['MAILER_DSN'] ?? '';
if (!empty($mailerDsn) && 'smtp://localhost' !== $mailerDsn) {
return false;
}

return true;
}

public function getTemplateParams(): array
{
return [];
}

public function handleFormResult(FormInterface $form): bool
{
$projectDir = $this->container->getParameter('kernel.project_dir');

return (new MailTransportHelper($projectDir))->handleFormData($form->getData());
}
}
Loading

0 comments on commit 47c48c8

Please sign in to comment.