diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 691cf2198..b90ca3e45 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -40,6 +40,8 @@ +
+ diff --git a/core/lib/Thelia/Config/Resources/routing/install.xml b/core/lib/Thelia/Config/Resources/routing/install.xml index 37ddde487..720761b40 100644 --- a/core/lib/Thelia/Config/Resources/routing/install.xml +++ b/core/lib/Thelia/Config/Resources/routing/install.xml @@ -5,27 +5,27 @@ xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> - Thelia\Controller\Install\InstallController::index + Thelia\Controller\Install\InstallController::indexAction - Thelia\Controller\Install\InstallController::checkPermission + Thelia\Controller\Install\InstallController::checkPermissionAction - Thelia\Controller\Install\InstallController::databaseConnection + Thelia\Controller\Install\InstallController::databaseConnectionAction - Thelia\Controller\Install\InstallController::databaseSelection + Thelia\Controller\Install\InstallController::databaseSelectionAction - Thelia\Controller\Install\InstallController::generalInformation + Thelia\Controller\Install\InstallController::generalInformationAction - Thelia\Controller\Install\InstallController::thanks + Thelia\Controller\Install\InstallController::thanksAction diff --git a/core/lib/Thelia/Controller/Install/InstallController.php b/core/lib/Thelia/Controller/Install/InstallController.php index 648ae843e..a6b0d975d 100644 --- a/core/lib/Thelia/Controller/Install/InstallController.php +++ b/core/lib/Thelia/Controller/Install/InstallController.php @@ -22,7 +22,12 @@ /*************************************************************************************/ namespace Thelia\Controller\Install; +use Thelia\Form\Exception\FormValidationException; +use Thelia\Form\InstallStep3Form; +use Thelia\Install\CheckDatabaseConnection; use Thelia\Install\CheckPermission; +use Thelia\Install\Exception\AlreadyInstallException; +use Thelia\Install\Exception\InstallException; /** * Class InstallController @@ -35,9 +40,14 @@ class InstallController extends BaseInstallController { public function indexAction() { - //$this->verifyStep(1); + $args = array(); + try { + //$this->verifyStep(1); // @todo implement + $this->getSession()->set("step", 1); + } catch (AlreadyInstallException $e) { + $args['isAlreadyInstalled'] = true; + } - $this->getSession()->set("step", 1); return $this->render("index.html"); } @@ -49,29 +59,22 @@ class InstallController extends BaseInstallController */ public function checkPermissionAction() { + try { + //$this->verifyStep(2); // @todo implement + $checkPermission = new CheckPermission(true, $this->getTranslator()); + $args['isValid'] = $isValid = $checkPermission->exec(); + $args['validationMessages'] = $checkPermission->getValidationMessages(); + + $this->getSession()->set("step", 2); + } catch (AlreadyInstallException $e) { + $args['isAlreadyInstalled'] = true; + } $args = array(); - var_dump('step2'); - //$this->verifyStep(2); - $checkPermission = new CheckPermission(true, $this->getTranslator()); - $args['isValid'] = $isValid = $checkPermission->exec(); - $args['validationMessages'] = $checkPermission->getValidationMessages(); - - $this->getSession()->set("step", 2); return $this->render("step-2.html", $args); } - /** - * Database connexion tests - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function databaseConnection() - { - var_dump('step 3 bis'); - } - /** * Database connexion tests * @@ -79,15 +82,95 @@ class InstallController extends BaseInstallController */ public function databaseConnectionAction() { - var_dump('step 3'); - exit(); - //$this->verifyStep(2); + $args = array(); - //$permission = new CheckPermission(); + try { + //$this->verifyStep(2); // @todo implement - $this->getSession()->set("step", 3); + if ($this->getRequest()->isMethod('POST')) { + // Create the form from the request + $step3Form = new InstallStep3Form($this->getRequest()); - return $this->render("step-3.html"); + $message = false; + try { + // Check the form against constraints violations + $form = $this->validateForm($step3Form, 'POST'); + + // Get the form field values + $data = $form->getData(); + var_dump('data', $data); + + // @todo implement tests + try { + new CheckDatabaseConnection( + $data['host'], + $data['user'], + $data['password'], + $data['port'], + true, + $this->getTranslator() + ); + + $this->getSession()->set('install', array( + 'host' =>$data['host'], + 'user' => $data['user'], + 'password' => $data['password'], + 'port' => $data['port'] + ) + ); + } catch (InstallException $e) { + $message = $this->getTranslator()->trans( + 'Can\'t connect with these credentials to this server', + array(), + 'install-wizard' + ); + } + + // $this->redirect( + // str_replace( + // '{id}', + // $couponEvent->getCoupon()->getId(), + // $creationForm->getSuccessUrl() + // ) + // ); + } catch (FormValidationException $e) { + // Invalid data entered + $message = $this->getTranslator()->trans( + 'Please check your input:', + array(), + 'install-wizard' + ); + + } catch (\Exception $e) { + // Any other error + $message = $this->getTranslator()->trans( + 'Sorry, an error occurred:', + array(), + 'install-wizard' + ); + } + + if ($message !== false) { + // Mark the form as with error + $step3Form->setErrorMessage($message); + + // Send the form and the error to the parser + $this->getParserContext() + ->addForm($step3Form) + ->setGeneralError($message); + } + } + + $this->getSession()->set("step", 3); + + $args['edit_language_locale'] = $this->getSession()->getLang()->getLocale(); + $args['formAction'] = 'install/step/3'; + + } catch (AlreadyInstallException $e) { + $args['isAlreadyInstalled'] = true; + } + + return $this->render('step-3.html', $args); } /** @@ -97,7 +180,14 @@ class InstallController extends BaseInstallController */ public function databaseSelectionAction() { - //$this->verifyStep(2); + $args = array(); + try { + + } catch (AlreadyInstallException $e) { + $args['isAlreadyInstalled'] = true; + } + + //$this->verifyStep(2); // @todo implement //$permission = new CheckPermission(); @@ -107,13 +197,19 @@ class InstallController extends BaseInstallController } /** - * Set general informations + * Set general information * * @return \Symfony\Component\HttpFoundation\Response */ public function generalInformationAction() { - //$this->verifyStep(2); + $args = array(); + try { + + } catch (AlreadyInstallException $e) { + $args['isAlreadyInstalled'] = true; + } + //$this->verifyStep(2); // @todo implement //$permission = new CheckPermission(); @@ -129,7 +225,13 @@ class InstallController extends BaseInstallController */ public function thanksAction() { - //$this->verifyStep(2); + $args = array(); + try { + + } catch (AlreadyInstallException $e) { + $args['isAlreadyInstalled'] = true; + } + //$this->verifyStep(2); // @todo implement //$permission = new CheckPermission(); @@ -162,5 +264,7 @@ class InstallController extends BaseInstallController } break; } + + return true; } } diff --git a/core/lib/Thelia/Form/InstallStep3Form.php b/core/lib/Thelia/Form/InstallStep3Form.php new file mode 100755 index 000000000..9388f14db --- /dev/null +++ b/core/lib/Thelia/Form/InstallStep3Form.php @@ -0,0 +1,111 @@ +. */ +/* */ +/**********************************************************************************/ + +namespace Thelia\Form; + +use Symfony\Component\Validator\Constraints\GreaterThan; +use Symfony\Component\Validator\Constraints\NotBlank; + +/** + * Created by JetBrains PhpStorm. + * Date: 8/29/13 + * Time: 3:45 PM + * + * Allow to build a form Install Step 3 Database connection + * + * @package Coupon + * @author Guillaume MOREL + * + */ +class InstallStep3Form extends BaseForm +{ + /** + * Build Coupon form + * + * @return void + */ + protected function buildForm() + { + $this->formBuilder + ->add( + 'host', + 'text', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'user', + 'text', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'password', + 'text', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ) + ->add( + 'port', + 'text', + array( + 'constraints' => array( + new NotBlank(), + new GreaterThan( + array( + 'value' => 0 + ) + ) + ) + ) + ) + ->add( + 'locale', + 'hidden', + array( + 'constraints' => array( + new NotBlank() + ) + ) + ); + } + + /** + * Get form name + * + * @return string + */ + public function getName() + { + return 'thelia_install_step3'; + } +} diff --git a/core/lib/Thelia/Install/BaseInstall.php b/core/lib/Thelia/Install/BaseInstall.php index 86928236a..aa41140dd 100644 --- a/core/lib/Thelia/Install/BaseInstall.php +++ b/core/lib/Thelia/Install/BaseInstall.php @@ -37,6 +37,8 @@ abstract class BaseInstall * Constructor * * @param bool $verifyInstall Verify if an installation already exists + * + * @throws Exception\AlreadyInstallException */ public function __construct($verifyInstall = true) { @@ -47,10 +49,9 @@ abstract class BaseInstall } else { $this->isConsoleMode = false; } - /* TODO : activate this part if (file_exists(THELIA_ROOT . '/local/config/database.yml') && $verifyInstall) { throw new AlreadyInstallException("Thelia is already installed"); - }*/ + } $this->exec(); diff --git a/core/lib/Thelia/Install/CheckDatabaseConnection.php b/core/lib/Thelia/Install/CheckDatabaseConnection.php new file mode 100644 index 000000000..50c117d22 --- /dev/null +++ b/core/lib/Thelia/Install/CheckDatabaseConnection.php @@ -0,0 +1,100 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Install; + +use PDO; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use Symfony\Component\Translation\TranslatorInterface; +use Thelia\Core\Translation\Translator; +use Thelia\Install\Exception\InstallException; + + +/** + * Class CheckDatabaseConnection + * + * Take care of integration tests (database connection) + * + * @package Thelia\Install + * @author Manuel Raynaud + * @author Guillaume MOREL + */ +class CheckDatabaseConnection extends BaseInstall +{ + protected $validationMessages = array(); + + /** @var bool If permissions are OK */ + protected $isValid = true; + + /** @var TranslatorInterface Translator Service */ + protected $translator = null; + + /** @var string Database host information */ + protected $host = null; + + /** @var string Database user information */ + protected $user = null; + + /** @var string Database password information */ + protected $password = null; + + /** @var int Database port information */ + protected $port = null; + + /** + * Constructor + * + * @param string $host Database host information + * @param string $user Database user information + * @param string $password Database password information + * @param int $port Database port information + * @param bool $verifyInstall If verify install + * @param Translator $translator Translator Service + * necessary for install wizard + */ + public function __construct($host, $user, $password, $port, $verifyInstall = true, Translator $translator = null) + { + $this->host = $host; + $this->user = $user; + $this->password = $password; + $this->port = $port; + + parent::__construct($verifyInstall); + } + + /** + * Perform database connection check + * + * @return bool + */ + public function exec() + { + $link = mysql_connect($this->host . ':' . $this->port, $this->user, $this->password); + if (!$link) { + throw new InstallException('Can\'t connect to the given credentials'); + } + mysql_close($link); + } + +} diff --git a/core/lib/Thelia/Install/CheckPermission.php b/core/lib/Thelia/Install/CheckPermission.php index d924bac35..d07b8ed83 100644 --- a/core/lib/Thelia/Install/CheckPermission.php +++ b/core/lib/Thelia/Install/CheckPermission.php @@ -52,6 +52,13 @@ class CheckPermission extends BaseInstall self::DIR_CACHE, ); + /** @var array Minimum server configuration necessary */ + protected $minServerConfigurationNecessary = array( + 'memory_limit' => 134217728, + 'post_max_size' => 20971520, + 'upload_max_filesize' => 2097152 + ); + protected $validationMessages = array(); /** @var bool If permissions are OK */ @@ -71,6 +78,12 @@ class CheckPermission extends BaseInstall { $this->translator = $translator; + $this->validationMessages['php_version'] = array( + 'text' => $this->getI18nPhpVersionText('5.4', phpversion(), true), + 'hint' => $this->getI18nPhpVersionHint(), + 'status' => true + ); + foreach ($this->directoriesToBeWritable as $directory) { $this->validationMessages[$directory] = array( 'text' => '', @@ -78,6 +91,14 @@ class CheckPermission extends BaseInstall 'status' => true ); } + foreach ($this->minServerConfigurationNecessary as $key => $value) { + $this->validationMessages[$key] = array( + 'text' => '', + 'hint' => $this->getI18nConfigHint(), + 'status' => true + ); + } + parent::__construct($verifyInstall); } @@ -88,19 +109,35 @@ class CheckPermission extends BaseInstall */ public function exec() { + if (version_compare(phpversion(), '5.4', '<')) { + $this->validationMessages['php_version'] = $this->getI18nPhpVersionText('5.4', phpversion(), false); + } + foreach ($this->directoriesToBeWritable as $directory) { $fullDirectory = THELIA_ROOT . $directory; - $this->validationMessages[$directory]['text'] = $this->getI18nText($fullDirectory, true); + $this->validationMessages[$directory]['text'] = $this->getI18nDirectoryText($fullDirectory, true); if (is_writable($fullDirectory) === false) { if (!$this->makeDirectoryWritable($fullDirectory)) { $this->isValid = false; $this->validationMessages[$directory]['status'] = false; - $this->validationMessages[$directory]['text'] = $this->getI18nText($fullDirectory, false); - $this->validationMessages[$directory]['hint'] = $this->getI18nHint($fullDirectory); + $this->validationMessages[$directory]['text'] = $this->getI18nDirectoryText($fullDirectory, false); + $this->validationMessages[$directory]['hint'] = $this->getI18nDirectoryHint($fullDirectory); } } } + foreach ($this->minServerConfigurationNecessary as $key => $value) { + $this->validationMessages[$key]['text'] = $this->getI18nConfigText($key, $this->formatBytes($value), ini_get($key), true); + if (!$this->verifyServerMemoryValues($key, $value)) { + $this->isValid = false; + $this->validationMessages[$key]['status'] = false; + $this->validationMessages[$key]['text'] = $this->getI18nConfigText($key, $this->formatBytes($value), ini_get($key), false);; + } + } + + + + return $this->isValid; } @@ -144,7 +181,7 @@ class CheckPermission extends BaseInstall * * @return string */ - protected function getI18nText($directory, $isValid) + protected function getI18nDirectoryText($directory, $isValid) { if ($this->translator !== null) { if ($isValid) { @@ -174,7 +211,7 @@ class CheckPermission extends BaseInstall * * @return string */ - protected function getI18nHint($directory) + protected function getI18nDirectoryHint($directory) { if ($this->translator !== null) { $sentence = 'chmod 777 %directory% on your server with admin rights could help'; @@ -191,4 +228,159 @@ class CheckPermission extends BaseInstall return $translatedText; } + + + /** + * Get Translated text about the directory state + * Not usable with CLI + * + * @param string $key .ini file key + * @param string $expectedValue Expected server value + * @param string $currentValue Actual server value + * @param bool $isValid If server configuration is valid + * + * @return string + */ + protected function getI18nConfigText($key, $expectedValue, $currentValue, $isValid) + { + if ($isValid) { + $sentence = 'Your %key% server configuration (currently %currentValue%) is well enough to run Thelia2 (%expectedValue% needed)'; + } else { + $sentence = 'Your %key% server configuration (currently %currentValue%) is not sufficient enough in order to run Thelia2 (%expectedValue% needed)'; + } + + $translatedText = $this->translator->trans( + $sentence, + array( + '%key%' => $key, + '%expectedValue%' => $expectedValue, + '%currentValue%' => $currentValue, + ), + 'install-wizard' + ); + + return $translatedText; + } + + /** + * Get Translated hint about the config requirement issue + * + * @return string + */ + protected function getI18nConfigHint() + { + $sentence = 'Modifying this value on your server php.ini file with admin rights could help'; + $translatedText = $this->translator->trans( + $sentence, + array(), + 'install-wizard' + ); + + return $translatedText; + } + + /** + * Get Translated hint about the PHP version requirement issue + * + * @param string $expectedValue + * @param string $currentValue + * @param bool $isValid + * + * @return string + */ + protected function getI18nPhpVersionText($expectedValue, $currentValue, $isValid) + { + if ($this->translator !== null) { + if ($isValid) { + $sentence = 'Your PHP version %currentValue% is well enough to run Thelia2 (%expectedValue% needed)'; + } else { + $sentence = 'Your PHP version %currentValue% is not sufficient enough to run Thelia2 (%expectedValue% needed)'; + } + + $translatedText = $this->translator->trans( + $sentence, + array( + '%expectedValue%' => $expectedValue, + '%currentValue%' => $currentValue, + ), + 'install-wizard' + ); + } else { + $translatedText = sprintf('Thelia needs at least PHP %s (%s currently)', $expectedValue, $currentValue); + } + + return $translatedText; + } + + /** + * Get Translated hint about the config requirement issue + * + * @return string + */ + protected function getI18nPhpVersionHint() + { + $sentence = 'Upgrading your version of PHP with admin rights could help'; + $translatedText = $this->translator->trans( + $sentence, + array(), + 'install-wizard' + ); + + return $translatedText; + } + + /** + * Check if a server memory value is met or not + * + * @param string $key .ini file key + * @param int $necessaryValueInBytes Expected value in bytes + * + * @return bool + */ + protected function verifyServerMemoryValues($key, $necessaryValueInBytes) + { + $serverValueInBytes = $this->returnBytes(ini_get($key)); + + return ($serverValueInBytes >= $necessaryValueInBytes); + } + + /** + * Return bytes from memory .ini value + * + * @param string $val .ini value + * + * @return int + */ + protected function returnBytes($val) + { + $val = trim($val); + $last = strtolower($val[strlen($val)-1]); + switch($last) { + // The 'G' modifier is available since PHP 5.1.0 + case 'g': + $val *= 1024; + case 'm': + $val *= 1024; + case 'k': + $val *= 1024; + } + + return $val; + } + + /** + * Convert bytes to readable string + * + * @param int $bytes bytes + * @param int $precision conversion precision + * + * @return string + */ + protected function formatBytes($bytes, $precision = 2) + { + $base = log($bytes) / log(1024); + $suffixes = array('', 'k', 'M', 'G', 'T'); + + return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; + } } diff --git a/templates/install/index.html b/templates/install/index.html index dd1d5f62b..b7843d528 100644 --- a/templates/install/index.html +++ b/templates/install/index.html @@ -34,7 +34,7 @@ diff --git a/templates/install/layout.tpl b/templates/install/layout.tpl index 6b38292e2..1497d7ea5 100644 --- a/templates/install/layout.tpl +++ b/templates/install/layout.tpl @@ -26,8 +26,12 @@ {* -- Main page content section ----------------------------------------- *} + {if $isAlreadyInstalled} +
{intl l='Thelia is already installed'}
+ {else} + {block name="main-content"}Put here the content of the template{/block} + {/if} - {block name="main-content"}Put here the content of the template{/block} {* -- Footer section ---------------------------------------------------- *} diff --git a/templates/install/step-2.html b/templates/install/step-2.html index a05267c7c..fbd34ddb5 100644 --- a/templates/install/step-2.html +++ b/templates/install/step-2.html @@ -37,8 +37,8 @@ diff --git a/templates/install/step-3.html b/templates/install/step-3.html index cb4157dd7..f93b0182b 100644 --- a/templates/install/step-3.html +++ b/templates/install/step-3.html @@ -23,29 +23,59 @@ -
- - -
- - -
-
- - -
-
- - -
- + {form name="thelia.install.step3"} +
+ {if ! empty($general_error) } +
{$general_error}
+ {/if} -
- - + {form_hidden_fields form=$form} + + {form_field form=$form field='locale'} + + {/form_field} + +
+ {form_field form=$form field='host'} +
+ + + {if $error}{$message}{/if} +
+ {/form_field} + + {form_field form=$form field='user'} +
+ + + {if $error}{$message}{/if} +
+ {/form_field} + + {form_field form=$form field='password'} +
+ + + {if $error}{$message}{/if} +
+ {/form_field} + + {form_field form=$form field='port'} +
+ + + {if $error}{$message}{/if} +
+ {/form_field} +
+