├── .editorconfig ├── .gitignore ├── .gitlab-ci.yml ├── .php_cs ├── AUTHORS.md ├── CHANGELOG.md ├── INSTALL.md ├── LICENCE.fr.txt ├── LICENSE.en.txt ├── README.md ├── action ├── add_comment.php └── send_edit_link_by_email_action.php ├── admin ├── check.php ├── index.php ├── install.php ├── logs.php ├── migration.php ├── polls.php └── purge.php ├── adminstuds.php ├── app ├── classes │ └── Framadate │ │ ├── Choice.php │ │ ├── Editable.php │ │ ├── Exception │ │ ├── AlreadyExistsException.php │ │ ├── ConcurrentEditionException.php │ │ ├── ConcurrentVoteException.php │ │ └── MomentAlreadyExistsException.php │ │ ├── Form.php │ │ ├── FramaDB.php │ │ ├── Message.php │ │ ├── Migration │ │ ├── AddColumn_ValueMax_In_poll_For_1_1.php │ │ ├── AddColumn_hidden_In_poll_For_0_9.php │ │ ├── AddColumn_receiveNewComments_For_0_9.php │ │ ├── AddColumn_uniqId_In_vote_For_0_9.php │ │ ├── AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9.php │ │ ├── Alter_Comment_table_adding_date.php │ │ ├── Alter_Comment_table_for_name_length.php │ │ ├── From_0_0_to_0_8_Migration.php │ │ ├── From_0_8_to_0_9_Migration.php │ │ ├── Generate_uniqId_for_old_votes.php │ │ ├── Increase_pollId_size.php │ │ ├── Migration.php │ │ └── RPadVotes_from_0_8.php │ │ ├── Repositories │ │ ├── AbstractRepository.php │ │ ├── CommentRepository.php │ │ ├── PollRepository.php │ │ ├── RepositoryFactory.php │ │ ├── SlotRepository.php │ │ └── VoteRepository.php │ │ ├── Security │ │ ├── PasswordHasher.php │ │ └── Token.php │ │ ├── Services │ │ ├── AdminPollService.php │ │ ├── InputService.php │ │ ├── InstallService.php │ │ ├── LogService.php │ │ ├── MailService.php │ │ ├── NotificationService.php │ │ ├── PollService.php │ │ ├── PurgeService.php │ │ ├── SecurityService.php │ │ ├── SessionService.php │ │ └── SuperAdminService.php │ │ └── Utils.php ├── inc │ ├── config.template.php │ ├── constants.php │ ├── i18n.php │ ├── init.php │ └── smarty.php └── tests │ ├── Framadate │ ├── FramaTestCase.php │ └── Services │ │ └── MailServiceUnitTest.php │ └── bootstrap.php ├── bandeaux.php ├── buildlang.php ├── compare.php ├── composer.json ├── composer.lock ├── create_classic_poll.php ├── create_date_poll.php ├── create_poll.php ├── css ├── app │ └── create_poll.css ├── bootstrap-theme.css ├── bootstrap-theme.css.map ├── bootstrap-theme.min.css ├── bootstrap-theme.min.css.map ├── bootstrap.css ├── bootstrap.css.map ├── bootstrap.min.css ├── bootstrap.min.css.map ├── datepicker.css ├── datepicker3.css ├── frama.css ├── jquery-ui.min.css ├── print.css ├── simplemde.min.css └── style.css ├── doc ├── TECHNICAL.md └── TREEVIEW.md ├── exportcsv.php ├── favicon.ico ├── find_polls.php ├── fonts ├── DejaVu Fonts License.txt ├── DejaVuSans-Bold.ttf ├── DejaVuSans-BoldOblique.ttf ├── DejaVuSans-ExtraLight.ttf ├── DejaVuSans-Oblique.ttf ├── DejaVuSans.ttf ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.svg ├── glyphicons-halflings-regular.ttf ├── glyphicons-halflings-regular.woff └── glyphicons-halflings-regular.woff2 ├── htaccess.txt ├── images ├── classic.png ├── date.png └── logo-framadate.png ├── index.php ├── js ├── Chart.StackedBar.js ├── Chart.min.js ├── app │ ├── admin │ │ └── polls.js │ ├── adminstuds.js │ ├── classic_poll.js │ ├── create_poll.js │ ├── date_poll.js │ ├── framadatepicker.js │ └── studs.js ├── bootstrap-datepicker.js ├── bootstrap.js ├── bootstrap.min.js ├── core.js ├── jquery-1.12.4.js ├── jquery-1.12.4.min.js ├── jquery-ui.min.js ├── locales │ ├── bootstrap-datepicker.ar.js │ ├── bootstrap-datepicker.az.js │ ├── bootstrap-datepicker.bg.js │ ├── bootstrap-datepicker.ca.js │ ├── bootstrap-datepicker.cs.js │ ├── bootstrap-datepicker.cy.js │ ├── bootstrap-datepicker.da.js │ ├── bootstrap-datepicker.de.js │ ├── bootstrap-datepicker.el.js │ ├── bootstrap-datepicker.es.js │ ├── bootstrap-datepicker.et.js │ ├── bootstrap-datepicker.fa.js │ ├── bootstrap-datepicker.fi.js │ ├── bootstrap-datepicker.fr.js │ ├── bootstrap-datepicker.gl.js │ ├── bootstrap-datepicker.he.js │ ├── bootstrap-datepicker.hr.js │ ├── bootstrap-datepicker.hu.js │ ├── bootstrap-datepicker.id.js │ ├── bootstrap-datepicker.is.js │ ├── bootstrap-datepicker.it.js │ ├── bootstrap-datepicker.ja.js │ ├── bootstrap-datepicker.ka.js │ ├── bootstrap-datepicker.kk.js │ ├── bootstrap-datepicker.kr.js │ ├── bootstrap-datepicker.lt.js │ ├── bootstrap-datepicker.lv.js │ ├── bootstrap-datepicker.mk.js │ ├── bootstrap-datepicker.ms.js │ ├── bootstrap-datepicker.nb.js │ ├── bootstrap-datepicker.nl-BE.js │ ├── bootstrap-datepicker.nl.js │ ├── bootstrap-datepicker.no.js │ ├── bootstrap-datepicker.pl.js │ ├── bootstrap-datepicker.pt-BR.js │ ├── bootstrap-datepicker.pt.js │ ├── bootstrap-datepicker.ro.js │ ├── bootstrap-datepicker.rs-latin.js │ ├── bootstrap-datepicker.rs.js │ ├── bootstrap-datepicker.ru.js │ ├── bootstrap-datepicker.sk.js │ ├── bootstrap-datepicker.sl.js │ ├── bootstrap-datepicker.sq.js │ ├── bootstrap-datepicker.sv.js │ ├── bootstrap-datepicker.sw.js │ ├── bootstrap-datepicker.th.js │ ├── bootstrap-datepicker.tr.js │ ├── bootstrap-datepicker.ua.js │ ├── bootstrap-datepicker.vi.js │ ├── bootstrap-datepicker.zh-CN.js │ └── bootstrap-datepicker.zh-TW.js ├── mde-wrapper.js └── simplemde.min.js ├── locale.bat ├── locale ├── br.json ├── de.json ├── en.json ├── es.json ├── fr.json ├── it.json ├── nl.json └── oc.json ├── maintenance.php ├── php.ini ├── phpunit.bat ├── phpunit.sh ├── po2json.php ├── robots.txt ├── scripts ├── .htaccess └── packaging.php ├── studs.php └── tpl ├── add_column.tpl ├── admin ├── admin_page.tpl ├── config.tpl ├── index.tpl ├── install.tpl ├── logs.tpl ├── migration.tpl ├── polls.tpl └── purge.tpl ├── confirm ├── delete_comments.tpl ├── delete_poll.tpl └── delete_votes.tpl ├── create_classic_poll_step3.tpl ├── create_date_poll_step_2.tpl ├── create_poll.tpl ├── error.tpl ├── find_polls.tpl ├── header.tpl ├── index.tpl ├── mail ├── find_polls.tpl └── remember_edit_link.tpl ├── maintenance.tpl ├── page.tpl ├── part ├── comments.tpl ├── comments_list.tpl ├── description_markdown.tpl ├── form_remember_edit_link.tpl ├── messages.tpl ├── password_request.tpl ├── poll_hint.tpl ├── poll_hint_admin.tpl ├── poll_info.tpl ├── scroll_left_right.tpl ├── vote_table_classic.tpl └── vote_table_date.tpl ├── poll_deleted.tpl └── studs.tpl /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .htaccess 2 | .htdigest 3 | .htpasswd 4 | admin/stdout.log 5 | composer.phar 6 | framanav 7 | nav 8 | app/inc/config.php 9 | vendor 10 | cache/ 11 | tpl_c/ 12 | .php_cs.cache 13 | 14 | # Temp files 15 | *~ 16 | \#*\# 17 | 18 | # Cache 19 | Thumbs.db 20 | 21 | # IDE 22 | .settings/ 23 | .project 24 | .idea/ 25 | *.iml 26 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: php 2 | stages: 3 | - test 4 | - deploy 5 | - funky 6 | 7 | # install zip, git, composer on each build 8 | before_script: 9 | - apt-get update -yqq 10 | - apt-get install zip unzip git -yqq 11 | - curl --silent --show-error https://getcomposer.org/installer | php 12 | 13 | # Run php-cs-fixer and phpunit on all branches 14 | test: 15 | stage: test 16 | script: 17 | - php composer.phar install -o --no-interaction --no-progress --prefer-dist 18 | - mkdir tpl_c 19 | - php vendor/bin/php-cs-fixer fix --verbose --dry-run 20 | - vendor/bin/phpunit --bootstrap app/tests/bootstrap.php --debug app/tests 21 | cache: 22 | paths: 23 | - vendor/ 24 | 25 | # Create artifacts on master 26 | pages: 27 | stage: deploy 28 | script: 29 | - latesttag=$(git describe --tags) 30 | - git checkout ${latesttag} 31 | - php composer.phar install -o --no-interaction --no-progress --prefer-dist --no-dev 32 | - php composer.phar dump-autoload --optimize --no-dev --classmap-authoritative 33 | - mkdir tpl_c 34 | - zip -r latest.zip . 35 | - mkdir .public 36 | - cp latest.zip .public 37 | - mv .public public 38 | artifacts: 39 | paths: 40 | - public 41 | only: 42 | - master 43 | 44 | # Deploy on funky 45 | funky: 46 | stage: funky 47 | script: 48 | - git checkout funky 49 | - php composer.phar install 50 | - mkdir tpl_c 51 | - mkdir .public 52 | - cp -r * .public 53 | - mv .public public 54 | - mkdir "${HOME}/.ssh" 55 | - chmod 700 "${HOME}/.ssh" 56 | - if [ ! -z ${DEPLOYEMENT_KNOWN_HOSTS+x} ]; then echo -e "${DEPLOYEMENT_KNOWN_HOSTS}" > ${HOME}/.ssh/known_hosts; fi 57 | - eval `ssh-agent -s` 58 | - if [ ! -z ${DEPLOYEMENT_KEY+x} ]; then ssh-add <(echo "${DEPLOYEMENT_KEY}" | base64 --decode -i); fi 59 | - if [ ! -z ${DEPLOYEMENT_KEY+x} ]; then rsync -a --delete --exclude admin/.stdout.log --exclude admin/.htpasswd --exclude app/inc/config.php --exclude stats/ --exclude errors/ public/ ${DEPLOYEMENT_USER}@${DEPLOYEMENT_HOST}:../../web/; fi 60 | only: 61 | - funky 62 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | setRiskyAllowed(true) 5 | ->setRules([ 6 | 'array_syntax' => [ 7 | 'syntax' => 'short' 8 | ], 9 | 'combine_consecutive_unsets' => true, 10 | 'heredoc_to_nowdoc' => true, 11 | 'no_extra_consecutive_blank_lines' => [ 12 | 'break', 13 | 'continue', 14 | 'extra', 15 | 'return', 16 | 'throw', 17 | 'use', 18 | 'parenthesis_brace_block', 19 | 'square_brace_block', 20 | 'curly_brace_block' 21 | ], 22 | 'no_unreachable_default_argument_value' => true, 23 | 'no_useless_else' => true, 24 | 'no_useless_return' => true, 25 | 'ordered_class_elements' => true, 26 | 'ordered_imports' => true, 27 | 'php_unit_strict' => true, 28 | 'phpdoc_order' => true, 29 | // 'psr4' => true, 30 | 'strict_comparison' => true, 31 | 'strict_param' => true, 32 | 'concat_space' => [ 33 | 'spacing' => 'one' 34 | ], 35 | ]) 36 | ->setFinder( 37 | PhpCsFixer\Finder::create() 38 | ->exclude([ 39 | 'vendor', 40 | 'var', 41 | 'web' 42 | ]) 43 | ->in(__DIR__) 44 | ) 45 | ; 46 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # [OpenSondage](https://opensondage.leblanc.io) 2 | * Simon Leblanc (development) 3 | 4 | # [Framasoft](http://framadate.org) 5 | * Pierre-Yves Gosset (development, graphism) 6 | * Pascal Chevrel (development) 7 | * Armony Altinier (accessibility) 8 | * JosephK (development) 9 | * Framasoft community 10 | *For a list of people who have contributed to the codebase, see [GitHub's list of contributors](https://github.com/framasoft/OpenSondage/graphs/contributors).* 11 | 12 | ## [STUdS](http://studs.u-strasbg.fr) 13 | * Guilhem Borghesi (borghesi@unistra.fr) 14 | * Raphaël Droz 15 | * Contributors from the University of Strasbourg: Guy, Christophe, Julien, Pierre, Romaric, Matthieu, Catherine, Christine, Olivier, Emmanuel and Florence 16 | 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | Un fichier est dédié à l'installation de OpenSondage : [INSTALL.md](INSTALL.md). 4 | 5 | # Comment contribuer 6 | 7 | ## Comprendre le code 8 | 9 | Un fichier est dédié à l'appréhension du code de OpenSondage : [Document technique](doc/TECHNICAL.md). 10 | 11 | # Traductions 12 | 13 | Les traductions se trouvent dans le dossier `locale`. Chaque langue est dans un fichier JSON différent organisé par section. 14 | 15 | # Synthèses des librairies utilisées 16 | 17 | [Smarty](http://www.smarty.net/), 18 | gestion des templates pour PHP 19 | 20 | [o80-i18n](https://github.com/olivierperez/o80-i18n), 21 | système d'internationalisation 22 | 23 | [PHP 5.4.4](http://php.net) 24 | 25 | PostgreSQL ou [MySQL 5.5](https://dev.mysql.com/downloads/mysql/5.5.html) 26 | 27 | --- 28 | 29 | OpenSondage est un fork du projet [STUdS](https://sourcesup.cru.fr/projects/studs/) 30 | 31 | Les auteurs principaux de OpenSondage sont : 32 | * Simon LEBLANC 33 | * Pierre-Yves GOSSET 34 | 35 | Les auteurs principaux du projet STUdS sont : 36 | * Guilhem BORGHESI 37 | * Raphaël DROZ 38 | 39 | --- 40 | 41 | Université de Strasbourg - Direction Informatique 42 | Auteur : Guilhem BORGHESI 43 | Création : Février 2008 44 | 45 | borghesi@unistra.fr 46 | 47 | Ce logiciel est régi par la licence CeCILL-B soumise au droit français et 48 | respectant les principes de diffusion des logiciels libres. Vous pouvez 49 | utiliser, modifier et/ou redistribuer ce programme sous les conditions 50 | de la licence CeCILL-B telle que diffusée par le CEA, le CNRS et l'INRIA 51 | sur le site "http://www.cecill.info". 52 | 53 | Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 54 | pris connaissance de la licence CeCILL-B, et que vous en avez accepté les 55 | termes. Vous pouvez trouver une copie de la licence dans le fichier LICENCE. 56 | 57 | --- 58 | 59 | Université de Strasbourg - Direction Informatique 60 | Author : Guilhem BORGHESI 61 | Creation : Feb 2008 62 | 63 | borghesi@unistra.fr 64 | 65 | This software is governed by the CeCILL-B license under French law and 66 | abiding by the rules of distribution of free software. You can use, 67 | modify and/ or redistribute the software under the terms of the CeCILL-B 68 | license as circulated by CEA, CNRS and INRIA at the following URL 69 | "http://www.cecill.info". 70 | 71 | The fact that you are presently reading this means that you have had 72 | knowledge of the CeCILL-B license and that you accept its terms. You can 73 | find a copy of this license in the file LICENSE. 74 | 75 | --- 76 | 77 | Janvier 2008 78 | Guilhem BORGHESI 79 | Université de Strasbourg 80 | 81 | Mai 2010 82 | Raphaël DROZ, raphael.droz@gmail.com 83 | 84 | -------------------------------------------------------------------------------- /action/add_comment.php: -------------------------------------------------------------------------------- 1 | ['regexp' => POLL_REGEX]]); 54 | $poll = $pollService->findById($poll_id); 55 | } 56 | 57 | if (!empty($_POST['poll_admin'])) { 58 | $admin_poll_id = filter_input(INPUT_POST, 'poll_admin', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); 59 | if (strlen($admin_poll_id) === 24) { 60 | $is_admin = ($pollService->findByAdminId($admin_poll_id) !== null); 61 | } 62 | } 63 | 64 | if (!$poll) { 65 | $message = new Message('error', __('Error', 'This poll doesn\'t exist !')); 66 | } else if ($poll && !$securityService->canAccessPoll($poll) && !$is_admin) { 67 | $message = new Message('error', __('Password', 'Wrong password')); 68 | } else { 69 | $name = $inputService->filterName($_POST['name']); 70 | $comment = $inputService->filterComment($_POST['comment']); 71 | 72 | if ($name === null) { 73 | $message = new Message('danger', __('Error', 'The name is invalid.')); 74 | } 75 | 76 | if ($message === null) { 77 | // Add comment 78 | $result = $pollService->addComment($poll_id, $name, $comment); 79 | if ($result) { 80 | $message = new Message('success', __('Comments', 'Comment added')); 81 | $notificationService->sendUpdateNotification($poll, NotificationService::ADD_COMMENT, $name); 82 | } else { 83 | $message = new Message('danger', __('Error', 'Comment failed')); 84 | } 85 | } 86 | $comments = $pollService->allCommentsByPollId($poll_id); 87 | } 88 | 89 | $smarty->error_reporting = E_ALL & ~E_NOTICE; 90 | $smarty->assign('comments', $comments); 91 | $comments_html = $smarty->fetch('part/comments_list.tpl'); 92 | 93 | $response = ['result' => $result, 'message' => $message, 'comments' => $comments_html]; 94 | 95 | echo json_encode($response); 96 | -------------------------------------------------------------------------------- /action/send_edit_link_by_email_action.php: -------------------------------------------------------------------------------- 1 | ['regexp' => POLL_REGEX]]); 42 | $poll = $pollService->findById($poll_id); 43 | } 44 | 45 | $token = $sessionService->get("Common", SESSION_EDIT_LINK_TOKEN); 46 | $token_form_value = empty($_POST['token']) ? null : $_POST['token']; 47 | $editedVoteUniqueId = filter_input(INPUT_POST, 'editedVoteUniqueId', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); 48 | if (is_null($poll) || $config['use_smtp'] === false || is_null($token) || is_null($token_form_value) 49 | || !$token->check($token_form_value) || is_null($editedVoteUniqueId)) { 50 | $message = new Message('error', __('Error', 'Something is going wrong...')); 51 | } 52 | 53 | if (is_null($message)) { 54 | $email = $mailService->isValidEmail($_POST['email']); 55 | if (is_null($email)) { 56 | $message = new Message('error', __('EditLink', 'The email address is not correct.')); 57 | } 58 | } 59 | 60 | if (is_null($message)) { 61 | $time = $sessionService->get("Common", SESSION_EDIT_LINK_TIME); 62 | 63 | if (!empty($time)) { 64 | $remainingTime = TIME_EDIT_LINK_EMAIL - (time() - $time); 65 | 66 | if ($remainingTime > 0) { 67 | $message = new Message('error', __f('EditLink', 'Please wait %d seconds before we can send an email to you then try again.', $remainingTime)); 68 | } 69 | } 70 | } 71 | 72 | if (is_null($message)) { 73 | $url = Utils::getUrlSondage($poll_id, false, $editedVoteUniqueId); 74 | 75 | $smarty->assign('poll', $poll); 76 | $smarty->assign('poll_id', $poll_id); 77 | $smarty->assign('editedVoteUniqueId', $editedVoteUniqueId); 78 | $body = $smarty->fetch('mail/remember_edit_link.tpl'); 79 | 80 | $subject = '[' . NOMAPPLICATION . '][' . __('EditLink', 'REMINDER') . '] ' . __f('EditLink', 'Edit link for poll "%s"', $poll->title); 81 | 82 | //$mailService->send($email, $subject, $body); 83 | $sessionService->remove("Common", SESSION_EDIT_LINK_TOKEN); 84 | $sessionService->set("Common", SESSION_EDIT_LINK_TIME, time()); 85 | 86 | $message = new Message('success', __('EditLink', 'Your reminder has been successfully sent!')); 87 | $result = true; 88 | } 89 | 90 | $smarty->error_reporting = E_ALL & ~E_NOTICE; 91 | 92 | $response = ['result' => $result, 'message' => $message]; 93 | 94 | echo json_encode($response); -------------------------------------------------------------------------------- /admin/index.php: -------------------------------------------------------------------------------- 1 | assign('title', __('Admin', 'Administration')); 23 | $smarty->assign('logsAreReadable', is_readable('../' . LOG_FILE)); 24 | $smarty->display('admin/index.tpl'); -------------------------------------------------------------------------------- /admin/install.php: -------------------------------------------------------------------------------- 1 | updateFields($_POST); 35 | $result = $installService->install($smarty); 36 | 37 | if ($result['status'] === 'OK') { 38 | header(('Location: ' . Utils::get_server_name() . 'admin/migration.php')); 39 | exit; 40 | } 41 | $error = __('Error', $result['code']); 42 | } 43 | 44 | $smarty->assign('error', $error); 45 | $smarty->assign('title', __('Admin', 'Installation')); 46 | $smarty->assign('fields', $installService->getFields()); 47 | $smarty->display('admin/install.tpl'); -------------------------------------------------------------------------------- /admin/logs.php: -------------------------------------------------------------------------------- 1 | assign('logs', $content); 27 | $smarty->assign('title', __('Admin', 'Logs')); 28 | 29 | $smarty->display('admin/logs.tpl'); -------------------------------------------------------------------------------- /admin/polls.php: -------------------------------------------------------------------------------- 1 | $value) { 36 | $query .= $key . '=' . urlencode($value) . '&'; 37 | } 38 | return substr($query, 0, -1); 39 | } 40 | 41 | /* --------- */ 42 | 43 | /* Variables */ 44 | /* --------- */ 45 | 46 | $polls = null; 47 | $poll_to_delete = null; 48 | 49 | /* Services */ 50 | /*----------*/ 51 | 52 | $logService = new LogService(); 53 | $pollService = new PollService($connect, $logService); 54 | $adminPollService = new AdminPollService($connect, $pollService, $logService); 55 | $superAdminService = new SuperAdminService(); 56 | $securityService = new SecurityService(); 57 | 58 | /* GET */ 59 | /*-----*/ 60 | $page = (int)filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT); 61 | $page = ($page >= 1) ? $page : 1; 62 | 63 | // Search 64 | $search['poll'] = filter_input(INPUT_GET, 'poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); 65 | $search['title'] = filter_input(INPUT_GET, 'title', FILTER_SANITIZE_STRING); 66 | $search['name'] = filter_input(INPUT_GET, 'name', FILTER_SANITIZE_STRING); 67 | $search['mail'] = filter_input(INPUT_GET, 'mail', FILTER_SANITIZE_STRING); 68 | 69 | /* PAGE */ 70 | /* ---- */ 71 | 72 | if (!empty($_POST['delete_poll']) && $securityService->checkCsrf('admin', $_POST['csrf'])) { 73 | $delete_id = filter_input(INPUT_POST, 'delete_poll', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); 74 | $poll_to_delete = $pollService->findById($delete_id); 75 | } 76 | 77 | // Traitement de la confirmation de suppression 78 | if (!empty($_POST['delete_confirm']) && $securityService->checkCsrf('admin', $_POST['csrf'])) { 79 | $poll_id = filter_input(INPUT_POST, 'delete_confirm', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); 80 | $adminPollService->deleteEntirePoll($poll_id); 81 | } 82 | 83 | $found = $superAdminService->findAllPolls($search, $page - 1, POLLS_PER_PAGE); 84 | $polls = $found['polls']; 85 | $count = $found['count']; 86 | $total = $found['total']; 87 | 88 | // Assign data to template 89 | $smarty->assign('polls', $polls); 90 | $smarty->assign('count', $count); 91 | $smarty->assign('total', $total); 92 | $smarty->assign('page', $page); 93 | $smarty->assign('pages', ceil($count / POLLS_PER_PAGE)); 94 | $smarty->assign('poll_to_delete', $poll_to_delete); 95 | $smarty->assign('crsf', $securityService->getToken('admin')); 96 | $smarty->assign('search', $search); 97 | $smarty->assign('search_query', buildSearchQuery($search)); 98 | 99 | $smarty->assign('title', __('Admin', 'Polls')); 100 | 101 | $smarty->display('admin/polls.tpl'); 102 | -------------------------------------------------------------------------------- /admin/purge.php: -------------------------------------------------------------------------------- 1 | filterName(isset($_POST['action']) ? $_POST['action'] : null); 45 | 46 | /* PAGE */ 47 | /* ---- */ 48 | 49 | if ($action === 'purge' && $securityService->checkCsrf('admin', $_POST['csrf'])) { 50 | $count = $purgeService->purgeOldPolls(); 51 | $message = __('Admin', 'Purged:') . ' ' . $count; 52 | } 53 | 54 | // Assign data to template 55 | $smarty->assign('message', $message); 56 | $smarty->assign('crsf', $securityService->getToken('admin')); 57 | 58 | $smarty->assign('title', __('Admin', 'Purge')); 59 | 60 | $smarty->display('admin/purge.tpl'); -------------------------------------------------------------------------------- /app/classes/Framadate/Choice.php: -------------------------------------------------------------------------------- 1 | name = $name; 36 | $this->slots = []; 37 | } 38 | 39 | public function addSlot($slot) 40 | { 41 | $this->slots[] = $slot; 42 | } 43 | 44 | public function getName() 45 | { 46 | return $this->name; 47 | } 48 | 49 | public function getSlots() 50 | { 51 | return $this->slots; 52 | } 53 | 54 | static function compare(Choice $a, Choice $b) 55 | { 56 | return strcmp($a->name, $b->name); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/classes/Framadate/Editable.php: -------------------------------------------------------------------------------- 1 | editable = Editable::EDITABLE_BY_ALL; 92 | $this->clearChoices(); 93 | } 94 | 95 | public function clearChoices() { 96 | $this->choices = []; 97 | } 98 | 99 | public function addChoice(Choice $choice) 100 | { 101 | $this->choices[] = $choice; 102 | } 103 | 104 | public function getChoices() 105 | { 106 | return $this->choices; 107 | } 108 | 109 | public function sortChoices() 110 | { 111 | usort($this->choices, ['Framadate\Choice', 'compare']); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /app/classes/Framadate/FramaDB.php: -------------------------------------------------------------------------------- 1 | pdo = new \PDO($connection_string, $user, $password); 31 | $this->pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ); 32 | $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); 33 | } 34 | 35 | /** 36 | * @return \PDO Connection to database 37 | */ 38 | function getPDO() { 39 | return $this->pdo; 40 | } 41 | 42 | /** 43 | * Find all tables in database. 44 | * 45 | * @return array The array of table names 46 | */ 47 | function allTables() { 48 | $result = $this->pdo->query('SHOW TABLES'); 49 | $schemas = $result->fetchAll(\PDO::FETCH_COLUMN); 50 | 51 | return $schemas; 52 | } 53 | 54 | function prepare($sql) { 55 | return $this->pdo->prepare($sql); 56 | } 57 | 58 | function beginTransaction() { 59 | $this->pdo->beginTransaction(); 60 | } 61 | 62 | function commit() { 63 | $this->pdo->commit(); 64 | } 65 | 66 | function rollback() { 67 | $this->pdo->rollback(); 68 | } 69 | 70 | function errorCode() { 71 | return $this->pdo->errorCode(); 72 | } 73 | 74 | function errorInfo() { 75 | return $this->pdo->errorInfo(); 76 | } 77 | 78 | function query($sql) { 79 | return $this->pdo->query($sql); 80 | } 81 | 82 | public function lastInsertId() { 83 | return $this->pdo->lastInsertId(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/classes/Framadate/Message.php: -------------------------------------------------------------------------------- 1 | type = $type; 31 | $this->message = $message; 32 | $this->link = $link; 33 | $this->linkTitle = $linkTitle; 34 | $this->linkIcon = $linkIcon; 35 | $this->includeTemplate = $includeTemplate; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/AddColumn_ValueMax_In_poll_For_1_1.php: -------------------------------------------------------------------------------- 1 | alterPollTable($pdo); 61 | 62 | return true; 63 | } 64 | 65 | private function alterPollTable(\PDO $pdo) { 66 | $pdo->exec(' 67 | ALTER TABLE `' . Utils::table('poll') . '` 68 | ADD `ValueMax` TINYINT, 69 | ADD CHECK (ValueMax > 0)'); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/AddColumn_hidden_In_poll_For_0_9.php: -------------------------------------------------------------------------------- 1 | query('SHOW TABLES'); 51 | $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); 52 | 53 | // Check if tables of v0.9 are presents 54 | $diff = array_diff([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')], $tables); 55 | return count($diff) === 0; 56 | } 57 | 58 | /** 59 | * This method is called only one time in the migration page. 60 | * 61 | * @param \PDO $pdo The connection to database 62 | * @return bool true is the execution succeeded 63 | */ 64 | function execute(\PDO $pdo) { 65 | $this->alterPollTable($pdo); 66 | 67 | return true; 68 | } 69 | 70 | private function alterPollTable(\PDO $pdo) { 71 | $pdo->exec(' 72 | ALTER TABLE `' . Utils::table('poll') . '` 73 | ADD `hidden` TINYINT( 1 ) NOT NULL DEFAULT "0"'); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/AddColumn_receiveNewComments_For_0_9.php: -------------------------------------------------------------------------------- 1 | query('SHOW TABLES'); 51 | $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); 52 | 53 | // Check if tables of v0.9 are presents 54 | $diff = array_diff([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')], $tables); 55 | return count($diff) === 0; 56 | } 57 | 58 | /** 59 | * This method is called only one time in the migration page. 60 | * 61 | * @param \PDO $pdo The connection to database 62 | * @return bool true is the execution succeeded 63 | */ 64 | function execute(\PDO $pdo) { 65 | $this->alterPollTable($pdo); 66 | 67 | return true; 68 | } 69 | 70 | private function alterPollTable(\PDO $pdo) { 71 | $pdo->exec(' 72 | ALTER TABLE `' . Utils::table('poll') . '` 73 | ADD `receiveNewComments` TINYINT(1) DEFAULT \'0\' 74 | AFTER `receiveNewVotes`'); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/AddColumn_uniqId_In_vote_For_0_9.php: -------------------------------------------------------------------------------- 1 | query('SHOW TABLES'); 51 | $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); 52 | 53 | // Check if tables of v0.9 are presents 54 | $diff = array_diff([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')], $tables); 55 | return count($diff) === 0; 56 | } 57 | 58 | /** 59 | * This method is called only one time in the migration page. 60 | * 61 | * @param \PDO $pdo The connection to database 62 | * @return bool true is the execution succeeded 63 | */ 64 | function execute(\PDO $pdo) { 65 | $this->alterPollTable($pdo); 66 | 67 | return true; 68 | } 69 | 70 | private function alterPollTable(\PDO $pdo) { 71 | $pdo->exec(' 72 | ALTER TABLE `' . Utils::table('vote') . '` 73 | ADD `uniqId` CHAR(16) NOT NULL 74 | AFTER `id`, 75 | ADD INDEX (`uniqId`) ;'); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/AddColumns_password_hash_And_results_publicly_visible_In_poll_For_0_9.php: -------------------------------------------------------------------------------- 1 | query('SHOW TABLES'); 51 | $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); 52 | 53 | // Check if tables of v0.9 are presents 54 | $diff = array_diff([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')], $tables); 55 | return count($diff) === 0; 56 | } 57 | 58 | /** 59 | * This method is called only one time in the migration page. 60 | * 61 | * @param \PDO $pdo The connection to database 62 | * @return bool true is the execution succeeded 63 | */ 64 | function execute(\PDO $pdo) { 65 | $this->alterPollTable($pdo); 66 | 67 | return true; 68 | } 69 | 70 | private function alterPollTable(\PDO $pdo) { 71 | $pdo->exec(' 72 | ALTER TABLE `' . Utils::table('poll') . '` 73 | ADD `password_hash` VARCHAR(255) NULL DEFAULT NULL , 74 | ADD `results_publicly_visible` TINYINT(1) NULL DEFAULT NULL'); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/Alter_Comment_table_adding_date.php: -------------------------------------------------------------------------------- 1 | alterCommentTable($pdo); 61 | 62 | return true; 63 | } 64 | 65 | private function alterCommentTable(\PDO $pdo) { 66 | $pdo->exec(' 67 | ALTER TABLE `' . Utils::table('comment') . '` 68 | ADD `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ;'); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/Alter_Comment_table_for_name_length.php: -------------------------------------------------------------------------------- 1 | alterCommentTable($pdo); 61 | 62 | return true; 63 | } 64 | 65 | private function alterCommentTable(\PDO $pdo) { 66 | $pdo->exec(' 67 | ALTER TABLE `' . Utils::table('comment') . '` 68 | CHANGE `name` `name` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ;'); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/Generate_uniqId_for_old_votes.php: -------------------------------------------------------------------------------- 1 | query('SHOW TABLES'); 40 | $tables = $stmt->fetchAll(\PDO::FETCH_COLUMN); 41 | 42 | // Check if tables of v0.9 are presents 43 | $diff = array_diff([Utils::table('poll'), Utils::table('slot'), Utils::table('vote'), Utils::table('comment')], $tables); 44 | return count($diff) === 0; 45 | } 46 | 47 | /** 48 | * This methode is called only one time in the migration page. 49 | * 50 | * @param \PDO $pdo The connection to database 51 | * @return bool true is the execution succeeded 52 | */ 53 | function execute(\PDO $pdo) { 54 | $pdo->beginTransaction(); 55 | $this->generateUniqIdsForEmptyOnes($pdo); 56 | $pdo->commit(); 57 | 58 | return true; 59 | } 60 | 61 | private function generateUniqIdsForEmptyOnes($pdo) { 62 | $select = $pdo->query(' 63 | SELECT `id` 64 | FROM `' . Utils::table('vote') . '` 65 | WHERE `uniqid` = \'\''); 66 | 67 | $update = $pdo->prepare(' 68 | UPDATE `' . Utils::table('vote') . '` 69 | SET `uniqid` = :uniqid 70 | WHERE `id` = :id'); 71 | 72 | while ($row = $select->fetch(\PDO::FETCH_OBJ)) { 73 | $token = Token::getToken(16); 74 | $update->execute([ 75 | 'uniqid' => $token, 76 | 'id' => $row->id 77 | ]); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/Increase_pollId_size.php: -------------------------------------------------------------------------------- 1 | alterCommentTable($pdo); 38 | $this->alterPollTable($pdo); 39 | $this->alterSlotTable($pdo); 40 | $this->alterVoteTable($pdo); 41 | } 42 | 43 | private function alterCommentTable(\PDO $pdo) { 44 | $pdo->exec(' 45 | ALTER TABLE `' . Utils::table('comment') . '` 46 | CHANGE `poll_id` `poll_id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;'); 47 | } 48 | 49 | private function alterPollTable(\PDO $pdo) { 50 | $pdo->exec(' 51 | ALTER TABLE `' . Utils::table('poll') . '` 52 | CHANGE `id` `id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;'); 53 | } 54 | 55 | private function alterSlotTable(\PDO $pdo) { 56 | $pdo->exec(' 57 | ALTER TABLE `' . Utils::table('slot') . '` 58 | CHANGE `poll_id` `poll_id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;'); 59 | } 60 | 61 | private function alterVoteTable(\PDO $pdo) { 62 | $pdo->exec(' 63 | ALTER TABLE `' . Utils::table('vote') . '` 64 | CHANGE `poll_id` `poll_id` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/classes/Framadate/Migration/Migration.php: -------------------------------------------------------------------------------- 1 | connect = $connect; 18 | } 19 | 20 | public function beginTransaction() { 21 | $this->connect->beginTransaction(); 22 | } 23 | 24 | public function commit() { 25 | $this->connect->commit(); 26 | } 27 | 28 | function rollback() { 29 | $this->connect->rollback(); 30 | } 31 | 32 | public function prepare($sql) { 33 | return $this->connect->prepare($sql); 34 | } 35 | 36 | function query($sql) { 37 | return $this->connect->query($sql); 38 | } 39 | 40 | function lastInsertId() { 41 | return $this->connect->lastInsertId(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/classes/Framadate/Repositories/CommentRepository.php: -------------------------------------------------------------------------------- 1 | prepare('SELECT * FROM `' . Utils::table('comment') . '` WHERE poll_id = ? ORDER BY id'); 14 | $prepared->execute([$poll_id]); 15 | 16 | return $prepared->fetchAll(); 17 | } 18 | 19 | /** 20 | * Insert a new comment. 21 | * 22 | * @param $poll_id 23 | * @param $name 24 | * @param $comment 25 | * @return bool 26 | */ 27 | function insert($poll_id, $name, $comment) { 28 | $prepared = $this->prepare('INSERT INTO `' . Utils::table('comment') . '` (poll_id, name, comment) VALUES (?,?,?)'); 29 | 30 | return $prepared->execute([$poll_id, $name, $comment]); 31 | } 32 | 33 | function deleteById($poll_id, $comment_id) { 34 | $prepared = $this->prepare('DELETE FROM `' . Utils::table('comment') . '` WHERE poll_id = ? AND id = ?'); 35 | 36 | return $prepared->execute([$poll_id, $comment_id]); 37 | } 38 | 39 | /** 40 | * Delete all comments of a given poll. 41 | * 42 | * @param $poll_id int The ID of the given poll. 43 | * @return bool|null true if action succeeded. 44 | */ 45 | function deleteByPollId($poll_id) { 46 | $prepared = $this->prepare('DELETE FROM `' . Utils::table('comment') . '` WHERE poll_id = ?'); 47 | 48 | return $prepared->execute([$poll_id]); 49 | } 50 | 51 | public function exists($poll_id, $name, $comment) { 52 | $prepared = $this->prepare('SELECT 1 FROM `' . Utils::table('comment') . '` WHERE poll_id = ? AND name = ? AND comment = ?'); 53 | $prepared->execute([$poll_id, $name, $comment]); 54 | 55 | return $prepared->rowCount() > 0; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/classes/Framadate/Repositories/RepositoryFactory.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/app/classes/Framadate/Repositories/RepositoryFactory.php -------------------------------------------------------------------------------- /app/classes/Framadate/Repositories/SlotRepository.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/app/classes/Framadate/Repositories/SlotRepository.php -------------------------------------------------------------------------------- /app/classes/Framadate/Repositories/VoteRepository.php: -------------------------------------------------------------------------------- 1 | prepare('SELECT * FROM `' . Utils::table('vote') . '` WHERE poll_id = ? ORDER BY id'); 14 | $prepared->execute([$poll_id]); 15 | 16 | return $prepared->fetchAll(); 17 | } 18 | 19 | function insertDefault($poll_id, $insert_position) { 20 | $prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = CONCAT(SUBSTRING(choices, 1, ?), " ", SUBSTRING(choices, ?)) WHERE poll_id = ?'); //#51 : default value for unselected vote 21 | 22 | return $prepared->execute([$insert_position, $insert_position + 1, $poll_id]); 23 | } 24 | 25 | function insert($poll_id, $name, $choices, $token) { 26 | $prepared = $this->prepare('INSERT INTO `' . Utils::table('vote') . '` (poll_id, name, choices, uniqId) VALUES (?,?,?,?)'); 27 | $prepared->execute([$poll_id, $name, $choices, $token]); 28 | 29 | $newVote = new \stdClass(); 30 | $newVote->poll_id = $poll_id; 31 | $newVote->id = $this->lastInsertId(); 32 | $newVote->name = $name; 33 | $newVote->choices = $choices; 34 | $newVote->uniqId = $token; 35 | 36 | return $newVote; 37 | } 38 | 39 | function deleteById($poll_id, $vote_id) { 40 | $prepared = $this->prepare('DELETE FROM `' . Utils::table('vote') . '` WHERE poll_id = ? AND id = ?'); 41 | 42 | return $prepared->execute([$poll_id, $vote_id]); 43 | } 44 | 45 | /** 46 | * Delete all votes of a given poll. 47 | * 48 | * @param $poll_id int The ID of the given poll. 49 | * @return bool|null true if action succeeded. 50 | */ 51 | function deleteByPollId($poll_id) { 52 | $prepared = $this->prepare('DELETE FROM `' . Utils::table('vote') . '` WHERE poll_id = ?'); 53 | 54 | return $prepared->execute([$poll_id]); 55 | } 56 | 57 | /** 58 | * Delete all votes made on given moment index. 59 | * 60 | * @param $poll_id int The ID of the poll 61 | * @param $index int The index of the vote into the poll 62 | * @return bool|null true if action succeeded. 63 | */ 64 | function deleteByIndex($poll_id, $index) { 65 | $prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = CONCAT(SUBSTR(choices, 1, ?), SUBSTR(choices, ?)) WHERE poll_id = ?'); 66 | 67 | return $prepared->execute([$index, $index + 2, $poll_id]); 68 | } 69 | 70 | function update($poll_id, $vote_id, $name, $choices) { 71 | $prepared = $this->prepare('UPDATE `' . Utils::table('vote') . '` SET choices = ?, name = ? WHERE poll_id = ? AND id = ?'); 72 | 73 | return $prepared->execute([$choices, $name, $poll_id, $vote_id]); 74 | } 75 | 76 | /** 77 | * Check if name is already used for the given poll. 78 | * 79 | * @param int $poll_id ID of the poll 80 | * @param string $name Name of the vote 81 | * @return bool true if vote already exists 82 | */ 83 | public function existsByPollIdAndName($poll_id, $name) { 84 | $prepared = $this->prepare('SELECT 1 FROM `' . Utils::table('vote') . '` WHERE poll_id = ? AND name = ?'); 85 | $prepared->execute([$poll_id, $name]); 86 | return $prepared->rowCount() > 0; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/classes/Framadate/Security/PasswordHasher.php: -------------------------------------------------------------------------------- 1 | length = $length; 13 | $this->time = time() + TOKEN_TIME; 14 | $this->value = $this->generate(); 15 | } 16 | 17 | public function getTime() { 18 | return $this->time; 19 | } 20 | 21 | public function getValue() { 22 | return $this->value; 23 | } 24 | 25 | public function isGone() { 26 | return $this->time < time(); 27 | } 28 | 29 | public function check($value) { 30 | return $value === $this->value; 31 | } 32 | 33 | /** 34 | * Get a secure token if possible, or a less secure one if not. 35 | * 36 | * @param int $length The token length 37 | * @param bool $crypto_strong If passed, tells if the token is "cryptographically strong" or not. 38 | * @return string 39 | */ 40 | public static function getToken($length = self::DEFAULT_LENGTH, &$crypto_strong = false) { 41 | if (function_exists('openssl_random_pseudo_bytes')) { 42 | openssl_random_pseudo_bytes(1, $crypto_strong); // Fake use to see if the algorithm used was "cryptographically strong" 43 | return self::getSecureToken($length); 44 | } 45 | return self::getUnsecureToken($length); 46 | } 47 | 48 | public static function getUnsecureToken($length) { 49 | $string = ''; 50 | mt_srand(); 51 | for ($i = 0; $i < $length; $i++) { 52 | $string .= self::$codeAlphabet[mt_rand() % strlen(self::$codeAlphabet)]; 53 | } 54 | 55 | return $string; 56 | } 57 | 58 | /** 59 | * @author http://stackoverflow.com/a/13733588 60 | */ 61 | public static function getSecureToken($length){ 62 | $token = ""; 63 | for($i=0;$i<$length;$i++){ 64 | $token .= self::$codeAlphabet[self::crypto_rand_secure(0,strlen(self::$codeAlphabet))]; 65 | } 66 | return $token; 67 | } 68 | 69 | private function generate() { 70 | return self::getToken($this->length); 71 | } 72 | 73 | /** 74 | * @author http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322 75 | */ 76 | private static function crypto_rand_secure($min, $max) { 77 | $range = $max - $min; 78 | if ($range < 0) return $min; // not so random... 79 | $log = log($range, 2); 80 | $bytes = (int) ($log / 8) + 1; // length in bytes 81 | $bits = (int) $log + 1; // length in bits 82 | $filter = (int) (1 << $bits) - 1; // set all lower bits to 1 83 | do { 84 | $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes))); 85 | $rnd = $rnd & $filter; // discard irrelevant bits 86 | } while ($rnd >= $range); 87 | return $min + $rnd; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/classes/Framadate/Services/LogService.php: -------------------------------------------------------------------------------- 1 | logService = new LogService(); 22 | $this->smtp_allowed = $smtp_allowed; 23 | if (true === is_array($smtp_options)) { 24 | $this->smtp_options = $smtp_options; 25 | } 26 | } 27 | 28 | public function isValidEmail($email) { 29 | return filter_var($email, FILTER_VALIDATE_EMAIL); 30 | } 31 | 32 | function send($to, $subject, $body, $msgKey = null) { 33 | if ($this->smtp_allowed === true && $this->canSendMsg($msgKey)) { 34 | $mail = new PHPMailer(true); 35 | $this->configureMailer($mail); 36 | 37 | // From 38 | $mail->FromName = NOMAPPLICATION; 39 | $mail->From = ADRESSEMAILADMIN; 40 | if ($this->isValidEmail(ADRESSEMAILREPONSEAUTO)) { 41 | $mail->addReplyTo(ADRESSEMAILREPONSEAUTO); 42 | } 43 | 44 | // To 45 | $mail->addAddress($to); 46 | 47 | // Subject 48 | $mail->Subject = $subject; 49 | 50 | // Bodies 51 | $body = $body . '

' . __('Mail', 'Thanks for your trust.') . '
' . NOMAPPLICATION . '
' . __('Mail', 'FOOTER'); 52 | $mail->isHTML(true); 53 | $mail->msgHTML($body, ROOT_DIR, true); 54 | 55 | // Build headers 56 | $mail->CharSet = 'UTF-8'; 57 | $mail->addCustomHeader('Auto-Submitted', 'auto-generated'); 58 | $mail->addCustomHeader('Return-Path', '<>'); 59 | 60 | // Send mail 61 | $mail->send(); 62 | 63 | // Log 64 | $this->logService->log('MAIL', 'Mail sent to: ' . $to . ', key: ' . $msgKey); 65 | 66 | // Store the mail sending date 67 | $_SESSION[self::MAILSERVICE_KEY][$msgKey] = time(); 68 | } 69 | } 70 | 71 | function canSendMsg($msgKey) { 72 | if ($msgKey === null) { 73 | return true; 74 | } 75 | 76 | if (!isset($_SESSION[self::MAILSERVICE_KEY])) { 77 | $_SESSION[self::MAILSERVICE_KEY] = []; 78 | } 79 | return !isset($_SESSION[self::MAILSERVICE_KEY][$msgKey]) || time() - $_SESSION[self::MAILSERVICE_KEY][$msgKey] > self::DELAY_BEFORE_RESEND; 80 | } 81 | 82 | /** 83 | * Configure the mailer with the options 84 | * 85 | * @param PHPMailer $mailer 86 | */ 87 | private function configureMailer(PHPMailer $mailer) { 88 | $mailer->isSMTP(); 89 | 90 | $available_options = [ 91 | 'host' => 'Host', 92 | 'auth' => 'SMTPAuth', 93 | 'username' => 'Username', 94 | 'password' => 'Password', 95 | 'secure' => 'SMTPSecure', 96 | 'port' => 'Port', 97 | ]; 98 | 99 | foreach ($available_options as $config_option => $mailer_option) { 100 | if ( 101 | true === isset($this->smtp_options[$config_option]) 102 | && 103 | false === empty($this->smtp_options[$config_option]) 104 | ) { 105 | $mailer->{$mailer_option} = $this->smtp_options[$config_option]; 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/classes/Framadate/Services/NotificationService.php: -------------------------------------------------------------------------------- 1 | mailService = $mailService; 21 | } 22 | 23 | /** 24 | * Send a notification to the poll admin to notify him about an update. 25 | * 26 | * @param $poll stdClass The poll 27 | * @param $name string The name user who triggered the notification 28 | * @param $type int cf: Constants on the top of this page 29 | */ 30 | function sendUpdateNotification(stdClass $poll, $type, $name='') { 31 | if (!isset($_SESSION['mail_sent'])) { 32 | $_SESSION['mail_sent'] = []; 33 | } 34 | 35 | $isVoteAndCanSendIt = ($type === self::UPDATE_VOTE || $type === self::ADD_VOTE) && $poll->receiveNewVotes; 36 | $isCommentAndCanSendIt = $type === self::ADD_COMMENT && $poll->receiveNewComments; 37 | $isOtherType = $type !== self::UPDATE_VOTE && $type !== self::ADD_VOTE && $type !== self::ADD_COMMENT; 38 | 39 | if ($isVoteAndCanSendIt || $isCommentAndCanSendIt || $isOtherType) { 40 | if (self::isParticipation($type)) { 41 | $translationString = 'Poll\'s participation: %s'; 42 | } else { 43 | $translationString = 'Notification of poll: %s'; 44 | } 45 | 46 | $subject = '[' . NOMAPPLICATION . '] ' . __f('Mail', $translationString, $poll->title); 47 | 48 | $message = ''; 49 | 50 | $urlSondage = Utils::getUrlSondage($poll->admin_id, true); 51 | $link = '' . $urlSondage . '' . "\n\n"; 52 | 53 | switch ($type) { 54 | case self::UPDATE_VOTE: 55 | $message .= $name . ' '; 56 | $message .= __('Mail', "updated a vote.\nYou can find your poll at the link") . " :\n\n"; 57 | $message .= $link; 58 | break; 59 | case self::ADD_VOTE: 60 | $message .= $name . ' '; 61 | $message .= __('Mail', "filled a vote.\nYou can find your poll at the link") . " :\n\n"; 62 | $message .= $link; 63 | break; 64 | case self::ADD_COMMENT: 65 | $message .= $name . ' '; 66 | $message .= __('Mail', "wrote a comment.\nYou can find your poll at the link") . " :\n\n"; 67 | $message .= $link; 68 | break; 69 | case self::UPDATE_POLL: 70 | $message = __f('Mail', 'Someone just change your poll available at the following link %s.', Utils::getUrlSondage($poll->admin_id, true)) . "\n\n"; 71 | break; 72 | case self::DELETED_POLL: 73 | $message = __f('Mail', 'Someone just delete your poll %s.', Utils::htmlEscape($poll->title)) . "\n\n"; 74 | break; 75 | } 76 | 77 | $messageTypeKey = $type . '-' . $poll->id; 78 | $this->mailService->send($poll->admin_mail, $subject, $message, $messageTypeKey); 79 | } 80 | } 81 | 82 | function isParticipation($type) 83 | { 84 | return $type >= self::UPDATE_POLL; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/classes/Framadate/Services/PurgeService.php: -------------------------------------------------------------------------------- 1 | logService = $logService; 20 | $this->pollRepository = RepositoryFactory::pollRepository(); 21 | $this->slotRepository = RepositoryFactory::slotRepository(); 22 | $this->voteRepository = RepositoryFactory::voteRepository(); 23 | $this->commentRepository = RepositoryFactory::commentRepository(); 24 | } 25 | 26 | /** 27 | * This methode purges all old polls (the ones with end_date in past). 28 | * 29 | * @return bool true is action succeeded 30 | */ 31 | function purgeOldPolls() { 32 | $oldPolls = $this->pollRepository->findOldPolls(); 33 | $count = count($oldPolls); 34 | 35 | if ($count > 0) { 36 | $this->logService->log('EXPIRATION', 'Going to purge ' . $count . ' poll(s)...'); 37 | 38 | foreach ($oldPolls as $poll) { 39 | if ($this->purgePollById($poll->id)) { 40 | $this->logService->log('EXPIRATION_SUCCESS', 'id: ' . $poll->id . ', title:' . $poll->title . ', format: ' . $poll->format . ', admin: ' . $poll->admin_name); 41 | } else { 42 | $this->logService->log('EXPIRATION_FAILED', 'id: ' . $poll->id . ', title:' . $poll->title . ', format: ' . $poll->format . ', admin: ' . $poll->admin_name); 43 | } 44 | } 45 | } 46 | 47 | return $count; 48 | } 49 | 50 | /** 51 | * This methode delete all data about a poll. 52 | * 53 | * @param $poll_id int The ID of the poll 54 | * @return bool true is action succeeded 55 | */ 56 | function purgePollById($poll_id) { 57 | $done = true; 58 | 59 | $this->pollRepository->beginTransaction(); 60 | $done &= $this->commentRepository->deleteByPollId($poll_id); 61 | $done &= $this->voteRepository->deleteByPollId($poll_id); 62 | $done &= $this->slotRepository->deleteByPollId($poll_id); 63 | $done &= $this->pollRepository->deleteById($poll_id); 64 | 65 | if ($done) { 66 | $this->pollRepository->commit(); 67 | } else { 68 | $this->pollRepository->rollback(); 69 | } 70 | 71 | return $done; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/classes/Framadate/Services/SecurityService.php: -------------------------------------------------------------------------------- 1 | 16 | *
  • There no token with the given name in session
  • 17 | *
  • The token time is in past
  • 18 | * 19 | * 20 | * @param $tokan_name string The name of the CSRF token 21 | * @return Token The token 22 | */ 23 | function getToken($tokan_name) { 24 | if (!isset($_SESSION['tokens'])) { 25 | $_SESSION['tokens'] = []; 26 | } 27 | if (!isset($_SESSION['tokens'][$tokan_name]) || $_SESSION['tokens'][$tokan_name]->isGone()) { 28 | $_SESSION['tokens'][$tokan_name] = new Token(); 29 | } 30 | 31 | return $_SESSION['tokens'][$tokan_name]->getValue(); 32 | } 33 | 34 | /** 35 | * Check if a given value is corresponding to the token in session. 36 | * 37 | * @param $tokan_name string Name of the token 38 | * @param $csrf string Value to check 39 | * @return bool true if the token is well checked 40 | */ 41 | public function checkCsrf($tokan_name, $csrf) { 42 | $checked = $_SESSION['tokens'][$tokan_name]->getValue() === $csrf; 43 | 44 | if($checked) { 45 | unset($_SESSION['tokens'][$tokan_name]); 46 | } 47 | 48 | return $checked; 49 | } 50 | 51 | /** 52 | * Verify if the current session allows to access given poll. 53 | * 54 | * @param $poll \stdClass The poll which we seek access 55 | * @return bool true if the current session can access this poll 56 | */ 57 | public function canAccessPoll($poll) { 58 | if (is_null($poll->password_hash)) { 59 | return true; 60 | } 61 | 62 | $this->ensureSessionPollSecurityIsCreated(); 63 | 64 | $currentPassword = isset($_SESSION['poll_security'][$poll->id]) ? $_SESSION['poll_security'][$poll->id] : null; 65 | if (!empty($currentPassword) && PasswordHasher::verify($currentPassword, $poll->password_hash)) { 66 | return true; 67 | } 68 | unset($_SESSION['poll_security'][$poll->id]); 69 | return false; 70 | } 71 | 72 | /** 73 | * Submit to the session a poll password 74 | * 75 | * @param $poll \stdClass The poll which we seek access 76 | * @param $password string the password to compare 77 | */ 78 | public function submitPollAccess($poll, $password) { 79 | if (!empty($password)) { 80 | $this->ensureSessionPollSecurityIsCreated(); 81 | $_SESSION['poll_security'][$poll->id] = $password; 82 | } 83 | } 84 | 85 | private function ensureSessionPollSecurityIsCreated() { 86 | if (!isset($_SESSION['poll_security'])) { 87 | $_SESSION['poll_security'] = []; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/classes/Framadate/Services/SessionService.php: -------------------------------------------------------------------------------- 1 | initSectionIfNeeded($section); 20 | 21 | $returnValue = $defaultValue; 22 | if (isset($_SESSION[$section][$key])) { 23 | $returnValue = $_SESSION[$section][$key]; 24 | } 25 | 26 | return $returnValue; 27 | } 28 | 29 | /** 30 | * Set a $value for $key in $section 31 | * 32 | * @param $section 33 | * @param $key 34 | * @param $value 35 | */ 36 | public function set($section, $key, $value) { 37 | assert(!empty($key)); 38 | assert(!empty($section)); 39 | 40 | $this->initSectionIfNeeded($section); 41 | 42 | $_SESSION[$section][$key] = $value; 43 | } 44 | 45 | /** 46 | * Remove a session value 47 | * 48 | * @param $section 49 | * @param $key 50 | */ 51 | public function remove($section, $key) { 52 | assert(!empty($key)); 53 | assert(!empty($section)); 54 | 55 | unset($_SESSION[$section][$key]); 56 | } 57 | 58 | private function initSectionIfNeeded($section) { 59 | if (!isset($_SESSION[$section])) { 60 | $_SESSION[$section] = []; 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /app/classes/Framadate/Services/SuperAdminService.php: -------------------------------------------------------------------------------- 1 | pollRepository = RepositoryFactory::pollRepository(); 16 | } 17 | 18 | /** 19 | * Return the list of all polls. 20 | * 21 | * @param array $search Array of search : ['id'=>..., 'title'=>..., 'name'=>..., 'mail'=>...] 22 | * @param int $page The page index (O = first page) 23 | * @param int $limit The limit size 24 | * @return array ['polls' => The {$limit} polls, 'count' => Entries found by the query, 'total' => Total count] 25 | */ 26 | public function findAllPolls($search, $page, $limit) { 27 | $start = $page * $limit; 28 | $polls = $this->pollRepository->findAll($search, $start, $limit); 29 | $count = $this->pollRepository->count($search); 30 | $total = $this->pollRepository->count(); 31 | 32 | return ['polls' => $polls, 'count' => $count, 'total' => $total]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/inc/constants.php: -------------------------------------------------------------------------------- 1 | setDefaultLang(DEFAULT_LANGUAGE); 23 | $i18n->setPath(__DIR__ . '/../../locale'); 24 | 25 | // Change langauge when user asked for it 26 | if (isset($_POST['lang']) && is_string($_POST['lang']) && in_array($_POST['lang'], array_keys($ALLOWED_LANGUAGES), true)) { 27 | $_SESSION['lang'] = $_POST['lang']; 28 | } 29 | 30 | /* */ 31 | $i18n->get('', 'Something, just to load the dictionary'); 32 | $locale = $i18n->getLoadedLang(); 33 | 34 | /* Date Format */ 35 | $date_format['txt_full'] = __('Date', 'FULL'); //summary in create_date_poll.php and removal date in choix_(date|autre).php 36 | $date_format['txt_short'] = __('Date', 'SHORT'); // radio title 37 | $date_format['txt_day'] = __('Date', 'DAY'); 38 | $date_format['txt_date'] = __('Date', 'DATE'); 39 | $date_format['txt_month_year'] = __('Date', 'MONTH_YEAR'); 40 | $date_format['txt_datetime_short'] = __('Date', 'DATETIME'); 41 | if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { //%e can't be used on Windows platform, use %#d instead 42 | foreach ($date_format as $k => $v) { 43 | $date_format[$k] = preg_replace('#(? 'Français', 53 | 'en' => 'English', 54 | 'es' => 'Español', 55 | 'de' => 'Deutsch', 56 | 'it' => 'Italiano', 57 | 'br' => 'Brezhoneg', 58 | ]; 59 | } 60 | 61 | require_once __DIR__ . '/i18n.php'; 62 | // Smarty 63 | require_once __DIR__ . '/smarty.php'; 64 | -------------------------------------------------------------------------------- /app/inc/smarty.php: -------------------------------------------------------------------------------- 1 | setTemplateDir(ROOT_DIR . '/tpl/'); 24 | $smarty->setCompileDir(ROOT_DIR . COMPILE_DIR); 25 | $smarty->setCacheDir(ROOT_DIR . '/cache/'); 26 | $smarty->caching = false; 27 | 28 | $smarty->assign('APPLICATION_NAME', NOMAPPLICATION); 29 | $smarty->assign('SERVER_URL', Utils::get_server_name()); 30 | $smarty->assign('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']); 31 | $smarty->assign('TITLE_IMAGE', IMAGE_TITRE); 32 | $smarty->assign('use_nav_js', strstr($_SERVER['SERVER_NAME'], 'framadate.org')); 33 | $smarty->assign('locale', $locale); 34 | $smarty->assign('langs', $ALLOWED_LANGUAGES); 35 | $smarty->assign('date_format', $date_format); 36 | if (isset($config['tracking_code'])) { 37 | $smarty->assign('tracking_code', $config['tracking_code']); 38 | } 39 | if (defined('FAVICON')) { 40 | $smarty->assign('favicon', FAVICON); 41 | } 42 | 43 | // Dev Mode 44 | if (isset($_SERVER['FRAMADATE_DEVMODE']) && $_SERVER['FRAMADATE_DEVMODE']) { 45 | $smarty->force_compile = true; 46 | $smarty->compile_check = true; 47 | } else { 48 | $smarty->force_compile = false; 49 | $smarty->compile_check = false; 50 | } 51 | 52 | function smarty_function_poll_url($params, Smarty_Internal_Template $template) { 53 | $poll_id = filter_var($params['id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]); 54 | $admin = (isset($params['admin']) && $params['admin']) ? true : false; 55 | $action = (isset($params['action']) && !empty($params['action'])) ? Utils::htmlEscape($params['action']) : false; 56 | $action_value = (isset($params['action_value']) && !empty($params['action_value'])) ? $params['action_value'] : false; 57 | $vote_unique_id = isset($params['vote_id']) ? filter_var($params['vote_id'], FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => POLL_REGEX]]) : ''; 58 | 59 | // If filter_var fails (i.e.: hack tentative), it will return false. At least no leak is possible from this. 60 | 61 | return Utils::getUrlSondage($poll_id, $admin, $vote_unique_id, $action, $action_value); 62 | } 63 | 64 | function smarty_modifier_markdown($md, $clear = false, $inline=true) { 65 | return Utils::markdown($md, $clear, $inline); 66 | } 67 | 68 | function smarty_modifier_resource($link) { 69 | return Utils::get_server_name() . $link; 70 | } 71 | function smarty_modifier_addslashes_single_quote($string) { 72 | return addcslashes($string, '\\\''); 73 | } 74 | 75 | function smarty_modifier_html($html) { 76 | return Utils::htmlEscape($html); 77 | } 78 | -------------------------------------------------------------------------------- /app/tests/Framadate/FramaTestCase.php: -------------------------------------------------------------------------------- 1 | getTestResourcePath($resourcepath)); 11 | } 12 | 13 | protected function invoke(&$object, $methodName) { 14 | $reflectionClass = new \ReflectionClass($object); 15 | $reflectionMethod = $reflectionClass->getMethod($methodName); 16 | $reflectionMethod->setAccessible(true); 17 | 18 | $params = array_slice(func_get_args(), 2); // get all the parameters after $methodName 19 | return $reflectionMethod->invokeArgs($object, $params); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/tests/Framadate/Services/MailServiceUnitTest.php: -------------------------------------------------------------------------------- 1 | time() - 1000]; 16 | 17 | // When 18 | $canSendMsg = $mailService->canSendMsg(self::MSG_KEY); 19 | 20 | // Then 21 | $this->assertSame(true, $canSendMsg); 22 | } 23 | 24 | /** 25 | * @test 26 | */ 27 | function should_not_send_2_mails_in_a_short_interval() { 28 | // Given 29 | $mailService = new MailService(true); 30 | $_SESSION[MailService::MAILSERVICE_KEY] = [self::MSG_KEY => time()]; 31 | 32 | // When 33 | $canSendMsg = $mailService->canSendMsg(self::MSG_KEY); 34 | 35 | // Then 36 | $this->assertSame(false, $canSendMsg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | addPsr4('Framadate\\', __DIR__ . '/Framadate'); 4 | -------------------------------------------------------------------------------- /bandeaux.php: -------------------------------------------------------------------------------- 1 | ' : ''; 28 | echo ' 29 |
    '; 30 | if(count($ALLOWED_LANGUAGES) > 1){ 31 | echo '
    32 |
    33 | 34 | 35 | 36 | 37 |
    38 |
    '; 39 | } 40 | echo ' 41 |

    ' . $img . '

    42 |

    ' . $titre . '

    43 | 44 |
    45 |
    '; 46 | 47 | global $connect; 48 | $tables = $connect->allTables(); 49 | $diff = array_diff([Utils::table('comment'), Utils::table('poll'), Utils::table('slot'), Utils::table('vote')], $tables); 50 | if (0 !== count($diff)) { 51 | echo '
    ' . __('Error', 'Framadate is not properly installed, please check the "INSTALL" to setup the database before continuing.') . '
    '; 52 | bandeau_pied(); 53 | die(); 54 | } 55 | } 56 | 57 | function liste_lang() 58 | { 59 | global $ALLOWED_LANGUAGES; global $locale; 60 | 61 | $str = ''; 62 | 63 | foreach ($ALLOWED_LANGUAGES as $k => $v ) { 64 | if (substr($k,0,2)===$locale) { 65 | $str .= '' . "\n" ; 66 | } else { 67 | $str .= '' . "\n" ; 68 | } 69 | } 70 | 71 | return $str; 72 | } 73 | 74 | function bandeau_pied() 75 | { 76 | echo ' 77 |
    78 | 79 | 80 | ' . "\n"; 81 | } 82 | -------------------------------------------------------------------------------- /buildlang.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 |
     $section) {
    17 |         foreach ($section as $key => $value) {
    18 |             $good[$sectionName][$key] = getFromOther($other, $key, $value, $otherLang);
    19 |         }
    20 |     }
    21 | 
    22 |     echo json_encode($good, JSON_PRETTY_PRINT | ~(JSON_ERROR_UTF8 | JSON_HEX_QUOT | JSON_HEX_APOS));
    23 | 
    24 |     function getFromOther($other, $goodKey, $default, $otherLang) {
    25 |         foreach ($other as $sectionName => $section) {
    26 |             foreach ($section as $key => $value) {
    27 |                 if (
    28 |                     strtolower($key) === strtolower($goodKey) ||
    29 |                     strtolower(trim($key)) === strtolower($goodKey) ||
    30 |                     strtolower(substr($key, 0, strlen($key) - 1)) === strtolower($goodKey) ||
    31 |                     strtolower(trim(substr(trim($key), 0, strlen($key) - 1))) === strtolower($goodKey)
    32 |                 ) {
    33 |                     return $value;
    34 |                 }
    35 |             }
    36 |         }
    37 | 
    38 |         echo '[-]' . $goodKey . "\n";
    39 | 
    40 |         return strtoupper($otherLang) . '_' . $default;
    41 |     }
    42 | 
    43 |     ?>
    44 | 
    45 | 46 | 47 | -------------------------------------------------------------------------------- /compare.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 |
     $section) {
    19 |         if (!isset($test[$sectionName])) {
    20 |             echo '- section: ' . $sectionName . "\n";
    21 |             $diffSection = true;
    22 |         }
    23 |     }
    24 |     foreach ($test as $sectionName => $section) {
    25 |         if (!isset($good[$sectionName])) {
    26 |             echo '+ section: ' . $sectionName . "\n";
    27 |             $diffSection = true;
    28 |         }
    29 |     }
    30 | 
    31 |     if (!$diffSection and array_keys($good)!==array_keys($test)) {
    32 |         var_dump(array_keys($good));
    33 |         var_dump(array_keys($test));
    34 |     } else {
    35 |         echo 'All sections are in two langs.' . "\n";
    36 |     }
    37 | 
    38 |     $diff = [];
    39 | 
    40 |     foreach ($good as $sectionName => $section) {
    41 |         $diffSection = false;
    42 |         foreach($section as $key=>$value) {
    43 |             if (!isset($test[$sectionName][$key])) {
    44 |                 $diff[$sectionName]['-'][] = $key;
    45 |                 $diffSection = true;
    46 |             }
    47 |         }
    48 | 
    49 |         if (!$diffSection and array_keys($good[$sectionName]) !== array_keys($test[$sectionName])) {
    50 |             $diff[$sectionName]['order_good'] = array_keys($good[$sectionName]);
    51 |             $diff[$sectionName]['order_test'] = array_keys($test[$sectionName]);
    52 |         }
    53 |     }
    54 | 
    55 |     foreach ($test as $sectionName => $section) {
    56 |         foreach($section as $key=>$value) {
    57 |             if (!isset($good[$sectionName][$key])) {
    58 |                 $diff[$sectionName]['+'][] = $key;
    59 |             }
    60 |         }
    61 |     }
    62 |     if (count($diff) > 0) {
    63 |         var_dump($diff);
    64 |     }
    65 |     ?>
    66 | 
    67 | 68 | 69 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leblanc-simon/opensondage", 3 | "description": "Application to facilitate the schedule of events or classic polls", 4 | "homepage": "https://opensondage.leblanc.io/", 5 | "keywords": ["poll", "opensondage"], 6 | "version": "0.9.0", 7 | "license": "CECILL-B", 8 | "type": "project", 9 | "support": { 10 | "issues": "https://github.com/leblanc-simon/OpenSondage/issues" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "Thomas CITHAREL", 15 | "email": "tcit@tcit.fr", 16 | "role": "Maintainer" 17 | }, 18 | { 19 | "name": "JosephK", 20 | "email": "joseph@framasoft.org", 21 | "role": "Maintainer" 22 | }, 23 | { 24 | "name": "Olivier PEREZ", 25 | "email": "olivier@olivierperez.fr", 26 | "role": "Former maintainer" 27 | }, 28 | { 29 | "name": "Antonin MURTIN", 30 | "email": "antonin.murtin@gmail.com", 31 | "role": "Former developper" 32 | }, 33 | { 34 | "name": "Simon LEBLANC", 35 | "role": "Former developper", 36 | "email": "contact@leblanc-simon.eu" 37 | }, 38 | { 39 | "name": "Pierre-Yves GOSSET", 40 | "role": "Former developper", 41 | "email": "pyg@framasoft.org" 42 | }, 43 | { 44 | "name": "Guilhem BORGHESI", 45 | "role": "Studs developper", 46 | "email": "borghesi@unistra.fr" 47 | }, 48 | { 49 | "name": "Raphaël DROZ", 50 | "role": "Studs developper", 51 | "email": "raphael.droz@gmail.com" 52 | } 53 | ], 54 | 55 | "require": { 56 | "php": ">=5.6.0", 57 | "ext-pdo": "*", 58 | "smarty/smarty": "^3.1", 59 | "o80/i18n": "dev-develop", 60 | "phpmailer/phpmailer": "^6.5", 61 | "ircmaxell/password-compat": "dev-master", 62 | "roave/security-advisories": "dev-master", 63 | "erusev/parsedown": "1.6.0" 64 | }, 65 | 66 | "require-dev": { 67 | "phpunit/phpunit": "^5.7", 68 | "friendsofphp/php-cs-fixer": "~2.0" 69 | }, 70 | 71 | "autoload": { 72 | "psr-4": { 73 | "Framadate\\": "app/classes/Framadate/" 74 | } 75 | }, 76 | 77 | "config": { 78 | "platform": { 79 | "php": "5.6.0" 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /css/app/create_poll.css: -------------------------------------------------------------------------------- 1 | .form-horizontal .radio label { 2 | width: 100%; 3 | } 4 | 5 | .optionnal-parameters:hover, .optionnal-parameters:focus { 6 | text-decoration: none; 7 | } 8 | 9 | .optionnal-parameters:active, .optionnal-parameters:focus { 10 | outline: none; 11 | } 12 | 13 | .optionnal-parameters .caret, .optionnal-parameters.collapsed .caret.caret-up { 14 | display: none; 15 | } 16 | 17 | .optionnal-parameters .caret.caret-up, .optionnal-parameters.collapsed .caret { 18 | display: inline-block; 19 | } 20 | 21 | .caret.caret-up { 22 | border-bottom: 4px dashed; 23 | border-top: 0 none; 24 | content: ""; 25 | } 26 | -------------------------------------------------------------------------------- /css/print.css: -------------------------------------------------------------------------------- 1 | @import url(./style.css); 2 | 3 | body { 4 | background:none; 5 | } 6 | 7 | table { 8 | page-break-after:always 9 | } 10 | 11 | table { 12 | page-break-inside:auto 13 | } 14 | 15 | tr { 16 | page-break-inside:avoid; 17 | page-break-after:auto; 18 | } 19 | 20 | thead { 21 | display:table-header-group; 22 | } 23 | 24 | tfoot { 25 | display:table-footer-group; 26 | } 27 | 28 | @page { 29 | size:landscape; 30 | } 31 | -------------------------------------------------------------------------------- /doc/TECHNICAL.md: -------------------------------------------------------------------------------- 1 | # Main language 2 | The main language of framadate is PHP. 3 | 4 | # Treeview of the project 5 | To understand what is the purpose of each page, may be you can look in the [Tree view](TREEVIEW.md) documentation. 6 | 7 | # Smarty - template engine 8 | The template engine [Smarty](www.smarty.net) is used for the dynamique pages. 9 | 10 | # Database 11 | The database is available throught the class **FramaDB**, to use it you should use the object _$connect_ which is created by the file _init.php_. 12 | 13 | This file init.php is included in each page. 14 | -------------------------------------------------------------------------------- /doc/TREEVIEW.md: -------------------------------------------------------------------------------- 1 | # Treeview of framadate 2 | 3 | Here are the main files and directories you need to know in order to develop on framadate project. 4 | 5 | ## Admin 6 | 7 | * admin/ 8 | * Le répertoire réservé à l'administrateur de l'application 9 | * admin/index.php 10 | * The admin home page, it holds links to other admin pages 11 | * admin/logs.php 12 | * The page to see the application logs 13 | * admin/migration.php 14 | * This page do the needed migration at loading 15 | * admin/polls.php 16 | * The list of all polls 17 | * admin/purge.php 18 | * The page to manually trigger the purge (even if the purge is still executed at poll creation) 19 | 20 | ## Main 21 | 22 | ### Root files 23 | 24 | * index.php 25 | * Landing page framadate 26 | * studs.php 27 | * La page de présentation de sondage 28 | * adminstuds.php 29 | * La page d'administration réservée à l'auteur du sondage 30 | * create_poll.php 31 | * La page (1/2) de création de sondage récupérant les informations générales 32 | * create_date_poll.php 33 | * La page de création (2/2) pour un sondage pour déterminer une date 34 | * crete_classic_poll.php 35 | * La page de création (2/2) pour un sondage sur un sujet quelconque 36 | * bandeaux.php 37 | * Le fichier contenant tous les bandeaux des pages PHP de l'application 38 | * favicon.ico 39 | * L'icone de favoris de l'application 40 | * exportcsv.php 41 | * Le fichier d'export de tous le tableau des participants avec leurs réponses dans un tableur (format .CSV) 42 | * CHANGELOG.md 43 | * Le fichier contenant toutes les modifications de l'application entre les différentes versions 44 | 45 | ### app/ directory 46 | 47 | * app/inc/config.template.php 48 | * Le fichier contenant le paramètrage de l'application, il faut le dupliquer vers app/inc/config.php avant de l'éditer 49 | * app/inc/constants.php 50 | * Le fichier contenant les constantes de l'application 51 | * app/inc/i18n.php 52 | * Le fichier contenant quelques fonctions récurrentes de l'application relatives à l'internationalisation 53 | * app/inc/init.php 54 | * Le fichier chargé à l'initialisation de chaque page 55 | * app/inc/smarty.php 56 | * Le fichier qui prépare le context de Smarty 57 | 58 | ### other directories 59 | 60 | * tpl/ 61 | * The directory that hold all the Smarty templates 62 | 63 | * css/style.css et css/frama.css 64 | * Les fichiers CSS de style pour toute l'application 65 | 66 | * scripts/ 67 | * Le répertoire qui contient tous les scripts de l'application 68 | 69 | * locale/ 70 | * Le répertoire qui contient les fichiers de traduction modifiables (.po) et compilés (.mo) au format gettext 71 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/favicon.ico -------------------------------------------------------------------------------- /find_polls.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/find_polls.php -------------------------------------------------------------------------------- /fonts/DejaVuSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/DejaVuSans-Bold.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans-BoldOblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/DejaVuSans-BoldOblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/DejaVuSans-ExtraLight.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans-Oblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/DejaVuSans-Oblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/DejaVuSans.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /htaccess.txt: -------------------------------------------------------------------------------- 1 | ###################### 2 | # .htaccess example. # 3 | ###################### 4 | 5 | 6 | RewriteEngine On 7 | RewriteCond %{REQUEST_FILENAME} -f [OR] 8 | RewriteCond %{REQUEST_FILENAME} -d 9 | RewriteRule . - [L] 10 | 11 | RewriteRule ^([a-zA-Z0-9-]+)$ studs.php?poll=$1 [L] 12 | RewriteRule ^([a-zA-Z0-9-]+)/action/([a-zA-Z_-]+)/(.+)$ studs.php?poll=$1&$2=$3 13 | RewriteRule ^([a-zA-Z0-9-]+)/vote/([a-zA-Z0-9]{16})$ studs.php?poll=$1&vote=$2 14 | RewriteRule ^([a-zA-Z0-9-]{24})/admin$ adminstuds.php?poll=$1 15 | RewriteRule ^([a-zA-Z0-9-]{24})/admin/vote/([a-zA-Z0-9]{16})$ adminstuds.php?poll=$1&vote=$2 16 | RewriteRule ^([a-zA-Z0-9-]{24})/admin/action/([a-zA-Z_-]+)(/(.+))?$ adminstuds.php?poll=$1&$2=$4 17 | -------------------------------------------------------------------------------- /images/classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/images/classic.png -------------------------------------------------------------------------------- /images/date.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/images/date.png -------------------------------------------------------------------------------- /images/logo-framadate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/images/logo-framadate.png -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | findById('aqg259dth55iuhwm'); 39 | $nbcol = max( $config['show_what_is_that'] + $config['show_the_software'] + $config['show_cultivate_your_garden'], 1 ); 40 | 41 | $smarty->assign('show_what_is_that', $config['show_what_is_that']); 42 | $smarty->assign('show_the_software', $config['show_the_software']); 43 | $smarty->assign('show_cultivate_your_garden', $config['show_cultivate_your_garden']); 44 | $smarty->assign('col_size', 12 / $nbcol); 45 | $smarty->assign('demo_poll', $demoPoll); 46 | 47 | $smarty->assign('title', __('Generic', 'Make your polls')); 48 | 49 | $smarty->display('index.tpl'); 50 | -------------------------------------------------------------------------------- /js/app/admin/polls.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leblanc-simon/OpenSondage/d9263f0a58c3174bb9921306455b55dbdc9e05b2/js/app/admin/polls.js -------------------------------------------------------------------------------- /js/app/create_poll.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This software is governed by the CeCILL-B license. If a copy of this license 3 | * is not distributed with this file, you can obtain one at 4 | * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt 5 | * 6 | * Authors of STUdS (initial project): Guilhem BORGHESI (borghesi@unistra.fr) and Raphaël DROZ 7 | * Authors of Framadate/OpenSondage: Framasoft (https://github.com/framasoft) 8 | * 9 | * ============================= 10 | * 11 | * Ce logiciel est régi par la licence CeCILL-B. Si une copie de cette licence 12 | * ne se trouve pas avec ce fichier vous pouvez l'obtenir sur 13 | * http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt 14 | * 15 | * Auteurs de STUdS (projet initial) : Guilhem BORGHESI (borghesi@unistra.fr) et Raphaël DROZ 16 | * Auteurs de Framadate/OpenSondage : Framasoft (https://github.com/framasoft) 17 | */ 18 | 19 | $(document).ready(function () { 20 | 21 | /** 22 | * Error check when submitting form 23 | */ 24 | $("#formulaire").submit(function (event) { 25 | var isHidden = $("#hidden").prop('checked'); 26 | var isOptionAllUserCanModifyEverything = $("#editableByAll").is(":checked"); 27 | 28 | if (isHidden && isOptionAllUserCanModifyEverything) { 29 | event.preventDefault(); 30 | $("#hiddenWithBadEditionModeError").removeClass("hidden"); 31 | } else { 32 | $("#hiddenWithBadEditionModeError").addClass("hidden"); 33 | } 34 | }); 35 | 36 | /** 37 | * Enable/Disable custom url options 38 | */ 39 | $("#use_customized_url").change(function () { 40 | if ($(this).prop("checked")) { 41 | $("#customized_url_options").removeClass("hidden"); 42 | } else { 43 | $("#customized_url_options").addClass("hidden"); 44 | } 45 | }); 46 | 47 | /** 48 | * Enable/Disable ValueMax options 49 | */ 50 | $("#use_ValueMax").change(function () { 51 | if ($(this).prop("checked")) { 52 | $("#ValueMax").removeClass("hidden"); 53 | } else { 54 | $("#ValueMax").addClass("hidden"); 55 | } 56 | }); 57 | 58 | 59 | /** 60 | * Hide/Show password options 61 | */ 62 | $("#use_password").change(function(){ 63 | if ($(this).prop("checked")) { 64 | $("#password_options").removeClass("hidden"); 65 | } else { 66 | $("#password_options").addClass("hidden"); 67 | } 68 | }); 69 | 70 | // Check cookies are enabled too 71 | var cookieEnabled = function () { 72 | var cookieEnabled = navigator.cookieEnabled; 73 | 74 | // if not IE4+ nor NS6+ 75 | if (!cookieEnabled && typeof navigator.cookieEnabled === "undefined") { 76 | document.cookie = "testcookie"; 77 | cookieEnabled = document.cookie.indexOf("testcookie") != -1; 78 | } 79 | 80 | return cookieEnabled; 81 | }; 82 | 83 | if (cookieEnabled()) { 84 | // Show the form block 85 | document.getElementById("form-block").setAttribute("style", ""); 86 | } else { 87 | // Show the warning about cookies 88 | document.getElementById("cookie-warning").setAttribute("style", ""); 89 | } 90 | 91 | var wrapper = new MDEWrapper($('#poll_comments')[0], $('#rich-editor-button'), $('#simple-editor-button')); 92 | if ($('#rich-editor-button').hasClass('active')) { 93 | wrapper.enable(); 94 | } 95 | 96 | }); 97 | -------------------------------------------------------------------------------- /js/core.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | window.lang = $('html').attr('lang'); 4 | 5 | // Horizontal scroll buttons 6 | if($('.results').width() > $('.container').width()) { 7 | $('.scroll-buttons').removeClass('hidden'); 8 | } 9 | 10 | var $scroll_page = 1; 11 | var $scroll_scale = $('#tableContainer').width()*2/3; 12 | 13 | $('.scroll-left').addClass('disabled'); 14 | 15 | $('.scroll-left').click(function(){ 16 | var next = Math.floor($scroll_page); 17 | if(next == $scroll_page) { 18 | next--; 19 | } 20 | 21 | $('.scroll-right').removeClass('disabled'); 22 | $('#tableContainer').animate({ 23 | scrollLeft: $scroll_scale*(next - 1) 24 | }, 1000); 25 | if($scroll_page == 1) { 26 | $(this).addClass('disabled'); 27 | } else { 28 | $scroll_page = next; 29 | } 30 | return false; 31 | }); 32 | $('.scroll-right').click(function(){ 33 | var next = Math.ceil($scroll_page); 34 | if(next == $scroll_page) 35 | next++; 36 | $('.scroll-left').removeClass('disabled'); 37 | $('#tableContainer').animate({ 38 | scrollLeft: $scroll_scale*(next - 1) 39 | }, 1000); 40 | 41 | if($scroll_scale*($scroll_page+1) > $('.results').width()) { 42 | $(this).addClass('disabled'); 43 | } else { 44 | $scroll_page = next; 45 | } 46 | return false; 47 | }); 48 | 49 | $('#tableContainer').scroll(function() { 50 | var position = $(this).scrollLeft(); 51 | $scroll_page = position / $scroll_scale + 1; 52 | if(position == 0) { 53 | $('.scroll-left').addClass('disabled'); 54 | } else { 55 | $('.scroll-left').removeClass('disabled'); 56 | } 57 | 58 | if(position >= $('.results').width() - $('#tableContainer').width()) { 59 | $('.scroll-right').addClass('disabled'); 60 | } else { 61 | $('.scroll-right').removeClass('disabled'); 62 | } 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Arabic translation for bootstrap-datepicker 3 | * Mohammed Alshehri 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ar'] = { 7 | days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"], 8 | daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"], 9 | daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"], 10 | months: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"], 11 | monthsShort: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"], 12 | today: "هذا اليوم", 13 | rtl: true 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.az.js: -------------------------------------------------------------------------------- 1 | // Azerbaijani 2 | ;(function($){ 3 | $.fn.datepicker.dates['az'] = { 4 | days: ["Bazar", "Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə", "Bazar"], 5 | daysShort: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş.", "B."], 6 | daysMin: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş.", "B."], 7 | months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "İyun", "İyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"], 8 | monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "İyun", "İyul", "Avq", "Sen", "Okt", "Noy", "Dek"], 9 | today: "Bu gün", 10 | weekStart: 1 11 | }; 12 | }(jQuery)); 13 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.bg.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bulgarian translation for bootstrap-datepicker 3 | * Apostol Apostolov 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['bg'] = { 7 | days: ["Неделя", "Понеделник", "Вторник", "Сряда", "Четвъртък", "Петък", "Събота", "Неделя"], 8 | daysShort: ["Нед", "Пон", "Вто", "Сря", "Чет", "Пет", "Съб", "Нед"], 9 | daysMin: ["Н", "П", "В", "С", "Ч", "П", "С", "Н"], 10 | months: ["Януари", "Февруари", "Март", "Април", "Май", "Юни", "Юли", "Август", "Септември", "Октомври", "Ноември", "Декември"], 11 | monthsShort: ["Ян", "Фев", "Мар", "Апр", "Май", "Юни", "Юли", "Авг", "Сеп", "Окт", "Ное", "Дек"], 12 | today: "днес" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ca.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Catalan translation for bootstrap-datepicker 3 | * J. Garcia 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ca'] = { 7 | days: ["Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte", "Diumenge"], 8 | daysShort: ["Diu", "Dil", "Dmt", "Dmc", "Dij", "Div", "Dis", "Diu"], 9 | daysMin: ["dg", "dl", "dt", "dc", "dj", "dv", "ds", "dg"], 10 | months: ["Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"], 11 | monthsShort: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Des"], 12 | today: "Avui" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.cs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Czech translation for bootstrap-datepicker 3 | * Matěj Koubík 4 | * Fixes by Michal Remiš 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['cs'] = { 8 | days: ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Neděle"], 9 | daysShort: ["Ned", "Pon", "Úte", "Stř", "Čtv", "Pát", "Sob", "Ned"], 10 | daysMin: ["Ne", "Po", "Út", "St", "Čt", "Pá", "So", "Ne"], 11 | months: ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"], 12 | monthsShort: ["Led", "Úno", "Bře", "Dub", "Kvě", "Čer", "Čnc", "Srp", "Zář", "Říj", "Lis", "Pro"], 13 | today: "Dnes" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.cy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welsh translation for bootstrap-datepicker 3 | * S. Morris 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['cy'] = { 7 | days: ["Sul", "Llun", "Mawrth", "Mercher", "Iau", "Gwener", "Sadwrn", "Sul"], 8 | daysShort: ["Sul", "Llu", "Maw", "Mer", "Iau", "Gwe", "Sad", "Sul"], 9 | daysMin: ["Su", "Ll", "Ma", "Me", "Ia", "Gwe", "Sa", "Su"], 10 | months: ["Ionawr", "Chewfror", "Mawrth", "Ebrill", "Mai", "Mehefin", "Gorfennaf", "Awst", "Medi", "Hydref", "Tachwedd", "Rhagfyr"], 11 | monthsShort: ["Ion", "Chw", "Maw", "Ebr", "Mai", "Meh", "Gor", "Aws", "Med", "Hyd", "Tach", "Rha"], 12 | today: "Heddiw" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.da.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Danish translation for bootstrap-datepicker 3 | * Christian Pedersen 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['da'] = { 7 | days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], 8 | daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], 9 | daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], 10 | months: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "I Dag", 13 | clear: "Nulstil" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.de.js: -------------------------------------------------------------------------------- 1 | /** 2 | * German translation for bootstrap-datepicker 3 | * Sam Zurcher 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['de'] = { 7 | days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"], 8 | daysShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam", "Son"], 9 | daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"], 10 | months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 11 | monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], 12 | today: "Heute", 13 | clear: "Löschen", 14 | weekStart: 1, 15 | format: "dd.mm.yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.el.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Greek translation for bootstrap-datepicker 3 | */ 4 | ;(function($){ 5 | $.fn.datepicker.dates['el'] = { 6 | days: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο", "Κυριακή"], 7 | daysShort: ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ", "Κυρ"], 8 | daysMin: ["Κυ", "Δε", "Τρ", "Τε", "Πε", "Πα", "Σα", "Κυ"], 9 | months: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"], 10 | monthsShort: ["Ιαν", "Φεβ", "Μαρ", "Απρ", "Μάι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"], 11 | today: "Σήμερα" 12 | }; 13 | }(jQuery)); 14 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.es.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Spanish translation for bootstrap-datepicker 3 | * Bruno Bonamin 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['es'] = { 7 | days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"], 8 | daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"], 9 | daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"], 10 | months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], 11 | monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"], 12 | today: "Hoy" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.et.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Estonian translation for bootstrap-datepicker 3 | * Ando Roots 4 | * Fixes by Illimar Tambek < 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['et'] = { 8 | days: ["Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev", "Pühapäev"], 9 | daysShort: ["Pühap", "Esmasp", "Teisip", "Kolmap", "Neljap", "Reede", "Laup", "Pühap"], 10 | daysMin: ["P", "E", "T", "K", "N", "R", "L", "P"], 11 | months: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"], 12 | monthsShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni", "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"], 13 | today: "Täna", 14 | clear: "Tühjenda", 15 | weekStart: 1, 16 | format: "dd.mm.yyyy" 17 | }; 18 | }(jQuery)); 19 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.fa.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Persian translation for bootstrap-datepicker 3 | * Mostafa Rokooie 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['fa'] = { 7 | days: ["یک‌شنبه", "دوشنبه", "سه‌شنبه", "چهارشنبه", "پنج‌شنبه", "جمعه", "شنبه", "یک‌شنبه"], 8 | daysShort: ["یک", "دو", "سه", "چهار", "پنج", "جمعه", "شنبه", "یک"], 9 | daysMin: ["ی", "د", "س", "چ", "پ", "ج", "ش", "ی"], 10 | months: ["ژانویه", "فوریه", "مارس", "آوریل", "مه", "ژوئن", "ژوئیه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "دسامبر"], 11 | monthsShort: ["ژان", "فور", "مار", "آور", "مه", "ژون", "ژوی", "اوت", "سپت", "اکت", "نوا", "دسا"], 12 | today: "امروز", 13 | clear: "پاک کن", 14 | weekStart: 1, 15 | format: "yyyy/mm/dd" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.fi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finnish translation for bootstrap-datepicker 3 | * Jaakko Salonen 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['fi'] = { 7 | days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"], 8 | daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau", "sun"], 9 | daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la", "su"], 10 | months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], 11 | monthsShort: ["tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mar", "jou"], 12 | today: "tänään", 13 | weekStart: 1, 14 | format: "d.m.yyyy" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.fr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * French translation for bootstrap-datepicker 3 | * Nico Mollet 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['fr'] = { 7 | days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"], 8 | daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"], 9 | daysMin: ["D", "L", "Ma", "Me", "J", "V", "S", "D"], 10 | months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], 11 | monthsShort: ["Jan", "Fév", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Déc"], 12 | today: "Aujourd'hui", 13 | clear: "Effacer", 14 | weekStart: 1, 15 | format: "dd/mm/yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.gl.js: -------------------------------------------------------------------------------- 1 | ;(function($){ 2 | $.fn.datepicker.dates['gl'] = { 3 | days: ["Domingo", "Luns", "Martes", "Mércores", "Xoves", "Venres", "Sábado", "Domingo"], 4 | daysShort: ["Dom", "Lun", "Mar", "Mér", "Xov", "Ven", "Sáb", "Dom"], 5 | daysMin: ["Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa", "Do"], 6 | months: ["Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"], 7 | monthsShort: ["Xan", "Feb", "Mar", "Abr", "Mai", "Xun", "Xul", "Ago", "Sep", "Out", "Nov", "Dec"], 8 | today: "Hoxe", 9 | clear: "Limpar" 10 | }; 11 | }(jQuery)); 12 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.he.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Hebrew translation for bootstrap-datepicker 3 | * Sagie Maoz 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['he'] = { 7 | days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"], 8 | daysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"], 9 | daysMin: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"], 10 | months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"], 11 | monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"], 12 | today: "היום", 13 | rtl: true 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.hr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Croatian localisation 3 | */ 4 | ;(function($){ 5 | $.fn.datepicker.dates['hr'] = { 6 | days: ["Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota", "Nedjelja"], 7 | daysShort: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub", "Ned"], 8 | daysMin: ["Ne", "Po", "Ut", "Sr", "Če", "Pe", "Su", "Ne"], 9 | months: ["Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"], 10 | monthsShort: ["Sij", "Velj", "Ožu", "Tra", "Svi", "Lip", "Srp", "Kol", "Ruj", "Lis", "Stu", "Pro"], 11 | today: "Danas" 12 | }; 13 | }(jQuery)); 14 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.hu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Hungarian translation for bootstrap-datepicker 3 | * Sotus László 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['hu'] = { 7 | days: ["Vasárnap", "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap"], 8 | daysShort: ["Vas", "Hét", "Ked", "Sze", "Csü", "Pén", "Szo", "Vas"], 9 | daysMin: ["Va", "Hé", "Ke", "Sz", "Cs", "Pé", "Sz", "Va"], 10 | months: ["Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Már", "Ápr", "Máj", "Jún", "Júl", "Aug", "Sze", "Okt", "Nov", "Dec"], 12 | today: "Ma", 13 | weekStart: 1, 14 | format: "yyyy.mm.dd" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.id.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Bahasa translation for bootstrap-datepicker 3 | * Azwar Akbar 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['id'] = { 7 | days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"], 8 | daysShort: ["Mgu", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Mgu"], 9 | daysMin: ["Mg", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa", "Mg"], 10 | months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"], 12 | today: "Hari Ini", 13 | clear: "Kosongkan" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.is.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Icelandic translation for bootstrap-datepicker 3 | * Hinrik Örn Sigurðsson 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['is'] = { 7 | days: ["Sunnudagur", "Mánudagur", "Þriðjudagur", "Miðvikudagur", "Fimmtudagur", "Föstudagur", "Laugardagur", "Sunnudagur"], 8 | daysShort: ["Sun", "Mán", "Þri", "Mið", "Fim", "Fös", "Lau", "Sun"], 9 | daysMin: ["Su", "Má", "Þr", "Mi", "Fi", "Fö", "La", "Su"], 10 | months: ["Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ágúst", "September", "Október", "Nóvember", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maí", "Jún", "Júl", "Ágú", "Sep", "Okt", "Nóv", "Des"], 12 | today: "Í Dag" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.it.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Italian translation for bootstrap-datepicker 3 | * Enrico Rubboli 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['it'] = { 7 | days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato", "Domenica"], 8 | daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"], 9 | daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"], 10 | months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], 11 | monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"], 12 | today: "Oggi", 13 | clear: "Cancella", 14 | weekStart: 1, 15 | format: "dd/mm/yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ja.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Japanese translation for bootstrap-datepicker 3 | * Norio Suzuki 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ja'] = { 7 | days: ["日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜", "日曜"], 8 | daysShort: ["日", "月", "火", "水", "木", "金", "土", "日"], 9 | daysMin: ["日", "月", "火", "水", "木", "金", "土", "日"], 10 | months: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], 11 | monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], 12 | today: "今日", 13 | format: "yyyy/mm/dd" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ka.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Georgian translation for bootstrap-datepicker 3 | * Levan Melikishvili 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ka'] = { 7 | days: ["კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი", "კვირა"], 8 | daysShort: ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ", "კვი"], 9 | daysMin: ["კვ", "ორ", "სა", "ოთ", "ხუ", "პა", "შა", "კვ"], 10 | months: ["იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომები", "ნოემბერი", "დეკემბერი"], 11 | monthsShort: ["იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ"], 12 | today: "დღეს", 13 | clear: "გასუფთავება", 14 | weekStart: 1, 15 | format: "dd.mm.yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.kk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Kazakh translation for bootstrap-datepicker 3 | * Yerzhan Tolekov 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['kk'] = { 7 | days: ["Жексенбі", "Дүйсенбі", "Сейсенбі", "Сәрсенбі", "Бейсенбі", "Жұма", "Сенбі", "Жексенбі"], 8 | daysShort: ["Жек", "Дүй", "Сей", "Сәр", "Бей", "Жұм", "Сен", "Жек"], 9 | daysMin: ["Жк", "Дс", "Сс", "Ср", "Бс", "Жм", "Сн", "Жк"], 10 | months: ["Қаңтар", "Ақпан", "Наурыз", "Сәуір", "Мамыр", "Маусым", "Шілде", "Тамыз", "Қыркүйек", "Қазан", "Қараша", "Желтоқсан"], 11 | monthsShort: ["Қаң", "Ақп", "Нау", "Сәу", "Мамыр", "Мау", "Шлд", "Тмз", "Қыр", "Қзн", "Қар", "Жел"], 12 | today: "Бүгін", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.kr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Korean translation for bootstrap-datepicker 3 | * Gu Youn 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['kr'] = { 7 | days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일", "일요일"], 8 | daysShort: ["일", "월", "화", "수", "목", "금", "토", "일"], 9 | daysMin: ["일", "월", "화", "수", "목", "금", "토", "일"], 10 | months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"], 11 | monthsShort: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"] 12 | }; 13 | }(jQuery)); 14 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.lt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Lithuanian translation for bootstrap-datepicker 3 | * Šarūnas Gliebus 4 | */ 5 | 6 | ;(function($){ 7 | $.fn.datepicker.dates['lt'] = { 8 | days: ["Sekmadienis", "Pirmadienis", "Antradienis", "Trečiadienis", "Ketvirtadienis", "Penktadienis", "Šeštadienis", "Sekmadienis"], 9 | daysShort: ["S", "Pr", "A", "T", "K", "Pn", "Š", "S"], 10 | daysMin: ["Sk", "Pr", "An", "Tr", "Ke", "Pn", "Št", "Sk"], 11 | months: ["Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "Rugpjūtis", "Rugsėjis", "Spalis", "Lapkritis", "Gruodis"], 12 | monthsShort: ["Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rugp", "Rugs", "Spa", "Lap", "Gru"], 13 | today: "Šiandien", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.lv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Latvian translation for bootstrap-datepicker 3 | * Artis Avotins 4 | */ 5 | 6 | ;(function($){ 7 | $.fn.datepicker.dates['lv'] = { 8 | days: ["Svētdiena", "Pirmdiena", "Otrdiena", "Trešdiena", "Ceturtdiena", "Piektdiena", "Sestdiena", "Svētdiena"], 9 | daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S", "Sv"], 10 | daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "Se", "Sv"], 11 | months: ["Janvāris", "Februāris", "Marts", "Aprīlis", "Maijs", "Jūnijs", "Jūlijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"], 12 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jūn", "Jūl", "Aug", "Sep", "Okt", "Nov", "Dec"], 13 | today: "Šodien", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.mk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Macedonian translation for bootstrap-datepicker 3 | * Marko Aleksic 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['mk'] = { 7 | days: ["Недела", "Понеделник", "Вторник", "Среда", "Четврток", "Петок", "Сабота", "Недела"], 8 | daysShort: ["Нед", "Пон", "Вто", "Сре", "Чет", "Пет", "Саб", "Нед"], 9 | daysMin: ["Не", "По", "Вт", "Ср", "Че", "Пе", "Са", "Не"], 10 | months: ["Јануари", "Февруари", "Март", "Април", "Мај", "Јуни", "Јули", "Август", "Септември", "Октомври", "Ноември", "Декември"], 11 | monthsShort: ["Јан", "Фев", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Ное", "Дек"], 12 | today: "Денес", 13 | format: "dd.mm.yyyy" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ms.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Malay translation for bootstrap-datepicker 3 | * Ateman Faiz 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ms'] = { 7 | days: ["Ahad", "Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu", "Ahad"], 8 | daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab", "Aha"], 9 | daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa", "Ah"], 10 | months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"], 12 | today: "Hari Ini" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.nb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Norwegian (bokmål) translation for bootstrap-datepicker 3 | * Fredrik Sundmyhr 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['nb'] = { 7 | days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], 8 | daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], 9 | daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], 10 | months: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"], 12 | today: "I Dag" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.nl-BE.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Belgium-Dutch translation for bootstrap-datepicker 3 | * Julien Poulin 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['nl-BE'] = { 7 | days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"], 8 | daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 9 | daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 10 | months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Vandaag", 13 | clear: "Leegmaken", 14 | weekStart: 1, 15 | format: "dd/mm/yyyy" 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.nl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dutch translation for bootstrap-datepicker 3 | * Reinier Goltstein 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['nl'] = { 7 | days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"], 8 | daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 9 | daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], 10 | months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Vandaag" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.no.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Norwegian translation for bootstrap-datepicker 3 | **/ 4 | ;(function($){ 5 | $.fn.datepicker.dates['no'] = { 6 | days: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'], 7 | daysShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'], 8 | daysMin: ['Sø','Ma','Ti','On','To','Fr','Lø'], 9 | months: ['Januar','Februar','Mars','April','Mai','Juni','Juli','August','September','Oktober','November','Desember'], 10 | monthsShort: ['Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Des'], 11 | today: 'I dag', 12 | clear: 'Nullstill', 13 | weekStart: 1, 14 | format: 'dd.mm.yyyy' 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.pl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Polish translation for bootstrap-datepicker 3 | * Robert 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['pl'] = { 7 | days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota", "Niedziela"], 8 | daysShort: ["Nie", "Pn", "Wt", "Śr", "Czw", "Pt", "So", "Nie"], 9 | daysMin: ["N", "Pn", "Wt", "Śr", "Cz", "Pt", "So", "N"], 10 | months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], 11 | monthsShort: ["Sty", "Lu", "Mar", "Kw", "Maj", "Cze", "Lip", "Sie", "Wrz", "Pa", "Lis", "Gru"], 12 | today: "Dzisiaj", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.pt-BR.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Brazilian translation for bootstrap-datepicker 3 | * Cauan Cabral 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['pt-BR'] = { 7 | days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], 8 | daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], 9 | daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], 10 | months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], 11 | monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], 12 | today: "Hoje", 13 | clear: "Limpar" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.pt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Portuguese translation for bootstrap-datepicker 3 | * Original code: Cauan Cabral 4 | * Tiago Melo 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['pt'] = { 8 | days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], 9 | daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], 10 | daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], 11 | months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], 12 | monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], 13 | today: "Hoje", 14 | clear: "Limpar" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ro.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Romanian translation for bootstrap-datepicker 3 | * Cristian Vasile 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ro'] = { 7 | days: ["Duminică", "Luni", "Marţi", "Miercuri", "Joi", "Vineri", "Sâmbătă", "Duminică"], 8 | daysShort: ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", "Dum"], 9 | daysMin: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sâ", "Du"], 10 | months: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"], 11 | monthsShort: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"], 12 | today: "Astăzi", 13 | clear: "Șterge", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.rs-latin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Serbian latin translation for bootstrap-datepicker 3 | * Bojan Milosavlević 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['rs-latin'] = { 7 | days: ["Nedelja","Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Petak", "Subota", "Nedelja"], 8 | daysShort: ["Ned", "Pon", "Uto", "Sre", "Čet", "Pet", "Sub", "Ned"], 9 | daysMin: ["N", "Po", "U", "Sr", "Č", "Pe", "Su", "N"], 10 | months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Danas" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.rs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Serbian cyrillic translation for bootstrap-datepicker 3 | * Bojan Milosavlević 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['rs'] = { 7 | days: ["Недеља","Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота", "Недеља"], 8 | daysShort: ["Нед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб", "Нед"], 9 | daysMin: ["Н", "По", "У", "Ср", "Ч", "Пе", "Су", "Н"], 10 | months: ["Јануар", "Фебруар", "Март", "Април", "Мај", "Јун", "Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар"], 11 | monthsShort: ["Јан", "Феб", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец"], 12 | today: "Данас" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ru.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Russian translation for bootstrap-datepicker 3 | * Victor Taranenko 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ru'] = { 7 | days: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"], 8 | daysShort: ["Вск", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Вск"], 9 | daysMin: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"], 10 | months: ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"], 11 | monthsShort: ["Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек"], 12 | today: "Сегодня", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.sk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Slovak translation for bootstrap-datepicker 3 | * Marek Lichtner 4 | * Fixes by Michal Remiš 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates["sk"] = { 8 | days: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota", "Nedeľa"], 9 | daysShort: ["Ned", "Pon", "Uto", "Str", "Štv", "Pia", "Sob", "Ned"], 10 | daysMin: ["Ne", "Po", "Ut", "St", "Št", "Pia", "So", "Ne"], 11 | months: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"], 12 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"], 13 | today: "Dnes" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.sl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Slovene translation for bootstrap-datepicker 3 | * Gregor Rudolf 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['sl'] = { 7 | days: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota", "Nedelja"], 8 | daysShort: ["Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob", "Ned"], 9 | daysMin: ["Ne", "Po", "To", "Sr", "Če", "Pe", "So", "Ne"], 10 | months: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Danes" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.sq.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Albanian translation for bootstrap-datepicker 3 | * Tomor Pupovci 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['sq'] = { 7 | days: ["E Diel", "E Hënë", "E martē", "E mërkurë", "E Enjte", "E Premte", "E Shtunë", "E Diel"], 8 | daysShort: ["Die", "Hën", "Mar", "Mër", "Enj", "Pre", "Shtu", "Die"], 9 | daysMin: ["Di", "Hë", "Ma", "Më", "En", "Pr", "Sht", "Di"], 10 | months: ["Janar", "Shkurt", "Mars", "Prill", "Maj", "Qershor", "Korrik", "Gusht", "Shtator", "Tetor", "Nëntor", "Dhjetor"], 11 | monthsShort: ["Jan", "Shk", "Mar", "Pri", "Maj", "Qer", "Korr", "Gu", "Sht", "Tet", "Nën", "Dhjet"], 12 | today: "Sot" 13 | }; 14 | }(jQuery)); 15 | 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.sv.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swedish translation for bootstrap-datepicker 3 | * Patrik Ragnarsson 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['sv'] = { 7 | days: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag"], 8 | daysShort: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör", "Sön"], 9 | daysMin: ["Sö", "Må", "Ti", "On", "To", "Fr", "Lö", "Sö"], 10 | months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"], 11 | monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 12 | today: "Idag", 13 | format: "yyyy-mm-dd", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.sw.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Swahili translation for bootstrap-datepicker 3 | * Edwin Mugendi 4 | * Source: http://scriptsource.org/cms/scripts/page.php?item_id=entry_detail&uid=xnfaqyzcku 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['sw'] = { 8 | days: ["Jumapili", "Jumatatu", "Jumanne", "Jumatano", "Alhamisi", "Ijumaa", "Jumamosi", "Jumapili"], 9 | daysShort: ["J2", "J3", "J4", "J5", "Alh", "Ij", "J1", "J2"], 10 | daysMin: ["2", "3", "4", "5", "A", "I", "1", "2"], 11 | months: ["Januari", "Februari", "Machi", "Aprili", "Mei", "Juni", "Julai", "Agosti", "Septemba", "Oktoba", "Novemba", "Desemba"], 12 | monthsShort: ["Jan", "Feb", "Mac", "Apr", "Mei", "Jun", "Jul", "Ago", "Sep", "Okt", "Nov", "Des"], 13 | today: "Leo" 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.th.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Thai translation for bootstrap-datepicker 3 | * Suchau Jiraprapot 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['th'] = { 7 | days: ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัส", "ศุกร์", "เสาร์", "อาทิตย์"], 8 | daysShort: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], 9 | daysMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], 10 | months: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"], 11 | monthsShort: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."], 12 | today: "วันนี้" 13 | }; 14 | }(jQuery)); 15 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.tr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Turkish translation for bootstrap-datepicker 3 | * Serkan Algur 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['tr'] = { 7 | days: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi", "Pazar"], 8 | daysShort: ["Pz", "Pzt", "Sal", "Çrş", "Prş", "Cu", "Cts", "Pz"], 9 | daysMin: ["Pz", "Pzt", "Sa", "Çr", "Pr", "Cu", "Ct", "Pz"], 10 | months: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"], 11 | monthsShort: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"], 12 | today: "Bugün", 13 | format: "dd.mm.yyyy" 14 | }; 15 | }(jQuery)); 16 | 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.ua.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Ukrainian translation for bootstrap-datepicker 3 | * Igor Polynets 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['ua'] = { 7 | days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятница", "Субота", "Неділя"], 8 | daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Нед"], 9 | daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"], 10 | months: ["Cічень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"], 11 | monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"], 12 | today: "Сьогодні", 13 | weekStart: 1 14 | }; 15 | }(jQuery)); 16 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.vi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vietnamese translation for bootstrap-datepicker 3 | * An Vo 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['vi'] = { 7 | days: ["Chủ nhật", "Thứ hai", "Thứ ba", "Thứ tư", "Thứ năm", "Thứ sáu", "Thứ bảy", "Chủ nhật"], 8 | daysShort: ["CN", "Thứ 2", "Thứ 3", "Thứ 4", "Thứ 5", "Thứ 6", "Thứ 7", "CN"], 9 | daysMin: ["CN", "T2", "T3", "T4", "T5", "T6", "T7", "CN"], 10 | months: ["Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"], 11 | monthsShort: ["Th1", "Th2", "Th3", "Th4", "Th5", "Th6", "Th7", "Th8", "Th9", "Th10", "Th11", "Th12"], 12 | today: "Hôm nay", 13 | clear: "Xóa", 14 | format: "dd/mm/yyyy" 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.zh-CN.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simplified Chinese translation for bootstrap-datepicker 3 | * Yuan Cheung 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['zh-CN'] = { 7 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 8 | daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], 9 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 10 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 11 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | today: "今日", 13 | format: "yyyy年mm月dd日", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /js/locales/bootstrap-datepicker.zh-TW.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Traditional Chinese translation for bootstrap-datepicker 3 | * Rung-Sheng Jang 4 | * FrankWu Fix more appropriate use of Traditional Chinese habit 5 | */ 6 | ;(function($){ 7 | $.fn.datepicker.dates['zh-TW'] = { 8 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 9 | daysShort: ["週日", "週一", "週二", "週三", "週四", "週五", "週六", "週日"], 10 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 11 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 13 | today: "今天", 14 | format: "yyyy年mm月dd日", 15 | weekStart: 1 16 | }; 17 | }(jQuery)); 18 | -------------------------------------------------------------------------------- /js/mde-wrapper.js: -------------------------------------------------------------------------------- 1 | function myPreviewRender (text) { 2 | text = text.replace(/[\u00A0-\u9999<>\&]/gim, function(i) { 3 | return '&#'+i.charCodeAt(0)+';'; 4 | }); 5 | text = SimpleMDE.prototype.markdown(text); 6 | text = text.replace(/ /g, ' '); 7 | 8 | return text; 9 | }; 10 | 11 | function MDEWrapper(textarea, enableButton, disableButton) { 12 | this.element = textarea; 13 | this.enableButton = enableButton; 14 | this.disableButton = disableButton; 15 | this.simplemde = null; 16 | 17 | var wrapper = this; 18 | 19 | if (this.enableButton) { 20 | this.enableButton.on('click', function() {wrapper.enable()}); 21 | } 22 | if (this.disableButton) { 23 | this.disableButton.on('click', function() {wrapper.disable()}); 24 | } 25 | } 26 | 27 | MDEWrapper.prototype.enable = function() { 28 | var wrapper = this; 29 | if (this.simplemde == null) { 30 | this.simplemde = new SimpleMDE({ 31 | element: wrapper.element, 32 | forceSync: true, 33 | status: true, 34 | previewRender: myPreviewRender, 35 | spellChecker: false, 36 | promptURLs: true 37 | }); 38 | if (this.enableButton) { 39 | this.enableButton.addClass('active'); 40 | } 41 | if (this.disableButton) { 42 | this.disableButton.removeClass('active'); 43 | } 44 | } 45 | } 46 | 47 | MDEWrapper.prototype.disable = function() { 48 | if (this.simplemde != null) { 49 | this.simplemde.toTextArea(); 50 | this.simplemde = null; 51 | if (this.disableButton) { 52 | this.disableButton.addClass('active'); 53 | } 54 | if (this.enableButton) { 55 | this.enableButton.removeClass('active'); 56 | } 57 | } 58 | } 59 | 60 | MDEWrapper.prototype.isEnabled = function() { 61 | return this.simplemde != null; 62 | } -------------------------------------------------------------------------------- /locale.bat: -------------------------------------------------------------------------------- 1 | msgfmt -o locale\fr_FR\LC_MESSAGES\Studs.mo locale\fr_FR\LC_MESSAGES\Studs.po 2 | msgfmt -o locale\es_ES\LC_MESSAGES\Studs.mo locale\es_ES\LC_MESSAGES\Studs.po 3 | msgfmt -o locale\de_DE\LC_MESSAGES\Studs.mo locale\de_DE\LC_MESSAGES\Studs.po 4 | msgfmt -o locale\en_GB\LC_MESSAGES\Studs.mo locale\en_GB\LC_MESSAGES\Studs.po 5 | pause -------------------------------------------------------------------------------- /maintenance.php: -------------------------------------------------------------------------------- 1 | display('maintenance.tpl'); 23 | -------------------------------------------------------------------------------- /php.ini: -------------------------------------------------------------------------------- 1 | display_errors = Off 2 | error_reporting = E_ALL & ~E_NOTICE 3 | log_errors = On 4 | error_log = /var/log/apache2/error.log 5 | ignore_repeated_errors = On 6 | register_globals = Off 7 | 8 | 9 | [Date] 10 | date.timezone = "Europe/Paris" 11 | -------------------------------------------------------------------------------- /phpunit.bat: -------------------------------------------------------------------------------- 1 | vendor\bin\phpunit.bat --bootstrap app\tests\bootstrap.php app/tests -------------------------------------------------------------------------------- /phpunit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | vendor/bin/phpunit --bootstrap app/tests/bootstrap.php app/tests 3 | -------------------------------------------------------------------------------- /po2json.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 |
    convert($po);
    13 | print_r($json);
    14 | ?>
    15 | 16 | -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | Allow: /index.php 4 | Allow: /create_poll.php 5 | Disallow: /* -------------------------------------------------------------------------------- /scripts/.htaccess: -------------------------------------------------------------------------------- 1 | allow from 127.0.0.1 2 | deny from all -------------------------------------------------------------------------------- /tpl/add_column.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name="header"} 4 | 10 | 11 | {/block} 12 | 13 | {block name=main} 14 | 15 |
    16 |
    17 |

    {__('adminstuds', 'Column\'s adding')}

    18 | 19 | {* Messages *} 20 | {include 'part/messages.tpl'} 21 | 22 | {if $format === 'D'} 23 |
    24 | 25 |
    26 |
    27 | 28 | 29 |
    30 | ({__('Date', 'dd/mm/yyyy')}) 31 |
    32 |
    33 |
    34 | 35 |
    36 | 37 |
    38 |
    39 | {else} 40 |
    41 | 42 |
    43 | 44 |
    45 |
    46 | {/if} 47 |
    48 | {__('adminstuds', 'Back to the poll')} 49 | 50 |
    51 |
    52 |
    53 | {/block} -------------------------------------------------------------------------------- /tpl/admin/admin_page.tpl: -------------------------------------------------------------------------------- 1 | {extends 'page.tpl'} 2 | 3 | {block 'main'} 4 | 9 | {block 'admin_main'}{/block} 10 | {/block} 11 | -------------------------------------------------------------------------------- /tpl/admin/config.tpl: -------------------------------------------------------------------------------- 1 | '; 24 | 25 | // Application name 26 | const NOMAPPLICATION = '{$appName|addslashes_single_quote}'; 27 | 28 | // Database administrator email 29 | const ADRESSEMAILADMIN = '{$appMail}'; 30 | 31 | // Email for automatic responses (you should set it to "no-reply") 32 | const ADRESSEMAILREPONSEAUTO = '{$responseMail}'; 33 | 34 | // Database server name, leave empty to use a socket 35 | const DB_CONNECTION_STRING = '{$dbConnectionString}'; 36 | 37 | // Database user 38 | const DB_USER= '{$dbUser}'; 39 | 40 | // Database password 41 | const DB_PASSWORD = '{$dbPassword|addslashes_single_quote}'; 42 | 43 | // Table name prefix 44 | const TABLENAME_PREFIX = '{$dbPrefix}'; 45 | 46 | // Name of the table that stores migration script already executed 47 | const MIGRATION_TABLE = '{$migrationTable}'; 48 | 49 | // Default Language 50 | const DEFAULT_LANGUAGE = '{$defaultLanguage}'; 51 | 52 | // List of supported languages, fake constant as arrays can be used as constants only in PHP >=5.6 53 | $ALLOWED_LANGUAGES = [ 54 | 'fr' => 'Français', 55 | 'en' => 'English', 56 | 'oc' => 'Occitan', 57 | 'es' => 'Español', 58 | 'de' => 'Deutsch', 59 | 'nl' => 'Dutch', 60 | 'it' => 'Italiano', 61 | 'br' => 'Brezhoneg', 62 | ]; 63 | 64 | // Path to image file with the title 65 | const IMAGE_TITRE = 'images/logo-framadate.png'; 66 | 67 | // Clean URLs, boolean 68 | const URL_PROPRE = {if in_array($cleanUrl, array('1', 'on', 'true'))}true{else}false{/if}; 69 | 70 | // Use REMOTE_USER data provided by web server 71 | const USE_REMOTE_USER = true; 72 | 73 | // Path to the log file 74 | const LOG_FILE = 'admin/stdout.log'; 75 | 76 | // Days (after expiration date) before purging a poll 77 | const PURGE_DELAY = 60; 78 | 79 | // Max slots per poll 80 | const MAX_SLOTS_PER_POLL = 366; 81 | 82 | // Number of seconds before we allow to resend an "Remember Edit Link" email. 83 | const TIME_EDIT_LINK_EMAIL = 60; 84 | 85 | // Config 86 | $config = [ 87 | /* general config */ 88 | 'use_smtp' => true, // use email for polls creation/modification/responses notification 89 | /* home */ 90 | 'show_what_is_that' => true, // display "how to use" section 91 | 'show_the_software' => true, // display technical information about the software 92 | 'show_cultivate_your_garden' => true, // display "development and administration" information 93 | /* create_classic_poll.php / create_date_poll.php */ 94 | 'default_poll_duration' => 180, // default values for the new poll duration (number of days). 95 | /* create_classic_poll.php */ 96 | 'user_can_add_img_or_link' => true, // user can add link or URL when creating his poll. 97 | 'markdown_editor_by_default' => true // The markdown editor for the description is enabled by default 98 | ]; 99 | -------------------------------------------------------------------------------- /tpl/admin/index.tpl: -------------------------------------------------------------------------------- 1 | {extends 'admin/admin_page.tpl'} 2 | 3 | {block 'main'} 4 |
    5 | 8 | 11 | 14 | 17 | {if $logsAreReadable} 18 | 21 | {/if} 22 |
    23 | {/block} 24 | -------------------------------------------------------------------------------- /tpl/admin/logs.tpl: -------------------------------------------------------------------------------- 1 | {extends 'admin/admin_page.tpl'} 2 | 3 | {block 'admin_main'} 4 |
    {$logs|html}
    5 | {/block} 6 | -------------------------------------------------------------------------------- /tpl/admin/migration.tpl: -------------------------------------------------------------------------------- 1 | {extends 'admin/admin_page.tpl'} 2 | 3 | {block 'admin_main'} 4 |
    5 |
    6 |

    {__('Admin', 'Summary')}

    7 | {__('Admin', 'Succeeded:')} {$countSucceeded|html} / {$countTotal|html} 8 |
    9 | {__('Admin', 'Failed:')} {$countFailed|html} / {$countTotal|html} 10 |
    11 | {__('Admin', 'Skipped:')} {$countSkipped|html} / {$countTotal|html} 12 |
    13 |
    14 |

    {__('Admin', 'Success')}

    15 |
      16 | {foreach $success as $s} 17 |
    • {$s|html}
    • 18 | {foreachelse} 19 |
    • {__('Admin', 'Nothing')}
    • 20 | {/foreach} 21 |
    22 |
    23 | 24 |
    25 |

    {__('Admin', 'Fail')}

    26 |
      27 | {foreach $fail as $f} 28 |
    • {$f|html}
    • 29 | {foreachelse} 30 |
    • {__('Admin', 'Nothing')}
    • 31 | {/foreach} 32 |
    33 |
    34 | 35 |
    36 | {__('Generic', 'Page generated in')} {$time} {__('Generic', 'seconds')} 37 |
    38 |
    39 | {/block} 40 | -------------------------------------------------------------------------------- /tpl/admin/purge.tpl: -------------------------------------------------------------------------------- 1 | {extends 'admin/admin_page.tpl'} 2 | 3 | {block 'admin_main'} 4 | {if $message} 5 | 6 | {/if} 7 |
    8 | 9 |
    10 | 11 |
    12 |
    13 | {/block} 14 | -------------------------------------------------------------------------------- /tpl/confirm/delete_comments.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name=main} 4 |
    5 |
    6 |

    {__('adminstuds', 'Confirm removal of all comments of the poll')}

    7 |

    8 |

    9 |
    10 |
    11 | {/block} -------------------------------------------------------------------------------- /tpl/confirm/delete_poll.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name=main} 4 |
    5 |
    6 |

    {__('adminstuds', 'Confirm removal of the poll')}

    7 |

    8 |

    9 |
    10 |
    11 | {/block} -------------------------------------------------------------------------------- /tpl/confirm/delete_votes.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name=main} 4 |
    5 |
    6 |

    {__('adminstuds', 'Confirm removal of all votes of the poll')}

    7 |

    8 |

    9 |
    10 |
    11 | {/block} -------------------------------------------------------------------------------- /tpl/create_classic_poll_step3.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name="header"} 4 | 10 | 11 | {/block} 12 | 13 | {block name="main"} 14 |
    15 |
    16 |
    17 |
    18 |

    {__('Step 3', 'List of your choices')}

    19 | {$summary} 20 |
    21 |
    22 |

    {__('Step 3', 'Your poll will automatically be archived')} {$default_poll_duration} {__('Generic', 'days')} {__('Step 3', 'after the last date of your poll.')} 23 |
    {__('Step 3', 'You can set a closer archiving date for it.')}

    24 |
    25 | 26 |
    27 |
    28 | 29 | 30 |
    31 |
    32 | {__('Date', 'dd/mm/yyyy')} 33 |
    34 |
    35 |
    36 |

    {__('Step 3', 'Once you have confirmed the creation of your poll, you will be automatically redirected on the administration page of your poll.')}

    37 | {if $use_smtp} 38 |

    {__('Step 3', 'Then, you will receive quickly two emails: one contening the link of your poll for sending it to the voters, the other contening the link to the administration page of your poll.')}

    39 | {/if} 40 |
    41 |

    42 | 43 | 44 |

    45 |
    46 |
    47 |
    48 | {/block} -------------------------------------------------------------------------------- /tpl/error.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name=main} 4 |
    5 |

    {$error|html}

    6 |

    {__('Generic', 'Back to the homepage of')} {$APPLICATION_NAME|html}

    7 |
    8 | {/block} 9 | -------------------------------------------------------------------------------- /tpl/find_polls.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name=main} 4 | {if !empty($message)} 5 | 6 | {/if} 7 |
    8 |
    9 |
    10 |
    11 |
    12 | 13 | 14 |
    15 |
    16 |
    17 |
    18 | 19 |
    20 |
    21 |
    22 | {/block} 23 | -------------------------------------------------------------------------------- /tpl/header.tpl: -------------------------------------------------------------------------------- 1 | 25 |
    26 | -------------------------------------------------------------------------------- /tpl/mail/find_polls.tpl: -------------------------------------------------------------------------------- 1 |

    {__f('FindPolls', 'Here is the list of the polls that you manage on %s:', $smarty.const.NOMAPPLICATION)}

    2 |
      3 | {foreach $polls as $poll} 4 |
    • 5 | {$poll->title|html} 6 | ({__('Generic', 'Creation date:')} {$poll->creation_date|date_format:$date_format['txt_full']}) 7 |
    • 8 | {/foreach} 9 |
    10 |

    {__('FindPolls','Have a good day!')}

    11 |

    12 | 13 | {__('FindPolls','PS: this email has been sent because you – or someone else – asked to get back the polls created with your email address.')} 14 | {capture name="email_url"}{$smarty.const.ADRESSEMAILADMIN}{/capture} 15 | {__f('FindPolls',"If you weren't the source of this action and if you think this is an abuse of the service, please notify the administrator on %s.", $smarty.capture.email_url)} 16 | 17 |

    -------------------------------------------------------------------------------- /tpl/mail/remember_edit_link.tpl: -------------------------------------------------------------------------------- 1 |

    {$poll->title|html|string_format:__('EditLink', 'Edit link for poll "%s"')}

    2 |

    3 | {__('EditLink', 'Here is the link for editing your vote:')} 4 | {$poll->title|html} 5 |

    -------------------------------------------------------------------------------- /tpl/maintenance.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name=main} 4 |
    5 |

    {__('Maintenance', 'The application')} {$APPLICATION_NAME} {__('Maintenance', 'is currently under maintenance.')}

    6 |

    {__('Maintenance', 'Thank you for your understanding.')}

    7 |
    8 | {/block} -------------------------------------------------------------------------------- /tpl/page.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {if !empty($title)} 8 | {$title|html} - {$APPLICATION_NAME|html} 9 | {else} 10 | {$APPLICATION_NAME|html} 11 | {/if} 12 | 13 | 14 | {if isset($favicon)} 15 | 16 | {/if} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {if "en" != $locale} 27 | 28 | {/if} 29 | 30 | 31 | {block name="header"}{/block} 32 | 33 | 34 | 35 | {if $use_nav_js} 36 | 37 | {/if} 38 |
    39 | 40 | {include file='header.tpl'} 41 | 42 | {block name=main}{/block} 43 | 44 |
    45 | 46 | {if isset($tracking_code)} 47 | {$tracking_code} 48 | {/if} 49 | 50 | 51 | -------------------------------------------------------------------------------- /tpl/part/comments.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | {* Comment list *} 4 | {include 'part/comments_list.tpl'} 5 | 6 | {* Add comment form *} 7 | {if $active && !$expired && $accessGranted} 8 |
    9 | 10 | 11 | {if !empty($admin_poll_id)} 12 | 13 | {/if} 14 |
    15 |
    16 |
    {__('Comments', 'Add a comment to the poll')} 17 |
    18 | 19 | 20 |
    21 |
    22 | 23 | 24 |
    25 |
    26 | 27 |
    28 |
    29 |
    30 |
    31 |
    32 |
    33 | {/if} -------------------------------------------------------------------------------- /tpl/part/comments_list.tpl: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | {if $comments|count > 0} 4 |

    {__('Comments', 'Comments of polled people')}

    5 | {foreach $comments as $comment} 6 |
    7 | {if $admin && !$expired} 8 | 9 | {/if} 10 | {$comment->date|date_format:$date_format['txt_datetime_short']} 11 | {$comment->name|html}  12 | {$comment->comment|escape|nl2br} 13 |
    14 | {/foreach} 15 | {/if} 16 |
    17 |
    18 |
    -------------------------------------------------------------------------------- /tpl/part/description_markdown.tpl: -------------------------------------------------------------------------------- 1 | {* Description buttons for markdown *} 2 | 3 |
    4 | 5 | 6 |
    7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tpl/part/form_remember_edit_link.tpl: -------------------------------------------------------------------------------- 1 |
    2 | 13 | 14 |
    15 | 16 | -------------------------------------------------------------------------------- /tpl/part/messages.tpl: -------------------------------------------------------------------------------- 1 | {* Messages *} 2 |
    3 | {if !empty($message)} 4 | 21 | {/if} 22 |
    23 | 24 | 25 | -------------------------------------------------------------------------------- /tpl/part/password_request.tpl: -------------------------------------------------------------------------------- 1 | {if !$expired && ($active || $resultPubliclyVisible)} 2 | 3 | 4 |
    5 |
    6 |
    7 | 8 |
    9 | 10 | 11 | 12 |
    13 |
    14 |
    15 |
    16 |
    17 | {/if} 18 | 19 | -------------------------------------------------------------------------------- /tpl/part/poll_hint.tpl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tpl/part/poll_hint_admin.tpl: -------------------------------------------------------------------------------- 1 | 35 | -------------------------------------------------------------------------------- /tpl/part/scroll_left_right.tpl: -------------------------------------------------------------------------------- 1 | {* Scroll left and right *} 2 | -------------------------------------------------------------------------------- /tpl/poll_deleted.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name=main} 4 |
    5 |

    {$message->message}

    6 |

    {__('Generic', 'Back to the homepage of')} {$APPLICATION_NAME|html}

    7 |
    8 | {/block} -------------------------------------------------------------------------------- /tpl/studs.tpl: -------------------------------------------------------------------------------- 1 | {extends file='page.tpl'} 2 | 3 | {block name="header"} 4 | 5 | 6 | 7 | 8 | 9 | 10 | {if $admin} 11 | 12 | 13 | 14 | 15 | {/if} 16 | 17 | {/block} 18 | 19 | {block name=main} 20 | 21 | 22 | {* Messages *} 23 | {include 'part/messages.tpl'} 24 | 25 | 26 | {if !$accessGranted && !$resultPubliclyVisible} 27 | 28 | {include 'part/password_request.tpl' active=$poll->active} 29 | 30 | {else} 31 | 32 | {* Global informations about the current poll *} 33 | {include 'part/poll_info.tpl' admin=$admin} 34 | 35 | {* Information about voting *} 36 | {if $expired} 37 |
    38 |

    {__('studs', 'The poll is expired, it will be deleted soon.')}

    39 |

    {__('studs', 'Deletion date:')} {$deletion_date|date_format:$date_format['txt_short']|html}

    40 |
    41 | {else} 42 | {if $admin} 43 | {include 'part/poll_hint_admin.tpl'} 44 | {else} 45 | {include 'part/poll_hint.tpl' active=$poll->active} 46 | {/if} 47 | {/if} 48 | 49 | {if !$accessGranted && $resultPubliclyVisible} 50 | {include 'part/password_request.tpl' active=$poll->active} 51 | {/if} 52 | 53 | {* Vote table *} 54 | {if $poll->format === 'D'} 55 | {include 'part/vote_table_date.tpl' active=$poll->active} 56 | {else} 57 | {include 'part/vote_table_classic.tpl' active=$poll->active} 58 | {/if} 59 | 60 | {* Comments *} 61 | {include 'part/comments.tpl' active=$poll->active comments=$comments} 62 | 63 | {/if} 64 | 65 | {/block} 66 | --------------------------------------------------------------------------------