Chris@0: getNamespaceName(); Chris@0: } Chris@0: else { Chris@0: $proxy_class_name = $this->buildProxyClassName($class_name); Chris@0: $proxy_namespace = $this->buildProxyNamespace($class_name); Chris@0: $proxy_class_shortname = str_replace($proxy_namespace . '\\', '', $proxy_class_name); Chris@0: } Chris@0: Chris@0: $output = ''; Chris@0: $class_documentation = <<<'EOS' Chris@0: Chris@0: namespace {{ namespace }}{ Chris@0: Chris@0: /** Chris@0: * Provides a proxy class for \{{ class_name }}. Chris@0: * Chris@0: * @see \Drupal\Component\ProxyBuilder Chris@0: */ Chris@0: Chris@0: EOS; Chris@0: $class_start = ' class {{ proxy_class_shortname }}'; Chris@0: Chris@0: // For cases in which the implemented interface is a child of another Chris@0: // interface, getInterfaceNames() also returns the parent. This causes a Chris@0: // PHP error. Chris@0: // In order to avoid that, check for each interface, whether one of its Chris@0: // parents is also in the list and exclude it. Chris@0: if ($interfaces = $reflection->getInterfaces()) { Chris@0: foreach ($interfaces as $interface_name => $interface) { Chris@0: // Exclude all parents from the list of implemented interfaces of the Chris@0: // class. Chris@0: if ($parent_interfaces = $interface->getInterfaceNames()) { Chris@0: foreach ($parent_interfaces as $parent_interface) { Chris@0: unset($interfaces[$parent_interface]); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: $interface_names = []; Chris@0: foreach ($interfaces as $interface) { Chris@0: $interface_names[] = '\\' . $interface->getName(); Chris@0: } Chris@0: $class_start .= ' implements ' . implode(', ', $interface_names); Chris@0: } Chris@0: Chris@0: $output .= $this->buildUseStatements(); Chris@0: Chris@0: // The actual class; Chris@0: $properties = <<<'EOS' Chris@0: /** Chris@0: * The id of the original proxied service. Chris@0: * Chris@0: * @var string Chris@0: */ Chris@0: protected $drupalProxyOriginalServiceId; Chris@0: Chris@0: /** Chris@0: * The real proxied service, after it was lazy loaded. Chris@0: * Chris@0: * @var \{{ class_name }} Chris@0: */ Chris@0: protected $service; Chris@0: Chris@0: /** Chris@0: * The service container. Chris@0: * Chris@0: * @var \Symfony\Component\DependencyInjection\ContainerInterface Chris@0: */ Chris@0: protected $container; Chris@0: Chris@0: Chris@0: EOS; Chris@0: Chris@0: $output .= $properties; Chris@0: Chris@0: // Add all the methods. Chris@0: $methods = []; Chris@0: $methods[] = $this->buildConstructorMethod(); Chris@0: $methods[] = $this->buildLazyLoadItselfMethod(); Chris@0: Chris@0: // Add all the methods of the proxied service. Chris@0: $reflection_methods = $reflection->getMethods(); Chris@0: Chris@0: foreach ($reflection_methods as $method) { Chris@0: if ($method->getName() === '__construct') { Chris@0: continue; Chris@0: } Chris@0: Chris@0: if ($method->isPublic()) { Chris@0: $methods[] = $this->buildMethod($method) . "\n"; Chris@0: } Chris@0: } Chris@0: Chris@0: $output .= implode("\n", $methods); Chris@0: Chris@0: // Indent the output. Chris@0: $output = implode("\n", array_map(function ($value) { Chris@0: if ($value === '') { Chris@0: return $value; Chris@0: } Chris@0: return " $value"; Chris@0: }, explode("\n", $output))); Chris@0: Chris@0: $final_output = $class_documentation . $class_start . "\n {\n\n" . $output . "\n }\n\n}\n"; Chris@0: Chris@0: $final_output = str_replace('{{ class_name }}', $class_name, $final_output); Chris@0: $final_output = str_replace('{{ namespace }}', $proxy_namespace ? $proxy_namespace . ' ' : '', $final_output); Chris@0: $final_output = str_replace('{{ proxy_class_shortname }}', $proxy_class_shortname, $final_output); Chris@0: Chris@0: return $final_output; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Generates the string for the method which loads the actual service. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function buildLazyLoadItselfMethod() { Chris@0: $output = <<<'EOS' Chris@0: /** Chris@0: * Lazy loads the real service from the container. Chris@0: * Chris@0: * @return object Chris@0: * Returns the constructed real service. Chris@0: */ Chris@0: protected function lazyLoadItself() Chris@0: { Chris@0: if (!isset($this->service)) { Chris@0: $this->service = $this->container->get($this->drupalProxyOriginalServiceId); Chris@0: } Chris@0: Chris@0: return $this->service; Chris@0: } Chris@0: Chris@0: EOS; Chris@0: Chris@0: return $output; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Generates the string representation of a single method: signature, body. Chris@0: * Chris@0: * @param \ReflectionMethod $reflection_method Chris@0: * A reflection method for the method. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function buildMethod(\ReflectionMethod $reflection_method) { Chris@0: Chris@0: $parameters = []; Chris@0: foreach ($reflection_method->getParameters() as $parameter) { Chris@0: $parameters[] = $this->buildParameter($parameter); Chris@0: } Chris@0: Chris@0: $function_name = $reflection_method->getName(); Chris@0: Chris@0: $reference = ''; Chris@0: if ($reflection_method->returnsReference()) { Chris@0: $reference = '&'; Chris@0: } Chris@0: Chris@0: $signature_line = <<<'EOS' Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: Chris@0: EOS; Chris@0: Chris@0: if ($reflection_method->isStatic()) { Chris@0: $signature_line .= 'public static function ' . $reference . $function_name . '('; Chris@0: } Chris@0: else { Chris@0: $signature_line .= 'public function ' . $reference . $function_name . '('; Chris@0: } Chris@0: Chris@0: $signature_line .= implode(', ', $parameters); Chris@0: $signature_line .= ')'; Chris@0: Chris@0: $output = $signature_line . "\n{\n"; Chris@0: Chris@0: $output .= $this->buildMethodBody($reflection_method); Chris@0: Chris@0: $output .= "\n" . '}'; Chris@0: return $output; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Builds a string for a single parameter of a method. Chris@0: * Chris@0: * @param \ReflectionParameter $parameter Chris@0: * A reflection object of the parameter. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function buildParameter(\ReflectionParameter $parameter) { Chris@0: $parameter_string = ''; Chris@0: Chris@0: if ($parameter->isArray()) { Chris@0: $parameter_string .= 'array '; Chris@0: } Chris@0: elseif ($parameter->isCallable()) { Chris@0: $parameter_string .= 'callable '; Chris@0: } Chris@0: elseif ($class = $parameter->getClass()) { Chris@0: $parameter_string .= '\\' . $class->getName() . ' '; Chris@0: } Chris@0: Chris@0: if ($parameter->isPassedByReference()) { Chris@0: $parameter_string .= '&'; Chris@0: } Chris@0: Chris@0: $parameter_string .= '$' . $parameter->getName(); Chris@0: Chris@0: if ($parameter->isDefaultValueAvailable()) { Chris@0: $parameter_string .= ' = '; Chris@0: $parameter_string .= var_export($parameter->getDefaultValue(), TRUE); Chris@0: } Chris@0: Chris@0: return $parameter_string; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Builds the body of a wrapped method. Chris@0: * Chris@0: * @param \ReflectionMethod $reflection_method Chris@0: * A reflection method for the method. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function buildMethodBody(\ReflectionMethod $reflection_method) { Chris@0: $output = ''; Chris@0: Chris@0: $function_name = $reflection_method->getName(); Chris@0: Chris@0: if (!$reflection_method->isStatic()) { Chris@0: $output .= ' return $this->lazyLoadItself()->' . $function_name . '('; Chris@0: } Chris@0: else { Chris@0: $class_name = $reflection_method->getDeclaringClass()->getName(); Chris@0: $output .= " \\$class_name::$function_name("; Chris@0: } Chris@0: Chris@0: // Add parameters; Chris@0: $parameters = []; Chris@0: foreach ($reflection_method->getParameters() as $parameter) { Chris@0: $parameters[] = '$' . $parameter->getName(); Chris@0: } Chris@0: Chris@0: $output .= implode(', ', $parameters) . ');'; Chris@0: Chris@0: return $output; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Builds the constructor used to inject the actual service ID. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function buildConstructorMethod() { Chris@0: $output = <<<'EOS' Chris@0: /** Chris@0: * Constructs a ProxyClass Drupal proxy object. Chris@0: * Chris@0: * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Chris@0: * The container. Chris@0: * @param string $drupal_proxy_original_service_id Chris@0: * The service ID of the original service. Chris@0: */ Chris@0: public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container, $drupal_proxy_original_service_id) Chris@0: { Chris@0: $this->container = $container; Chris@0: $this->drupalProxyOriginalServiceId = $drupal_proxy_original_service_id; Chris@0: } Chris@0: Chris@0: EOS; Chris@0: Chris@0: return $output; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Build the required use statements of the proxy class. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: protected function buildUseStatements() { Chris@0: $output = ''; Chris@0: Chris@0: return $output; Chris@0: } Chris@0: Chris@0: }