<?php
/*-------------------------------------------------------+
| PHPFusion Content Management System
| Copyright (C) PHP Fusion Inc
| https://phpfusion.com/
+--------------------------------------------------------+
| Filename: poll.php
| Author: Chan (Frederick MC Chan)
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/
namespace PHPFusion\Forums\Threads;
/**
* Class Poll
*
* @package PHPFusion\Forums\Threads
*/
class Poll {
/**
* Permissions for Forum Poll
*
* @var array
*/
private static $permissions = [];
/**
* Poll data
*
* @var array
*/
private static $data = [];
private static $poll_info = [
'openform' => '', // the oepn form tag and request url action link
'closeform' => '', // the closing form tag
'edit_button' => '', // ['title'] title of the button ['link'] edit url of the button
'delete_button' => '', // same as above but for delete action
'post_button' => '', // the post button
'content' => [], // ['value'] - the option choice count, ['title'] - the title of the poll option, ['output'] - the
];
/**
* Forum Poll Locale
*
* @var array
*/
private static $locale = [];
/**
* Object
*
* @param array $thread_info
*/
public function __construct(array $thread_info) {
self::$locale = fusion_get_locale('', FORUM_LOCALE);
self::setPollPermissions($thread_info['permissions']);
self::setThreadData($thread_info['thread']);
}
/**
* Set Permissions Settings
*
* @param array $thread_info
*/
private static function setPollPermissions(array $thread_info) {
self::$permissions = $thread_info;
}
/**
* @param array $thread_data
*/
private static function setThreadData(array $thread_data) {
self::$data = $thread_data;
}
/**
* Displays HTML Poll Form
*
* @param bool $edit
*
* @template display_forum_pollform
* @throws \Exception
*/
public static function renderPollForm($edit = FALSE) {
$access_admin = $edit ? self::getPollPermissions("can_edit_poll") : self::getPollPermissions(
"can_create_poll"
);
if ($access_admin === TRUE) { // if permitted creating new poll.
$locale = self::$locale;
$poll_field = [];
$poll_data = [
'thread_id' => self::$data['thread_id'],
'forum_poll_title' => isset($_POST['forum_poll_title']) ? form_sanitizer(
$_POST['forum_poll_title'], '', 'forum_poll_title'
) : '',
'forum_poll_start' => time(), // time poll started
'forum_poll_length' => 2, // how many poll options we have
'forum_poll_votes' => 0, // how many vote this poll has
];
// counter of lengths
$option_data[1] = '';
$option_data[2] = '';
// calculate poll lengths
if (post(['poll_options']) && is_array(post(['poll_options']))) {
foreach (post(['poll_options']) as $i => $value) {
$option_data[$i] = form_sanitizer($value, '', "poll_options");
}
}
if (isset($_POST['add_poll_option']) && post(['poll_options'])) {
// reindex the whole array with blank values.
foreach (post(['poll_options']) as $i => $value) {
$option_data[$i] = form_sanitizer($value, '', "poll_options");
}
if (fusion_safe()) {
$option_data = array_values(array_filter($option_data));
array_unshift($option_data, NULL);
unset($option_data[0]);
$poll_data['forum_poll_length'] = count($option_data);
}
array_push($option_data, '');
}
if ($edit === TRUE) {
$result = dbquery(
"SELECT * FROM ".DB_FORUM_POLLS." WHERE thread_id='".self::$data['thread_id']."'"
);
if (dbrows($result) > 0) {
if (isset($_POST['update_poll']) || isset($_POST['add_poll_option'])) {
$load = FALSE;
$poll_data += dbarray($result); // append if not available.
} else {
$load = TRUE;
$poll_data = dbarray($result); // call
}
if (isset($_POST['update_poll'])) {
$poll_data = [
'thread_id' => self::$data['thread_id'],
'forum_poll_title' => form_sanitizer($_POST['forum_poll_title'], '', 'forum_poll_title'),
'forum_poll_start' => $poll_data['forum_poll_start'], // time poll started
'forum_poll_length' => $poll_data['forum_poll_length'], // how many poll options we have
];
dbquery_insert(
DB_FORUM_POLLS, $poll_data, 'update', ['primary_key' => 'thread_id', 'no_unique' => TRUE]
);
$i = 1;
// populate data for matches
$poll_result = dbquery(
"SELECT forum_poll_option_id FROM ".DB_FORUM_POLL_OPTIONS." WHERE thread_id='".self::$data['thread_id']."'"
);
while ($_data = dbarray($poll_result)) {
$_poll[$_data['forum_poll_option_id']] = $_data;
// Prune the emptied fields AND field is not required.
if (empty($option_data[$_data['forum_poll_option_id']]) && fusion_safe()) {
dbquery(
"DELETE FROM ".DB_FORUM_POLL_OPTIONS." WHERE thread_id='".self::$data['thread_id']."' AND forum_poll_option_id='".$_data['forum_poll_option_id']."'"
);
}
}
foreach ($option_data as $option_text) {
if ($option_text) {
if (fusion_safe()) {
if (isset($_poll[$i])) { // has record
dbquery(
"UPDATE ".DB_FORUM_POLL_OPTIONS." SET forum_poll_option_text='".$option_text."' WHERE thread_id='".self::$data['thread_id']."' AND forum_poll_option_id='".$i."'"
);
} else { // no record - create
$array = [
'thread_id' => self::$data['thread_id'],
'forum_poll_option_id' => $i,
'forum_poll_option_text' => $option_text,
'forum_poll_option_votes' => 0,
];
dbquery_insert(DB_FORUM_POLL_OPTIONS, $array, 'save');
}
}
$i++;
}
}
if (fusion_safe()) {
redirect(fusion_get_settings('siteurl')."infusions/forum/postify.php?post=editpoll&error=0&forum_id=".self::$data['forum_id']."&thread_id=".self::$data['thread_id']);
}
}
// how to make sure values containing options votes
$poll_field['openform'] = openform('pollform', 'post', FUSION_REQUEST);
$poll_field['openform'] .= "<div class='text-info m-b-20 m-t-10'>".str_replace(
'{REQUIRED}', '<span class=\'required\'>*</span>', $locale['forum_0613']
)."</div>\n";
$poll_field['poll_field'] = form_text(
'forum_poll_title', $locale['forum_0604'], $poll_data['forum_poll_title'],
[
'max_length' => 255,
'placeholder' => $locale['forum_0604a'],
'inline' => TRUE,
'required' => TRUE
]
);
if ($load == FALSE) {
for ($i = 1; $i <= count($option_data); $i++) {
$poll_field['poll_field'] .= form_text(
"poll_options[$i]", sprintf($locale['forum_0606'], $i), $option_data[$i],
[
'max_length' => 255,
'placeholder' => $locale['forum_0605'],
'inline' => TRUE,
'required' => $i <= 2
]
);
}
} else {
$poll_query = "
SELECT forum_poll_option_text, forum_poll_option_votes
FROM ".DB_FORUM_POLL_OPTIONS." WHERE thread_id='".intval(self::$data['thread_id'])."' ORDER BY forum_poll_option_id ASC
";
$result = dbquery($poll_query);
$i = 1;
while ($_pData = dbarray($result)) {
$poll_field['poll_field'] .= form_text(
"poll_options[$i]", $locale['forum_0605'].' '.$i, $_pData['forum_poll_option_text'],
[
'max_length' => 255,
'placeholder' => 'Poll Options',
'inline' => 1,
'required' => $i <= 2 or $_pData['forum_poll_option_votes']
]
);
$i++;
}
}
$poll_field['poll_field'] .= "<div class='col-xs-12 col-sm-offset-3'>\n";
$poll_field['poll_field'] .= form_button(
'add_poll_option', $locale['forum_0608'], $locale['forum_0608'], ['class' => 'btn-default']
);
$poll_field['poll_field'] .= "</div>\n";
$poll_field['poll_button'] = form_button(
'update_poll', $locale['forum_2013'], $locale['forum_2013'], ['class' => 'btn-primary']
);
$poll_field['closeform'] = closeform();
} else {
redirect(FORUM."index.php"); // redirect because the poll id is not available.
}
} else {
// Save New Poll
if (isset($_POST['add_poll'])) {
dbquery_insert(DB_FORUM_POLLS, $poll_data, 'save');
$poll_data['forum_poll_id'] = dblastid();
$i = 1;
foreach ($option_data as $option_text) {
if ($option_text) {
$poll_data['forum_poll_option_id'] = $i;
$poll_data['forum_poll_option_text'] = $option_text;
$poll_data['forum_poll_option_votes'] = 0;
dbquery_insert(DB_FORUM_POLL_OPTIONS, $poll_data, 'save');
$i++;
}
}
if (fusion_safe()) {
dbquery(
"UPDATE ".DB_FORUM_THREADS." SET thread_poll='1' WHERE thread_id='".self::$data['thread_id']."'"
);
redirect(fusion_get_settings('siteurl')."infusions/forum/postify.php?post=newpoll&error=0&forum_id=".self::$data['forum_id']."&thread_id=".self::$data['thread_id']);
}
}
// blank poll - no poll on edit or new thread
$poll_field['openform'] = openform('pollform', 'post', FUSION_REQUEST, ['class' => 'spacer-xs']);
$poll_field['poll_field'] = form_text(
'forum_poll_title', $locale['forum_0604'], $poll_data['forum_poll_title'],
[
'max_length' => 255,
'placeholder' => $locale['forum_0604a'],
'inline' => TRUE,
'required' => TRUE
]
);
for ($i = 1; $i <= count($option_data); $i++) {
$poll_field['poll_field'] .= form_text(
"poll_options[$i]", sprintf($locale['forum_0606'], $i), $option_data[$i],
[
'max_length' => 255,
'placeholder' => $locale['forum_0605'],
'inline' => 1,
'required' => $i <= 2
]
);
}
$poll_field['poll_field'] .= "<div class='col-xs-12 col-sm-offset-3'>\n";
$poll_field['poll_field'] .= form_button(
'add_poll_option', $locale['forum_0608'], $locale['forum_0608'], ['class' => 'btn-default']
);
$poll_field['poll_field'] .= "</div>\n";
$poll_field['poll_button'] = form_button(
'add_poll', $locale['forum_2011'], $locale['forum_2011'], ['class' => 'btn-primary']
);
$poll_field['closeform'] = closeform();
}
$info = [
'title' => (isset($_GET['action']) && $_GET['action'] == 'editpoll') ? $locale['forum_0603'] : $locale['forum_0366'],
'description' => $locale['forum_2000'].self::$data['thread_subject'],
'field' => $poll_field
];
display_forum_pollform($info);
} else {
redirect(FORUM);
}
}
/**
* Fetches Permissions Settings
*
* @param string $key
*
* @return bool
*/
private static function getPollPermissions($key) {
return (isset(self::$permissions[$key])) ? self::$permissions[$key] : FALSE;
}
/**
* HTML output for Poll form
*
* @return array
*/
public static function getPollInfo() {
return self::$poll_info;
}
/**
* Generate Poll HTML
*
* @param array $thread_data
*
* @return string
*/
public function generatePoll(array $thread_data) {
$locale = self::$locale;
$html = '';
if (self::getPollPermissions("can_access") && $thread_data['thread_poll'] == TRUE) {
$poll_query = "
SELECT poll_opts.*, poll.forum_poll_title, poll.forum_poll_votes
FROM ".DB_FORUM_POLL_OPTIONS." poll_opts
INNER JOIN ".DB_FORUM_POLLS." poll using (thread_id)
WHERE poll.thread_id=:thread_id ORDER BY forum_poll_option_id ASC
";
$poll_param = [':thread_id' => intval($thread_data['thread_id'])];
$poll_result = dbquery($poll_query, $poll_param);
if (dbrows($poll_result) > 0) {
$i = 0;
while ($pdata = dbarray($poll_result)) {
if ($i == 0) {
$poll['forum_poll_title'] = $pdata['forum_poll_title'];
$poll['forum_poll_votes'] = $pdata['forum_poll_votes'];
$poll['forum_poll_max_options'] = dbrows($poll_result);
}
$poll['forum_poll_options'][$pdata['forum_poll_option_id']] = $pdata;
$i++;
}
if (!empty($poll)) {
$can_vote_poll = self::getPollPermissions('can_vote_poll');
//var_dump($can_vote_poll);
$can_edit_poll = self::getPollPermissions('can_edit_poll');
//var_dump($can_edit_poll);
self::$poll_info['poll_title'] = $poll['forum_poll_title'];
// SQL cast poll vote
if (isset($_POST['poll_option']) && isnum(
$_POST['poll_option']
) && $_POST['poll_option'] <= $poll['forum_poll_max_options']) {
// Vote Poll
if ($can_vote_poll) {
$pollInput['poll_option_id'] = stripinput($_POST['poll_option']);
if (fusion_safe()) {
dbquery(
"UPDATE ".DB_FORUM_POLL_OPTIONS." SET forum_poll_option_votes=forum_poll_option_votes+1 WHERE thread_id='".intval(
$thread_data['thread_id']
)."' AND forum_poll_option_id='".intval($pollInput['poll_option_id'])."'"
);
dbquery(
"UPDATE ".DB_FORUM_POLLS." SET forum_poll_votes=forum_poll_votes+1 WHERE thread_id='".intval(
$thread_data['thread_id']
)."'"
);
dbquery(
"INSERT INTO ".DB_FORUM_POLL_VOTERS." (thread_id, forum_vote_user_id, forum_vote_user_ip, forum_vote_user_ip_type) VALUES ('".$thread_data['thread_id']."', '".fusion_get_userdata(
"user_id"
)."', '".USER_IP."', '".USER_IP_TYPE."')"
);
addnotice('success', $locale['forum_0614']);
redirect(INFUSIONS."forum/viewthread.php?thread_id=".$thread_data['thread_id']);
} else {
addnotice('danger', $locale['forum_0617']);
}
}
}
if ($can_vote_poll) {
// skips flood interval settings
self::$poll_info['openform'] = openform(
'poll_vote_form', 'post', '', [
'token_time' => time() - fusion_get_settings('flood_interval')
]
);
self::$poll_info['post_button'] = form_button(
'vote', $locale['forum_2010'], 'vote', ['class' => 'btn btn-primary m-l-20']
);
self::$poll_info['closeform'] = closeform();
}
if ($can_edit_poll === TRUE) {
self::$poll_info['edit_button'] = [
'link' => INFUSIONS."forum/viewthread.php?action=editpoll&forum_id=".$thread_data['forum_id']."&thread_id=".$thread_data['thread_id'],
'title' => $locale['forum_0603']
];
self::$poll_info['delete_button'] = [
'link' => INFUSIONS."forum/viewthread.php?action=deletepoll&forum_id=".$thread_data['forum_id']."&thread_id=".$thread_data['thread_id'],
'title' => $locale['delete']
];
$html .= "<div class='pull-right btn-group'>\n";
$html .= "<a class='btn btn-sm btn-default' href='".self::$poll_info['edit_button']['link']."'>".self::$poll_info['edit_button']['title']."</a>\n";
$html .= "<a class='btn btn-sm btn-default' href='".self::$poll_info['delete_button']['link']."' onclick='confirm('".$locale['forum_0616']."');'>".self::$poll_info['delete_button']['title']."</a>\n";
$html .= "</div>\n";
}
$html .= self::$poll_info['openform'];
$html .= "<h2 class='strong m-t-0 m-b-10'>".$locale['forum_0314'].": ".self::$poll_info['poll_title']."</h2>\n";
$html .= "<ul class='p-l-20 p-t-0 block'>\n";
if (!empty($poll['forum_poll_options'])) {
$i = 1;
self::$poll_info['poll_options'] = $poll['forum_poll_options'];
foreach ($poll['forum_poll_options'] as $poll_option) {
if (self::getPollPermissions("can_vote_poll") == TRUE) {
self::$poll_info['content'][$i] = [
'value' => $i,
'title' => $poll_option['forum_poll_option_text'],
'output' => "<input id='opt-".$i."' type='radio' name='poll_option' value='".$i."' class='m-r-15'>",
];
$html .= "<li><label for='opt-".$i."'>".self::$poll_info['content'][$i]['output'].self::$poll_info['content'][$i]['title']."</span>\n</label></li>\n";
} else {
$option_votes = ($poll['forum_poll_votes'] ? number_format(
100 / $poll['forum_poll_votes'] * $poll_option['forum_poll_option_votes']
) : 0);
self::$poll_info['content'][$i] = [
'value' => $i,
'title' => $poll_option['forum_poll_option_text'],
'output' => $option_votes,
];
$html .= progress_bar(
self::$poll_info['content'][$i]['output'], self::$poll_info['content'][$i]['title'].' ['.$poll_option['forum_poll_option_votes'].'/'.$poll['forum_poll_votes'].']',
['height' => '10px']
);
}
$i++;
}
}
$html .= "</ul>\n";
$html .= self::$poll_info['post_button'].self::$poll_info['closeform'];
}
}
}
return $html;
}
/**
* Executes poll deletion
*/
public function deletePoll() {
if (!empty(self::$data['thread_poll']) && $this->getPollPermissions("can_edit_poll")) {
if (fusion_safe()) {
dbquery("DELETE FROM ".DB_FORUM_POLLS." WHERE thread_id='".self::$data['thread_id']."'");
dbquery("DELETE FROM ".DB_FORUM_POLL_OPTIONS." WHERE thread_id='".self::$data['thread_id']."'");
dbquery("DELETE FROM ".DB_FORUM_POLL_VOTERS." WHERE thread_id='".self::$data['thread_id']."'");
dbquery(
"UPDATE ".DB_FORUM_THREADS." SET thread_poll='0' WHERE thread_id='".self::$data['thread_id']."'"
);
redirect(
INFUSIONS."forum/postify.php?post=deletepoll&error=4&forum_id=".self::$data['forum_id']."&thread_id=".self::$data['thread_id']
);
}
}
redirect(
INFUSIONS."forum/viewthread.php?forum_id=".self::$data['forum_id']."&thread_id=".self::$data['thread_id']
);
}
}