1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
placement.php
См. документацию.
1<?php
2namespace Bitrix\Rest\Api;
3
4
5use Bitrix\Main\Application;
6use Bitrix\Main\ArgumentException;
7use Bitrix\Main\ArgumentNullException;
8use Bitrix\Main\Entity\ExpressionField;
9use Bitrix\Main\Error;
10use Bitrix\Main\Loader;
11use Bitrix\Main\Result;
12use Bitrix\Rest\AccessException;
13use Bitrix\Rest\AppTable;
14use Bitrix\Rest\AuthTypeException;
15use Bitrix\Rest\HandlerHelper;
16use Bitrix\Rest\OAuth\Auth;
17use Bitrix\Rest\PlacementLangTable;
18use Bitrix\Rest\PlacementTable;
19use Bitrix\Rest\RestException;
20use Bitrix\Rest\Exceptions;
21use Bitrix\Rest\Lang;
22use Bitrix\Main\ArgumentTypeException;
23
25{
26 const SCOPE_PLACEMENT = 'placement';
27
28 public static function onRestServiceBuildDescription()
29 {
30 return array(
31 static::SCOPE_PLACEMENT => array(
32 'placement.list' => array(
33 'callback' => array(__CLASS__, 'getList'),
34 'options' => array()
35 ),
36 'placement.bind' => array(
37 'callback' => array(__CLASS__, 'bind'),
38 'options' => array()
39 ),
40 'placement.unbind' => array(
41 'callback' => array(__CLASS__, 'unbind'),
42 'options' => array()
43 ),
44 'placement.get' => array(
45 'callback' => array(__CLASS__, 'get'),
46 'options' => array()
47 )
48 ),
49 );
50 }
51
52
53 public static function getList($query, $n, \CRestServer $server)
54 {
55 if($server->getAuthType() !== Auth::AUTH_TYPE)
56 {
57 throw new AuthTypeException("Application context required");
58 }
59
60 $result = array();
61
62 $serviceDescription = $server->getServiceDescription();
63
64 $scopeList = array(\CRestUtil::GLOBAL_SCOPE);
65
66 $query = array_change_key_case($query, CASE_UPPER);
67
68 if(isset($query['SCOPE']))
69 {
70 if($query['SCOPE'] != '')
71 {
72 $scopeList = array($query['SCOPE']);
73 }
74 }
75 elseif($query['FULL'] == true)
76 {
77 $scopeList = array_keys($serviceDescription);
78 }
79 else
80 {
81 $scopeList = static::getScope($server);
82 $scopeList[] = \CRestUtil::GLOBAL_SCOPE;
83 }
84
85 $placementList = static::getPlacementList($server, $scopeList);
86
87 foreach($placementList as $placement => $placementInfo)
88 {
89 if(!$placementInfo['private'])
90 {
91 $result[] = $placement;
92 }
93 }
94
95 return $result;
96 }
97
98 public static function bind($params, $n, \CRestServer $server)
99 {
100 static::checkPermission($server);
101
102 $params = array_change_key_case($params, CASE_UPPER);
103
104 if(!is_string($params['PLACEMENT']))
105 {
106 throw new Exceptions\ArgumentTypeException('PLACEMENT', 'string');
107 }
108
109 $placement = mb_strtoupper($params['PLACEMENT']);
110 $placementHandler = $params['HANDLER'];
111
112 if($placement == '')
113 {
114 throw new Exceptions\ArgumentNullException("PLACEMENT");
115 }
116
117 if($placement == PlacementTable::PLACEMENT_DEFAULT)
118 {
119 throw new Exceptions\ArgumentNullException("Wrong value", "PLACEMENT");
120 }
121
122 if($placementHandler == '')
123 {
124 throw new Exceptions\ArgumentNullException("HANDLER");
125 }
126
127 $appInfo = static::getApplicationInfo($server);
128 HandlerHelper::checkCallback($placementHandler, $appInfo);
129
130 $scopeList = static::getScope($server);
131 $scopeList[] = \CRestUtil::GLOBAL_SCOPE;
132
133 $placementList = static::getPlacementList($server, $scopeList);
134 $placementInfo = $placementList[$placement];
135
136 if (is_array($placementInfo) && (!isset($placementInfo['private']) || !$placementInfo['private']))
137 {
138 $placementLangList = [];
139 $paramsOptions = $params['OPTIONS'] ?? [];
140 $placementInfoOptions = $placementInfo['options'] ?? [];
141
142 $placementBind = array(
143 'APP_ID' => $appInfo['ID'],
144 'USER_ID' => (isset($params['USER_ID']) && (int)$params['USER_ID'] > 0) ? (int)$params['USER_ID'] : PlacementTable::DEFAULT_USER_ID_VALUE,
145 'PLACEMENT' => $placement,
146 'PLACEMENT_HANDLER' => $placementHandler,
147 'OPTIONS' => static::prepareOptions($paramsOptions, $placementInfoOptions),
148 );
149
150 if (
151 $placementBind['USER_ID'] !== PlacementTable::DEFAULT_USER_ID_VALUE
152 && $placementInfo['user_mode'] !== true
153 )
154 {
155 throw new RestException(
156 'User mode is not available.',
158 );
159 }
160
161 $langList = Lang::listLanguage();
162 $langDefault = reset($langList);
163
164 if (empty($params['LANG_ALL']))
165 {
166 if (!empty($params['TITLE']))
167 {
168 $placementLangList[$langDefault]['TITLE'] = trim($params['TITLE']);
169 }
170
171 if (!empty($params['DESCRIPTION']))
172 {
173 $placementLangList[$langDefault]['DESCRIPTION'] = trim($params['DESCRIPTION']);
174 }
175
176 if (!empty($params['GROUP_NAME']))
177 {
178 $placementLangList[$langDefault]['GROUP_NAME'] = trim($params['GROUP_NAME']);
179 }
180 }
181 else
182 {
183 $fieldList = [
184 'TITLE',
185 'DESCRIPTION',
186 'GROUP_NAME',
187 ];
188 foreach ($params['LANG_ALL'] as $langCode => $langItem)
189 {
190 foreach ($fieldList as $field)
191 {
192 $placementLangList[$langCode][$field] = trim($langItem[$field] ?? '');
193 }
194 }
195 }
196
197 $placementBind['LANG_ALL'] = $placementLangList;
198 $placementBind = Lang::mergeFromLangAll($placementBind);
199 unset($placementBind['LANG_ALL']);
200
201 if ($placementInfo['max_count'] > 0)
202 {
203 $filter = [
204 '=APP_ID' => $placementBind['APP_ID'],
205 '=PLACEMENT' => $placementBind['PLACEMENT'],
206 ];
207 if ($placementInfo['user_mode'] === true)
208 {
209 $filter['=USER_ID'] = [
211 (int)$placementBind['USER_ID'],
212 ];
213 }
214
215 $res = PlacementTable::getList(
216 [
217 'filter' => $filter,
218 'select' => [
219 'COUNT',
220 ],
221 'runtime' => [
222 new ExpressionField('COUNT', 'COUNT(*)'),
223 ]
224 ]
225 );
226
227 if ($result = $res->fetch())
228 {
229 if ($result['COUNT'] >= $placementInfo['max_count'])
230 {
231 throw new RestException(
232 'Placement max count: ' . $placementInfo['max_count'],
234 );
235 }
236 }
237 }
238
239 if (
240 array_key_exists('ICON', $params)
241 && is_array($params['ICON'])
242 && $params['ICON']['fileData']
243 && ($file = \CRestUtil::saveFile($params['ICON']['fileData']))
244 )
245 {
246 $placementBind['ICON'] = $file;
247 }
248 if (!empty($placementInfo['registerCallback']['callback']))
249 {
250 if (
251 $placementInfo['registerCallback']['moduleId']
252 && Loader::includeModule($placementInfo['registerCallback']['moduleId'])
253 && is_callable($placementInfo['registerCallback']['callback'])
254 )
255 {
256 $resultCallback = call_user_func(
257 $placementInfo['registerCallback']['callback'],
258 $placementBind,
259 $placementInfo
260 );
261 if (!empty($resultCallback['error']) && !empty($resultCallback['error_description']))
262 {
263 return $resultCallback;
264 }
265 }
266 }
267
268 $lockKey = implode('|', [
269 $placementBind['APP_ID'],
270 $placementBind['PLACEMENT'],
271 $placementBind['PLACEMENT_HANDLER']
272 ]);
273
274 if (Application::getConnection()->lock($lockKey))
275 {
276 $result = PlacementTable::add($placementBind);
277 Application::getConnection()->unlock($lockKey);
278 }
279 else
280 {
281 $result = (new Result())->addError(new Error('Process of binding the handler has already started'));
282 }
283
284 if ($result->isSuccess())
285 {
286 $placementId = $result->getId();
287 if (empty($placementLangList))
288 {
289 $app = AppTable::getByClientId($placementBind['APP_ID']);
290 if (!empty($app['APP_NAME']))
291 {
292 $placementLangList[$langDefault] = [
293 'TITLE' => $app['APP_NAME']
294 ];
295 }
296 }
297 foreach ($placementLangList as $langId => $data)
298 {
299 $data['PLACEMENT_ID'] = $placementId;
300 $data['LANGUAGE_ID'] = $langId;
302 if (!$res->isSuccess())
303 {
304 $errorMessage = $res->getErrorMessages();
305 throw new RestException(
306 'Unable to set placements language: ' . implode(', ', $errorMessage),
308 );
309 }
310 }
311 }
312 else
313 {
314 $errorMessage = $result->getErrorMessages();
315 throw new RestException(
316 'Unable to set placement handler: ' . implode(', ', $errorMessage),
318 );
319 }
320
321 return true;
322 }
323
324 throw new RestException(
325 'Placement not found',
327 );
328 }
329
330 private static function prepareOptions($paramsOptions = [], $placementInfoOptions = []): array
331 {
332 $result = [];
333 if (empty($placementInfoOptions))
334 {
335 return $result;
336 }
337 $requiredOptions = self::getRequiredOptions($placementInfoOptions);
338 $defaultOptions = self::getDefaultOptions($placementInfoOptions);
339
340 if (!is_array($paramsOptions))
341 {
342 if (!empty($requiredOptions))
343 {
344 throw new ArgumentTypeException('options', 'array');
345 }
346
347 return $defaultOptions;
348 }
349
350 self::checkRequiredOptionsInParamsOptions($paramsOptions, $requiredOptions);
351
352 foreach ($placementInfoOptions as $optionName => $optionSetting)
353 {
354 $optionValue = $paramsOptions[$optionName] ?? $defaultOptions[$optionName] ?? null;
355 $optionType = null;
356
357 if (!is_array($optionSetting))
358 {
359 $optionType = $optionSetting;
360 }
361 else
362 {
363 $optionType = $optionSetting['type'];
364 }
365
366 switch($optionType)
367 {
368 case 'int':
370
371 break;
372 case 'string':
374
375 break;
376 case 'array':
377 if (!is_array($optionValue))
378 {
379 throw new ArgumentTypeException($optionName, 'array');
380 }
381 $result[$optionName] = self::prepareCompositeOptions($optionValue, $optionSetting);
382
383 break;
384 }
385 }
386
387 return $result;
388 }
389
397 private static function prepareCompositeOptions(array $paramOptionData, array $optionSetting): array
398 {
399 $result = [];
400 if (!is_array($optionSetting['typeValue']))
401 {
402 throw new ArgumentTypeException('typeValue', 'array');
403 }
404
405 $allowedTypes = ['integer', 'string', 'array'];
406 $optionSetting['typeValue'] = str_replace('int', 'integer', $optionSetting['typeValue']);
407 $optionSetting['typeValue'] = array_intersect($optionSetting['typeValue'], $allowedTypes);
408
409 //1. check transmitted placement data
410 foreach ($paramOptionData as $keyOption => $valueOption)
411 {
412 $typeValue = gettype($valueOption);
413 //do not take arrays, they are processed as a separate entity
414 if (in_array($typeValue, $optionSetting['typeValue']) && $typeValue !== 'array')
415 {
416 $result[$keyOption] = $valueOption;
417 }
418 }
419
420 //2. check default placement setting
421 foreach ($optionSetting as $keySetting => $valueSetting)
422 {
423 //type and typeValue - service data
424 if ($keySetting === 'type' || $keySetting === 'typeValue')
425 {
426 continue;
427 }
428
429 $typeValueSetting = gettype($valueSetting);
430
431 if (
432 $typeValueSetting === 'array'
433 && in_array('array', $optionSetting['typeValue'])
434 && isset($valueSetting['type'])
435 && isset($valueSetting['typeValue'])
436 && isset($paramOptionData[$keySetting])
437 )
438 {
439 $result[$keySetting] = self::prepareCompositeOptions($paramOptionData[$keySetting], $valueSetting);
440 }
441 }
442
443 return $result;
444 }
445
446
462 private static function getDefaultOptions(array $placementInfoOptions): array
463 {
464 $result = [];
465
466 foreach ($placementInfoOptions as $optionName => $optionSetting)
467 {
468 if (isset($optionSetting['default']))
469 {
470 $result[$optionName] = $optionSetting['default'];
471 }
472 }
473
474 return $result;
475 }
476
483 private static function checkRequiredOptionsInParamsOptions(array $paramsOptions, array $requiredOptions): void
484 {
485 foreach ($requiredOptions as $requiredOption)
486 {
487 if (!array_key_exists($requiredOption, $paramsOptions))
488 {
489 throw new ArgumentNullException($requiredOption);
490 }
491 }
492 }
493
494
500 private static function getRequiredOptions(array $placementInfoOptions): array
501 {
502 $result = [];
503 foreach ($placementInfoOptions as $optionName => $optionSettings)
504 {
505 if (self::isRequiredOption($optionSettings))
506 {
508 }
509 }
510
511 return $result;
512 }
513
518 private static function isRequiredOption($optionSettings): bool
519 {
520 if (!isset($optionSettings['require']))
521 {
522 return false;
523 }
524
525 return (bool)$optionSettings['require'];
526 }
527
528 public static function unbind($params, $n, \CRestServer $server)
529 {
530 static::checkPermission($server);
531
532 $params = array_change_key_case($params, CASE_UPPER);
533
534 if (!is_string($params['PLACEMENT']))
535 {
536 throw new Exceptions\ArgumentTypeException('PLACEMENT', 'string');
537 }
538
539 $placement = mb_strtoupper($params['PLACEMENT']);
540 $placementHandler = $params['HANDLER'];
541
542 if ($placement == '')
543 {
544 throw new Exceptions\ArgumentNullException("PLACEMENT");
545 }
546
547 $cnt = 0;
548
549 $placementList = static::getPlacementList($server);
550
551 if (array_key_exists($placement, $placementList) && !$placementList[$placement]['private'])
552 {
553 $appInfo = static::getApplicationInfo($server);
554
555 $filter = array(
556 '=APP_ID' => $appInfo["ID"],
557 '=PLACEMENT' => $placement,
558 );
559
560 if (array_key_exists('USER_ID', $params))
561 {
562 $filter['USER_ID'] = (int)$params['USER_ID'];
563 }
564
565 if($placementHandler <> '')
566 {
567 $filter['=PLACEMENT_HANDLER'] = $placementHandler;
568 }
569
570 $dbRes = PlacementTable::getList(array(
571 'filter' => $filter
572 ));
573
574 while($placementHandler = $dbRes->fetch())
575 {
576 $cnt++;
577 $result = PlacementTable::delete($placementHandler["ID"]);
578 if($result->isSuccess())
579 {
580 $cnt++;
581 }
582 }
583 }
584
585 return array('count' => $cnt);
586 }
587
588
589 public static function get($params, $n, \CRestServer $server)
590 {
591 static::checkPermission($server);
592
593 $result = array();
594
595 $appInfo = static::getApplicationInfo($server);
596
597 $dbRes = PlacementTable::getList(array(
598 "filter" => array(
599 "=APP_ID" => $appInfo["ID"],
600 ),
601 'order' => array(
602 "ID" => "ASC",
603 )
604 ));
605
606 $placementList = static::getPlacementList($server);
607
608 foreach ($dbRes->fetchCollection() as $placement)
609 {
610 if (
611 array_key_exists($placement->getPlacement(), $placementList)
612 && !$placementList[$placement->getPlacement()]['private']
613 )
614 {
615 $langList = [];
616 $placement->fillLangAll();
617 if (!is_null($placement->getLangAll()))
618 {
619 foreach ($placement->getLangAll() as $lang)
620 {
621 $langList[$lang->getLanguageId()] = [
622 'TITLE' => $lang->getTitle(),
623 'DESCRIPTION' => $lang->getDescription(),
624 'GROUP_NAME' => $lang->getGroupName(),
625 ];
626 }
627 }
628 $result[] = array(
629 'placement' => $placement->getPlacement(),
630 'userId' => $placement->getUserId(),
631 'handler' => $placement->getPlacementHandler(),
632 'options' => $placement->getOptions(),
633 'title' => $placement->getTitle(),
634 'description' => $placement->getComment(),
635 'langAll' => $langList,
636 );
637 }
638 }
639
640 return $result;
641 }
642
643 protected static function checkPermission(\CRestServer $server)
644 {
645 if($server->getAuthType() !== Auth::AUTH_TYPE)
646 {
647 throw new AuthTypeException("Application context required");
648 }
649
650 if(!\CRestUtil::isAdmin())
651 {
652 throw new AccessException();
653 }
654 }
655
656 protected static function getScope(\CRestServer $server)
657 {
658 $result = array();
659
660 $authData = $server->getAuthData();
661
662 $scopeList = explode(',', $authData['scope']);
663
664 $serviceDescription = $server->getServiceDescription();
665 foreach($scopeList as $scope)
666 {
667 if(array_key_exists($scope, $serviceDescription))
668 {
669 $result[] = $scope;
670 }
671 }
672
673 return $result;
674 }
675
676 protected static function getApplicationInfo(\CRestServer $server)
677 {
678 if($server->getAuthType() !== Auth::AUTH_TYPE)
679 {
680 throw new AuthTypeException("Application context required");
681 }
682
683 return AppTable::getByClientId($server->getClientId());
684 }
685
686 protected static function getPlacementList(\CRestServer $server, $scopeList = null)
687 {
688 $serviceDescription = $server->getServiceDescription();
689
690 if($scopeList === null)
691 {
692 $scopeList = array_keys($serviceDescription);
693 }
694
695 $result = array();
696
697 foreach($scopeList as $scope)
698 {
699 if(
700 isset($serviceDescription[$scope])
701 && is_array($serviceDescription[$scope][\CRestUtil::PLACEMENTS])
702 )
703 {
704 $result = array_merge($result, $serviceDescription[$scope][\CRestUtil::PLACEMENTS]);
705 }
706 }
707
708 return $result;
709 }
710}
Определения error.php:15
static add(array $data)
Определения datamanager.php:877
static onRestServiceBuildDescription()
Определения placement.php:28
static getScope(\CRestServer $server)
Определения placement.php:656
static getPlacementList(\CRestServer $server, $scopeList=null)
Определения placement.php:686
const SCOPE_PLACEMENT
Определения placement.php:26
static getApplicationInfo(\CRestServer $server)
Определения placement.php:676
static checkPermission(\CRestServer $server)
Определения placement.php:643
static getList($query, $n, \CRestServer $server)
Определения placement.php:53
static unbind($params, $n, \CRestServer $server)
Определения placement.php:528
static bind($params, $n, \CRestServer $server)
Определения placement.php:98
static getByClientId($clientId)
Определения app.php:967
static checkCallback($handlerUrl, $appInfo=array(), $checkInstallUrl=true)
Определения handlerhelper.php:31
static listLanguage()
Определения lang.php:19
static mergeFromLangAll($data)
Определения lang.php:59
const PLACEMENT_DEFAULT
Определения placement.php:51
const ERROR_PLACEMENT_MAX_COUNT
Определения placement.php:54
const ERROR_PLACEMENT_NOT_FOUND
Определения placement.php:53
const ERROR_PLACEMENT_USER_MODE
Определения placement.php:55
const DEFAULT_USER_ID_VALUE
Определения placement.php:49
const ERROR_CORE
Определения restexception.php:15
Определения rest.php:24
getServiceDescription()
Определения rest.php:397
getAuthData()
Определения rest.php:324
getAuthType()
Определения rest.php:347
getClientId()
Определения rest.php:362
Определения rest.php:896
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$filter
Определения iblock_catalog_list.php:54
while($arParentIBlockProperty=$dbParentIBlockProperty->Fetch()) $errorMessage
$app
Определения proxy.php:8
if(!defined('SITE_ID')) $lang
Определения include.php:91
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$optionName
Определения options.php:1735
$optionValue
Определения options.php:3512
$n
Определения update_log.php:107
$dbRes
Определения yandex_detail.php:168