Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
attach.php
1<?php
8namespace Bitrix\Vote;
9use \Bitrix\Main\AccessDeniedException;
10use \Bitrix\Main\ArgumentNullException;
11use \Bitrix\Main\ArgumentTypeException;
12use \Bitrix\Main\Entity;
13use \Bitrix\Main\Error;
14use \Bitrix\Main\ErrorCollection;
15use \Bitrix\Main\InvalidOperationException;
16use \Bitrix\Main\Localization\Loc;
17use \Bitrix\Main\ArgumentException;
18use \Bitrix\Main\NotSupportedException;
19use \Bitrix\Main\Type\DateTime;
20use \Bitrix\Vote\Attachment\Connector;
21use \Bitrix\Vote\Base\BaseObject;
22use \Bitrix\Vote\DBResult;
23use \Bitrix\Main\SystemException;
24use \Bitrix\Vote\Event;
25use \Bitrix\Main\ObjectNotFoundException;
26
27Loc::loadMessages(__FILE__);
28
56class AttachTable extends Entity\DataManager
57{
62 public static function getTableName()
63 {
64 return 'b_vote_attached_object';
65 }
66
71 public static function getMap()
72 {
73 return array(
74 'ID' => array(
75 'data_type' => 'integer',
76 'primary' => true,
77 'autocomplete' => true,
78 'title' => Loc::getMessage('V_TABLE_FIELD_ID'),
79 ),
80 'OBJECT_ID' => array(
81 'data_type' => 'integer',
82 'title' => Loc::getMessage('V_TABLE_FIELD_OBJECT_ID'),
83 ),
84 'MODULE_ID' => array(
85 'data_type' => 'string',
86 'size' => 32,
87 'title' => Loc::getMessage('V_TABLE_FIELD_MODULE_ID')
88 ),
89 'ENTITY_TYPE' => array(
90 'data_type' => 'string',
91 'size' => 100,
92 'title' => Loc::getMessage('V_TABLE_FIELD_ENTITY_TYPE')
93 ),
94 'ENTITY_ID' => array(
95 'data_type' => 'integer',
96 'title' => Loc::getMessage('V_TABLE_FIELD_OBJECT_ID'),
97 ),
98 'CREATE_TIME' => array(
99 'data_type' => 'datetime',
100 'title' => Loc::getMessage('V_TABLE_FIELD_TIMESTAMP_X'),
101 ),
102 'CREATED_BY' => array(
103 'data_type' => 'integer',
104 'title' => Loc::getMessage('V_TABLE_FIELD_AUTHOR_ID'),
105 ),
106 'VOTE' => array(
107 'data_type' => '\Bitrix\Vote\VoteTable',
108 'reference' => array(
109 '=this.OBJECT_ID' => 'ref.ID',
110 ),
111 'join_type' => 'INNER',
112 ),
113 );
114 }
115
120 public static function getList(array $parameters = array())
121 {
122 return new DBResult(parent::getList($parameters));
123 }
124
131 public static function deleteByFilter(array $filter)
132 {
133 if (!$filter)
134 {
135 throw new \Bitrix\Main\ArgumentNullException('filter');
136 }
137
138 $result = static::getList(array(
139 'select' => array('ID'),
140 'filter' => $filter,
141 ));
142 while($row = $result->fetch())
143 {
144 if(!empty($row['ID']))
145 {
146 $resultDelete = static::delete($row['ID']);
147 if(!$resultDelete->isSuccess())
148 {
149 return false;
150 }
151 }
152 }
153 return true;
154 }
155}
156
157class Attach extends BaseObject implements \ArrayAccess
158{
160 protected $attach;
162 protected $vote;
164 protected $connector;
166 protected $channel;
167
168 public static $storage = array();
169 protected static $loaded = array(
170 "attachIds" => array(),
171 "voteIds" => array(),
172 "entities" => array()
173 );
174
179 function init()
180 {
181 $attach = null;
182 $vote = null;
183 if (is_array($this->id))
184 {
186 }
187 else
188 {
189 $data = self::getData($this->id);
190 if (is_null($data))
191 {
192 throw new ObjectNotFoundException("Attach");
193 }
194 [$attach, $vote] = $data;
195 }
196 if (!is_array($attach) || empty($attach))
197 {
198 throw new ObjectNotFoundException("Wrong attach id!");
199 }
200
201 if (!array_key_exists("MODULE_ID", $attach) || $attach["MODULE_ID"] == '')
202 throw new ArgumentNullException("module ID");
203 if (!array_key_exists("ENTITY_TYPE", $attach) || $attach["ENTITY_TYPE"] == '')
204 throw new ArgumentNullException("entity type");
205 if (array_key_exists("ID", $attach))
206 $this->id = intval($attach["ID"]);
207 else
208 {
209 $this->id = null;
210 unset($attach["ID"]);
211 }
212
213 $this->attach = $attach;
214
215 if (is_array($vote))
216 {
217 $this->setVote($vote["ID"]);
218 $this->setStorage($this->vote["CHANNEL_ID"]);
219 }
220 }
221
225 public function setVote($vote)
226 {
227 if ($vote instanceof Vote)
228 $this->vote = $vote;
229 else
230 $this->vote = Vote::loadFromId($vote);
231 }
232
237 public function setStorage($id)
238 {
239 $this->channel = new Channel($id);
240 }
246 public static function getData($id)
247 {
248 $filter = array();
249
250 if (is_array($id))
251 {
252 $filter = array_change_key_case($id, CASE_UPPER);
253 $id = md5(serialize($filter));
254 }
255 else if (($id = intval($id)) && $id > 0)
256 $filter["ID"] = $id;
257 else
258 return null;
259
260 if (!array_key_exists($id, self::$storage))
261 {
262 self::$storage[$id] = null;
263 $dbRes = AttachTable::getList(array(
264 'select' => array(
265 'O_' => "*",
266 'V_' => 'VOTE.*',
267 'V_LAMP' => 'VOTE.LAMP',
268 'Q_' => 'VOTE.QUESTION.*',
269 'A_' => 'VOTE.QUESTION.ANSWER',
270 ),
271 'order' => array(
272 'VOTE.ID' => 'ASC',
273 'VOTE.QUESTION.C_SORT' => 'ASC',
274 'VOTE.QUESTION.ID' => 'ASC',
275 'VOTE.QUESTION.ANSWER.C_SORT' => 'ASC',
276 'VOTE.QUESTION.ANSWER.ID' => 'ASC',
277 ),
278 'filter' => $filter
279 ));
280 $attaches = [];
281 $images = [];
282 $attach = ["ID" => null];
283 $vote = ["ID" => null];
284 $question = ["ID" => null];
285
286 while (($res = $dbRes->fetch()) && $res)
287 {
288 $buffer = ["attach" => [], "vote" => [], "question" => []];
289 unset($answer);
290 $answer = [];
291 foreach ($res as $key => $val)
292 {
293 if (mb_strpos($key, "O_") === 0)
294 $buffer["attach"][mb_substr($key, 2)] = $val;
295 else if (mb_strpos($key, "V_") === 0)
296 $buffer["vote"][mb_substr($key, 2)] = $val;
297 else if (mb_strpos($key, "Q_") === 0)
298 $buffer["question"][mb_substr($key, 2)] = $val;
299 else if (mb_strpos($key, "A_") === 0)
300 $answer[mb_substr($key, 2)] = $val;
301 }
302 if ($buffer["attach"]["ID"] != $attach["ID"])
303 {
304 unset($attach);
305 $attach = $buffer["attach"];
306 $attaches[$attach["ID"]] = $attach;
307 }
308 if ($buffer["vote"]["ID"] != $vote["ID"])
309 {
310 unset($vote);
311 $vote = $buffer["vote"] + array(
312 "FIELD_NAME" => \Bitrix\Vote\Event::getExtrasFieldName($attach["ID"], "#ENTITY_ID#"),
313 "IMAGE" => null,
314 "QUESTIONS" => array());
315 if ($vote["IMAGE_ID"] > 0)
316 $images[$vote["IMAGE_ID"]] = &$vote["IMAGE"];
317 if (!array_key_exists($vote["ID"], Vote::$storage))
318 Vote::$storage[$vote["ID"]] = &$vote;
319 }
320 if ($buffer["question"]["ID"] != $question["ID"])
321 {
322 unset($question);
323 $question = $buffer["question"] + array(
324 "FIELD_NAME" => \Bitrix\Vote\Event::getFieldName($attach["ID"], $buffer["question"]["ID"]),
325 "IMAGE" => null,
326 "ANSWERS" => array()
327 );
328 if ($question["IMAGE_ID"] > 0)
329 $images[$question["IMAGE_ID"]] = &$question["IMAGE"];
330 if (!array_key_exists($question["ID"], Question::$storage))
331 Question::$storage[$question["ID"]] = &$question;
332 $vote["QUESTIONS"][$question["ID"]] = &$question;
333 }
334 $answer["FIELD_NAME"] = $answer["~FIELD_NAME"] = \Bitrix\Vote\Event::getFieldName($attach["ID"], $question["ID"]);
335 $answer["MESSAGE_FIELD_NAME"] = \Bitrix\Vote\Event::getMessageFieldName($attach["ID"], $question["ID"], $answer["ID"]);
336 if (
337 $answer["FIELD_TYPE"] == \Bitrix\Vote\AnswerTypes::TEXT ||
338 $answer["FIELD_TYPE"] == \Bitrix\Vote\AnswerTypes::TEXTAREA
339 )
340 {
341 if ($question["FIELD_TYPE"] == \Bitrix\Vote\QuestionTypes::COMPATIBILITY)
342 $answer["FIELD_NAME"] = $answer["MESSAGE_FIELD_NAME"];
343 }
344 else if ($question["FIELD_TYPE"] != \Bitrix\Vote\QuestionTypes::COMPATIBILITY)
345 {
346 $answer["FIELD_TYPE"] = $question["FIELD_TYPE"];
347 }
348 $answer["~PERCENT"] = ($question["COUNTER"] > 0 ? $answer["COUNTER"] * 100 / $question["COUNTER"] : 0);
349 $answer["PERCENT"] = round($answer["~PERCENT"], 2);
350 $question["ANSWERS"][$answer["ID"]] = &$answer;
351 Answer::$storage[$answer["ID"]] = &$answer;
352 unset($answer);
353 }
354 unset($vote); unset($question);
355 //region Getting images
356 if (count($images) > 0)
357 {
358 $dbRes = \Bitrix\Main\FileTable::getList(array('select' => array('*'), 'filter' => array('ID' => array_keys($images))));
359 while ($res = $dbRes->fetch())
360 {
361 $images[$res["ID"]] = $res + array("SRC" => \CFile::GetFileSRC($res));
362 }
363 }
364 //endregion
365 //region Setting data into local storages
366 foreach ($attaches as $attach)
367 {
368 self::$storage[$attach["ID"]] = array($attach, Vote::$storage[$attach["OBJECT_ID"]]);
369 if (is_string($id))
370 {
371 self::$storage[$id] = (is_array(self::$storage[$id]) ? self::$storage[$id] : array());
372 self::$storage[$id][$attach["ID"]] = array($attach, Vote::$storage[$attach["OBJECT_ID"]]);
373 }
374 }
375 //endregion
376 }
377 return self::$storage[$id];
378 }
379
385 public static function getDataByEntity(array $id)
386 {
387 $id1 = md5(serialize($id));
388 if (!array_key_exists($id1, self::$storage))
389 {
390 self::$storage[$id1] = array();
391
392 $dbRes = AttachTable::getList(array(
393 'select' => array(
394 'O_' => "*",
395 'V_' => 'VOTE.*',
396 'V_LAMP' => 'VOTE.LAMP',
397 'Q_' => 'VOTE.QUESTION.*',
398 'A_' => 'VOTE.QUESTION.ANSWER',
399 ),
400 'order' => array(
401 'VOTE.QUESTION.C_SORT' => 'ASC',
402 'VOTE.QUESTION.ID' => 'ASC',
403 'VOTE.QUESTION.ANSWER.C_SORT' => 'ASC',
404 'VOTE.QUESTION.ANSWER.ID' => 'ASC',
405 ),
406 'filter' => array(
407 'ENTITY_TYPE' => $id['ENTITY_TYPE'],
408 'ENTITY_ID' => $id['ENTITY_ID']
409 )
410 ));
411 if (($res = $dbRes->fetch()) && $res)
412 {
413 $attach = array();
414 $vote = array();
415 foreach ($res as $key => $val)
416 if (mb_strpos($key, "O_") === 0)
417 $attach[mb_substr($key, 2)] = $val;
418 else if (mb_strpos($key, "V_") === 0)
419 $vote[mb_substr($key, 2)] = $val;
420 $vote["QUESTIONS"] = array();
421 $questions = &$vote["QUESTIONS"];
422 do
423 {
424 $question = array(); $answer = array();
425 foreach ($res as $key => $val)
426 {
427 if (mb_strpos($key, "Q_") === 0)
428 $question[mb_substr($key, 2)] = $val;
429 else if (mb_strpos($key, "A_") === 0)
430 $answer[mb_substr($key, 2)] = $val;
431 }
432 $qid = "".$question["ID"];
433 if (!array_key_exists($qid, $questions))
434 $questions[$qid] = array_merge($question, array("ANSWERS" => array()));
435 if (!array_key_exists($qid, Question::$storage))
436 Question::$storage[$qid] = $question;
437 $answers = &$questions[$qid]["ANSWERS"];
438 if (!empty($answer))
439 {
440 if (!array_key_exists($answer["ID"], $answers))
441 $answers[$answer["ID"]] = $answer;
442 if (!array_key_exists($answer["ID"], Answer::$storage))
443 Answer::$storage[$answer["ID"]] = $answer;
444 }
445
446 } while (($res = $dbRes->fetch()) && $res);
447 Vote::$storage[$vote["ID"]] = $vote;
448 self::$storage[$id1] = array($attach, $vote);
449 }
450 }
451 return self::$storage[$id1];
452 }
453
460 public function canRead($userId)
461 {
462 return $this->getConnector()->canRead($userId);
463 }
464
470 public function canParticipate($userId)
471 {
472 return $this->getConnector()->canRead($userId) && is_object($this->vote) && $this->vote["LAMP"] == "green";
473 }
474
475 public function canVote($userId)
476 {
477 return $this->vote->canVote($userId);
478 }
479
480 public function canRevote($userId)
481 {
482 return $this->vote->canRevote($userId);
483 }
484
485 public function canReadResult($userId)
486 {
487 return $this->vote->canReadResult($userId);
488 }
495 public function canEdit($userId)
496 {
497 return $this->getConnector()->canEdit($userId);
498 }
499
506 public function getConnector()
507 {
508 if ($this->connector === null)
509 {
510 $this->connector = Connector::buildFromAttachedObject($this);
511 }
512 return $this->connector;
513 }
514
518 public function getStorage()
519 {
520 if (!($this->channel instanceof Channel))
521 {
522 $this->setStorage($this->vote instanceof Vote ? $this->vote["CHANNEL_ID"] : null);
523 }
524 return $this->channel;
525 }
530 public function getAttachId()
531 {
532 return array_key_exists("ID", $this->attach) ? $this->attach["ID"] : null;
533 }
538 public function getVoteId()
539 {
540 return is_object($this->vote) ? $this->vote["ID"] : null;
541 }
546 public function getModuleId()
547 {
548 return $this->attach["MODULE_ID"];
549 }
554 public function getEntityType()
555 {
556 return $this->attach["ENTITY_TYPE"];
557 }
562 public function getEntityId()
563 {
564 return $this->attach["ENTITY_ID"];
565 }
566
570 public function fillStatistic()
571 {
572 if (is_object($this->vote))
573 $this->vote->fillStatistic();
574 }
575
580 public function delete()
581 {
582 if (empty($this->vote))
583 return true;
584
585 if ($this->attach["ID"] > 0)
586 AttachTable::delete($this->attach["ID"]);
587
588 $othersAttaches = AttachTable::getList(array(
589 "select" => array("ID", "OBJECT_ID"),
590 "filter" => array("OBJECT_ID" => $this->vote["ID"]),
591 'order' => array(
592 'ID' => 'ASC'
593 )
594 ))->fetch();
595
596 if (empty($othersAttaches) && ($channel = $this->getStorage()) && $channel["HIDDEN"] == "Y")
597 Vote::delete($this->vote["ID"]);
598
599 return true;
600 }
601
623 public function checkData(array &$data)
624 {
625 $channel = $this->getStorage();
626 if ($channel["ACTIVE"] !== "Y")
627 throw new AccessDeniedException(Loc::getMessage("VOTE_CHANNEL_IS_NOT_ACTIVE"));
628 $data = array_merge($data, (is_null($this->vote) ? [
629 "ACTIVE" => "Y",
630 "DATE_START" => new DateTime(),
631 ] : []), [
632 "CHANNEL_ID" => $channel["ID"],
633 "DATE_END" => (isset($data["DATE_END"]) ? new DateTime($data["DATE_END"]) : (new DateTime())->add("1Y"))
634 ]);
635 $this->getConnector()->checkFields($data);
636 Vote::checkData($data, $data["ID"]);
637 if (($data["TITLE"] ?? null) == '' && is_array($data["QUESTIONS"]))
638 {
639 $q = reset($data["QUESTIONS"]);
640 if (is_array($q) && $q["QUESTION"] <> '')
641 {
642 $data["TITLE"] = $q["QUESTION"];
643 }
644 }
645 }
646
668 public function save($data, $createdBy = 0)
669 {
670 if (!isset($data["AUTHOR_ID"]))
671 $data["AUTHOR_ID"] = $createdBy;
672
673 $this->checkData($data);
674
675 $voteId = Vote::saveData(is_null($this->vote) ? 0 : $this->vote["ID"], $data);
676 if ($voteId > 0)
677 {
678 if (!array_key_exists("ID", $this->attach))
679 {
680 $id = AttachTable::add(array(
681 'MODULE_ID' => $this->getModuleId(),
682 'OBJECT_ID' => $voteId,
683 'ENTITY_ID' => $this->getEntityId(),
684 'ENTITY_TYPE' => $this->getEntityType(),
685 'CREATED_BY' => $createdBy,
686 'CREATE_TIME' => new DateTime()
687 ))->getId();
688 }
689 else
690 {
691 $id = $this->attach["ID"];
692 }
693 [$attach, $vote] = \Bitrix\Vote\Attach::getData($id);
694 $this->attach = $attach;
695 $this->vote = $vote;
696 }
697 else if ($this->attach["ID"] ?? null > 0)
698 {
699 $this->attach = null;
700 $this->vote = null;
701 }
702 return true;
703 }
704
716 public function voteFor(array $request)
717 {
718 if (!is_object($this->vote))
719 throw new InvalidOperationException("Poll is not found.");
720 $res = \Bitrix\Vote\Event::getDataFromRequest($this->getAttachId(), $request);
721 if (empty($res)) // for custom templates
722 $result = $this->vote->voteFor($request, ["revote" => true]);
723 else
724 $result = $this->vote->registerEvent($res, ["revote" => true], User::getCurrent());
725 if (!$result)
726 $this->errorCollection->add($this->vote->getErrors());
727 return $result;
728 }
734 public function exportExcel()
735 {
736 if (!is_object($this->vote))
737 throw new InvalidOperationException("Poll is not found.");
738 $this->vote->exportExcel();
739 }
745 public function isVotedFor($userId)
746 {
747 if ($this->vote)
748 return $this->vote->isVotedFor($userId);
749 return false;
750 }
751
757 public function resume()
758 {
759 if (!is_object($this->vote))
760 throw new InvalidOperationException("Poll is not found.");
761 return $this->vote->resume();
762 }
763
769 public function stop()
770 {
771 if (!is_object($this->vote))
772 throw new InvalidOperationException("Poll is not found.");
773 return $this->vote->stop();
774 }
775
780 public function offsetExists($offset)
781 {
782 if (is_array($this->attach) && array_key_exists($offset, $this->attach) || is_object($this->vote) && isset($this->vote[$offset]))
783 return true;
784 if ($offset == "VOTE_ID" && is_object($this->vote))
785 return true;
786 return false;
787 }
788
793 public function offsetGet($offset)
794 {
795 if (is_array($this->attach) && array_key_exists($offset, $this->attach))
796 return $this->attach[$offset];
797 if (is_object($this->vote))
798 {
799 if (isset($this->vote[$offset]))
800 return $this->vote[$offset];
801 if ($offset == "VOTE_ID")
802 return $this->vote["ID"];
803 }
804 return null;
805 }
806
814 public function offsetSet($offset, $value)
815 {
816 throw new NotSupportedException('Model provide ArrayAccess only for reading');
817 }
818
825 public function offsetUnset($offset)
826 {
827 throw new NotSupportedException('Model provide ArrayAccess only for reading');
828 }
834 public static function loadFromId($id, $shouldBeNewIfIdIsNull = false)
835 {
836 return parent::loadFromId($id, true);
837 }
838}
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
canEdit($userId)
Definition attach.php:495
offsetUnset($offset)
Definition attach.php:825
offsetExists($offset)
Definition attach.php:780
save($data, $createdBy=0)
Definition attach.php:668
offsetGet($offset)
Definition attach.php:793
isVotedFor($userId)
Definition attach.php:745
static getData($id)
Definition attach.php:246
static getDataByEntity(array $id)
Definition attach.php:385
checkData(array &$data)
Definition attach.php:623
canRead($userId)
Definition attach.php:460
canRevote($userId)
Definition attach.php:480
offsetSet($offset, $value)
Definition attach.php:814
canReadResult($userId)
Definition attach.php:485
voteFor(array $request)
Definition attach.php:716
canVote($userId)
Definition attach.php:475
canParticipate($userId)
Definition attach.php:470
static loadFromId($id, $shouldBeNewIfIdIsNull=false)
Definition attach.php:834
static deleteByFilter(array $filter)
Definition attach.php:131
static getList(array $parameters=array())
Definition attach.php:120
static loadFromId($id, $shouldBeNewIfIdIsNull=false)
static getExtrasFieldName($id, $name)
Definition event.php:530
static getFieldName($id, $questionId)
Definition event.php:522
static getCurrent()
Definition user.php:312