Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Instance.php
Go to the documentation of this file.
1 <?php
7 
10 
29 {
30  const SPECIFIC_ENTITIES = 'specific';
31 
32  const ALL_ENTITIES = 'all';
33 
34  const DEFAULT_LAYOUT_HANDLE = 'default';
35 
36  const PRODUCT_LAYOUT_HANDLE = 'catalog_product_view';
37 
42 
43  const SINGLE_PRODUCT_LAYOUT_HANDLE = 'catalog_product_view_id_{{ID}}';
44 
45  const PRODUCT_TYPE_LAYOUT_HANDLE = 'catalog_product_view_type_{{TYPE}}';
46 
47  const ANCHOR_CATEGORY_LAYOUT_HANDLE = 'catalog_category_view_type_layered';
48 
49  const NOTANCHOR_CATEGORY_LAYOUT_HANDLE = 'catalog_category_view_type_default';
50 
51  const SINGLE_CATEGORY_LAYOUT_HANDLE = 'catalog_category_view_id_{{ID}}';
52 
56  protected $_layoutHandles = [];
57 
62 
66  protected $_widgetConfigXml = null;
67 
73  protected $_eventPrefix = 'widget_widget_instance';
74 
78  protected $_viewFileSystem;
79 
83  protected $_widgetModel;
84 
89 
93  protected $_cacheTypeList;
94 
99 
104  protected $_productType;
105 
110  protected $_reader;
111 
115  protected $_escaper;
116 
120  protected $mathRandom;
121 
125  protected $_directory;
126 
130  protected $conditionsHelper;
131 
135  private $serializer;
136 
157  public function __construct(
158  \Magento\Framework\Model\Context $context,
159  \Magento\Framework\Registry $registry,
160  \Magento\Framework\Escaper $escaper,
161  \Magento\Framework\View\FileSystem $viewFileSystem,
162  \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
163  \Magento\Catalog\Model\Product\Type $productType,
164  \Magento\Widget\Model\Config\Reader $reader,
165  \Magento\Widget\Model\Widget $widgetModel,
166  \Magento\Widget\Model\NamespaceResolver $namespaceResolver,
167  \Magento\Framework\Math\Random $mathRandom,
168  \Magento\Framework\Filesystem $filesystem,
169  \Magento\Widget\Helper\Conditions $conditionsHelper,
170  \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
171  \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
172  array $relatedCacheTypes = [],
173  array $data = [],
174  Json $serializer = null
175  ) {
176  $this->_escaper = $escaper;
177  $this->_viewFileSystem = $viewFileSystem;
178  $this->_cacheTypeList = $cacheTypeList;
179  $this->_relatedCacheTypes = $relatedCacheTypes;
180  $this->_productType = $productType;
181  $this->_reader = $reader;
182  $this->_widgetModel = $widgetModel;
183  $this->mathRandom = $mathRandom;
184  $this->conditionsHelper = $conditionsHelper;
185  $this->_directory = $filesystem->getDirectoryRead(DirectoryList::ROOT);
186  $this->_namespaceResolver = $namespaceResolver;
187  $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Json::class);
188  parent::__construct($context, $registry, $resource, $resourceCollection, $data);
189  }
190 
196  protected function _construct()
197  {
198  parent::_construct();
199  $this->_init(\Magento\Widget\Model\ResourceModel\Widget\Instance::class);
200  $this->_layoutHandles = [
201  'anchor_categories' => self::ANCHOR_CATEGORY_LAYOUT_HANDLE,
202  'notanchor_categories' => self::NOTANCHOR_CATEGORY_LAYOUT_HANDLE,
203  'all_products' => self::PRODUCT_LAYOUT_HANDLE,
204  'all_pages' => self::DEFAULT_LAYOUT_HANDLE,
205  ];
206  $this->_specificEntitiesLayoutHandles = [
207  'anchor_categories' => self::SINGLE_CATEGORY_LAYOUT_HANDLE,
208  'notanchor_categories' => self::SINGLE_CATEGORY_LAYOUT_HANDLE,
209  'all_products' => self::SINGLE_PRODUCT_LAYOUT_HANDLE,
210  ];
211  foreach (array_keys($this->_productType->getTypes()) as $typeId) {
212  $layoutHandle = str_replace('{{TYPE}}', $typeId, self::PRODUCT_TYPE_LAYOUT_HANDLE);
213  $this->_layoutHandles[$typeId . '_products'] = $layoutHandle;
214  $this->_specificEntitiesLayoutHandles[$typeId . '_products'] = self::SINGLE_PRODUCT_LAYOUT_HANDLE;
215  }
216  }
217 
225  public function beforeSave()
226  {
227  $pageGroupIds = [];
228  $tmpPageGroups = [];
229  $pageGroups = $this->getData('page_groups');
230  if ($pageGroups) {
231  foreach ($pageGroups as $pageGroup) {
232  if (isset($pageGroup[$pageGroup['page_group']])) {
233  $pageGroupData = $pageGroup[$pageGroup['page_group']];
234  if ($pageGroupData['page_id']) {
235  $pageGroupIds[] = $pageGroupData['page_id'];
236  }
237  if (in_array($pageGroup['page_group'], ['pages', 'page_layouts'])) {
238  $layoutHandle = $pageGroupData['layout_handle'];
239  } else {
240  $layoutHandle = $this->_layoutHandles[$pageGroup['page_group']];
241  }
242  if (!isset($pageGroupData['template'])) {
243  $pageGroupData['template'] = '';
244  }
245  $tmpPageGroup = [
246  'page_id' => $pageGroupData['page_id'],
247  'group' => $pageGroup['page_group'],
248  'layout_handle' => $layoutHandle,
249  'for' => $pageGroupData['for'],
250  'block_reference' => $pageGroupData['block'],
251  'entities' => '',
252  'layout_handle_updates' => [$layoutHandle],
253  'template' => $pageGroupData['template'] ? $pageGroupData['template'] : '',
254  ];
255  if ($pageGroupData['for'] == self::SPECIFIC_ENTITIES) {
256  $layoutHandleUpdates = [];
257  foreach (explode(',', $pageGroupData['entities']) as $entity) {
258  $layoutHandleUpdates[] = str_replace(
259  '{{ID}}',
260  $entity,
261  $this->_specificEntitiesLayoutHandles[$pageGroup['page_group']]
262  );
263  }
264  $tmpPageGroup['entities'] = $pageGroupData['entities'];
265  $tmpPageGroup['layout_handle_updates'] = $layoutHandleUpdates;
266  }
267  $tmpPageGroups[] = $tmpPageGroup;
268  }
269  }
270  }
271  if (is_array($this->getData('store_ids'))) {
272  $this->setData('store_ids', implode(',', $this->getData('store_ids')));
273  }
274  $parameters = $this->getData('widget_parameters');
275  if (is_array($parameters)) {
276  if (array_key_exists('show_pager', $parameters) && !array_key_exists('page_var_name', $parameters)) {
277  $parameters['page_var_name'] = 'p' . $this->mathRandom->getRandomString(
278  5,
279  \Magento\Framework\Math\Random::CHARS_LOWERS
280  );
281  }
282 
283  $this->setData('widget_parameters', $this->serializer->serialize($parameters));
284  }
285  $this->setData('page_groups', $tmpPageGroups);
286  $this->setData('page_group_ids', $pageGroupIds);
287 
288  return parent::beforeSave();
289  }
290 
296  public function validate()
297  {
298  if ($this->isCompleteToCreate()) {
299  return true;
300  }
301  return __('We cannot create the widget instance because it is missing required information.');
302  }
303 
309  public function isCompleteToCreate()
310  {
311  return $this->getType() && $this->getThemeId();
312  }
313 
319  public function getCode()
320  {
321  $code = $this->_getData('instance_code');
322  if ($code == null) {
323  $code = $this->getWidgetReference('type', $this->getType(), 'code');
324  $this->setData('instance_code', $code);
325  }
326  return $code;
327  }
328 
337  public function setCode($code)
338  {
339  $this->setData('instance_code', $code);
340  return $this;
341  }
342 
350  public function setType($type)
351  {
352  $this->setData('instance_type', $type);
353  return $this;
354  }
355 
362  public function getType()
363  {
364  return $this->_getData('instance_type');
365  }
366 
373  public function getArea()
374  {
375  //TODO Shouldn't we get "area" from theme model which we can load using "theme_id"?
376  if (!$this->_getData('area')) {
377  return \Magento\Framework\View\DesignInterface::DEFAULT_AREA;
378  }
379  return $this->_getData('area');
380  }
381 
388  public function getStoreIds()
389  {
390  if (is_string($this->getData('store_ids'))) {
391  return explode(',', $this->getData('store_ids'));
392  }
393  return $this->getData('store_ids');
394  }
395 
402  public function getWidgetParameters()
403  {
404  if (is_string($this->getData('widget_parameters'))) {
405  return $this->serializer->unserialize($this->getData('widget_parameters'));
406  } elseif (null === $this->getData('widget_parameters')) {
407  return [];
408  }
409  return is_array($this->getData('widget_parameters')) ? $this->getData('widget_parameters') : [];
410  }
411 
418  public function getWidgetsOptionArray($value = 'code')
419  {
420  $widgets = [];
421  $widgetsArr = $this->_widgetModel->getWidgetsArray();
422  foreach ($widgetsArr as $widget) {
423  $widgets[] = ['value' => $widget[$value], 'label' => $widget['name']];
424  }
425  return $widgets;
426  }
427 
436  public function getWidgetReference($matchParam, $value, $requestedParam)
437  {
438  $reference = null;
439  $widgetsArr = $this->_widgetModel->getWidgetsArray();
440  foreach ($widgetsArr as $widget) {
441  if ($widget[$matchParam] === $value) {
442  $reference = $widget[$requestedParam];
443  break;
444  }
445  }
446  return $reference;
447  }
448 
455  public function getWidgetConfigAsArray()
456  {
457  if ($this->_widgetConfigXml === null) {
458  $this->_widgetConfigXml = $this->_widgetModel->getWidgetByClassType($this->getType());
459  if ($this->_widgetConfigXml) {
460  $configFile = $this->_viewFileSystem->getFilename(
461  'widget.xml',
462  [
463  'area' => $this->getArea(),
464  'theme' => $this->getThemeId(),
465  'module' => $this->_namespaceResolver->determineOmittedNamespace(
466  preg_replace('/^(.+?)\/.+$/', '\\1', $this->getType()),
467  true
468  )
469  ]
470  );
471 
472  $isReadable = $configFile
473  && $this->_directory->isReadable($this->_directory->getRelativePath($configFile));
474  if ($isReadable) {
475  $config = $this->_reader->readFile($configFile);
476  $widgetName = isset($this->_widgetConfigXml['name']) ? $this->_widgetConfigXml['name'] : null;
477  $themeWidgetConfig = null;
478  if ($widgetName !== null) {
479  foreach ($config as $widget) {
480  if (isset($widget['name']) && $widgetName === $widget['name']) {
481  $themeWidgetConfig = $widget;
482  break;
483  }
484  }
485  }
486  if ($themeWidgetConfig) {
487  $this->_widgetConfigXml = array_replace_recursive($this->_widgetConfigXml, $themeWidgetConfig);
488  }
489  }
490  }
491  }
493  }
494 
500  public function getWidgetTemplates()
501  {
502  $templates = [];
503  $widgetConfig = $this->getWidgetConfigAsArray();
504  if ($widgetConfig && isset($widgetConfig['parameters']) && isset($widgetConfig['parameters']['template'])) {
505  $configTemplates = $widgetConfig['parameters']['template'];
506  if (isset($configTemplates['values'])) {
507  foreach ($configTemplates['values'] as $name => $template) {
508  $templates[(string)$name] = [
509  'value' => $template['value'],
510  'label' => __((string)$template['label']),
511  ];
512  }
513  }
514  }
515  return $templates;
516  }
517 
524  {
525  $containers = [];
526  $widgetConfig = $this->getWidgetConfigAsArray();
527  if (isset($widgetConfig) && isset($widgetConfig['supported_containers'])) {
528  $configNodes = $widgetConfig['supported_containers'];
529  foreach ($configNodes as $node) {
530  if (isset($node['container_name'])) {
531  $containers[] = (string)$node['container_name'];
532  }
533  }
534  }
535  return $containers;
536  }
537 
544  public function getWidgetSupportedTemplatesByContainer($containerName)
545  {
546  $templates = [];
547  $widgetTemplates = $this->getWidgetTemplates();
548  $widgetConfig = $this->getWidgetConfigAsArray();
549  if (isset($widgetConfig)) {
550  if (!isset($widgetConfig['supported_containers'])) {
551  return $widgetTemplates;
552  }
553  $configNodes = $widgetConfig['supported_containers'];
554  foreach ($configNodes as $node) {
555  if (isset($node['container_name']) && (string)$node['container_name'] == $containerName) {
556  if (isset($node['template'])) {
557  $templateChildren = $node['template'];
558  foreach ($templateChildren as $template) {
559  if (isset($widgetTemplates[(string)$template])) {
560  $templates[] = $widgetTemplates[(string)$template];
561  }
562  }
563  }
564  }
565  }
566  } else {
567  return $widgetTemplates;
568  }
569  return $templates;
570  }
571 
581  public function generateLayoutUpdateXml($container, $templatePath = '')
582  {
583  $templateFilename = $this->_viewFileSystem->getTemplateFileName(
584  $templatePath,
585  [
586  'area' => $this->getArea(),
587  'themeId' => $this->getThemeId(),
588  'module' => \Magento\Framework\View\Element\AbstractBlock::extractModuleName($this->getType())
589  ]
590  );
591  if (!$this->getId() && !$this->isCompleteToCreate() || $templatePath && !is_readable($templateFilename)) {
592  return '';
593  }
594  $parameters = $this->getWidgetParameters();
595  $xml = '<body><referenceContainer name="' . $container . '">';
596  $template = '';
597  if (isset($parameters['template'])) {
598  unset($parameters['template']);
599  }
600  if ($templatePath) {
601  $template = ' template="' . $templatePath . '"';
602  }
603 
604  $hash = $this->mathRandom->getUniqueHash();
605  $xml .= '<block class="' . $this->getType() . '" name="' . $hash . '"' . $template . '>';
606  foreach ($parameters as $name => $value) {
607  if ($name == 'conditions') {
608  $name = 'conditions_encoded';
609  $value = $this->conditionsHelper->encode($value);
610  } elseif (is_array($value)) {
611  $value = implode(',', $value);
612  }
613  if ($name && strlen((string)$value)) {
614  $value = html_entity_decode($value);
615  $xml .= '<action method="setData">' .
616  '<argument name="name" xsi:type="string">' .
617  $name .
618  '</argument>' .
619  '<argument name="value" xsi:type="string">' .
620  $this->_escaper->escapeHtml(
621  $value
622  ) . '</argument>' . '</action>';
623  }
624  }
625  $xml .= '</block></referenceContainer></body>';
626 
627  return $xml;
628  }
629 
635  protected function _invalidateCache()
636  {
637  if (count($this->_relatedCacheTypes)) {
638  $this->_cacheTypeList->invalidate($this->_relatedCacheTypes);
639  }
640  return $this;
641  }
642 
648  public function afterSave()
649  {
650  if ($this->dataHasChangedFor('page_groups') || $this->dataHasChangedFor('widget_parameters')) {
651  $this->_invalidateCache();
652  }
653  return parent::afterSave();
654  }
655 
661  public function beforeDelete()
662  {
663  if ($this->getPageGroups()) {
664  $this->_invalidateCache();
665  }
666  return parent::beforeDelete();
667  }
668 }
getData($key='', $index=null)
Definition: DataObject.php:119
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
getWidgetSupportedTemplatesByContainer($containerName)
Definition: Instance.php:544
$config
Definition: fraud_order.php:17
__()
Definition: __.php:13
$resource
Definition: bulk.php:12
__construct(\Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Escaper $escaper, \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList, \Magento\Catalog\Model\Product\Type $productType, \Magento\Widget\Model\Config\Reader $reader, \Magento\Widget\Model\Widget $widgetModel, \Magento\Widget\Model\NamespaceResolver $namespaceResolver, \Magento\Framework\Math\Random $mathRandom, \Magento\Framework\Filesystem $filesystem, \Magento\Widget\Helper\Conditions $conditionsHelper, \Magento\Framework\Model\ResourceModel\AbstractResource $resource=null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection=null, array $relatedCacheTypes=[], array $data=[], Json $serializer=null)
Definition: Instance.php:157
$type
Definition: item.phtml:13
$value
Definition: gender.phtml:16
generateLayoutUpdateXml($container, $templatePath='')
Definition: Instance.php:581
$entity
Definition: element.phtml:22
$filesystem
$template
Definition: export.php:12
getWidgetReference($matchParam, $value, $requestedParam)
Definition: Instance.php:436
$code
Definition: info.phtml:12
if(!isset($_GET['name'])) $name
Definition: log.php:14