![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/framework/Reflection/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Framework\Reflection; use Magento\Framework\Serialize\SerializerInterface; use Laminas\Code\Reflection\ClassReflection; use Laminas\Code\Reflection\MethodReflection; use Laminas\Code\Reflection\ParameterReflection; use Magento\Framework\App\Cache\Type\Reflection as ReflectionCache; /** * Gathers method metadata information. * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class MethodsMap { const SERVICE_METHOD_PARAMS_CACHE_PREFIX = 'service_method_params_'; const SERVICE_INTERFACE_METHODS_CACHE_PREFIX = 'serviceInterfaceMethodsMap'; const BASE_MODEL_CLASS = \Magento\Framework\Model\AbstractExtensibleModel::class; const METHOD_META_NAME = 'name'; const METHOD_META_TYPE = 'type'; const METHOD_META_HAS_DEFAULT_VALUE = 'isDefaultValueAvailable'; const METHOD_META_DEFAULT_VALUE = 'defaultValue'; /** * @var \Magento\Framework\Cache\FrontendInterface */ private $cache; /** * @var TypeProcessor */ private $typeProcessor; /** * @var array */ private $serviceInterfaceMethodsMap = []; /** * @var FieldNamer */ private $fieldNamer; /** * @var \Magento\Framework\Serialize\SerializerInterface */ private $serializer; /** * @var \Magento\Framework\Api\AttributeTypeResolverInterface */ private $attributeTypeResolver; /** * @param \Magento\Framework\Cache\FrontendInterface $cache * @param TypeProcessor $typeProcessor * @param \Magento\Framework\Api\AttributeTypeResolverInterface $typeResolver * @param FieldNamer $fieldNamer */ public function __construct( \Magento\Framework\Cache\FrontendInterface $cache, TypeProcessor $typeProcessor, \Magento\Framework\Api\AttributeTypeResolverInterface $typeResolver, FieldNamer $fieldNamer ) { $this->cache = $cache; $this->typeProcessor = $typeProcessor; $this->attributeTypeResolver = $typeResolver; $this->fieldNamer = $fieldNamer; } /** * Get return type by type name and method name. * * @param string $typeName * @param string $methodName * @return string */ public function getMethodReturnType($typeName, $methodName) { return $this->getMethodsMap($typeName)[$methodName]['type']; } /** * Return service interface or Data interface methods loaded from cache * * @param string $interfaceName * @return array * <pre> * Service methods' reflection data stored in cache as 'methodName' => 'returnType' * ex. * [ * 'create' => '\Magento\Customer\Api\Data\Customer', * 'validatePassword' => 'boolean' * ] * </pre> * @throws \InvalidArgumentException if methods don't have annotation * @throws \ReflectionException for missing DocBock or invalid reflection class */ public function getMethodsMap($interfaceName) { //phpcs:ignore Magento2.Security.InsecureFunction $key = self::SERVICE_INTERFACE_METHODS_CACHE_PREFIX . "-" . md5($interfaceName); if (!isset($this->serviceInterfaceMethodsMap[$key])) { $methodMap = $this->cache->load($key); if ($methodMap) { $this->serviceInterfaceMethodsMap[$key] = $this->getSerializer()->unserialize($methodMap); } else { $methodMap = $this->getMethodMapViaReflection($interfaceName); $this->serviceInterfaceMethodsMap[$key] = $methodMap; $this->cache->save($this->getSerializer()->serialize($this->serviceInterfaceMethodsMap[$key]), $key); } } return $this->serviceInterfaceMethodsMap[$key]; } /** * Retrieve requested service method params metadata. * * @param string $serviceClassName * @param string $serviceMethodName * @return array */ public function getMethodParams($serviceClassName, $serviceMethodName) { $cacheId = self::SERVICE_METHOD_PARAMS_CACHE_PREFIX . hash('md5', $serviceClassName . $serviceMethodName); $params = $this->cache->load($cacheId); if ($params !== false) { return $this->getSerializer()->unserialize($params); } $serviceClass = new ClassReflection($serviceClassName); /** @var MethodReflection $serviceMethod */ $serviceMethod = $serviceClass->getMethod($serviceMethodName); $params = []; /** @var ParameterReflection $paramReflection */ foreach ($serviceMethod->getParameters() as $paramReflection) { $isDefaultValueAvailable = $paramReflection->isDefaultValueAvailable(); $params[] = [ self::METHOD_META_NAME => $paramReflection->getName(), self::METHOD_META_TYPE => $this->typeProcessor->getParamType($paramReflection), self::METHOD_META_HAS_DEFAULT_VALUE => $isDefaultValueAvailable, self::METHOD_META_DEFAULT_VALUE => $isDefaultValueAvailable ? $paramReflection->getDefaultValue() : null ]; } $this->cache->save($this->getSerializer()->serialize($params), $cacheId, [ReflectionCache::CACHE_TAG]); return $params; } /** * Use reflection to load the method information * * @param string $interfaceName * @return array * @throws \ReflectionException for missing DocBock or invalid reflection class * @throws \InvalidArgumentException if methods don't have annotation */ private function getMethodMapViaReflection($interfaceName) { $methodMap = []; $class = new ClassReflection($interfaceName); $baseClassMethods = false; foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { // Include all the methods of classes inheriting from AbstractExtensibleObject. // Ignore all the methods of AbstractExtensibleModel's parent classes if ($method->class === self::BASE_MODEL_CLASS) { $baseClassMethods = true; } elseif ($baseClassMethods) { // ReflectionClass::getMethods() sorts the methods by class (lowest in inheritance tree first) // then by the order they are defined in the class definition break; } if ($this->isSuitableMethod($method)) { $methodMap[$method->getName()] = $this->typeProcessor->getGetterReturnType($method); } } return $methodMap; } /** * Determines if the method is suitable to be used by the processor. * * @param \ReflectionMethod $method * @return bool */ private function isSuitableMethod($method) { $isSuitableMethodType = !($method->isConstructor() || $method->isFinal() || $method->isStatic() || $method->isDestructor()); $isExcludedMagicMethod = strpos($method->getName(), '__') === 0; return $isSuitableMethodType && !$isExcludedMagicMethod; } /** * Determines if the given method's on the given type is suitable for an output data array. * * @param string $type * @param string $methodName * @return bool */ public function isMethodValidForDataField($type, $methodName) { $methods = $this->getMethodsMap($type); if (isset($methods[$methodName])) { $methodMetadata = $methods[$methodName]; // any method with parameter(s) gets ignored because we do not know the type and value of // the parameter(s), so we are not able to process if ($methodMetadata['parameterCount'] > 0) { return false; } return $this->fieldNamer->getFieldNameForMethodName($methodName) !== null; } return false; } /** * If the method has only non-null return types * * @param string $type * @param string $methodName * @return bool */ public function isMethodReturnValueRequired($type, $methodName) { $methods = $this->getMethodsMap($type); return $methods[$methodName]['isRequired']; } /** * Get serializer * * @return \Magento\Framework\Serialize\SerializerInterface * @deprecated 101.0.0 */ private function getSerializer() { if ($this->serializer === null) { $this->serializer = \Magento\Framework\App\ObjectManager::getInstance() ->get(SerializerInterface::class); } return $this->serializer; } }