Passed
Pull Request — master (#23)
by Michael
12:42
created

index.php (2 issues)

1
<?php declare(strict_types=1);
2
/*
3
                XOOPS - PHP Content Management System
4
                    Copyright (c) 2000-2020 XOOPS.org
5
                       <https://xoops.org>
6
  This program is free software; you can redistribute it and/or modify
7
  it under the terms of the GNU General Public License as published by
8
  the Free Software Foundation; either version 2 of the License, or
9
  (at your option) any later version.
10
11
  You may not change or alter any portion of this comment or credits
12
  of supporting developers from this source code or any supporting
13
  source code which is considered copyrighted (c) material of the
14
  original comment or credit authors.
15
16
  This program is distributed in the hope that it will be useful,
17
  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
  GNU General Public License for more details.
20
21
  You should have received a copy of the GNU General Public License
22
  along with this program; if not, write to the Free Software
23
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
24
*/
25
26
/**
27
 * XOOPS Poll main index page
28
 *
29
 * @copyright::  {@link https://xoops.org XOOPS Project}
30
 * @license  ::    {@link https://www.gnu.org/licenses/gpl-2.0.html GNU GPL 2.0 or later}
31
 * @since    ::      1.0
32
 *
33
 * @uses     xoops_load() method used to load classes
34
 * @uses     CriteriaCompo
35
 * @uses     Criteria
36
 * @uses     mixed $GLOBALS['xoops']::path gets XOOPS directory information
37
 * @uses     string $GLOBALS['xoops']::url gets XOOPS URL/URI information
38
 * @uses     mixed $GLOBALS['xoopsUser'] gets information about the currently logged-in user
39
 * @uses     xoops_getenv() function to retrieve XOOPS environment variables
40
 * @uses     xoops_getUserTimestamp() function to convert time to user timestamp
41
 * @uses     formatTimestamp() function to convert timestamp to human-readable form
42
 * @uses     xoops_getModuleHandler() to load handler for this module's class(es)
43
 * @uses     redirect_header() function used to send user to another location after completing task(s)
44
 */
45
46
use Xmf\Module\Admin;
47
use Xmf\Request;
48
use XoopsModules\Newbb;
49
use XoopsModules\Xoopspoll\{
50
    Constants,
51
    Helper,
52
    Poll,
53
    Renderer,
54
    Utility
55
};
56
57
require_once \dirname(__DIR__, 2) . '/mainfile.php';
58
59
$helper      = Helper::getInstance();
60
$myts        = \MyTextSanitizer::getInstance();
61
$pollHandler = $helper->getHandler('Poll');
62
$logHandler  = $helper->getHandler('Log');
63
64
$pollId = Request::getInt('poll_id', 0);
65
$url    = Request::getString('url', '');
66
67
if (empty($pollId)) {
68
    $GLOBALS['xoopsOption']['template_main'] = 'xoopspoll_index.tpl';
69
    require $GLOBALS['xoops']->path('header.php');
70
    $GLOBALS['xoopsTpl']->assign(
71
        [
72
            'lang_pollslist'      => _MD_XOOPSPOLL_POLLSLIST,
73
            'lang_pollquestion'   => _MD_XOOPSPOLL_POLLQUESTION,
74
            'lang_pollvoters'     => _MD_XOOPSPOLL_VOTERS,
75
            'lang_votes'          => _MD_XOOPSPOLL_VOTES,
76
            'lang_expiration'     => _MD_XOOPSPOLL_EXPIRATION,
77
            'lang_results'        => _MD_XOOPSPOLL_RESULTS,
78
            'lang_mustlogin'      => _MD_XOOPSPOLL_MUSTLOGIN,
79
            'disp_votes'          => $GLOBALS['xoopsModuleConfig']['disp_vote_nums'],
80
            'results_link_icon'   => Admin::iconUrl('', '16') . '/open12.gif',
81
            'obscured_icon'       => $GLOBALS['xoops']->url('modules/xoopspoll/assets/images/icons/obscured.png'),
82
            'lang_obscured_alt'   => _MD_XOOPSPOLL_OBSCURED,
83
            'lang_obscured_title' => _MD_XOOPSPOLL_OBSCURED,
84
        ]
85
    );
86
87
    /* get polls to display on this page */
88
    $limit    = Request::getInt('limit', Constants::DEFAULT_POLL_PAGE_LIMIT);
89
    $start    = Request::getInt('start', 0);
90
    $criteria = new \CriteriaCompo();
91
    $criteria->add(new \Criteria('start_time', time(), '<='));  // only display polls that have started
92
93
    /* check to see if forum module is installed and
94
     * exclude polls created from a forum
95
     */
96
    if ($GLOBALS['xoopsModuleConfig']['hide_forum_polls']) {
97
        /** @var \XoopsModuleHandler $moduleHandler */
98
        $moduleHandler = xoops_getHandler('module');
99
        $newbbModule   = $moduleHandler->getByDirname('newbb');
100
        if ($newbbModule instanceof \XoopsModule && $newbbModule->isactive()) {
101
            /** @var Newbb\TopicHandler $topicHandler */
102
            $topicHandler = Newbb\Helper::getInstance()->getHandler('Topic');
103
            $tFields      = ['topic_id', 'poll_id'];
104
            $tArray       = $topicHandler->getAll(new \Criteria('topic_haspoll', 0, '>'), $tFields, false);
105
            if (!empty($tArray)) {
106
                $tcriteria = [];
107
                foreach ($tArray as $t) {
108
                    $tcriteria[] = $t['poll_id'];
109
                }
110
                if (!empty($tcriteria)) {
111
                    $tstring = '(' . implode(',', $tcriteria) . ')';
112
                    $criteria->add(new \Criteria('poll_id', $tstring, 'NOT IN'));
113
                }
114
            }
115
            unset($topicHandler, $tFields, $tArray);
116
        }
117
        unset($newbbModule);
118
    }
119
    $criteria->setLimit($limit);
120
    $criteria->setStart($start);
121
    $criteria->setSort('weight ASC, end_time');  // trick criteria to allow 2 sort criteria
122
    $criteria->setOrder('DESC');
123
    $pollObjs = $pollHandler->getAll($criteria);
124
125
    foreach ($pollObjs as $pollObj) {
126
        $polls                 = [];
127
        $id                    = $pollObj->getVar('poll_id');
128
        $polls['pollId']       = $id;
129
        $polls['pollQuestion'] = $pollObj->getVar('question');
130
131
        if ($pollObj->getVar('end_time') > time()) {
132
            $polls['hasEnded'] = false;
133
            $polls['pollEnd']  = formatTimestamp($pollObj->getVar('end_time'), 'm');
134
            $uid               = (($GLOBALS['xoopsUser'] instanceof \XoopsUser)
135
                                  && ($GLOBALS['xoopsUser']->getVar('uid') > 0)) ? $GLOBALS['xoopsUser']->getVar('uid') : 0;
136
            /**
137
             * {@internal DEBUG CODE
138
             * echo "<br>ID[{$id}] IP[" . xoops_getenv('REMOTE_ADDR') . "] UID[{$uid}]<br>";
139
             * $vp = (!empty($_COOKIE['voted_polls'])) ? $_COOKIE['voted_polls'] : array();
140
             * $cook = (!array_key_exists($id, $vp)) ? "NO COOKIE KEY" : "FOUND COOKIE KEY";
141
             * $cv = (!$pollObj->isAllowedToVote()) ? "Not ALLOWED" :  "ALLOWED";
142
             * $lv = ($logHandler->hasVoted($id, xoops_getenv('REMOTE_ADDR'), $uid)) ? "HAS VOTED" : "HAS NOT VOTED";
143
             * if (!$pollObj->isAllowedToVote() || ($logHandler->hasVoted($id, xoops_getenv('REMOTE_ADDR'), $uid))) {
144
             * echo "NO: {$cv} {$lv} {$cook}<br>\n";
145
             * } else {
146
             * echo "YES: {$cv} {$lv} {$cook}<br>\n";
147
             * }
148
             * } */
149
            if (!$pollObj->isAllowedToVote() || $logHandler->hasVoted($id, xoops_getenv('REMOTE_ADDR'), $uid)) {
150
                $polls['canVote'] = false;
151
            } else {
152
                $polls['canVote'] = true;
153
            }
154
        } else {
155
            /* poll has ended */
156
            $polls['hasEnded'] = true;
157
            $polls['pollEnd']  = _MD_XOOPSPOLL_EXPIRED;
158
            $polls['canVote']  = false; /* force so user can't vote */
159
        }
160
        $polls['pollVoters'] = (int)$pollObj->getVar('voters');
161
        $polls['pollVotes']  = (int)$pollObj->getVar('votes');
162
        $polls['visible']    = true === $pollObj->isResultVisible();
163
        $GLOBALS['xoopsTpl']->append('polls', $polls);
164
    }
165
    unset($pollObjs);
166
    require $GLOBALS['xoops']->path('footer.php');
167
} elseif (!empty($_POST['option_id'])) {
168
    /* user just tried to vote */
169
    //    $option_id   = Request::getInt('option_id', 0, 'POST');
170
    $mail_author = false;
171
    $pollObj     = $pollHandler->get($pollId);
172
    if ($pollObj instanceof Poll) {
173
        if ($pollObj->getVar('multiple')) {
174
            $optionId = Request::getArray('option_id', [], 'POST');
175
            $optionId = array_map('\intval', $optionId); // make sure values are integers
176
        } else {
177
            $optionId = Request::getInt('option_id', 0, 'POST');
178
        }
179
        if ($pollObj->hasExpired()) {
180
            /* poll has expired so just show the results */
181
            $msg = _MD_XOOPSPOLL_SORRYEXPIRED;
182
        } else {
183
            $msg = _MD_XOOPSPOLL_MUSTLOGIN;
184
            //@todo:: add $url to all redirects
185
            //            $url = $GLOBALS['xoops']->buildUrl("index.php", array('poll_id' => $pollId));
186
            if ($pollObj->isAllowedToVote()) {
187
                $thisVoter     = (!empty($GLOBALS['xoopsUser'])
188
                                  && ($GLOBALS['xoopsUser'] instanceof \XoopsUser)) ? $GLOBALS['xoopsUser']->getVar('uid') : null;
189
                $votedThisPoll = $logHandler->hasVoted($pollId, xoops_getenv('REMOTE_ADDR'), (int)$thisVoter);
190
                if (!$votedThisPoll) {
191
                    /* user that hasn't voted before in this poll or module preferences allow it */
192
                    $voteTime = time();
193
                    if ($pollObj->vote($optionId, xoops_getenv('REMOTE_ADDR'), $voteTime)) {
194
                        if (!$pollHandler->updateCount($pollObj)) { // update the count and save in db
0 ignored issues
show
Bug Best Practice introduced by
The expression $pollHandler->updateCount($pollObj) of type false|integer is loosely compared to false; this is ambiguous if the integer can be 0. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
195
                            echo $pollObj->getHtmlErrors();
196
                            exit();
197
                        }
198
                        $msg = _MD_XOOPSPOLL_THANKSFORVOTE;
199
                    } else {
200
                        /* there was a problem registering the vote */
201
                        redirect_header($GLOBALS['xoops']->buildUrl('index.php', ['poll_id' => $pollId]), Constants::REDIRECT_DELAY_MEDIUM, _MD_XOOPSPOLL_VOTE_ERROR);
202
                    }
203
                } else {
204
                    $msg = _MD_XOOPSPOLL_ALREADYVOTED;
205
                }
206
                /* set anon user vote (and the time they voted) */
207
                if (!$GLOBALS['xoopsUser'] instanceof \XoopsUser) {
208
                    Utility::setVoteCookie($pollId, (string)$voteTime, 0);
209
                }
210
            } else {
211
                $msg = _MD_XOOPSPOLL_CANNOTVOTE;
212
            }
213
        }
214
    } else {
215
        $msg = _MD_XOOPSPOLL_ERROR_INVALID_POLLID;
216
    }
217
    if ('' !== $url) {
218
        redirect_header($url, Constants::REDIRECT_DELAY_MEDIUM, $msg);
219
    } else {
220
        redirect_header($GLOBALS['xoops']->buildUrl('pollresults.php', ['poll_id' => $pollId]), Constants::REDIRECT_DELAY_MEDIUM, $msg);
221
    }
222
} else {
223
    $pollObj = $pollHandler->get($pollId);
224
    if ($pollObj->hasExpired()) {
225
        redirect_header($GLOBALS['xoops']->buildUrl('pollresults.php', ['poll_id' => $pollId]), Constants::REDIRECT_DELAY_SHORT, _MD_XOOPSPOLL_SORRYEXPIRED);
226
    }
227
    $GLOBALS['xoopsOption']['template_main'] = 'xoopspoll_view.tpl';
228
    require $GLOBALS['xoops']->path('header.php');
229
230
    $renderer = new Renderer($pollObj, $helper);
231
    $renderer->assignForm($GLOBALS['xoopsTpl']);
232
233
    $voteCount = $logHandler->getTotalVotesByPollId($pollId);
234
235
    $canVote    = false;
236
    $lang_multi = '';
237
    if ($pollObj->isAllowedToVote()) {
238
        $thisVoter  = (!empty($GLOBALS['xoopsUser'])
239
                       && ($GLOBALS['xoopsUser'] instanceof \XoopsUser)) ? $GLOBALS['xoopsUser']->getVar('uid') : null;
240
        $canVote    = !$logHandler->hasVoted($pollId, xoops_getenv('REMOTE_ADDR'), $thisVoter);
0 ignored issues
show
It seems like $thisVoter can also be of type null; however, parameter $uid of XoopsModules\Xoopspoll\LogHandler::hasVoted() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

240
        $canVote    = !$logHandler->hasVoted($pollId, xoops_getenv('REMOTE_ADDR'), /** @scrutinizer ignore-type */ $thisVoter);
Loading history...
241
        $multiple   = $pollObj->getVar('multiple');
242
        $multiLimit = (int)$pollObj->getVar('multilimit');
243
        if ($multiple && ($multiLimit > 0)) {
244
            $lang_multi = sprintf(_MD_XOOPSPOLL_MULTITEXT, $multiLimit);
245
        }
246
    }
247
248
    $GLOBALS['xoopsTpl']->assign(
249
        [
250
            'voteCount'    => $voteCount,
251
            'lang_vote'    => _MD_XOOPSPOLL_VOTE,
252
            'lang_results' => _MD_XOOPSPOLL_RESULTS,
253
            'disp_votes'   => $GLOBALS['xoopsModuleConfig']['disp_vote_nums'],
254
            'can_vote'     => $canVote,
255
            'lang_multi'   => $lang_multi,
256
        ]
257
    );
258
    require $GLOBALS['xoops']->path('footer.php');
259
}
260