30 private $pageNavigation;
32 private $calculateTotalCount =
true;
34 public static function onFindMethodDescription($potentialAction)
36 $restManager =
new static();
39 $request = new \Bitrix\Main\HttpRequest(
41 [
'action' => $potentialActionData[
'method']],
47 if (empty($controllersConfig[
'controllers'][
'restIntegration'][
'enabled']))
53 list($controller) = $router->getControllerAndAction();
60 'scope' => static::getModuleScopeAlias($potentialActionData[
'scope']),
62 $restManager,
'processMethodRequest'
69 if($moduleId ===
'tasks')
77 private static function getAlternativeScope($scope): ?array
79 if ($scope === \
Bitrix\Rest\Api\User::SCOPE_USER)
82 \Bitrix\Rest\Api\User::SCOPE_USER_BRIEF,
83 \Bitrix\Rest\Api\User::SCOPE_USER_BASIC,
92 if (!in_array($scope, $scopeList,
true))
94 $altScopeList = static::getAlternativeScope($scope);
95 if (is_array($altScopeList))
97 $hasScope = array_intersect($scopeList, $altScopeList);
98 if (count($hasScope) > 0)
100 $scopeList[] = $scope;
119 public function processMethodRequest(array $params, $start, \CRestServer
$restServer)
121 $start = intval($start);
128 $request = new \Bitrix\Main\HttpRequest(
130 [
'action' => $methodData[
'method']],
137 $router->getVendor(),
138 $router->getModule(),
139 $router->getAction(),
144 throw new RestException(
"Unknown {$method}. There is not controller in module {$router->getModule()}");
147 $this->calculateTotalCount =
true;
148 if ((
int)$start === self::DONT_CALCULATE_COUNT)
150 $this->calculateTotalCount =
false;
153 $autoWirings = $this->getAutoWirings();
155 $this->registerAutoWirings($autoWirings);
156 $result = $controller->run($action, [$params, [
'__restServer' =>
$restServer,
'__calculateTotalCount' => $this->calculateTotalCount]]);
157 $this->unRegisterAutoWirings($autoWirings);
159 if ($result instanceof Engine\Response\File)
161 return $result->send();
164 if ($result instanceof HttpResponse)
166 if ($result instanceof Errorable)
168 $errorCollection->add($result->getErrors());
171 $result = $result->getContent();
174 if ($result instanceof RestException)
179 if ($result ===
null)
181 $errorCollection->add($controller->getErrors());
182 if (!$errorCollection->isEmpty())
184 throw $this->createExceptionFromErrors($errorCollection->toArray());
188 return $this->processData($result);
195 private function initialize(\CRestServer
$restServer,
int $start): void
197 $pageNavigation =
new PageNavigation(
'nav');
198 $pageNavigation->setPageSize(static::LIST_LIMIT);
201 $pageNavigation->setCurrentPage((
int)($start / static::LIST_LIMIT) + 1);
204 $this->pageNavigation = $pageNavigation;
214 private function getNavigationData(Engine\Response\DataType\Page $page): array
216 if (!$this->calculateTotalCount)
222 $offset = $this->pageNavigation->getOffset();
223 $total = $page->getTotalCount();
225 $currentPageSize = count($page->getItems());
227 if ($offset + $currentPageSize < $total)
229 $result[
'next'] = $offset + $currentPageSize;
232 $result[
'total'] = $total;
238 private function processData($result)
240 if ($result instanceof DateTime)
242 return \CRestUtil::convertDateTime($result);
245 if ($result instanceof Date)
247 return \CRestUtil::convertDate($result);
250 if ($result instanceof Uri)
252 return $this->convertAjaxUriToRest($result);
255 if ($result instanceof Engine\Response\DataType\Page)
257 if (method_exists($result,
'getId'))
259 $data = [$result->getId() => $this->processData($result->getIterator())];
263 $data = $this->processData($result->getIterator());
266 return array_merge($data, $this->getNavigationData($result));
269 if ($result instanceof Contract\Arrayable)
271 $result = $result->toArray();
274 if (is_array($result))
276 foreach ($result as $key => $item)
278 if ($item instanceof Engine\Response\DataType\ContentUri)
280 $result[$key .
"Machine"] = $this->processData($item);
281 $result[$key] = $this->processData(
new Uri($item));
285 $result[$key] = $this->processData($item);
290 elseif ($result instanceof \Traversable)
293 foreach ($result as $key => $item)
295 $newResult[$key] = $this->processData($item);
298 $result = $newResult;
304 private function convertAjaxUriToRest(Uri $uri)
306 if (!($uri instanceof Engine\Response\DataType\ContentUri))
308 return $uri->getUri();
312 if ($uri->getPath() !== $endPoint->getPath())
314 return $uri->getUri();
317 if ($uri->getHost() && $uri->getHost() !== $endPoint->getHost())
319 return $uri->getUri();
322 parse_str($uri->getQuery(), $params);
323 if (empty($params[
'action']))
325 return $uri->getUri();
328 return \CRestUtil::getSpecialUrl($params[
'action'], $params, $this->restServer);
331 private function getRestEndPoint()
333 return \Bitrix\Main\Config\Option::get(
'rest',
'rest_server_path',
'/rest');
340 private function createExceptionFromErrors(array $errors)
347 $firstError = reset($errors);
349 return new RestException($firstError->getMessage(), $firstError->getCode());
355 private function registerAutoWirings(array $autoWirings): void
357 foreach ($autoWirings as $parameter)
359 AutoWire\Binder::registerGlobalAutoWiredParameter($parameter);
366 private function unRegisterAutoWirings(array $autoWirings): void
368 foreach ($autoWirings as $parameter)
370 AutoWire\Binder::unRegisterGlobalAutoWiredParameter($parameter);
377 private function getAutoWirings(): array
381 'class' => \CRestServer::class,
382 'constructor' =>
function() {
386 'pageNavigation' => [
387 'class' => PageNavigation::class,
388 'constructor' =>
function() {
389 return $this->pageNavigation;
395 foreach ($buildRules as $rule)
397 $autoWirings[] =
new AutoWire\Parameter($rule[
'class'], $rule[
'constructor']);
static getControllerAndAction($vendor, $module, $action, $scope=Controller::SCOPE_AJAX)