Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
forum.php
1<?php
2namespace Bitrix\Forum;
3
8use Bitrix\Main\Entity\ReferenceField;
9use \Bitrix\Main\Localization\Loc;
19
20Loc::loadMessages(__FILE__);
21
95class ForumTable extends \Bitrix\Main\Entity\DataManager
96{
97 private static $topicSort = array(
98 "P" => "LAST_POST_DATE",
99 "T" => "TITLE",
100 "N" => "POSTS",
101 "V" => "VIEWS",
102 "D" => "START_DATE",
103 "A" => "USER_START_NAME"
104 );
105 private static $cache = [];
106
112 public static function getTableName()
113 {
114 return 'b_forum';
115 }
116
122 public static function getMap()
123 {
124 return [
125 (new IntegerField("ID", ["primary" => true, "autocomplete" => true])),
126 (new IntegerField("FORUM_GROUP_ID")),
127 (new StringField("NAME", ["required" => true, "size" => 255])),
128 (new TextField("DESCRIPTION")),
129 (new IntegerField("SORT", ["default_value" => 150])),
130 (new BooleanField("ACTIVE", ["values" => ["N", "Y"], "default_value" => "Y"])),
131 (new BooleanField("ALLOW_HTML", ["values" => ["N", "Y"], "default_value" => "N"])),
132 (new BooleanField("ALLOW_ANCHOR", ["values" => ["N", "Y"], "default_value" => "Y"])),
133 (new BooleanField("ALLOW_BIU", ["values" => ["N", "Y"], "default_value" => "Y"])),
134 (new BooleanField("ALLOW_IMG", ["values" => ["N", "Y"], "default_value" => "Y"])),
135 (new BooleanField("ALLOW_VIDEO", ["values" => ["N", "Y"], "default_value" => "Y"])),
136 (new BooleanField("ALLOW_LIST", ["values" => ["N", "Y"], "default_value" => "Y"])),
137 (new BooleanField("ALLOW_QUOTE", ["values" => ["N", "Y"], "default_value" => "Y"])),
138 (new BooleanField("ALLOW_CODE", ["values" => ["N", "Y"], "default_value" => "Y"])),
139 (new BooleanField("ALLOW_FONT", ["values" => ["N", "Y"], "default_value" => "Y"])),
140 (new BooleanField("ALLOW_SMILES", ["values" => ["N", "Y"], "default_value" => "Y"])),
141 (new BooleanField("ALLOW_TABLE", ["values" => ["N", "Y"], "default_value" => "Y"])),
142 (new BooleanField("ALLOW_ALIGN", ["values" => ["N", "Y"], "default_value" => "Y"])),
143 (new BooleanField("ALLOW_NL2BR", ["values" => ["N", "Y"], "default_value" => "Y"])),
144
145 (new EnumField("ALLOW_UPLOAD", ["values" => ["Y", "F", "A"], "default_value" => "F"])),
146 (new StringField("ALLOW_UPLOAD_EXT", ["size" => 255])),
147
148 (new BooleanField("ALLOW_MOVE_TOPIC", ["values" => ["N", "Y"], "default_value" => "Y"])),
149 (new BooleanField("ALLOW_TOPIC_TITLED", ["values" => ["N", "Y"], "default_value" => "Y"])),
150
151 (new BooleanField("ALLOW_SIGNATURE", ["values" => ["N", "Y"], "default_value" => "Y"])),
152 (new BooleanField("ASK_GUEST_EMAIL", ["values" => ["N", "Y"], "default_value" => "N"])),
153 (new BooleanField("USE_CAPTCHA", ["values" => ["N", "Y"], "default_value" => "Y"])),
154
155 (new BooleanField("INDEXATION", ["values" => ["N", "Y"], "default_value" => "Y"])),
156 (new BooleanField("DEDUPLICATION", ["values" => ["N", "Y"], "default_value" => "N"])),
157 (new BooleanField("MODERATION", ["values" => ["N", "Y"], "default_value" => "N"])),
158 (new EnumField("ORDER_BY", ["values" => self::$topicSort, "default_value" => "P"])),
159 (new EnumField("ORDER_DIRECTION", ["values" => ["ASC", "DESC"], "default_value" => "DESC"])),
160
161 (new IntegerField("TOPICS")),
162 (new IntegerField("POSTS")),
163 (new IntegerField("POSTS_UNAPPROVED")),
164
165 (new IntegerField("LAST_POSTER_ID")),
166 (new StringField("LAST_POSTER_NAME", ["size" => 255])),
167 (new DatetimeField("LAST_POST_DATE", ["default_value" => function(){return new DateTime();}])),
168 (new IntegerField("LAST_MESSAGE_ID")),
169
170 (new IntegerField("ABS_LAST_POSTER_ID")),
171 (new StringField("ABS_LAST_POSTER_NAME", ["size" => 255])),
172 (new DatetimeField("ABS_LAST_POST_DATE", ["default_value" => function(){return new DateTime();}])),
173 (new IntegerField("ABS_LAST_MESSAGE_ID")),
174
175 (new StringField("EVENT1")),
176 (new StringField("EVENT2")),
177 (new StringField("EVENT3")),
178 (new StringField("XML_ID", ["size" => 255])),
179 (new StringField("HTML", ["size" => 255])),
180
181 (new Reference("PERMISSION", \Bitrix\Forum\PermissionTable::class, Join::on("this.ID", "ref.FORUM_ID"))),
182 (new Reference("SITE", \Bitrix\Forum\ForumSiteTable::class, Join::on("this.ID", "ref.FORUM_ID"))),
183 (new Reference("GROUP", \Bitrix\Forum\GroupTable::class, Join::on("this.FORUM_GROUP_ID", "ref.ID")))
184 ];
185 }
186
187 private static function getFilteredFields()
188 {
189 return [
190 "LAST_POSTER_NAME"
191 ];
192 }
193 /*
194 * Returns main data
195 * @return array|null
196 */
197 public static function getMainData(int $forumId, ?string $siteId = null): ?array
198 {
199 $cacheKey = implode('_', ([$forumId] + ($siteId === null ? [] : [$siteId])));
200 if (!array_key_exists($cacheKey, self::$cache))
201 {
202 $q = ForumTable::query()
203 ->setSelect([
204 'ID', 'FORUM_GROUP_ID', 'NAME', 'DESCRIPTION', 'SORT', 'ACTIVE',
205 'ALLOW_HTML', 'ALLOW_ANCHOR', 'ALLOW_BIU', 'ALLOW_IMG', 'ALLOW_VIDEO',
206 'ALLOW_LIST', 'ALLOW_QUOTE', 'ALLOW_CODE', 'ALLOW_FONT', 'ALLOW_SMILES',
207 'ALLOW_TABLE', 'ALLOW_ALIGN', 'ALLOW_UPLOAD', 'ALLOW_UPLOAD_EXT',
208 'ALLOW_MOVE_TOPIC', 'ALLOW_TOPIC_TITLED', 'ALLOW_NL2BR', 'ALLOW_SIGNATURE',
209 'ASK_GUEST_EMAIL', 'USE_CAPTCHA' ,'INDEXATION', 'DEDUPLICATION',
210 'MODERATION', 'ORDER_BY', 'ORDER_DIRECTION',
211 'EVENT1', 'EVENT2', 'EVENT3', 'XML_ID'])
212 ->where('ID', $forumId)
213 ->setCacheTtl(84600);
214 if ($siteId !== null)
215 {
216 $q->registerRuntimeField(
217 '',
218 new ReferenceField('SITE',
219 ForumSiteTable::getEntity(),
220 [
221 '=ref.FORUM_ID' => 'this.ID',
222 '=ref.SITE_ID' => new SqlExpression('?s', $siteId)
223 ]
224 )
225 )
226 ->addSelect('SITE.PATH2FORUM_MESSAGE', 'PATH2FORUM_MESSAGE');
227 }
228 self::$cache[$cacheKey] = $q->fetch() ?: null;
229 }
230 self::bindOldKernelEvents();
231 return self::$cache[$cacheKey];
232 }
233
234 public static function updateSilently($id, $fields)
235 {
236 $connection = Main\Application::getConnection();
237 $helper = $connection->getSqlHelper();
238 $update = $helper->prepareUpdate(self::getTableName(), $fields);
239 $where = $helper->prepareAssignment(self::getTableName(), 'ID', $id);
240 $sql = 'UPDATE '.$helper->quote(self::getTableName()).' SET '.$update[0].' WHERE '.$where;
241 return $connection->query($sql, $update[1]);
242 }
243
244 public static function onBeforeUpdate(\Bitrix\Main\ORM\Event $event)
245 {
246 $result = new \Bitrix\Main\ORM\EventResult();
248 $data = $event->getParameter("fields");
249 $id = $event->getParameter("id");
250 $id = $id["ID"];
251 $forum = self::getById($id)->fetch();
252
253 if (\Bitrix\Main\Config\Option::get("forum", "FILTER", "Y") == "Y")
254 {
255 $filteredFields = self::getFilteredFields();
256 if (!empty(array_intersect($filteredFields, array_keys($data))))
257 {
258 $res = [];
259 foreach ($filteredFields as $key)
260 {
261 $res[$key] = $val = array_key_exists($key, $data) ? $data[$key] : $forum[$key];
262 if (!empty($val))
263 {
264 $res[$key] = \CFilterUnquotableWords::Filter($val);
265 if (empty($res[$key]))
266 {
267 $res[$key] = "*";
268 }
269 }
270 }
271 $data["HTML"] = serialize($res);
272 }
273 }
274
275 if ($data != $event->getParameter("fields"))
276 {
277 $result->modifyFields($data);
278 }
279 return $result;
280 }
281
282 public static function onAfterAdd(\Bitrix\Main\ORM\Event $event)
283 {
284 self::$cache = [];
285 return new Entity\EventResult();
286 }
287
288 public static function onAfterUpdate(\Bitrix\Main\ORM\Event $event)
289 {
290 self::$cache = [];
291 return new Entity\EventResult();
292 }
293
294 public static function onAfterDelete(\Bitrix\Main\ORM\Event $event)
295 {
296 self::$cache = [];
297 return new Entity\EventResult();
298 }
299
300 public static function clearCache() // TODO redesign old forum new to D7
301 {
302 self::$cache = [];
303 self::getEntity()->cleanCache();
304 }
305
306 private static function bindOldKernelEvents() // TODO redesign old forum new to D7 and delete this function
307 {
308 static $bound = false;
309 if ($bound === true)
310 {
311 return;
312 }
313 $eventManager = \Bitrix\Main\EventManager::getInstance();
314 $eventManager->addEventHandler("forum", "onAfterForumAdd", [__CLASS__, "clearCache"]);
315 $eventManager->addEventHandler("forum", "onAfterForumUpdate", [__CLASS__, "clearCache"]);
316 $eventManager->addEventHandler("forum", "OnAfterForumDelete", [__CLASS__, "clearCache"]);
317 $bound = true;
318 }
319}
320
321class Forum implements \ArrayAccess {
322 use \Bitrix\Forum\Internals\EntityFabric;
323 use \Bitrix\Forum\Internals\EntityBaseMethods;
324
326 protected $id = 0;
328 protected $data = [];
330 protected $strore = [];
331
332 public function __construct($id)
333 {
334 $this->id = $id;
335 if ($id <= 0)
336 {
337 throw new \Bitrix\Main\ArgumentNullException("Forum id is null.");
338 }
339 $this->data = ForumTable::getMainData($this->id);
340 if (empty($this->data))
341 {
342 throw new \Bitrix\Main\ObjectNotFoundException("Forum with id {$this->id} is not found.");
343 }
344 $this->bindEvents();
345 $this->errorCollection = new \Bitrix\Main\ErrorCollection();
346 }
347
348 private function bindEvents()
349 {
350 $eventManager = \Bitrix\Main\EventManager::getInstance();
351 $eventManager->addEventHandler("forum", "onAfterPermissionSet", [$this, "clearCache"]);
352 $eventManager->addEventHandler("forum", "onAfterUserUpdate", [$this, "clearCache"]);
353 }
354
355 public function clearCache()
356 {
357 $this->strore = [];
358 }
359
360 public function getPermissions()
361 {
362 if (!array_key_exists("permission_for_all", $this->strore))
363 {
364 $dbRes = PermissionTable::getList([
365 "select" => ["GROUP_ID", "PERMISSION"],
366 "filter" => ["FORUM_ID" => $this->id],
367 "cache" => ["ttl" => 84600]
368 ]);
369 $this->strore["permission_for_all"] = [];
370 while ($res = $dbRes->fetch())
371 {
372 $this->strore["permission_for_all"][$res["GROUP_ID"]] = $res["PERMISSION"];
373 }
374 }
375 return $this->strore["permission_for_all"];
376 }
377
378 private function getPermissionFromUserGroups(array $groups)
379 {
380 sort($groups);
381 $key = "permission_".implode("_", $groups);
382 if (!array_key_exists($key, $this->strore))
383 {
384 $this->strore[$key] =
385 $dbRes = PermissionTable::getList([
386 "select" => ["MAX_PERMISSION"],
387 "runtime" => [
388 new \Bitrix\Main\Entity\ExpressionField("MAX_PERMISSION", "MAX(%s)", ["PERMISSION"])
389 ],
390 "filter" => [
391 "FORUM_ID" => $this->id,
392 "GROUP_ID" => $groups + [2]
393 ],
394 "group" => "FORUM_ID",
395 "cache" => ["ttl" => "3600"]
396 ]);
397 $this->strore[$key] = ($res = $dbRes->fetch()) ? $res["MAX_PERMISSION"] : Permission::ACCESS_DENIED;
398 }
399 return $this->strore[$key];
400 }
401
402 public function getPermissionForUser(\Bitrix\Forum\User $user)
403 {
404 if ($user->isAdmin())
405 {
406 $result = Permission::FULL_ACCESS;
407 }
408 elseif ($this->data["ACTIVE"] != "Y")
409 {
411 }
412 else
413 {
414 $result = $this->getPermissionFromUserGroups($user->getGroups());
415 }
416 return $result;
417 }
418
419 public function getPermissionForUserGroups(array $groups)
420 {
421 if (\Bitrix\Forum\User::isUserAdmin($groups))
422 {
423 $result = Permission::FULL_ACCESS;
424 }
425 elseif ($this->data["ACTIVE"] != "Y")
426 {
428 }
429 else
430 {
431 $result = $this->getPermissionFromUserGroups($groups);
432 }
433 return $result;
434 }
435
436 public function setPermission(array $groups)
437 {
438 $dbRes = PermissionTable::getList([
439 "select" => ["ID"],
440 "filter" => [
441 "FORUM_ID" => $this->id
442 ]
443 ]);
444 while ($res = $dbRes->fetch())
445 {
446 PermissionTable::delete($res["ID"]);
447 }
448 foreach ($groups as $key => $val)
449 {
450 PermissionTable::add([
451 "FORUM_ID" => $this->id,
452 "GROUP_ID" => $key,
453 "PERMISSION" => mb_strtoupper($val)
454 ]);
455 }
456 foreach (GetModuleEvents("forum", "onAfterPermissionSet", true) as $arEvent)
457 {
458 ExecuteModuleEventEx($arEvent, array($this->id, $groups));
459 }
460 return true;
461 }
462
463 public function getSites()
464 {
465 if (!array_key_exists("sites", $this->strore))
466 {
467 $dbRes = ForumSiteTable::getList([
468 "select" => ["*"],
469 "filter" => ["FORUM_ID" => $this->id],
470 "cache" => ["ttl" => 84600]
471 ]);
472 $this->strore["sites"] = [];
473 while ($res = $dbRes->fetch())
474 {
475 $this->strore["sites"][$res["SITE_ID"]] = $res["PATH2FORUM_MESSAGE"];
476 }
477 }
478 return $this->strore["sites"];
479 }
480
481 public function calculateStatistic()
482 {
483 $forumId = (int) $this->getId();
484 $sql = <<<SQL
485UPDATE
486 b_forum f,
487 (SELECT ID, AUTHOR_ID, AUTHOR_NAME, POST_DATE, FORUM_ID FROM b_forum_message WHERE FORUM_ID={$forumId} AND APPROVED='Y' ORDER BY ID DESC LIMIT 1) AS last_message,
488 (SELECT ID, AUTHOR_ID, AUTHOR_NAME, POST_DATE, FORUM_ID FROM b_forum_message WHERE FORUM_ID={$forumId} ORDER BY ID DESC LIMIT 1) AS abs_last_message
489set
490 f.TOPICS = (SELECT COUNT(ID) FROM b_forum_topic WHERE FORUM_ID={$forumId} AND APPROVED='Y' GROUP BY FORUM_ID),
491 f.POSTS = (SELECT COUNT(ID) FROM b_forum_message WHERE FORUM_ID={$forumId} AND APPROVED='Y' GROUP BY FORUM_ID),
492 f.POSTS_UNAPPROVED = (SELECT COUNT(ID) FROM b_forum_message WHERE FORUM_ID={$forumId} AND APPROVED != 'Y' GROUP BY FORUM_ID),
493 f.LAST_MESSAGE_ID = last_message.ID,
494 f.LAST_POSTER_ID = last_message.AUTHOR_ID,
495 f.LAST_POSTER_NAME = last_message.AUTHOR_NAME,
496 f.LAST_POST_DATE = last_message.POST_DATE,
497 f.ABS_LAST_MESSAGE_ID = abs_last_message.ID,
498 f.ABS_LAST_POSTER_ID = abs_last_message.AUTHOR_ID,
499 f.ABS_LAST_POSTER_NAME = abs_last_message.AUTHOR_NAME,
500 f.ABS_LAST_POST_DATE = abs_last_message.POST_DATE
501WHERE f.ID = {$forumId} AND last_message.FORUM_ID = f.ID AND abs_last_message.FORUM_ID = f.ID
502SQL;
503 Main\Application::getConnection()->queryExecute($sql);
504 }
505
506 public function incrementStatistic(array $message)
507 {
508 $fields = [
509 "ABS_LAST_POSTER_ID" => $message["AUTHOR_ID"],
510 "ABS_LAST_POSTER_NAME" => $message["AUTHOR_NAME"],
511 "ABS_LAST_POST_DATE" => $message["POST_DATE"],
512 "ABS_LAST_MESSAGE_ID" => $message["ID"]
513 ];
514 if ($message["APPROVED"] == "Y")
515 {
516 $fields += [
517 "LAST_POSTER_ID" => $message["AUTHOR_ID"],
518 "LAST_POSTER_NAME" => $message["AUTHOR_NAME"],
519 "LAST_POST_DATE" => $message["POST_DATE"],
520 "LAST_MESSAGE_ID" => $message["ID"]
521 ];
522 $fields["POSTS"] = new \Bitrix\Main\DB\SqlExpression('?# + 1', "POSTS");
523 if ($message["NEW_TOPIC"] == "Y")
524 {
525 $fields["TOPICS"] = new \Bitrix\Main\DB\SqlExpression('?# + 1', "TOPICS");
526 }
527 }
528 else
529 {
530 $fields["POSTS_UNAPPROVED"] = new \Bitrix\Main\DB\SqlExpression('?# + 1', "POSTS_UNAPPROVED");
531 }
532
533 ForumTable::updateSilently($this->getId(), $fields);
534
535 if (\CModule::IncludeModule("statistic"))
536 {
537 $F_EVENT1 = $this->data["EVENT1"];
538 $F_EVENT2 = $this->data["EVENT2"];
539 $F_EVENT3 = $this->data["EVENT3"];
540 if (empty($F_EVENT3))
541 {
542 $F_EVENT3 = $_SERVER["HTTP_REFERER"] ?? '';
543 }
544 \CStatistics::Set_Event($F_EVENT1, $F_EVENT2, $F_EVENT3);
545 }
546 }
547
548 public function decrementStatistic(array $message)
549 {
550 $forumId = (int) $this->getId();
551 if ($message['APPROVED'] == 'Y')
552 {
553 $subQueryTopics = "";
554 if ($message['NEW_TOPIC'] === 'Y')
555 {
556 $subQueryTopics = <<<SQL
557 f.TOPICS = (SELECT COUNT(ID) FROM b_forum_topic WHERE FORUM_ID={$forumId} AND APPROVED='Y' GROUP BY FORUM_ID),
558SQL;
559 }
560 $sql = <<<SQL
561UPDATE
562 b_forum f,
563 (SELECT ID, AUTHOR_ID, AUTHOR_NAME, POST_DATE, FORUM_ID FROM b_forum_message WHERE FORUM_ID={$forumId} AND APPROVED='Y' ORDER BY ID DESC LIMIT 1) AS last_message,
564 (SELECT ID, AUTHOR_ID, AUTHOR_NAME, POST_DATE, FORUM_ID FROM b_forum_message WHERE FORUM_ID={$forumId} ORDER BY ID DESC LIMIT 1) AS abs_last_message
565set
566 {$subQueryTopics}
567 f.POSTS = f.POSTS - 1,
568 f.LAST_MESSAGE_ID = last_message.ID,
569 f.LAST_POSTER_ID = last_message.AUTHOR_ID,
570 f.LAST_POSTER_NAME = last_message.AUTHOR_NAME,
571 f.LAST_POST_DATE = last_message.POST_DATE,
572 f.ABS_LAST_MESSAGE_ID = abs_last_message.ID,
573 f.ABS_LAST_POSTER_ID = abs_last_message.AUTHOR_ID,
574 f.ABS_LAST_POSTER_NAME = abs_last_message.AUTHOR_NAME,
575 f.ABS_LAST_POST_DATE = abs_last_message.POST_DATE,
576 f.HTML = ''
577WHERE f.ID = {$forumId} AND last_message.FORUM_ID = f.ID AND abs_last_message.FORUM_ID = f.ID
578SQL;
579 }
580 else
581 {
582 $sql = <<<SQL
583UPDATE
584 b_forum f,
585 (SELECT ID, AUTHOR_ID, AUTHOR_NAME, POST_DATE, FORUM_ID FROM b_forum_message WHERE FORUM_ID={$forumId} ORDER BY ID DESC LIMIT 1) AS abs_last_message
586set
587 f.POSTS_UNAPPROVED = f.POSTS_UNAPPROVED - 1,
588 f.ABS_LAST_MESSAGE_ID = abs_last_message.ID,
589 f.ABS_LAST_POSTER_ID = abs_last_message.AUTHOR_ID,
590 f.ABS_LAST_POSTER_NAME = abs_last_message.AUTHOR_NAME,
591 f.ABS_LAST_POST_DATE = abs_last_message.POST_DATE,
592 f.HTML = ''
593WHERE f.ID = {$forumId} AND abs_last_message.FORUM_ID = f.ID
594SQL;
595 }
596
597 Main\Application::getConnection()->queryExecute($sql);
598 }
599}
incrementStatistic(array $message)
Definition forum.php:506
decrementStatistic(array $message)
Definition forum.php:548
getPermissionForUserGroups(array $groups)
Definition forum.php:419
getPermissionForUser(\Bitrix\Forum\User $user)
Definition forum.php:402
setPermission(array $groups)
Definition forum.php:436
static onAfterAdd(\Bitrix\Main\ORM\Event $event)
Definition forum.php:282
static updateSilently($id, $fields)
Definition forum.php:234
static onAfterDelete(\Bitrix\Main\ORM\Event $event)
Definition forum.php:294
static onAfterUpdate(\Bitrix\Main\ORM\Event $event)
Definition forum.php:288
static getMainData(int $forumId, ?string $siteId=null)
Definition forum.php:197
static isUserAdmin(array $groups)
Definition user.php:964
static loadMessages($file)
Definition loc.php:64