2 namespace TYPO3\CMS\Extbase\Reflection
;
5 * This file is part of the TYPO3 CMS project.
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use Doctrine\Common\Annotations\AnnotationReader
;
18 use TYPO3\CMS\Core\SingletonInterface
;
19 use TYPO3\CMS\Core\Utility\ClassNamingUtility
;
20 use TYPO3\CMS\Core\Utility\GeneralUtility
;
21 use TYPO3\CMS\Core\Utility\StringUtility
;
22 use TYPO3\CMS\Extbase\Annotation\IgnoreValidation
;
23 use TYPO3\CMS\Extbase\Annotation\Inject
;
24 use TYPO3\CMS\Extbase\Annotation\ORM\Cascade
;
25 use TYPO3\CMS\Extbase\Annotation\ORM\Lazy
;
26 use TYPO3\CMS\Extbase\Annotation\ORM\Transient
;
27 use TYPO3\CMS\Extbase\Annotation\Validate
;
28 use TYPO3\CMS\Extbase\DomainObject\AbstractEntity
;
29 use TYPO3\CMS\Extbase\DomainObject\AbstractValueObject
;
30 use TYPO3\CMS\Extbase\Mvc\Controller\ControllerInterface
;
31 use TYPO3\CMS\Extbase\Utility\TypeHandlingUtility
;
32 use TYPO3\CMS\Extbase\Validation\Exception\InvalidTypeHintException
;
33 use TYPO3\CMS\Extbase\Validation\Exception\InvalidValidationConfigurationException
;
34 use TYPO3\CMS\Extbase\Validation\ValidatorResolver
;
39 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
44 * Available model types
46 const MODELTYPE_ENTITY
= 1;
47 const MODELTYPE_VALUEOBJECT
= 2;
50 * Name of the class this schema is referring to
57 * Model type of the class this schema is referring to
61 protected $modelType = self
::MODELTYPE_ENTITY
;
64 * Whether a repository exists for the class this schema is referring to
68 protected $aggregateRoot = false;
71 * The name of the property holding the uuid of an entity, if any.
75 protected $uuidPropertyName;
78 * Properties of the class which need to be persisted
82 protected $properties = [];
85 * The properties forming the identity of an object
89 protected $identityProperties = [];
92 * Indicates if the class is a singleton or not.
101 private $isController;
116 private $injectProperties = [];
121 private $injectMethods = [];
124 * Constructs this class schema
126 * @param string $className Name of the class this schema is referring to
127 * @throws \TYPO3\CMS\Extbase\Reflection\Exception\UnknownClassException
128 * @throws \ReflectionException
130 public function __construct($className)
132 $this->className
= $className;
134 $reflectionClass = new \
ReflectionClass($className);
136 $this->isSingleton
= $reflectionClass->implementsInterface(SingletonInterface
::class);
137 $this->isController
= $reflectionClass->implementsInterface(ControllerInterface
::class);
139 if ($reflectionClass->isSubclassOf(AbstractEntity
::class)) {
140 $this->modelType
= static::MODELTYPE_ENTITY
;
142 $possibleRepositoryClassName = ClassNamingUtility
::translateModelNameToRepositoryName($className);
143 if (class_exists($possibleRepositoryClassName)) {
144 $this->setAggregateRoot(true);
148 if ($reflectionClass->isSubclassOf(AbstractValueObject
::class)) {
149 $this->modelType
= static::MODELTYPE_VALUEOBJECT
;
152 $docCommentParser = new DocCommentParser(true);
153 $docCommentParser->parseDocComment($reflectionClass->getDocComment());
154 $this->tags
= $docCommentParser->getTagsValues();
156 $this->reflectProperties($reflectionClass);
157 $this->reflectMethods($reflectionClass);
161 * @param \ReflectionClass $reflectionClass
163 protected function reflectProperties(\ReflectionClass
$reflectionClass)
165 $annotationReader = new AnnotationReader();
167 foreach ($reflectionClass->getProperties() as $reflectionProperty) {
168 $propertyName = $reflectionProperty->getName();
170 $this->properties
[$propertyName] = [
171 'default' => $reflectionProperty->isDefault(),
172 'private' => $reflectionProperty->isPrivate(),
173 'protected' => $reflectionProperty->isProtected(),
174 'public' => $reflectionProperty->isPublic(),
175 'static' => $reflectionProperty->isStatic(),
176 'type' => null, // Extbase
177 'elementType' => null, // Extbase
183 $docCommentParser = new DocCommentParser(true);
184 $docCommentParser->parseDocComment($reflectionProperty->getDocComment());
185 foreach ($docCommentParser->getTagsValues() as $tag => $values) {
186 $this->properties
[$propertyName]['tags'][strtolower($tag)] = $values;
189 $this->properties
[$propertyName]['annotations']['inject'] = false;
190 $this->properties
[$propertyName]['annotations']['lazy'] = false;
191 $this->properties
[$propertyName]['annotations']['transient'] = false;
192 $this->properties
[$propertyName]['annotations']['type'] = null;
193 $this->properties
[$propertyName]['annotations']['cascade'] = null;
194 $this->properties
[$propertyName]['annotations']['dependency'] = null;
196 $annotations = $annotationReader->getPropertyAnnotations($reflectionProperty);
198 /** @var array|Validate[] $validateAnnotations */
199 $validateAnnotations = array_filter($annotations, function ($annotation) {
200 return $annotation instanceof Validate
;
203 if (count($validateAnnotations) > 0) {
204 $validatorResolver = GeneralUtility
::makeInstance(ValidatorResolver
::class);
206 foreach ($validateAnnotations as $validateAnnotation) {
207 $validatorObjectName = $validatorResolver->resolveValidatorObjectName($validateAnnotation->validator
);
209 $this->properties
[$propertyName]['validators'][] = [
210 'name' => $validateAnnotation->validator
,
211 'options' => $validateAnnotation->options
,
212 'className' => $validatorObjectName,
217 if ($docCommentParser->isTaggedWith('validate')) {
220 'Property %s::%s is tagged with @validate which is deprecated and will be removed in TYPO3 v10.0.',
221 $reflectionClass->getName(),
222 $reflectionProperty->getName()
227 $validatorResolver = GeneralUtility
::makeInstance(ValidatorResolver
::class);
229 $validateValues = $docCommentParser->getTagValues('validate');
230 foreach ($validateValues as $validateValue) {
231 $validatorConfiguration = $validatorResolver->parseValidatorAnnotation($validateValue);
233 foreach ($validatorConfiguration['validators'] ??
[] as $validator) {
234 $validatorObjectName = $validatorResolver->resolveValidatorObjectName($validator['validatorName']);
236 $this->properties
[$propertyName]['validators'][] = [
237 'name' => $validator['validatorName'],
238 'options' => $validator['validatorOptions'],
239 'className' => $validatorObjectName,
245 if ($annotationReader->getPropertyAnnotation($reflectionProperty, Lazy
::class) instanceof Lazy
) {
246 $this->properties
[$propertyName]['annotations']['lazy'] = true;
249 if ($docCommentParser->isTaggedWith('lazy')) {
250 $this->properties
[$propertyName]['annotations']['lazy'] = true;
253 'Property %s::%s is tagged with @lazy which is deprecated and will be removed in TYPO3 v10.0.',
254 $reflectionClass->getName(),
255 $reflectionProperty->getName()
261 if ($annotationReader->getPropertyAnnotation($reflectionProperty, Transient
::class) instanceof Transient
) {
262 $this->properties
[$propertyName]['annotations']['transient'] = true;
265 if ($docCommentParser->isTaggedWith('transient')) {
266 $this->properties
[$propertyName]['annotations']['transient'] = true;
269 'Property %s::%s is tagged with @transient which is deprecated and will be removed in TYPO3 v10.0.',
270 $reflectionClass->getName(),
271 $reflectionProperty->getName()
277 if ($propertyName !== 'settings'
278 && ($annotationReader->getPropertyAnnotation($reflectionProperty, Inject
::class) instanceof Inject
)
281 $varValue = ltrim($docCommentParser->getTagValues('var')[0], '\\');
282 $this->properties
[$propertyName]['annotations']['inject'] = true;
283 $this->properties
[$propertyName]['annotations']['type'] = $varValue;
284 $this->properties
[$propertyName]['annotations']['dependency'] = $varValue;
286 $this->injectProperties
[] = $propertyName;
287 } catch (\Exception
$e) {
291 if ($propertyName !== 'settings' && $docCommentParser->isTaggedWith('inject')) {
294 'Property %s::%s is tagged with @inject which is deprecated and will be removed in TYPO3 v10.0.',
295 $reflectionClass->getName(),
296 $reflectionProperty->getName()
301 $varValues = $docCommentParser->getTagValues('var');
302 $this->properties
[$propertyName]['annotations']['inject'] = true;
303 $this->properties
[$propertyName]['annotations']['type'] = ltrim($varValues[0], '\\');
304 $this->properties
[$propertyName]['annotations']['dependency'] = ltrim($varValues[0], '\\');
306 if (!$reflectionProperty->isPublic()) {
309 'Property %s::%s is not public and tagged with @inject which is deprecated and will stop working in TYPO3 v10.0.',
310 $reflectionClass->getName(),
311 $reflectionProperty->getName()
317 $this->injectProperties
[] = $propertyName;
318 } catch (\Exception
$e) {
322 if ($docCommentParser->isTaggedWith('var') && !$docCommentParser->isTaggedWith('transient')) {
324 $cascadeAnnotationValues = $docCommentParser->getTagValues('cascade');
325 $this->properties
[$propertyName]['annotations']['cascade'] = $cascadeAnnotationValues[0];
326 } catch (\Exception
$e) {
329 if ($this->properties
[$propertyName]['annotations']['cascade'] !== null) {
332 'Property %s::%s is tagged with @cascade which is deprecated and will be removed in TYPO3 v10.0.',
333 $reflectionClass->getName(),
334 $reflectionProperty->getName()
340 if (($annotation = $annotationReader->getPropertyAnnotation($reflectionProperty, Cascade
::class)) instanceof Cascade
) {
341 /** @var Cascade $annotation */
342 $this->properties
[$propertyName]['annotations']['cascade'] = $annotation->value
;
346 $type = TypeHandlingUtility
::parseType(implode(' ', $docCommentParser->getTagValues('var')));
347 } catch (\Exception
$e) {
350 'elementType' => null
354 $this->properties
[$propertyName]['type'] = $type['type'] ?
ltrim($type['type'], '\\') : null;
355 $this->properties
[$propertyName]['elementType'] = $type['elementType'] ?
ltrim($type['elementType'], '\\') : null;
358 if ($docCommentParser->isTaggedWith('uuid')) {
359 $this->setUuidPropertyName($propertyName);
362 if ($docCommentParser->isTaggedWith('identity')) {
363 $this->markAsIdentityProperty($propertyName);
369 * @param \ReflectionClass $reflectionClass
371 protected function reflectMethods(\ReflectionClass
$reflectionClass)
373 $annotationReader = new AnnotationReader();
375 foreach ($reflectionClass->getMethods() as $reflectionMethod) {
376 $methodName = $reflectionMethod->getName();
378 $this->methods
[$methodName] = [];
379 $this->methods
[$methodName]['private'] = $reflectionMethod->isPrivate();
380 $this->methods
[$methodName]['protected'] = $reflectionMethod->isProtected();
381 $this->methods
[$methodName]['public'] = $reflectionMethod->isPublic();
382 $this->methods
[$methodName]['static'] = $reflectionMethod->isStatic();
383 $this->methods
[$methodName]['abstract'] = $reflectionMethod->isAbstract();
384 $this->methods
[$methodName]['params'] = [];
385 $this->methods
[$methodName]['tags'] = [];
386 $this->methods
[$methodName]['annotations'] = [];
387 $this->methods
[$methodName]['isAction'] = StringUtility
::endsWith($methodName, 'Action');
389 $docCommentParser = new DocCommentParser(true);
390 $docCommentParser->parseDocComment($reflectionMethod->getDocComment());
392 $argumentValidators = [];
394 $annotations = $annotationReader->getMethodAnnotations($reflectionMethod);
396 /** @var array|Validate[] $validateAnnotations */
397 $validateAnnotations = array_filter($annotations, function ($annotation) {
398 return $annotation instanceof Validate
;
401 if ($this->isController
&& $this->methods
[$methodName]['isAction'] && count($validateAnnotations) > 0) {
402 $validatorResolver = GeneralUtility
::makeInstance(ValidatorResolver
::class);
404 foreach ($validateAnnotations as $validateAnnotation) {
405 $validatorName = $validateAnnotation->validator
;
406 $validatorObjectName = $validatorResolver->resolveValidatorObjectName($validatorName);
408 $argumentValidators[$validateAnnotation->param
][] = [
409 'name' => $validatorName,
410 'options' => $validateAnnotation->options
,
411 'className' => $validatorObjectName,
416 foreach ($docCommentParser->getTagsValues() as $tag => $values) {
417 if ($tag === 'ignorevalidation') {
420 'Method %s::%s is tagged with @ignorevalidation which is deprecated and will be removed in TYPO3 v10.0.',
421 $reflectionClass->getName(),
422 $reflectionMethod->getName()
427 if ($tag === 'validate' && $this->isController
&& $this->methods
[$methodName]['isAction']) {
430 'Method %s::%s is tagged with @validate which is deprecated and will be removed in TYPO3 v10.0.',
431 $reflectionClass->getName(),
432 $reflectionMethod->getName()
437 $validatorResolver = GeneralUtility
::makeInstance(ValidatorResolver
::class);
439 foreach ($values as $validate) {
440 $methodValidatorDefinition = $validatorResolver->parseValidatorAnnotation($validate);
442 foreach ($methodValidatorDefinition['validators'] as $validator) {
443 $validatorObjectName = $validatorResolver->resolveValidatorObjectName($validator['validatorName']);
445 $argumentValidators[$methodValidatorDefinition['argumentName']][] = [
446 'name' => $validator['validatorName'],
447 'options' => $validator['validatorOptions'],
448 'className' => $validatorObjectName,
453 $this->methods
[$methodName]['tags'][$tag] = array_map(function ($value) use ($tag) {
454 // not stripping the dollar sign for @validate annotations is just
455 // a quick fix for a regression introduced in 9.0.0.
456 // This exception to the rules will vanish once the resolving of
457 // validators will take place inside this class and not in the
458 // controller during runtime.
459 return $tag === 'validate' ?
$value : ltrim($value, '$');
462 unset($methodValidatorDefinition);
464 foreach ($annotations as $annotation) {
465 if ($annotation instanceof IgnoreValidation
) {
466 $this->methods
[$methodName]['tags']['ignorevalidation'][] = $annotation->argumentName
;
470 $this->methods
[$methodName]['description'] = $docCommentParser->getDescription();
472 foreach ($reflectionMethod->getParameters() as $parameterPosition => $reflectionParameter) {
473 /* @var $reflectionParameter \ReflectionParameter */
475 $parameterName = $reflectionParameter->getName();
477 $this->methods
[$methodName]['params'][$parameterName] = [];
478 $this->methods
[$methodName]['params'][$parameterName]['position'] = $parameterPosition; // compat
479 $this->methods
[$methodName]['params'][$parameterName]['byReference'] = $reflectionParameter->isPassedByReference(); // compat
480 $this->methods
[$methodName]['params'][$parameterName]['array'] = $reflectionParameter->isArray(); // compat
481 $this->methods
[$methodName]['params'][$parameterName]['optional'] = $reflectionParameter->isOptional();
482 $this->methods
[$methodName]['params'][$parameterName]['allowsNull'] = $reflectionParameter->allowsNull(); // compat
483 $this->methods
[$methodName]['params'][$parameterName]['class'] = null; // compat
484 $this->methods
[$methodName]['params'][$parameterName]['type'] = null;
485 $this->methods
[$methodName]['params'][$parameterName]['nullable'] = $reflectionParameter->allowsNull();
486 $this->methods
[$methodName]['params'][$parameterName]['default'] = null;
487 $this->methods
[$methodName]['params'][$parameterName]['hasDefaultValue'] = $reflectionParameter->isDefaultValueAvailable();
488 $this->methods
[$methodName]['params'][$parameterName]['defaultValue'] = null; // compat
489 $this->methods
[$methodName]['params'][$parameterName]['dependency'] = null; // Extbase DI
490 $this->methods
[$methodName]['params'][$parameterName]['validators'] = [];
492 if ($reflectionParameter->isDefaultValueAvailable()) {
493 $this->methods
[$methodName]['params'][$parameterName]['default'] = $reflectionParameter->getDefaultValue();
494 $this->methods
[$methodName]['params'][$parameterName]['defaultValue'] = $reflectionParameter->getDefaultValue(); // compat
497 if (($reflectionType = $reflectionParameter->getType()) instanceof \ReflectionType
) {
498 $this->methods
[$methodName]['params'][$parameterName]['type'] = (string)$reflectionType;
499 $this->methods
[$methodName]['params'][$parameterName]['nullable'] = $reflectionType->allowsNull();
502 if (($parameterClass = $reflectionParameter->getClass()) instanceof \ReflectionClass
) {
503 $this->methods
[$methodName]['params'][$parameterName]['class'] = $parameterClass->getName();
504 $this->methods
[$methodName]['params'][$parameterName]['type'] = ltrim($parameterClass->getName(), '\\');
506 $methodTagsAndValues = $this->methods
[$methodName]['tags'];
507 if (isset($methodTagsAndValues['param'][$parameterPosition])) {
508 $explodedParameters = explode(' ', $methodTagsAndValues['param'][$parameterPosition]);
509 if (count($explodedParameters) >= 2) {
510 if (TypeHandlingUtility
::isSimpleType($explodedParameters[0])) {
511 // ensure that short names of simple types are resolved correctly to the long form
512 // this is important for all kinds of type checks later on
513 $typeInfo = TypeHandlingUtility
::parseType($explodedParameters[0]);
515 $this->methods
[$methodName]['params'][$parameterName]['type'] = ltrim($typeInfo['type'], '\\');
517 $this->methods
[$methodName]['params'][$parameterName]['type'] = ltrim($explodedParameters[0], '\\');
524 if ($reflectionParameter->getClass() instanceof \ReflectionClass
525 && ($reflectionMethod->isConstructor() ||
$this->hasInjectMethodName($reflectionMethod))
527 $this->methods
[$methodName]['params'][$parameterName]['dependency'] = $reflectionParameter->getClass()->getName();
530 // Extbase Validation
531 if (isset($argumentValidators[$parameterName])) {
532 if ($this->methods
[$methodName]['params'][$parameterName]['type'] === null) {
533 throw new InvalidTypeHintException(
534 'Missing type information for parameter "$' . $parameterName . '" in ' . $this->className
. '->' . $methodName . '(): Either use an @param annotation or use a type hint.',
539 $this->methods
[$methodName]['params'][$parameterName]['validators'] = $argumentValidators[$parameterName];
540 unset($argumentValidators[$parameterName]);
544 // Extbase Validation
545 foreach ($argumentValidators as $parameterName => $validators) {
546 $validatorNames = array_column($validators, 'name');
548 throw new InvalidValidationConfigurationException(
549 'Invalid validate annotation in ' . $this->className
. '->' . $methodName . '(): The following validators have been defined for missing param "$' . $parameterName . '": ' . implode(', ', $validatorNames),
555 $this->methods
[$methodName]['injectMethod'] = false;
556 if ($this->hasInjectMethodName($reflectionMethod)
557 && count($this->methods
[$methodName]['params']) === 1
558 && reset($this->methods
[$methodName]['params'])['dependency'] !== null
560 $this->methods
[$methodName]['injectMethod'] = true;
561 $this->injectMethods
[] = $methodName;
567 * Returns the class name this schema is referring to
569 * @return string The class name
571 public function getClassName(): string
573 return $this->className
;
577 * Adds (defines) a specific property and its type.
579 * @param string $name Name of the property
580 * @param string $type Type of the property
581 * @param bool $lazy Whether the property should be lazy-loaded when reconstituting
582 * @param string $cascade Strategy to cascade the object graph.
583 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
585 public function addProperty($name, $type, $lazy = false, $cascade = '')
588 'This method will be removed in TYPO3 v10.0, properties will be automatically added on ClassSchema construction.',
591 $type = TypeHandlingUtility
::parseType($type);
592 $this->properties
[$name] = [
593 'type' => $type['type'],
594 'elementType' => $type['elementType'],
596 'cascade' => $cascade
601 * Returns the given property defined in this schema. Check with
602 * hasProperty($propertyName) before!
604 * @param string $propertyName
607 public function getProperty($propertyName)
609 return isset($this->properties
[$propertyName]) && is_array($this->properties
[$propertyName])
610 ?
$this->properties
[$propertyName]
615 * Returns all properties defined in this schema
619 public function getProperties()
621 return $this->properties
;
625 * Sets the model type of the class this schema is referring to.
627 * @param int $modelType The model type, one of the MODELTYPE_* constants.
628 * @throws \InvalidArgumentException
629 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
631 public function setModelType($modelType)
634 'This method will be removed in TYPO3 v10.0, modelType will be automatically set on ClassSchema construction.',
637 if ($modelType < self
::MODELTYPE_ENTITY ||
$modelType > self
::MODELTYPE_VALUEOBJECT
) {
638 throw new \
InvalidArgumentException('"' . $modelType . '" is an invalid model type.', 1212519195);
640 $this->modelType
= $modelType;
644 * Returns the model type of the class this schema is referring to.
646 * @return int The model type, one of the MODELTYPE_* constants.
647 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
649 public function getModelType()
652 'This method will be removed in TYPO3 v10.0.',
655 return $this->modelType
;
659 * Marks the class if it is root of an aggregate and therefore accessible
660 * through a repository - or not.
662 * @param bool $isRoot TRUE if it is the root of an aggregate
664 public function setAggregateRoot($isRoot)
666 $this->aggregateRoot
= $isRoot;
670 * Whether the class is an aggregate root and therefore accessible through
673 * @return bool TRUE if it is managed
675 public function isAggregateRoot(): bool
677 return $this->aggregateRoot
;
681 * If the class schema has a certain property.
683 * @param string $propertyName Name of the property
686 public function hasProperty($propertyName): bool
688 return array_key_exists($propertyName, $this->properties
);
692 * Sets the property marked as uuid of an object with @uuid
694 * @param string $propertyName
695 * @throws \InvalidArgumentException
696 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
698 public function setUuidPropertyName($propertyName)
701 'Tagging properties with @uuid is deprecated and will be removed in TYPO3 v10.0.',
704 if (!array_key_exists($propertyName, $this->properties
)) {
705 throw new \
InvalidArgumentException('Property "' . $propertyName . '" must be added to the class schema before it can be marked as UUID property.', 1233863842);
707 $this->uuidPropertyName
= $propertyName;
711 * Gets the name of the property marked as uuid of an object
714 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
716 public function getUuidPropertyName()
719 'Tagging properties with @uuid is deprecated and will be removed in TYPO3 v10.0.',
722 return $this->uuidPropertyName
;
726 * Marks the given property as one of properties forming the identity
727 * of an object. The property must already be registered in the class
730 * @param string $propertyName
731 * @throws \InvalidArgumentException
732 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
734 public function markAsIdentityProperty($propertyName)
737 'Tagging properties with @identity is deprecated and will be removed in TYPO3 v10.0.',
740 if (!array_key_exists($propertyName, $this->properties
)) {
741 throw new \
InvalidArgumentException('Property "' . $propertyName . '" must be added to the class schema before it can be marked as identity property.', 1233775407);
743 if ($this->properties
[$propertyName]['annotations']['lazy'] === true) {
744 throw new \
InvalidArgumentException('Property "' . $propertyName . '" must not be makred for lazy loading to be marked as identity property.', 1239896904);
746 $this->identityProperties
[$propertyName] = $this->properties
[$propertyName]['type'];
750 * Gets the properties (names and types) forming the identity of an object.
753 * @see markAsIdentityProperty()
754 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.
756 public function getIdentityProperties()
759 'Tagging properties with @identity is deprecated and will be removed in TYPO3 v10.0.',
762 return $this->identityProperties
;
768 public function hasConstructor(): bool
770 return isset($this->methods
['__construct']);
774 * @param string $name
777 public function getMethod(string $name): array
779 return $this->methods
[$name] ??
[];
785 public function getMethods(): array
787 return $this->methods
;
791 * @param \ReflectionMethod $reflectionMethod
794 protected function hasInjectMethodName(\ReflectionMethod
$reflectionMethod): bool
796 $methodName = $reflectionMethod->getName();
797 if ($methodName === 'injectSettings' ||
!$reflectionMethod->isPublic()) {
802 strpos($reflectionMethod->getName(), 'inject') === 0
814 public function isModel(): bool
816 return $this->isEntity() ||
$this->isValueObject();
823 public function isEntity(): bool
825 return $this->modelType
=== static::MODELTYPE_ENTITY
;
832 public function isValueObject(): bool
834 return $this->modelType
=== static::MODELTYPE_VALUEOBJECT
;
840 public function isSingleton(): bool
842 return $this->isSingleton
;
846 * @param string $methodName
849 public function hasMethod(string $methodName): bool
851 return isset($this->methods
[$methodName]);
857 public function getTags(): array
865 public function hasInjectProperties(): bool
867 return count($this->injectProperties
) > 0;
873 public function hasInjectMethods(): bool
875 return count($this->injectMethods
) > 0;
881 public function getInjectMethods(): array
884 foreach ($this->injectMethods
as $injectMethodName) {
885 $injectMethods[$injectMethodName] = reset($this->methods
[$injectMethodName]['params'])['dependency'];
888 return $injectMethods;
894 public function getInjectProperties(): array
896 $injectProperties = [];
897 foreach ($this->injectProperties
as $injectPropertyName) {
898 $injectProperties[$injectPropertyName] = $this->properties
[$injectPropertyName]['annotations']['dependency'];
901 return $injectProperties;
907 public function getConstructorArguments(): array
909 if (!$this->hasConstructor()) {
913 return $this->methods
['__construct']['params'];