<?php
 class vB_Api_Content_Poll extends vB_Api_Content_Text { protected $contenttype = 'vBForum_Poll'; protected $bbcode_parser = false; protected $tableFields = []; protected $textRequired = false; protected function __construct() { parent::__construct(); $this->library = vB_Library::instance('Content_Poll'); } public function vote($polloptionids) { $polloptionids = is_array($polloptionids) ? $polloptionids : [$polloptionids]; $polloptionids = array_map('intval', $polloptionids); $polloptionids = array_unique($polloptionids); [ 'nodeid' => $nodeid, 'polloptions' => $options, ] = $this->validateAndGetPolloptions($polloptionids); $usercontext = vB::getUserContext(); if (!$usercontext->getChannelPermission('forumpermissions', 'canvote', $nodeid)) { throw new vB_Exception_Api('no_permission'); } $poll = $this->getContent($nodeid)[$nodeid] ?? false; if (empty($poll)) { return false; } if ($poll['timeout'] AND $poll['timeout'] < vB::getRequest()->getTimeNow()) { return false; } $currentUserid = vB::getCurrentSession()->get('userid'); if (!$currentUserid) { throw new vB_Exception_Api('not_logged_no_permission'); } $existingVotes = $this->assertor->getRows('vBForum:pollvote', [ 'userid' => $currentUserid, 'nodeid' => $nodeid, vB_dB_Query::COLUMNS_KEY => ['pollvoteid', 'polloptionid',] ]); if (count($existingVotes)) { if ($poll['canchangevotes']) { $this->deletePollVotes($existingVotes, $currentUserid); } else { return false; } } $lib = $this->library; $nodeid = $lib->vote($options); $lib->updatePollCache($nodeid, true); return $nodeid; } private function deletePollVotes($pollvotes, $userid) { $pollvoteids = array_column($pollvotes, 'pollvoteid'); $polloptionids = array_column($pollvotes, 'polloptionid'); $this->assertor->delete('vBForum:pollvote', [ 'pollvoteid' => $pollvoteids, ]); $polloptionCaches = $this->assertor->getRows('vBForum:polloption', [ 'polloptionid' => $polloptionids, vB_dB_Query::COLUMNS_KEY => ['polloptionid', 'voters', 'votes',] ], false, 'polloptionid'); foreach ($polloptionCaches AS $__polloptionid => ['voters' => $__voters, 'votes' => $__votes]) { $__voters = vb_unserialize($__voters ?? 'a:0:{}'); $__k = array_search($userid, $__voters); if ($__k !== false) { unset($__voters[$__k]); } $__voters = array_values($__voters); $__votes = count($__voters); $this->assertor->assertQuery('vBForum:polloption', [ vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'voters' => serialize($__voters), 'votes' => $__votes, vB_dB_Query::CONDITIONS_KEY => [ 'polloptionid' => $__polloptionid ] ]); } } private function validateAndGetPolloptions(array $polloptionids) : array { $options = $this->assertor->getRows('vBForum:polloption', [ 'polloptionid' => $polloptionids, ]); if (count($options) != count($polloptionids)) { throw new vB_Exception_Api('invalidvote'); } $nodeid = reset($options)['nodeid'] ?? 0; if (!$nodeid) { throw new vB_Exception_Api('invalidvote'); } foreach ($options AS ['nodeid' => $__nodeid]) { if ($nodeid != $__nodeid) { throw new vB_Exception_Api('invalidvote'); } } return [ 'nodeid' => $nodeid, 'polloptions' => $options, ]; } } 