Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Block.php
Go to the documentation of this file.
1 <?php
7 
12 
17 class Block implements Layout\GeneratorInterface
18 {
22  const TYPE = 'block';
23 
27  protected $blockFactory;
28 
33 
37  protected $eventManager;
38 
42  protected $logger;
43 
47  protected $scopeConfig;
48 
52  protected $scopeResolver;
53 
57  protected $appState;
58 
63 
69  private $defaultClass;
70 
82  public function __construct(
84  \Magento\Framework\Data\Argument\InterpreterInterface $argumentInterpreter,
86  \Psr\Log\LoggerInterface $logger,
89  \Magento\Framework\View\Element\ExceptionHandlerBlockFactory $exceptionHandlerBlockFactory,
91  $defaultClass = Template::class
92  ) {
93  $this->blockFactory = $blockFactory;
94  $this->argumentInterpreter = $argumentInterpreter;
95  $this->eventManager = $eventManager;
96  $this->logger = $logger;
97  $this->scopeConfig = $scopeConfig;
98  $this->scopeResolver = $scopeResolver;
99  $this->exceptionHandlerBlockFactory = $exceptionHandlerBlockFactory;
100  $this->appState = $appState;
101  $this->defaultClass = $defaultClass;
102  }
103 
109  public function getType()
110  {
111  return self::TYPE;
112  }
113 
122  public function process(Layout\Reader\Context $readerContext, Layout\Generator\Context $generatorContext)
123  {
124  $scheduledStructure = $readerContext->getScheduledStructure();
125  $layout = $generatorContext->getLayout();
126  $structure = $generatorContext->getStructure();
128  $blocks = [];
129  $blockActions = [];
130  // Instantiate blocks and collect all actions data
131  foreach ($scheduledStructure->getElements() as $elementName => $element) {
132  list($type, $data) = $element;
133  if ($type === self::TYPE) {
134  try {
135  $block = $this->generateBlock($scheduledStructure, $structure, $elementName);
136  $blocks[$elementName] = $block;
137  $layout->setBlock($elementName, $block);
138  if (!empty($data['actions'])) {
139  $blockActions[$elementName] = $data['actions'];
140  }
141  } catch (\Exception $e) {
142  $this->handleRenderException($e);
143  unset($blocks[$elementName]);
144  }
145  }
146  }
147  // Set layout instance to all generated block (trigger _prepareLayout method)
148  foreach ($blocks as $elementName => $block) {
149  try {
150  $block->setLayout($layout);
151  $this->eventManager->dispatch('core_layout_block_create_after', ['block' => $block]);
152  } catch (\Exception $e) {
153  $this->handleRenderException($e);
154  $layout->setBlock(
155  $elementName,
156  $this->exceptionHandlerBlockFactory->create(['blockName' => $elementName])
157  );
158  unset($blockActions[$elementName]);
159  }
160  $scheduledStructure->unsetElement($elementName);
161  }
162  // Run all actions after layout initialization
163  foreach ($blockActions as $elementName => $actions) {
164  try {
165  foreach ($actions as $action) {
166  list($methodName, $actionArguments, $configPath, $scopeType) = $action;
167  if (empty($configPath)
168  || $this->scopeConfig->isSetFlag($configPath, $scopeType, $this->scopeResolver->getScope())
169  ) {
170  $this->generateAction($blocks[$elementName], $methodName, $actionArguments);
171  }
172  }
173  } catch (\Exception $e) {
174  $this->handleRenderException($e);
175  $layout->setBlock(
176  $elementName,
177  $this->exceptionHandlerBlockFactory->create(['blockName' => $elementName])
178  );
179  }
180  }
181  return $this;
182  }
183 
191  protected function handleRenderException(\Exception $cause)
192  {
193  if ($this->appState->getMode() === State::MODE_DEVELOPER) {
194  throw $cause;
195  }
196  $message = ($cause instanceof LocalizedException) ? $cause->getLogMessage() : $cause->getMessage();
197  $this->logger->critical($message);
198  }
199 
208  protected function generateBlock(
209  Layout\ScheduledStructure $scheduledStructure,
212  ) {
213  list(, $data) = $scheduledStructure->getElement($elementName);
214  $attributes = $data['attributes'];
215 
216  if (!empty($attributes['group'])) {
217  $structure->addToParentGroup($elementName, $attributes['group']);
218  }
219  if (!empty($attributes['display'])) {
220  $structure->setAttribute($elementName, 'display', $attributes['display']);
221  }
222 
223  // create block
224  $className = isset($attributes['class']) && !empty($attributes['class']) ?
225  $attributes['class'] : $this->defaultClass;
226  $block = $this->createBlock($className, $elementName, [
227  'data' => $this->evaluateArguments($data['arguments'])
228  ]);
229  if (!empty($attributes['template'])) {
230  $block->setTemplate($attributes['template']);
231  }
232  if (!empty($attributes['ttl'])) {
233  $ttl = (int)$attributes['ttl'];
234  $block->setTtl($ttl);
235  }
236  return $block;
237  }
238 
247  public function createBlock($block, $name, array $arguments = [])
248  {
250  $block->setType(get_class($block));
251  $block->setNameInLayout($name);
252  $block->addData(isset($arguments['data']) ? $arguments['data'] : []);
253  return $block;
254  }
255 
264  protected function getBlockInstance($block, array $arguments = [])
265  {
266  $e = null;
267  if ($block && is_string($block)) {
268  try {
269  $block = $this->blockFactory->createBlock($block, $arguments);
270  } catch (\ReflectionException $e) {
271  $this->logger->critical($e->getMessage());
272  }
273  }
274  if (!$block instanceof \Magento\Framework\View\Element\AbstractBlock) {
275  throw new \Magento\Framework\Exception\LocalizedException(
276  new \Magento\Framework\Phrase(
277  'Invalid block type: %1',
278  [is_object($block) ? get_class($block) : (string) $block]
279  ),
280  $e
281  );
282  }
283  return $block;
284  }
285 
294  protected function generateAction($block, $methodName, $actionArguments)
295  {
296  $profilerKey = 'BLOCK_ACTION:' . $block->getNameInLayout() . '>' . $methodName;
297  \Magento\Framework\Profiler::start($profilerKey);
298  $args = $this->evaluateArguments($actionArguments);
299  call_user_func_array([$block, $methodName], $args);
300  \Magento\Framework\Profiler::stop($profilerKey);
301  }
302 
309  protected function evaluateArguments(array $arguments)
310  {
311  $result = [];
312  foreach ($arguments as $argumentName => $argumentData) {
313  if (!isset($argumentData[Dom::TYPE_ATTRIBUTE])) {
314  $result[$argumentName] = $argumentData;
315  continue;
316  }
317  $result[$argumentName] = $this->argumentInterpreter->evaluate($argumentData);
318  }
319  return $result;
320  }
321 }
getBlockInstance($block, array $arguments=[])
Definition: Block.php:264
$message
$block
Definition: block.php:8
$type
Definition: item.phtml:13
generateAction($block, $methodName, $actionArguments)
Definition: Block.php:294
generateBlock(Layout\ScheduledStructure $scheduledStructure, Layout\Data\Structure $structure, $elementName)
Definition: Block.php:208
$attributes
Definition: matrix.phtml:13
$arguments
process(Reader\Context $readerContext, Generator\Context $generatorContext)
__construct(\Magento\Framework\View\Element\BlockFactory $blockFactory, \Magento\Framework\Data\Argument\InterpreterInterface $argumentInterpreter, \Magento\Framework\Event\ManagerInterface $eventManager, \Psr\Log\LoggerInterface $logger, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\App\ScopeResolverInterface $scopeResolver, \Magento\Framework\View\Element\ExceptionHandlerBlockFactory $exceptionHandlerBlockFactory, State $appState, $defaultClass=Template::class)
Definition: Block.php:82
createBlock($block, $name, array $arguments=[])
Definition: Block.php:247
$elementName
Definition: gallery.phtml:10
if($currentSelectedMethod==$_code) $className
Definition: form.phtml:31
if(!isset($_GET['name'])) $name
Definition: log.php:14
$element
Definition: element.phtml:12