diff --git a/admin/install.php b/admin/install.php new file mode 100644 index 0000000000000000000000000000000000000000..9240f14783465115666ecaf1aaf50ee85a4d8ec5 --- /dev/null +++ b/admin/install.php @@ -0,0 +1,48 @@ +<?php +/** + * This software is governed by the CeCILL-B license. If a copy of this license + * is not distributed with this file, you can obtain one at + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt + * + * Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ + * Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft) + * + * ============================= + * + * Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence + * ne se trouve pas avec ce fichier vous pouvez l'obtenir sur + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt + * + * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ + * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) + */ + +use Framadate\Services\InstallService; +use Framadate\Utils; + +require_once '../app/inc/init.php'; + +if (is_file(CONF_FILENAME)) { + header(('Location: ' . Utils::get_server_name())); + exit; +} + +$error = null; +$installService = new InstallService(); + +if (!empty($_POST)) { + $installService->updateFields($_POST); + $result = $installService->install($smarty); + + if ($result['status'] === 'OK') { + header(('Location: ' . Utils::get_server_name() . 'admin/migration.php')); + exit; + } else { + $error = __('Error', $result['code']); + } +} + +$smarty->assign('error', $error); +$smarty->assign('title', __('Admin', 'Installation')); +$smarty->assign('fields', $installService->getFields()); +$smarty->display('admin/install.tpl'); \ No newline at end of file diff --git a/app/classes/Framadate/Services/InstallService.php b/app/classes/Framadate/Services/InstallService.php new file mode 100644 index 0000000000000000000000000000000000000000..0db9f1f8c8562e1c862048fc40fb9eac7027c65c --- /dev/null +++ b/app/classes/Framadate/Services/InstallService.php @@ -0,0 +1,123 @@ +<?php +/** + * This software is governed by the CeCILL-B license. If a copy of this license + * is not distributed with this file, you can obtain one at + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt + * + * Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ + * Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft) + * + * ============================= + * + * Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence + * ne se trouve pas avec ce fichier vous pouvez l'obtenir sur + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt + * + * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ + * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) + */ +namespace Framadate\Services; +use Framadate\Utils; +use Smarty; + +/** + * This class helps to clean all inputs from the users or external services. + */ +class InstallService { + + private $fields = array( + // General + 'appName' => 'Framadate', + 'appMail' => '', + 'responseMail' => '', + 'defaultLanguage' => 'fr', + 'cleanUrl' => true, + + // Database configuration + 'dbConnectionString' => 'mysql:host=<HOST>;dbname=<SCHEMA>;port=3306', + 'dbUser' => 'root', + 'dbPassword' => '', + 'dbPrefix' => 'fd_', + 'migrationTable' => 'framadate_migration' + ); + + function __construct() {} + + public function updateFields($data) { + foreach ($data as $field => $value) { + $this->fields[$field] = $value; + } + } + + public function install(Smarty &$smarty) { + // Check values are present + if (empty($this->fields['appName']) || empty($this->fields['appMail']) || empty($this->fields['defaultLanguage']) || empty($this->fields['dbConnectionString']) || empty($this->fields['dbUser'])) { + return $this->error('MISSING_VALUES'); + } + + // Connect to database + $connect = $this->connectTo($this->fields['dbConnectionString'], $this->fields['dbUser'], $this->fields['dbPassword']); + if (!$connect) { + return $this->error('CANT_CONNECT_TO_DATABASE'); + } + + // Write configuration to conf.php file + $this->writeConfiguration($smarty); + + return $this->ok(); + } + + function connectTo($connectionString, $user, $password) { + try { + $pdo = @new \PDO($connectionString, $user, $password); + $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + return $pdo; + } catch(\Exception $e) { + return null; + } + } + + function writeConfiguration(Smarty &$smarty) { + foreach($this->fields as $field=>$value) { + $smarty->assign($field, $value); + } + + $content = $smarty->fetch('admin/config.tpl'); + + $this->writeToFile($content); + } + + /** + * @param $content + */ + function writeToFile($content) { + file_put_contents(CONF_FILENAME, $content); + } + + /** + * @return array + */ + function ok() { + return array( + 'status' => 'OK', + 'msg' => __f('Installation', 'Ended', Utils::get_server_name()) + ); + } + + /** + * @param $msg + * @return array + */ + function error($msg) { + return array( + 'status' => 'ERROR', + 'code' => $msg + ); + } + + public function getFields() { + return $this->fields; + } + +} diff --git a/app/classes/Framadate/Utils.php b/app/classes/Framadate/Utils.php index 5eec8b55093f04f8ca905bd8c5c966fd15f06c38..aca9b9baedabc2e7a668184c2bf41009edc1fa6e 100644 --- a/app/classes/Framadate/Utils.php +++ b/app/classes/Framadate/Utils.php @@ -75,7 +75,7 @@ class Utils { <script type="text/javascript" src="' . self::get_server_name() . 'js/bootstrap-datepicker.js"></script> <script type="text/javascript" src="' . self::get_server_name() . 'js/locales/bootstrap-datepicker.' . $locale . '.js"></script> <script type="text/javascript" src="' . self::get_server_name() . 'js/core.js"></script>'; - if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/nav/nav.js")) { + if (is_file($_SERVER['DOCUMENT_ROOT'] . "/nav/nav.js")) { echo '<script src="/nav/nav.js" id="nav_js" type="text/javascript" charset="utf-8"></script><!-- /Framanav -->'; } diff --git a/app/inc/XXconfig.php b/app/inc/XXconfig.php new file mode 100644 index 0000000000000000000000000000000000000000..6530d1364b3d3abd1b9accc4e946665dcc4a3d6b --- /dev/null +++ b/app/inc/XXconfig.php @@ -0,0 +1,88 @@ +<?php +/** + * This software is governed by the CeCILL-B license. If a copy of this license + * is not distributed with this file, you can obtain one at + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt + * + * Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ + * Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft) + * + * ============================= + * + * Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence + * ne se trouve pas avec ce fichier vous pouvez l'obtenir sur + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt + * + * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ + * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) + */ + +// Fully qualified domain name of your webserver. +// If this is unset or empty, the servername is determined automatically. +// You *have to set this* if you are running Framedate behind a reverse proxy. +// const APP_URL = '<www.mydomain.fr>'; + +// Application name +const NOMAPPLICATION = 'Développement OPZ'; + +// Database administrator email +const ADRESSEMAILADMIN = 'framadate-dev@olivierperez.fr'; + +// Email for automatic responses (you should set it to "no-reply") +const ADRESSEMAILREPONSEAUTO = 'no-reply@olivierperez.fr'; + +// Database user +const DB_USER= 'dev_framadate'; + +// Database password +const DB_PASSWORD = 'dev_framadate'; + +// Database server name, leave empty to use a socket +const DB_CONNECTION_STRING = 'mysql:host=localhost;dbname=framadate_dev;port=3306'; + +// Name of the table that store migration script already executed +const MIGRATION_TABLE = 'framadate_migration'; + +// Table name prefix +const TABLENAME_PREFIX = 'fd_'; + +// Default Language using POSIX variant of BC P47 standard (choose in $ALLOWED_LANGUAGES) +const DEFAULT_LANGUAGE = 'fr'; + +// List of supported languages, fake constant as arrays can be used as constants only in PHP >=5.6 +$ALLOWED_LANGUAGES = [ + 'fr' => 'Français', + 'en' => 'English', + 'es' => 'Español', + 'de' => 'Deutsch', + 'it' => 'Italiano', +]; + +// Nom et emplacement du fichier image contenant le titre +const IMAGE_TITRE = 'images/logo-framadate.png'; + +// Clean URLs, boolean +const URL_PROPRE = false; + +// Use REMOTE_USER data provided by web server +const USE_REMOTE_USER = true; + +// Path to the log file +const LOG_FILE = 'admin/stdout.log'; + +// Days (after expiration date) before purge a poll +const PURGE_DELAY = 60; + +// Config +$config = [ + /* general config */ + 'use_smtp' => false, // use email for polls creation/modification/responses notification + /* home */ + 'show_what_is_that' => true, // display "how to use" section + 'show_the_software' => true, // display technical information about the software + 'show_cultivate_your_garden' => true, // display "developpement and administration" information + /* create_classic_poll.php / create_date_poll.php */ + 'default_poll_duration' => 180, // default values for the new poll duration (number of days). + /* create_classic_poll.php */ + 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. +]; diff --git a/app/inc/config.template.php b/app/inc/config.template.php index a29b57304cf5d6f6cdb1ddad9a2c34a8b0aa3ec6..9aad34e4bcce015035728a42cf554f0f5015f9f0 100644 --- a/app/inc/config.template.php +++ b/app/inc/config.template.php @@ -58,12 +58,6 @@ $ALLOWED_LANGUAGES = [ 'it' => 'Italiano', ]; -// Path to logo -const LOGOBANDEAU = '<relative path to the logo file>'; - -// Path to logo in PDF export -const LOGOLETTRE = '<relative path to the logo file for pdf>'; - // Nom et emplacement du fichier image contenant le titre const IMAGE_TITRE = 'images/logo-framadate.png'; diff --git a/app/inc/init.php b/app/inc/init.php index 63379ef6d02c0f715b561a6e0699baed5f67ffd8..8879bae747efb4e49ec09d9fc34ceb477ce3c5d6 100644 --- a/app/inc/init.php +++ b/app/inc/init.php @@ -32,15 +32,31 @@ if (ini_get('date.timezone') == '') { } define('ROOT_DIR', __DIR__ . '/../../'); +define('CONF_FILENAME', ROOT_DIR . '/app/inc/config.php'); -require_once __DIR__ . '/constants.php'; -require_once __DIR__ . '/config.php'; -require_once __DIR__ . '/i18n.php'; +if (is_file(CONF_FILENAME)) { -// Smarty -require_once __DIR__ . '/smarty.php'; + require_once __DIR__ . '/constants.php'; + @include_once __DIR__ . '/config.php'; + + // Connection to database + $connect = new FramaDB(DB_CONNECTION_STRING, DB_USER, DB_PASSWORD); + RepositoryFactory::init($connect); + $err = 0; +} else { + define('NOMAPPLICATION', 'Framadate'); + define('DEFAULT_LANGUAGE', 'fr'); + define('IMAGE_TITRE', 'images/logo-framadate.png'); + define('LOG_FILE', 'admin/stdout.log'); + $ALLOWED_LANGUAGES = [ + 'fr' => 'Français', + 'en' => 'English', + 'es' => 'Español', + 'de' => 'Deutsch', + 'it' => 'Italiano', + ]; +} -// Connection to database -$connect = new FramaDB(DB_CONNECTION_STRING, DB_USER, DB_PASSWORD); -RepositoryFactory::init($connect); -$err = 0; +require_once __DIR__ . '/i18n.php'; +// Smarty +require_once __DIR__ . '/smarty.php'; \ No newline at end of file diff --git a/app/inc/smarty.php b/app/inc/smarty.php index 83dddedf9dff02250a492317db20887a54e9d333..26be0b30141eff986c43713a86cfaa032876e9b0 100644 --- a/app/inc/smarty.php +++ b/app/inc/smarty.php @@ -29,7 +29,7 @@ $smarty->assign('APPLICATION_NAME', NOMAPPLICATION); $smarty->assign('SERVER_URL', Utils::get_server_name()); $smarty->assign('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']); $smarty->assign('TITLE_IMAGE', IMAGE_TITRE); -$smarty->assign('use_nav_js', file_exists($_SERVER['DOCUMENT_ROOT'] . '/nav/nav.js')); +$smarty->assign('use_nav_js', is_file($_SERVER['DOCUMENT_ROOT'] . '/nav/nav.js')); $smarty->assign('locale', $locale); $smarty->assign('langs', $ALLOWED_LANGUAGES); $smarty->assign('date_format', $date_format); diff --git a/buildlang.php b/buildlang.php new file mode 100644 index 0000000000000000000000000000000000000000..9677f405d832727eee21053abc4e5a739f8661be --- /dev/null +++ b/buildlang.php @@ -0,0 +1,46 @@ +<?php +include_once __DIR__ . '/app/inc/init.php'; +?> +<html> +<head> + <meta charset="utf-8"/> +</head> +<body><pre><?php + + $goodLang = $_GET['good']; + $otherLang = $_GET['other']; + + $good = json_decode(file_get_contents(__DIR__ . '/locale/' . $goodLang . '.json'), true); + $other = json_decode(file_get_contents(__DIR__ . '/locale/' . $otherLang . '.json'), true); + + foreach ($good as $sectionName => $section) { + foreach ($section as $key => $value) { + $good[$sectionName][$key] = getFromOther($other, $key, $value, $otherLang); + } + } + + echo json_encode($good, JSON_PRETTY_PRINT | ~(JSON_ERROR_UTF8 | JSON_HEX_QUOT | JSON_HEX_APOS)); + + function getFromOther($other, $goodKey, $default, $otherLang) { + foreach ($other as $sectionName => $section) { + foreach ($section as $key => $value) { + if ( + strtolower($key) === strtolower($goodKey) || + strtolower(trim($key)) === strtolower($goodKey) || + strtolower(substr($key, 0, strlen($key) - 1)) === strtolower($goodKey) || + strtolower(trim(substr(trim($key), 0, strlen($key) - 1))) === strtolower($goodKey) + ) { + return $value; + } + } + } + + echo '[-]' . $goodKey . "\n"; + + return strtoupper($otherLang) . '_' . $default; + } + + ?> +</pre> +</body> +</html> diff --git a/compare.php b/compare.php new file mode 100644 index 0000000000000000000000000000000000000000..aa780a4a772da52b1635d9822cdb2f2f9770c8b3 --- /dev/null +++ b/compare.php @@ -0,0 +1,69 @@ +<?php +include_once __DIR__ . '/app/inc/init.php'; +?> +<html> +<head> + <meta charset="utf-8"/> +</head> +<body><pre><?php + + $goodLang = $_GET['good']; + $testLang = $_GET['test']; + + $good = json_decode(file_get_contents(__DIR__ . '/locale/' . $goodLang . '.json'), true); + $test = json_decode(file_get_contents(__DIR__ . '/locale/' . $testLang . '.json'), true); + + $diffSection = false; + + foreach ($good as $sectionName => $section) { + if (!isset($test[$sectionName])) { + echo '- section: ' . $sectionName . "\n"; + $diffSection = true; + } + } + foreach ($test as $sectionName => $section) { + if (!isset($good[$sectionName])) { + echo '+ section: ' . $sectionName . "\n"; + $diffSection = true; + } + } + + if (!$diffSection and array_keys($good)!=array_keys($test)) { + var_dump(array_keys($good)); + var_dump(array_keys($test)); + } else { + echo 'All sections are in two langs.' . "\n"; + } + + + $diff = array(); + + foreach ($good as $sectionName => $section) { + $diffSection = false; + foreach($section as $key=>$value) { + if (!isset($test[$sectionName][$key])) { + $diff[$sectionName]['-'][] = $key; + $diffSection = true; + } + } + + if (!$diffSection and array_keys($good[$sectionName]) != array_keys($test[$sectionName])) { + $diff[$sectionName]['order_good'] = array_keys($good[$sectionName]); + $diff[$sectionName]['order_test'] = array_keys($test[$sectionName]); + } + } + + foreach ($test as $sectionName => $section) { + foreach($section as $key=>$value) { + if (!isset($good[$sectionName][$key])) { + $diff[$sectionName]['+'][] = $key; + } + } + } + if (count($diff) > 0) { + var_dump($diff); + } + ?> +</pre> +</body> +</html> diff --git a/create_classic_poll.php b/create_classic_poll.php index 0df4a69a82b3d4002225399cef2f2c957c62596e..87c5d249a36b9b904aa894c34133dd25c300e4c6 100644 --- a/create_classic_poll.php +++ b/create_classic_poll.php @@ -32,7 +32,7 @@ $pollService = new PollService($connect, $logService); $mailService = new MailService($config['use_smtp']); $purgeService = new PurgeService($connect, $logService); -if (file_exists('bandeaux_local.php')) { +if (is_file('bandeaux_local.php')) { include_once('bandeaux_local.php'); } else { include_once('bandeaux.php'); diff --git a/index.php b/index.php index 364c90c3ef2dfa5a65d3ecf523150f93112f897a..8ee6b6f9eb7d596c65a597183e49ab6d18ceba9d 100644 --- a/index.php +++ b/index.php @@ -18,9 +18,15 @@ */ use Framadate\Services\PollService; +use Framadate\Utils; include_once __DIR__ . '/app/inc/init.php'; +if (!is_file(CONF_FILENAME)) { + header(('Location: ' . Utils::get_server_name() . 'admin/install.php')); + exit; +} + /* SERVICES */ /* -------- */ $logService = '\Framadate\Services\LogService'; diff --git a/install/InstallComposer.php b/install/InstallComposer.php deleted file mode 100644 index a370f9580ab866322595aac5f78970a4fe5d30c4..0000000000000000000000000000000000000000 --- a/install/InstallComposer.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php - -class InstallComposer -{ - /** - * @var string - */ - private $composer; - - /** - * @return bool - */ - public function check() - { - return file_exists(dirname(__DIR__).'/vendor/autoload.php'); - } - - public function install() - { - require_once 'phar://'.$this->getComposer().'/src/bootstrap.php'; - - $this->initEnv(); - - $application = new \Composer\Console\Application(); - $application->setAutoExit(false); - - $input = new \Symfony\Component\Console\Input\ArrayInput(array( - 'command' => 'install', - '-d' => __DIR__.'/..', - '-vvv', - '--optimize-autoloader', - )); - $output = new \Symfony\Component\Console\Output\NullOutput(); - - $application->run($input, $output); - } - - /** - * @return string - */ - private function getComposer() - { - if (null === $this->composer) { - $this->initComposer(); - } - - return $this->composer; - } - - private function initComposer() - { - // Composer exist ? - $locations = array( - __DIR__.'/../composer.phar', - '/usr/bin/composer.phar', - '/usr/local/bin/composer.phar', - ); - - $this->composer = null; - foreach ($locations as $location) { - if (file_exists($location) === true) { - $this->composer = $location; - break; - } - } - - // If composer not found, download it ! - if (null === $this->composer) { - if (!file_put_contents( - __DIR__.'/../composer.phar', - file_get_contents('https://getcomposer.org/composer.phar') - ) - ) { - throw new \Exception('Impossible to download composer'); - } - - $this->composer = __DIR__.'/../composer.phar'; - } - } - - private function initEnv() - { - $composer_home = getenv('COMPOSER_HOME'); - $personal_home = getenv('HOME'); - if (empty($composer_home) === true && empty($personal_home) === true) { - putenv('COMPOSER_HOME='.sys_get_temp_dir()); - } - } - -} diff --git a/install/InstallConfiguration.php b/install/InstallConfiguration.php deleted file mode 100644 index 3595312e98e1c78d234833fc1c769f079b7a8dba..0000000000000000000000000000000000000000 --- a/install/InstallConfiguration.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php - -class InstallConfiguration -{ - /** - * @var array - */ - private $datas; - - /** - * @var array - */ - private $checks = array( - 'title' => 'Application name', - 'email' => 'email address', - 'no-reply-email' => 'no-reply@mydomain.com', - 'db-name' => 'database name', - 'db-user' => 'database user', - 'db-pass' => 'database password', - 'db-host' => 'database server', - 'db-type' => 'database type', - ); - - /** - * @param array $datas - */ - public function __construct(array $datas) - { - $this->datas = $datas; - } - - /** - * @return bool - */ - public function checkValues() - { - foreach (array_keys($this->checks) as $key) { - if (isset($this->datas[$key]) === false) { - return false; - } - } - - return true; - } - - public function copy($template, $destination) - { - $configuration = file_get_contents($template); - if (false === $configuration) { - throw new \Exception('Impossible to read template configuration'); - } - - $configuration = $this->convertConfigurationFile($configuration); - - if (file_put_contents($destination, $configuration) === false) { - throw new \Exception('Impossible to save configuration'); - } - } - - - private function convertConfigurationFile($content) - { - foreach ($this->checks as $replace => $search) { - $content = str_replace( - '\'<'.$search.'>\'', - var_export($this->datas[$replace], true), - $content - ); - } - - return $content; - } -} diff --git a/install/InstallSql.php b/install/InstallSql.php deleted file mode 100644 index 749767b24b40841da6df73571ad8cf37356b10d8..0000000000000000000000000000000000000000 --- a/install/InstallSql.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -class InstallSql -{ - public function inject() - { - require_once __DIR__.'/../app/inc/init.php'; - - if ($connect->ErrorMsg() !== '') { - throw new \Exception('Bad database configuration : '.$connect->ErrorMsg()); - } - - $sqls = explode("\n", file_get_contents(__DIR__.'/install.mysql.auto.sql')); - foreach ($sqls as $sql) { - $sql = trim($sql); - if (empty($sql) === true) { - continue; - } - - $query = $connect->Prepare($sql); - $cleaning = $connect->Execute($query); - } - } -} diff --git a/install/error.html b/install/error.html deleted file mode 100644 index c6dc5ba17190d3a792eafe1e050a4641df1d8fd7..0000000000000000000000000000000000000000 --- a/install/error.html +++ /dev/null @@ -1,33 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8" /> - <title>OpenSondage Installation</title> - <link rel="stylesheet" href="../css/bootstrap.min.css"> - <link rel="stylesheet" href="../css/style.css"> - <link rel="stylesheet" href="../css/frama.css"> - <link rel="stylesheet" href="install.css"> - </head> - <body> - <div class="container ombre"> - <header role="banner"> - <h1> - <img src="../images/logo-framadate.png" width="360" height="50" alt="Framadate" /> - </h1> - <h2>Make your polls</h2> - <hr class="trait" role="presentation"> - </header> - <main role="main"> - <h3>Framadate Installation</h3> - <div class="alert alert-danger" role="alert"> - <?php echo htmlspecialchars($e->getMessage(), ENT_COMPAT | ENT_HTML401, 'UTF-8') ?> - </div> - <div class="alert alert-info" role="alert"> - <pre> - <?php echo htmlspecialchars($e->getTraceAsString(), ENT_COMPAT | ENT_HTML401, 'UTF-8') ?> - </pre> - </div> - </main> - </div> - </body> -</html> diff --git a/install/install.css b/install/install.css deleted file mode 100644 index 18f3dc539ee9ec75f531f15e039821948e604e6e..0000000000000000000000000000000000000000 --- a/install/install.css +++ /dev/null @@ -1,11 +0,0 @@ -header { - padding-bottom: 0; -} - -main { - padding-top: 0; -} - -fieldset { - margin: 1.5em 0; -} \ No newline at end of file diff --git a/install/install.html b/install/install.html deleted file mode 100644 index 1caa3af2c9c9e3764280be3595520e9d459f1a5f..0000000000000000000000000000000000000000 --- a/install/install.html +++ /dev/null @@ -1,72 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8" /> - <title>OpenSondage Installation</title> - <link rel="stylesheet" href="../css/bootstrap.min.css"> - <link rel="stylesheet" href="../css/style.css"> - <link rel="stylesheet" href="../css/frama.css"> - <link rel="stylesheet" href="install.css"> - </head> - <body> - <div class="container ombre"> - <header role="banner"> - <h1> - <img src="../images/logo-framadate.png" width="360" height="50" alt="Framadate" /> - </h1> - <h2>Make your polls</h2> - <hr class="trait" role="presentation"> - </header> - <main role="main"> - <h3>Framadate Installation</h3> - <form action="" method="post" role="form"> - <fieldset> - <legend>General</legend> - - <div class="form-group"> - <label for="title">Title</label> - <input type="text" class="form-control" id="title" name="title" placeholder="Application name" required> - </div> - <div class="form-group"> - <label for="email">Administrator email</label> - <input type="email" class="form-control" id="email" name="email" placeholder="Email of the administrator" required> - </div> - <div class="form-group"> - <label for="no-reply-email">No-reply email</label> - <input type="email" class="form-control" id="no-reply-email" name="no-reply-email" placeholder="Email for automatic responses" required> - </div> - </fieldset> - <fieldset> - <legend>Database</legend> - - <div class="form-group"> - <label for="db-type">Type</label> - <select name="db-type" id="db-type" required> - <option value="pdo">PDO - MySQL (recommanded)</option> - <option value="mysql">MySQL</option> - </select> - </div> - <div class="form-group"> - <label for="db-host">Host</label> - <input type="text" class="form-control" id="db-host" name="db-host" value="localhost" required> - </div> - <div class="form-group"> - <label for="db-name">Database name</label> - <input type="text" class="form-control" id="db-name" name="db-name" value="opensondage" required> - </div> - <div class="form-group"> - <label for="db-user">Username</label> - <input type="text" class="form-control" id="db-user" name="db-user" value="root" required> - </div> - <div class="form-group"> - <label for="db-pass">Password</label> - <input type="password" class="form-control" id="db-pass" name="db-pass" value=""> - </div> - </fieldset> - - <input type="submit" class="btn btn-success" name="install" value="Install"> - </form> - </main> - </div> - </body> -</html> diff --git a/install/install.mysql.auto.sql b/install/install.mysql.auto.sql deleted file mode 100644 index a42245e12f6a0a91f9733597c046827754409098..0000000000000000000000000000000000000000 --- a/install/install.mysql.auto.sql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE TABLE IF NOT EXISTS `comments` (`id_comment` int(11) unsigned NOT NULL AUTO_INCREMENT, `id_sondage` char(16) NOT NULL, `comment` text NOT NULL, `usercomment` text, PRIMARY KEY (`id_comment`), KEY `id_sondage` (`id_sondage`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE IF NOT EXISTS `sondage` (`id_sondage` char(16) NOT NULL, `commentaires` text, `mail_admin` varchar(128) DEFAULT NULL, `nom_admin` varchar(64) DEFAULT NULL, `titre` text, `id_sondage_admin` char(24) DEFAULT NULL, `date_creation` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `date_fin` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `format` varchar(2) DEFAULT NULL, `mailsonde` tinyint(1) DEFAULT '0', `statut` int(11) NOT NULL DEFAULT '1' COMMENT '1 = actif ; 0 = inactif ; ', UNIQUE KEY `id_sondage` (`id_sondage`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE IF NOT EXISTS `sujet_studs` (`id_sondage` char(16) NOT NULL, `sujet` text, KEY `id_sondage` (`id_sondage`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE IF NOT EXISTS `user_studs` (`id_users` int(11) unsigned NOT NULL AUTO_INCREMENT, `nom` varchar(64) NOT NULL, `id_sondage` char(16) NOT NULL, `reponses` text NOT NULL, PRIMARY KEY (`id_users`), KEY `id_sondage` (`id_sondage`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ; - -INSERT INTO `sondage` (`id_sondage`, `commentaires`, `mail_admin`, `nom_admin`, `titre`, `id_sondage_admin`, `date_fin`, `format`) VALUES ('aqg259dth55iuhwm','Repas de Noel du service','Stephanie@retaillard.com','Stephanie', 'Repas de Noel','aqg259dth55iuhwmy9d8jlwk', FROM_UNIXTIME('1627100361'),'D+'); -INSERT INTO `sujet_studs` (`id_sondage`, `sujet`) VALUES ('aqg259dth55iuhwm','1225839600@12h,1225839600@19h,1226012400@12h,1226012400@19h,1226876400@12h,1226876400@19h,1227049200@12h,1227049200@19h,1227826800@12h,1227826800@19h'); -INSERT INTO `user_studs` (`nom`, `id_sondage`, `reponses`, `id_users`) VALUES ('marcel','aqg259dth55iuhwm','0110111101','933'), ('paul','aqg259dth55iuhwm','1011010111','935'), ('sophie','aqg259dth55iuhwm','1110110000','945'), ('barack','aqg259dth55iuhwm','0110000','948'), ('takashi','aqg259dth55iuhwm','0000110100','951'), ('albert','aqg259dth55iuhwm','1010110','975'), ('alfred','aqg259dth55iuhwm','0110010','1135'), ('marcs','aqg259dth55iuhwm','0100001010','1143'), ('laure','aqg259dth55iuhwm','0011000','1347'), ('benda','aqg259dth55iuhwm','1101101100','1667'), ('Albert','aqg259dth55iuhwm','1111110011','1668'); diff --git a/install/install.mysql.sql b/install/install.mysql.sql deleted file mode 100644 index aa0354cf984784bb559f1586a622202019f47781..0000000000000000000000000000000000000000 --- a/install/install.mysql.sql +++ /dev/null @@ -1,112 +0,0 @@ --- -------------------------------------------------------- - --- --- Table structure `poll` --- - -CREATE TABLE IF NOT EXISTS `poll` ( - `id` CHAR(16) NOT NULL, - `admin_id` CHAR(24) NOT NULL, - `title` TEXT NOT NULL, - `description` TEXT, - `admin_name` VARCHAR(64) DEFAULT NULL, - `admin_mail` VARCHAR(128) DEFAULT NULL, - `creation_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - `end_date` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', - `format` VARCHAR(1) DEFAULT NULL, - `editable` TINYINT(1) DEFAULT '0', - `receiveNewVotes` TINYINT(1) DEFAULT '0', - `active` TINYINT(1) DEFAULT '1', - PRIMARY KEY (`id`) -) - ENGINE = InnoDB - DEFAULT CHARSET = utf8; - --- -------------------------------------------------------- - --- --- Table structure `slot` --- - -CREATE TABLE IF NOT EXISTS `slot` ( - `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, - `poll_id` CHAR(16) NOT NULL, - `title` TEXT, - `moments` TEXT, - PRIMARY KEY (`id`), - KEY `poll_id` (`poll_id`) -) - ENGINE = InnoDB - DEFAULT CHARSET = utf8; - --- -------------------------------------------------------- - --- --- Table structure `comment` --- - -CREATE TABLE IF NOT EXISTS `comment` ( - `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, - `poll_id` CHAR(16) NOT NULL, - `name` TEXT, - `comment` TEXT NOT NULL, - PRIMARY KEY (`id`), - KEY `poll_id` (`poll_id`) -) - ENGINE = InnoDB - DEFAULT CHARSET = utf8; - --- -------------------------------------------------------- - --- --- Table structure `vote` --- - -CREATE TABLE IF NOT EXISTS `vote` ( - `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, - `poll_id` CHAR(16) NOT NULL, - `name` VARCHAR(64) NOT NULL, - `choices` TEXT NOT NULL, - PRIMARY KEY (`id`), - KEY `poll_id` (`poll_id`) -) - ENGINE = InnoDB - DEFAULT CHARSET = utf8; - - --- --- Data for Name: poll; Type: TABLE DATA; --- - -INSERT INTO `poll` -(`id`, `description`, `admin_mail`, `admin_name`, `title`, `admin_id`, `end_date`, `format`) -VALUES - ('aqg259dth55iuhwm', 'Repas de Noel du service', 'Stephanie@retaillard.com', 'Stephanie', 'Repas de Noel', - 'aqg259dth55iuhwmy9d8jlwk', FROM_UNIXTIME('1627100361'), 'D'); - --- --- Data for Name: slot; Type: TABLE DATA; --- - -INSERT INTO `slot` (`poll_id`, `title`, `moments`) VALUES - ('aqg259dth55iuhwm', '1225839600', '12h,19h'), - ('aqg259dth55iuhwm', '1226012400', '12h,19h'), - ('aqg259dth55iuhwm', '1226876400', '12h,19h'), - ('aqg259dth55iuhwm', '1227826800', '12h,19h'); - --- --- Data for Name: vote; Type: TABLE DATA; --- - -INSERT INTO `vote` (`name`, `poll_id`, `choices`) VALUES - ('marcel', 'aqg259dth55iuhwm', '02202222'), - ('paul', 'aqg259dth55iuhwm', '20220202'), - ('sophie', 'aqg259dth55iuhwm', '22202200'), - ('barack', 'aqg259dth55iuhwm', '02200000'), - ('takashi', 'aqg259dth55iuhwm', '00002202'), - ('albert', 'aqg259dth55iuhwm', '20202200'), - ('alfred', 'aqg259dth55iuhwm', '02200200'), - ('marcs', 'aqg259dth55iuhwm', '02000020'), - ('laure', 'aqg259dth55iuhwm', '00220000'), - ('benda', 'aqg259dth55iuhwm', '22022022'), - ('albert', 'aqg259dth55iuhwm', '22222200'); diff --git a/install/install.php b/install/install.php deleted file mode 100644 index 8cf9f3f9b13cdf0a390875d4cbe1549969d1bb20..0000000000000000000000000000000000000000 --- a/install/install.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -require_once __DIR__.'/InstallComposer.php'; -require_once __DIR__.'/InstallConfiguration.php'; -require_once __DIR__.'/InstallSql.php'; - -$configuration_file = __DIR__.'/../app/inc/constants.php'; - -if (file_exists($configuration_file) === true) { - header('Location: ../index.php'); - exit; -} - -if (isset($_POST['install']) === true) { - try { - // Composer installation - $composer = new InstallComposer(); - if ($composer->check() === false) { - ini_set('max_execution_time', 0); - $composer->install(); - } - - // Save configuration - $configuration = new InstallConfiguration($_POST); - if ($configuration->checkValues() === false) { - throw new \Exception('Bad value for configuration'); - } - - $configuration->copy($configuration_file.'.template', $configuration_file); - - // Inject database - $sql = new InstallSql(); - $sql->inject(); - - header('Location: ../index.php'); - die(); - } catch (Exception $e) { - require_once __DIR__.'/error.html'; - die(); - } -} - -require_once __DIR__.'/install.html'; diff --git a/locale/de.json b/locale/de.json index f33b3aca3a55e59a04f8ba5c9673469c453ce569..a6d180d636c433f179bdbcfe79f9f7a7acdd8648 100644 --- a/locale/de.json +++ b/locale/de.json @@ -261,6 +261,7 @@ "Migration": "Migration", "Purge": "Säuberung", "Logs": "Verlauf", + "Installation": "Installation", "Poll ID": "Umfrage-ID", "Format": "Format", "Title": "Titel", diff --git a/locale/en.json b/locale/en.json index 8f0dbe7fa557ceeef41b2bb614703cf59b722852..2edcb2b51ef02d60d247c7690c6d4ab25d948cf4 100644 --- a/locale/en.json +++ b/locale/en.json @@ -259,6 +259,7 @@ "Migration": "Migration", "Purge": "Purge", "Logs": "Logs", + "Installation": "Installation", "Poll ID": "Poll ID", "Format": "Format", "Title": "Title", diff --git a/locale/es.json b/locale/es.json index fbb6c6b86025bb946529eecead0f32d279f173de..763559024e5693968cd3b9694164e3f1cc5a5bc2 100644 --- a/locale/es.json +++ b/locale/es.json @@ -261,6 +261,7 @@ "Migration": "ES_Migration", "Purge": "ES_Purge", "Logs": "Histórico", + "Installation": "Instalación", "Poll ID": "ES_ID sondage", "Format": "ES_Format", "Title": "ES_Titre", diff --git a/locale/fr.json b/locale/fr.json index 7e420b5fb914ebe1e0dd51f8a0af201a81a5e3fe..4c267f0ba303aeca566c9ab25ab2d1dfe8603364 100644 --- a/locale/fr.json +++ b/locale/fr.json @@ -36,7 +36,8 @@ "Choice": "Choix", "Link": "Lien", "Search": "Chercher", - "Creation date:": "Date de création :" + "Creation date:": "Date de création :", + "ASTERISK": "*" }, "Date": { "dd/mm/yyyy": "jj/mm/aaaa", @@ -261,6 +262,7 @@ "Migration": "Migration", "Purge": "Purge", "Logs": "Historique", + "Installation": "Installation", "Poll ID": "ID sondage", "Format": "Format", "Title": "Titre", @@ -309,6 +311,21 @@ "Author's message": "Réservé à l'auteur", "For sending to the polled users": "Pour diffusion aux sondés" }, + "Installation": { + "AppMail": "Adresse mail de l'application", + "AppName": "Nom de l'application", + "CleanUrl": "URL propres", + "Database": "Base de données", + "DbConnectionString": "Chaîne de connexion", + "DbPassword": "Mot de passe", + "DbPrefix": "Préfixe", + "DbUser": "Utilisateur", + "DefaultLanguage": "Langue par défaut", + "General": "Général", + "Install": "Installer", + "MigrationTable": "Table de migration", + "ResponseMail": "Mail de réponse" + }, "Error": { "Error!": "Erreur !", "Enter a title": "Il faut saisir un titre !", @@ -333,6 +350,8 @@ "Adding vote failed": "Ajout d'un vote échoué", "Comment failed": "Commentaire échoué", "You can't create a poll with hidden results with the following edition option:": "Vous ne pouvez pas créer de sondage avec résulats cachés avec les options d'éditions suivantes : ", - "Failed to delete column": "Échec de la suppression de colonne" + "Failed to delete column": "Échec de la suppression de colonne", + "MISSING_VALUES": "Il manque des valeurs", + "CANT_CONNECT_TO_DATABASE": "Impossible de se connecter à la base de données" } } diff --git a/locale/it.json b/locale/it.json index 977f254ae14dd5e5dcdf232cad2bda9a6e39551d..904efa694f76a265baf1f4416a671c38168313ff 100644 --- a/locale/it.json +++ b/locale/it.json @@ -261,6 +261,7 @@ "Migration": "IT_Migration", "Purge": "IT_Purge", "Logs": "Log", + "Installation": "Installazione", "Poll ID": "ID sondaggio", "Format": "Formato", "Title": "Titolo", diff --git a/po2json.php b/po2json.php new file mode 100644 index 0000000000000000000000000000000000000000..07b77b78622ce32f9300c937ce87c14e574d76b6 --- /dev/null +++ b/po2json.php @@ -0,0 +1,15 @@ +<?php +include_once __DIR__ . '/app/inc/init.php'; +?> +<html> +<head> + <meta charset="utf-8"/> +</head> +<body><pre><?php +$lang = 'fr_FR'; +$po = file_get_contents(__DIR__ . '/locale/' . $lang . '/LC_MESSAGES/Studs.po'); +$converter = new \o80\convert\Po2JsonConverter(); +$json = $converter->convert($po); +print_r($json); +?></pre></body> +</html> diff --git a/tpl/admin/config.tpl b/tpl/admin/config.tpl new file mode 100644 index 0000000000000000000000000000000000000000..3254e91968421c01c9b93a6878498c3b25e4ef6b --- /dev/null +++ b/tpl/admin/config.tpl @@ -0,0 +1,89 @@ +<?php +/** + * This software is governed by the CeCILL-B license. If a copy of this license + * is not distributed with this file, you can obtain one at + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt + * + * Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ + * Authors of Framadate/OpenSondate: Framasoft (https://github.com/framasoft) + * + * ============================= + * + * Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence + * ne se trouve pas avec ce fichier vous pouvez l'obtenir sur + * http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt + * + * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ + * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) + */ + +// Fully qualified domain name of your webserver. +// If this is unset or empty, the servername is determined automatically. +// You *have to set this* if you are running Framedate behind a reverse proxy. +// const APP_URL = '<www.mydomain.fr>'; + +// Application name +const NOMAPPLICATION = '{$appName}'; + +// Database administrator email +const ADRESSEMAILADMIN = '{$appMail}'; + +// Email for automatic responses (you should set it to "no-reply") +const ADRESSEMAILREPONSEAUTO = '{$responseMail}'; + +// Database server name, leave empty to use a socket +const DB_CONNECTION_STRING = '{$dbConnectionString}'; + +// Database user +const DB_USER= '{$dbUser}'; + +// Database password +const DB_PASSWORD = '{$dbPassword}'; + +// Table name prefix +const TABLENAME_PREFIX = '{$dbPrefix}'; + +// Name of the table that store migration script already executed +const MIGRATION_TABLE = '{$migrationTable}'; + +// Default Language +const DEFAULT_LANGUAGE = '{$defaultLanguage}'; + +// List of supported languages, fake constant as arrays can be used as constants only in PHP >=5.6 +$ALLOWED_LANGUAGES = [ + 'fr' => 'Français', + 'en' => 'English', + 'es' => 'Español', + 'de' => 'Deutsch', + 'it' => 'Italiano', +]; + +// Nom et emplacement du fichier image contenant le titre +const IMAGE_TITRE = 'images/logo-framadate.png'; + +// Clean URLs, boolean +const URL_PROPRE = {if in_array($cleanUrl, array('1', 'on', 'true'))}true{else}false{/if}; + +// Use REMOTE_USER data provided by web server +const USE_REMOTE_USER = true; + +// Path to the log file +const LOG_FILE = 'admin/stdout.log'; + +// Days (after expiration date) before purge a poll +const PURGE_DELAY = 60; + +// Config +$config = [ + /* general config */ + 'use_smtp' => true, // use email for polls creation/modification/responses notification + /* home */ + 'show_what_is_that' => true, // display "how to use" section + 'show_the_software' => true, // display technical information about the software + 'show_cultivate_your_garden' => true, // display "developpement and administration" information + /* create_classic_poll.php / create_date_poll.php */ + 'default_poll_duration' => 180, // default values for the new poll duration (number of days). + /* create_classic_poll.php */ + 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. +]; + diff --git a/tpl/admin/install.tpl b/tpl/admin/install.tpl new file mode 100644 index 0000000000000000000000000000000000000000..38f613cc5bcaaffcbc3db3cd95c8b32960e4a5b1 --- /dev/null +++ b/tpl/admin/install.tpl @@ -0,0 +1,102 @@ +{extends 'admin/admin_page.tpl'} + +{block 'main'} +<div class="row"> + <div class="col-md-12"> + <form action="" method="POST"> + + {if $error} + <div id="result" class="alert alert-danger">{$error}</div> + {/if} + + <fieldset> + <legend>{__('Installation', 'General')}</legend> + <div class="form-group"> + <div class="form-group"> + <div class="input-group"> + <label for="appName" class="input-group-addon">{__('Generic', 'ASTERISK')} {__('Installation', 'AppName')}</label> + <input type="text" class="form-control" id="appName" name="appName" value="{$fields['appName']}" autofocus required> + </div> + </div> + + <div class="form-group"> + <div class="input-group"> + <label for="appMail" class="input-group-addon">{__('Generic', 'ASTERISK')} {__('Installation', 'AppMail')}</label> + <input type="email" class="form-control" id="appMail" name="appMail" value="{$fields['appMail']}" required> + </div> + </div> + + <div class="form-group"> + <div class="input-group"> + <label for="responseMail" class="input-group-addon">{__('Installation', 'ResponseMail')}</label> + <input type="email" class="form-control" id="responseMail" name="responseMail" value="{$fields['responseMail']}"> + </div> + </div> + + <div class="form-group"> + <div class="input-group"> + <label for="defaultLanguage" class="input-group-addon">{__('Generic', 'ASTERISK')} {__('Installation', 'DefaultLanguage')}</label> + <select type="email" class="form-control" id="defaultLanguage" name="defaultLanguage" required> + {foreach $langs as $lang=>$label} + <option value="{$lang}" {if $lang==$fields['defaultLanguage']}selected{/if}>{$label}</option> + {/foreach} + </select> + </div> + </div> + + <div class="input-group"> + <label for="cleanUrl" class="input-group-addon">{__('Installation', 'CleanUrl')}</label> + + <div class="form-control"> + <input type="checkbox" id="cleanUrl" name="cleanUrl" {($fields['cleanUrl']) ? 'checked' : ''}> + </div> + </div> + </div> + </fieldset> + + <fieldset> + <legend>{__('Installation', 'Database')}</legend> + <div class="form-group"> + <div class="input-group"> + <label for="dbConnectionString" class="input-group-addon">{__('Generic', 'ASTERISK')} {__('Installation', 'DbConnectionString')}</label> + <input type="text" class="form-control" id="dbConnectionString" name="dbConnectionString" value="{$fields['dbConnectionString']}" required> + </div> + </div> + + <div class="form-group"> + <div class="input-group"> + <label for="dbUser" class="input-group-addon">{__('Generic', 'ASTERISK')} {__('Installation', 'DbUser')}</label> + <input type="text" class="form-control" id="dbUser" name="dbUser" value="{$fields['dbUser']}" required> + </div> + </div> + + <div class="form-group"> + <div class="input-group"> + <label for="dbPassword" class="input-group-addon">{__('Installation', 'DbPassword')}</label> + <input type="password" class="form-control" id="dbPassword" name="dbPassword" value="{$fields['dbPassword']}"> + </div> + </div> + + <div class="form-group"> + <div class="input-group"> + <label for="dbPrefix" class="input-group-addon">{__('Installation', 'DbPrefix')}</label> + <input type="text" class="form-control" id="dbPrefix" name="dbPrefix" value="{$fields['dbPrefix']}"> + </div> + </div> + + <div class="form-group"> + <div class="input-group"> + <label for="migrationTable" class="input-group-addon">{__('Generic', 'ASTERISK')} {__('Installation', 'MigrationTable')}</label> + <input type="text" class="form-control" id="migrationTable" name="migrationTable" value="{$fields['migrationTable']}" required> + </div> + </div> + </fieldset> + + <div class="text-center form-group"> + <button type="submit" class="btn btn-primary">{__('Installation', 'Install')}</button> + </div> + + </form> + </div> +</div> +{/block} diff --git a/tpl/create_poll.tpl b/tpl/create_poll.tpl index c064dbf72353264cf590ee8a85e6881335dba21f..a298396d8a1fca243e1b6a19631bc7384c4fb3c0 100644 --- a/tpl/create_poll.tpl +++ b/tpl/create_poll.tpl @@ -96,10 +96,6 @@ <div class="form-group"> <div class="col-sm-offset-4 col-sm-8"> <div class="radio"> - <label> - <input type="radio" name="editable" {if empty($poll_editable) or $poll_editable==constant("Framadate\Editable::NOT_EDITABLE")}checked{/if} value="{constant("Framadate\Editable::NOT_EDITABLE")}"> - {__('Step 1', 'Votes cannot be modified.')} - </label> <label> <input type="radio" name="editable" id="editableByAll" {if $poll_editable==constant("Framadate\Editable::EDITABLE_BY_ALL")}checked{/if} value="{constant("Framadate\Editable::EDITABLE_BY_ALL")}"> {__('Step 1', 'All voters can modify any vote')} @@ -108,6 +104,10 @@ <input type="radio" name="editable" {if $poll_editable==constant("Framadate\Editable::EDITABLE_BY_OWN")}checked{/if} value="{constant("Framadate\Editable::EDITABLE_BY_OWN")}"> {__('Step 1', 'Voters can modify their vote themselves')} </label> + <label> + <input type="radio" name="editable" {if empty($poll_editable) or $poll_editable==constant("Framadate\Editable::NOT_EDITABLE")}checked{/if} value="{constant("Framadate\Editable::NOT_EDITABLE")}"> + {__('Step 1', 'Votes cannot be modified.')} + </label> </div> </div> </div>