diff --git a/.env.dist b/.env.dist
new file mode 100644
index 0000000..5e1fedc
--- /dev/null
+++ b/.env.dist
@@ -0,0 +1,24 @@
+# This file is a "template" of which env vars need to be defined for your application
+# Copy this file to .env file for development, create environment variables when deploying to production
+# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
+
+###> symfony/framework-bundle ###
+APP_ENV=dev
+APP_SECRET=e168e005fbbc528f5e4f8b75a0dffce8
+#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
+#TRUSTED_HOSTS=localhost,example.com
+###< symfony/framework-bundle ###
+
+###> symfony/swiftmailer-bundle ###
+# For Gmail as a transport, use: "gmail://username:password@localhost"
+# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
+# Delivery is disabled by default via "null://localhost"
+MAILER_URL=null://localhost
+###< symfony/swiftmailer-bundle ###
+
+###> doctrine/doctrine-bundle ###
+# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
+# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
+# Configure your db driver and server_version in config/packages/doctrine.yaml
+DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
+###< doctrine/doctrine-bundle ###
diff --git a/.gitignore b/.gitignore
index 69538d1..0348fcb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,21 +6,30 @@ composer.phar
framanav
nav
app/inc/config.php
-vendor
cache/
tpl_c/
-.php_cs.cache
.zanata-cache/
-# Temp files
-*~
-\#*\#
+cover/
-# Cache
-Thumbs.db
+###> symfony/framework-bundle ###
+.env
+/public/bundles/
+/var/
+/vendor/
+###< symfony/framework-bundle ###
-# IDE
-.settings/
-.project
-.idea/
-*.iml
+###> symfony/webpack-encore-pack ###
+/node_modules/
+/public/build/
+###< symfony/webpack-encore-pack ###
+
+###> symfony/phpunit-bridge ###
+.phpunit
+/phpunit.xml
+###< symfony/phpunit-bridge ###
+
+###> friendsofphp/php-cs-fixer ###
+/.php_cs
+/.php_cs.cache
+###< friendsofphp/php-cs-fixer ###
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0a1f14f..4d7c1d3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: framasoft/framadate-ci
+image: tcitworld/framadate-sf4-ci
stages:
- test
- deploy
@@ -8,11 +8,29 @@ stages:
# Run php-cs-fixer and phpunit on all branches
test:
stage: test
+ services:
+ - mysql:latest
+ variables:
+ MYSQL_DATABASE: framadate
+ MYSQL_ROOT_PASSWORD: framadate_password
+ APP_ENV: test
+ APP_SECRET: e168e005fbbc9b6f5e4f8b15a0dffce8
+ DATABASE_URL: mysql://root:framadate_password@mysql/framadate
+ APP_LOCALE: fr_FR
+ APP_NAME: Framadate
+ APP_ADMIN_EMAIL: tcit@tcit.fr
+ APP_SEND_EMAILS: "true"
+ APP_EMAIL_FROM_NAME: admin
+ APP_EMAIL_FROM_EMAIL: admin@domain.tld
+ APP_DEFAULT_POLL_DURATION: 180
script:
+ - npm i
+ - ./node_modules/.bin/encore production
- composer install -o --no-interaction --no-progress --prefer-dist
- - mkdir tpl_c
- - php vendor/bin/php-cs-fixer fix --verbose --dry-run
- - vendor/bin/phpunit --bootstrap app/tests/bootstrap.php --debug app/tests
+ - php vendor/bin/php-cs-fixer fix --verbose --dry-run src/
+ - bin/console doctrine:migrations:migrate --env="test"
+ - bin/console framadate:tests:fixtures --env="test"
+ - bin/phpunit --debug --coverage-text --colors=never
cache:
paths:
- vendor/
@@ -51,7 +69,9 @@ pages:
paths:
- public
only:
- - master
+ - tags
+ except:
+ - (beta|alpha)
# Deploy on develop
beta:
diff --git a/.php_cs b/.php_cs
deleted file mode 100644
index 30f2c6a..0000000
--- a/.php_cs
+++ /dev/null
@@ -1,45 +0,0 @@
-setRiskyAllowed(true)
- ->setRules([
- 'array_syntax' => [
- 'syntax' => 'short'
- ],
- 'combine_consecutive_unsets' => true,
- 'heredoc_to_nowdoc' => true,
- 'no_extra_consecutive_blank_lines' => [
- 'break',
- 'continue',
- 'extra',
- 'return',
- 'throw',
- 'use',
- 'parenthesis_brace_block',
- 'square_brace_block',
- 'curly_brace_block'
- ],
- 'no_unreachable_default_argument_value' => true,
- 'no_useless_else' => true,
- 'no_useless_return' => true,
- 'ordered_class_elements' => true,
- 'ordered_imports' => true,
- 'php_unit_strict' => true,
- 'phpdoc_order' => true,
- // 'psr4' => true,
- 'strict_comparison' => true,
- 'strict_param' => true,
- 'concat_space' => [
- 'spacing' => 'one'
- ],
- ])
- ->setFinder(
- PhpCsFixer\Finder::create()
- ->exclude([
- 'vendor',
- 'var',
- 'web'
- ])
- ->in(__DIR__)
- )
-;
diff --git a/Makefile b/Makefile
index 30fa4c0..772d705 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ push-locales: locales
zanata-cli -q -B push
pull-locales:
- zanata-cli -q -B pull
+ zanata-cli -q -B pull --min-doc-percent 50
./.po2json.sh
stats-locales:
diff --git a/action/add_comment.php b/action/add_comment.php
deleted file mode 100644
index df75385..0000000
--- a/action/add_comment.php
+++ /dev/null
@@ -1,95 +0,0 @@
- ['regexp' => POLL_REGEX]]);
- $poll = $pollService->findById($poll_id);
-}
-
-if (!empty($_POST['poll_admin'])) {
- $admin_poll_id = filter_input(INPUT_POST, 'poll_admin', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
- if (strlen($admin_poll_id) === 24) {
- $is_admin = ($pollService->findByAdminId($admin_poll_id) !== null);
- }
-}
-
-if (!$poll) {
- $message = new Message('error', __('Error', 'This poll doesn\'t exist !'));
-} else if ($poll && !$securityService->canAccessPoll($poll) && !$is_admin) {
- $message = new Message('error', __('Password', 'Wrong password'));
-} else {
- $name = $inputService->filterName($_POST['name']);
- $comment = $inputService->filterComment($_POST['comment']);
-
- if ($name === null) {
- $message = new Message('danger', __('Error', 'The name is invalid.'));
- }
-
- if ($message === null) {
- // Add comment
- $result = $pollService->addComment($poll_id, $name, $comment);
- if ($result) {
- $message = new Message('success', __('Comments', 'Comment added'));
- $notificationService->sendUpdateNotification($poll, NotificationService::ADD_COMMENT, $name);
- } else {
- $message = new Message('danger', __('Error', 'Comment failed'));
- }
- }
- $comments = $pollService->allCommentsByPollId($poll_id);
-}
-
-$smarty->error_reporting = E_ALL & ~E_NOTICE;
-$smarty->assign('comments', $comments);
-$comments_html = $smarty->fetch('part/comments_list.tpl');
-
-$response = ['result' => $result, 'message' => $message, 'comments' => $comments_html];
-
-echo json_encode($response);
diff --git a/action/send_edit_link_by_email_action.php b/action/send_edit_link_by_email_action.php
deleted file mode 100644
index a2ac204..0000000
--- a/action/send_edit_link_by_email_action.php
+++ /dev/null
@@ -1,94 +0,0 @@
- ['regexp' => POLL_REGEX]]);
- $poll = $pollService->findById($poll_id);
-}
-
-$token = $sessionService->get("Common", SESSION_EDIT_LINK_TOKEN);
-$token_form_value = empty($_POST['token']) ? null : $_POST['token'];
-$editedVoteUniqueId = filter_input(INPUT_POST, 'editedVoteUniqueId', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
-if (is_null($poll) || $config['use_smtp'] === false || is_null($token) || is_null($token_form_value)
- || !$token->check($token_form_value) || is_null($editedVoteUniqueId)) {
- $message = new Message('error', __('Error', 'Something is going wrong...'));
-}
-
-if (is_null($message)) {
- $email = $mailService->isValidEmail($_POST['email']);
- if (is_null($email)) {
- $message = new Message('error', __('EditLink', 'The email address is not correct.'));
- }
-}
-
-if (is_null($message)) {
- $time = $sessionService->get("Common", SESSION_EDIT_LINK_TIME);
-
- if (!empty($time)) {
- $remainingTime = TIME_EDIT_LINK_EMAIL - (time() - $time);
-
- if ($remainingTime > 0) {
- $message = new Message('error', __f('EditLink', 'Please wait %d seconds before we can send an email to you then try again.', $remainingTime));
- }
- }
-}
-
-if (is_null($message)) {
- $url = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId);
-
- $smarty->assign('poll', $poll);
- $smarty->assign('poll_id', $poll_id);
- $smarty->assign('editedVoteUniqueId', $editedVoteUniqueId);
- $body = $smarty->fetch('mail/remember_edit_link.tpl');
-
- $subject = '[' . NOMAPPLICATION . '][' . __('EditLink', 'REMINDER') . '] ' . __f('EditLink', 'Edit link for poll "%s"', $poll->title);
-
- $mailService->send($email, $subject, $body);
- $sessionService->remove("Common", SESSION_EDIT_LINK_TOKEN);
- $sessionService->set("Common", SESSION_EDIT_LINK_TIME, time());
-
- $message = new Message('success', __('EditLink', 'Your reminder has been successfully sent!'));
- $result = true;
-}
-
-$smarty->error_reporting = E_ALL & ~E_NOTICE;
-
-$response = ['result' => $result, 'message' => $message];
-
-echo json_encode($response);
diff --git a/admin/check.php b/admin/check.php
index 24a8dcc..17dabd3 100644
--- a/admin/check.php
+++ b/admin/check.php
@@ -48,7 +48,7 @@ $ALLOWED_LANGUAGES = [
'br' => 'Brezhoneg',
];
const DEFAULT_LANGUAGE = 'en';
-require_once ROOT_DIR . 'app/inc/i18n.php';
+require_once ROOT_DIR . 'app/inc/I18nWrapper.php';
/**
* Function to sort messages by type (priorise errors on warning, warning on info, etc.)
diff --git a/admin/index.php b/admin/index.php
index a669eff..477a854 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -19,6 +19,7 @@
require_once '../app/inc/init.php';
-$smarty->assign('title', __('Admin', 'Administration'));
-$smarty->assign('logsAreReadable', is_readable('../' . LOG_FILE));
-$smarty->display('admin/index.tpl');
\ No newline at end of file
+echo $twig->render('admin/index.twig', [
+ 'title' => __('Admin', 'Administration'),
+ 'logsAreReadable' => is_readable('../' . LOG_FILE),
+]);
diff --git a/admin/install.php b/admin/install.php
index 2876120..dc409eb 100644
--- a/admin/install.php
+++ b/admin/install.php
@@ -32,16 +32,17 @@ $installService = new InstallService();
if (!empty($_POST)) {
$installService->updateFields($_POST);
- $result = $installService->install($smarty);
+ $result = $installService->install($twig);
if ($result['status'] === 'OK') {
header(('Location: ' . Utils::get_server_name() . 'admin/migration.php'));
exit;
- }
+ }
$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
+echo $twig->render('admin/install.twig', [
+ 'error' => $error,
+ 'title' => __('Admin', 'Installation'),
+ 'fields' => $installService->getFields(),
+]);
diff --git a/admin/logs.php b/admin/logs.php
index 57dd9b7..9d35f2f 100644
--- a/admin/logs.php
+++ b/admin/logs.php
@@ -23,7 +23,7 @@ ob_start();
is_readable('../' . LOG_FILE) ? readfile('../' . LOG_FILE) : null;
$content = ob_get_clean();
-$smarty->assign('logs', $content);
-$smarty->assign('title', __('Admin', 'Logs'));
-
-$smarty->display('admin/logs.tpl');
\ No newline at end of file
+echo $twig->render('admin/logs.twig', [
+ 'logs' => $content,
+ 'title' => __('Admin', 'Logs'),
+]);
diff --git a/admin/migration.php b/admin/migration.php
deleted file mode 100644
index 3948909..0000000
--- a/admin/migration.php
+++ /dev/null
@@ -1,128 +0,0 @@
-allTables();
-$pdo = $connect->getPDO();
-$prefixedMigrationTable = Utils::table(MIGRATION_TABLE);
-
-if (!in_array($prefixedMigrationTable, $tables, true)) {
- $pdo->exec('
-CREATE TABLE IF NOT EXISTS `' . $prefixedMigrationTable . '` (
- `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
- `name` TEXT NOT NULL,
- `execute_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
- PRIMARY KEY (`id`)
-)
- ENGINE = MyISAM
- DEFAULT CHARSET = utf8;');
-}
-
-$selectStmt = $pdo->prepare('SELECT id FROM `' . $prefixedMigrationTable . '` WHERE name=?');
-$insertStmt = $pdo->prepare('INSERT INTO `' . $prefixedMigrationTable . '` (name) VALUES (?)');
-$countSucceeded = 0;
-$countFailed = 0;
-$countSkipped = 0;
-
-// Loop on every Migration sub classes
-$success = [];
-$fail = [];
-foreach ($migrations as $migration) {
- $className = get_class($migration);
-
- // Check if $className is a Migration sub class
- if (!$migration instanceof Migration) {
- $smarty->assign('error', 'The class ' . $className . ' is not a sub class of Framadate\\Migration\\Migration.');
- $smarty->display('error.tpl');
- exit;
- }
-
- // Check if the Migration is already executed
- $selectStmt->execute([$className]);
- $executed = $selectStmt->rowCount();
- $selectStmt->closeCursor();
-
- if (!$executed && $migration->preCondition($pdo)) {
- $migration->execute($pdo);
- if ($insertStmt->execute([$className])) {
- $countSucceeded++;
- $success[] = $migration->description();
- } else {
- $countFailed++;
- $fail[] = $migration->description();
- }
- } else {
- $countSkipped++;
- }
-}
-
-$countTotal = $countSucceeded + $countFailed + $countSkipped;
-
-$smarty->assign('success', $success);
-$smarty->assign('fail', $fail);
-
-$smarty->assign('countSucceeded', $countSucceeded);
-$smarty->assign('countFailed', $countFailed);
-$smarty->assign('countSkipped', $countSkipped);
-$smarty->assign('countTotal', $countTotal);
-$smarty->assign('time', $total_time = round((microtime(true)-$_SERVER['REQUEST_TIME_FLOAT']), 4));
-
-$smarty->assign('title', __('Admin', 'Migration'));
-
-$smarty->display('admin/migration.tpl');
diff --git a/admin/polls.php b/admin/polls.php
index 06d3b45..e5d32f2 100644
--- a/admin/polls.php
+++ b/admin/polls.php
@@ -86,16 +86,15 @@ $count = $found['count'];
$total = $found['total'];
// Assign data to template
-$smarty->assign('polls', $polls);
-$smarty->assign('count', $count);
-$smarty->assign('total', $total);
-$smarty->assign('page', $page);
-$smarty->assign('pages', ceil($count / POLLS_PER_PAGE));
-$smarty->assign('poll_to_delete', $poll_to_delete);
-$smarty->assign('crsf', $securityService->getToken('admin'));
-$smarty->assign('search', $search);
-$smarty->assign('search_query', buildSearchQuery($search));
-
-$smarty->assign('title', __('Admin', 'Polls'));
-
-$smarty->display('admin/polls.tpl');
+echo $twig->render('admin/polls.twig', [
+ 'polls' => $polls,
+ 'count' => $count,
+ 'total' => $total,
+ 'page' => $page,
+ 'pages' => ceil($count / POLLS_PER_PAGE),
+ 'poll_to_delete' => $poll_to_delete,
+ 'crsf' => $securityService->getToken('admin'),
+ 'search' => $search,
+ 'search_query' => buildSearchQuery($search),
+ 'title' => __('Admin', 'Polls'),
+]);
diff --git a/admin/purge.php b/admin/purge.php
index 7593a9f..a89753b 100644
--- a/admin/purge.php
+++ b/admin/purge.php
@@ -52,9 +52,9 @@ if ($action === 'purge' && $securityService->checkCsrf('admin', $_POST['csrf']))
}
// Assign data to template
-$smarty->assign('message', $message);
-$smarty->assign('crsf', $securityService->getToken('admin'));
-$smarty->assign('title', __('Admin', 'Purge'));
-
-$smarty->display('admin/purge.tpl');
\ No newline at end of file
+echo $twig->render('admin/purge.twig', [
+ 'message' => $message,
+ 'crsf' => $securityService->getToken('admin'),
+ 'title' => __('Admin', 'Purge'),
+]);
diff --git a/adminstuds.php b/adminstuds.php
deleted file mode 100644
index 5c51d94..0000000
--- a/adminstuds.php
+++ /dev/null
@@ -1,469 +0,0 @@
- ['regexp' => POLL_REGEX]]);
- if (strlen($admin_poll_id) === 24) {
- $poll = $pollService->findByAdminId($admin_poll_id);
- }
-}
-
-if ($poll) {
- $poll_id = $poll->id;
-} else {
- $smarty->assign('error', __('Error', 'This poll doesn\'t exist !'));
- $smarty->display('error.tpl');
- exit;
-}
-
-// -------------------------------
-// creation message
-// -------------------------------
-
-$messagePollCreated = $sessionService->get("Framadate", "messagePollCreated", FALSE);
-
-if ($messagePollCreated) {
- $sessionService->remove("Framadate", "messagePollCreated");
-
- $message = new Message('success', __('adminstuds', 'The poll is created.'));
-}
-
-// -------------------------------
-// Update poll info
-// -------------------------------
-
-if (isset($_POST['update_poll_info'])) {
- $updated = false;
- $field = $inputService->filterAllowedValues($_POST['update_poll_info'], ['title', 'admin_mail', 'description',
- 'rules', 'expiration_date', 'name', 'hidden', 'removePassword', 'password']);
-
- // Update the right poll field
- if ($field === 'title') {
- $title = $inputService->filterTitle($_POST['title']);
- if ($title) {
- $poll->title = $title;
- $updated = true;
- }
- } elseif ($field === 'admin_mail') {
- $admin_mail = $inputService->filterMail($_POST['admin_mail']);
- if ($admin_mail) {
- $poll->admin_mail = $admin_mail;
- $updated = true;
- }
- } elseif ($field === 'description') {
- $description = $inputService->filterDescription($_POST['description']);
- if ($description) {
- $poll->description = $description;
- $updated = true;
- }
- } elseif ($field === 'rules') {
- $rules = strip_tags($_POST['rules']);
- switch ($rules) {
- case 0:
- $poll->active = false;
- $poll->editable = Editable::NOT_EDITABLE;
- $updated = true;
- break;
- case 1:
- $poll->active = true;
- $poll->editable = Editable::NOT_EDITABLE;
- $updated = true;
- break;
- case 2:
- $poll->active = true;
- $poll->editable = Editable::EDITABLE_BY_ALL;
- $updated = true;
- break;
- case 3:
- $poll->active = true;
- $poll->editable = Editable::EDITABLE_BY_OWN;
- $updated = true;
- break;
- }
- } elseif ($field === 'expiration_date') {
- $expiration_date = $inputService->filterDate($_POST['expiration_date']);
- if ($expiration_date) {
- $poll->end_date = $expiration_date;
- $updated = true;
- }
- } elseif ($field === 'name') {
- $admin_name = $inputService->filterName($_POST['name']);
- if ($admin_name) {
- $poll->admin_name = $admin_name;
- $updated = true;
- }
- } elseif ($field === 'hidden') {
- $hidden = isset($_POST['hidden']) ? $inputService->filterBoolean($_POST['hidden']) : false;
- if ($hidden !== $poll->hidden) {
- $poll->hidden = $hidden;
- $poll->results_publicly_visible = false;
- $updated = true;
- }
- } elseif ($field === 'removePassword') {
- $removePassword = isset($_POST['removePassword']) ? $inputService->filterBoolean($_POST['removePassword']) : false;
- if ($removePassword) {
- $poll->results_publicly_visible = false;
- $poll->password_hash = null;
- $updated = true;
- }
- } elseif ($field === 'password') {
- $password = isset($_POST['password']) ? $_POST['password'] : null;
-
- /**
- * Did the user choose results to be publicly visible ?
- */
- $resultsPubliclyVisible = isset($_POST['resultsPubliclyVisible']) ? $inputService->filterBoolean($_POST['resultsPubliclyVisible']) : false;
- /**
- * If there's one, save the password
- */
- if (!empty($password)) {
- $poll->password_hash = PasswordHasher::hash($password);
- $updated = true;
- }
-
- /**
- * If not pasword was set and the poll should be hidden, hide the results
- */
- if ($poll->password_hash === null || $poll->hidden === true) {
- $poll->results_publicly_visible = false;
- }
-
- /**
- * We don't have a password, the poll is hidden and we change the results public visibility
- */
- if ($resultsPubliclyVisible !== $poll->results_publicly_visible && $poll->password_hash !== null && $poll->hidden === false) {
- $poll->results_publicly_visible = $resultsPubliclyVisible;
- $updated = true;
- }
- }
-
- // Update poll in database
- if ($updated && $adminPollService->updatePoll($poll)) {
- $message = new Message('success', __('adminstuds', 'Poll saved'));
- $notificationService->sendUpdateNotification($poll, NotificationService::UPDATE_POLL);
- } else {
- $message = new Message('danger', __('Error', 'Failed to save poll'));
- $poll = $pollService->findById($poll_id);
- }
-}
-
-// -------------------------------
-// A vote is going to be edited
-// -------------------------------
-
-if (!empty($_GET['vote'])) {
- $editingVoteId = filter_input(INPUT_GET, 'vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
-}
-
-// -------------------------------
-// Something to save (edit or add)
-// -------------------------------
-
-$selectedNewVotes = [];
-
-if (!empty($_POST['save'])) { // Save edition of an old vote
- $name = $inputService->filterName($_POST['name']);
- $editedVote = filter_input(INPUT_POST, 'save', FILTER_VALIDATE_INT);
- $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
- $slots_hash = $inputService->filterMD5($_POST['control']);
-
- if (empty($editedVote)) {
- $message = new Message('danger', __('Error', 'Something is going wrong...'));
- }
- if (count($choices) !== count($_POST['choices'])) {
- $message = new Message('danger', __('Error', 'There is a problem with your choices'));
- }
-
- if ($message === null) {
- // Update vote
- try {
- $result = $pollService->updateVote($poll_id, $editedVote, $name, $choices, $slots_hash);
- if ($result) {
- $message = new Message('success', __('adminstuds', 'Vote updated'));
- } else {
- $message = new Message('danger', __('Error', 'Update vote failed'));
- }
- } catch (AlreadyExistsException $aee) {
- $message = new Message('danger', __('Error', 'The name you\'ve chosen already exist in this poll!'));
- } catch (ConcurrentEditionException $cee) {
- $message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
- } catch (ConcurrentVoteException $cve) {
- $message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry."));
- }
- }
-} elseif (isset($_POST['save'])) { // Add a new vote
- $name = $inputService->filterName($_POST['name']);
- $choices = $inputService->filterArray($_POST['choices'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => CHOICE_REGEX]]);
- $slots_hash = $inputService->filterMD5($_POST['control']);
-
- if ($name === null) {
- $message = new Message('danger', __('Error', 'The name is invalid.'));
- }
- if (count($choices) !== count($_POST['choices'])) {
- $message = new Message('danger', __('Error', 'There is a problem with your choices'));
- }
-
- if ($message === null) {
- // Add vote
- try {
- $result = $pollService->addVote($poll_id, $name, $choices, $slots_hash);
- if ($result) {
- $message = new Message('success', __('adminstuds', 'Vote added'));
- } else {
- $message = new Message('danger', __('Error', 'Adding vote failed'));
- }
- } catch (AlreadyExistsException $aee) {
- $message = new Message('danger', __('Error', 'You already voted'));
- $selectedNewVotes = $choices;
- } catch (ConcurrentEditionException $cee) {
- $message = new Message('danger', __('Error', 'Poll has been updated before you vote'));
- } catch (ConcurrentVoteException $cve) {
- $message = new Message('danger', __('Error', "Your vote wasn't counted, because someone voted in the meantime and it conflicted with your choices and the poll conditions. Please retry."));
- }
- }
-}
-
-// -------------------------------
-// Delete a votes
-// -------------------------------
-
-if (!empty($_GET['delete_vote'])) {
- $vote_id = filter_input(INPUT_GET, 'delete_vote', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => BASE64_REGEX]]);
- $vote_id = Utils::base64url_decode($vote_id);
- if ($vote_id && $adminPollService->deleteVote($poll_id, $vote_id)) {
- $message = new Message('success', __('adminstuds', 'Vote deleted'));
- } else {
- $message = new Message('danger', __('Error', 'Failed to delete the vote!'));
- }
-}
-
-// -------------------------------
-// Remove all votes
-// -------------------------------
-
-if (isset($_POST['remove_all_votes'])) {
- $smarty->assign('poll_id', $poll_id);
- $smarty->assign('admin_poll_id', $admin_poll_id);
- $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
- $smarty->display('confirm/delete_votes.tpl');
- exit;
-}
-if (isset($_POST['confirm_remove_all_votes'])) {
- if ($adminPollService->cleanVotes($poll_id)) {
- $message = new Message('success', __('adminstuds', 'All votes deleted'));
- } else {
- $message = new Message('danger', __('Error', 'Failed to delete all votes'));
- }
-}
-
-// -------------------------------
-// Delete a comment
-// -------------------------------
-
-if (!empty($_POST['delete_comment'])) {
- $comment_id = filter_input(INPUT_POST, 'delete_comment', FILTER_VALIDATE_INT);
-
- if ($adminPollService->deleteComment($poll_id, $comment_id)) {
- $message = new Message('success', __('adminstuds', 'Comment deleted'));
- } else {
- $message = new Message('danger', __('Error', 'Failed to delete the comment'));
- }
-}
-
-// -------------------------------
-// Remove all comments
-// -------------------------------
-
-if (isset($_POST['remove_all_comments'])) {
- $smarty->assign('poll_id', $poll_id);
- $smarty->assign('admin_poll_id', $admin_poll_id);
- $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
- $smarty->display('confirm/delete_comments.tpl');
- exit;
-}
-if (isset($_POST['confirm_remove_all_comments'])) {
- if ($adminPollService->cleanComments($poll_id)) {
- $message = new Message('success', __('adminstuds', 'All comments deleted'));
- } else {
- $message = new Message('danger', __('Error', 'Failed to delete all comments'));
- }
-}
-
-// -------------------------------
-// Delete the entire poll
-// -------------------------------
-
-if (isset($_POST['delete_poll'])) {
- $smarty->assign('poll_id', $poll_id);
- $smarty->assign('admin_poll_id', $admin_poll_id);
- $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
- $smarty->display('confirm/delete_poll.tpl');
- exit;
-}
-if (isset($_POST['confirm_delete_poll'])) {
- if ($adminPollService->deleteEntirePoll($poll_id)) {
- $message = new Message('success', __('adminstuds', 'Poll fully deleted'));
- $notificationService->sendUpdateNotification($poll, NotificationService::DELETED_POLL);
- } else {
- $message = new Message('danger', __('Error', 'Failed to delete the poll'));
- }
- $smarty->assign('poll_id', $poll_id);
- $smarty->assign('admin_poll_id', $admin_poll_id);
- $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
- $smarty->assign('message', $message);
- $smarty->display('poll_deleted.tpl');
- exit;
-}
-
-// -------------------------------
-// Delete a slot
-// -------------------------------
-
-if (isset($_GET['delete_column'])) {
- $column = filter_input(INPUT_GET, 'delete_column', FILTER_DEFAULT);
- $column = Utils::base64url_decode($column);
-
- if ($poll->format === 'D') {
- $ex = explode('@', $column);
-
- $slot = new stdClass();
- $slot->title = $ex[0];
- $slot->moment = $ex[1];
-
- $result = $adminPollService->deleteDateSlot($poll, $slot);
- } else {
- $result = $adminPollService->deleteClassicSlot($poll, $column);
- }
-
- if ($result) {
- $message = new Message('success', __('adminstuds', 'Column removed'));
- } else {
- $message = new Message('danger', __('Error', 'Failed to delete column'));
- }
-}
-
-// -------------------------------
-// Add a slot
-// -------------------------------
-
-function exit_displaying_add_column($message = null) {
- global $smarty, $poll_id, $admin_poll_id, $poll;
- $smarty->assign('poll_id', $poll_id);
- $smarty->assign('admin_poll_id', $admin_poll_id);
- $smarty->assign('format', $poll->format);
- $smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
- $smarty->assign('message', $message);
- $smarty->display('add_column.tpl');
- exit;
-}
-
-if (isset($_GET['add_column'])) {
- exit_displaying_add_column();
-}
-
-if (isset($_POST['confirm_add_column'])) {
- try {
- if (($poll->format === 'D' && empty($_POST['newdate']))
- || ($poll->format === 'A' && empty($_POST['choice']))) {
- exit_displaying_add_column(new Message('danger', __('Error', "Can't create an empty column.")));
- }
- if ($poll->format === 'D') {
- $date = DateTime::createFromFormat(__('Date', 'datetime_parseformat'), $_POST['newdate'])->setTime(0, 0, 0);
- $time = $date->getTimestamp();
- $newmoment = str_replace(',', '-', strip_tags($_POST['newmoment']));
- $adminPollService->addDateSlot($poll_id, $time, $newmoment);
- } else {
- $newslot = str_replace(',', '-', strip_tags($_POST['choice']));
- $adminPollService->addClassicSlot($poll_id, $newslot);
- }
-
- $message = new Message('success', __('adminstuds', 'Choice added'));
- } catch (MomentAlreadyExistsException $e) {
- exit_displaying_add_column(new Message('danger', __('Error', 'The column already exists')));
- }
-}
-
-// Retrieve data
-$slots = $pollService->allSlotsByPoll($poll);
-$votes = $pollService->allVotesByPollId($poll_id);
-$comments = $pollService->allCommentsByPollId($poll_id);
-
-// Assign data to template
-$smarty->assign('poll_id', $poll_id);
-$smarty->assign('admin_poll_id', $admin_poll_id);
-$smarty->assign('poll', $poll);
-$smarty->assign('title', __('Generic', 'Poll') . ' - ' . $poll->title);
-$smarty->assign('expired', strtotime($poll->end_date) < time());
-$smarty->assign('deletion_date', strtotime($poll->end_date) + PURGE_DELAY * 86400);
-$smarty->assign('slots', $poll->format === 'D' ? $pollService->splitSlots($slots) : $slots);
-$smarty->assign('slots_hash', $pollService->hashSlots($slots));
-$smarty->assign('votes', $pollService->splitVotes($votes));
-$smarty->assign('best_choices', $pollService->computeBestChoices($votes, $poll));
-$smarty->assign('comments', $comments);
-$smarty->assign('editingVoteId', $editingVoteId);
-$smarty->assign('message', $message);
-$smarty->assign('admin', true);
-$smarty->assign('hidden', false);
-$smarty->assign('accessGranted', true);
-$smarty->assign('resultPubliclyVisible', true);
-$smarty->assign('editedVoteUniqueId', '');
-$smarty->assign('default_to_marldown_editor', $config['markdown_editor_by_default']);
-$smarty->assign('selectedNewVotes', $selectedNewVotes);
-
-$smarty->display('studs.tpl');
diff --git a/app/classes/Framadate/Choice.php b/app/classes/Framadate/Choice.php
deleted file mode 100644
index e583e26..0000000
--- a/app/classes/Framadate/Choice.php
+++ /dev/null
@@ -1,58 +0,0 @@
-name = $name;
- $this->slots = [];
- }
-
- public function addSlot($slot)
- {
- $this->slots[] = $slot;
- }
-
- public function getName()
- {
- return $this->name;
- }
-
- public function getSlots()
- {
- return $this->slots;
- }
-
- static function compare(Choice $a, Choice $b)
- {
- return strcmp($a->name, $b->name);
- }
-}
diff --git a/app/classes/Framadate/Exception/AlreadyExistsException.php b/app/classes/Framadate/Exception/AlreadyExistsException.php
deleted file mode 100644
index 86e73aa..0000000
--- a/app/classes/Framadate/Exception/AlreadyExistsException.php
+++ /dev/null
@@ -1,7 +0,0 @@
-editable = Editable::EDITABLE_BY_ALL;
- $this->clearChoices();
- }
-
- public function clearChoices() {
- $this->choices = [];
- }
-
- public function addChoice(Choice $choice)
- {
- $this->choices[] = $choice;
- }
-
- public function getChoices()
- {
- return $this->choices;
- }
-
- public function sortChoices()
- {
- usort($this->choices, ['Framadate\Choice', 'compare']);
- }
-}
diff --git a/app/classes/Framadate/FramaDB.php b/app/classes/Framadate/FramaDB.php
deleted file mode 100644
index bed6327..0000000
--- a/app/classes/Framadate/FramaDB.php
+++ /dev/null
@@ -1,85 +0,0 @@
-pdo = new \PDO($connection_string, $user, $password);
- $this->pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
- $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
- }
-
- /**
- * @return \PDO Connection to database
- */
- function getPDO() {
- return $this->pdo;
- }
-
- /**
- * Find all tables in database.
- *
- * @return array The array of table names
- */
- function allTables() {
- $result = $this->pdo->query('SHOW TABLES');
- $schemas = $result->fetchAll(\PDO::FETCH_COLUMN);
-
- return $schemas;
- }
-
- function prepare($sql) {
- return $this->pdo->prepare($sql);
- }
-
- function beginTransaction() {
- $this->pdo->beginTransaction();
- }
-
- function commit() {
- $this->pdo->commit();
- }
-
- function rollback() {
- $this->pdo->rollback();
- }
-
- function errorCode() {
- return $this->pdo->errorCode();
- }
-
- function errorInfo() {
- return $this->pdo->errorInfo();
- }
-
- function query($sql) {
- return $this->pdo->query($sql);
- }
-
- public function lastInsertId() {
- return $this->pdo->lastInsertId();
- }
-}
diff --git a/app/classes/Framadate/Migration/Increase_pollId_size.php b/app/classes/Framadate/Migration/Increase_pollId_size.php
deleted file mode 100644
index 37eec25..0000000
--- a/app/classes/Framadate/Migration/Increase_pollId_size.php
+++ /dev/null
@@ -1,66 +0,0 @@
-alterCommentTable($pdo);
- $this->alterPollTable($pdo);
- $this->alterSlotTable($pdo);
- $this->alterVoteTable($pdo);
- }
-
- private function alterCommentTable(\PDO $pdo) {
- $pdo->exec('
- ALTER TABLE `' . Utils::table('comment') . '`
- CHANGE `poll_id` `poll_id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;');
- }
-
- private function alterPollTable(\PDO $pdo) {
- $pdo->exec('
- ALTER TABLE `' . Utils::table('poll') . '`
- CHANGE `id` `id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;');
- }
-
- private function alterSlotTable(\PDO $pdo) {
- $pdo->exec('
- ALTER TABLE `' . Utils::table('slot') . '`
- CHANGE `poll_id` `poll_id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;');
- }
-
- private function alterVoteTable(\PDO $pdo) {
- $pdo->exec('
- ALTER TABLE `' . Utils::table('vote') . '`
- CHANGE `poll_id` `poll_id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;');
- }
-}
diff --git a/app/classes/Framadate/Migration/Migration.php b/app/classes/Framadate/Migration/Migration.php
deleted file mode 100644
index c4bed57..0000000
--- a/app/classes/Framadate/Migration/Migration.php
+++ /dev/null
@@ -1,46 +0,0 @@
-connect = $connect;
- }
-
- public function beginTransaction() {
- $this->connect->beginTransaction();
- }
-
- public function commit() {
- $this->connect->commit();
- }
-
- function rollback() {
- $this->connect->rollback();
- }
-
- public function prepare($sql) {
- return $this->connect->prepare($sql);
- }
-
- function query($sql) {
- return $this->connect->query($sql);
- }
-
- function lastInsertId() {
- return $this->connect->lastInsertId();
- }
-}
diff --git a/app/classes/Framadate/Repositories/CommentRepository.php b/app/classes/Framadate/Repositories/CommentRepository.php
deleted file mode 100644
index 262ed0a..0000000
--- a/app/classes/Framadate/Repositories/CommentRepository.php
+++ /dev/null
@@ -1,57 +0,0 @@
-prepare('SELECT * FROM `' . Utils::table('comment') . '` WHERE poll_id = ? ORDER BY id');
- $prepared->execute([$poll_id]);
-
- return $prepared->fetchAll();
- }
-
- /**
- * Insert a new comment.
- *
- * @param $poll_id
- * @param $name
- * @param $comment
- * @return bool
- */
- function insert($poll_id, $name, $comment) {
- $prepared = $this->prepare('INSERT INTO `' . Utils::table('comment') . '` (poll_id, name, comment) VALUES (?,?,?)');
-
- return $prepared->execute([$poll_id, $name, $comment]);
- }
-
- function deleteById($poll_id, $comment_id) {
- $prepared = $this->prepare('DELETE FROM `' . Utils::table('comment') . '` WHERE poll_id = ? AND id = ?');
-
- return $prepared->execute([$poll_id, $comment_id]);
- }
-
- /**
- * Delete all comments of a given poll.
- *
- * @param $poll_id int The ID of the given poll.
- * @return bool|null true if action succeeded.
- */
- function deleteByPollId($poll_id) {
- $prepared = $this->prepare('DELETE FROM `' . Utils::table('comment') . '` WHERE poll_id = ?');
-
- return $prepared->execute([$poll_id]);
- }
-
- public function exists($poll_id, $name, $comment) {
- $prepared = $this->prepare('SELECT 1 FROM `' . Utils::table('comment') . '` WHERE poll_id = ? AND name = ? AND comment = ?');
- $prepared->execute([$poll_id, $name, $comment]);
-
- return $prepared->rowCount() > 0;
- }
-}
diff --git a/app/classes/Framadate/Repositories/PollRepository.php b/app/classes/Framadate/Repositories/PollRepository.php
deleted file mode 100644
index 5a11c0b..0000000
--- a/app/classes/Framadate/Repositories/PollRepository.php
+++ /dev/null
@@ -1,184 +0,0 @@
-prepare($sql);
- $prepared->execute([$poll_id, $admin_poll_id, $form->title, $form->description, $form->admin_name, $form->admin_mail, $form->end_date, $form->format, ($form->editable>=0 && $form->editable<=2) ? $form->editable : 0, $form->receiveNewVotes ? 1 : 0, $form->receiveNewComments ? 1 : 0, $form->hidden ? 1 : 0, $form->password_hash, $form->results_publicly_visible ? 1 : 0,$form->ValueMax]);
- }
-
- function findById($poll_id) {
- $prepared = $this->prepare('SELECT * FROM `' . Utils::table('poll') . '` WHERE id = ?');
-
- $prepared->execute([$poll_id]);
- $poll = $prepared->fetch();
- $prepared->closeCursor();
-
- return $poll;
- }
-
- public function findByAdminId($admin_poll_id) {
- $prepared = $this->prepare('SELECT * FROM `' . Utils::table('poll') . '` WHERE admin_id = ?');
-
- $prepared->execute([$admin_poll_id]);
- $poll = $prepared->fetch();
- $prepared->closeCursor();
-
- return $poll;
- }
-
- public function existsById($poll_id) {
- $prepared = $this->prepare('SELECT 1 FROM `' . Utils::table('poll') . '` WHERE id = ?');
-
- $prepared->execute([$poll_id]);
-
- return $prepared->rowCount() > 0;
- }
-
- public function existsByAdminId($admin_poll_id) {
- $prepared = $this->prepare('SELECT 1 FROM `' . Utils::table('poll') . '` WHERE admin_id = ?');
-
- $prepared->execute([$admin_poll_id]);
-
- return $prepared->rowCount() > 0;
- }
-
- function update($poll) {
- $prepared = $this->prepare('UPDATE `' . Utils::table('poll') . '` SET title=?, admin_name=?, admin_mail=?, description=?, end_date=?, active=?, editable=?, hidden=?, password_hash=?, results_publicly_visible=? WHERE id = ?');
-
- return $prepared->execute([$poll->title, $poll->admin_name, $poll->admin_mail, $poll->description, $poll->end_date, $poll->active, ($poll->editable>=0 && $poll->editable<=2) ? $poll->editable : 0, $poll->hidden ? 1 : 0, $poll->password_hash, $poll->results_publicly_visible ? 1 : 0, $poll->id]);
- }
-
- function deleteById($poll_id) {
- $prepared = $this->prepare('DELETE FROM `' . Utils::table('poll') . '` WHERE id = ?');
-
- return $prepared->execute([$poll_id]);
- }
-
- /**
- * Find old polls. Limit: 20.
- *
- * @return array Array of old polls
- */
- public function findOldPolls() {
- $prepared = $this->prepare('SELECT * FROM `' . Utils::table('poll') . '` WHERE DATE_ADD(`end_date`, INTERVAL ' . PURGE_DELAY . ' DAY) < NOW() AND `end_date` != 0 LIMIT 20');
- $prepared->execute([]);
-
- return $prepared->fetchAll();
- }
-
- /**
- * Search polls in database.
- *
- * @param array $search Array of search : ['id'=>..., 'title'=>..., 'name'=>..., 'mail'=>...]
- * @param int $start The number of first entry to select
- * @param int $limit The number of entries to find
- * @return array The found polls
- */
- public function findAll($search, $start, $limit) {
- // Polls
-
- $request = "";
- $request .= "SELECT p.*,";
- $request .= " (SELECT count(1) FROM `" . Utils::table('vote') . "` v WHERE p.id=v.poll_id) votes";
- $request .= " FROM `" . Utils::table('poll') . "` p";
- $request .= " WHERE 1";
-
- $values = [];
-
- if (!empty($search["poll"])) {
- $request .= " AND p.id LIKE :poll";
- $values["poll"] = "{$search["poll"]}%";
- }
-
- $fields = [
- // key of $search => column name
- "title" => "title",
- "name" => "admin_name",
- "mail" => "admin_mail",
- ];
-
- foreach ($fields as $searchKey => $columnName) {
- if (empty($search[$searchKey])) {
- continue;
- }
-
- $request .= " AND p.$columnName LIKE :$searchKey";
- $values[$searchKey] = "%{$search[$searchKey]}%";
- }
-
- $request .= " ORDER BY p.title ASC";
- $request .= " LIMIT :start, :limit";
-
- $prepared = $this->prepare($request);
-
- foreach ($values as $searchKey => $value) {
- $prepared->bindParam(":$searchKey", $value, PDO::PARAM_STR);
- }
-
- $prepared->bindParam(':start', $start, PDO::PARAM_INT);
- $prepared->bindParam(':limit', $limit, PDO::PARAM_INT);
-
- $prepared->execute();
-
- return $prepared->fetchAll();
- }
-
- /**
- * Find all polls that are created with the given admin mail.
- *
- * @param string $mail Email address of the poll admin
- * @return array The list of matching polls
- */
- public function findAllByAdminMail($mail) {
- $prepared = $this->prepare('SELECT * FROM `' . Utils::table('poll') . '` WHERE admin_mail = :admin_mail');
- $prepared->execute(['admin_mail' => $mail]);
-
- return $prepared->fetchAll();
- }
-
- /**
- * Get the total number of polls in databse.
- *
- * @param array $search Array of search : ['id'=>..., 'title'=>..., 'name'=>...]
- * @return int The number of polls
- */
- public function count($search = null) {
- // Total count
- $prepared = $this->prepare('
-SELECT count(1) nb
- FROM `' . Utils::table('poll') . '` p
- WHERE (:id = "" OR p.id LIKE :id)
- AND (:title = "" OR p.title LIKE :title)
- AND (:name = "" OR p.admin_name LIKE :name)
- ORDER BY p.title ASC');
-
- $poll = $search === null ? '' : $search['poll'] . '%';
- $title = $search === null ? '' : '%' . $search['title'] . '%';
- $name = $search === null ? '' : '%' . $search['name'] . '%';
- $prepared->bindParam(':id', $poll, PDO::PARAM_STR);
- $prepared->bindParam(':title', $title, PDO::PARAM_STR);
- $prepared->bindParam(':name', $name, PDO::PARAM_STR);
-
- $prepared->execute();
- $count = $prepared->fetch();
-
- /*echo '---';
- print_r($count);
- echo '---';
- exit;*/
-
- return $count->nb;
- }
-}
diff --git a/app/classes/Framadate/Repositories/RepositoryFactory.php b/app/classes/Framadate/Repositories/RepositoryFactory.php
deleted file mode 100644
index 810d391..0000000
--- a/app/classes/Framadate/Repositories/RepositoryFactory.php
+++ /dev/null
@@ -1,81 +0,0 @@
-prepare('INSERT INTO `' . Utils::table('slot') . '` (poll_id, title, moments) VALUES (?, ?, ?)');
-
- foreach ($choices as $choice) {
- // We prepared the slots (joined by comas)
- $joinedSlots = '';
- $first = true;
- foreach ($choice->getSlots() as $slot) {
- if ($first) {
- $joinedSlots = $slot;
- $first = false;
- } else {
- $joinedSlots .= ',' . $slot;
- }
- }
-
- // We execute the insertion
- if (empty($joinedSlots)) {
- $prepared->execute([$poll_id, $choice->getName(), null]);
- } else {
- $prepared->execute([$poll_id, $choice->getName(), $joinedSlots]);
- }
- }
- }
-
- function listByPollId($poll_id) {
- $prepared = $this->prepare('SELECT * FROM `' . Utils::table('slot') . '` WHERE poll_id = ? ORDER BY id');
- $prepared->execute([$poll_id]);
-
- return $prepared->fetchAll();
- }
-
- /**
- * Find the slot into poll for a given datetime.
- *
- * @param $poll_id int The ID of the poll
- * @param $datetime int The datetime of the slot
- * @return mixed Object The slot found, or null
- */
- function findByPollIdAndDatetime($poll_id, $datetime) {
- $prepared = $this->prepare('SELECT * FROM `' . Utils::table('slot') . '` WHERE poll_id = ? AND SUBSTRING_INDEX(title, \'@\', 1) = ?');
-
- $prepared->execute([$poll_id, $datetime]);
- $slot = $prepared->fetch();
- $prepared->closeCursor();
-
- return $slot;
- }
-
- /**
- * Insert a new slot into a given poll.
- *
- * @param $poll_id int The ID of the poll
- * @param $title mixed The title of the slot
- * @param $moments mixed|null The moments joined with ","
- * @return bool true if action succeeded
- */
- function insert($poll_id, $title, $moments) {
- $prepared = $this->prepare('INSERT INTO `' . Utils::table('slot') . '` (poll_id, title, moments) VALUES (?,?,?)');
-
- return $prepared->execute([$poll_id, $title, $moments]);
- }
-
- /**
- * Update a slot into a poll.
- *
- * @param $poll_id int The ID of the poll
- * @param $datetime int The datetime of the slot to update
- * @param $newMoments mixed The new moments
- * @return bool|null true if action succeeded.
- */
- function update($poll_id, $datetime, $newMoments) {
- $prepared = $this->prepare('UPDATE `' . Utils::table('slot') . '` SET moments = ? WHERE poll_id = ? AND title = ?');
-
- return $prepared->execute([$newMoments, $poll_id, $datetime]);
- }
-
- /**
- * Delete a entire slot from a poll.
- *
- * @param $poll_id int The ID of the poll
- * @param $datetime mixed The datetime of the slot
- */
- function deleteByDateTime($poll_id, $datetime) {
- $prepared = $this->prepare('DELETE FROM `' . Utils::table('slot') . '` WHERE poll_id = ? AND title = ?');
- $prepared->execute([$poll_id, $datetime]);
- }
-
- function deleteByPollId($poll_id) {
- $prepared = $this->prepare('DELETE FROM `' . Utils::table('slot') . '` WHERE poll_id = ?');
-
- return $prepared->execute([$poll_id]);
- }
-}
diff --git a/app/classes/Framadate/Services/AdminPollService.php b/app/classes/Framadate/Services/AdminPollService.php
deleted file mode 100644
index 0f76150..0000000
--- a/app/classes/Framadate/Services/AdminPollService.php
+++ /dev/null
@@ -1,305 +0,0 @@
-connect = $connect;
- $this->pollService = $pollService;
- $this->logService = $logService;
- $this->pollRepository = RepositoryFactory::pollRepository();
- $this->slotRepository = RepositoryFactory::slotRepository();
- $this->voteRepository = RepositoryFactory::voteRepository();
- $this->commentRepository = RepositoryFactory::commentRepository();
- }
-
- function updatePoll($poll) {
- global $config;
- if ($poll->end_date > $poll->creation_date) {
- return $this->pollRepository->update($poll);
- }
- return false;
- }
-
- /**
- * Delete a comment from a poll.
- *
- * @param $poll_id int The ID of the poll
- * @param $comment_id int The ID of the comment
- * @return mixed true is action succeeded
- */
- function deleteComment($poll_id, $comment_id) {
- return $this->commentRepository->deleteById($poll_id, $comment_id);
- }
-
- /**
- * Remove all comments of a poll.
- *
- * @param $poll_id int The ID a the poll
- * @return bool|null true is action succeeded
- */
- function cleanComments($poll_id) {
- $this->logService->log("CLEAN_COMMENTS", "id:$poll_id");
- return $this->commentRepository->deleteByPollId($poll_id);
- }
-
- /**
- * Delete a vote from a poll.
- *
- * @param $poll_id int The ID of the poll
- * @param $vote_id int The ID of the vote
- * @return mixed true is action succeeded
- */
- function deleteVote($poll_id, $vote_id) {
- return $this->voteRepository->deleteById($poll_id, $vote_id);
- }
-
- /**
- * Remove all votes of a poll.
- *
- * @param $poll_id int The ID of the poll
- * @return bool|null true is action succeeded
- */
- function cleanVotes($poll_id) {
- $this->logService->log('CLEAN_VOTES', 'id:' . $poll_id);
- return $this->voteRepository->deleteByPollId($poll_id);
- }
-
- /**
- * Delete the entire given poll.
- *
- * @param $poll_id int The ID of the poll
- * @return bool true is action succeeded
- */
- function deleteEntirePoll($poll_id) {
- $poll = $this->pollRepository->findById($poll_id);
- $this->logService->log('DELETE_POLL', "id:$poll->id, format:$poll->format, admin:$poll->admin_name, mail:$poll->admin_mail");
-
- // Delete the entire poll
- $this->voteRepository->deleteByPollId($poll_id);
- $this->commentRepository->deleteByPollId($poll_id);
- $this->slotRepository->deleteByPollId($poll_id);
- $this->pollRepository->deleteById($poll_id);
-
- return true;
- }
-
- /**
- * Delete a slot from a poll.
- *
- * @param object $poll The ID of the poll
- * @param object $slot The slot informations (datetime + moment)
- * @return bool true if action succeeded
- */
- public function deleteDateSlot($poll, $slot) {
- $this->logService->log('DELETE_SLOT', 'id:' . $poll->id . ', slot:' . json_encode($slot));
-
- $datetime = $slot->title;
- $moment = $slot->moment;
-
- $slots = $this->pollService->allSlotsByPoll($poll);
-
- // We can't delete the last slot
- if ($poll->format === 'D' && count($slots) === 1 && strpos($slots[0]->moments, ',') === false) {
- return false;
- } elseif ($poll->format === 'A' && count($slots) === 1) {
- return false;
- }
-
- $index = 0;
- $indexToDelete = -1;
- $newMoments = [];
-
- // Search the index of the slot to delete
- foreach ($slots as $aSlot) {
- $moments = explode(',', $aSlot->moments);
-
- foreach ($moments as $rowMoment) {
- if ($datetime === $aSlot->title) {
- if ($moment === $rowMoment) {
- $indexToDelete = $index;
- } else {
- $newMoments[] = $rowMoment;
- }
- }
- $index++;
- }
- }
-
- // Remove votes
- $this->connect->beginTransaction();
- $this->voteRepository->deleteByIndex($poll->id, $indexToDelete);
- if (count($newMoments) > 0) {
- $this->slotRepository->update($poll->id, $datetime, implode(',', $newMoments));
- } else {
- $this->slotRepository->deleteByDateTime($poll->id, $datetime);
- }
- $this->connect->commit();
-
- return true;
- }
-
- public function deleteClassicSlot($poll, $slot_title) {
- $this->logService->log('DELETE_SLOT', 'id:' . $poll->id . ', slot:' . $slot_title);
-
- $slots = $this->pollService->allSlotsByPoll($poll);
-
- if (count($slots) === 1) {
- return false;
- }
-
- $index = 0;
- $indexToDelete = -1;
-
- // Search the index of the slot to delete
- foreach ($slots as $aSlot) {
- if ($slot_title === $aSlot->title) {
- $indexToDelete = $index;
- }
- $index++;
- }
-
- // Remove votes
- $this->connect->beginTransaction();
- $this->voteRepository->deleteByIndex($poll->id, $indexToDelete);
- $this->slotRepository->deleteByDateTime($poll->id, $slot_title);
- $this->connect->commit();
-
- return true;
- }
-
- /**
- * Add a new slot to a date poll. And insert default values for user's votes.
- *
- *
Create a new slot if no one exists for the given date
- *
Create a new moment if a slot already exists for the given date
- *
- *
- * @param $poll_id int The ID of the poll
- * @param $datetime int The datetime
- * @param $new_moment string The moment's name
- * @throws MomentAlreadyExistsException When the moment to add already exists in database
- */
- public function addDateSlot($poll_id, $datetime, $new_moment) {
- $this->logService->log('ADD_COLUMN', 'id:' . $poll_id . ', datetime:' . $datetime . ', moment:' . $new_moment);
-
- $slots = $this->slotRepository->listByPollId($poll_id);
- $result = $this->findInsertPosition($slots, $datetime);
-
- // Begin transaction
- $this->connect->beginTransaction();
-
- if ($result->slot !== null) {
- $slot = $result->slot;
- $moments = explode(',', $slot->moments);
-
- // Check if moment already exists (maybe not necessary)
- if (in_array($new_moment, $moments, true)) {
- throw new MomentAlreadyExistsException();
- }
-
- // Update found slot
- $moments[] = $new_moment;
- $this->slotRepository->update($poll_id, $datetime, implode(',', $moments));
- } else {
- $this->slotRepository->insert($poll_id, $datetime, $new_moment);
- }
-
- $this->voteRepository->insertDefault($poll_id, $result->insert);
-
- // Commit transaction
- $this->connect->commit();
- }
-
- /**
- * Add a new slot to a classic poll. And insert default values for user's votes.
- *
- *
Create a new slot if no one exists for the given title
- *
- *
- * @param $poll_id int The ID of the poll
- * @param $title int The title
- * @throws MomentAlreadyExistsException When the moment to add already exists in database
- */
- public function addClassicSlot($poll_id, $title) {
- $this->logService->log('ADD_COLUMN', 'id:' . $poll_id . ', title:' . $title);
-
- $slots = $this->slotRepository->listByPollId($poll_id);
-
- // Check if slot already exists
- $titles = array_map(function ($slot) {
- return $slot->title;
- }, $slots);
- if (in_array($title, $titles, true)) {
- // The moment already exists
- throw new MomentAlreadyExistsException();
- }
-
- // Begin transaction
- $this->connect->beginTransaction();
-
- // New slot
- $this->slotRepository->insert($poll_id, $title, null);
- // Set default votes
- $this->voteRepository->insertDefault($poll_id, count($slots));
-
- // Commit transaction
- $this->connect->commit();
- }
-
- /**
- * This method find where to insert a datatime+moment into a list of slots.
- * Return the {insert:X}, where X is the index of the moment into the whole poll (ex: X=0 => Insert to the first column).
- * Return {slot:Y}, where Y is not null if there is a slot existing for the given datetime.
- *
- * @param $slots array All the slots of the poll
- * @param $datetime int The datetime of the new slot
- * @return \stdClass An object like this one: {insert:X, slot:Y} where Y can be null.
- */
- private function findInsertPosition($slots, $datetime) {
- $result = new \stdClass();
- $result->slot = null;
- $result->insert = 0;
-
- // Sort slots before searching where to insert
- $this->pollService->sortSlorts($slots);
-
- // Search where to insert new column
- foreach ($slots as $k=>$slot) {
- $rowDatetime = $slot->title;
- $moments = explode(',', $slot->moments);
-
- if ($datetime === $rowDatetime) {
- // Here we have to insert at the end of a slot
- $result->insert += count($moments);
- $result->slot = $slot;
- break;
- } elseif ($datetime < $rowDatetime) {
- // We have to insert before this slot
- break;
- }
- $result->insert += count($moments);
- }
-
- return $result;
- }
-}
-
\ No newline at end of file
diff --git a/app/classes/Framadate/Services/MailService.php b/app/classes/Framadate/Services/MailService.php
deleted file mode 100644
index 9c32f3f..0000000
--- a/app/classes/Framadate/Services/MailService.php
+++ /dev/null
@@ -1,102 +0,0 @@
-logService = new LogService();
- $this->smtp_allowed = $smtp_allowed;
- if (true === is_array($smtp_options)) {
- $this->smtp_options = $smtp_options;
- }
- }
-
- public function isValidEmail($email) {
- return filter_var($email, FILTER_VALIDATE_EMAIL);
- }
-
- public function send($to, $subject, $body, $msgKey = null) {
- if ($this->smtp_allowed === true && $this->canSendMsg($msgKey)) {
- $mail = new PHPMailer(true);
- $this->configureMailer($mail);
-
- // From
- $mail->FromName = NOMAPPLICATION;
- $mail->From = ADRESSEMAILADMIN;
- if ($this->isValidEmail(ADRESSEMAILREPONSEAUTO)) {
- $mail->addReplyTo(ADRESSEMAILREPONSEAUTO);
- }
-
- // To
- $mail->addAddress($to);
-
- // Subject
- $mail->Subject = $subject;
-
- // Bodies
- $body = $body . '
' . __('Mail', 'Thanks for your trust.') . ' ' . NOMAPPLICATION . ' ' . __('Mail', 'FOOTER');
- $mail->isHTML(true);
- $mail->msgHTML($body, ROOT_DIR, true);
-
- // Build headers
- $mail->CharSet = 'UTF-8';
- $mail->addCustomHeader('Auto-Submitted', 'auto-generated');
- $mail->addCustomHeader('Return-Path', '<>');
-
- // Send mail
- $mail->send();
-
- // Log
- $this->logService->log('MAIL', 'Mail sent to: ' . $to . ', key: ' . $msgKey);
-
- // Store the mail sending date
- $_SESSION[self::MAILSERVICE_KEY][$msgKey] = time();
- }
- }
-
- public function canSendMsg($msgKey) {
- if ($msgKey === null) {
- return true;
- }
-
- if (!isset($_SESSION[self::MAILSERVICE_KEY])) {
- $_SESSION[self::MAILSERVICE_KEY] = [];
- }
- return !isset($_SESSION[self::MAILSERVICE_KEY][$msgKey]) || time() - $_SESSION[self::MAILSERVICE_KEY][$msgKey] > self::DELAY_BEFORE_RESEND;
- }
-
- /**
- * Configure the mailer with the options
- *
- * @param PHPMailer $mailer
- */
- private function configureMailer(PHPMailer $mailer) {
- $mailer->isSMTP();
-
- $available_options = [
- 'host' => 'Host',
- 'auth' => 'SMTPAuth',
- 'username' => 'Username',
- 'password' => 'Password',
- 'secure' => 'SMTPSecure',
- 'port' => 'Port',
- ];
-
- foreach ($available_options as $config_option => $mailer_option) {
- if (true === isset($this->smtp_options[$config_option]) && false === empty($this->smtp_options[$config_option])) {
- $mailer->{$mailer_option} = $this->smtp_options[$config_option];
- }
- }
- }
-}
diff --git a/app/classes/Framadate/Services/NotificationService.php b/app/classes/Framadate/Services/NotificationService.php
deleted file mode 100644
index bed7ec7..0000000
--- a/app/classes/Framadate/Services/NotificationService.php
+++ /dev/null
@@ -1,86 +0,0 @@
-mailService = $mailService;
- }
-
- /**
- * Send a notification to the poll admin to notify him about an update.
- *
- * @param $poll stdClass The poll
- * @param $name string The name user who triggered the notification
- * @param $type int cf: Constants on the top of this page
- */
- function sendUpdateNotification(stdClass $poll, $type, $name='') {
- if (!isset($_SESSION['mail_sent'])) {
- $_SESSION['mail_sent'] = [];
- }
-
- $isVoteAndCanSendIt = ($type === self::UPDATE_VOTE || $type === self::ADD_VOTE) && $poll->receiveNewVotes;
- $isCommentAndCanSendIt = $type === self::ADD_COMMENT && $poll->receiveNewComments;
- $isOtherType = $type !== self::UPDATE_VOTE && $type !== self::ADD_VOTE && $type !== self::ADD_COMMENT;
-
- if ($isVoteAndCanSendIt || $isCommentAndCanSendIt || $isOtherType) {
- if (self::isParticipation($type)) {
- $translationString = 'Poll\'s participation: %s';
- } else {
- $translationString = 'Notification of poll: %s';
- }
-
- $subject = '[' . NOMAPPLICATION . '] ' . __f('Mail', $translationString, $poll->title);
-
- $message = '';
-
- $urlSondage = Utils::getUrlSondage($poll->admin_id, true);
- $link = '' . $urlSondage . '' . "\n\n";
-
- switch ($type) {
- case self::UPDATE_VOTE:
- $message .= $name . ' ';
- $message .= __('Mail', "updated a vote.\nYou can find your poll at the link") . " :\n\n";
- $message .= $link;
- break;
- case self::ADD_VOTE:
- $message .= $name . ' ';
- $message .= __('Mail', "filled a vote.\nYou can find your poll at the link") . " :\n\n";
- $message .= $link;
- break;
- case self::ADD_COMMENT:
- $message .= $name . ' ';
- $message .= __('Mail', "wrote a comment.\nYou can find your poll at the link") . " :\n\n";
- $message .= $link;
- break;
- case self::UPDATE_POLL:
- $message = __f('Mail', 'Someone just change your poll available at the following link %s.', Utils::getUrlSondage($poll->admin_id, true)) . "\n\n";
- break;
- case self::DELETED_POLL:
- $message = __f('Mail', 'Someone just delete your poll %s.', Utils::htmlEscape($poll->title)) . "\n\n";
- break;
- }
-
- $messageTypeKey = $type . '-' . $poll->id;
- $this->mailService->send($poll->admin_mail, $subject, $message, $messageTypeKey);
- }
- }
-
- function isParticipation($type)
- {
- return $type >= self::UPDATE_POLL;
- }
-}
diff --git a/app/classes/Framadate/Services/PollService.php b/app/classes/Framadate/Services/PollService.php
deleted file mode 100644
index d3d6590..0000000
--- a/app/classes/Framadate/Services/PollService.php
+++ /dev/null
@@ -1,362 +0,0 @@
-connect = $connect;
- $this->logService = $logService;
- $this->pollRepository = RepositoryFactory::pollRepository();
- $this->slotRepository = RepositoryFactory::slotRepository();
- $this->voteRepository = RepositoryFactory::voteRepository();
- $this->commentRepository = RepositoryFactory::commentRepository();
- }
-
- /**
- * Find a poll from its ID.
- *
- * @param $poll_id int The ID of the poll
- * @return \stdClass|null The found poll, or null
- */
- function findById($poll_id) {
- if (preg_match(POLL_REGEX, $poll_id)) {
- return $this->pollRepository->findById($poll_id);
- }
-
- return null;
- }
-
- public function findByAdminId($admin_poll_id) {
- if (preg_match(ADMIN_POLL_REGEX, $admin_poll_id)) {
- return $this->pollRepository->findByAdminId($admin_poll_id);
- }
-
- return null;
- }
-
- function allCommentsByPollId($poll_id) {
- return $this->commentRepository->findAllByPollId($poll_id);
- }
-
- function allVotesByPollId($poll_id) {
- return $this->voteRepository->allUserVotesByPollId($poll_id);
- }
-
- function allSlotsByPoll($poll) {
- $slots = $this->slotRepository->listByPollId($poll->id);
- if ($poll->format === 'D') {
- $this->sortSlorts($slots);
- }
- return $slots;
- }
-
- /**
- * @param $poll_id
- * @param $vote_id
- * @param $name
- * @param $choices
- * @param $slots_hash
- * @throws AlreadyExistsException
- * @throws ConcurrentEditionException
- * @throws ConcurrentVoteException
- * @return bool
- */
- public function updateVote($poll_id, $vote_id, $name, $choices, $slots_hash) {
- $this->checkVoteConstraints($choices, $poll_id, $slots_hash, $name, $vote_id);
-
- // Update vote
- $choices = implode($choices);
- return $this->voteRepository->update($poll_id, $vote_id, $name, $choices);
- }
-
- /**
- * @param $poll_id
- * @param $name
- * @param $choices
- * @param $slots_hash
- * @throws AlreadyExistsException
- * @throws ConcurrentEditionException
- * @throws ConcurrentVoteException
- * @return \stdClass
- */
- function addVote($poll_id, $name, $choices, $slots_hash) {
- $this->checkVoteConstraints($choices, $poll_id, $slots_hash, $name);
-
- // Insert new vote
- $choices = implode($choices);
- $token = $this->random(16);
- return $this->voteRepository->insert($poll_id, $name, $choices, $token);
- }
-
- function addComment($poll_id, $name, $comment) {
- if ($this->commentRepository->exists($poll_id, $name, $comment)) {
- return true;
- }
-
- return $this->commentRepository->insert($poll_id, $name, $comment);
- }
-
- /**
- * @param Form $form
- * @return array
- */
- function createPoll(Form $form) {
- // Generate poll IDs, loop while poll ID already exists
-
- if (empty($form->id)) { // User want us to generate an id for him
- do {
- $poll_id = $this->random(16);
- } while ($this->pollRepository->existsById($poll_id));
- $admin_poll_id = $poll_id . $this->random(8);
- } else { // User have choosen the poll id
- $poll_id = $form->id;
- do {
- $admin_poll_id = $this->random(24);
- } while ($this->pollRepository->existsByAdminId($admin_poll_id));
- }
-
- // Insert poll + slots
- $this->pollRepository->beginTransaction();
- $this->pollRepository->insertPoll($poll_id, $admin_poll_id, $form);
- $this->slotRepository->insertSlots($poll_id, $form->getChoices());
- $this->pollRepository->commit();
-
- $this->logService->log('CREATE_POLL', 'id:' . $poll_id . ', title: ' . $form->title . ', format:' . $form->format . ', admin:' . $form->admin_name . ', mail:' . $form->admin_mail);
-
- return [$poll_id, $admin_poll_id];
- }
-
- public function findAllByAdminMail($mail) {
- return $this->pollRepository->findAllByAdminMail($mail);
- }
-
- /**
- * @param array $votes
- * @param \stdClass $poll
- * @return array
- */
- public function computeBestChoices($votes, $poll) {
- if (0 === count($votes)) {
- return $this->computeEmptyBestChoices($poll);
- }
- $result = ['y' => [], 'inb' => []];
-
- // if there are votes
- foreach ($votes as $vote) {
- $choices = str_split($vote->choices);
- foreach ($choices as $i => $choice) {
- if (!isset($result['y'][$i])) {
- $result['inb'][$i] = 0;
- $result['y'][$i] = 0;
- }
- if ($choice === "1") {
- $result['inb'][$i]++;
- }
- if ($choice === "2") {
- $result['y'][$i]++;
- }
- }
- }
-
- return $result;
- }
-
- function splitSlots($slots) {
- $splitted = [];
- foreach ($slots as $slot) {
- $obj = new \stdClass();
- $obj->day = $slot->title;
- $obj->moments = explode(',', $slot->moments);
-
- $splitted[] = $obj;
- }
-
- return $splitted;
- }
-
- /**
- * @param $slots array The slots to hash
- * @return string The hash
- */
- public function hashSlots($slots) {
- return md5(array_reduce($slots, function($carry, $item) {
- return $carry . $item->id . '@' . $item->moments . ';';
- }));
- }
-
- function splitVotes($votes) {
- $splitted = [];
- foreach ($votes as $vote) {
- $obj = new \stdClass();
- $obj->id = $vote->id;
- $obj->name = $vote->name;
- $obj->uniqId = $vote->uniqId;
- $obj->choices = str_split($vote->choices);
-
- $splitted[] = $obj;
- }
-
- return $splitted;
- }
-
- /**
- * @return int The max timestamp allowed for expiry date
- */
- public function maxExpiryDate() {
- global $config;
- return time() + (86400 * $config['default_poll_duration']);
- }
-
- /**
- * @return int The min timestamp allowed for expiry date
- */
- public function minExpiryDate() {
- return time() + 86400;
- }
-
- /**
- * @return mixed
- */
- public function sortSlorts(&$slots) {
- uasort($slots, function ($a, $b) {
- return $a->title > $b->title;
- });
- return $slots;
- }
-
- /**
- * @param \stdClass $poll
- * @return array
- */
- private function computeEmptyBestChoices($poll)
- {
- $result = ['y' => [], 'inb' => []];
- // if there is no votes, calculates the number of slot
-
- $slots = $this->allSlotsByPoll($poll);
-
- if ($poll->format === 'A') {
- // poll format classic
-
- for ($i = 0; $i < count($slots); $i++) {
- $result['y'][] = 0;
- $result['inb'][] = 0;
- }
- } else {
- // poll format date
-
- $slots = $this->splitSlots($slots);
-
- foreach ($slots as $slot) {
- for ($i = 0; $i < count($slot->moments); $i++) {
- $result['y'][] = 0;
- $result['inb'][] = 0;
- }
- }
- }
- return $result;
- }
-
- private function random($length) {
- return Token::getToken($length);
- }
-
- /**
- * @param $choices
- * @param $poll_id
- * @param $slots_hash
- * @param $name
- * @param string $vote_id
- * @throws AlreadyExistsException
- * @throws ConcurrentVoteException
- * @throws ConcurrentEditionException
- */
- private function checkVoteConstraints($choices, $poll_id, $slots_hash, $name, $vote_id = FALSE) {
- // Check if vote already exists with the same name
- if (FALSE === $vote_id) {
- $exists = $this->voteRepository->existsByPollIdAndName($poll_id, $name);
- } else {
- $exists = $this->voteRepository->existsByPollIdAndNameAndVoteId($poll_id, $name, $vote_id);
- }
-
- if ($exists) {
- throw new AlreadyExistsException();
- }
-
- $poll = $this->findById($poll_id);
-
- // Check that no-one voted in the meantime and it conflicts the maximum votes constraint
- $this->checkMaxVotes($choices, $poll, $poll_id);
-
- // Check if slots are still the same
- $this->checkThatSlotsDidntChanged($poll, $slots_hash);
- }
-
- /**
- * This method checks if the hash send by the user is the same as the computed hash.
- *
- * @param $poll /stdClass The poll
- * @param $slots_hash string The hash sent by the user
- * @throws ConcurrentEditionException Thrown when hashes are differents
- */
- private function checkThatSlotsDidntChanged($poll, $slots_hash) {
- $slots = $this->allSlotsByPoll($poll);
- if ($slots_hash !== $this->hashSlots($slots)) {
- throw new ConcurrentEditionException();
- }
- }
-
- /**
- * This method checks if the votes doesn't conflicts the maximum votes constraint
- *
- * @param $user_choice
- * @param \stdClass $poll
- * @param string $poll_id
- * @throws ConcurrentVoteException
- */
- private function checkMaxVotes($user_choice, $poll, $poll_id) {
- $votes = $this->allVotesByPollId($poll_id);
- if (count($votes) <= 0) {
- return;
- }
- $best_choices = $this->computeBestChoices($votes, $poll);
- foreach ($best_choices['y'] as $i => $nb_choice) {
- // if for this option we have reached maximum value and user wants to add itself too
- if ($poll->ValueMax !== null && $nb_choice >= $poll->ValueMax && $user_choice[$i] === "2") {
- throw new ConcurrentVoteException();
- }
- }
- }
-}
diff --git a/app/classes/Framadate/Services/PurgeService.php b/app/classes/Framadate/Services/PurgeService.php
deleted file mode 100644
index 7b59b7a..0000000
--- a/app/classes/Framadate/Services/PurgeService.php
+++ /dev/null
@@ -1,74 +0,0 @@
-logService = $logService;
- $this->pollRepository = RepositoryFactory::pollRepository();
- $this->slotRepository = RepositoryFactory::slotRepository();
- $this->voteRepository = RepositoryFactory::voteRepository();
- $this->commentRepository = RepositoryFactory::commentRepository();
- }
-
- /**
- * This methode purges all old polls (the ones with end_date in past).
- *
- * @return bool true is action succeeded
- */
- function purgeOldPolls() {
- $oldPolls = $this->pollRepository->findOldPolls();
- $count = count($oldPolls);
-
- if ($count > 0) {
- $this->logService->log('EXPIRATION', 'Going to purge ' . $count . ' poll(s)...');
-
- foreach ($oldPolls as $poll) {
- if ($this->purgePollById($poll->id)) {
- $this->logService->log('EXPIRATION_SUCCESS', 'id: ' . $poll->id . ', title:' . $poll->title . ', format: ' . $poll->format . ', admin: ' . $poll->admin_name);
- } else {
- $this->logService->log('EXPIRATION_FAILED', 'id: ' . $poll->id . ', title:' . $poll->title . ', format: ' . $poll->format . ', admin: ' . $poll->admin_name);
- }
- }
- }
-
- return $count;
- }
-
- /**
- * This methode delete all data about a poll.
- *
- * @param $poll_id int The ID of the poll
- * @return bool true is action succeeded
- */
- function purgePollById($poll_id) {
- $done = true;
-
- $this->pollRepository->beginTransaction();
- $done &= $this->commentRepository->deleteByPollId($poll_id);
- $done &= $this->voteRepository->deleteByPollId($poll_id);
- $done &= $this->slotRepository->deleteByPollId($poll_id);
- $done &= $this->pollRepository->deleteById($poll_id);
-
- if ($done) {
- $this->pollRepository->commit();
- } else {
- $this->pollRepository->rollback();
- }
-
- return $done;
- }
-}
-
\ No newline at end of file
diff --git a/app/classes/Framadate/Services/SecurityService.php b/app/classes/Framadate/Services/SecurityService.php
deleted file mode 100644
index f641052..0000000
--- a/app/classes/Framadate/Services/SecurityService.php
+++ /dev/null
@@ -1,91 +0,0 @@
-
- *
There no token with the given name in session
- *
The token time is in past
- *
- *
- * @param $tokan_name string The name of the CSRF token
- * @return Token The token
- */
- function getToken($tokan_name) {
- if (!isset($_SESSION['tokens'])) {
- $_SESSION['tokens'] = [];
- }
- if (!isset($_SESSION['tokens'][$tokan_name]) || $_SESSION['tokens'][$tokan_name]->isGone()) {
- $_SESSION['tokens'][$tokan_name] = new Token();
- }
-
- return $_SESSION['tokens'][$tokan_name]->getValue();
- }
-
- /**
- * Check if a given value is corresponding to the token in session.
- *
- * @param $tokan_name string Name of the token
- * @param $csrf string Value to check
- * @return bool true if the token is well checked
- */
- public function checkCsrf($tokan_name, $csrf) {
- $checked = $_SESSION['tokens'][$tokan_name]->getValue() === $csrf;
-
- if($checked) {
- unset($_SESSION['tokens'][$tokan_name]);
- }
-
- return $checked;
- }
-
- /**
- * Verify if the current session allows to access given poll.
- *
- * @param $poll \stdClass The poll which we seek access
- * @return bool true if the current session can access this poll
- */
- public function canAccessPoll($poll) {
- if (is_null($poll->password_hash)) {
- return true;
- }
-
- $this->ensureSessionPollSecurityIsCreated();
-
- $currentPassword = isset($_SESSION['poll_security'][$poll->id]) ? $_SESSION['poll_security'][$poll->id] : null;
- if (!empty($currentPassword) && PasswordHasher::verify($currentPassword, $poll->password_hash)) {
- return true;
- }
- unset($_SESSION['poll_security'][$poll->id]);
- return false;
- }
-
- /**
- * Submit to the session a poll password
- *
- * @param $poll \stdClass The poll which we seek access
- * @param $password string the password to compare
- */
- public function submitPollAccess($poll, $password) {
- if (!empty($password)) {
- $this->ensureSessionPollSecurityIsCreated();
- $_SESSION['poll_security'][$poll->id] = $password;
- }
- }
-
- private function ensureSessionPollSecurityIsCreated() {
- if (!isset($_SESSION['poll_security'])) {
- $_SESSION['poll_security'] = [];
- }
- }
-}
-
\ No newline at end of file
diff --git a/app/inc/constants.php b/app/inc/constants.php
deleted file mode 100644
index 44dd6ef..0000000
--- a/app/inc/constants.php
+++ /dev/null
@@ -1,44 +0,0 @@
-setDefaultLang(DEFAULT_LANGUAGE);
-$i18n->setPath(__DIR__ . '/../../locale');
-
-// Change langauge when user asked for it
-if (isset($_POST['lang']) && is_string($_POST['lang']) && in_array($_POST['lang'], array_keys($ALLOWED_LANGUAGES), true)) {
- $_SESSION['lang'] = $_POST['lang'];
-}
-
-/* */
-$i18n->get('', 'Something, just to load the dictionary');
-$locale = str_replace('_', '-', $i18n->getLoadedLang());
-
-/* Date Format */
-$date_format['txt_full'] = __('Date', 'FULL'); //summary in create_date_poll.php and removal date in choix_(date|autre).php
-$date_format['txt_short'] = __('Date', 'SHORT'); // radio title
-$date_format['txt_day'] = __('Date', 'DAY');
-$date_format['txt_date'] = __('Date', 'DATE');
-$date_format['txt_month_year'] = __('Date', 'MONTH_YEAR');
-$date_format['txt_datetime_short'] = __('Date', 'DATETIME');
-if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { //%e can't be used on Windows platform, use %#d instead
- foreach ($date_format as $k => $v) {
- $date_format[$k] = preg_replace('#(? 'Français',
- 'en' => 'English',
- 'es' => 'Español',
- 'de' => 'Deutsch',
- 'it' => 'Italiano',
- 'br' => 'Brezhoneg',
- ];
-}
-
-require_once __DIR__ . '/i18n.php';
-// Smarty
-require_once __DIR__ . '/smarty.php';
diff --git a/app/inc/smarty.php b/app/inc/smarty.php
deleted file mode 100644
index 96f57ac..0000000
--- a/app/inc/smarty.php
+++ /dev/null
@@ -1,103 +0,0 @@
-setTemplateDir(ROOT_DIR . '/tpl/');
-$smarty->setCompileDir(ROOT_DIR . COMPILE_DIR);
-$smarty->setCacheDir(ROOT_DIR . '/cache/');
-$smarty->caching = false;
-
-$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', strstr($_SERVER['SERVER_NAME'], 'framadate.org'));
-$smarty->assign('locale', $locale);
-$smarty->assign('langs', $ALLOWED_LANGUAGES);
-$smarty->assign('date_format', $date_format);
-if (isset($config['tracking_code'])) {
- $smarty->assign('tracking_code', $config['tracking_code']);
-}
-if (defined('FAVICON')) {
- $smarty->assign('favicon', FAVICON);
-}
-
-// Dev Mode
-if (isset($_SERVER['FRAMADATE_DEVMODE']) && $_SERVER['FRAMADATE_DEVMODE']) {
- $smarty->force_compile = true;
- $smarty->compile_check = true;
-} else {
- $smarty->force_compile = false;
- $smarty->compile_check = false;
-}
-
-function smarty_function_poll_url($params, Smarty_Internal_Template $template) {
- $poll_id = filter_var($params['id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]);
- $admin = (isset($params['admin']) && $params['admin']) ? true : false;
- $action = (isset($params['action']) && !empty($params['action'])) ? Utils::htmlEscape($params['action']) : false;
- $action_value = (isset($params['action_value']) && !empty($params['action_value'])) ? $params['action_value'] : false;
- $vote_unique_id = isset($params['vote_id']) ? filter_var($params['vote_id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]) : '';
-
- // If filter_var fails (i.e.: hack tentative), it will return false. At least no leak is possible from this.
-
- return Utils::getUrlSondage($poll_id, $admin, $vote_unique_id, $action, $action_value);
-}
-
-function smarty_modifier_markdown($md, $clear = false, $inline=true) {
- return Utils::markdown($md, $clear, $inline);
-}
-
-function smarty_modifier_resource($link) {
- return Utils::get_server_name() . $link;
-}
-function smarty_modifier_addslashes_single_quote($string) {
- return addcslashes($string, '\\\'');
-}
-
-function smarty_modifier_html($html) {
- return Utils::htmlEscape($html);
-}
-
-function smarty_modifier_datepicker_path($lang) {
- $i = 0;
- while (!is_file(path_for_datepicker_locale($lang)) && $i < 3) {
- $lang_arr = explode('-', $lang);
- if ($lang_arr && count($lang_arr) > 1) {
- $lang = $lang_arr[0];
- } else {
- $lang = 'en';
- }
- $i += 1;
- }
- return 'js/locales/bootstrap-datepicker.' . $lang . '.js';
-}
-
-function smarty_modifier_locale_2_lang($locale) {
- $lang_arr = explode('-', $locale);
- if ($lang_arr && count($lang_arr) > 1) {
- return $lang_arr[0];
- }
- return $locale;
-}
-
-function path_for_datepicker_locale($lang) {
- return __DIR__ . '/../../js/locales/bootstrap-datepicker.' . $lang . '.js';
-}
diff --git a/app/tests/Framadate/FramaTestCase.php b/app/tests/Framadate/FramaTestCase.php
deleted file mode 100644
index 6210a31..0000000
--- a/app/tests/Framadate/FramaTestCase.php
+++ /dev/null
@@ -1,23 +0,0 @@
-getTestResourcePath($resourcepath));
- }
-
- protected function invoke(&$object, $methodName) {
- $reflectionClass = new \ReflectionClass($object);
- $reflectionMethod = $reflectionClass->getMethod($methodName);
- $reflectionMethod->setAccessible(true);
-
- $params = array_slice(func_get_args(), 2); // get all the parameters after $methodName
- return $reflectionMethod->invokeArgs($object, $params);
- }
-}
diff --git a/app/tests/Framadate/Services/MailServiceUnitTest.php b/app/tests/Framadate/Services/MailServiceUnitTest.php
deleted file mode 100644
index f70e687..0000000
--- a/app/tests/Framadate/Services/MailServiceUnitTest.php
+++ /dev/null
@@ -1,32 +0,0 @@
- time() - 1000];
-
- // When
- $canSendMsg = $mailService->canSendMsg(self::MSG_KEY);
-
- // Then
- $this->assertSame(true, $canSendMsg);
- }
-
- public function test_should_not_send_2_mails_in_a_short_interval() {
- // Given
- $mailService = new MailService(true);
- $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time()];
-
- // When
- $canSendMsg = $mailService->canSendMsg(self::MSG_KEY);
-
- // Then
- $this->assertSame(false, $canSendMsg);
- }
-}
diff --git a/app/tests/bootstrap.php b/app/tests/bootstrap.php
deleted file mode 100644
index a5685d4..0000000
--- a/app/tests/bootstrap.php
+++ /dev/null
@@ -1,3 +0,0 @@
-addPsr4('Framadate\\', __DIR__ . '/Framadate');
diff --git a/assets/.gitignore b/assets/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/css/app/create_poll.css b/assets/css/app/create_poll.css
similarity index 91%
rename from css/app/create_poll.css
rename to assets/css/app/create_poll.css
index d17e7bf..7de91dc 100644
--- a/css/app/create_poll.css
+++ b/assets/css/app/create_poll.css
@@ -23,3 +23,7 @@
border-top: 0 none;
content: "";
}
+
+.required-parameter::after {
+ content: " *";
+}
diff --git a/css/bootstrap-theme.css.map b/assets/css/bootstrap-theme.css.map
similarity index 100%
rename from css/bootstrap-theme.css.map
rename to assets/css/bootstrap-theme.css.map
diff --git a/css/bootstrap-theme.min.css b/assets/css/bootstrap-theme.min.css
similarity index 100%
rename from css/bootstrap-theme.min.css
rename to assets/css/bootstrap-theme.min.css
diff --git a/css/bootstrap-theme.min.css.map b/assets/css/bootstrap-theme.min.css.map
similarity index 100%
rename from css/bootstrap-theme.min.css.map
rename to assets/css/bootstrap-theme.min.css.map
diff --git a/css/bootstrap.css.map b/assets/css/bootstrap.css.map
similarity index 100%
rename from css/bootstrap.css.map
rename to assets/css/bootstrap.css.map
diff --git a/css/bootstrap.min.css b/assets/css/bootstrap.min.css
similarity index 100%
rename from css/bootstrap.min.css
rename to assets/css/bootstrap.min.css
diff --git a/css/bootstrap.min.css.map b/assets/css/bootstrap.min.css.map
similarity index 100%
rename from css/bootstrap.min.css.map
rename to assets/css/bootstrap.min.css.map
diff --git a/css/frama.css b/assets/css/frama.css
similarity index 100%
rename from css/frama.css
rename to assets/css/frama.css
diff --git a/css/print.css b/assets/css/print.css
similarity index 91%
rename from css/print.css
rename to assets/css/print.css
index a109a78..9f09be1 100644
--- a/css/print.css
+++ b/assets/css/print.css
@@ -1,4 +1,4 @@
-@import url(./style.css);
+@import url(style.scss);
body {
background:none;
diff --git a/css/style.css b/assets/css/style.scss
similarity index 97%
rename from css/style.css
rename to assets/css/style.scss
index 9696951..f0a3c2d 100644
--- a/css/style.css
+++ b/assets/css/style.scss
@@ -14,6 +14,14 @@
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
* Auteurs d'OpenSondage : Framasoft (https://github.com/framasoft)
*/
+
+@import '~bootstrap/dist/css/bootstrap.css';
+@import '~bootstrap/dist/css/bootstrap-theme.css';
+// @import 'jquery-ui.min.css';
+@import '~bootstrap-datepicker/dist/css/bootstrap-datepicker3.css';
+@import '~simplemde/dist/simplemde.min.css';
+@import 'app/create_poll.css';
+
@font-face {
font-family: "DejaVu Sans";
src: url('../fonts/DejaVuSans.ttf');
@@ -91,10 +99,6 @@ header h1 {
margin-top:0;
}
-.summary {
- font-weight:bold;
-}
-
.summary img {
max-width:100px;
}
@@ -272,10 +276,11 @@ table.results thead th {
border:2px solid white;
padding: 5px;
min-width:40px;
- font-size:12px;
+ font-size: 13px;
max-width:100px;
overflow:hidden;
text-overflow:ellipsis;
+ font-weight: normal;
}
table.results thead th img {
diff --git a/fonts/DejaVu Fonts License.txt b/assets/fonts/DejaVu Fonts License.txt
similarity index 100%
rename from fonts/DejaVu Fonts License.txt
rename to assets/fonts/DejaVu Fonts License.txt
diff --git a/fonts/DejaVuSans-Bold.ttf b/assets/fonts/DejaVuSans-Bold.ttf
similarity index 100%
rename from fonts/DejaVuSans-Bold.ttf
rename to assets/fonts/DejaVuSans-Bold.ttf
diff --git a/fonts/DejaVuSans-BoldOblique.ttf b/assets/fonts/DejaVuSans-BoldOblique.ttf
similarity index 100%
rename from fonts/DejaVuSans-BoldOblique.ttf
rename to assets/fonts/DejaVuSans-BoldOblique.ttf
diff --git a/fonts/DejaVuSans-ExtraLight.ttf b/assets/fonts/DejaVuSans-ExtraLight.ttf
similarity index 100%
rename from fonts/DejaVuSans-ExtraLight.ttf
rename to assets/fonts/DejaVuSans-ExtraLight.ttf
diff --git a/fonts/DejaVuSans-Oblique.ttf b/assets/fonts/DejaVuSans-Oblique.ttf
similarity index 100%
rename from fonts/DejaVuSans-Oblique.ttf
rename to assets/fonts/DejaVuSans-Oblique.ttf
diff --git a/fonts/DejaVuSans.ttf b/assets/fonts/DejaVuSans.ttf
similarity index 100%
rename from fonts/DejaVuSans.ttf
rename to assets/fonts/DejaVuSans.ttf
diff --git a/fonts/glyphicons-halflings-regular.eot b/assets/fonts/glyphicons-halflings-regular.eot
similarity index 100%
rename from fonts/glyphicons-halflings-regular.eot
rename to assets/fonts/glyphicons-halflings-regular.eot
diff --git a/fonts/glyphicons-halflings-regular.svg b/assets/fonts/glyphicons-halflings-regular.svg
similarity index 100%
rename from fonts/glyphicons-halflings-regular.svg
rename to assets/fonts/glyphicons-halflings-regular.svg
diff --git a/fonts/glyphicons-halflings-regular.ttf b/assets/fonts/glyphicons-halflings-regular.ttf
similarity index 100%
rename from fonts/glyphicons-halflings-regular.ttf
rename to assets/fonts/glyphicons-halflings-regular.ttf
diff --git a/fonts/glyphicons-halflings-regular.woff b/assets/fonts/glyphicons-halflings-regular.woff
similarity index 100%
rename from fonts/glyphicons-halflings-regular.woff
rename to assets/fonts/glyphicons-halflings-regular.woff
diff --git a/fonts/glyphicons-halflings-regular.woff2 b/assets/fonts/glyphicons-halflings-regular.woff2
similarity index 100%
rename from fonts/glyphicons-halflings-regular.woff2
rename to assets/fonts/glyphicons-halflings-regular.woff2
diff --git a/images/classic.png b/assets/images/classic.png
similarity index 100%
rename from images/classic.png
rename to assets/images/classic.png
diff --git a/images/date.png b/assets/images/date.png
similarity index 100%
rename from images/date.png
rename to assets/images/date.png
diff --git a/images/logo-framadate.png b/assets/images/logo-framadate.png
similarity index 100%
rename from images/logo-framadate.png
rename to assets/images/logo-framadate.png
diff --git a/js/app/admin/polls.js b/assets/js/app/admin/polls.js
similarity index 100%
rename from js/app/admin/polls.js
rename to assets/js/app/admin/polls.js
diff --git a/js/app/adminstuds.js b/assets/js/app/adminstuds.js
similarity index 91%
rename from js/app/adminstuds.js
rename to assets/js/app/adminstuds.js
index fadda2a..6517bc1 100644
--- a/js/app/adminstuds.js
+++ b/assets/js/app/adminstuds.js
@@ -1,7 +1,12 @@
+import MDEWrapper from '../mde-wrapper';
+
$(document).ready(function() {
- wrapper = new MDEWrapper($('.js-desc textarea')[0], $('#rich-editor-button'), $('#simple-editor-button'));
+ if (document.getElementById('add-comment')) {
+ const wrapper = new MDEWrapper($('.js-desc textarea')[0], $('#rich-editor-button'), $('#simple-editor-button'));
+ }
var firstOpening = true;
+
$('[data-toggle="popover"]').popover();
function createNode(text) {
@@ -59,17 +64,19 @@ $(document).ready(function() {
}
});
- $('#title-form .btn-edit').on('click', function() {
- $('#title-form h3').hide();
+ const titleForm = $('#title-form');
+
+ titleForm.find('.btn-edit').on('click', function() {
+ titleForm.find('h3').hide();
$('.js-title').removeClass('hidden');
$('.js-title input').focus();
return false;
});
- $('#title-form .btn-cancel').on('click', function() {
- $('#title-form h3').show();
- $('#title-form .js-title').addClass('hidden');
- $('#title-form .btn-edit').focus();
+ titleForm.find('.btn-cancel').on('click', function() {
+ titleForm.find('h3').show();
+ titleForm.find('.js-title').addClass('hidden');
+ titleForm.find('.btn-edit').focus();
return false;
});
diff --git a/js/app/classic_poll.js b/assets/js/app/classic_poll.js
similarity index 79%
rename from js/app/classic_poll.js
rename to assets/js/app/classic_poll.js
index a091f4a..e1dc618 100644
--- a/js/app/classic_poll.js
+++ b/assets/js/app/classic_poll.js
@@ -19,10 +19,10 @@
// 2 choices filled and you can submit
- var submitChoicesAvalaible = function () {
+ var submitChoicesAvailable = function () {
var nb_filled_choices = 0;
$('.choice-field input').each(function () {
- if ($(this).val() != '') {
+ if ($(this).val() !== '') {
nb_filled_choices++;
}
});
@@ -36,8 +36,10 @@
};
// Handle form submission
- $(document.formulaire).on('submit', function (e) {
- if (!submitChoicesAvalaible()) {
+ $('form[name="formulaire-classic"]').on('submit', (e) => {
+ console.log("Submit form");
+ console.log(e);
+ if (!submitChoicesAvailable()) {
e.preventDefault();
e.stopPropagation();
}
@@ -74,23 +76,23 @@
$('.choice-field:last').remove();
var nb_choices = $('.choice-field').length;
$('#choice' + (nb_choices - 1)).focus();
- if (nb_choices == 1) {
+ if (nb_choices === 1) {
$('#remove-a-choice').addClass('disabled');
}
- submitChoicesAvalaible();
+ submitChoicesAvailable();
});
- $(document).on('keyup, change', '.choice-field input', function () {
- submitChoicesAvalaible();
+ $(document).on('keyup, change', '.choice-field input', () => {
+ submitChoicesAvailable();
});
- submitChoicesAvalaible();
+ submitChoicesAvailable();
// Button to build markdown from: link + image-url + text
- var md_a_imgModal = $('#md-a-imgModal');
- var md_text = $('#md-text');
- var md_img = $('#md-img');
- var md_val = $('#md-a');
+ const md_a_imgModal = $('#md-a-imgModal');
+ const md_text = $('#md-text');
+ const md_img = $('#md-img');
+ const md_val = $('#md-a');
$(document).on('click', '.md-a-img', function () {
md_a_imgModal.modal('show');
@@ -98,16 +100,16 @@
$('#md-a-imgModalLabel').text($(this).attr('title'));
});
md_a_imgModal.find('.btn-primary').on('click', function () {
- var text = md_text.val();
- var img = md_img.val();
- var link = md_val.val();
- var element = $('#' + $(this).val());
+ const text = md_text.val();
+ const img = md_img.val();
+ const link = md_val.val();
+ const element = $('#' + $(this).val());
- if (img != '' && link != '') {
+ if (img !== '' && link !== '') {
element.val('[](' + link + ')');
- } else if (img != '') {
+ } else if (img !== '') {
element.val('');
- } else if (link != '') {
+ } else if (link !== '') {
element.val('[' + (text?text:link) + '](' + link + ')');
} else {
element.val(text);
@@ -116,6 +118,6 @@
md_img.val('');
md_val.val('');
md_text.val('');
- submitChoicesAvalaible();
+ submitChoicesAvailable();
});
-})();
\ No newline at end of file
+})();
diff --git a/js/app/create_poll.js b/assets/js/app/create_poll.js
similarity index 57%
rename from js/app/create_poll.js
rename to assets/js/app/create_poll.js
index c3fcffc..e9f94a6 100644
--- a/js/app/create_poll.js
+++ b/assets/js/app/create_poll.js
@@ -16,14 +16,16 @@
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
-$(document).ready(function () {
+import MDEWrapper from '../mde-wrapper';
+
+$(document).ready(() => {
/**
* Error check when submitting form
*/
- $("#formulaire").submit(function (event) {
- var isHidden = $("#hidden").prop('checked');
- var isOptionAllUserCanModifyEverything = $("#editableByAll").is(":checked");
+ $('form[name="poll"]').submit((event) => {
+ const isHidden = $("#hidden").prop('checked');
+ const isOptionAllUserCanModifyEverything = $("#editableByAll").is(":checked");
if (isHidden && isOptionAllUserCanModifyEverything) {
event.preventDefault();
@@ -36,60 +38,71 @@ $(document).ready(function () {
/**
* Enable/Disable custom url options
*/
- $("#use_customized_url").change(function () {
- if ($(this).prop("checked")) {
+ function toggle_customized_url() {
+ if ($("#poll_use_customized_url").prop("checked")) {
$("#customized_url_options").removeClass("hidden");
} else {
$("#customized_url_options").addClass("hidden");
}
- });
+ }
- /**
+ /**
* Enable/Disable ValueMax options
*/
- $("#use_ValueMax").change(function () {
- if ($(this).prop("checked")) {
+ function toggle_use_value_max() {
+ if ($("#poll_use_ValueMax").prop("checked")) {
$("#ValueMax").removeClass("hidden");
} else {
$("#ValueMax").addClass("hidden");
}
- });
+ }
/**
* Hide/Show password options
*/
- $("#use_password").change(function(){
- if ($(this).prop("checked")) {
+ function toggle_use_password() {
+ if ($("#poll_use_password").prop("checked")) {
$("#password_options").removeClass("hidden");
} else {
$("#password_options").addClass("hidden");
}
- });
+ }
+
+ $("#poll_use_customized_url").change(toggle_customized_url);
+ $("#poll_use_ValueMax").change(toggle_use_value_max);
+ $("#poll_use_password").change(toggle_use_password);
+
+ toggle_customized_url();
+ toggle_use_value_max();
+ toggle_use_password();
// Check cookies are enabled too
- var cookieEnabled = function () {
- var cookieEnabled = navigator.cookieEnabled;
+ const cookieEnabled = () => {
+ let cookieEnabled = navigator.cookieEnabled;
// if not IE4+ nor NS6+
if (!cookieEnabled && typeof navigator.cookieEnabled === "undefined") {
document.cookie = "testcookie";
- cookieEnabled = document.cookie.indexOf("testcookie") != -1;
+ cookieEnabled = document.cookie.indexOf("testcookie") !== -1;
}
return cookieEnabled;
};
- if (cookieEnabled()) {
- // Show the form block
- document.getElementById("form-block").setAttribute("style", "");
- } else {
- // Show the warning about cookies
- document.getElementById("cookie-warning").setAttribute("style", "");
+ if (document.getElementById("form-block")) {
+ if (cookieEnabled()) {
+ // Show the form block
+ document.getElementById("form-block").setAttribute("style", "");
+ } else {
+ // Show the warning about cookies
+ document.getElementById("cookie-warning").setAttribute("style", "");
+ }
}
- var wrapper = new MDEWrapper($('#poll_comments')[0], $('#rich-editor-button'), $('#simple-editor-button'));
- if ($('#rich-editor-button').hasClass('active')) {
+ const rich_editor_button = document.getElementById('rich-editor-button');
+ const wrapper = new MDEWrapper(document.getElementById('poll_description'), rich_editor_button, document.getElementById('simple-editor-button'));
+ if ($(rich_editor_button).hasClass('active')) {
wrapper.enable();
}
diff --git a/js/app/date_poll.js b/assets/js/app/date_poll.js
similarity index 60%
rename from js/app/date_poll.js
rename to assets/js/app/date_poll.js
index a3a6110..0229776 100644
--- a/js/app/date_poll.js
+++ b/assets/js/app/date_poll.js
@@ -16,31 +16,35 @@
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
+import moment from 'moment';
+
$(document).ready(function () {
// Global variables
- var $selected_days = $('#selected-days');
- var $removeaday = $('#remove-a-day');
- var $copyhours = $('#copyhours');
- var $next = $('button[name="choixheures"]');
+ const $selected_days = $('#selected-days');
+ const $removeaday = $('#remove-a-day');
+ const $copyhours = $('#copyhours');
+ const $next = $('button[name="choixheures"]');
+
+ const $collectionHolder = $('#poll_date_choices_choices');
- var updateButtonState = function () {
+ const updateButtonState = () => {
$removeaday.toggleClass('disabled', $selected_days.find('fieldset').length <= 1);
$copyhours.toggleClass('disabled', !hasFirstDayFilledHours());
$next.toggleClass('disabled', countFilledDays() < 1)
};
// at least 1 day filled and you can submit
- var isSubmitDaysAvaillable = function() {
+ const isSubmitDaysAvailable = () => {
return (countFilledDays() >= 1);
};
- var countFilledDays = function () {
- var nb_filled_days = 0;
- $selected_days.find('fieldset legend input').each(function () {
- if ($(this).val() != '') {
+ const countFilledDays = () => {
+ let nb_filled_days = 0;
+ $selected_days.find('fieldset legend input').each(() => {
+ if ($(this).val() !== '') {
nb_filled_days++;
}
});
@@ -48,76 +52,49 @@ $(document).ready(function () {
};
- var hasFirstDayFilledHours = function () {
- var hasFilledHours = false;
- $selected_days.find('fieldset').first().find('.hours').each(function () {
- if ($(this).val() != '') {
+ const hasFirstDayFilledHours = () => {
+ let hasFilledHours = false;
+ $selected_days.find('fieldset').first().find('.hours').each((index, element) => {
+ if ($(element).val() !== '') {
hasFilledHours = true;
}
});
return hasFilledHours;
};
+ function addDayForm($collectionHolder, value) {
+ let newForm = $collectionHolder.data('prototype');
+ const index = $collectionHolder.find('input[type="date"]').length;
+ newForm = newForm.replace(/__name__/g, index);
- /**
- * Parse a string date
- * @param dateStr The string date
- * @param format The format PHP style (allowed: %Y, %m and %d)
- */
- var parseDate = function (dateStr, format) {
- var dtsplit = dateStr.split(/[\/ .:-]/);
- var dfsplit = format.split(/[\/ .:-]/);
-
- if (dfsplit.length != dtsplit.length) {
- return null;
+ const last_day = $selected_days.find('fieldset').filter(':last');
+ const new_day = last_day.after(newForm).next();
+ if (value) {
+ new_day.find('input[type="date"]').val(value);
}
+ const moments_div = new_day.find('div#poll_date_choices_choices_'+ index +'_moments');
- // creates assoc array for date
- var df = [];
- for (var dc = 0; dc < dtsplit.length; dc++) {
- df[dfsplit[dc]] = dtsplit[dc];
- }
+ const hour_form = moments_div.data('prototype');
+ const new_hour = moments_div.html(hour_form);
+ new_hour.after(hour_form);
+ new_hour.after(hour_form);
- // Build date
- return new Date(parseInt(df['%Y']), parseInt(df['%m']) - 1, parseInt(df['%d']), 0, 0, 0, 0);
- };
-
- var formatDate = function (date, format) {
- return format
- .replace('%d', ("00" +date.getDate()).slice(-2))
- .replace('%m', ("00" + (date.getMonth() + 1)).slice(-2))
- .replace('%Y', ("0000" + date.getFullYear()).slice(-4));
- };
-
- function getLastDayNumber(last_day) {
- if (last_day == null) {
- last_day = $selected_days.find('fieldset').filter(':last');
- }
- return parseInt(/^d([0-9]+)-h[0-9]+$/.exec($(last_day).find('.hours').filter(':first').attr('id'))[1])
}
- function newDateFields(dateStr) {
- var last_day = $selected_days.find('fieldset').filter(':last');
- var last_day_title = last_day.find('legend input').attr('title');
- var new_day_number = getLastDayNumber(last_day) + 1;
+ function addHourForm($collectionHolder) {
+ // Get the data-prototype explained earlier
+ let newForm = $collectionHolder.data('prototype');
- var re_id_hours = new RegExp('"d' + (new_day_number - 1) + '-h', 'g');
- var re_name_hours = new RegExp('name="horaires' + (new_day_number - 1), 'g');
+ newForm = newForm.replace(/__name__/g, $collectionHolder.find('input.hours').length);
- var new_day_html = last_day.html().replace(re_id_hours, '"d' + new_day_number + '-h')
- .replace('id="day' + (new_day_number - 1) + '"', 'id="day' + new_day_number + '"')
- .replace('for="day' + (new_day_number - 1) + '"', 'for="day' + new_day_number + '"')
- .replace(re_name_hours, 'name="horaires' + new_day_number)
- .replace(/value="(.*?)"/g, 'value=""')
- .replace(/hours" title="(.*?)"/g, 'hours" title="" p')
- .replace('title="' + last_day_title + '"', 'title="' + last_day_title.substring(0, last_day_title.indexOf(' ')) + ' ' + (new_day_number + 1) + '"');
+ // Display the form in the page in an li, before the "Add a tag" link li
+ const last_hour = $collectionHolder.find('.col-sm-2').filter(':last');
+ last_hour.after(newForm);
+ }
- last_day
- .after('')
- .next().find('legend input').val(dateStr);
- $('#day' + (new_day_number)).focus();
- updateButtonState();
+ function newDateFields(date) {
+ addDayForm($collectionHolder, date);
}
function manageRemoveadayAndCopyhoursButtons() {
@@ -128,12 +105,18 @@ $(document).ready(function () {
}
}
- var useFirstEmptyDateField = function (dateStr) {
- var used = false;
- $selected_days.find('fieldset legend input').each(function () {
+ /**
+ * Fills the first field
+ *
+ * @param dateStr
+ * @returns {boolean}
+ */
+ const useFirstEmptyDateField = (dateStr) => {
+ let used = false;
+ $selected_days.find('fieldset legend input[type="date"]').each((index, elem) => {
if (!used) {
- if ($(this).val() == '') {
- $(this).val(dateStr);
+ if ($(elem).val() == '') {
+ $(elem).val(dateStr);
used = true;
}
}
@@ -143,8 +126,8 @@ $(document).ready(function () {
};
// Handle form submission
- $(document.formulaire).on('submit', function (e) {
- if (!isSubmitDaysAvaillable()) {
+ $('form[name="formulaire-classic"]').on('submit', function (e) {
+ if (!isSubmitDaysAvailable()) {
e.preventDefault();
e.stopPropagation();
}
@@ -164,7 +147,7 @@ $(document).ready(function () {
$('#resetdays').on('click', function () {
$selected_days.find('fieldset:gt(0)').remove();
- $('#day0').focus();
+ $('input[type="date"]').val('').focus();
updateButtonState();
});
@@ -225,27 +208,27 @@ $(document).ready(function () {
// Buttons "Add an hour"
- $(document).on('click', '.add-an-hour', function () {
- var last_hour = $(this).parent('div').parent('div').prev();
- addHour(last_hour, $(this));
+ $(document).on('click', '.add-an-hour', function (e) {
+ const last_hour = $(e.target).parent('div').parent('div').prev();
+ addHourForm(last_hour);
});
// Buttons "Remove an hour"
- $(document).on('click', '.remove-an-hour', function () {
- var last_hour = $(this).parent('div').parent('div').prev();
+ $(document).on('click', '.remove-an-hour', function (e) {
+ const last_hour = $(e.target).parent('div').parent('div').prev().children('.col-sm-2').last();
// for and id
- var di_hj = last_hour.children('.hours').attr('id').split('-');
- var di = parseInt(di_hj[0].replace('d', ''));
- var hj = parseInt(di_hj[1].replace('h', ''));
+ const di_hj = last_hour.find('input').attr('id').split('_');
+ const hj = parseInt(di_hj[di_hj.length - 1]);
+ const di = parseInt(di_hj[di_hj.length - 3]);
// The first hour must not be removed
if (hj > 0) {
last_hour.remove();
$('#d' + di + '-h' + (hj - 1)).focus();
- $(this).next('.add-an-hour').removeClass('disabled');
- if (hj == 1) {
- $(this).addClass('disabled');
+ $(e.target).next('.add-an-hour').removeClass('disabled');
+ if (hj === 1) {
+ $(e.target).addClass('disabled');
}
}
updateButtonState();
@@ -254,23 +237,23 @@ $(document).ready(function () {
// Button "Add a day"
$('#add-a-day').on('click', function () {
- newDateFields();
+ //newDateFields();
+ addDayForm($collectionHolder);
});
// Button "Remove a day"
$removeaday.on('click', function () {
$selected_days.find('fieldset:last').remove();
- $('#day' + (getLastDayNumber() - 1)).focus();
updateButtonState();
});
// Button "Remove the current day"
- $(document).on('click', '.remove-day', function () {
- if ($('#days_container').find('fieldset').length > 1) {
- $(this).parents('fieldset').remove();
+ $(document).on('click', '.remove-day', (e) => {
+ if ($('#poll_date_choices_choices').find('fieldset').length > 1) {
+ $(e.target).parents('fieldset').remove();
}
updateButtonState();
});
@@ -280,30 +263,30 @@ $(document).ready(function () {
$('#interval_add').on('click', function (ev) {
var startDateField = $('#range_start');
var endDateField = $('#range_end');
- var startDate = parseDate(startDateField.val(), window.date_formats.DATE);
- var endDate = parseDate(endDateField.val(), window.date_formats.DATE);
+ const startDate = moment(startDateField.val());
+ const endDate = moment(endDateField.val());
// Clear error classes
startDateField.parent().removeClass('has-error');
endDateField.parent().removeClass('has-error');
- var maxDates = 123; // 123 = 4 months
- var tooMuchDates = endDate - startDate > maxDates * 86400 * 1000;
+ const maxDates = 123; // 123 = 4 months
+ const tooMuchDates = endDate.diff(startDate) > moment.duration(maxDates, 'days');
if (startDate != null && endDate != null && !tooMuchDates) {
- if (startDate <= endDate) {
- while (startDate <= endDate) {
- var dateStr = formatDate(startDate, window.date_formats.DATE);
- if (!useFirstEmptyDateField(dateStr)) {
- newDateFields(dateStr);
+ if (startDate.isSameOrBefore(endDate)) {
+ while (startDate.isSameOrBefore(endDate)) {
+ if (!useFirstEmptyDateField(startDate.format('YYYY-MM-DD'))) {
+ newDateFields(startDate.format('YYYY-MM-DD'));
}
- startDate.setDate(startDate.getDate() + 1);
+ startDate.add(1, 'day');
}
// Hide modal
startDateField.val('');
endDateField.val('');
$('#add_days').modal('hide');
+ // Dirty fix for modal not hiding
updateButtonState();
} else {
@@ -327,6 +310,14 @@ $(document).ready(function () {
});
+ $('.modal').on('hide.bs.modal', (e) => {
+ console.log(e);
+ });
+
+ $('.modal').on('hidden.bs.modal', (e) => {
+ console.log(e);
+ });
+
// Title update on hours and buttons -/+ hours
$(document).on('change', '.input-group.date input', function () {
diff --git a/js/app/framadatepicker.js b/assets/js/app/framadatepicker.js
similarity index 96%
rename from js/app/framadatepicker.js
rename to assets/js/app/framadatepicker.js
index 10847c6..7fef0b6 100644
--- a/js/app/framadatepicker.js
+++ b/assets/js/app/framadatepicker.js
@@ -15,11 +15,17 @@
* Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
+import $ from 'jquery';
+import 'bootstrap-datepicker';
+
$(document).ready(function () {
+
+ require(`../locales/bootstrap-datepicker.${lang}.js`);
+
var init_datepicker = function () {
$('.input-group.date').datepicker({
format: window.date_formats.DATEPICKER || "dd/mm/yyyy",
- todayBtn: "linked",
+ todayBtn: true,
orientation: "top left",
autoclose: true,
language: lang,
@@ -95,4 +101,4 @@ $(document).ready(function () {
}
});
-});
\ No newline at end of file
+});
diff --git a/js/app/studs.js b/assets/js/app/studs.js
similarity index 64%
rename from js/app/studs.js
rename to assets/js/app/studs.js
index 3322faf..3e3c60d 100644
--- a/js/app/studs.js
+++ b/assets/js/app/studs.js
@@ -16,6 +16,9 @@
* Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft)
*/
+import $ from 'jquery';
+import 'jquery-ui-bundle';
+
$(document).ready(function () {
$('#poll_form').submit(function (event) {
@@ -65,40 +68,37 @@ $(document).ready(function () {
type: 'POST',
url: form.attr('action'),
data: form.serialize(),
- dataType: 'json',
- success: function(data)
- {
- $('#comment').val('');
- if (data.result) {
- $('#comments_list')
- .replaceWith(data.comments);
- var lastComment = $('#comments_list')
- .find('div.comment')
- .last();
- // TODO : replace old jQuery UI Effect with Modern CSS
- // lastComment.effect('highlight', {color: 'green'}, 401);
- $('html, body').animate({
- scrollTop: lastComment.offset().top
- }, 750);
- } else {
- var newMessage = $('#genericErrorTemplate').clone();
- newMessage
- .find('.contents')
- .text(data.message.message);
- newMessage.removeClass('hidden');
- var commentsAlert = $('#comments_alerts');
- commentsAlert
- .empty()
- .append(newMessage);
- $('html, body').animate({
- scrollTop: commentsAlert.offset().top
- }, 750);
- }
- },
- complete: function() {
- $('#add_comment').removeAttr("disabled");
+ dataType: 'json'
+ }).done(function (data) {
+ $('#comment').val('');
+ if (data.result) {
+ const comment_list = $('#comments_list');
+ comment_list.append('