Julio 9 жил өмнө
parent
commit
4f6fd69ce5
60 өөрчлөгдсөн 5364 нэмэгдсэн , 0 устгасан
  1. 12 0
      composer.json
  2. 26 0
      src/Chamilo/InstallerBundle/ChamiloInstallerBundle.php
  3. 537 0
      src/Chamilo/InstallerBundle/Command/InstallCommand.php
  4. 98 0
      src/Chamilo/InstallerBundle/Command/PlatformUpdateCommand.php
  5. 265 0
      src/Chamilo/InstallerBundle/CommandExecutor.php
  6. 21 0
      src/Chamilo/InstallerBundle/DependencyInjection/ChamiloInstallerExtension.php
  7. 30 0
      src/Chamilo/InstallerBundle/DependencyInjection/Compiler/InstallerPass.php
  8. 41 0
      src/Chamilo/InstallerBundle/DependencyInjection/Configuration.php
  9. 104 0
      src/Chamilo/InstallerBundle/EventListener/RequestListener.php
  10. 98 0
      src/Chamilo/InstallerBundle/Form/Type/Configuration/DatabaseType.php
  11. 122 0
      src/Chamilo/InstallerBundle/Form/Type/Configuration/MailerType.php
  12. 49 0
      src/Chamilo/InstallerBundle/Form/Type/Configuration/SystemType.php
  13. 58 0
      src/Chamilo/InstallerBundle/Form/Type/ConfigurationType.php
  14. 99 0
      src/Chamilo/InstallerBundle/Form/Type/Setup/AdminType.php
  15. 109 0
      src/Chamilo/InstallerBundle/Form/Type/Setup/PortalType.php
  16. 42 0
      src/Chamilo/InstallerBundle/Form/Type/SetupType.php
  17. 14 0
      src/Chamilo/InstallerBundle/InstallerEvents.php
  18. 79 0
      src/Chamilo/InstallerBundle/Persister/YamlPersister.php
  19. 34 0
      src/Chamilo/InstallerBundle/Process/InstallerScenario.php
  20. 22 0
      src/Chamilo/InstallerBundle/Process/PhpExecutableFinder.php
  21. 151 0
      src/Chamilo/InstallerBundle/Process/Step/AbstractStep.php
  22. 74 0
      src/Chamilo/InstallerBundle/Process/Step/ConfigureStep.php
  23. 22 0
      src/Chamilo/InstallerBundle/Process/Step/FinalStep.php
  24. 133 0
      src/Chamilo/InstallerBundle/Process/Step/InstallationStep.php
  25. 63 0
      src/Chamilo/InstallerBundle/Process/Step/SchemaStep.php
  26. 143 0
      src/Chamilo/InstallerBundle/Process/Step/SetupStep.php
  27. 32 0
      src/Chamilo/InstallerBundle/Process/Step/WelcomeStep.php
  28. 99 0
      src/Chamilo/InstallerBundle/README.md
  29. 340 0
      src/Chamilo/InstallerBundle/Requirement/ExtensionsRequirements.php
  30. 125 0
      src/Chamilo/InstallerBundle/Requirement/FilesystemRequirements.php
  31. 68 0
      src/Chamilo/InstallerBundle/Requirement/Requirement.php
  32. 43 0
      src/Chamilo/InstallerBundle/Requirement/RequirementCollection.php
  33. 186 0
      src/Chamilo/InstallerBundle/Requirement/SettingsRequirements.php
  34. 39 0
      src/Chamilo/InstallerBundle/Requirement/SyliusRequirements.php
  35. 54 0
      src/Chamilo/InstallerBundle/Resources/config/form.yml
  36. 7 0
      src/Chamilo/InstallerBundle/Resources/config/routing.yml
  37. 31 0
      src/Chamilo/InstallerBundle/Resources/config/services.yml
  38. 197 0
      src/Chamilo/InstallerBundle/Resources/public/css/install.css
  39. 60 0
      src/Chamilo/InstallerBundle/Resources/translations/messages.de.yml
  40. 128 0
      src/Chamilo/InstallerBundle/Resources/translations/messages.en.yml
  41. 57 0
      src/Chamilo/InstallerBundle/Resources/translations/messages.es.yml
  42. 58 0
      src/Chamilo/InstallerBundle/Resources/translations/messages.fr.yml
  43. 63 0
      src/Chamilo/InstallerBundle/Resources/translations/requirements.de.yml
  44. 57 0
      src/Chamilo/InstallerBundle/Resources/translations/requirements.en.yml
  45. 63 0
      src/Chamilo/InstallerBundle/Resources/translations/requirements.es.yml
  46. 63 0
      src/Chamilo/InstallerBundle/Resources/translations/requirements.fr.yml
  47. 37 0
      src/Chamilo/InstallerBundle/Resources/views/Form/fields.html.twig
  48. 48 0
      src/Chamilo/InstallerBundle/Resources/views/Process/Step/configure.html.twig
  49. 30 0
      src/Chamilo/InstallerBundle/Resources/views/Process/Step/final.html.twig
  50. 94 0
      src/Chamilo/InstallerBundle/Resources/views/Process/Step/installation.html.twig
  51. 62 0
      src/Chamilo/InstallerBundle/Resources/views/Process/Step/schema.html.twig
  52. 47 0
      src/Chamilo/InstallerBundle/Resources/views/Process/Step/setup.html.twig
  53. 22 0
      src/Chamilo/InstallerBundle/Resources/views/Process/Step/welcome.html.twig
  54. 141 0
      src/Chamilo/InstallerBundle/Resources/views/layout.html.twig
  55. 40 0
      src/Chamilo/InstallerBundle/Resources/views/progress.html.twig
  56. 89 0
      src/Chamilo/InstallerBundle/ScriptExecutor.php
  57. 226 0
      src/Chamilo/InstallerBundle/ScriptManager.php
  58. 12 0
      src/Chamilo/InstallerBundle/Validator/Constraints/DatabaseConnection.php
  59. 34 0
      src/Chamilo/InstallerBundle/Validator/Constraints/DatabaseConnectionValidator.php
  60. 266 0
      web/install.php

+ 12 - 0
composer.json

@@ -30,6 +30,12 @@
             "main/inc/lib/hook"
         ]
     },
+  "repositories": [
+    {
+      "type": "vcs",
+      "url": "https://github.com/jmontoyaa/MigrationBundle.git"
+    }
+  ],
     "require": {
         "php": ">=5.4",
         "ext-intl": "*",
@@ -53,9 +59,12 @@
         "sylius/settings-bundle": "~0.1",
         "sylius/translation": "~0.1",
         "sylius/attribute": "~0.1",
+        "sylius/flow-bundle": "~0.1",
         "sylius/resource-bundle": "~0.1",
         "sylius/resource": "~0.1",
 
+        "willdurand/faker-bundle": "~1.0",
+
         "sabre/vobject": "~3.1",
         "toin0u/digitalocean": "~1.4",
         "twig/twig": "1.*",
@@ -71,6 +80,8 @@
         "doctrine/orm": "~2.2,>=2.2.3,<2.5",
         "doctrine/migrations": "~1.0@dev",
         "doctrine/doctrine-migrations-bundle": "*@dev",
+        "doctrine/doctrine-fixtures-bundle": "~2.2",
+        "doctrine/data-fixtures": "~1.0@dev",
 
         "ircmaxell/password-compat": "~1.0.4",
         "gedmo/doctrine-extensions": "~2.3",
@@ -79,6 +90,7 @@
         "knplabs/knp-menu-bundle": "~2.0",
 
         "sp/bower-bundle": "dev-master",
+        "jmontoyaa/migration-bundle":"dev-master",
 
         "sonata-project/core-bundle": "2.3.x-dev",
         "sonata-project/user-bundle": "~2.2@dev",

+ 26 - 0
src/Chamilo/InstallerBundle/ChamiloInstallerBundle.php

@@ -0,0 +1,26 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+use Chamilo\InstallerBundle\DependencyInjection\Compiler\InstallerPass;
+
+/**
+ * Class ChamiloInstallerBundle
+ * @package Chamilo\InstallerBundle
+ */
+class ChamiloInstallerBundle extends Bundle
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function build(ContainerBuilder $container)
+    {
+        parent::build($container);
+
+        $container->addCompilerPass(new InstallerPass());
+    }
+}

+ 537 - 0
src/Chamilo/InstallerBundle/Command/InstallCommand.php

@@ -0,0 +1,537 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Command;
+
+use RuntimeException;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\ArrayInput;
+use Chamilo\InstallerBundle\CommandExecutor;
+use Chamilo\InstallerBundle\ScriptExecutor;
+
+/**
+ * Class InstallCommand
+ * Based in OroInstallBundle
+ * @package Chamilo\InstallerBundle\Command
+ */
+class InstallCommand extends ContainerAwareCommand
+{
+    /**
+     *
+     */
+    protected function configure()
+    {
+        $this
+            ->setName('chamilo:install')
+            ->setDescription('Chamilo installer.')
+            ->addOption(
+                'force',
+                null,
+                InputOption::VALUE_NONE,
+                'Force installation'
+            )
+            ->addOption(
+                'timeout',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                'Timeout for child command execution',
+                300
+            )
+            ->addOption(
+                'drop-database',
+                null,
+                InputOption::VALUE_NONE,
+                'Database will be dropped and all data will be deleted.'
+            );
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return int|null|void
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $forceInstall = $input->getOption('force');
+
+        $commandExecutor = new CommandExecutor(
+            $input->hasOption('env') ? $input->getOption('env') : null,
+            $output,
+            $this->getApplication()
+        //$this->getContainer()->get('oro_cache.oro_data_cache_manager')
+        );
+
+        $commandExecutor->setDefaultTimeout($input->getOption('timeout'));
+
+        // if there is application is not installed or no --force option
+        $isInstalled = $this->getContainer()->hasParameter('installed')
+            && $this->getContainer()->getParameter('installed');
+
+        if ($isInstalled && !$forceInstall) {
+
+            $output->writeln(
+                '<comment>ATTENTION</comment>: Chamilo is already installed.'
+            );
+            $output->writeln(
+                'To proceed with install - run command with <info>--force</info> option:'
+            );
+            $output->writeln(
+                sprintf('    <info>%s --force</info>', $this->getName())
+            );
+            $output->writeln(
+                'To reinstall over existing database - run command with <info>--force --drop-database</info> options:'
+            );
+            $output->writeln(
+                sprintf(
+                    '    <info>%s --force --drop-database</info>',
+                    $this->getName()
+                )
+            );
+            $output->writeln(
+                '<comment>ATTENTION</comment>: All data will be lost. '.
+                'Database backup is highly recommended before executing this command.'
+            );
+            $output->writeln('');
+
+            return;
+        }
+
+        if ($forceInstall) {
+            // if --force option we have to clear cache and set installed to false
+            $this->updateInstalledFlag(false);
+            // See https://github.com/symfony/symfony/issues/12278
+            $commandExecutor->runCommand(
+                'cache:clear',
+                array(
+                    '--no-optional-warmers' => true,
+                    '--process-isolation' => true,
+                )
+            );
+        }
+
+        $output->writeln('<info>Installing Chamilo.</info>');
+        $output->writeln('');
+
+        $this
+            ->checkStep($input, $output)
+            ->setupStep($commandExecutor, $input, $output)
+            ->finalStep($commandExecutor, $input, $output);
+
+        $output->writeln('');
+        $output->writeln(
+            sprintf(
+                '<info>Chamilo has been successfully installed in <comment>%s</comment> mode.</info>',
+                $input->getOption('env')
+            )
+        );
+        if ('prod' != $input->getOption('env')) {
+            $output->writeln(
+                '<info>To run application in <comment>prod</comment> mode, '.
+                'please run <comment>cache:clear</comment> command with <comment>--env prod</comment> parameter</info>'
+            );
+        }
+    }
+
+    /**
+     * @param string $command
+     * @param OutputInterface $output
+     * @param array $arguments
+     * @return $this
+     * @throws \Exception
+     */
+    protected function runCommand(
+        $command,
+        OutputInterface $output,
+        $arguments = array()
+    ) {
+        $arguments['command'] = $command;
+        $input = new ArrayInput($arguments);
+
+        $this
+            ->getApplication()
+            ->find($command)
+            ->run($input, $output);
+
+        return $this;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return $this
+     */
+    protected function checkStep(InputInterface $input, OutputInterface $output)
+    {
+        $output->writeln('<info>Checking system requirements.</info>');
+
+        require_once $this->getContainer()->getParameter('kernel.root_dir')
+            .DIRECTORY_SEPARATOR
+            .'ChamiloRequirements.php';
+
+        $collection = new \ChamiloRequirements();
+
+        $this->renderTable(
+            $collection->getMandatoryRequirements(),
+            'Mandatory requirements',
+            $output
+        );
+        $this->renderTable(
+            $collection->getPhpIniRequirements(),
+            'PHP settings',
+            $output
+        );
+        $this->renderTable(
+            $collection->getChamiloRequirements(),
+            'Chamilo specific requirements',
+            $output
+        );
+        $this->renderTable(
+            $collection->getRecommendations(),
+            'Optional recommendations',
+            $output
+        );
+
+        if (count($collection->getFailedRequirements())) {
+            throw new \RuntimeException(
+                'Some system requirements are not fulfilled. Please check output messages and fix them.'
+            );
+        }
+
+        $output->writeln('');
+
+        return $this;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return $this
+     */
+    protected function setupStep(
+        CommandExecutor $commandExecutor,
+        InputInterface $input,
+        OutputInterface $output
+    ) {
+        $output->writeln('<info>Setting up database.</info>');
+
+        /** @var DialogHelper $dialog */
+        $dialog = $this->getHelperSet()->get('dialog');
+        $options = $input->getOptions();
+
+        $input->setInteractive(false);
+
+        $schemaDropOptions = array(
+            '--force' => true,
+            '--process-isolation' => true,
+        );
+
+        if ($input->getOption('drop-database')) {
+            $schemaDropOptions['--full-database'] = true;
+        }
+
+        $commandExecutor
+            ->runCommand(
+                'doctrine:schema:drop',
+                $schemaDropOptions
+            )
+            //->runCommand('oro:entity-config:cache:clear', array('--no-warmup' => true))
+            //->runCommand('oro:entity-extend:cache:clear', array('--no-warmup' => true))
+            ->runCommand(
+                'oro:migration:load',
+                array(
+                    '--force' => true,
+                    '--process-isolation' => true,
+                )
+            )
+            /*->runCommand(
+                'oro:workflow:definitions:load',
+                array(
+                    '--process-isolation' => true,
+                )
+            )*/
+            /*->runCommand(
+                'oro:process:configuration:load',
+                array(
+                    '--process-isolation' => true
+                )
+            )*/
+            ->runCommand(
+                'oro:migration:data:load',
+                array(
+                    '--process-isolation' => true,
+                    '--no-interaction' => true,
+                )
+            );
+        //if ($this->getHelperSet()->get('dialog')->askConfirmation($output, '<question>Load fixtures (Y/N)?</question>', false)) {
+        $this->setupFixtures($input, $output);
+
+        // Installing platform settings
+        $settingsManager = $this->getContainer()->get(
+            'chamilo.settings.manager'
+        );
+        $url = $this->getContainer()->get('doctrine')->getRepository(
+            'ChamiloCoreBundle:AccessUrl'
+        )->find(1);
+        $settingsManager->installSchemas($url);
+
+        $output->writeln('');
+        $output->writeln('<info>Administration setup.</info>');
+
+        $this->setupAdmin($output);
+
+        $this->runCommand(
+            'sonata:page:update-core-routes',
+            $output,
+            array('--site' => array('all'))
+        );
+        $this->runCommand(
+            'sonata:page:create-snapshots',
+            $output,
+            array('--site' => array('all'))
+        );
+
+        $output->writeln('');
+
+        return $this;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     */
+    protected function setupDatabase(
+        InputInterface $input,
+        OutputInterface $output
+    ) {
+        $this
+            ->runCommand('doctrine:database:create', $input, $output)
+            ->runCommand('doctrine:schema:create', $input, $output)
+            //->runCommand('doctrine:phpcr:repository:init', $input, $output)
+            //->runCommand('assets:install', $input, $output)
+            //->runCommand('assetic:dump', $input, $output)
+        ;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     */
+    protected function setupFixtures(
+        InputInterface $input,
+        OutputInterface $output
+    ) {
+        $this
+            ->runCommand(
+                'doctrine:fixtures:load',
+                $output,
+                array('--no-interaction' => true)
+            )//->runCommand('doctrine:phpcr:fixtures:load', $input, $output)
+        ;
+    }
+
+    /**
+     * @param OutputInterface $output
+     */
+    protected function setupAdmin(OutputInterface $output)
+    {
+        $dialog = $this->getHelperSet()->get('dialog');
+        $em = $this->getApplication()->getKernel()->getContainer()->get(
+            'doctrine'
+        )->getManager();
+        /** @var \Chamilo\UserBundle\Entity\User $user */
+        $user = $em->getRepository('ChamiloUserBundle:User')->findOneById(1);
+
+        $user->setUsername(
+            $dialog->ask(
+                $output,
+                '<question>Username</question>(admin):',
+                'admin'
+            )
+        );
+        $user->setPlainPassword(
+            $dialog->ask(
+                $output,
+                '<question>Password</question>(admin):',
+                'admin'
+            )
+        );
+        $user->setFirstname(
+            $dialog->ask(
+                $output,
+                '<question>Firstname</question>(Jane):',
+                'Jane'
+            )
+        );
+        $user->setLastname(
+            $dialog->ask($output, '<question>Lastname</question>(Doe):', 'Doe')
+        );
+        $user->setEmail(
+            $dialog->ask(
+                $output,
+                '<question>Email</question>(admin@example.org):',
+                'admin@example.org'
+            )
+        );
+        $user->setEnabled(true);
+        $user->addRole('ROLE_SUPER_ADMIN');
+
+        $em = $this->getContainer()->get('doctrine.orm.entity_manager');
+        $em->persist($user);
+        $em->flush();
+    }
+
+    /**
+     * @param CommandExecutor $commandExecutor
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return InstallCommand
+     */
+    protected function finalStep(
+        CommandExecutor $commandExecutor,
+        InputInterface $input,
+        OutputInterface $output
+    ) {
+        $output->writeln('<info>Preparing application.</info>');
+        $input->setInteractive(false);
+        $commandExecutor
+            /*->runCommand(
+                'oro:navigation:init',
+                array(
+                    '--process-isolation' => true,
+                )
+            )
+            ->runCommand(
+                'fos:js-routing:dump',
+                array(
+                    '--target' => 'web/js/routes.js',
+                    '--process-isolation' => true,
+                )
+            )
+            ->runCommand('oro:localization:dump')
+            */
+            ->runCommand(
+                'assets:install',
+                array(
+                    'target' => './',
+                    '--symlink' => true,
+                    '--relative' => true,
+                )
+            )
+            ->runCommand(
+                'assetic:dump',
+                array(
+                    '--process-isolation' => true,
+                )
+            )/*->runCommand(
+                'oro:translation:dump',
+                array(
+                    '--process-isolation' => true,
+                )
+            )
+            ->runCommand(
+                'oro:requirejs:build',
+                array(
+                    '--ignore-errors' => true,
+                    '--process-isolation' => true,
+                )
+            )*/
+        ;
+
+        // run installer scripts
+        $this->processInstallerScripts($output, $commandExecutor);
+        $this->updateInstalledFlag(date('c'));
+
+        // clear the cache set installed flag in DI container
+        $commandExecutor->runCommand(
+            'cache:clear',
+            array(
+                '--process-isolation' => true,
+            )
+        );
+
+        $output->writeln('');
+
+        return $this;
+    }
+
+    /**
+     * Process installer scripts
+     *
+     * @param OutputInterface $output
+     * @param CommandExecutor $commandExecutor
+     */
+    protected function processInstallerScripts(
+        OutputInterface $output,
+        CommandExecutor $commandExecutor
+    ) {
+        $scriptExecutor = new ScriptExecutor(
+            $output,
+            $this->getContainer(),
+            $commandExecutor
+        );
+        /** @var ScriptManager $scriptManager */
+        $scriptManager = $this->getContainer()->get(
+            'chamilo_installer.script_manager'
+        );
+        $scriptFiles = $scriptManager->getScriptFiles();
+        if (!empty($scriptFiles)) {
+            foreach ($scriptFiles as $scriptFile) {
+                $scriptExecutor->runScript($scriptFile);
+            }
+        }
+    }
+
+    /**
+     * Update installed flag in parameters.yml
+     *
+     * @param bool|string $installed
+     */
+    protected function updateInstalledFlag($installed)
+    {
+        $dumper = $this->getContainer()->get(
+            'chamilo_installer.yaml_persister'
+        );
+        $params = $dumper->parse();
+        $params['system']['installed'] = $installed;
+        $dumper->dump($params);
+    }
+
+    /**
+     * Render requirements table
+     *
+     * @param array $collection
+     * @param string $header
+     * @param OutputInterface $output
+     */
+    protected function renderTable(
+        array $collection,
+        $header,
+        OutputInterface $output
+    ) {
+        /** @var TableHelper $table */
+        $table = $this->getHelperSet()->get('table');
+
+        $table
+            ->setHeaders(array('Check  ', $header))
+            ->setRows(array());
+
+        /** @var \Requirement $requirement */
+        foreach ($collection as $requirement) {
+            if ($requirement->isFulfilled()) {
+                $table->addRow(array('OK', $requirement->getTestMessage()));
+            } else {
+                $table->addRow(
+                    array(
+                        $requirement->isOptional() ? 'WARNING' : 'ERROR',
+                        $requirement->getHelpText(),
+                    )
+                );
+            }
+        }
+
+        $table->render($output);
+    }
+}

+ 98 - 0
src/Chamilo/InstallerBundle/Command/PlatformUpdateCommand.php

@@ -0,0 +1,98 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Command;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+
+use Chamilo\InstallerBundle\CommandExecutor;
+
+/**
+ * Class PlatformUpdateCommand
+ * * Based in OroInstallBundlePlatformUpdateCommand
+ * @package Chamilo\InstallerBundle\Command
+ */
+class PlatformUpdateCommand extends ContainerAwareCommand
+{
+    /**
+     * @inheritdoc
+     */
+    protected function configure()
+    {
+        $this->setName('chamilo:platform:update')
+            ->setDescription(
+                'Execute platform application update commands and init platform assets.'
+            )
+            ->addOption(
+                'force',
+                null,
+                InputOption::VALUE_NONE,
+                'Forces operation to be executed.'
+            )
+            ->addOption(
+                'timeout',
+                null,
+                InputOption::VALUE_OPTIONAL,
+                'Timeout for child command execution',
+                300
+            );
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $force = $input->getOption('force');
+
+        if ($force) {
+            $commandExecutor = new CommandExecutor(
+                $input->hasOption('env') ? $input->getOption('env') : null,
+                $output,
+                $this->getApplication()
+            //$this->getContainer()->get('oro_cache.oro_data_cache_manager')
+            );
+            $commandExecutor->setDefaultTimeout($input->getOption('timeout'));
+
+            $commandExecutor
+                ->runCommand(
+                    'oro:migration:load',
+                    array('--process-isolation' => true, '--force' => true)
+                )
+                //->runCommand('oro:workflow:definitions:load', array('--process-isolation' => true))
+                //->runCommand('oro:process:configuration:load', array('--process-isolation' => true))
+                ->runCommand(
+                    'oro:migration:data:load',
+                    array('--process-isolation' => true)
+                )
+                //->runCommand('oro:navigation:init', array('--process-isolation' => true))
+                //  ->runCommand('assets:install')
+                //  ->runCommand('assetic:dump')
+            ;
+            //->runCommand('fos:js-routing:dump', array('--target' => 'web/js/routes.js'))
+            //->runCommand('oro:localization:dump')
+            //->runCommand('oro:translation:dump')
+            //->runCommand('oro:requirejs:build', array('--ignore-errors' => true));
+        } else {
+            $output->writeln(
+                '<comment>ATTENTION</comment>: Database backup is highly recommended before executing this command.'
+            );
+            $output->writeln(
+                '           Please make sure that application cache is up-to-date before run this command.'
+            );
+            $output->writeln(
+                '           Use <info>cache:clear</info> if needed.'
+            );
+            $output->writeln('');
+            $output->writeln(
+                'To force execution run command with <info>--force</info> option:'
+            );
+            $output->writeln(
+                sprintf('    <info>%s --force</info>', $this->getName())
+            );
+        }
+    }
+}

+ 265 - 0
src/Chamilo/InstallerBundle/CommandExecutor.php

@@ -0,0 +1,265 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle;
+
+use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Application;
+use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
+use Symfony\Component\Process\ProcessBuilder;
+
+use Oro\Bundle\CacheBundle\Manager\OroDataCacheManager;
+use Chamilo\InstallerBundle\Process\PhpExecutableFinder;
+
+/**
+ * Class CommandExecutor
+ * @package Chamilo\InstallerBundle
+ */
+class CommandExecutor
+{
+    const DEFAULT_TIMEOUT = 300;
+
+    /**
+     * @var string|null
+     */
+    protected $env;
+
+    /**
+     * @var OutputInterface
+     */
+    protected $output;
+
+    /**
+     * @var Application
+     */
+    protected $application;
+
+    /**
+     * @var OroDataCacheManager
+     */
+    protected $dataCacheManager;
+
+    /**
+     * @var int
+     */
+    protected $lastCommandExitCode;
+
+    /**
+     * @var int
+     */
+    protected $defaultTimeout = 300;
+
+    /**
+     * Constructor
+     *
+     * @param string|null $env
+     * @param OutputInterface $output
+     * @param Application $application
+     */
+    public function __construct(
+        $env,
+        OutputInterface $output,
+        Application $application
+        //OroDataCacheManager $dataCacheManager = null
+    )
+    {
+        $this->env = $env;
+        $this->output = $output;
+        $this->application = $application;
+        //$this->dataCacheManager = $dataCacheManager;
+    }
+
+    /**
+     * Launches a command.
+     * If '--process-isolation' parameter is specified the command will be launched as a separate process.
+     * In this case you can parameter '--process-timeout' to set the process timeout
+     * in seconds. Default timeout is 300 seconds.
+     * If '--ignore-errors' parameter is specified any errors are ignored;
+     * otherwise, an exception is raises if an error happened.
+     *
+     * @param string $command
+     * @param array $params
+     * @return CommandExecutor
+     * @throws \RuntimeException if command failed and '--ignore-errors' parameter is not specified
+     */
+    public function runCommand($command, $params = array())
+    {
+        $params = array_merge(
+            array(
+                'command' => $command,
+            ),
+            $params
+        );
+        if ($this->env && $this->env !== 'dev') {
+            $params['--env'] = $this->env;
+        }
+        $ignoreErrors = false;
+        if (array_key_exists('--ignore-errors', $params)) {
+            $ignoreErrors = true;
+            unset($params['--ignore-errors']);
+        }
+
+        if (array_key_exists('--process-isolation', $params)) {
+            unset($params['--process-isolation']);
+            $pb = new ProcessBuilder();
+            $pb
+                ->add($this->getPhp())
+                ->add($_SERVER['argv'][0]);
+
+            if (array_key_exists('--process-timeout', $params)) {
+                $pb->setTimeout($params['--process-timeout']);
+                unset($params['--process-timeout']);
+            } else {
+                $pb->setTimeout($this->defaultTimeout);
+            }
+
+            foreach ($params as $name => $val) {
+                $this->processParameter($pb, $name, $val);
+            }
+
+            $process = $pb
+                ->inheritEnvironmentVariables(true)
+                ->getProcess();
+
+            $output = $this->output;
+            $process->run(
+                function ($type, $data) use ($output) {
+                    $output->write($data);
+                }
+            );
+
+            $this->lastCommandExitCode = $process->getExitCode();
+
+            // synchronize all data caches
+            /*if ($this->dataCacheManager) {
+                $this->dataCacheManager->sync();
+            }*/
+        } else {
+            $this->application->setAutoExit(false);
+            $this->application->setCatchExceptions(false);
+            $this->lastCommandExitCode = $this->application->run(
+                new ArrayInput($params),
+                $this->output
+            );
+        }
+
+        $this->processResult($ignoreErrors);
+
+        return $this;
+    }
+
+    /**
+     * Gets an exit code of last executed command
+     *
+     * @return int
+     */
+    public function getLastCommandExitCode()
+    {
+        return $this->lastCommandExitCode;
+    }
+
+    /**
+     * @param bool $ignoreErrors
+     * @throws \RuntimeException
+     */
+    protected function processResult($ignoreErrors)
+    {
+        if (0 !== $this->lastCommandExitCode) {
+            if ($ignoreErrors) {
+                $this->output->writeln(
+                    sprintf(
+                        '<error>The command terminated with an exit code: %u.</error>',
+                        $this->lastCommandExitCode
+                    )
+                );
+            } else {
+                throw new \RuntimeException(
+                    sprintf(
+                        'The command terminated with an exit code: %u.',
+                        $this->lastCommandExitCode
+                    )
+                );
+            }
+        }
+    }
+
+    /**
+     * @param ProcessBuilder $pb
+     * @param string $name
+     * @param array|string|null $value
+     */
+    protected function processParameter(ProcessBuilder $pb, $name, $value)
+    {
+        if ($name && '-' === $name[0]) {
+            if ($value === true) {
+                $this->addParameter($pb, $name);
+            } else {
+                $this->addParameter($pb, $name, $value);
+            }
+        } else {
+            $this->addParameter($pb, $value);
+        }
+    }
+
+    /**
+     * @param ProcessBuilder $pb
+     * @param string $name
+     * @param array|string|null $value
+     */
+    protected function addParameter(ProcessBuilder $pb, $name, $value = null)
+    {
+        $parameters = array();
+
+        if (null !== $value) {
+            if (is_array($value)) {
+                foreach ($value as $item) {
+                    $parameters[] = sprintf('%s=%s', $name, $item);
+                }
+            } else {
+                $parameters[] = sprintf('%s=%s', $name, $value);
+            }
+        } else {
+            $parameters[] = $name;
+        }
+
+        foreach ($parameters as $parameter) {
+            $pb->add($parameter);
+        }
+    }
+
+    /**
+     * Finds the PHP executable.
+     *
+     * @return string
+     * @throws FileNotFoundException
+     */
+    protected function getPhp()
+    {
+        $phpFinder = new PhpExecutableFinder();
+        $phpPath = $phpFinder->find();
+        if (!$phpPath) {
+            throw new FileNotFoundException(
+                'The PHP executable could not be found.'
+            );
+        }
+
+        return $phpPath;
+    }
+
+    /**
+     * @return int
+     */
+    public function getDefaultTimeout()
+    {
+        return $this->defaultTimeout;
+    }
+
+    /**
+     * @param int $defaultTimeout
+     */
+    public function setDefaultTimeout($defaultTimeout)
+    {
+        $this->defaultTimeout = $defaultTimeout;
+    }
+}

+ 21 - 0
src/Chamilo/InstallerBundle/DependencyInjection/ChamiloInstallerExtension.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace Chamilo\InstallerBundle\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\DependencyInjection\Extension;
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\DependencyInjection\Loader;
+
+class ChamiloInstallerExtension extends Extension
+{
+    public function load(array $config, ContainerBuilder $container)
+    {
+        $loader = new Loader\YamlFileLoader(
+            $container,
+            new FileLocator(__DIR__.'/../Resources/config')
+        );
+        $loader->load('services.yml');
+        $loader->load('form.yml');
+    }
+}

+ 30 - 0
src/Chamilo/InstallerBundle/DependencyInjection/Compiler/InstallerPass.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace Chamilo\InstallerBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+class InstallerPass implements CompilerPassInterface
+{
+    public function process(ContainerBuilder $container)
+    {
+        // we have to add installer listener even if the application is already installed
+        // this is required because we are clearing the cache on the last installation step
+        // and as the result the login page is appeared instead of the final installer page
+        //if ($container->hasParameter('installed') && $container->getParameter('installed')) {
+        //    return;
+        //}
+
+        $listener = $container->getDefinition('kernel.listener.install.event');
+
+        $listener->addTag(
+            'kernel.event_listener',
+            array(
+                'priority' => 10,
+                'event' => 'kernel.request',
+                'method' => 'onRequest',
+            )
+        );
+    }
+}

+ 41 - 0
src/Chamilo/InstallerBundle/DependencyInjection/Configuration.php

@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\DependencyInjection;
+
+use Symfony\Component\Config\Definition\Builder\TreeBuilder;
+use Symfony\Component\Config\Definition\ConfigurationInterface;
+
+class Configuration implements ConfigurationInterface
+{
+    public function getConfigTreeBuilder()
+    {
+        $treeBuilder = new TreeBuilder();
+
+        $treeBuilder->root('chamilo_installer')
+            ->addDefaultsIfNotSet()
+            ->children()
+            ->arrayNode('classes')
+            ->addDefaultsIfNotSet()
+            ->children()
+            ->arrayNode('user')
+            ->addDefaultsIfNotSet()
+            ->children()
+            ->scalarNode('model')->isRequired()->end()
+            ->end()
+            ->end()
+            ->end()
+            ->end()
+            ->end();
+
+        return $treeBuilder;
+    }
+}

+ 104 - 0
src/Chamilo/InstallerBundle/EventListener/RequestListener.php

@@ -0,0 +1,104 @@
+<?php
+
+namespace Chamilo\InstallerBundle\EventListener;
+
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\HttpKernel;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\Routing\RouterInterface;
+
+class RequestListener
+{
+    /**
+     * @var Router
+     */
+    protected $router;
+
+    /**
+     * Installed flag
+     *
+     * @var bool
+     */
+    protected $installed;
+
+    /**
+     * Debug flag
+     *
+     * @var bool
+     */
+    protected $debug;
+
+    /**
+     * Constructor
+     */
+    public function __construct(
+        RouterInterface $router,
+        $installed,
+        $debug = false
+    ) {
+        $this->router = $router;
+        $this->installed = $installed;
+        $this->debug = $debug;
+    }
+
+    public function onRequest(GetResponseEvent $event)
+    {
+        if (HttpKernel::MASTER_REQUEST != $event->getRequestType()) {
+            return;
+        }
+
+        if (!$this->installed) {
+            $allowedRoutes = array(
+                'chamilo_installer_flow',
+                'sylius_flow_display',
+                'sylius_flow_forward',
+            );
+
+            if ($this->debug) {
+                $allowedRoutes = array_merge(
+                    $allowedRoutes,
+                    array(
+                        '_wdt',
+                        '_profiler',
+                        '_profiler_search',
+                        '_profiler_search_bar',
+                        '_profiler_search_results',
+                        '_profiler_router',
+                    )
+                );
+            }
+
+            if (!in_array(
+                $event->getRequest()->get('_route'),
+                $allowedRoutes
+            )
+            ) {
+                $event->setResponse(
+                    new RedirectResponse(
+                        $event->getRequest()->getBasePath().'/install.php'
+                    )
+                );
+            }
+
+            $event->stopPropagation();
+        } else {
+            // allow open the installer even if the application is already installed
+            // this is required because we are clearing the cache on the last installation step
+            // and as the result the login page is appeared instead of the final installer page
+            if ($event->getRequest()->attributes->get(
+                    'scenarioAlias'
+                ) === 'chamilo_installer' &&
+                (
+                    $event->getRequest()->attributes->get(
+                        '_route'
+                    ) === 'sylius_flow_forward' ||
+                    $event->getRequest()->attributes->get(
+                        '_route'
+                    ) === 'sylius_flow_display'
+                )
+            ) {
+                $event->stopPropagation();
+            }
+        }
+    }
+}

+ 98 - 0
src/Chamilo/InstallerBundle/Form/Type/Configuration/DatabaseType.php

@@ -0,0 +1,98 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Form\Type\Configuration;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Class DatabaseType
+ * @package Chamilo\InstallerBundle\Form\Type\Configuration
+ */
+class DatabaseType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            /*->add(
+                'chamilo_installer_database_driver',
+                'choice',
+                array(
+                    'label'       => 'form.configuration.database.driver',
+                    'choices'       => array(
+                        'pdo_mysql' => 'MySQL',
+                        'pdo_pgsql' => 'PostgreSQL',
+                    ),
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                        new ExtensionLoaded(),
+                    ),
+                )
+            )*/
+            ->add(
+                'chamilo_installer_database_host',
+                'text',
+                array(
+                    'label' => 'form.configuration.database.host',
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                    ),
+                )
+            )
+            ->add(
+                'chamilo_installer_database_port',
+                'integer',
+                array(
+                    'label' => 'form.configuration.database.port',
+                    'required' => false,
+                    'constraints' => array(
+                        new Assert\Type(array('type' => 'integer')),
+                    ),
+                )
+            )
+            ->add(
+                'chamilo_installer_database_name',
+                'text',
+                array(
+                    'label' => 'form.configuration.database.name',
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                    ),
+                )
+            )
+            ->add(
+                'chamilo_installer_database_user',
+                'text',
+                array(
+                    'label' => 'form.configuration.database.user',
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                    ),
+                )
+            )
+            ->add(
+                'chamilo_installer_database_password',
+                'password',
+                array(
+                    'label' => 'form.configuration.database.password',
+                    'required' => false,
+                )
+            )
+            ->add(
+                'chamilo_installer_database_drop_full',
+                'checkbox',
+                array(
+                    'label' => 'form.configuration.database.drop_full',
+                    'required' => false,
+                    'data' => false,
+                )
+            );
+    }
+
+    public function getName()
+    {
+        return 'chamilo_installer_configuration_database';
+    }
+}

+ 122 - 0
src/Chamilo/InstallerBundle/Form/Type/Configuration/MailerType.php

@@ -0,0 +1,122 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Form\Type\Configuration;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormInterface;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+use Symfony\Component\OptionsResolver\OptionsResolverInterface;
+
+/**
+ * Class MailerType
+ * @package Chamilo\InstallerBundle\Form\Type\Configuration
+ */
+class MailerType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->add(
+                'chamilo_installer_mailer_transport',
+                'choice',
+                array(
+                    'label' => 'form.configuration.mailer.transport.header',
+                    'preferred_choices' => array('mail'),
+                    'choices' => array(
+                        'mail' => 'PHP mail',
+                        'smtp' => 'SMTP',
+                        'sendmail' => 'sendmail',
+                    ),
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                    ),
+                    //'client_validation' => false,
+                )
+            )
+            ->add(
+                'chamilo_installer_mailer_host',
+                'text',
+                array(
+                    'label' => 'form.configuration.mailer.host',
+                    'constraints' => array(
+                        new Assert\NotBlank(array('groups' => array('SMTP'))),
+                    ),
+                )
+            )
+            ->add(
+                'chamilo_installer_mailer_port',
+                'integer',
+                array(
+                    'label' => 'form.configuration.mailer.port',
+                    'required' => false,
+                    'constraints' => array(
+                        new Assert\Type(
+                            array(
+                                'groups' => array('SMTP'),
+                                'type' => 'integer',
+                            )
+                        ),
+                    ),
+                )
+            )
+            ->add(
+                'chamilo_installer_mailer_encryption',
+                'choice',
+                array(
+                    'label' => 'form.configuration.mailer.encryption',
+                    'required' => false,
+                    'preferred_choices' => array(''),
+                    'choices' => array(
+                        '' => 'None',
+                        'ssl' => 'SSL',
+                        'tls' => 'TLS',
+                    ),
+                    //'client_validation' => false,
+                )
+            )
+            ->add(
+                'chamilo_installer_mailer_user',
+                'text',
+                array(
+                    'label' => 'form.configuration.mailer.user',
+                    'required' => false,
+                )
+            )
+            ->add(
+                'chamilo_installer_mailer_password',
+                'password',
+                array(
+                    'label' => 'form.configuration.mailer.password',
+                    'required' => false,
+                )
+            );
+    }
+
+    /**
+     * @param OptionsResolverInterface $resolver
+     */
+    public function setDefaultOptions(OptionsResolverInterface $resolver)
+    {
+        $resolver->setDefaults(
+            array(
+                'validation_groups' => function (FormInterface $form) {
+                    $data = $form->getData();
+
+                    return 'smtp' == $data['chamilo_installer_mailer_transport']
+                        ? array('Default', 'SMTP')
+                        : array('Default', '');
+                },
+            )
+        );
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return 'chamilo_installer_configuration_mailer';
+    }
+}

+ 49 - 0
src/Chamilo/InstallerBundle/Form/Type/Configuration/SystemType.php

@@ -0,0 +1,49 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Form\Type\Configuration;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Class SystemType
+ * @package Chamilo\InstallerBundle\Form\Type\Configuration
+ */
+class SystemType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->add(
+                'chamilo_installer_locale',
+                'locale',
+                array(
+                    'label' => 'form.configuration.system.locale',
+                    'preferred_choices' => array('en'),
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                        new Assert\Locale(),
+                    ),
+                    //'client_validation'  => false,
+                )
+            )
+            ->add(
+                'chamilo_installer_secret',
+                'text',
+                array(
+                    'label' => 'form.configuration.system.secret',
+                    'data' => md5(uniqid()),
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                    ),
+                )
+            );
+    }
+
+    public function getName()
+    {
+        return 'chamilo_installer_configuration_system';
+    }
+}

+ 58 - 0
src/Chamilo/InstallerBundle/Form/Type/ConfigurationType.php

@@ -0,0 +1,58 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Form\Type;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+
+use Chamilo\InstallerBundle\Validator\Constraints as Assert;
+
+/**
+ * Class ConfigurationType
+ * @package Chamilo\InstallerBundle\Form\Type
+ */
+class ConfigurationType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        // See class DatabaseConnectionValidator to see the validator.
+        $builder
+            ->add(
+                'database',
+                'chamilo_installer_configuration_database',
+                array(
+                    'label' => 'form.configuration.database.header',
+                    'constraints' => array(
+                        new Assert\DatabaseConnection(),
+                    ),
+                )
+            )
+            ->add(
+                'mailer',
+                'chamilo_installer_configuration_mailer',
+                array(
+                    'label' => 'form.configuration.mailer.header',
+                )
+            )
+            /*->add(
+                'websocket',
+                'chamilo_installer_configuration_websocket',
+                array(
+                    'label' => 'form.configuration.websocket.header'
+                )
+            )*/
+            ->add(
+                'system',
+                'chamilo_installer_configuration_system',
+                array(
+                    'label' => 'form.configuration.system.header',
+                )
+            );
+    }
+
+    public function getName()
+    {
+        return 'chamilo_installer_configuration';
+    }
+}

+ 99 - 0
src/Chamilo/InstallerBundle/Form/Type/Setup/AdminType.php

@@ -0,0 +1,99 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Form\Type\Setup;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+use Symfony\Component\OptionsResolver\OptionsResolverInterface;
+
+/**
+ * Class AdminType
+ * @package Chamilo\InstallerBundle\Form\Type\Setup
+ */
+class AdminType extends AbstractType
+{
+    protected $dataClass;
+
+    public function __construct($dataClass)
+    {
+        $this->dataClass = $dataClass;
+    }
+
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->add(
+                'username',
+                'text',
+                array(
+                    'label' => 'form.setup.admin.username',
+                )
+            )
+            ->add(
+                'plainPassword',
+                'repeated',
+                array(
+                    'type' => 'password',
+                    'invalid_message' => 'The password fields must match.',
+                    'first_options' => array('label' => 'form.setup.admin.password'),
+                    'second_options' => array('label' => 'form.setup.admin.password_re'),
+                )
+            )
+            ->add(
+                'email',
+                'email',
+                array(
+                    'label' => 'form.setup.admin.email',
+                )
+            )
+            ->add(
+                'firstName',
+                'text',
+                array(
+                    'label' => 'form.setup.admin.firstname',
+                )
+            )
+            ->add(
+                'lastName',
+                'text',
+                array(
+                    'label' => 'form.setup.admin.lastname',
+                )
+            )
+            ->add(
+                'phone',
+                'text',
+                array(
+                    'label' => 'form.setup.admin.phone',
+                )
+            );
+        /*
+            ->add(
+                'loadFixtures',
+                'checkbox',
+                array(
+                    'label'    => 'form.setup.load_fixtures',
+                    'required' => false,
+                    'mapped'   => false,
+                )
+            );*/
+    }
+
+    public function setDefaultOptions(OptionsResolverInterface $resolver)
+    {
+        $resolver->setDefaults(
+            array(
+                'data_class' => $this->dataClass,
+                'validation_groups' => array('Registration', 'Default'),
+            )
+        );
+    }
+
+
+    public function getName()
+    {
+        return 'chamilo_installer_setup_admin';
+    }
+}

+ 109 - 0
src/Chamilo/InstallerBundle/Form/Type/Setup/PortalType.php

@@ -0,0 +1,109 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Form\Type\Setup;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+use Symfony\Component\OptionsResolver\OptionsResolverInterface;
+
+/**
+ * Class PortalType
+ * @package Chamilo\InstallerBundle\Form\Type\Setup
+ */
+class PortalType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->add(
+                'institution',
+                'text',
+                array(
+                    'label' => 'form.setup.portal.institution',
+                    'mapped' => false,
+                    'constraints' => array(
+                        new Assert\NotBlank(),
+                        new Assert\Length(array('max' => 15)),
+                    ),
+                )
+            )
+            ->add(
+                'site_name',
+                'text',
+                array(
+                    'label' => 'form.setup.portal.site_name',
+                    'mapped' => false,
+                    'required' => false,
+                )
+            )
+            ->add(
+                'institution_url',
+                'url',
+                array(
+                    'label' => 'form.setup.portal.institution_url',
+                    'mapped' => false,
+                    'required' => false,
+                )
+            )
+            ->add(
+                'allow_self_registration',
+                'choice',
+                array(
+                    'label' => 'form.setup.portal.allow_self_registration',
+                    'mapped' => false,
+                    'required' => true,
+                    'choices' => array(
+                        '1' => 'Yes',
+                        '0' => 'No',
+                    ),
+                )
+            )
+            ->add(
+                'allow_self_registration_as_trainer',
+                'choice',
+                array(
+                    'label' => 'form.setup.portal.allow_self_registration_as_trainer',
+                    'mapped' => false,
+                    'required' => true,
+                    'choices' => array(
+                        '1' => 'Yes',
+                        '0' => 'No',
+                    ),
+                )
+            )
+            ->add(
+                'timezone',
+                'timezone',
+                array(
+                    'label' => 'form.setup.portal.timezone',
+                    'mapped' => false,
+                    'required' => false,
+                    'preferred_choices' => array('Europe/Paris'),
+                )
+            );
+
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setDefaultOptions(OptionsResolverInterface $resolver)
+    {
+        $resolver->setDefaults(
+            array(
+                'allow_self_registration_as_trainer' => '0',
+                'allow_self_registration' => '1',
+            )
+        );
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return 'chamilo_installer_setup_portal';
+    }
+}

+ 42 - 0
src/Chamilo/InstallerBundle/Form/Type/SetupType.php

@@ -0,0 +1,42 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Form\Type;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Validator\Constraints as Assert;
+
+/**
+ * Class SetupType
+ * @package Chamilo\InstallerBundle\Form\Type
+ */
+class SetupType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options)
+    {
+        $builder
+            ->add(
+                'admin',
+                'chamilo_installer_setup_admin',
+                array(
+                    'label' => 'form.setup.admin.header',
+                )
+            )
+            ->add(
+                'portal',
+                'chamilo_installer_setup_portal',
+                array(
+                    'label' => 'form.setup.portal.header',
+                )
+            );
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return 'chamilo_installer_setup';
+    }
+}

+ 14 - 0
src/Chamilo/InstallerBundle/InstallerEvents.php

@@ -0,0 +1,14 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle;
+
+final class InstallerEvents
+{
+    /**
+     * The installer.finish event is thrown upon complete of a final step of the installation process.
+     *
+     * @var string
+     */
+    const FINISH = 'installer.finish';
+}

+ 79 - 0
src/Chamilo/InstallerBundle/Persister/YamlPersister.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace Chamilo\InstallerBundle\Persister;
+
+use Symfony\Component\Yaml\Yaml;
+
+class YamlPersister
+{
+    /**
+     * Path to parameters.yml file
+     *
+     * @var string
+     */
+    protected $paramFile;
+
+    /**
+     * @param string $dir Path to parameters storage directory
+     * @param string $env Current environment
+     */
+    public function __construct($dir, $env)
+    {
+        if (file_exists($file = $dir.'/parameters_'.$env.'.yml')) {
+            $this->paramFile = $file;
+        } elseif (file_exists($dir.'/parameters_'.$env.'.yml.dist')) {
+            $this->paramFile = $dir.'/parameters_'.$env.'.yml';
+        } else {
+            $this->paramFile = $dir.'/parameters.yml';
+        }
+    }
+
+    public function parse()
+    {
+        $data = Yaml::parse($this->paramFile);
+
+        if (!is_array($data) || !isset($data['parameters'])) {
+            return array();
+        }
+
+        $parameters = array();
+
+        foreach ($data['parameters'] as $key => $value) {
+            $section = explode('_', $key);
+            $section = isset($section[1]) ? $section[0] : 'system';
+
+            if (!isset($parameters[$section])) {
+                $parameters[$section] = array();
+            }
+
+            $parameters[$section]['chamilo_installer_'.$key] = $value;
+        }
+
+        return $parameters;
+    }
+
+    public function dump(array $data)
+    {
+        $parameters = array();
+
+        foreach ($data as $section) {
+            foreach ($section as $key => $value) {
+                $parameters[str_replace(
+                    'chamilo_installer_',
+                    '',
+                    $key
+                )] = $value;
+            }
+        }
+
+        if (false === file_put_contents(
+                $this->paramFile,
+                Yaml::dump(array('parameters' => $parameters))
+            )
+        ) {
+            throw new \RuntimeException(
+                sprintf('Failed to write to %s.', $this->paramFile)
+            );
+        }
+    }
+}

+ 34 - 0
src/Chamilo/InstallerBundle/Process/InstallerScenario.php

@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\Process;
+
+use Sylius\Bundle\FlowBundle\Process\Builder\ProcessBuilderInterface;
+use Sylius\Bundle\FlowBundle\Process\Scenario\ProcessScenarioInterface;
+use Symfony\Component\DependencyInjection\ContainerAware;
+
+class InstallerScenario extends ContainerAware implements ProcessScenarioInterface
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function build(ProcessBuilderInterface $builder)
+    {
+        $builder
+            ->add('welcome', new Step\WelcomeStep())
+            ->add('configure', new Step\ConfigureStep())
+            ->add('schema', new Step\SchemaStep())
+            ->add('setup', new Step\SetupStep())
+            ->add('installation', new Step\InstallationStep())
+            ->add('final', new Step\FinalStep())
+            ->setRedirect('homepage');
+    }
+}

+ 22 - 0
src/Chamilo/InstallerBundle/Process/PhpExecutableFinder.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace Chamilo\InstallerBundle\Process;
+
+use Symfony\Component\Process\PhpExecutableFinder as BasePhpExecutableFinder;
+
+class PhpExecutableFinder extends BasePhpExecutableFinder
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function find($includeArgs = true)
+    {
+        if ($php = getenv('CHAMILO_PHP_PATH')) {
+            if (is_executable($php)) {
+                return $php;
+            }
+        }
+
+        return parent::find($includeArgs);
+    }
+}

+ 151 - 0
src/Chamilo/InstallerBundle/Process/Step/AbstractStep.php

@@ -0,0 +1,151 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Process\Step;
+
+use Chamilo\InstallerBundle\CommandExecutor;
+use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\Console\Output\StreamOutput;
+
+use Sylius\Bundle\FlowBundle\Process\Step\AbstractControllerStep;
+
+/**
+ * Class AbstractStep
+ * @package Chamilo\InstallerBundle\Process\Step
+ */
+abstract class AbstractStep extends AbstractControllerStep
+{
+    /**
+     * @var Application
+     */
+    protected $application;
+
+    /**
+     * @var StreamOutput
+     */
+    protected $output;
+
+    /**
+     *
+     * @param  string $command
+     * @param  array $params
+     * @return mixed
+     */
+    protected function handleAjaxAction($command, $params = array())
+    {
+        $exitCode = $this->runCommand($command, $params);
+
+        return $this->getRequest()->isXmlHttpRequest()
+            ? new JsonResponse(array('result' => true, 'exitCode' => $exitCode))
+            : $this->redirect(
+                $this->generateUrl(
+                    'sylius_flow_display',
+                    array(
+                        'scenarioAlias' => 'chamilo_installer',
+                        'stepName' => $this->getName(),
+                    )
+                )
+            );
+    }
+
+    /**
+     * Execute Symfony2 command
+     *
+     * @param  string $command Command name (for example, "cache:clear")
+     * @param  array $params [optional] Additional command parameters, like "--force" etc
+     * @return int an executed command exit code
+     * @throws \Exception
+     * @throws \RuntimeException
+     */
+    protected function runCommand($command, $params = array())
+    {
+        $application = $this->getApplication();
+        $output = $this->getOutput();
+        $commandExecutor = new CommandExecutor(
+            $application->getKernel()->getEnvironment(),
+            $output,
+            $application
+        );
+        $output->writeln('');
+        $output->writeln(
+            sprintf(
+                '[%s] Launching "%s" command',
+                date('Y-m-d H:i:s'),
+                $command
+            )
+        );
+        error_log(
+            sprintf(
+                '[%s] Launching "%s" command',
+                date('Y-m-d H:i:s'),
+                $command
+            )
+        );
+        error_log($command);
+        error_log(print_r($params, 1));
+        // Add error_log in vendor/symfony/symfony/src/Symfony/Component/Console/Application.php run() function
+        $mem = (int)memory_get_usage() / (1024 * 1024);
+        $time = time();
+
+        $result = null;
+        try {
+            $commandExecutor->runCommand($command, $params);
+            $result = $commandExecutor->getLastCommandExitCode();
+        } catch (\RuntimeException $ex) {
+            $result = $ex;
+            error_log($ex->getMessage());
+        }
+
+        $output->writeln('');
+        $output->writeln(
+            sprintf(
+                'Command "%s" executed in %u second(s), memory usage: %.2fMb',
+                $command,
+                time() - $time,
+                (int)memory_get_usage() / (1024 * 1024) - $mem
+            )
+        );
+        $output->writeln('');
+
+        // check for any error
+        if ($result instanceof \RuntimeException) {
+            throw $result;
+        }
+
+        return $result;
+    }
+
+    /**
+     * @return Application
+     */
+    protected function getApplication()
+    {
+        if (!$this->application) {
+            $this->application = new Application($this->get('kernel'));
+
+            $this->application->setAutoExit(false);
+        }
+
+        return $this->application;
+    }
+
+    /**
+     * @return StreamOutput
+     */
+    protected function getOutput()
+    {
+        if (!$this->output) {
+            $this->output = new StreamOutput(
+                fopen(
+                    $this->container->getParameter(
+                        'kernel.logs_dir'
+                    ).DIRECTORY_SEPARATOR.'chamilo_install.log',
+                    'a+'
+                )
+            );
+        }
+
+        return $this->output;
+    }
+}

+ 74 - 0
src/Chamilo/InstallerBundle/Process/Step/ConfigureStep.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace Chamilo\InstallerBundle\Process\Step;
+
+use Sylius\Bundle\FlowBundle\Process\Context\ProcessContextInterface;
+
+/**
+ * Class ConfigureStep
+ * @package Chamilo\InstallerBundle\Process\Step
+ */
+class ConfigureStep extends AbstractStep
+{
+    public function displayAction(ProcessContextInterface $context)
+    {
+        if ($this->container->hasParameter(
+                'installed'
+            ) && $this->container->getParameter('installed')
+        ) {
+            return $this->redirect($this->generateUrl('home'));
+        }
+
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:configure.html.twig',
+            array(
+                'form' => $this->createConfigurationForm()->createView(),
+            )
+        );
+    }
+
+    public function forwardAction(ProcessContextInterface $context)
+    {
+        set_time_limit(600);
+
+        $form = $this->createConfigurationForm();
+
+        $form->handleRequest($this->getRequest());
+
+        if ($form->isValid()) {
+            $data = $form->getData();
+
+            $context->getStorage()->set(
+                'fullDatabase',
+                $form->has('database') &&
+                $form->get('database')->has(
+                    'chamilo_installer_database_drop_full'
+                ) &&
+                $form->get('database')->get(
+                    'chamilo_installer_database_drop_full'
+                )->getData()
+            );
+
+            $this->get('chamilo_installer.yaml_persister')->dump($data);
+
+            return $this->complete();
+        }
+
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:configure.html.twig',
+            array(
+                'form' => $form->createView(),
+            )
+        );
+    }
+
+    protected function createConfigurationForm()
+    {
+        $data = $this->get('chamilo_installer.yaml_persister')->parse();
+
+        return $this->createForm(
+            'chamilo_installer_configuration',
+            empty($data) ? null : $data
+        );
+    }
+}

+ 22 - 0
src/Chamilo/InstallerBundle/Process/Step/FinalStep.php

@@ -0,0 +1,22 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Process\Step;
+
+use Sylius\Bundle\FlowBundle\Process\Context\ProcessContextInterface;
+
+/**
+ * Class FinalStep
+ * @package Chamilo\InstallerBundle\Process\Step
+ */
+class FinalStep extends AbstractStep
+{
+    public function displayAction(ProcessContextInterface $context)
+    {
+        $this->complete();
+
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:final.html.twig'
+        );
+    }
+}

+ 133 - 0
src/Chamilo/InstallerBundle/Process/Step/InstallationStep.php

@@ -0,0 +1,133 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Process\Step;
+
+use Sylius\Bundle\FlowBundle\Process\Context\ProcessContextInterface;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+use Chamilo\InstallerBundle\InstallerEvents;
+use Chamilo\InstallerBundle\CommandExecutor;
+use Chamilo\InstallerBundle\ScriptExecutor;
+
+/**
+ * Class InstallationStep
+ * @package Chamilo\InstallerBundle\Process\Step
+ */
+class InstallationStep extends AbstractStep
+{
+    /**
+     * @param ProcessContextInterface $context
+     * @return JsonResponse|\Symfony\Component\HttpFoundation\Response
+     */
+    public function displayAction(ProcessContextInterface $context)
+    {
+        set_time_limit(900);
+
+        $action = $this->getRequest()->query->get('action');
+        switch ($action) {
+            case 'pages':
+                $this->handleAjaxAction(
+                    'sonata:page:update-core-routes',
+                    array('--site' => array('all'))
+                );
+
+                return $this->handleAjaxAction(
+                    'sonata:page:create-snapshots',
+                    array('--site' => array('all'))
+                );
+            case 'fixtures':
+                return $this->handleAjaxAction(
+                    'oro:migration:data:load',
+                    array('--fixtures-type' => 'demo')
+                );
+            case 'navigation':
+                return $this->handleAjaxAction('oro:navigation:init');
+//            case 'js-routing':
+//                return $this->handleAjaxAction('fos:js-routing:dump', array('--target' => 'js/routes.js'));
+            case 'localization':
+                //return $this->handleAjaxAction('oro:localization:dump');
+            case 'assets':
+                /*return $this->handleAjaxAction(
+                    'oro:assets:install',
+                    array('target' => './', '--exclude' => ['OroInstallerBundle'])
+                );*/
+
+                $settingsManager = $this->container->get(
+                    'chamilo.settings.manager'
+                );
+                $url = $this->container->get('doctrine')->getRepository(
+                    'ChamiloCoreBundle:AccessUrl'
+                )->find(1);
+                $settingsManager->installSchemas($url);
+
+                return $this->handleAjaxAction(
+                    'assets:install',
+                    array(
+                        'target' => './',
+                        '--symlink' => true,
+                        '--relative' => true,
+                    )
+                );
+            case 'assetic':
+                return $this->handleAjaxAction('assetic:dump');
+            case 'translation':
+                //return $this->handleAjaxAction('oro:translation:dump');
+            case 'requirejs':
+                //return $this->handleAjaxAction('oro:requirejs:build', array('--ignore-errors' => true));
+            case 'finish':
+                $this->get('event_dispatcher')->dispatch(
+                    InstallerEvents::FINISH
+                );
+                // everything was fine - update installed flag in parameters.yml
+                $dumper = $this->get('chamilo_installer.yaml_persister');
+                $params = $dumper->parse();
+                $params['system']['installed'] = date('c');
+                $dumper->dump($params);
+                // launch 'cache:clear' to set installed flag in DI container
+                // suppress warning: ini_set(): A session is active. You cannot change the session
+                // module's ini settings at this time
+                error_reporting(E_ALL ^ E_WARNING);
+
+                return $this->handleAjaxAction(
+                    'cache:clear',
+                    array('--env' => 'prod', '--no-debug' => true)
+                );
+
+        }
+
+        // check if we have package installation step
+        if (strpos($action, 'installerScript-') !== false) {
+            $scriptFile = $this->container->get(
+                'chamilo_installer.script_manager'
+            )->getScriptFileByKey(
+                str_replace('installerScript-', '', $action)
+            );
+
+            $scriptExecutor = new ScriptExecutor(
+                $this->getOutput(),
+                $this->container,
+                new CommandExecutor(
+                    $this->container->getParameter('kernel.environment'),
+                    $this->getOutput(),
+                    $this->getApplication()
+                )
+            );
+            $scriptExecutor->runScript($scriptFile);
+
+            return new JsonResponse(array('result' => true));
+        }
+
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:installation.html.twig',
+            array(
+                'loadFixtures' => $context->getStorage()->get('loadFixtures'),
+                'installerScripts' => $this
+                    ->container
+                    ->get('chamilo_installer.script_manager')
+                    ->getScriptLabels(),
+            )
+        );
+    }
+}

+ 63 - 0
src/Chamilo/InstallerBundle/Process/Step/SchemaStep.php

@@ -0,0 +1,63 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Process\Step;
+
+use Sylius\Bundle\FlowBundle\Process\Context\ProcessContextInterface;
+
+/**
+ * Class SchemaStep
+ * @package Chamilo\InstallerBundle\Process\Step
+ */
+class SchemaStep extends AbstractStep
+{
+    public function displayAction(ProcessContextInterface $context)
+    {
+        set_time_limit(600);
+
+        switch ($this->getRequest()->query->get('action')) {
+            case 'cache':
+                // suppress warning: ini_set(): A session is active. You cannot change the session
+                // module's ini settings at this time
+                error_reporting(E_ALL ^ E_WARNING);
+
+                return $this->handleAjaxAction(
+                    'cache:clear',
+                    array('--no-optional-warmers' => true)
+                );
+            /*case 'clear-config':
+                return $this->handleAjaxAction('oro:entity-config:cache:clear', array('--no-warmup' => true));*/
+            /*case 'clear-extend':
+                return $this->handleAjaxAction('oro:entity-extend:cache:clear', array('--no-warmup' => true));*/
+            case 'schema-drop':
+                return $this->handleAjaxAction(
+                    'doctrine:schema:drop',
+                    array(
+                        '--force' => true,
+                        '--full-database' => $context->getStorage()->get(
+                            'fullDatabase',
+                            false
+                        ),
+                    )
+                );
+            case 'schema-update':
+                return $this->handleAjaxAction(
+                    'oro:migration:load',
+                    array('--force' => true)
+                );
+            case 'fixtures':
+                return $this->handleAjaxAction(
+                    'oro:migration:data:load',
+                    array('--no-interaction' => true)
+                );
+            /*case 'workflows':
+                return $this->handleAjaxAction('oro:workflow:definitions:load');
+            case 'processes':
+                return $this->handleAjaxAction('oro:process:configuration:load');*/
+        }
+
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:schema.html.twig'
+        );
+    }
+}

+ 143 - 0
src/Chamilo/InstallerBundle/Process/Step/SetupStep.php

@@ -0,0 +1,143 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Process\Step;
+
+use Sylius\Bundle\FlowBundle\Process\Context\ProcessContextInterface;
+use Application\Migrations\Data\ORM\LoadAdminUserData;
+//use Oro\Bundle\ConfigBundle\Config\ConfigManager;
+use Sylius\Bundle\SettingsBundle\Manager\SettingsManager;
+use Symfony\Component\HttpFoundation\Response;
+use Chamilo\UserBundle\Entity\User;
+
+/**
+ * Class SetupStep
+ * @package Chamilo\InstallerBundle\Process\Step
+ */
+class SetupStep extends AbstractStep
+{
+    /**
+     * @param ProcessContextInterface $context
+     * @return Response
+     */
+    public function displayAction(ProcessContextInterface $context)
+    {
+        $form = $this->createSetupForm();
+
+        $settingsManager = $this->get('chamilo.settings.manager');
+        $settings = $settingsManager->loadSettings('platform');
+
+        $form->get('portal')->get('institution')->setData(
+            $settings->get('institution')
+        );
+        $form->get('portal')->get('institution_url')->setData(
+            $settings->get('institution_url')
+        );
+        $form->get('portal')->get('site_name')->setData(
+            $settings->get('site_name')
+        );
+        $date = new \DateTime();
+        $timezone = $date->getTimezone();
+        $form->get('portal')->get('timezone')->setData($timezone->getName());
+
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:setup.html.twig',
+            array(
+                'form' => $form->createView(),
+            )
+        );
+    }
+
+    /**
+     * @param ProcessContextInterface $context
+     * @return null|\Sylius\Bundle\FlowBundle\Process\Step\ActionResult|Response
+     */
+    public function forwardAction(ProcessContextInterface $context)
+    {
+        $adminUser = $this
+            ->getDoctrine()
+            ->getRepository('ChamiloUserBundle:User')
+            ->findOneBy(
+                array('username' => LoadAdminUserData::DEFAULT_ADMIN_USERNAME)
+            );
+
+        if (!$adminUser) {
+            throw new \RuntimeException(
+                "Admin user wasn't loaded in fixtures."
+            );
+        }
+
+        $form = $this->createSetupForm();
+        $form->get('admin')->setData($adminUser);
+
+        $form->handleRequest($this->getRequest());
+
+        if ($form->isValid()) {
+            // pass "load demo fixtures" flag to the next step
+            /*$context->getStorage()->set(
+                'loadFixtures',
+                $form->has('loadFixtures') && $form->get('loadFixtures')->getData()
+            );*/
+            $this->get('fos_user.user_manager')->updateUser($adminUser);
+
+            // Setting portal parameters
+            $settingsManager = $this->get('chamilo.settings.manager');
+            $url = $this->get('chamilo_core.manager.access_url')->find(1);
+            $settingsManager->setUrl($url);
+            $settings = $settingsManager->loadSettings('platform');
+
+            $parameters = array(
+                'institution' => $form->get('portal')->get(
+                    'institution'
+                )->getData(),
+                'institution_url' => $form->get('portal')->get(
+                    'institution_url'
+                )->getData(),
+                'site_name' => $form->get('portal')->get('site_name')->getData(
+                ),
+                'administrator_email' => $adminUser->getEmail(),
+                'administrator_name' => $adminUser->getFirstName(),
+                'administrator_surname' => $adminUser->getLastName(),
+                'administrator_phone' => $adminUser->getPhone(),
+                'timezone' => $form->get('portal')->get('timezone')->getData(),
+            );
+            $settings->setParameters($parameters);
+            $settingsManager->saveSettings('platform', $settings);
+
+            /*$defaultCompanyName  = $configManager->get('oro_ui.application_name');
+            $defaultCompanyTitle = $configManager->get('oro_ui.application_title');
+            $companyName         = $form->get('company_name')->getData();
+            $companyTitle        = $form->get('company_title')->getData();
+            if (!empty($companyName) && $companyName !== $defaultCompanyName) {
+                $configManager->set('oro_ui.application_name', $companyName);
+            }
+            if (!empty($companyTitle) && $companyTitle !== $defaultCompanyTitle) {
+                $configManager->set('oro_ui.application_title', $companyTitle);
+            }
+            $configManager->flush();
+            */
+
+            return $this->complete();
+        }
+
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:setup.html.twig',
+            array(
+                'form' => $form->createView(),
+            )
+        );
+    }
+
+    /**
+     * @return \Symfony\Component\Form\Form
+     */
+    protected function createSetupForm()
+    {
+        $data = $this->get('chamilo_installer.yaml_persister')->parse();
+
+        return $this->createForm(
+            'chamilo_installer_setup',
+            empty($data) ? null : $data
+        );
+    }
+}

+ 32 - 0
src/Chamilo/InstallerBundle/Process/Step/WelcomeStep.php

@@ -0,0 +1,32 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle\Process\Step;
+
+use Sylius\Bundle\FlowBundle\Process\Context\ProcessContextInterface;
+use Sylius\Bundle\FlowBundle\Process\Step\AbstractControllerStep;
+
+/**
+ * Class WelcomeStep
+ * @package Chamilo\InstallerBundle\Process\Step
+ */
+class WelcomeStep extends AbstractControllerStep
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function displayAction(ProcessContextInterface $context)
+    {
+        return $this->render(
+            'ChamiloInstallerBundle:Process/Step:welcome.html.twig'
+        );
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function forwardAction(ProcessContextInterface $context)
+    {
+        return $this->complete();
+    }
+}

+ 99 - 0
src/Chamilo/InstallerBundle/README.md

@@ -0,0 +1,99 @@
+InstallerBundle
+==================
+
+Web installer. Inspired by [Sylius](https://github.com/Sylius/SyliusInstallerBundle).
+
+To run the installer on existing setup, you need to update parameters.yml file:
+``` yaml
+# ...
+session_handler: ~
+installed: ~
+```
+
+## Usage ##
+If you are using distribution package, you will be redirected to installer page automatically.
+
+Otherwise, following installation instructions offered:
+``` bash
+$ git clone https://github.com/chamilo/chamilo-lms.git
+$ cd chamilo-lms
+$ wget http://getcomposer.org/composer.phar
+$ php composer.phar install
+$ php app/console chamilo:install
+```
+
+## Events ##
+To add additional actions to the installation process you may use event listeners.
+Currently only "onFinish" installer event dispatched.
+
+Example:
+
+``` yaml
+services:
+    installer.listener.finish.event:
+        class:  Acme\Bundle\MyBundle\EventListener\MyListener
+        tags:
+            - { name: kernel.event_listener, event: installer.finish, method: onFinish }
+```
+
+``` php
+<?php
+
+namespace Acme\Bundle\MyBundle\EventListener;
+
+class MyListener
+{
+    public function onFinish()
+    {
+        // do something
+    }
+}
+
+```
+
+## Sample data ##
+To provide demo fixtures for your bundle just place them in "YourBundle\Data\Demo" directory.
+
+## Additional install files in bundles and packages ##
+
+To add additional install scripts during install process you can use install.php files in your bundles and packages.
+This install files will be run before last clear cache during installation.
+
+This file must be started with `@ChamiloScript` annotation with script label which will be shown during web install process.
+
+Example:
+``` php
+<?php
+/**
+ * @ChamiloScript("Your script label")
+ */
+
+ // here you can add additional install logic
+
+```
+
+The following variables are available in installer script:
+
+ - `$container` - Symfony2 DI container
+ - `$commandExecutor` - An instance of [CommandExecutor](./CommandExecutor.php) class. You can use it to execute Symfony console commands
+
+All outputs from installer script will be logged in chamilo_install.log file or will be shown in console in you use console installer.
+
+## Launching plain PHP script in Chamilo context ##
+In some cases you may need to launch PHP scripts in context of Platform. It means that you need an access to Symfony DI container. Examples of such cases may be some installation or maintenance sctipts. To achieve this you can use `chamilo:platform:run-script` command.
+Each script file must be started with `@ChamiloScript` annotation. For example:
+``` php
+<?php
+/**
+ * @ChamiloScript("Your script label")
+ */
+
+ // here you can write some PHP code
+
+```
+
+The following variables are available in a script:
+
+ - `$container` - Symfony2 DI container
+ - `$commandExecutor` - An instance of [CommandExecutor](./CommandExecutor.php) class. You can use it to execute Symfony console commands
+

+ 340 - 0
src/Chamilo/InstallerBundle/Requirement/ExtensionsRequirements.php

@@ -0,0 +1,340 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\Requirement;
+
+use ReflectionExtension;
+use Symfony\Component\Translation\TranslatorInterface;
+
+class ExtensionsRequirements extends RequirementCollection
+{
+    public function __construct(TranslatorInterface $translator)
+    {
+        parent::__construct(
+            $translator->trans('sylius.extensions', array(), 'requirements')
+        );
+
+        $on = $translator->trans(
+            'sylius.extensions.on',
+            array(),
+            'requirements'
+        );
+        $off = $translator->trans(
+            'sylius.extensions.off',
+            array(),
+            'requirements'
+        );
+
+        $pcreVersion = defined('PCRE_VERSION') ? (float)PCRE_VERSION : null;
+
+        $this
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.json_encode',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = function_exists('json_encode'),
+                    $on,
+                    $status ? $on : $off,
+                    true,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'JSON'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.session_start',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = function_exists('session_start'),
+                    $on,
+                    $status ? $on : $off,
+                    true,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'session'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.ctype',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = function_exists('ctype_alpha'),
+                    $on,
+                    $status ? $on : $off,
+                    true,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'ctype'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.token_get_all',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = function_exists('token_get_all'),
+                    $on,
+                    $status ? $on : $off,
+                    true,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'JSON'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.simplexml_import_dom',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = function_exists('simplexml_import_dom'),
+                    $on,
+                    $status ? $on : $off,
+                    true,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'SimpleXML'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.apc',
+                        array(),
+                        'requirements'
+                    ),
+                    !(function_exists('apc_store') && ini_get(
+                            'apc.enabled'
+                        )) || version_compare(
+                        phpversion('apc'),
+                        '3.0.17',
+                        '>='
+                    ),
+                    '>=3.0.17',
+                    phpversion('apc'),
+                    true,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'APC (>=3.0.17)'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.pcre',
+                        array(),
+                        'requirements'
+                    ),
+                    null !== $pcreVersion && $pcreVersion > 8.0,
+                    '>=8.0',
+                    $pcreVersion,
+                    true,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'PCRE (>=8.0)'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.php_xml',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = class_exists('DomDocument'),
+                    $on,
+                    $status ? $on : $off,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'PHP-XML'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.mbstring',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = function_exists('mb_strlen'),
+                    $on,
+                    $status ? $on : $off,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'mbstring'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.iconv',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = function_exists('iconv'),
+                    $on,
+                    $status ? $on : $off,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'iconv'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.intl',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = class_exists('Locale'),
+                    $on,
+                    $status ? $on : $off,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'intl'),
+                        'requirements'
+                    )
+                )
+            );
+
+        if (class_exists('Locale')) {
+            if (defined('INTL_ICU_VERSION')) {
+                $version = INTL_ICU_VERSION;
+            } else {
+                $reflector = new ReflectionExtension('intl');
+
+                ob_start();
+                $reflector->info();
+                $output = strip_tags(ob_get_clean());
+
+                preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches);
+                $version = $matches[1];
+            }
+
+            $this->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.icu',
+                        array(),
+                        'requirements'
+                    ),
+                    version_compare($version, '4.0', '>='),
+                    '4.0',
+                    $version,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'ICU (>=4.0)'),
+                        'requirements'
+                    )
+                )
+            );
+        }
+
+        $status = (function_exists('apc_store') && ini_get('apc.enabled'))
+            || function_exists('eaccelerator_put') && ini_get(
+                'eaccelerator.enable'
+            )
+            || function_exists('xcache_set');
+
+        $this
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.accelerator',
+                        array(),
+                        'requirements'
+                    ),
+                    $status,
+                    $on,
+                    $status ? $on : $off,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.accelerator.help',
+                        array(),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.pdo',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = class_exists('PDO'),
+                    $on,
+                    $status ? $on : $off,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'PDO'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.extensions.gd',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = defined('GD_VERSION'),
+                    $on,
+                    $status ? $on : $off,
+                    false,
+                    $translator->trans(
+                        'sylius.extensions.help',
+                        array('%extension%' => 'gd'),
+                        'requirements'
+                    )
+                )
+            );
+    }
+}

+ 125 - 0
src/Chamilo/InstallerBundle/Requirement/FilesystemRequirements.php

@@ -0,0 +1,125 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\Requirement;
+
+use Symfony\Component\Translation\TranslatorInterface;
+
+class FilesystemRequirements extends RequirementCollection
+{
+    public function __construct(TranslatorInterface $translator, $root)
+    {
+        parent::__construct(
+            $translator->trans('sylius.filesystem', array(), 'requirements')
+        );
+
+        $exists = $translator->trans(
+            'sylius.filesystem.exists',
+            array(),
+            'requirements'
+        );
+        $notExists = $translator->trans(
+            'sylius.filesystem.not_exists',
+            array(),
+            'requirements'
+        );
+        $writable = $translator->trans(
+            'sylius.filesystem.writable',
+            array(),
+            'requirements'
+        );
+        $notWritable = $translator->trans(
+            'sylius.filesystem.not_writable',
+            array(),
+            'requirements'
+        );
+
+        $this
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.filesystem.vendors',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = is_dir($root.'/../vendor'),
+                    $exists,
+                    $status ? $exists : $notExists
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.filesystem.cache',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = is_writable($root.'/cache'),
+                    $translator->trans(
+                        'sylius.filesystem.writable',
+                        array(),
+                        'requirements'
+                    ),
+                    $status ? $translator->trans(
+                        'sylius.filesystem.writable',
+                        array(),
+                        'requirements'
+                    ) : $translator->trans(
+                        'sylius.filesystem.not_writable',
+                        array(),
+                        'requirements'
+                    ),
+                    true,
+                    $translator->trans(
+                        'sylius.filesystem.cache.help',
+                        array('%path%' => $root.'/cache'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.filesystem.logs',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = is_writable($root.'/logs'),
+                    $writable,
+                    $status ? $writable : $notWritable,
+                    true,
+                    $translator->trans(
+                        'sylius.filesystem.logs.help',
+                        array('%path%' => $root.'/logs'),
+                        'requirements'
+                    )
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.filesystem.parameters',
+                        array(),
+                        'requirements'
+                    ),
+                    $status = is_writable($root.'/config/parameters.yml'),
+                    $writable,
+                    $status ? $writable : $notWritable,
+                    true,
+                    $translator->trans(
+                        'sylius.filesystem.parameters.help',
+                        array('%path%' => $root.'/config/parameters.yml'),
+                        'requirements'
+                    )
+                )
+            );
+    }
+}

+ 68 - 0
src/Chamilo/InstallerBundle/Requirement/Requirement.php

@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\Requirement;
+
+class Requirement
+{
+    protected $label;
+    protected $fulfilled;
+    protected $expected;
+    protected $actual;
+    protected $help;
+    protected $required;
+
+    public function __construct(
+        $label,
+        $fulfilled,
+        $expected,
+        $actual,
+        $required = true,
+        $help = null
+    ) {
+        $this->label = $label;
+        $this->fulfilled = (Boolean)$fulfilled;
+        $this->expected = $expected;
+        $this->actual = $actual;
+        $this->required = (Boolean)$required;
+        $this->help = $help;
+    }
+
+    public function getLabel()
+    {
+        return $this->label;
+    }
+
+    public function isFulfilled()
+    {
+        return $this->fulfilled;
+    }
+
+    public function getExpected()
+    {
+        return $this->expected;
+    }
+
+    public function getActual()
+    {
+        return $this->actual;
+    }
+
+    public function isRequired()
+    {
+        return $this->required;
+    }
+
+    public function getHelp()
+    {
+        return $this->help;
+    }
+}

+ 43 - 0
src/Chamilo/InstallerBundle/Requirement/RequirementCollection.php

@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\Requirement;
+
+use ArrayIterator;
+use IteratorAggregate;
+
+class RequirementCollection implements IteratorAggregate
+{
+    protected $label;
+    protected $requirements = array();
+
+    public function __construct($label)
+    {
+        $this->label = $label;
+    }
+
+    public function getLabel()
+    {
+        return $this->label;
+    }
+
+    public function getIterator()
+    {
+        return new ArrayIterator($this->requirements);
+    }
+
+    public function add(Requirement $requirement)
+    {
+        $this->requirements[] = $requirement;
+
+        return $this;
+    }
+}

+ 186 - 0
src/Chamilo/InstallerBundle/Requirement/SettingsRequirements.php

@@ -0,0 +1,186 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\Requirement;
+
+use DateTimeZone;
+use Symfony\Component\Translation\TranslatorInterface;
+
+class SettingsRequirements extends RequirementCollection
+{
+    const REQUIRED_PHP_VERSION = '5.3.3';
+
+    public function __construct(TranslatorInterface $translator)
+    {
+        parent::__construct(
+            $translator->trans('sylius.settings', array(), 'requirements')
+        );
+
+        $on = $translator->trans('sylius.settings.on', array(), 'requirements');
+        $off = $translator->trans(
+            'sylius.settings.off',
+            array(),
+            'requirements'
+        );
+
+        $this
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.version',
+                        array(),
+                        'requirements'
+                    ),
+                    version_compare(
+                        phpversion(),
+                        self::REQUIRED_PHP_VERSION,
+                        '>='
+                    ),
+                    '>='.self::REQUIRED_PHP_VERSION,
+                    phpversion()
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.version_recommanded',
+                        array(),
+                        'requirements'
+                    ),
+                    version_compare(phpversion(), '5.3.8', '>='),
+                    '>=5.3.8',
+                    phpversion(),
+                    false
+                )
+            )/*->add(new Requirement(
+                $translator->trans('sylius.settings.timezone', array(), 'requirements'),
+                $this->isOn('date.timezone'),
+                $translator->trans('sylius.settings.any', array(), 'requirements'),
+                ini_get('date.timezone')
+            ))*/
+        ;
+
+        if (version_compare(phpversion(), self::REQUIRED_PHP_VERSION, '>=')) {
+            $this->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.timezone_deprecated',
+                        array(),
+                        'requirements'
+                    ),
+                    in_array(
+                        date_default_timezone_get(),
+                        DateTimeZone::listIdentifiers()
+                    ),
+                    $translator->trans(
+                        'sylius.settings.non_deprecated',
+                        array(),
+                        'requirements'
+                    ),
+                    date_default_timezone_get(),
+                    true,
+                    $translator->trans(
+                        'sylius.settings.timezone_deprecated.help',
+                        array('%timezone%' => date_default_timezone_get()),
+                        'requirements'
+                    )
+                )
+            );
+        }
+
+        $this
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.detect_unicode',
+                        array(),
+                        'requirements'
+                    ),
+                    !$this->isOn('detect_unicode'),
+                    $on,
+                    ini_get('detect_unicode'),
+                    false
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.detect_unicode',
+                        array(),
+                        'requirements'
+                    ),
+                    !$this->isOn('detect_unicode'),
+                    $on,
+                    ini_get('detect_unicode'),
+                    false
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.short_open_tag',
+                        array(),
+                        'requirements'
+                    ),
+                    !$this->isOn('short_open_tag'),
+                    $off,
+                    ini_get('short_open_tag'),
+                    false
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.magic_quotes_gpc',
+                        array(),
+                        'requirements'
+                    ),
+                    !$this->isOn('magic_quotes_gpc'),
+                    $off,
+                    ini_get('magic_quotes_gpc'),
+                    false
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.register_globals',
+                        array(),
+                        'requirements'
+                    ),
+                    !$this->isOn('register_globals'),
+                    $off,
+                    ini_get('register_globals'),
+                    false
+                )
+            )
+            ->add(
+                new Requirement(
+                    $translator->trans(
+                        'sylius.settings.session.auto_start',
+                        array(),
+                        'requirements'
+                    ),
+                    !$this->isOn('session.auto_start'),
+                    $off,
+                    ini_get('session.auto_start'),
+                    false
+                )
+            );
+    }
+
+    private function isOn($key)
+    {
+        $value = ini_get($key);
+
+        return false != $value && 'off' !== $value;
+    }
+}

+ 39 - 0
src/Chamilo/InstallerBundle/Requirement/SyliusRequirements.php

@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of the Sylius package.
+ *
+ * (c) Paweł Jędrzejewski
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Chamilo\InstallerBundle\Requirement;
+
+use ArrayIterator;
+use IteratorAggregate;
+
+class SyliusRequirements implements IteratorAggregate
+{
+    protected $collections = array();
+
+    public function __construct(array $requirementCollections)
+    {
+        foreach ($requirementCollections as $requirementCollection) {
+            $this->add($requirementCollection);
+        }
+    }
+
+    public function getIterator()
+    {
+        return new ArrayIterator($this->collections);
+    }
+
+    public function add(RequirementCollection $collection)
+    {
+        $this->collections[] = $collection;
+
+        return $this;
+    }
+}

+ 54 - 0
src/Chamilo/InstallerBundle/Resources/config/form.yml

@@ -0,0 +1,54 @@
+parameters:
+    chamilo_installer.form.type.configuration.class:          Chamilo\InstallerBundle\Form\Type\ConfigurationType
+    chamilo_installer.form.type.configuration.database.class: Chamilo\InstallerBundle\Form\Type\Configuration\DatabaseType
+    chamilo_installer.form.type.configuration.mailer.class:   Chamilo\InstallerBundle\Form\Type\Configuration\MailerType
+    chamilo_installer.form.type.configuration.system.class:   Chamilo\InstallerBundle\Form\Type\Configuration\SystemType
+#    chamilo_installer.form.type.configuration.ws.class:       Chamilo\InstallerBundle\Form\Type\Configuration\WebsocketType
+    chamilo_installer.form.type.setup.admin.class:            Chamilo\InstallerBundle\Form\Type\Setup\AdminType
+    chamilo_installer.form.type.setup.portal.class:           Chamilo\InstallerBundle\Form\Type\Setup\PortalType
+    chamilo_installer.form.type.setup.class:                  Chamilo\InstallerBundle\Form\Type\SetupType
+
+
+services:
+    chamilo_installer.form.type.configuration:
+        class:                                            %chamilo_installer.form.type.configuration.class%
+        tags:
+            - { name: form.type, alias: chamilo_installer_configuration }
+
+    chamilo_installer.form.type.configuration.database:
+        class:                                            %chamilo_installer.form.type.configuration.database.class%
+        tags:
+            - { name: form.type, alias: chamilo_installer_configuration_database }
+
+    chamilo_installer.form.type.configuration.mailer:
+        class:                                            %chamilo_installer.form.type.configuration.mailer.class%
+        tags:
+            - { name: form.type, alias: chamilo_installer_configuration_mailer }
+
+    chamilo_installer.form.type.configuration.system:
+        class:                                            %chamilo_installer.form.type.configuration.system.class%
+        tags:
+            - { name: form.type, alias: chamilo_installer_configuration_system }
+
+    chamilo_installer.form.type.setup:
+        class:                                            %chamilo_installer.form.type.setup.class%
+        tags:
+            - { name: form.type, alias: chamilo_installer_setup }
+
+    chamilo_installer.form.type.setup.admin:
+        class:                                            %chamilo_installer.form.type.setup.admin.class%
+        arguments:
+            - Chamilo\UserBundle\Entity\User
+        tags:
+            - { name: form.type, alias: chamilo_installer_setup_admin }
+
+    chamilo_installer.form.type.setup.portal:
+        class:                                            %chamilo_installer.form.type.setup.portal.class%
+        tags:
+            - { name: form.type, alias: chamilo_installer_setup_portal }
+
+#    chamilo_installer.form.type.configuration.websocket:
+#        class:                                            %chamilo_installer.form.type.configuration.ws.class%
+#        tags:
+#            - { name: form.type, alias: chamilo_installer_configuration_websocket }
+

+ 7 - 0
src/Chamilo/InstallerBundle/Resources/config/routing.yml

@@ -0,0 +1,7 @@
+chamilo_installer_flow:
+    pattern: /installer
+    defaults: { _controller: sylius.controller.process:startAction, scenarioAlias: 'chamilo_installer' }
+
+chamilo_flow_bundle:
+    resource: @SyliusFlowBundle/Resources/config/routing.yml
+    prefix: /installer

+ 31 - 0
src/Chamilo/InstallerBundle/Resources/config/services.yml

@@ -0,0 +1,31 @@
+parameters:
+    chamilo_installer.scenario.class:                     Chamilo\InstallerBundle\Process\InstallerScenario
+    chamilo_installer.yaml_persister.class:               Chamilo\InstallerBundle\Persister\YamlPersister
+    chamilo_installer.listener.request.class:             Chamilo\InstallerBundle\EventListener\RequestListener
+    chamilo_installer.script_manager.class:               Chamilo\InstallerBundle\ScriptManager
+
+services:
+    chamilo_installer.scenario:
+        class: %chamilo_installer.scenario.class%
+        calls:
+          - [ setContainer, ["@service_container"] ]
+        tags:
+          - { name: sylius.process.scenario, alias: chamilo_installer }
+
+    chamilo_installer.yaml_persister:
+        class: %chamilo_installer.yaml_persister.class%
+        arguments:
+            - %kernel.root_dir%/config
+            - %kernel.environment%
+
+    kernel.listener.install.event:
+        class: %chamilo_installer.listener.request.class%
+        arguments:
+            - "@router"
+            - %installed%
+            - %kernel.debug%
+
+    chamilo_installer.script_manager:
+        class: %chamilo_installer.script_manager.class%
+        arguments:
+            - @kernel

+ 197 - 0
src/Chamilo/InstallerBundle/Resources/public/css/install.css

@@ -0,0 +1,197 @@
+/* Sticky footer styles
+-------------------------------------------------- */
+html {
+    position: relative;
+    min-height: 100%;
+}
+
+body {
+    /* Margin bottom by footer height */
+    margin-bottom: 60px;
+}
+
+.footer {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    /* Set the fixed height of the footer here */
+    height: 60px;
+    background-color: #f5f5f5;
+}
+
+.container .text-muted {
+    margin: 20px 0;
+}
+
+.wizard-container {
+    padding-bottom: 20px;
+}
+
+.install-form-actions {
+    padding: 20px 0px 20px 0px;
+}
+
+/* Wizard nav*/
+
+/*  https://github.com/LeadDyno/bootstrap-nav-wizard/blob/master/dist/bootstrap-nav-wizard.css
+    http://leaddyno.github.io/bootstrap-nav-wizard/
+ */
+ul.nav-wizard {
+    background-color: #f9f9f9;
+    border: 1px solid #d4d4d4;
+    -webkit-border-radius: 6px;
+    -moz-border-radius: 6px;
+    border-radius: 6px;
+    *zoom: 1;
+    position: relative;
+    overflow: hidden;
+}
+
+ul.nav-wizard:before {
+    display: block;
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    top: 46px;
+    height: 47px;
+    border-top: 1px solid #d4d4d4;
+    border-bottom: 1px solid #d4d4d4;
+    z-index: 11;
+    content: " ";
+}
+
+ul.nav-wizard:after {
+    display: block;
+    position: absolute;
+    left: 0px;
+    right: 0px;
+    top: 138px;
+    height: 47px;
+    border-top: 1px solid #d4d4d4;
+    border-bottom: 1px solid #d4d4d4;
+    z-index: 11;
+    content: " ";
+}
+
+ul.nav-wizard li {
+    position: relative;
+    float: left;
+    height: 46px;
+    display: inline-block;
+    text-align: middle;
+    padding: 0 20px 0 30px;
+    margin: 0;
+    font-size: 16px;
+    line-height: 46px;
+}
+
+ul.nav-wizard li a {
+    color: #468847;
+    padding: 0;
+}
+
+ul.nav-wizard li a:hover {
+    background-color: transparent;
+}
+
+ul.nav-wizard li:before {
+    position: absolute;
+    display: block;
+    border: 24px solid transparent;
+    border-left: 16px solid #d4d4d4;
+    border-right: 0;
+    top: -1px;
+    z-index: 10;
+    content: '';
+    right: -16px;
+}
+
+ul.nav-wizard li:after {
+    position: absolute;
+    display: block;
+    border: 24px solid transparent;
+    border-left: 16px solid #f9f9f9;
+    border-right: 0;
+    top: -1px;
+    z-index: 10;
+    content: '';
+    right: -15px;
+}
+
+ul.nav-wizard li.active {
+    color: #3a87ad;
+    background: #d9edf7;
+}
+
+ul.nav-wizard li.active:after {
+    border-left: 16px solid #d9edf7;
+}
+
+ul.nav-wizard li.active a,
+ul.nav-wizard li.active a:active,
+ul.nav-wizard li.active a:visited,
+ul.nav-wizard li.active a:focus {
+    color: #3a87ad;
+    background: #d9edf7;
+}
+
+ul.nav-wizard .active ~ li {
+    color: #999999;
+    background: #ededed;
+}
+
+ul.nav-wizard .active ~ li:after {
+    border-left: 16px solid #ededed;
+}
+
+ul.nav-wizard .active ~ li a,
+ul.nav-wizard .active ~ li a:active,
+ul.nav-wizard .active ~ li a:visited,
+ul.nav-wizard .active ~ li a:focus {
+    color: #999999;
+    background: #ededed;
+}
+
+ul.nav-wizard.nav-wizard-backnav li:hover {
+    color: #468847;
+    background: #f6fbfd;
+}
+
+ul.nav-wizard.nav-wizard-backnav li:hover:after {
+    border-left: 16px solid #f6fbfd;
+}
+
+ul.nav-wizard.nav-wizard-backnav li:hover a,
+ul.nav-wizard.nav-wizard-backnav li:hover a:active,
+ul.nav-wizard.nav-wizard-backnav li:hover a:visited,
+ul.nav-wizard.nav-wizard-backnav li:hover a:focus {
+    color: #468847;
+    background: #f6fbfd;
+}
+
+ul.nav-wizard.nav-wizard-backnav .active ~ li {
+    color: #999999;
+    background: #ededed;
+}
+
+ul.nav-wizard.nav-wizard-backnav .active ~ li:after {
+    border-left: 16px solid #ededed;
+}
+
+ul.nav-wizard.nav-wizard-backnav .active ~ li a,
+ul.nav-wizard.nav-wizard-backnav .active ~ li a:active,
+ul.nav-wizard.nav-wizard-backnav .active ~ li a:visited,
+ul.nav-wizard.nav-wizard-backnav .active ~ li a:focus {
+    color: #999999;
+    background: #ededed;
+}
+
+td pre.output {
+    background-color: #232125;
+    overflow: auto;
+    line-height: 1.3em;
+    color: #fff;
+    font-size: 14px;
+    padding: .7em;
+    margin-top: 10px;
+}

+ 60 - 0
src/Chamilo/InstallerBundle/Resources/translations/messages.de.yml

@@ -0,0 +1,60 @@
+# This file is part of the Sylius package.
+# (c) Paweł Jędrzejewski
+
+flashes:
+  installed: Chamilo wurde erfolgreich installiert.
+form:
+  configuration:
+    database:
+      0: Datenbankverbindung
+      driver:
+        0: Datenbanktreiber
+        microsoft_sql_server: Microsoft SQL Server
+        mysql: MySQL
+        oracle: Oracle
+        postgresql: PostgreSQL
+        sqlite: SQLite
+      host: Datenbankserver
+      name: Datenbankname
+      password: Datenbank Passwort
+      port: Datenbank Port
+      user: Datenbankbenutzer
+    locale:
+      0: Lokale Einstellungen
+      currency: Währung
+      locale: Gebietsschema
+    mailer:
+      0: E-Mail Einstellungen
+      host: E-Mail Host
+      password: E-Mail Passwort
+      transport:
+        0: Transport
+        gmail: Google Mail
+        mail: E-Mail
+        sendmail: Sendmail
+        smtp: SMTP
+      user: E-Mail Benutzer
+  setup:
+    email: E-Mail
+    load_fixtures: Testdaten laden
+    plain_password: Passwort
+    username: Benutzername
+process:
+  step:
+    check:
+      button:
+        back: Zurück
+        install: Installieren
+        next: Weiter
+      header: 'Überprüfen der Systemvoraussetzungen <small>Chamilo installer</small>'
+      table:
+        current: Aktuell
+        required: Benötigt
+        status: Status
+    configure:
+      header: 'Einstellungen <small>Chamilo installer</small>'
+    setup:
+      header: 'Administration Einstellungen <small>Chamilo installer</small>'
+    welcome:
+      content: '<p>Willkommen beim Chamilo installer.</p>'
+      header: 'Willkommen <small>Chamilo installer</small>'

+ 128 - 0
src/Chamilo/InstallerBundle/Resources/translations/messages.en.yml

@@ -0,0 +1,128 @@
+title: Chamilo installation
+
+flashes:
+    installed: Chamilo has been successfully installed.
+form:
+    configuration:
+        database:
+            header: Database connection
+            driver:
+                0: Driver
+                microsoft_sql_server: Microsoft SQL Server
+                mysql: MySQL
+                oracle: Oracle
+                postgresql: PostgreSQL
+                sqlite: SQLite
+            host: Host
+            name: Name
+            password: Password
+            port: Port
+            user: User
+            drop_full:    Drop Full Database
+        locale:
+            header: Locale settings
+            currency: Currency
+            locale: Locale
+        mailer:
+            header: Mailer settings
+            host: Host
+            password: Password
+            transport:
+                header: Transport
+                gmail: Gmail
+                mail: Mail
+                sendmail: Sendmail
+                smtp: SMTP
+            user: User
+            port: Port
+            encryption: Encryption
+        system:
+            header:       System settings
+            secret:       Secret
+            locale:       Locale
+    setup:
+        admin:
+            header: Admin information
+            username:         Username
+            firstname:        First name
+            lastname:         Last name
+            password:         Password
+            password_re:      Re-enter password
+            email:            Email
+            phone:            Phone
+        portal:
+            header: Portal information
+            institution: Institution
+            institution_url: Institution URL
+            site_name: Site name
+            portal_name: Portal name
+            company_title: Company name
+            company_url: Company URL
+            allow_self_registration_as_trainer: Allow self-registration as a trainer
+            allow_self_registration: Allow self-registration
+            timezone: Timezone
+
+        load_fixtures:    Load Sample Data
+
+process:
+    step:
+        welcome:
+            header: Welcome!
+            content: <p>Welcome to the installer.</p>
+        check:
+            header: System requirements
+            invalid: Some of the requirements are not met and the installation process cannot continue. Please check below for the minimum requirements to Install.
+            phpchanges: Changes to the <strong>php.ini</strong> file must be done in "<strong>%path%</strong>".
+            phpcreate: To change settings, create a "<strong>php.ini</strong>".
+
+            table:
+                mandatory:  Mandatory requirements
+                php:        PHP settings
+                chamilo:    Chamilo Specific requirements
+                optional:   Optional recommendations
+                check:      Check
+                cli:        PHP CLI
+                status: Status
+            requirement_status:
+                ok: Ok
+                warning: Warning
+                danger: Danger
+        configure:
+            header: Configuration
+        schema:
+            header:        Database initialization
+            cache:         Clear cache before database initialization
+            clear-config:  Clear entities cache
+            clear-extend:  Clear extended entities data
+            schema-drop:   Drop current schema
+            schema-update: Schema update
+            fixtures:      Load fixtures
+            workflows:     Load workflow definitions
+            processes:     Load processes configuration
+        setup:
+            header: Administration setup
+        installation:
+            header:        Installation
+            fixtures:      Load sample data
+            navigation:    Init navigation
+            js-routing:    Dump JS routing
+            localization:  Dump localization
+            assets:        Install assets
+            assetic:       Dump assetic
+            translation:   Prepare translations
+            requirejs:     Optimize JS resources (optional)
+            finish:        Clear cache to finalize installation
+        final:
+            header:        Finish
+            greeting:      Success!!!
+            content:       You are now ready to start using Chamilo.<br>For help please join our community <a href="http://www.chamilo.org/forums">forums</a>.
+
+    button:
+        back:              Back
+        next:              Next
+        install:           Install
+        finish:            Launch application
+        continue:          Continue
+        refresh:           Refresh
+    operation:             Operation
+    status:                Status

+ 57 - 0
src/Chamilo/InstallerBundle/Resources/translations/messages.es.yml

@@ -0,0 +1,57 @@
+flashes:
+  installed: Chamilo se ha instalado correctamente.
+form:
+  configuration:
+    database:
+      0: Conexión con la base de datos.
+      driver:
+        0: Driver
+        microsoft_sql_server: Microsoft SQL Server
+        mysql: MySQL
+        oracle: Oracle
+        postgresql: PostgreSQL
+        sqlite: SQLite
+      host: Servidor
+      name: Nombre
+      password: Contraseña
+      port: Puerto
+      user: Usuario
+    locale:
+      0: Configuración del idioma
+      currency: Moneda
+      locale: Idioma
+    mailer:
+      0: Configuración de Mailer
+      host: Servidor
+      password: Contraseña
+      transport:
+        0: Transporte
+        gmail: Gmail
+        mail: Correo
+        sendmail: Sendmail
+        smtp: SMTP
+      user: Usuario
+  setup:
+    email: Correo electrónico
+    load_fixtures: Cargar datos de prueba
+    plain_password: Contraseña
+    username: Nombre de usuario
+process:
+  step:
+    check:
+      button:
+        back: Atrás
+        install: Instalar
+        next: Siguiente
+      header: 'Comprobar requisitos del sistema <small>instalador de Chamilo</small>'
+      table:
+        current: Actual
+        required: Requerido
+        status: Estado
+    configure:
+      header: 'Configuración <small>instalador de Chamilo</small>'
+    setup:
+      header: 'Configuración de administración <small>instalador de Chamilo</small>'
+    welcome:
+      content: '<p>Bienvenido al instalador de Chamilo.</p>'
+      header: 'Bienvenido <small>instalador de Chamilo</small>'

+ 58 - 0
src/Chamilo/InstallerBundle/Resources/translations/messages.fr.yml

@@ -0,0 +1,58 @@
+flashes:
+  installed: Chamilo a été installé avec succès.
+form:
+  configuration:
+    database:
+      0: Connexion à la base de données
+      driver:
+        0: Pilote
+        microsoft_sql_server: Microsoft SQL Server
+        mysql: MySQL
+        oracle: Oracle
+        postgresql: PostgreSQL
+        sqlite: SQLite
+      host: Serveur
+      name: Nom
+      password: Mot de passe
+      port: Port
+      user: Utilisateur
+    locale:
+      0: Paramètres régionaux
+      currency: Devise
+      locale: Paramètre régional
+    mailer:
+      0: "Paramètres pour l'envoi d'e-mail"
+      host: Serveur
+      password: Mot de passe
+      transport:
+        0: Transport
+        gmail: Gmail
+        mail: Mail
+        sendmail: Sendmail
+        smtp: SMTP
+      user: Utilisateur
+  setup:
+    email: E-mail
+    load_fixtures: Charger les données de test
+    plain_password: Mot de passe
+    username: Identifiant
+process:
+  step:
+    check:
+      button:
+        back: Retour
+        install: Installer
+        next: Suivant
+      header: 'Vérification de la configuration système requise <small>Installateur Chamilo</small>'
+      table:
+        current: Courant
+        required: obligatoire
+        status: statut
+    configure:
+      header: 'Configuration <small>Installateur Chamilo</small>'
+    setup:
+      header: "Configuration de l'administration <small>Installateur Chamilo</small>"
+    welcome:
+      content: "<p>Bienvenue sur l'installateur Chamilo.</p>"
+      header: 'Bienvenue <small>Installateur Chamilo</small>'
+€: €

+ 63 - 0
src/Chamilo/InstallerBundle/Resources/translations/requirements.de.yml

@@ -0,0 +1,63 @@
+# This file is part of the Sylius package.
+# (c) Paweł Jędrzejewski
+
+sylius:
+  extensions:
+    0: Erweiterungen
+    accelerator:
+      0: Accelerator
+      help: Installiere und aktiviere einen PHP Accelerator wie zum Beispiel APC (Dringend empfohlen).
+    apc: APC
+    ctype: Ctype
+    gd: GD
+    help: 'Installiere und aktiviere die %extension% Erweiterung.'
+    iconv: Iconv
+    icu: ICU
+    intl: Intl
+    json_encode: JSON
+    mbstring: Multibyte String
+    "off": false
+    "on": true
+    pcre: PCRE
+    pdo: PDO
+    php_xml: PHP-XML
+    session_start: Session
+    simplexml_import_dom: SimpleXML
+    token_get_all: Tokenizer
+  filesystem:
+    0: Dateisystem
+    cache:
+      0: Cache
+      help:
+        To set permissions run: 'sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%'
+    exists: Existiert
+    logs:
+      0: Logs
+      help:
+        To set permissions run: 'sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%'
+    not_exists: Existiert nicht
+    not_writable: Schreibgeschützt
+    parameters:
+      0: parameters.yml
+      help:
+        To set permissions run: 'sudo chmod a+w %path%'
+    vendors: vendors
+    writable: Beschreibbar
+  settings:
+    0: PHP Version und Einstellungen
+    any: Jeder
+    detect_unicode: detect_unicode
+    magic_quotes_gpc: magic_quotes_gpc
+    non_deprecated: Nicht veraltet
+    "off": false
+    "on": true
+    register_globals: register_globals
+    session:
+      auto_start: session.auto_start
+    short_open_tag: short_open_tag
+    timezone: timezone
+    timezone_deprecated:
+      0: Veraltete Zeitzone
+      help: 'Zeituone %timezone% ist veraltet. Korriegiere die php.ini Datei (Liste der veralteten Zeitzonen: http://php.net/manual/en/timezones.others.php).'
+    version: PHP Version
+    version_recommanded: Empfohlene PHP Version

+ 57 - 0
src/Chamilo/InstallerBundle/Resources/translations/requirements.en.yml

@@ -0,0 +1,57 @@
+sylius:
+    extensions:
+        0: extensions
+        accelerator:
+            0: Accelerator
+            help: Install and enable a PHP accelerator like APC (highly recommended).
+        apc: APC
+        ctype: Ctype
+        gd: GD
+        help: Install and enable the %extension% extension.
+        iconv: Iconv
+        icu: ICU
+        intl: Intl
+        json_encode: JSON
+        mbstring: Multibyte String
+        off: off
+        on: on
+        pcre: PCRE
+        pdo: PDO
+        php_xml: PHP-XML
+        session_start: Session
+        simplexml_import_dom: SimpleXML
+        token_get_all: Tokenizer
+    filesystem:
+        0: file system
+        cache:
+            0: cache
+            help: To set permissions run: sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%
+        exists: exists
+        logs:
+            0: logs
+            help: To set permissions run: sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%
+        not_exists: not exists
+        not_writable: not writable
+        parameters:
+            0: parameters.yml
+            help: To set permissions run: sudo chmod a+w %path%
+        vendors: vendors
+        writable: writable
+    settings:
+        0: PHP version and settings
+        any: any
+        detect_unicode: detect_unicode
+        magic_quotes_gpc: magic_quotes_gpc
+        non_deprecated: non deprecated
+        off: off
+        on: on
+        register_globals: register_globals
+        session:
+            auto_start: session.auto_start
+        short_open_tag: short_open_tag
+        timezone: timezone
+        timezone_deprecated:
+            0: Deprecated timezone
+            help: Timezone %timezone% is deprecated. Fix your php.ini file (list of deprecated timezones http://php.net/manual/en/timezones.others.php).
+        version: PHP version
+        version_recommanded: Recommended PHP version

+ 63 - 0
src/Chamilo/InstallerBundle/Resources/translations/requirements.es.yml

@@ -0,0 +1,63 @@
+# This file is part of the Sylius package.
+# (c) Paweł Jędrzejewski
+
+sylius:
+  extensions:
+    0: Extensiones
+    accelerator:
+      0: Acelerador
+      help: Instala y activa un acelerador PHP como APC (altamente recomendado).
+    apc: APC
+    ctype: Ctype
+    gd: GD
+    help: 'Instala y activa la extensión %extension%.'
+    iconv: Iconv
+    icu: ICU
+    intl: Intl
+    json_encode: JSON
+    mbstring: Multibyte String
+    "off": false
+    "on": true
+    pcre: PCRE
+    pdo: PDO
+    php_xml: PHP-XML
+    session_start: Sesión
+    simplexml_import_dom: SimpleXML
+    token_get_all: Tokenizer
+  filesystem:
+    0: sistema de ficheros
+    cache:
+      0: cache
+      help:
+        To set permissions run: 'sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%'
+    exists: Existe
+    logs:
+      0: logs
+      help:
+        To set permissions run: 'sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%'
+    not_exists: No existe
+    not_writable: Sin permisos de escritura
+    parameters:
+      0: parameters.yml
+      help:
+        To set permissions run: 'sudo chmod a+w %path%'
+    vendors: Vendors
+    writable: Con permisos de escritura
+  settings:
+    0: Versión de PHP y configuración
+    any: Cualquiera
+    detect_unicode: detect_unicode
+    magic_quotes_gpc: magic_quotes_gpc
+    non_deprecated: No obsoleto
+    "off": false
+    "on": true
+    register_globals: register_globals
+    session:
+      auto_start: session.auto_start
+    short_open_tag: short_open_tag
+    timezone: Zona horaria
+    timezone_deprecated:
+      0: Zona horaria obsoleta
+      help: 'La zona horaria %timezone% está obsoleta. Arregla tu fichero php.ini (Lista de zonas horarias obsoletas http://php.net/manual/en/timezones.others.php).'
+    version: Versión de PHP
+    version_recommanded: Versión de PHP recomendada

+ 63 - 0
src/Chamilo/InstallerBundle/Resources/translations/requirements.fr.yml

@@ -0,0 +1,63 @@
+# This file is part of the Sylius package.
+# (c) Paweł Jędrzejewski
+
+sylius:
+  extensions:
+    0: extensions
+    accelerator:
+      0: Accélérateur
+      help: Installer et activer un accélérateur PHP comme APC (fortement recommandé).
+    apc: APC
+    ctype: CType
+    gd: GD
+    help: "Installer et activer l'extension %extension%."
+    iconv: Iconv
+    icu: ICU
+    intl: Intl
+    json_encode: JSON
+    mbstring: Chaîne de caractères multi-octets
+    "off": false
+    "on": true
+    pcre: PCRE
+    pdo: PDO
+    php_xml: PHP-XML
+    session_start: Session
+    simplexml_import_dom: SimpleXML
+    token_get_all: Analyseur de code PHP
+  filesystem:
+    0: système de fichiers
+    cache:
+      0: cache
+      help:
+        To set permissions run: 'sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%'
+    exists: Existe
+    logs:
+      0: Logs
+      help:
+        To set permissions run: 'sudo setfacl -R -m u:www-data:rwX -m u:`whoami`:rwX %path% & sudo setfacl -dR -m u:www-data:rwx -m u:`whoami`:rwx %path%'
+    not_exists: "N'existe pas"
+    not_writable: pas accessible en écriture
+    parameters:
+      0: parameters.yml
+      help:
+        To set permissions run: 'sudo chmod a+w %path%'
+    vendors: vendors
+    writable: accessible en écriture
+  settings:
+    0: Version de PHP et paramètres
+    any: "N'importe quel"
+    detect_unicode: detect_unicode
+    magic_quotes_gpc: magic_quotes_gpc
+    non_deprecated: Non obsolète
+    "off": false
+    "on": true
+    register_globals: register_globals
+    session:
+      auto_start: session.auto_start
+    short_open_tag: short_open_tag
+    timezone: fuseau horaire
+    timezone_deprecated:
+      0: Fuseau horaire obsolète
+      help: 'Le fuseau horaire %timezone% est déconseillé. Corrigez votre fichier php.ini (liste des fuseaux horaires obsolètes http://php.net/manual/fr/timezones.others.php).'
+    version: Version de PHP
+    version_recommanded: Version de PHP recommandée

+ 37 - 0
src/Chamilo/InstallerBundle/Resources/views/Form/fields.html.twig

@@ -0,0 +1,37 @@
+{% block _chamilo_installer_configuration_mailer_chamilo_installer_mailer_transport_row %}
+
+    <script type="text/javascript">
+        $(function () {
+            var con = $('#chamilo_installer_configuration_mailer');
+
+            checkTransport();
+
+            con.find('.form-group:first select').change(checkTransport);
+
+            function checkTransport() {
+                if (con.find('.form-group:first select').val() != 'smtp') {
+                    con.find('.form-group:not(:first)').hide()
+                            .find('input').attr('disabled', 'disabled');
+                } else {
+                    con.find('.form-group:not(:first)').show()
+                            .find('input').attr('disabled', null);
+                }
+            }
+        });
+    </script>
+    {{ block('form_row') }}
+{% endblock %}
+
+{% block form_errors %}
+    {% spaceless %}
+        {% if errors|length > 0 %}
+            <div class="alert alert-warning" role="alert">
+                <ul>
+                    {% for error in errors %}
+                        <li>{{ error.message }}</li>
+                    {% endfor %}
+                </ul>
+            </div>
+        {% endif %}
+    {% endspaceless %}
+{% endblock form_errors %}

+ 48 - 0
src/Chamilo/InstallerBundle/Resources/views/Process/Step/configure.html.twig

@@ -0,0 +1,48 @@
+{% extends 'ChamiloInstallerBundle::layout.html.twig' %}
+{% set step = 'configure' %}
+{% use 'ChamiloInstallerBundle::progress.html.twig' %}
+{% form_theme form with 'ChamiloInstallerBundle:Form:fields.html.twig' %}
+
+{% block title %}
+    {% autoescape false %}
+        {{ 'process.step.configure.header'|trans }} - {{ parent() }}
+    {% endautoescape %}
+{% endblock %}
+
+{% block content %}
+    <div>
+        <form action="{{ path('sylius_flow_forward', { scenarioAlias: 'chamilo_installer', stepName: 'configure'}) }}"
+              method="post">
+            {{ form_errors(form) }}
+            <div class="row">
+                <div class="col-sm-6">
+                    <h3 class="sub-title">{{ form.database.vars.label|trans }}</h3>
+                    {{ form_widget(form.database) }}
+                </div>
+                <div class="col-sm-6">
+                    <h3 class="sub-title">{{ form.mailer.vars.label|trans }}</h3>
+                    {{ form_widget(form.mailer) }}
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-sm-12">
+                    <h3 class="sub-title">{{ form.system.vars.label|trans }}</h3>
+                    {{ form_widget(form.system) }}
+                </div>
+                {{ form_rest(form) }}
+            </div>
+
+            <div class="install-form-actions">
+                <a href="{{ app.request.basePath }}/install.php"
+                   class="btn btn-lg btn-default back">
+                    {{ 'process.button.back'|trans }}
+                </a>
+                <button class="btn btn-lg btn-primary button next"
+                        type="submit">
+                    <i class="fa fa-chevron-right"></i>
+                    {{ 'process.button.next'|trans }}
+                </button>
+            </div>
+        </form>
+    </div>
+{% endblock %}

+ 30 - 0
src/Chamilo/InstallerBundle/Resources/views/Process/Step/final.html.twig

@@ -0,0 +1,30 @@
+{% extends 'ChamiloInstallerBundle::layout.html.twig' %}
+{% set step = 'final' %}
+{% use 'ChamiloInstallerBundle::progress.html.twig' %}
+
+{% block title %}
+    {% autoescape false %}
+        {{ 'process.step.final.header'|trans }} - {{ parent() }}
+    {% endautoescape %}
+{% endblock %}
+
+{% block content %}
+    <div class="page-title">
+        <h2>{{ 'process.step.final.header'|trans }}</h2>
+    </div>
+
+    <div class="well">
+        <p>{{ 'process.step.final.content'|trans|raw }}</p>
+    </div>
+
+    <div class="install-form-actions">
+        <a href="{{ path('home') }}" class="btn btn-success btn-lg"
+           target="_blank">
+            {{ 'process.button.finish'|trans }}
+        </a>
+    </div>
+{% endblock %}
+
+{% block javascript %}
+    {{ parent() }}
+{% endblock javascript %}

+ 94 - 0
src/Chamilo/InstallerBundle/Resources/views/Process/Step/installation.html.twig

@@ -0,0 +1,94 @@
+{% extends 'ChamiloInstallerBundle::layout.html.twig' %}
+{#{% set step, platformSteps = 'administration', ['navigation', 'js-routing', 'localization', 'assets', 'assetic', 'translation', 'requirejs'] %}#}
+{% set step, platformSteps = 'installation', ['assets', 'assetic', 'fixtures', 'pages'] %}
+{% use 'ChamiloInstallerBundle::progress.html.twig' %}
+
+{% if loadFixtures %}
+    {% set platformSteps = ['fixtures']|merge(platformSteps) %}
+{% endif %}
+
+{% set steps = platformSteps %}
+
+{% if installerScripts is not empty %}
+    {% for stepName in installerScripts|keys %}
+        {% set steps = steps|merge(['installerScript-' ~ stepName]) %}
+    {% endfor %}
+{% endif %}
+
+{% set steps = steps|merge(['finish']) %}
+
+{% block title %}
+    {% autoescape false %}
+        {{ 'process.step.installation.header'|trans }} - {{ parent() }}
+    {% endautoescape %}
+{% endblock %}
+
+{% block content %}
+    <div class="page-title">
+        <h2>{{ 'process.step.installation.header'|trans }}</h2>
+    </div>
+
+    <div>
+        <table class="table table-striped">
+            <col width="75%" valign="top">
+            <col width="25%" valign="top">
+            <thead>
+            <tr>
+                <th>{{ 'process.operation'|trans }}</th>
+                <th>{{ 'process.status'|trans }}</th>
+            </tr>
+            </thead>
+            <tbody>
+            {% for step in platformSteps %}
+                <tr>
+                    <td>
+                        <span id="step-{{ step }}"></span>{{ ('process.step.installation.' ~ step)|trans }}
+                    </td>
+                    <td>&nbsp;</td>
+                </tr>
+            {% endfor %}
+            {% if installerScripts is not empty %}
+                {% for stepKey, stepLabel in installerScripts %}
+                    <tr>
+                        <td>
+                            <span id="step-installerScript-{{ stepKey }}"></span>{{ stepLabel|trans }}
+                        </td>
+                        <td>&nbsp;</td>
+                    </tr>
+                {% endfor %}
+            {% endif %}
+            <tr>
+                <td>
+                    <span id="step-finish"></span>{{ 'process.step.installation.finish'|trans }}
+                </td>
+                <td>&nbsp;</td>
+            </tr>
+            </tbody>
+        </table>
+
+        <div class="install-form-actions">
+            <a href="{{ path('sylius_flow_display', { scenarioAlias: 'chamilo_installer', stepName: 'configure' }) }}"
+               class="btn btn-lg btn-default back disabled">
+                <span>{{ 'process.button.back'|trans }}</span>
+            </a>
+            <a href="javascript: void(0)"
+               class="btn btn-lg btn-primary next primary disabled">
+                <i class="fa fa-chevron-right"></i>
+                <span>{{ 'process.button.next'|trans }}</span>
+            </a>
+        </div>
+    </div>
+{% endblock %}
+
+{% block javascript %}
+    {{ parent() }}
+
+    <script type="text/javascript">
+        $(function () {
+            ajaxQueue(
+                    [{% for step in steps %}'{{ step }}'{{ loop.last ? '' : ', ' }}{% endfor %}],
+                    '{{ path('sylius_flow_forward', { scenarioAlias: 'chamilo_installer', stepName: 'installation' }) }}'
+            );
+        });
+    </script>
+{% endblock javascript %}

+ 62 - 0
src/Chamilo/InstallerBundle/Resources/views/Process/Step/schema.html.twig

@@ -0,0 +1,62 @@
+{% extends 'ChamiloInstallerBundle::layout.html.twig' %}
+{#{% set step, steps = 'schema', ['cache', 'schema-drop', 'clear-config', 'clear-extend', 'schema-update', 'workflows', 'processes', 'fixtures'] %}#}
+{% set step, steps = 'schema', ['cache', 'schema-drop', 'schema-update', 'fixtures'] %}
+{% use 'ChamiloInstallerBundle::progress.html.twig' %}
+
+{% block title %}
+    {% autoescape false %}
+        {{ 'process.step.schema.header'|trans }} - {{ parent() }}
+    {% endautoescape %}
+{% endblock %}
+
+{% block content %}
+    <div class="page-title">
+        <h2>{{ 'process.step.schema.header'|trans }}</h2>
+    </div>
+    <div>
+        <table class="table table-striped">
+            <col width="75%" valign="top">
+            <col width="25%" valign="top">
+            <thead>
+            <tr>
+                <th>{{ 'process.operation'|trans }}</th>
+                <th>{{ 'process.status'|trans }}</th>
+            </tr>
+            </thead>
+            <tbody>
+            {% for step in steps %}
+                <tr>
+                    <td>
+                        <span id="step-{{ step }}"></span>{{ ('process.step.schema.' ~ step)|trans }}
+                    </td>
+                    <td>&nbsp;</td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        </table>
+
+        <div class="install-form-actions">
+            <a href="{{ path('sylius_flow_display', { scenarioAlias: 'chamilo_installer', stepName: 'configure' }) }}"
+               class="btn btn-lg btn-default back disabled">
+                {{ 'process.button.back'|trans }}
+            </a>
+            <a href="javascript: void(0)"
+               class="btn btn-lg btn-primary next primary disabled">
+                <i class="fa fa-chevron-right"></i> {{ 'process.button.next'|trans }}
+            </a>
+        </div>
+    </div>
+{% endblock %}
+
+{% block javascript %}
+    {{ parent() }}
+
+    <script type="text/javascript">
+        $(function () {
+            ajaxQueue(
+                    [{% for step in steps %}'{{ step }}'{{ loop.last ? '' : ', ' }}{% endfor %}],
+                    '{{ path('sylius_flow_forward', { scenarioAlias: 'chamilo_installer', stepName: 'schema' }) }}'
+            );
+        });
+    </script>
+{% endblock javascript %}

+ 47 - 0
src/Chamilo/InstallerBundle/Resources/views/Process/Step/setup.html.twig

@@ -0,0 +1,47 @@
+{% extends 'ChamiloInstallerBundle::layout.html.twig' %}
+{% set step = 'setup' %}
+{% use 'ChamiloInstallerBundle::progress.html.twig' %}
+
+{% block title %}
+    {% autoescape false %}
+        {{ 'process.step.setup.header'|trans }} - {{ parent() }}
+    {% endautoescape %}
+{% endblock %}
+
+{% block content %}
+    <div class="row">
+        <div class="col-sm-12">
+            <div class="page-header">
+                <h2>{{ 'process.step.setup.header'|trans|raw }}</h2>
+            </div>
+
+            <form action="{{ path('sylius_flow_forward', {'scenarioAlias': 'chamilo_installer', 'stepName': 'setup'}) }}"
+                  method="post">
+                {{ form_errors(form) }}
+                <div class="row">
+                    <div class="col-sm-6">
+                        <h3 class="sub-title">{{ form.admin.vars.label|trans }}</h3>
+
+                        {{ form_widget(form.admin) }}
+                    </div>
+                    <div class="col-sm-6">
+                        <h3 class="sub-title">{{ form.portal.vars.label|trans }}</h3>
+
+                        {{ form_widget(form.portal) }}
+                    </div>
+                </div>
+                {{ form_rest(form) }}
+                <div class="install-form-actions">
+                    <a href="{{ path('sylius_flow_display', {'scenarioAlias': 'chamilo_installer', 'stepName': 'configure'}) }}"
+                       class="btn btn-lg btn-default">
+                        <i class="fa fa-chevron-left"></i>
+                        {{ 'process.button.back'|trans }}
+                    </a> &nbsp;
+                    <button class="btn btn-lg btn-primary" type="submit">
+                        <i class="fa fa-magic"></i> {{ 'process.button.install'|trans }}
+                    </button>
+                </div>
+            </form>
+        </div>
+    </div>
+{% endblock %}

+ 22 - 0
src/Chamilo/InstallerBundle/Resources/views/Process/Step/welcome.html.twig

@@ -0,0 +1,22 @@
+{% extends 'ChamiloInstallerBundle::layout.html.twig' %}
+{% set step = 'welcome' %}
+{% use 'ChamiloInstallerBundle::progress.html.twig' %}
+{% block title %}
+    {% autoescape false %}
+        {{ 'process.step.welcome.header'|trans }} - {{ parent() }}
+    {% endautoescape %}
+{% endblock %}
+
+{% block content %}
+
+    <div class="well">
+        {{ 'process.step.welcome.content'|trans|raw }}
+    </div>
+
+    <div class="install-form-actions">
+        <a href="{{ path('sylius_flow_forward', {'scenarioAlias': 'chamilo_installer', 'stepName': 'welcome'}) }}"
+           class="btn btn-lg btn-primary">
+            <i class="fa fa-chevron-right"></i> {{ 'process.button.continue'|trans }}
+        </a>
+    </div>
+{% endblock %}

+ 141 - 0
src/Chamilo/InstallerBundle/Resources/views/layout.html.twig

@@ -0,0 +1,141 @@
+<!doctype html>
+<!--[if IE 7 ]>
+<html class="no-js ie ie7" lang="en"> <![endif]-->
+<!--[if IE 8 ]>
+<html class="no-js ie ie8" lang="en"> <![endif]-->
+<!--[if IE 9 ]>
+<html class="no-js ie ie9" lang="en"> <![endif]-->
+<!--[if (gte IE 10)|!(IE)]><!-->
+<html class="no-js" lang="en"> <!--<![endif]-->
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <title>{% block title %}{{ 'title'|trans }}{% endblock %}</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+    {% block stylesheets %}
+    {% endblock %}
+
+    <link rel="stylesheet"
+          href="{{ asset('bundles/chamilotheme/components/bootstrap/dist/css/bootstrap.css') }}"/>
+    <link rel="stylesheet"
+          href="{{ asset('bundles/chamilotheme/components/fontawesome/css/font-awesome.css') }}"/>
+    <link rel="stylesheet"
+          href="{{ asset('bundles/chamiloinstaller/css/install.css') }}"/>
+
+    <script type="text/javascript"
+            src="{{ asset('bundles/chamilotheme/components/jquery/dist/jquery.js') }}"></script>
+    <script type="text/javascript"
+            src="{{ asset('bundles/chamilotheme/components/bootstrap/dist/js/bootstrap.js') }}"></script>
+    <script type="text/javascript"
+            src="{{ asset('bundles/chamilotheme/components/ajaxQueue/dist/jquery.ajaxQueue.js') }}"></script>
+
+    {% block javascript %}
+        <script type="text/javascript">
+
+            $(function () {
+                $('.progress-bar li:last-child em.fix-bg').width($('.progress-bar li:last-child').width() / 2);
+                $('.progress-bar li:first-child em.fix-bg').width($('.progress-bar li:first-child').width() / 2);
+
+                $('form').submit(function () {
+                    $(this).find(':submit').attr('disabled', true).addClass('disabled');
+                });
+
+                $('input[type="checkbox"]').addClass('icheckbox_minimal');
+                $('input[type="checkbox"]').removeClass('form-control');
+            });
+
+            var wait = '<i class="fa fa-clock-o"></i> {{ 'wait'|trans }}';
+            var progress = '<i class="fa fa-circle-o-notch fa-spin"></i> {{ 'progress'|trans }}';
+            var skipped = '<i class="fa fa-circle-thin"></i> {{ 'skipped'|trans }}';
+            var passed = '<i class="fa fa-check-circle-o"></i> {{ 'passed'|trans }}';
+            var failed = '<i class="fa fa-exclamation-triangle"></i> {{ 'failed'|trans }}';
+
+            function ajaxQueue(actions, url) {
+                var finRes = true,
+                        aborted = false;
+
+                $.each(actions, function (i) {
+                    var stepCon = $('#step-' + this);
+
+                    stepCon.closest('tr').find('td:last').html(wait);
+
+                    if (i == 0) {
+                        stepCon
+                                .addClass('icon-wait')
+                                .closest('tr').find('td:last').html(progress);
+                    }
+
+                    $.ajaxQueue({
+                        url: '?action=' + this,
+                        beforeSend: function (jqXHR) {
+                            if (!finRes) {
+                                aborted = true;
+                                jqXHR.abort();
+                            }
+                        }
+                    }).done(function (data) {
+                        var curRes = typeof data.result != 'undefined' && data.result,
+                                exitCode = typeof data.exitCode != 'undefined' ? data.exitCode : 0,
+                                finRes = finRes || curRes;
+
+                        stepCon
+                                .removeClass('icon-wait')
+                                .addClass('icon-' + (curRes ? (exitCode == 0 ? 'yes' : 'warning') : 'no'))
+                                .closest('tr')
+                                .find('td:last').html(
+                                curRes
+                                        ? (exitCode == 0 ? passed : skipped)
+                                        : failed
+                        ).end()
+                                .closest('tr').next()
+                                .find('td:last').html(progress).end()
+                                .find('span').addClass('icon-wait');
+
+                        if (i == actions.length - 1 && finRes) {
+                            $('a.back').removeClass('disabled');
+                            $('a.primary').removeClass('disabled').attr('href', url);
+                        }
+                    }).fail(function () {
+                        if (aborted) {
+                            stepCon
+                                    .removeClass('icon-wait')
+                                    .addClass('icon-warning')
+                                    .closest('tr').find('td:last').html(skipped);
+                        } else {
+                            finRes = false;
+                            stepCon
+                                    .removeClass('icon-wait')
+                                    .addClass('icon-no')
+                                    .closest('tr').find('td:last').html(failed);
+                        }
+                        if (i == actions.length - 1) {
+                            $('a.back').removeClass('disabled');
+                        }
+                    });
+                });
+            }
+        </script>
+    {% endblock javascript %}
+</head>
+
+<body>
+<div class="container">
+    <div class="page-header">
+        <h1 class="logo">{{ 'title'|trans }}</h1>
+    </div>
+    {% block progress %}{% endblock %}
+    {% block content %}{% endblock %}
+</div>
+
+{% block bottom %}
+    <footer class="footer">
+        <div class="container">
+            <p class="text-muted">
+                Chamilo {{ "now"|date("Y") }}
+            </p>
+        </div>
+    </footer>
+{% endblock bottom %}
+</body>
+</html>

+ 40 - 0
src/Chamilo/InstallerBundle/Resources/views/progress.html.twig

@@ -0,0 +1,40 @@
+{% block progress %}
+    {% set step = step is defined ? step|lower : 'welcome' %}
+    <div class="row wizard-container">
+        <div class="col-sm-12">
+            <ul class="nav nav-wizard">
+                <li{% if step == 'welcome' %} class="active"{% endif %}>
+                    <em class="fix-bg">&nbsp;</em>
+                    <strong class="step">1</strong>
+                    <span>{{ 'process.step.welcome.header'|trans }}</span>
+                </li>
+                {#<li{% if step == 'check' %} class="active"{% endif %}>#}
+                {#<em class="fix-bg">&nbsp;</em>#}
+                {#<strong class="step">2</strong>#}
+                {#<span>{{ 'process.step.check.header'|trans }}</span>#}
+                {#</li>#}
+                <li{% if step == 'configure' %} class="active"{% endif %}>
+                    <em class="fix-bg">&nbsp;</em>
+                    <strong class="step">2</strong>
+                    <span>{{ 'process.step.configure.header'|trans }}</span>
+                </li>
+                <li{% if step == 'schema' %} class="active"{% endif %}>
+                    <em class="fix-bg">&nbsp;</em>
+                    <strong class="step">3</strong>
+                    <span>{{ 'process.step.schema.header'|trans }}</span>
+                </li>
+                <li{% if step == 'setup' %} class="active"{% endif %}>
+                    <em class="fix-bg">&nbsp;</em>
+                    <strong class="step">4</strong>
+                    <span>{{ 'process.step.setup.header'|trans }}</span>
+                </li>
+                <li{% if step == 'final' %} class="active"{% endif %}>
+                    <em class="fix-bg">&nbsp;</em>
+                    <strong class="step">5</strong>
+                    <span>{{ 'process.step.final.header'|trans }}</span>
+                </li>
+            </ul>
+        </div>
+    </div>
+
+{% endblock %}

+ 89 - 0
src/Chamilo/InstallerBundle/ScriptExecutor.php

@@ -0,0 +1,89 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle;
+
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Class ScriptExecutor
+ * @package Chamilo\InstallerBundle
+ */
+class ScriptExecutor
+{
+    const CHAMILO_SCRIPT_ANNOTATION = 'ChamiloScript';
+
+    /**
+     * @var OutputInterface
+     */
+    protected $output;
+
+    /**
+     * @var ContainerInterface
+     */
+    protected $container;
+
+    /**
+     * @var CommandExecutor
+     */
+    protected $commandExecutor;
+
+    /**
+     * @param OutputInterface $output
+     * @param ContainerInterface $container
+     * @param CommandExecutor $commandExecutor
+     */
+    public function __construct(
+        OutputInterface $output,
+        ContainerInterface $container,
+        CommandExecutor $commandExecutor
+    ) {
+        $this->output = $output;
+        $this->container = $container;
+        $this->commandExecutor = $commandExecutor;
+    }
+
+    /**
+     * Run script
+     *
+     * @param string $fileName
+     */
+    public function runScript($fileName)
+    {
+        if (is_file($fileName)) {
+            $tokens = [];
+            if (preg_match(
+                '/@'.self::CHAMILO_SCRIPT_ANNOTATION.'(\(("([\w -]*)")?\))?/i',
+                file_get_contents($fileName),
+                $tokens
+            )
+            ) {
+                $scriptLabel = count($tokens) === 4 && $tokens[3]
+                    ? sprintf('"%s" (%s)', $tokens[3], $fileName)
+                    : sprintf('"%s"', $fileName);
+                $this->output->writeln(
+                    sprintf('Launching %s script', $scriptLabel)
+                );
+                ob_start();
+                $container = $this->container;
+                $commandExecutor = $this->commandExecutor;
+                include($fileName);
+                $scriptOutput = ob_get_contents();
+                ob_clean();
+                $this->output->writeln($scriptOutput);
+            } else {
+                $this->output->writeln(
+                    sprintf(
+                        'The "%s" script must contains @%s annotation',
+                        $fileName,
+                        self::CHAMILO_SCRIPT_ANNOTATION
+                    )
+                );
+            }
+
+        } else {
+            $this->output->writeln(sprintf('File "%s" not found', $fileName));
+        }
+    }
+}

+ 226 - 0
src/Chamilo/InstallerBundle/ScriptManager.php

@@ -0,0 +1,226 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+namespace Chamilo\InstallerBundle;
+
+use Symfony\Component\HttpKernel\Kernel;
+
+/**
+ * Class ScriptManager
+ * @package Chamilo\InstallerBundle
+ */
+class ScriptManager
+{
+    const CHAMILO_INSTALLER_SCRIPT_FILE_NAME = 'install.php';
+
+    /**
+     * @var Kernel
+     */
+    protected $kernel;
+
+    /**
+     * @var array
+     *      key   -> script md5 key
+     *      value -> array
+     *                  'index' - script index (used for execute scripts in properly order)
+     *                  'key'   - script file md5 key
+     *                  'file'  - script file name
+     *                  'label' - script label
+     */
+    protected $scripts = null;
+
+    /**
+     * Constructor
+     *
+     * @param Kernel $kernel
+     */
+    public function __construct(Kernel $kernel)
+    {
+        $this->kernel = $kernel;
+    }
+
+    /**
+     * get array with scripts keys and labels
+     *
+     * @return array
+     *      key   -> script file md5 key
+     *      value -> script label
+     */
+    public function getScriptLabels()
+    {
+        $this->ensureScriptsLoaded();
+
+        $result = [];
+        if (!empty($this->scripts)) {
+            foreach ($this->scripts as $script) {
+                $result[$script['key']] = $script['label'];
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Get list of scripts
+     *
+     * @return array
+     *      key   -> script md5 key
+     *      value -> script file name
+     */
+    public function getScriptFiles()
+    {
+        $this->ensureScriptsLoaded();
+
+        $result = [];
+        if (!empty($this->scripts)) {
+            foreach ($this->scripts as $script) {
+                $result[$script['key']] = $script['file'];
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Get script file name array by script md5 key
+     *
+     * @param string $scriptKey Script md5 key
+     * @return string|bool
+     */
+    public function getScriptFileByKey($scriptKey)
+    {
+        $this->ensureScriptsLoaded();
+
+        if (!empty($this->scripts) && isset($this->scripts[$scriptKey])) {
+            return $this->scripts[$scriptKey]['file'];
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks if scripts were loaded and load they if needed
+     */
+    protected function ensureScriptsLoaded()
+    {
+        if ($this->scripts === null) {
+            $this->loadScripts();
+        }
+    }
+
+    /**
+     * Read scripts info from files
+     */
+    protected function loadScripts()
+    {
+        $index = 0;
+        $scripts = [];
+        $this->scripts = [];
+        $rootDir = realpath(
+            $this->kernel->getRootDir(
+            ).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR
+        );
+        $bundles = $this->kernel->getBundles();
+        foreach ($bundles as $bundle) {
+            $bundleDirName = $bundle->getPath();
+            $this->getScriptInfo($bundleDirName, $index, $scripts);
+
+            $relativePathArray = explode(
+                DIRECTORY_SEPARATOR,
+                str_replace($rootDir, '', $bundleDirName)
+            );
+            if ($relativePathArray[0] == '') {
+                unset ($relativePathArray[0]);
+            }
+            for ($i = count($relativePathArray); $i >= 0; $i--) {
+                unset($relativePathArray[$i]);
+                $checkPath = $rootDir.DIRECTORY_SEPARATOR.implode(
+                        DIRECTORY_SEPARATOR,
+                        $relativePathArray
+                    );
+                if ($this->getScriptInfo($checkPath, $index, $scripts)) {
+                    break;
+                }
+            }
+        }
+        if (!empty($scripts)) {
+            usort($scripts, array($this, "compareScripts"));
+            foreach ($scripts as $script) {
+                $this->scripts[$script['key']] = $script;
+            }
+        }
+    }
+
+    /**
+     * Get script info from dir
+     *
+     * @param string $dirName
+     * @param int $index
+     * @param array $scripts
+     * @return array|bool
+     */
+    protected function getScriptInfo($dirName, &$index, &$scripts)
+    {
+        $file = $dirName.DIRECTORY_SEPARATOR.self::CHAMILO_INSTALLER_SCRIPT_FILE_NAME;
+        if (is_file($file) && !isset($scripts[md5($file)])) {
+            $data = $this->getScriptInfoFromFile($file);
+            if ($data) {
+                $data['index'] = $index;
+                $index++;
+                $scripts[$data['file']] = $data;
+
+                return $data;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Compare two scripts for sorting
+     *
+     * @param array $a
+     * @param array $b
+     * @return int
+     */
+    protected function compareScripts($a, $b)
+    {
+        $pathA = dirname($a['file']).DIRECTORY_SEPARATOR;
+        $pathB = dirname($b['file']).DIRECTORY_SEPARATOR;
+
+        if (strpos($pathA, $pathB) === 0) {
+            return -1;
+        } elseif (strpos($pathB, $pathA) === 0) {
+            return 1;
+        }
+
+        return $a['index'] < $b['index'] ? -1 : 1;
+    }
+
+    /**
+     * Get info about script file
+     *
+     * @param string $fileName
+     * @return array|bool
+     */
+    protected function getScriptInfoFromFile($fileName)
+    {
+        $tokens = [];
+        if (preg_match(
+            '/@'.ScriptExecutor::CHAMILO_SCRIPT_ANNOTATION.'\("([\w -]+)"\)/i',
+            file_get_contents($fileName),
+            $tokens
+        )
+        ) {
+            if (isset($tokens[1])) {
+                return [
+                    'key' => md5($fileName),
+                    'file' => $fileName,
+                    'label' => str_replace('"', '', $tokens[1]),
+                ];
+            }
+        }
+
+        return false;
+    }
+}

+ 12 - 0
src/Chamilo/InstallerBundle/Validator/Constraints/DatabaseConnection.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace Chamilo\InstallerBundle\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+
+class DatabaseConnection extends Constraint
+{
+    //@codingStandardsIgnoreStart
+    public $message = 'Unable to connect to database "%name%". Please check database connection parameters and user permissions.';
+    //@codingStandardsIgnoreEnd
+}

+ 34 - 0
src/Chamilo/InstallerBundle/Validator/Constraints/DatabaseConnectionValidator.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace Chamilo\InstallerBundle\Validator\Constraints;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+
+use Doctrine\DBAL\DriverManager;
+
+class DatabaseConnectionValidator extends ConstraintValidator
+{
+    public function validate($value, Constraint $constraint)
+    {
+        $params = array(
+            'host' => $value['chamilo_installer_database_host'],
+            'port' => $value['chamilo_installer_database_port'],
+            'dbname' => $value['chamilo_installer_database_name'],
+            'user' => $value['chamilo_installer_database_user'],
+            'password' => $value['chamilo_installer_database_password'],
+            //'driver'   => $value['chamilo_installer_database_driver'],
+            'driver' => 'pdo_mysql',
+            'charset' => 'UTF8',
+        );
+
+        try {
+            DriverManager::getConnection($params)->connect();
+        } catch (\PDOException $e) {
+            $this->context->addViolation(
+                $constraint->message,
+                array('%name%' => $params['dbname'])
+            );
+        }
+    }
+}

+ 266 - 0
web/install.php

@@ -0,0 +1,266 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+if (!isset($_SERVER['HTTP_HOST'])) {
+    exit('This script cannot be run from the CLI. Run it from a browser.');
+}
+
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\Loader\YamlFileLoader;
+use Symfony\Component\Yaml\Yaml;
+use Symfony\Component\HttpFoundation\Request;
+
+require_once __DIR__.'/../app/ChamiloRequirements.php';
+require_once __DIR__.'/../app/autoload.php';
+
+// check for installed system
+$paramFile = __DIR__.'/../app/config/parameters.yml';
+
+if (file_exists($paramFile)) {
+    $data = Yaml::parse($paramFile);
+    if (is_array($data)
+        && isset($data['parameters'])
+        && isset($data['parameters']['installed'])
+        && false != $data['parameters']['installed']
+    ) {
+        require_once __DIR__.'/app_dev.php';
+        exit;
+
+        require_once __DIR__.'/../app/AppKernel.php';
+
+        $kernel = new AppKernel('dev', false);
+        $kernel->loadClassCache();
+        $request = Request::createFromGlobals();
+        $response = $kernel->handle($request);
+        $response->send();
+        $kernel->terminate($request, $response);
+        exit;
+    }
+}
+
+/**
+ * @todo Identify correct locale (headers?)
+ */
+$locale = 'en';
+$collection = new ChamiloRequirements();
+$translator = new Translator($locale);
+$majorProblems = $collection->getFailedRequirements();
+$minorProblems = $collection->getFailedRecommendations();
+
+$translator->addLoader('yml', new YamlFileLoader());
+$translator->addResource(
+    'yml',
+    __DIR__.'/../src/Chamilo/InstallerBundle/Resources/translations/messages.'.$locale.'.yml',
+    $locale
+);
+
+function iterateRequirements(array $collection, $translator)
+{
+    foreach ($collection as $requirement) :
+        ?>
+        <tr>
+            <td class="dark">
+                <?php if ($requirement->isFulfilled()) : ?>
+                <span class="icon-yes">
+            <?php elseif (!$requirement->isOptional()) : ?>
+                    <span class="icon-no">
+            <?php else : ?>
+                        <span class="icon-warning">
+            <?php endif; ?>
+            <?php echo $requirement->getTestMessage(); ?>
+            </span>
+                        <?php if ($requirement instanceof CliRequirement && !$requirement->isFulfilled(
+                            )
+                        ) : ?>
+                            <pre
+                                class="output"><?php echo $requirement->getOutput(
+                                ); ?></pre>
+                        <?php endif; ?>
+            </td>
+            <td>
+                <?php
+                if ($requirement->isFulfilled()) {
+                    echo '<h4><span class="label label-success"><i class="fa fa-check-circle"></i>  '.$translator->trans(
+                            'process.step.check.requirement_status.ok'
+                        ).'</span></h4>';
+                } else {
+                    if (!$requirement->isOptional()) {
+                        echo '<h4><span class="label label-danger"><i class="fa fa-exclamation-triangle"> </i> '.$translator->trans(
+                                'process.step.check.requirement_status.danger'
+                            ).'</span></h4>';
+                    } else {
+                        echo '<h4><span class="label label-warning"><i class="fa fa-exclamation-triangle"></i> '.$translator->trans(
+                                'process.step.check.requirement_status.warning'
+                            ).'</span></h4>';
+                    }
+                    $requirement->getHelpHtml();
+                    echo '</span>';
+                }
+                ?>
+            </td>
+        </tr>
+        <?php
+    endforeach;
+}
+
+?>
+<!doctype html>
+<!--[if IE 7 ]>
+<html class="no-js ie ie7" lang="en"> <![endif]-->
+<!--[if IE 8 ]>
+<html class="no-js ie ie8" lang="en"> <![endif]-->
+<!--[if IE 9 ]>
+<html class="no-js ie ie9" lang="en"> <![endif]-->
+<!--[if (gte IE 10)|!(IE)]><!-->
+<html class="no-js" lang="en"> <!--<![endif]-->
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <title><?php echo $translator->trans('title'); ?></title>
+
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" type="text/css"
+          href="bundles/chamilotheme/components/bootstrap/dist/css/bootstrap.css"/>
+    <link rel="stylesheet" type="text/css"
+          href="bundles/chamilotheme/components/fontawesome/css/font-awesome.css"/>
+    <link rel="stylesheet" type="text/css"
+          href="bundles/chamiloinstaller/css/install.css"/>
+    <script type="text/javascript"
+            src="bundles/chamilotheme/components/jquery/dist/jquery.min.js"></script>
+
+    <script type="text/javascript">
+        $(function () {
+            $('.progress-bar li:last-child em.fix-bg').width($('.progress-bar li:last-child').width() / 2);
+            $('.progress-bar li:first-child em.fix-bg').width($('.progress-bar li:first-child').width() / 2);
+
+            var splash = $('div.start-box'),
+                body = $('body'),
+                winHeight = $(window).height();
+
+            $('#begin-install').click(function () {
+                splash.hide();
+                body.css({'overflow': 'visible', 'height': 'auto'});
+            });
+
+            if ('localStorage' in window && window['localStorage'] !== null) {
+                if (!localStorage.getItem('oroInstallSplash')) {
+                    splash.show().height(winHeight);
+                    body.css({'overflow': 'hidden', 'height': winHeight});
+
+                    localStorage.setItem('oroInstallSplash', true);
+                }
+            }
+
+            <?php if (!count($majorProblems)) : ?>
+            // initiate application in background
+            $.get('app_dev.php/installer/flow/chamilo_installer/configure');
+            <?php endif; ?>
+        });
+    </script>
+</head>
+<body>
+<div class="container">
+    <div class="page-header">
+        <h1 class="logo"><?php echo $translator->trans('title'); ?></h1>
+    </div>
+    <div class="content">
+        <div class="page-title">
+            <h2><?php echo $translator->trans(
+                    'process.step.check.header'
+                ); ?></h2>
+        </div>
+        <div>
+            <?php if (count($majorProblems)) : ?>
+                <div class="alert alert-warning" role="alert">
+                    <ul>
+                        <li><?php echo $translator->trans(
+                                'process.step.check.invalid'
+                            ); ?></li>
+                        <?php if ($collection->hasPhpIniConfigIssue()): ?>
+                            <li id="phpini">*
+                                <?php
+                                if ($collection->getPhpIniConfigPath()) :
+                                    echo $translator->trans(
+                                        'process.step.check.phpchanges',
+                                        array(
+                                            '%path%' => $collection->getPhpIniConfigPath(
+                                            ),
+                                        )
+                                    );
+                                else :
+                                    echo $translator->trans(
+                                        'process.step.check.phpchanges'
+                                    );
+                                endif;
+                                ?>
+                            </li>
+                        <?php endif; ?>
+                    </ul>
+                </div>
+            <?php endif; ?>
+
+            <?php
+            $requirements = array(
+                'mandatory' => $collection->getMandatoryRequirements(),
+                'php' => $collection->getPhpIniRequirements(),
+                'chamilo' => $collection->getChamiloRequirements(),
+                'cli' => $collection->getCliRequirements(),
+                'optional' => $collection->getRecommendations(),
+            );
+
+            foreach ($requirements as $type => $requirement) : ?>
+                <table class="table table-striped">
+                    <col width="75%" valign="top">
+                    <col width="25%" valign="top">
+                    <thead>
+                    <tr>
+                        <th><?php echo $translator->trans(
+                                'process.step.check.table.'.$type
+                            ); ?></th>
+                        <th><?php echo $translator->trans(
+                                'process.step.check.table.status'
+                            ); ?></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <?php iterateRequirements($requirement, $translator); ?>
+                    </tbody>
+                </table>
+            <?php endforeach; ?>
+        </div>
+
+        <hr/>
+        <br/>
+
+        <div class="install-form-actions">
+            <?php if (count($majorProblems) || count($minorProblems)): ?>
+                <a href="install.php" class="btn btn-default btn-lg">
+                    <i class="fa fa-refresh"></i> <?php echo $translator->trans(
+                        'process.button.refresh'
+                    ); ?>
+                </a>
+            <?php endif; ?>
+            <a href="<?php echo count(
+                $majorProblems
+            ) ? 'javascript: void(0);' : 'app_dev.php/installer/flow/chamilo_installer/welcome'; ?>"
+               class="btn btn-lg btn-primary <?php echo count(
+                   $majorProblems
+               ) ? 'disabled' : 'primary'; ?>">
+                <i class="fa fa-chevron-right"></i> <?php echo $translator->trans(
+                    'process.button.continue'
+                ); ?>
+            </a>
+        </div>
+    </div>
+</div>
+<hr/>
+<br/>
+<footer class="footer">
+    <div class="container">
+        <p class="text-muted">
+            Chamilo
+        </p>
+    </div>
+</footer>
+</body>
+</html>