Fabien Potencier vor 14 Jahren
Commit
da970ee628

+ 161 - 0
Configurator.php

@@ -0,0 +1,161 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle;
+
+use Symfony\Bundle\WebConfiguratorBundle\Step\StepInterface;
+
+/**
+ * Configurator.
+ *
+ * @author Marc Weistroff <marc.weistroff@gmail.com>
+ */
+class Configurator
+{
+    protected $filename;
+    protected $steps;
+    protected $parameters;
+
+    public function __construct($kernelDir)
+    {
+        $this->kernelDir = $kernelDir;
+        $this->filename = $kernelDir.'/config/parameters.ini';
+
+        $this->steps = array();
+        $this->parameters = $this->read();
+    }
+
+    public function isFileWritable()
+    {
+        return is_writable($this->filename);
+    }
+
+    public function clean()
+    {
+        if (file_exists($this->getCacheFilename())) {
+            @unlink($this->getCacheFilename());
+        }
+    }
+
+    /**
+     * @param StepInterface $step
+     */
+    public function addStep(StepInterface $step)
+    {
+        $this->steps[] = $step;
+    }
+
+    /**
+     * @param integer $index
+     *
+     * @return StepInterface
+     */
+    public function getStep($index)
+    {
+        if (isset($this->steps[$index])) {
+            return $this->steps[$index];
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function getSteps()
+    {
+        return $this->steps;
+    }
+
+    /**
+     * @return array
+     */
+    public function getParameters()
+    {
+        return $this->parameters;
+    }
+
+    /**
+     * @return integer
+     */
+    public function getStepCount()
+    {
+        return count($this->steps);
+    }
+
+    /**
+     * @param array $parameters
+     */
+    public function mergeParameters($parameters)
+    {
+        $this->parameters = array_merge($this->parameters, $parameters);
+    }
+
+    /**
+     * Renders parameters as a string.
+     *
+     * @return string
+     */
+    public function render()
+    {
+        $lines[] = "[parameters]\n";
+
+        foreach ($this->parameters as $key => $value) {
+            $lines[] = sprintf("    %s=%s\n", $key, $value);
+        }
+
+        return implode('', $lines);
+    }
+
+    /**
+     * Writes parameters to parameters.ini or temporary in the cache directory.
+     *
+     * @return boolean
+     */
+    public function write()
+    {
+        $filename = $this->isFileWritable() ? $this->filename : $this->getCacheFilename();
+
+        return file_put_contents($filename, $this->render());
+    }
+
+    /**
+     * Reads parameters from file.
+     *
+     * @return array
+     */
+    protected function read()
+    {
+        $filename = $this->filename;
+        if (!$this->isFileWritable() && file_exists($this->getCacheFilename())) {
+            $filename = $this->getCacheFilename();
+        }
+
+        $ret = parse_ini_file($filename, true);
+        if (false === $ret || array() === $ret) {
+            throw new \InvalidArgumentException(sprintf('The %s file is not valid.', $filename));
+        }
+
+        if (isset($ret['parameters']) && is_array($ret['parameters'])) {
+            return $ret['parameters'];
+        } else {
+            return array();
+        }
+    }
+
+    /**
+     * getCacheFilename
+     *
+     * @return string
+     */
+    protected function getCacheFilename()
+    {
+        return $this->kernelDir.'/cache/parameters.ini';
+    }
+}

+ 101 - 0
Controller/ConfiguratorController.php

@@ -0,0 +1,101 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle\Controller;
+
+use Symfony\Component\DependencyInjection\ContainerAware;
+use Symfony\Bundle\WebConfiguratorBundle\Exception\StepRequirementException;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+
+/**
+ * ConfiguratorController.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ConfiguratorController extends ContainerAware
+{
+    /**
+     * @return Response A Response instance
+     */
+    public function stepAction($index = 0)
+    {
+        $configurator = $this->container->get('symfony.webconfigurator');
+
+        $step = $configurator->getStep($index);
+        $form = $step->getForm($this->container->get('form.context'));
+
+        $form->bind($this->container->get('request'), $step);
+
+        if ($form->isValid()) {
+            $configurator->mergeParameters($step->update($form->getData()));
+            $configurator->write();
+
+            $index++;
+
+            if ($index < $configurator->getStepCount()) {
+                return new RedirectResponse($this->container->get('router')->generate('_configurator_step', array('index' => $index)));
+            }
+
+            return new RedirectResponse($this->container->get('router')->generate('_configurator_final'));
+        }
+
+        return $this->container->get('templating')->renderResponse($step->getTemplate(),
+            array('form' => $form, 'index' => $index, 'count' => $configurator->getStepCount()));
+    }
+
+    public function checkAction()
+    {
+        $configurator = $this->container->get('symfony.webconfigurator');
+
+        $steps = $configurator->getSteps();
+
+        $majors = array();
+        $minors = array();
+
+        // Trying to get as much requirements as possible
+        foreach ($steps as $step) {
+            foreach ($step->checkRequirements() as $major) {
+                $majors[] = $major;
+            }
+
+            foreach ($step->checkOptionalSettings() as $minor) {
+                $minors[] = $minor;
+            }
+        }
+
+        $url = $this->container->get('router')->generate('_configurator_step', array('index' => 0));
+
+        if (empty($majors) && empty($minors)) {
+            return new RedirectResponse($url);
+        }
+
+        return $this->container->get('templating')->renderResponse('SymfonyWebConfiguratorBundle::check.html.twig',
+            array(
+                'majors' => $majors,
+                'minors' => $minors,
+                'url'    => $url,
+            )
+        );
+    }
+
+    public function finalAction()
+    {
+        $configurator = $this->container->get('symfony.webconfigurator');
+        $configurator->clean();
+
+        return $this->container->get('templating')->renderResponse('SymfonyWebConfiguratorBundle::final.html.twig',
+            array(
+                'parameters'  => $configurator->render(),
+                'is_writable' => $configurator->isFileWritable(),
+            )
+        );
+    }
+}

+ 33 - 0
DependencyInjection/SymfonyWebConfiguratorExtension.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace Symfony\Bundle\WebConfiguratorBundle\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
+use Symfony\Component\HttpKernel\DependencyInjection\Extension;
+use Symfony\Component\Config\FileLocator;
+
+/**
+ * SymfonyWebConfiguratorExtension.
+ *
+ * @author Marc Weistroff <marc.weistroff@sensio.com>
+ */
+class SymfonyWebConfiguratorExtension extends Extension
+{
+    public function load(array $configs, ContainerBuilder $container)
+    {
+        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
+
+        $loader->load('webconfigurator.xml');
+    }
+
+    public function getNamespace()
+    {
+        return 'http://symfony.com/schema/dic/symfony';
+    }
+
+    public function getAlias()
+    {
+        return 'symfony_web_configurator';
+    }
+}

+ 28 - 0
Form/CsrfForm.php

@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle\Form;
+
+use Symfony\Component\Form\Form;
+use Symfony\Component\Form\TextField;
+
+/**
+ * CSRF Form.
+ *
+ * @author Marc Weistroff <marc.weistroff@sensio.com>
+ */
+class CsrfForm extends Form
+{
+    public function configure()
+    {
+        $this->add(new TextField('csrf_secret'));
+    }
+}

+ 37 - 0
Form/DoctrineForm.php

@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle\Form;
+
+use Symfony\Bundle\WebConfiguratorBundle\Step\DoctrineStep;
+use Symfony\Component\Form\Form;
+use Symfony\Component\Form\TextField;
+use Symfony\Component\Form\ChoiceField;
+use Symfony\Component\Form\PasswordField;
+use Symfony\Component\Form\RepeatedField;
+use Symfony\Component\Form\HiddenField;
+
+/**
+ * Doctrine Form.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DoctrineForm extends Form
+{
+    public function configure()
+    {
+        $this->add(new ChoiceField('driver', array('choices' => DoctrineStep::getDrivers())));
+        $this->add(new TextField('name'));
+        $this->add(new TextField('host'));
+        $this->add(new TextField('user'));
+        $this->add(new RepeatedField(new PasswordField('password'), array('first_key' => 'Password', 'second_key' => 'Again')));
+    }
+}

+ 18 - 0
Resources/config/routing/configurator.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<routes xmlns="http://symfony.com/schema/routing"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
+
+    <route id="_configurator_home" pattern="/">
+        <default key="_controller">SymfonyWebConfiguratorBundle:Configurator:check</default>
+    </route>
+
+    <route id="_configurator_step" pattern="/step/{index}">
+        <default key="_controller">SymfonyWebConfiguratorBundle:Configurator:step</default>
+    </route>
+
+    <route id="_configurator_final" pattern="/final">
+        <default key="_controller">SymfonyWebConfiguratorBundle:Configurator:final</default>
+    </route>
+</routes>

+ 17 - 0
Resources/config/webconfigurator.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+
+<container xmlns="http://symfony.com/schema/dic/services"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
+
+    <parameters>
+        <parameter key="symfony.webconfigurator.class">Symfony\Bundle\WebConfiguratorBundle\Configurator</parameter>
+    </parameters>
+
+    <services>
+        <service id="symfony.webconfigurator" class="%symfony.webconfigurator.class%">
+            <argument>%kernel.root_dir%</argument>
+        </service>
+    </services>
+</container>
+

Datei-Diff unterdrückt, da er zu groß ist
+ 422 - 0
Resources/public/css/configure.css


Datei-Diff unterdrückt, da er zu groß ist
+ 367 - 0
Resources/public/css/install.css


BIN
Resources/public/images/background-textfield.gif


BIN
Resources/public/images/blue-arrow.png


BIN
Resources/public/images/logo-big.gif


BIN
Resources/public/images/logo-small.gif


BIN
Resources/public/images/notification.gif


+ 45 - 0
Resources/views/Step/csrf.html.twig

@@ -0,0 +1,45 @@
+{% extends "SymfonyWebConfiguratorBundle::layout.html.twig" %}
+
+{% block title %}Symfony - Configure CSRF{% endblock %}
+
+{% block content %}
+    {% form_theme form "SymfonyWebConfiguratorBundle::form.html.twig" %}
+    {% include "SymfonyWebConfiguratorBundle::steps.html.twig" with { "index": index, "count": count } %}
+
+    <h1>CSRF Protection</h1>
+    <p>Configure CSRF protection for your website :</p>
+
+    {{ form_errors(form) }}
+    <form action="{{ path('_configurator_step', { 'index': index }) }} " method="POST">
+        {{ form_hidden(form) }}
+
+        <div class="symfony-form-row">
+            {{ form_label(form.csrf_secret) }}
+            <div class="symfony-form-field">
+                {{ form_field(form.csrf_secret) }}
+                <a class="symfony-button-grey" href="#" onclick="generateCsrf(); return false;">Generate</a>
+                <div class="symfony-form-errors">
+                    {{ form_errors(form.csrf_secret) }}
+                </div>
+            </div>
+        </div>
+
+        <div class="symfony-form-footer">
+            <p><input type="submit" value="Next Step" class="symfony-button-grey" /></p>
+            <p>* mandatory fields</p>
+        </div>
+
+    </form>
+
+    <script type="text/javascript">
+        function generateCsrf()
+        {
+            var result = '';
+            for (i=0; i < 32; i++) {
+                result += Math.round(Math.random()*16).toString(16);
+            }
+            document.getElementById('config_csrf_secret').value = result;
+        }
+    </script>
+
+{% endblock %}

+ 37 - 0
Resources/views/Step/doctrine.html.twig

@@ -0,0 +1,37 @@
+{% extends "SymfonyWebConfiguratorBundle::layout.html.twig" %}
+
+{% block title %}Symfony - Configure database{% endblock %}
+
+{% block content %}
+    {% form_theme form "SymfonyWebConfiguratorBundle::form.html.twig" %}
+    {% include "SymfonyWebConfiguratorBundle::steps.html.twig" with { "index": index, "count": count } %}
+
+    <h1>Configure your Database</h1>
+    <p>If your website needs a database connection, please configure it here.</p>
+
+    {{ form_errors(form) }}
+    <form action="{{ path('_configurator_step', { 'index': index }) }}" method="POST">
+        {{ form_hidden(form) }}
+
+        {{ form_row(form.driver) }}
+        {{ form_row(form.name) }}
+        {{ form_row(form.host) }}
+        {{ form_row(form.user) }}
+        <div class="symfony-form-row">
+            {{ form_label(form.password) }}
+            <div class="symfony-form-field">
+                {{ form_field(form.password.Password) }}
+                <div class="symfony-form-errors">
+                    {{ form_errors(form.password) }}
+                </div>
+            </div>
+        </div>
+        {{ form_row(form.password.Again) }}
+
+
+        <div class="symfony-form-footer">
+            <p><input type="submit" value="Next Step" class="symfony-button-grey" /></p>
+            <p>* mandatory fields</p>
+        </div>
+    </form>
+{% endblock %}

+ 43 - 0
Resources/views/check.html.twig

@@ -0,0 +1,43 @@
+{% extends "SymfonyWebConfiguratorBundle::layout.html.twig" %}
+
+{% block content %}
+    {% if majors|length %}
+        <h1>Major Problems that need to be fixed now</h1>
+        <p>
+            We have detected <strong>{{ majors|length }}</strong> major problems.
+            You <em>must</em> fix them before continuing:
+        </p>
+        <ol>
+            {% for message in majors %}
+                <li>{{ message }}</li>
+            {% endfor %}
+        </ol>
+    {% endif %}
+
+    {% if minors|length %}
+        <h1>Some Recommandations</h1>
+
+        <p>
+            {% if majors|length %}
+            Additionally, we
+            {% else %}
+            We
+            {% endif %}
+            have detected some minor problems that we <em>recommend</em> you to fix to have a better Symfony
+            experience:
+
+            <ol>
+                {% for message in minors %}
+                    <li>{{ message }}</li>
+                {% endfor %}
+            </ol>
+        </p>
+
+    {% endif %}
+
+    {% if not majors|length %}
+        <ul class="symfony_list">
+            <li><a href="{{ url }}">Configure your Symfony Application online</a></li>
+        </p>
+    {% endif %}
+{% endblock %}

+ 23 - 0
Resources/views/final.html.twig

@@ -0,0 +1,23 @@
+{% extends "SymfonyWebConfiguratorBundle::layout.html.twig" %}
+
+{% block content_class %}config_done{% endblock %}
+{% block content %}
+    <h1>Well done!</h1>
+    <h2>Your distribution is configured!</h2>
+
+    <h3>
+        <span>
+            {% if is_writable %}
+                Your parameter.ini has been overwritten with these parameters:
+            {% else %}
+                Your parameters.ini file is not writeable ! Here are the parameters you can copy and paste.
+            {% endif %}
+        </span>
+    </h3>
+
+    <textarea class="symfony-configuration">{{ parameters }}</textarea>
+
+    <ul>
+        <li><a href="{{ path('_welcome') }}">Go to the Welcome page</a></li>
+    </ul>
+{% endblock %}

+ 46 - 0
Resources/views/form.html.twig

@@ -0,0 +1,46 @@
+{% extends "TwigBundle::form.html.twig" %}
+
+{% block field_row %}
+    <div class="symfony-form-row">
+        {{ form_label(child) }}
+        <div class="symfony-form-field">
+            {{ form_field(child) }}
+            <div class="symfony-form-errors">
+                {{ form_errors(child) }}
+            </div>
+        </div>
+    </div>
+{% endblock %}
+
+{% block label %}
+    <label for="{{ field.id }}">
+        {% trans label %}
+        {% if field.required %}
+            <span class="symfony-form-required" title="This field is required">*</span>
+        {% endif %}
+    </label>
+{% endblock label %}
+
+{% block errors %}
+    {% if field.hasErrors %}
+        <ul>
+        {% for error in field.errors %}
+            <li>{% trans error.messageTemplate with error.messageParameters from 'validators' %}</li>
+        {% endfor %}
+        </ul>
+    {% endif %}
+{% endblock errors %}
+
+{% block text_field %}
+    {% if attr.type is defined and attr.type != "text" %}
+        <input {{ block('field_attributes') }} value="{{ field.displayedData }}" />
+    {% else %}
+        {% set attr = attr|merge({ 'maxlength': attr.maxlength|default(field.maxlength) }) %}
+        <input type="text" {{ block('field_attributes') }} value="{{ field.displayedData }}" />
+    {% endif %}
+{% endblock text_field %}
+
+{% block password_field %}
+    {% set attr = attr|merge({ 'maxlength': attr.maxlength|default(field.maxlength) }) %}
+    <input type="password" {{ block('field_attributes') }} class="medium_txt" value="{{ field.displayedData }}" />
+{% endblock password_field %}

+ 18 - 0
Resources/views/layout.html.twig

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+        <link rel="stylesheet" href="{{ asset('bundles/symfonywebconfigurator/css/configure.css') }}" type="text/css" media="all" />
+        <title>{% block title %}Web Configurator Bundle{% endblock %}</title>
+    </head>
+    <body>
+        <div id="symfony-wrapper">
+            <div id="symfony-header">
+                <img src="{{ asset("bundles/symfonywebconfigurator/images/logo-small.gif") }}" alt="Symfony" />
+            </div>
+            <div id="symfony-content">
+                {% block content %}{% endblock %}
+            </div>
+        </div>
+    </body>
+</html>

+ 14 - 0
Resources/views/steps.html.twig

@@ -0,0 +1,14 @@
+<div class="symfony-block-steps">
+    {% for i in 1..count %}
+
+      {% if i == index + 1 %}
+          <span class="selected">Step {{ i }}</span>
+      {% else %}
+          <span>Step {{ i }}</span>
+      {% endif %}
+
+      {% if i != count %}
+        &gt;
+      {% endif %}
+    {% endfor %}
+</div>

+ 74 - 0
Step/CsrfStep.php

@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle\Step;
+
+use Symfony\Component\Form\FormContext;
+use Symfony\Bundle\WebConfiguratorBundle\Form\CsrfForm;
+use Symfony\Bundle\WebConfiguratorBundle\Exception\StepRequirementException;
+
+/**
+ * Csrf Step.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class CsrfStep implements StepInterface
+{
+    /**
+     * @validation:NotBlank
+     */
+    public $csrf_secret;
+
+    public function __construct(array $parameters)
+    {
+        $this->csrf_secret = $parameters['csrf_secret'];
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function getForm(FormContext $context)
+    {
+        return CsrfForm::create($context, 'config');
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function checkRequirements()
+    {
+        return array();
+    }
+
+    /**
+     * checkOptionalSettings
+     */
+    public function checkOptionalSettings()
+    {
+        return array();
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function update(StepInterface $data)
+    {
+        return array('csrf_secret' => $data->csrf_secret);
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function getTemplate()
+    {
+        return 'SymfonyWebConfiguratorBundle:Step:csrf.html.twig';
+    }
+}

+ 142 - 0
Step/DoctrineStep.php

@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle\Step;
+
+use Symfony\Component\Form\FormContext;
+use Symfony\Bundle\WebConfiguratorBundle\Form\DoctrineForm;
+use Symfony\Bundle\WebConfiguratorBundle\Exception\StepRequirementException;
+
+/**
+ * Doctrine Step.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DoctrineStep implements StepInterface
+{
+    /**
+     * @validation:Choice(callback="getDriverKeys")
+     */
+    public $driver;
+
+    /**
+     * @validation:NotBlank
+     */
+    public $host;
+
+    /**
+     * @validation:NotBlank
+     */
+    public $name;
+
+    /**
+     * @validation:NotBlank
+     */
+    public $user;
+
+    /**
+     * @validation:NotBlank
+     */
+    public $password;
+
+    public function __construct(array $parameters)
+    {
+        foreach ($parameters as $key => $value) {
+            if (0 === strpos($key, 'database_')) {
+                $parameters[substr($key, 9)] = $value;
+                $key = substr($key, 9);
+                $this->$key = $value;
+            }
+        }
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function getForm(FormContext $context)
+    {
+        return DoctrineForm::create($context, 'config');
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function checkRequirements()
+    {
+        $messages = array();
+
+        if (!class_exists('\PDO')) {
+            $messages[] = 'PDO extension is mandatory.';
+        } else {
+            $drivers = \PDO::getAvailableDrivers();
+            if (0 == count($drivers)) {
+                $messages[] = 'Please install PDO drivers.';
+            }
+        }
+
+        return $messages;
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function checkOptionalSettings()
+    {
+        return array();
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function update(StepInterface $data)
+    {
+        $parameters = array();
+
+        foreach ($data as $key => $value) {
+            $parameters['database_'.$key] = $value;
+        }
+
+        return $parameters;
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function getTemplate()
+    {
+        return 'SymfonyWebConfiguratorBundle:Step:doctrine.html.twig';
+    }
+
+    /**
+     * @return array
+     */
+    static public function getDriverKeys()
+    {
+        return array_keys(static::getDrivers());
+    }
+
+    /**
+     * @return array
+     */
+    static public function getDrivers()
+    {
+        return array(
+            'pdo_mysql'  => 'MySQL (PDO)',
+            'pdo_sqlite' => 'SQLite (PDO)',
+            'pdo_pgsql'  => 'PosgreSQL (PDO)',
+            'oci8'       => 'Oracle (native)',
+            'ibm_db2'    => 'IBM DB2 (native)',
+            'pdo_oci'    => 'Oracle (PDO)',
+            'pdo_ibm'    => 'IBM DB2 (PDO)',
+            'pdo_sqlsrv' => 'SQLServer (PDO)',
+        );
+    }
+}

+ 73 - 0
Step/DumbStep.php

@@ -0,0 +1,73 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle\Step;
+
+use Symfony\Component\Form\FormContext;
+use Symfony\Bundle\WebConfiguratorBundle\Form\DoctrineForm;
+use Symfony\Bundle\WebConfiguratorBundle\Exception\StepRequirementException;
+
+/**
+ * Csrf Step.
+ *
+ * @author Marc Weistroff <marc.weistroff@sensio.com>
+ */
+class CsrfStep implements StepInterface
+{
+    /**
+     * @validation:NotBlank
+     */
+    public $csrf_secret;
+
+    public function __construct(array $parameters)
+    {
+        $this->csrf_secret = $parameters['csrf_secret'];
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function getName()
+    {
+        return 'CSRF';
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function getForm(FormContext $context)
+    {
+        return CsrfForm::create($context, 'config');
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function checkRequirements()
+    {
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function update(StepInterface $data)
+    {
+        return array('csrf_secret' => $data->csrf_secret);
+    }
+
+    /**
+     * @see StepInterface
+     */
+    public function getTemplate()
+    {
+        return 'SymfonyWebConfiguratorBundle:Step:csrf.html.twig';
+    }
+}

+ 66 - 0
Step/StepInterface.php

@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle\Step;
+
+use Symfony\Component\Form\FormContext;
+
+/**
+ * StepInterface.
+ *
+ * @author Marc Weistroff <marc.weistroff@sensio.com>
+ */
+interface StepInterface
+{
+    /**
+     * __construct
+     *
+     * @param array $parameters
+     */
+    function __construct(array $parameters);
+
+    /**
+     * Returns the form used for configuration.
+     *
+     * @param FormContext $context
+     * @return Symfony\Component\Form\Form
+     */
+    function getForm(FormContext $context);
+
+    /**
+     * Checks for requirements.
+     *
+     * @return array
+     */
+    function checkRequirements();
+
+    /**
+     * Checks for optional setting it could be nice to have.
+     *
+     * @return array
+     */
+    function checkOptionalSettings();
+
+    /**
+     * Returns the template to be renderer for this step.
+     *
+     * @return string
+     */
+    function getTemplate();
+
+    /**
+     * Updates form data parameters.
+     *
+     * @param array $parameters
+     * @return array
+     */
+    function update(StepInterface $data);
+}

+ 32 - 0
SymfonyWebConfiguratorBundle.php

@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\WebConfiguratorBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Bundle\WebConfiguratorBundle\Step\DoctrineStep;
+use Symfony\Bundle\WebConfiguratorBundle\Step\CsrfStep;
+
+/**
+ * SymfonyWebConfiguratorBundle.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Marc Weistroff <marc.weistroff@sensio.com>
+ */
+class SymfonyWebConfiguratorBundle extends Bundle
+{
+    public function boot()
+    {
+        $configurator = $this->container->get('symfony.webconfigurator');
+        $configurator->addStep(new DoctrineStep($configurator->getParameters()));
+        $configurator->addStep(new CsrfStep($configurator->getParameters()));
+    }
+}