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