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