Your IP : 52.15.224.97


Current Path : /var/www/www-root/data/www/info.monolith-realty.ru/bitrix/modules/vote/lib/
Upload File :
Current File : /var/www/www-root/data/www/info.monolith-realty.ru/bitrix/modules/vote/lib/event.php

<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage vote
 * @copyright 2001-2016 Bitrix
 */
namespace Bitrix\Vote;
use Bitrix\Main\ArgumentException;
use Bitrix\Main\ArgumentNullException;
use Bitrix\Main\ArgumentTypeException;
use \Bitrix\Main\Entity;
use Bitrix\Main\Error;
use Bitrix\Main\ErrorCollection;
use \Bitrix\Main\Localization\Loc;
use Bitrix\Main\DB\MssqlConnection;
use Bitrix\Main\DB\MysqlCommonConnection;
use Bitrix\Main\DB\OracleConnection;
use Bitrix\Main\Application;
use Bitrix\Main\ORM\Fields\BooleanField;
use Bitrix\Main\ORM\Fields\DatetimeField;
use Bitrix\Main\ORM\Fields\EnumField;
use Bitrix\Main\ORM\Fields\ExpressionField;
use Bitrix\Main\ORM\Fields\IntegerField;
use Bitrix\Main\ORM\Fields\Relations\Reference;
use Bitrix\Main\ORM\Fields\StringField;
use Bitrix\Main\ORM\Fields\TextField;
use Bitrix\Main\ORM\Query\Join;
use Bitrix\Main\Type\Dictionary as EventResult;
use Bitrix\Vote\Base\BaseObject;

Loc::loadMessages(__FILE__);

/**
 * Class VoteEventTable
 * Fields:
 * <ul>
 * <li> ID int mandatory
 * <li> VOTE_ID int,
 * <li> VOTE_USER_ID int,
 * <li> DATE_VOTE datetime,
 * <li> STAT_SESSION_ID int,
 * <li> IP string(15),
 * <li> VALID string(1)
 * </ul>
 *
 */
class EventTable extends Entity\DataManager
{
	/**
	 * Returns DB table name for entity
	 *
	 * @return string
	 */
	public static function getTableName()
	{
		return 'b_vote_event';
	}

	/**
	 * Returns entity map definition.
	 *
	 * @return array
	 */
	public static function getMap()
	{
		return array(
			(new IntegerField('ID', ['primary' => true, 'autocomplete' => true])),
			(new IntegerField('VOTE_ID')),
			(new IntegerField('VOTE_USER_ID', ["required" => true])),
			(new DatetimeField('DATE_VOTE')),
			(new IntegerField('STAT_SESSION_ID')),
			(new StringField('IP', ['size' => 15])),
			(new BooleanField('VALID', ['values' => ['N', 'Y'], 'default_value' => 'Y'])),
			(new BooleanField('VISIBLE', ['values' => ['N', 'Y'], 'default_value' => 'Y'])),
			(new Reference('QUESTION', \Bitrix\Vote\EventQuestionTable::class, Join::on('this.ID', 'ref.EVENT_ID'))),
			(new Reference('USER', \Bitrix\Vote\UserTable::class, Join::on('this.VOTE_USER_ID', 'ref.ID'))),
		);
	}
}
/**
 * Class EventQuestionTable
 * Fields:
 * <ul>
 * <li> ID int mandatory
 * <li> EVENT_ID int,
 * <li> QUESTION_ID int,
 * </ul>
 *
 */
class EventQuestionTable extends Entity\DataManager
{
	/**
	 * Returns DB table name for entity
	 *
	 * @return string
	 */
	public static function getTableName()
	{
		return 'b_vote_event_question';
	}

	/**
	 * Returns entity map definition.
	 *
	 * @return array
	 */
	public static function getMap()
	{
		return array(
			'ID' => array(
				'data_type' => 'integer',
				'primary' => true,
				'autocomplete' => true,
			),
			'EVENT_ID' => array(
				'data_type' => 'integer',
			),
			'QUESTION_ID' => array(
				'data_type' => 'integer',
			),
			'VOTE' => array(
				'data_type' => '\Bitrix\Vote\EventTable',
				'reference' => array(
					'=this.EVENT_ID' => 'ref.ID',
				),
				'join_type' => 'RIGHT',
			),
			'ANSWER' => array(
				'data_type' => '\Bitrix\Vote\EventAnswerTable',
				'reference' => array(
					'=this.ID' => 'ref.EVENT_QUESTION_ID',
				),
				'join_type' => 'LEFT',
			)
		);
	}
}/**
 * Class EventAnswerTable
 * Fields:
 * <ul>
 * <li> ID int mandatory
 * <li> EVENT_QUESTION_ID int,
 * <li> ANSWER_ID int,
 * <li> MESSAGE text,
 * </ul>
 *
 *
 * DO NOT WRITE ANYTHING BELOW THIS
 *
 * <<< ORMENTITYANNOTATION
 * @method static EO_EventAnswer_Query query()
 * @method static EO_EventAnswer_Result getByPrimary($primary, array $parameters = array())
 * @method static EO_EventAnswer_Result getById($id)
 * @method static EO_EventAnswer_Result getList(array $parameters = array())
 * @method static EO_EventAnswer_Entity getEntity()
 * @method static \Bitrix\Vote\EO_EventAnswer createObject($setDefaultValues = true)
 * @method static \Bitrix\Vote\EO_EventAnswer_Collection createCollection()
 * @method static \Bitrix\Vote\EO_EventAnswer wakeUpObject($row)
 * @method static \Bitrix\Vote\EO_EventAnswer_Collection wakeUpCollection($rows)
 */
class EventAnswerTable extends Entity\DataManager
{
	/**
	 * Returns DB table name for entity
	 *
	 * @return string
	 */
	public static function getTableName()
	{
		return 'b_vote_event_answer';
	}

	/**
	 * Returns entity map definition.
	 *
	 * @return array
	 */
	public static function getMap()
	{
		return array(
			'ID' => array(
				'data_type' => 'integer',
				'primary' => true,
				'autocomplete' => true,
			),
			'EVENT_QUESTION_ID' => array(
				'data_type' => 'integer',
			),
			'ANSWER_ID' => array(
				'data_type' => 'integer',
			),
			'MESSAGE' => array(
				'data_type' => 'text',
			)
		);
	}
}

class Event extends BaseObject
{
	private $vote;
	/**
	 * EVENT_FIELD_BALLOT_TEMPLATE - is a template to catch voting
	 * [#ID#][BALLOT][#QUESTION_ID#][#ANSWER_ID#][MESSAGE] - template for text
	 */
	const EVENT_FIELD_NAME = "bx_vote_event"; //
	const EVENT_FIELD_BALLOT_TEMPLATE = self::EVENT_FIELD_NAME."[#ID#][BALLOT][#QUESTION_ID#]"; // this is template for voting
	const EVENT_FIELD_MESSAGE_TEMPLATE = self::EVENT_FIELD_NAME."[#ID#][MESSAGE][#QUESTION_ID#][#ANSWER_ID#]"; // this is template for voting
	const EVENT_FIELD_EXTRAS_TEMPLATE = self::EVENT_FIELD_NAME."[#ID#][EXTRAS][#ENTITY_ID#]";

	/** @var  ErrorCollection */
	protected $errorCollection;
	/**
	 * Event constructor.
	 * @param Vote $vote
	 */
	function __construct(\Bitrix\Vote\Vote $vote)
	{
		$this->vote = $vote;
		$this->errorCollection = new ErrorCollection;
	}

	/**
	 * @param int $voteId Vote Id.
	 * @return void
	 */
	public static function calculateStatistic($voteId)
	{
		$connection = Application::getInstance()->getConnection();
		if ($connection instanceof MysqlCommonConnection)
		{
			$connection->executeSqlBatch(<<<SQL
UPDATE b_vote V SET V.COUNTER=(
	SELECT COUNT(VE.ID) 
	FROM b_vote_event VE 
	WHERE VE.VOTE_ID=V.ID) 
WHERE V.ID={$voteId};
UPDATE b_vote_question VQ SET VQ.COUNTER=(
	SELECT COUNT(VEQ.ID) 
	FROM b_vote_event_question VEQ 
	WHERE VEQ.QUESTION_ID=VQ.ID)
WHERE VQ.VOTE_ID={$voteId};
UPDATE b_vote_answer VA, b_vote_question VQ SET VA.COUNTER=(
	SELECT COUNT(VEA.ID)
	FROM b_vote_event_answer VEA 
	WHERE VEA.ANSWER_ID=VA.ID)
WHERE VQ.ID = VA.QUESTION_ID AND VQ.VOTE_ID={$voteId};
UPDATE b_vote_user VU, b_vote_event VE SET VU.COUNTER=(
	SELECT COUNT(VE.ID)
	FROM b_vote_event VE 
	WHERE VU.ID=VE.VOTE_USER_ID AND VE.VALID='Y')
WHERE VU.ID IN (SELECT VOTE_USER_ID FROM b_vote_event WHERE VOTE_ID={$voteId});
SQL
			);
		}
		else if ($connection instanceof MssqlConnection)
		{
			$connection->executeSqlBatch(<<<SQL
UPDATE b_vote SET b_vote.COUNTER=E.COUNTER
FROM (
	SELECT COUNT(ID) COUNTER, VOTE_ID
	FROM b_vote_event  
	WHERE VOTE_ID={$voteId}
	GROUP BY VOTE_ID) E 
WHERE b_vote.ID=E.VOTE_ID AND b_vote.ID={$voteId}
GO
UPDATE b_vote_question SET COUNTER=E.COUNTER
FROM (
	SELECT COUNT(EQ.ID) COUNTER, EQ.QUESTION_ID
	FROM b_vote_event_question EQ
	JOIN b_vote_question Q ON (Q.ID = EQ.QUESTION_ID) 
	WHERE Q.VOTE_ID={$voteId}
	GROUP BY EQ.QUESTION_ID) E
WHERE b_vote_question.ID=E.QUESTION_ID AND b_vote_question.VOTE_ID={$voteId}
GO
UPDATE b_vote_answer SET b_vote_answer.COUNTER=E.COUNTER
FROM (
	SELECT COUNT(VEA.ID) COUNTER, VEA.ANSWER_ID
	FROM b_vote_event_answer VEA 
	INNER JOIN b_vote_answer VA ON (VA.ID=VEA.ANSWER_ID)
	INNER JOIN b_vote_question VQ ON (VQ.ID=VA.QUESTION_ID)
	WHERE VQ.VOTE_ID={$voteId}
	GROUP BY VEA.ANSWER_ID
) E
WHERE b_vote_answer.ID=E.ANSWER_ID
GO
UPDATE b_vote_user SET b_vote_user.COUNTER=E.COUNTER
FROM (
	SELECT COUNT(ID) COUNTER, VOTE_USER_ID 
	FROM b_vote_event 
	WHERE VALID='Y'
	GROUP BY VOTE_USER_ID
) E 
WHERE b_vote_user.ID=E.VOTE_USER_ID AND b_vote_user.ID IN (SELECT VOTE_USER_ID FROM b_vote_event WHERE VOTE_ID={$voteId})
GO
SQL
			);
		}
		elseif ($connection instanceof OracleConnection)
		{
			$connection->executeSqlBatch(<<<SQL
UPDATE b_vote V SET V.COUNTER=(
	SELECT COUNT(VE.ID) 
	FROM b_vote_event VE 
	WHERE VE.VOTE_ID=V.ID) 
WHERE V.ID={$voteId}
/
UPDATE b_vote_question VQ SET VQ.COUNTER=(
	SELECT COUNT(VEQ.ID) 
	FROM b_vote_event_question VEQ 
	WHERE VEQ.QUESTION_ID=VQ.ID)
WHERE VQ.VOTE_ID={$voteId}
/
UPDATE b_vote_answer VA SET VA.COUNTER=(
	SELECT COUNT(ID)
	FROM b_vote_event_answer
	WHERE ANSWER_ID=VA.ID)
WHERE VA.QUESTION_ID IN (
	SELECT ID 
	FROM b_vote_question 
	WHERE VOTE_ID={$voteId}
)
/
UPDATE b_vote_user VU SET VU.COUNTER=(
	SELECT COUNT(ID)
	FROM b_vote_event 
	WHERE VU.ID=VOTE_USER_ID AND VALID='Y')
WHERE VU.ID IN (SELECT VOTE_USER_ID FROM b_vote_event WHERE VOTE_ID={$voteId})
/
SQL
			);
		}
	}

	/**
	 * @param int $voteId Vote Id.
	 * @return void
	 */
	public static function resetStatistic($voteId)
	{
		$connection = Application::getInstance()->getConnection();
		$helper = $connection->getSqlHelper();

		$connection->query($helper->prepareCorrelatedUpdate(
			'b_vote_user',
			'U',
			[
				'COUNTER' => '(CASE WHEN U.COUNTER - E.COUNTER > 0 THEN U.COUNTER - E.COUNTER ELSE 0 END)'
			],
			"( SELECT count(ID) as COUNTER, VOTE_USER_ID
				FROM b_vote_event
				WHERE VOTE_ID={$voteId}
				GROUP BY VOTE_USER_ID ) E",
			'E.VOTE_USER_ID=U.ID'
		));

		$connection->query("UPDATE b_vote set COUNTER = 0 WHERE ID = {$voteId}");

		$connection->query("UPDATE b_vote_question SET COUNTER=0 WHERE VOTE_ID = {$voteId}");

		$connection->query("UPDATE b_vote_answer SET COUNTER=0
			WHERE QUESTION_ID IN (
				SELECT ID FROM b_vote_question WHERE VOTE_ID={$voteId}
		)");

		$connection->query("DELETE FROM b_vote_event WHERE VOTE_ID = {$voteId}");

		$connection->query("DELETE FROM b_vote_event_question
			WHERE QUESTION_ID IN (
				SELECT ID from b_vote_question WHERE VOTE_ID = {$voteId}
		)");

		$connection->query("DELETE FROM b_vote_event_answer
			WHERE ANSWER_ID IN (
				SELECT A.ID
					FROM b_vote_answer A
					JOIN b_vote_question Q ON (Q.ID = A.QUESTION_ID)
				WHERE Q.VOTE_ID = {$voteId}
		)");

		/***************** Event OnVoteReset *******************************/
		foreach (GetModuleEvents("vote", "onVoteReset", true) as $event)
		{
			ExecuteModuleEventEx($event, array($voteId));
		}
		/***************** /Event ******************************************/
	}

	/**
	 * @param int $eventId Event ID.
	 * @return boolean
	 */
	public static function deleteEvent($eventId)
	{
		if (!is_integer($eventId))
			throw new ArgumentTypeException("event ID");
		else if ($eventId <= 0)
			throw new ArgumentNullException("event ID");

		self::setValid($eventId, "N");
		$connection = Application::getInstance()->getConnection();
		$connection->queryExecute("DELETE FROM b_vote_event_answer WHERE EVENT_QUESTION_ID IN (SELECT VEQ.ID FROM b_vote_event_question VEQ WHERE VEQ.EVENT_ID={$eventId})");
		$connection->queryExecute("DELETE FROM b_vote_event_question WHERE EVENT_ID={$eventId}");
		$connection->queryExecute("DELETE FROM b_vote_event WHERE ID={$eventId}");
		return $connection->getAffectedRowsCount() > 0;
	}
	/**
	 * @param int $eventId Event ID.
	 * @param string $valid Validation ("Y" || "N").
	 * @return boolean
	 */
	public static function setValid($eventId, $valid)
	{
		$valid = ($valid == "Y" ? "Y" : "N");
		$eventId = intval($eventId);
		if ($eventId <= 0)
			return false;

		$dbRes = EventTable::getList(array(
			'select' => array(
				'V_' => '*',
				'Q_' => 'QUESTION.*',
				'A_' => 'QUESTION.ANSWER.*'),
			'filter' => array(
				'ID' => $eventId,
				'!=VALID' => $valid),
			'order' => array(
				'ID' => 'ASC',
				'QUESTION.ID' => 'ASC',
				'QUESTION.ANSWER.ID' => 'ASC')));
		if (($res = $dbRes->fetch()) && $res)
		{
			$questions = array();
			$answers = array();
			EventTable::update($eventId, array("VALID" => $valid));
			VoteTable::setCounter(array($res["V_VOTE_ID"]), ($valid == "Y"));
			UserTable::setCounter(array($res["V_VOTE_USER_ID"]), ($valid == "Y"));
			do
			{
				$questions[] = $res["Q_QUESTION_ID"];
				$answers[] = $res["A_ANSWER_ID"];
			} while ($res = $dbRes->fetch());

			QuestionTable::setCounter(array_unique($questions), ($valid == "Y"));
			AnswerTable::setCounter($answers, ($valid == "Y"));
			return true;
		}
		return false;
	}

	public static function getFieldName($id, $questionId)
	{
		return str_replace(array("#ID#", "#QUESTION_ID#"), array($id, $questionId), self::EVENT_FIELD_BALLOT_TEMPLATE);
	}
	public static function getMessageFieldName($id, $questionId, $answerId)
	{
		return str_replace(array("#ID#", "#QUESTION_ID#", "#ANSWER_ID#"), array($id, $questionId, $answerId), self::EVENT_FIELD_MESSAGE_TEMPLATE);
	}
	public static function getExtrasFieldName($id, $name)
	{
		return str_replace(array("#ID#", "#ENTITY_ID#"), array($id, $name), self::EVENT_FIELD_EXTRAS_TEMPLATE);
	}

	public static function getDataFromRequest($id, array $request)
	{
		if (
			array_key_exists(self::EVENT_FIELD_NAME, $request) &&
			is_array($request[self::EVENT_FIELD_NAME]) &&
			array_key_exists($id, $request[self::EVENT_FIELD_NAME]) &&
			is_array($request[self::EVENT_FIELD_NAME][$id])
		)
		{
			$data = [];
			if (array_key_exists("BALLOT", $request[self::EVENT_FIELD_NAME][$id]))
			{
				foreach ($request[self::EVENT_FIELD_NAME][$id]["BALLOT"] as $qId => $answerIds)
				{
					$answerIds = is_array($answerIds) ? $answerIds : array($answerIds);
					foreach ($answerIds as $answerId)
					{
						$data["BALLOT"] = isset($data["BALLOT"]) && is_array($data["BALLOT"]) ? $data["BALLOT"] : [];
						$data["BALLOT"][$qId] = isset($data["BALLOT"][$qId]) && is_array($data["BALLOT"][$qId]) ? $data["BALLOT"][$qId] : [];
						$data["BALLOT"][$qId][$answerId] = true;
					}
				}
			}
			if (array_key_exists("MESSAGE", $request[self::EVENT_FIELD_NAME][$id]))
			{
				foreach ($request[self::EVENT_FIELD_NAME][$id]["MESSAGE"] as $qId => $answerIds)
				{

					foreach ($answerIds as $answerId => $message)
					{
						$message = trim($message);
						if ($message <> '')
						{
							$data["MESSAGE"][$qId] = is_array($data["MESSAGE"][$qId]) ? $data["MESSAGE"][$qId] : [];
							$data["MESSAGE"][$qId][$answerId] = $message;
						}
					}
				}
			}
			if (array_key_exists("EXTRAS", $request[self::EVENT_FIELD_NAME][$id]))
			{
				$data["EXTRAS"] = $request[self::EVENT_FIELD_NAME][$id]["EXTRAS"];
			}
			if (!empty($data))
				return $data;
		}
		return null;
	}
	/**
	 * @param $data
	 * @return array
	 */
	public function check(array $ballot)
	{
		$questions = $this->vote->getQuestions();
		$fields = array();
		$data = (array_key_exists("BALLOT", $ballot) ? $ballot["BALLOT"] : []);
		$message = (array_key_exists("MESSAGE", $ballot) ? $ballot["MESSAGE"] : []);
		foreach ($questions as $questionId => $question)
		{
			if (array_key_exists($question["ID"], $data) && is_array($data[$question["ID"]]))
			{
				$answers = array_intersect_key($data[$question["ID"]], $question["ANSWERS"]);
				if ($question["FIELD_TYPE"] === QuestionTypes::COMPATIBILITY && array_key_exists($question["ID"], $message))
				{
					foreach($message[$question["ID"]] as $id => $value)
					{
						$value = trim($value);
						if ($value <> '')
						{
							$answers[$id] = true;
						}
					}
				}
				if (!empty($answers))
				{
					//region  this code should not exists
					if ($question["FIELD_TYPE"] == QuestionTypes::COMPATIBILITY)
					{
						$singleVal = array(AnswerTypes::RADIO => false, AnswerTypes::DROPDOWN => false);
						$res = [];
						foreach ($answers as $id => $value)
						{
							$answer = $question["ANSWERS"][$id];
							switch ($answer["FIELD_TYPE"])
							{
								case AnswerTypes::RADIO :
								case AnswerTypes::DROPDOWN :
									if (!$singleVal[$answer["FIELD_TYPE"]])
									{
										$singleVal[$answer["FIELD_TYPE"]] = true;
										$res[$id] = $value;
									}
									break;
								default :
									$res[$id] = $value;
									break;
							}
						}
						if (!empty($res))
						{
							$fields[$question["ID"]] = $res;
						}
					}
					//endregion
					else if ($question["FIELD_TYPE"] == QuestionTypes::RADIO ||
						$question["FIELD_TYPE"] == QuestionTypes::DROPDOWN)
					{
						$val = reset($answers);
						$fields[$question["ID"]] = array(
							key($answers) => $val
						);
					}
					else
					{
						$fields[$question["ID"]] = $answers;
					}
					//region Check for message text from form
					$res = $fields[$question["ID"]];
					if (array_key_exists($question["ID"], $message))
					{
						$message[$question["ID"]] = is_array($message[$question["ID"]]) ? $message[$question["ID"]] : [];
						foreach ($fields[$question["ID"]] as $id => $value)
						{
							if (array_key_exists($id, $message[$question["ID"]]))
								$fields[$question["ID"]][$id] = trim($message[$question["ID"]][$id]);
						}
					}
					if (empty($fields[$question["ID"]]))
					{
						unset($fields[$question["ID"]]);
					}
					//endregion
				}
			}
			if ($question['REQUIRED'] === 'Y' && $question['ACTIVE'] === 'Y' && !array_key_exists($question["ID"], $fields))
			{
				$this->errorCollection->add(array(new Error(Loc::getMessage("VOTE_REQUIRED_MISSING"), "QUESTION_".$questionId)));
			}
		}
		if (empty($fields))
			$this->errorCollection->add(array(new Error(Loc::getMessage("USER_VOTE_EMPTY"), "VOTE_".$this->vote->getId())));

		return $fields;
	}

	public function add(array $eventFields, array $ballot, $setCounter = true): ?EventResult
	{
		$this->errorCollection->clear();
		$fields = $this->check($ballot);
		if (!$this->errorCollection->isEmpty())
		{
			return null;
		}
		$eventFields = array(
			"VOTE_ID"			=> $this->vote->getId(),
			"VOTE_USER_ID"		=> $eventFields["VOTE_USER_ID"],
			"DATE_VOTE"			=> (array_key_exists("DATE_VOTE", $eventFields) ? $eventFields["DATE_VOTE"] : new \Bitrix\Main\Type\DateTime()),
			"STAT_SESSION_ID"	=> $eventFields["STAT_SESSION_ID"],
			"IP"				=> $eventFields["IP"],
			"VALID"				=> $eventFields["VALID"] ?: "Y",
			"VISIBLE" 			=> ($eventFields["VISIBLE"] ?: "Y")
		);
		if (array_key_exists("EXTRAS", $ballot) && is_array($ballot["EXTRAS"]) && array_key_exists("VISIBLE", $ballot["EXTRAS"]))
			$eventFields["VISIBLE"] = ($ballot["EXTRAS"]["VISIBLE"] === "N" ? "N" : "Y");

		// Compatibility
		$sqlAnswers = array();
		foreach ($fields as $questionId => $fieldsAnswer)
		{
			foreach ($fieldsAnswer as $answerId => $value)
			{
				$sqlAnswers[$questionId][$answerId] = array(
					"ANSWER_ID" => $answerId,
					"MESSAGE" => is_string($value)? mb_substr($value, 0, 2000) : "");
			}
		}

		/***************** Event onBeforeVoting ****************************/
		foreach (GetModuleEvents("vote", "onBeforeVoting", true) as $event)
		{
			if (ExecuteModuleEventEx($event, array(&$eventFields, &$sqlAnswers)) === false)
			{
				$this->errorCollection->add(array(new Error("onBeforeVoting error", "VOTE_".$eventFields["VOTE_ID"])));
				return null;
			}
		}
		/***************** /Event ******************************************/
		if (!empty($sqlAnswers) && ($eventId = EventTable::add($eventFields)->getId()) && $eventId > 0)
		{
			$ids = array();
			$answerIdsForCounter = array();
			foreach ($sqlAnswers as $questionId => $fieldsAnswer)
			{
				if (($eventQId = EventQuestionTable::add(array("EVENT_ID" => $eventId, "QUESTION_ID" => $questionId))->getId()) && $eventQId > 0)
				{
					$ids[$questionId] = [
						"EVENT_ID" => $eventQId,
						"ANSWERS" => []
					];
					foreach ($fieldsAnswer as $answerId => $res)
					{
						if (($eventAId = EventAnswerTable::add(array(
								"EVENT_QUESTION_ID" => $eventQId,
								"ANSWER_ID" => $res["ANSWER_ID"],
								"MESSAGE" => $res["MESSAGE"]))->getId()
							) && $eventAId > 0)
						{
							$ids[$questionId]["ANSWERS"][$answerId] = [
								"EVENT_ID" => $eventAId,
								"EVENT_QUESTION_ID" => $eventQId,
								"ANSWER_ID" => $res["ANSWER_ID"],
								"MESSAGE" => $res["MESSAGE"]
							];
							$answerIdsForCounter[] = $answerId;
						}
					}
					if (empty($ids[$questionId]))
					{
						EventQuestionTable::delete($eventQId);
						unset($ids[$questionId]);
					}
				}
			}

			if (!empty($ids))
			{
				if ($setCounter)
				{
					VoteTable::setCounter(array($this->vote->getId()), true);
					QuestionTable::setCounter(array_keys($ids), true);
					AnswerTable::setCounter($answerIdsForCounter, true);
				}

				return new EventResult(array(
					"EVENT_ID" => $eventId,
					"VOTE_ID"			=> $eventFields["VOTE_ID"],
					"VOTE_USER_ID"		=> $eventFields["VOTE_USER_ID"],
					"DATE_VOTE"			=> $eventFields["DATE_VOTE"],
					"STAT_SESSION_ID"	=> $eventFields["SESS_SESSION_ID"] ?? null,
					"IP"				=> $eventFields["IP"],
					"VISIBLE"			=> $eventFields["VISIBLE"],
					"VALID"				=> $eventFields["VALID"],
					"BALLOT" => $ids
				));
			}
			EventTable::delete($eventId);
		}
		return null;
	}
}