Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Proxy.php
Go to the documentation of this file.
1 <?php
9 
10 class Proxy extends \Magento\Framework\Code\Generator\EntityAbstract
11 {
15  const ENTITY_TYPE = 'proxy';
16 
20  const NON_INTERCEPTABLE_INTERFACE = \Magento\Framework\ObjectManager\NoninterceptableInterface::class;
21 
26  protected function _getDefaultResultClassName($modelClassName)
27  {
28  return $modelClassName . '_' . ucfirst(static::ENTITY_TYPE);
29  }
30 
36  protected function _getClassProperties()
37  {
38  $properties = parent::_getClassProperties();
39 
40  // protected $_instanceName = null;
41  $properties[] = [
42  'name' => '_instanceName',
43  'visibility' => 'protected',
44  'docblock' => [
45  'shortDescription' => 'Proxied instance name',
46  'tags' => [['name' => 'var', 'description' => 'string']],
47  ],
48  ];
49 
50  $properties[] = [
51  'name' => '_subject',
52  'visibility' => 'protected',
53  'docblock' => [
54  'shortDescription' => 'Proxied instance',
55  'tags' => [['name' => 'var', 'description' => $this->getSourceClassName()]],
56  ],
57  ];
58 
59  // protected $_shared = null;
60  $properties[] = [
61  'name' => '_isShared',
62  'visibility' => 'protected',
63  'docblock' => [
64  'shortDescription' => 'Instance shareability flag',
65  'tags' => [['name' => 'var', 'description' => 'bool']],
66  ],
67  ];
68  return $properties;
69  }
70 
76  protected function _getClassMethods()
77  {
78  $construct = $this->_getDefaultConstructorDefinition();
79 
80  // create proxy methods for all non-static and non-final public methods (excluding constructor)
81  $methods = [$construct];
82  $methods[] = [
83  'name' => '__sleep',
84  'body' => 'return [\'_subject\', \'_isShared\', \'_instanceName\'];',
85  'docblock' => ['tags' => [['name' => 'return', 'description' => 'array']]],
86  ];
87  $methods[] = [
88  'name' => '__wakeup',
89  'body' => '$this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();',
90  'docblock' => ['shortDescription' => 'Retrieve ObjectManager from global scope'],
91  ];
92  $methods[] = [
93  'name' => '__clone',
94  'body' => "\$this->_subject = clone \$this->_getSubject();",
95  'docblock' => ['shortDescription' => 'Clone proxied instance'],
96  ];
97 
98  $methods[] = [
99  'name' => '_getSubject',
100  'visibility' => 'protected',
101  'body' => "if (!\$this->_subject) {\n" .
102  " \$this->_subject = true === \$this->_isShared\n" .
103  " ? \$this->_objectManager->get(\$this->_instanceName)\n" .
104  " : \$this->_objectManager->create(\$this->_instanceName);\n" .
105  "}\n" .
106  "return \$this->_subject;",
107  'docblock' => [
108  'shortDescription' => 'Get proxied instance',
109  'tags' => [['name' => 'return', 'description' => $this->getSourceClassName()]],
110  ],
111  ];
112  $reflectionClass = new \ReflectionClass($this->getSourceClassName());
113  $publicMethods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
114  foreach ($publicMethods as $method) {
115  if (!($method->isConstructor() ||
116  $method->isFinal() ||
117  $method->isStatic() ||
118  $method->isDestructor()) && !in_array(
119  $method->getName(),
120  ['__sleep', '__wakeup', '__clone']
121  )
122  ) {
123  $methods[] = $this->_getMethodInfo($method);
124  }
125  }
126 
127  return $methods;
128  }
129 
133  protected function _generateCode()
134  {
135  $typeName = $this->getSourceClassName();
136  $reflection = new \ReflectionClass($typeName);
137 
138  if ($reflection->isInterface()) {
139  $this->_classGenerator->setImplementedInterfaces([$typeName, '\\' . self::NON_INTERCEPTABLE_INTERFACE]);
140  } else {
141  $this->_classGenerator->setExtendedClass($typeName);
142  $this->_classGenerator->setImplementedInterfaces(['\\' . self::NON_INTERCEPTABLE_INTERFACE]);
143  }
144  return parent::_generateCode();
145  }
146 
153  protected function _getMethodInfo(\ReflectionMethod $method)
154  {
155  $parameterNames = [];
156  $parameters = [];
157  foreach ($method->getParameters() as $parameter) {
158  $name = $parameter->isVariadic() ? '... $' . $parameter->getName() : '$' . $parameter->getName();
159  $parameterNames[] = $name;
160  $parameters[] = $this->_getMethodParameterInfo($parameter);
161  }
162 
163  $returnType = $method->getReturnType();
164  $returnTypeValue = $returnType
165  ? ($returnType->allowsNull() ? '?' : '') .$returnType->getName()
166  : null;
167  $methodInfo = [
168  'name' => $method->getName(),
169  'parameters' => $parameters,
170  'body' => $this->_getMethodBody(
171  $method->getName(),
172  $parameterNames,
173  $returnTypeValue === 'void'
174  ),
175  'docblock' => ['shortDescription' => '{@inheritdoc}'],
176  'returntype' => $returnTypeValue,
177  ];
178 
179  return $methodInfo;
180  }
181 
187  protected function _getDefaultConstructorDefinition()
188  {
189  /*
190  * public function __construct(
191  * \Magento\Framework\ObjectManagerInterface $objectManager,
192  * $instanceName,
193  * $shared = false
194  * )
195  */
196  return [
197  'name' => '__construct',
198  'parameters' => [
199  ['name' => 'objectManager', 'type' => '\\' . \Magento\Framework\ObjectManagerInterface::class],
200  ['name' => 'instanceName', 'defaultValue' => $this->getSourceClassName()],
201  ['name' => 'shared', 'defaultValue' => true],
202  ],
203  'body' => "\$this->_objectManager = \$objectManager;" .
204  "\n\$this->_instanceName = \$instanceName;" .
205  "\n\$this->_isShared = \$shared;",
206  'docblock' => [
207  'shortDescription' => ucfirst(static::ENTITY_TYPE) . ' constructor',
208  'tags' => [
209  [
210  'name' => 'param',
211  'description' => '\Magento\Framework\ObjectManagerInterface $objectManager',
212  ],
213  ['name' => 'param', 'description' => 'string $instanceName'],
214  ['name' => 'param', 'description' => 'bool $shared'],
215  ],
216  ]
217  ];
218  }
219 
228  protected function _getMethodBody(
229  $name,
230  array $parameters = [],
231  bool $withoutReturn = false
232  ) {
233  if (count($parameters) == 0) {
234  $methodCall = sprintf('%s()', $name);
235  } else {
236  $methodCall = sprintf('%s(%s)', $name, implode(', ', $parameters));
237  }
238 
239  return ($withoutReturn ? '' : 'return ')
240  .'$this->_getSubject()->' . $methodCall . ';';
241  }
242 
246  protected function _validateData()
247  {
248  $result = parent::_validateData();
249  if ($result) {
250  $sourceClassName = $this->getSourceClassName();
251  $resultClassName = $this->_getResultClassName();
252 
253  if ($resultClassName !== $sourceClassName . '\\Proxy') {
254  $this->_addError(
255  'Invalid Proxy class name [' . $resultClassName . ']. Use ' . $sourceClassName . '\\Proxy'
256  );
257  $result = false;
258  }
259  }
260  return $result;
261  }
262 }
$methods
Definition: billing.phtml:71
$reflectionClass
Definition: categories.php:25
$method
Definition: info.phtml:13
_getMethodBody( $name, array $parameters=[], bool $withoutReturn=false)
Definition: Proxy.php:228
$properties
Definition: categories.php:26
_getMethodParameterInfo(\ReflectionParameter $parameter)
if(!isset($_GET['name'])) $name
Definition: log.php:14