1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
binder.php
См. документацию.
1<?php
2
4
9use Psr\Container\NotFoundExceptionInterface;
10
11class Binder
12{
13 const STATUS_FOUND = true;
14 const STATUS_NOT_FOUND = false;
15
16 private $instance;
17 private $method;
19 private $configuration = [];
21 private static $globalAutoWiredParameters;
23 private $autoWiredParameters = [];
25 private $reflectionFunctionAbstract;
27 private $methodParams = null;
29 private $args = null;
30
31 public function __construct($instance, $method, $configuration = [])
32 {
33 $this->instance = $instance;
34 $this->method = $method;
35 $this->configuration = $configuration;
36
37 if ($this->instance === null)
38 {
39 $this->buildReflectionFunction();
40 }
41 else
42 {
43 $this->buildReflectionMethod();
44 }
45
46 }
47
48 final public static function buildForFunction($callable, $configuration = [])
49 {
50 return new static(null, $callable, $configuration);
51 }
52
53 final public static function buildForMethod($instance, $method, $configuration = [])
54 {
55 return new static($instance, $method, $configuration);
56 }
57
58 private function buildReflectionMethod()
59 {
60 $this->reflectionFunctionAbstract = new \ReflectionMethod($this->instance, $this->method);
61 $this->reflectionFunctionAbstract->setAccessible(true);
62 }
63
64 private function buildReflectionFunction()
65 {
66 $this->reflectionFunctionAbstract = new \ReflectionFunction($this->method);
67 }
68
72 public function getInstance()
73 {
74 return $this->instance;
75 }
76
80 public function getMethod()
81 {
82 return $this->method;
83 }
84
88 public function getConfiguration()
89 {
90 return $this->configuration;
91 }
92
98 public function setConfiguration($configuration)
99 {
100 $this->configuration = $configuration;
101
102 return $this;
103 }
104
110 public function setAutoWiredParameters(array $parameters)
111 {
112 $this->autoWiredParameters = [];
113
114 foreach ($parameters as $parameter)
115 {
116 $this->appendAutoWiredParameter($parameter);
117 }
118
119 return $this;
120 }
121
122 public function appendAutoWiredParameter(Parameter $parameter)
123 {
124 $this->autoWiredParameters[] = $parameter;
125
126 return $this;
127 }
128
134 public static function registerGlobalAutoWiredParameter(Parameter $parameter)
135 {
136 if (self::$globalAutoWiredParameters === null)
137 {
138 self::$globalAutoWiredParameters = new \SplObjectStorage();
139 }
140
141 if (!self::$globalAutoWiredParameters->contains($parameter))
142 {
143 self::$globalAutoWiredParameters[$parameter] = $parameter;
144 }
145 }
146
151 public static function unRegisterGlobalAutoWiredParameter(Parameter $parameter): void
152 {
153 if (self::$globalAutoWiredParameters === null)
154 {
155 return;
156 }
157
158 if (self::$globalAutoWiredParameters->contains($parameter))
159 {
160 self::$globalAutoWiredParameters->detach($parameter);
161 }
162 }
163
164 private function getPriorityByParameter(Parameter $parameter)
165 {
166 return $parameter->getPriority();
167 }
168
172 public function getAutoWiredParameters()
173 {
174 return $this->autoWiredParameters;
175 }
176
177 public function setSourcesParametersToMap(array $parameters)
178 {
179 $this->configuration['sourceParameters'] = $parameters;
180
181 return $this;
182 }
183
185 {
186 return $this->configuration['sourceParameters']?: [];
187 }
188
189 public function appendSourcesParametersToMap(array $parameter)
190 {
191 if (!isset($this->configuration['sourceParameters']))
192 {
193 $this->configuration['sourceParameters'] = [];
194 }
195
196 $this->configuration['sourceParameters'][] = $parameter;
197
198 return $this;
199 }
200
205 final public function invoke()
206 {
207 try
208 {
209 if ($this->reflectionFunctionAbstract instanceof \ReflectionMethod)
210 {
211 return $this->reflectionFunctionAbstract->invokeArgs($this->instance, $this->getArgs());
212 }
213
214 if ($this->reflectionFunctionAbstract instanceof \ReflectionFunction)
215 {
216 return $this->reflectionFunctionAbstract->invokeArgs($this->getArgs());
217 }
218 }
219 catch (\TypeError $exception)
220 {
221 throw $exception;
222 }
223 catch (\ErrorException $exception)
224 {
225 throw $exception;
226 }
227
228 return null;
229 }
230
235 final public function getMethodParams()
236 {
237 if ($this->methodParams === null)
238 {
239 $this->bindParams();
240 }
241
242 return $this->methodParams;
243 }
244
251 final public function setMethodParams(array $params)
252 {
253 $this->methodParams = $params;
254 $this->args = array_values($params);
255
256 return $this;
257 }
258
263 final public function getArgs()
264 {
265 if ($this->args === null)
266 {
267 $this->bindParams();
268 }
269
270 return $this->args;
271 }
272
273 private function bindParams()
274 {
275 $this->args = $this->methodParams = [];
276
277 foreach ($this->reflectionFunctionAbstract->getParameters() as $param)
278 {
279 $value = $this->getParameterValue($param);
280 $this->args[] = $this->methodParams[$param->getName()] = $value;
281 }
282
283 return $this->args;
284 }
285
291 private function getAutoWiredByClass(\ReflectionParameter $reflectionParameter)
292 {
293 $result = new \SplPriorityQueue();
294 foreach ($this->getAllAutoWiredParameters() as $parameter)
295 {
296 if ($parameter->match($reflectionParameter))
297 {
298 $result->insert($parameter, $this->getPriorityByParameter($parameter));
299 }
300 }
301
302 return $result;
303 }
304
308 private function getAllAutoWiredParameters()
309 {
310 $list = $this->getAutoWiredParameters();
311 if (self::$globalAutoWiredParameters)
312 {
313 foreach (self::$globalAutoWiredParameters as $globalAutoWiredParameter)
314 {
315 $list[] = $globalAutoWiredParameter;
316 }
317 }
318
319 return $list;
320 }
321
322 protected function constructValue(\ReflectionParameter $parameter, Parameter $autoWireParameter, Result $captureResult): Result
323 {
324 $result = new Result();
325
326 $constructedValue = $autoWireParameter->constructValue($parameter, $captureResult);
327
328 $result->setData([
329 'value' => $constructedValue,
330 ]);
331
332 return $result;
333 }
334
340 private function getParameterValue(\ReflectionParameter $parameter)
341 {
342 $sourceParameters = $this->getSourcesParametersToMap();
343
344 $reflectionType = $parameter->getType();
345 if (
346 ($reflectionType instanceof \ReflectionUnionType)
347 || ($reflectionType instanceof \ReflectionIntersectionType)
348 )
349 {
350 throw new BinderArgumentException(
351 "Currently there is no support for union or intersection types {{$parameter->getName()}}",
352 $parameter
353 );
354 }
355
356 if (($reflectionType instanceof \ReflectionNamedType) && !$reflectionType->isBuiltin())
357 {
358 foreach ($this->getAutoWiredByClass($parameter) as $autoWireParameter)
359 {
360 $result = $autoWireParameter->captureData($parameter, $sourceParameters, $this->getAllAutoWiredParameters());
361 if (!$result->isSuccess())
362 {
363 continue;
364 }
365
366 $constructedValue = null;
367 $constructResult = $this->constructValue($parameter, $autoWireParameter, $result);
368 if ($constructResult->isSuccess())
369 {
370 ['value' => $constructedValue] = $constructResult->getData();
371 }
372
373 if ($constructedValue === null)
374 {
375 if ($parameter->allowsNull())
376 {
377 return null;
378 }
379
380 if ($parameter->isDefaultValueAvailable())
381 {
382 return $parameter->getDefaultValue();
383 }
384
385 throw new BinderArgumentException(
386 "Could not construct parameter {{$parameter->getName()}}",
387 $parameter,
388 $constructResult->getErrors(),
389 );
390 }
391
392 (new ValidationChecker($parameter, $constructedValue))->check();
393
394 return $constructedValue;
395 }
396
397 $reflectionClass = new \ReflectionClass($reflectionType->getName());
398 if ($reflectionClass->isEnum())
399 {
400 $enum = new \ReflectionEnum($reflectionType->getName());
401 $backedType = $enum->getBackingType();
402 if ($backedType && $enum->isBacked())
403 {
404 $backedValue = $this->findParameterInSourceList($parameter->getName(), $status);
405 if ($status === self::STATUS_NOT_FOUND)
406 {
407 if ($parameter->isDefaultValueAvailable())
408 {
409 return $parameter->getDefaultValue();
410 }
411
412 throw new BinderArgumentException(
413 "Could not find value for parameter {{$parameter->getName()}}",
414 $parameter
415 );
416 }
417 $declarationChecker = new TypeDeclarationChecker($backedType, $backedValue);
418 if (!$declarationChecker->isSatisfied())
419 {
420 throw new BinderArgumentException(
421 "Invalid value {{$backedValue}} to match with parameter {{$parameter->getName()}}. Should be value of type {$backedType->getName()}.",
422 $parameter
423 );
424 }
425
426 $enumValue = $reflectionType->getName()::tryFrom($backedValue);
427 if ($enumValue)
428 {
429 return $enumValue;
430 }
431 }
432 }
433
434 if ($parameter->isDefaultValueAvailable())
435 {
436 return $parameter->getDefaultValue();
437 }
438
439 try
440 {
441 if (class_exists($reflectionType->getName()))
442 {
443 if ($object = ServiceLocator::getInstance()->get($reflectionType->getName()))
444 {
445 return $object;
446 }
447 }
448 }
449 catch (ObjectNotFoundException $exception)
450 {
451 throw new BinderArgumentException(
452 $exception->getMessage(),
453 $parameter
454 );
455 }
456
457 $exceptionMessage = "Could not find value for parameter to build auto wired argument {{$reflectionType->getName()} \${$parameter->getName()}}";
458 if (isset($result) && ($result instanceof Result) && $result->getErrorMessages())
459 {
460 $exceptionMessage = $result->getErrorMessages()[0];
461 }
462
463 throw new BinderArgumentException(
464 $exceptionMessage,
465 $parameter
466 );
467 }
468
469 $value = $this->findParameterInSourceList($parameter->getName(), $status);
470 if ($status === self::STATUS_NOT_FOUND)
471 {
472 if ($parameter->isDefaultValueAvailable())
473 {
474 return $parameter->getDefaultValue();
475 }
476
477 throw new BinderArgumentException(
478 "Could not find value for parameter {{$parameter->getName()}}",
479 $parameter
480 );
481 }
482 if ($reflectionType instanceof \ReflectionNamedType)
483 {
484 $declarationChecker = new TypeDeclarationChecker($reflectionType, $value);
485 if (!$declarationChecker->isSatisfied())
486 {
487 throw new BinderArgumentException(
488 "Invalid value {{$value}} to match with parameter {{$parameter->getName()}}. Should be value of type {$reflectionType->getName()}.",
489 $parameter
490 );
491 }
492 if ($declarationChecker->isArray())
493 {
494 $value = (array)$value;
495 }
496
497 (new ValidationChecker($parameter, $value))->check();
498 }
499
500 return $value;
501 }
502
503 private function findParameterInSourceList($name, &$status)
504 {
505 $status = self::STATUS_FOUND;
506 foreach ($this->getSourcesParametersToMap() as $source)
507 {
508 if (isset($source[$name]))
509 {
510 return $source[$name];
511 }
512
513 if ($source instanceof \ArrayAccess && $source->offsetExists($name))
514 {
515 return $source[$name];
516 }
517
518 if (is_array($source) && array_key_exists($name, $source))
519 {
520 return $source[$name];
521 }
522 }
523
524 $status = self::STATUS_NOT_FOUND;
525
526 return null;
527 }
528}
static unRegisterGlobalAutoWiredParameter(Parameter $parameter)
Определения binder.php:151
appendSourcesParametersToMap(array $parameter)
Определения binder.php:189
appendAutoWiredParameter(Parameter $parameter)
Определения binder.php:122
static registerGlobalAutoWiredParameter(Parameter $parameter)
Определения binder.php:134
setConfiguration($configuration)
Определения binder.php:98
__construct($instance, $method, $configuration=[])
Определения binder.php:31
const STATUS_NOT_FOUND
Определения binder.php:14
const STATUS_FOUND
Определения binder.php:13
static buildForFunction($callable, $configuration=[])
Определения binder.php:48
setAutoWiredParameters(array $parameters)
Определения binder.php:110
static buildForMethod($instance, $method, $configuration=[])
Определения binder.php:53
getSourcesParametersToMap()
Определения binder.php:184
setSourcesParametersToMap(array $parameters)
Определения binder.php:177
setMethodParams(array $params)
Определения binder.php:251
constructValue(\ReflectionParameter $parameter, Parameter $autoWireParameter, Result $captureResult)
Определения binder.php:322
constructValue(\ReflectionParameter $parameter, Result $captureResult, $newThis=null)
Определения parameter.php:47
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$status
Определения session.php:10
$name
Определения menu_edit.php:35
$value
Определения Param.php:39
$instance
Определения ps_b24_final.php:14
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$method
Определения index.php:27