Skip to content

Commit

Permalink
Merge pull request #2 from atravkovs/customWidgetsSupport
Browse files Browse the repository at this point in the history
Custom widgets support
  • Loading branch information
alfredsgenkins authored Sep 9, 2019
2 parents 5e99475 + 0129c30 commit 3b34739
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/Api/AttributeHandlerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace ScandiPWA\CmsGraphQl\Api;

interface AttributeHandlerInterface {
public function resolve(string $value): string;
}
21 changes: 21 additions & 0 deletions src/Model/Resolver/Attribute/ConditionsEncoded.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php
/**
* ScandiPWA_CmsGraphQl
*
* @category Scandiweb
* @package ScandiPWA_CmsGraphQl
* @author Artjoms Travkovs <[email protected]>
* @copyright Copyright (c) 2018 Scandiweb, Ltd (https://scandiweb.com)
*/

namespace ScandiPWA\CmsGraphQl\Model\Resolver\Attribute;

use ScandiPWA\CmsGraphQl\Api\AttributeHandlerInterface;

class ConditionsEncoded implements AttributeHandlerInterface
{
public function resolve(string $value): string
{
return base64_encode($value);
}
}
156 changes: 156 additions & 0 deletions src/Model/Template/FilterEmulate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?php
/**
* ScandiPWA_CmsGraphQl
*
* @category Scandiweb
* @package ScandiPWA_CmsGraphQl
* @author Artjoms Travkovs <[email protected]>
* @copyright Copyright (c) 2018 Scandiweb, Ltd (https://scandiweb.com)
*/

namespace ScandiPWA\CmsGraphQl\Model\Template;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\State;
use Magento\Framework\Escaper;
use Magento\Framework\Stdlib\StringUtils;
use Magento\Framework\UrlInterface;
use Magento\Framework\View\Asset\Repository;
use Magento\Framework\View\LayoutFactory;
use Magento\Framework\View\LayoutInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Variable\Model\Source\Variables;
use Magento\Variable\Model\VariableFactory;
use Magento\Widget\Block\BlockInterface;
use Magento\Widget\Model\Widget;
use Pelago\Emogrifier;
use Psr\Log\LoggerInterface;

/**
* Class FilterEmulate
* @package ScandiPWA\CmsGraphQl\Model\Template
*/
class FilterEmulate extends \Magento\Widget\Model\Template\FilterEmulate
{

/**
* Array of keys that will not be escaped
* in custom widget html output
*
* @var string[]
*/
protected $widgetParamsWhitelist;

protected $widgetCustomParamsHandlers;

/**
* Array of objects that will parsed to custom widget syntax
*
* @var object[]
*/
public $availableFilters;

public function __construct(
StringUtils $string,
LoggerInterface $logger,
Escaper $escaper,
Repository $assetRepo,
ScopeConfigInterface $scopeConfig,
VariableFactory $coreVariableFactory,
StoreManagerInterface $storeManager,
LayoutInterface $layout,
LayoutFactory $layoutFactory,
State $appState,
UrlInterface $urlModel,
Emogrifier $emogrifier,
Variables $configVariables,
\Magento\Widget\Model\ResourceModel\Widget $widgetResource,
Widget $widget,
array $availableFilters,
array $widgetUnescapedParams,
array $widgetCustomParamsHandlers
) {
parent::__construct($string, $logger, $escaper, $assetRepo, $scopeConfig, $coreVariableFactory, $storeManager, $layout, $layoutFactory, $appState, $urlModel, $emogrifier, $configVariables, $widgetResource, $widget);
$this->availableFilters = $availableFilters;
$this->widgetParamsWhitelist = $widgetUnescapedParams;
$this->widgetCustomParamsHandlers = $widgetCustomParamsHandlers;
}

/**
* General method for generate widget
*
* @param string[] $construction
* @return string
*/
public function generateWidget($construction)
{
$params = $this->getParameters($construction[2]);

// Determine what name block should have in layout
$name = null;
if (isset($params['name'])) {
$name = $params['name'];
}

if (isset($this->_storeId) && !isset($params['store_id'])) {
$params['store_id'] = $this->_storeId;
}

// validate required parameter type or id
if (!empty($params['type'])) {
$type = $params['type'];
} elseif (!empty($params['id'])) {
$preConfigured = $this->_widgetResource->loadPreconfiguredWidget($params['id']);
$type = $preConfigured['widget_type'];
$params = $preConfigured['parameters'];
} else {
return '';
}

// we have no other way to avoid fatal errors for type like 'cms/widget__link', '_cms/widget_link' etc.
$xml = $this->_widget->getWidgetByClassType($type);
if ($xml === null) {
return '';
}

if ($widgetName = array_search($params['type'], $this->availableFilters)) {
return $this->widgetToHtml($params, $widgetName);
}

// define widget block and check the type is instance of Widget Interface
$widget = $this->_layout->createBlock($type, $name, ['data' => $params]);
if (!$widget instanceof BlockInterface) {
return '';
}

return $widget->toHtml();
}

/**
* Generates widget html-like instructions
*
* @param string[] $params
* @param string $widgetName
* @return string
*/
public function widgetToHtml($params, $widgetName)
{
unset($params['template']);
$params['type'] = $widgetName;

$paramsList = [];
foreach ($params as $key => $value) {
if (key_exists($key, $this->widgetCustomParamsHandlers)) {
$value = $this->widgetCustomParamsHandlers[$key]->resolve($value);
} elseif (!in_array($key, $this->widgetParamsWhitelist)) {
$value = $this->_escaper->escapeHtmlAttr($value);
}

$paramsList[] = "$key='$value'";
}

$attributes = implode(' ', $paramsList);

return "<widget $attributes></widget>";
}
}
17 changes: 17 additions & 0 deletions src/etc/di.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<virtualType name="ScandiPWA\CmsGraphQl\Model\Template\VirtualFilterEmulate" type="ScandiPWA\CmsGraphQl\Model\Template\FilterEmulate">
<arguments>
<argument name="availableFilters" xsi:type="array">
<item name="Slider" xsi:type="string">Scandiweb\Slider\Block\Widget\Slider</item>
<item name="NewProducts" xsi:type="string">Magento\Catalog\Block\Product\Widget\NewWidget</item>
<item name="CatalogProductList" xsi:type="string">Magento\CatalogWidget\Block\Product\ProductsList</item>
</argument>
<argument name="widgetUnescapedParams" xsi:type="array">
<item name="type" xsi:type="string">type</item>
</argument>
<argument name="widgetCustomParamsHandlers" xsi:type="array">
<item name="conditions_encoded" xsi:type="object">ScandiPWA\CmsGraphQl\Model\Resolver\Attribute\ConditionsEncoded</item>
</argument>
</arguments>
</virtualType>

<preference for="Magento\CmsGraphQl\Model\Resolver\Page" type="ScandiPWA\CmsGraphQl\Model\Resolver\Page"/>
<preference for="Magento\Widget\Model\Template\FilterEmulate" type="ScandiPWA\CmsGraphQl\Model\Template\VirtualFilterEmulate"/>
<preference for="Magento\CmsGraphQl\Model\Resolver\DataProvider\Block" type="ScandiPWA\CmsGraphQl\Model\Resolver\DataProvider\Block"/>
</config>
1 change: 1 addition & 0 deletions src/etc/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<sequence>
<module name="Magento_CmsGraphQl"/>
<module name="Magento_GraphQl"/>
<module name="Magento_Widget"/>
</sequence>
</module>
</config>

0 comments on commit 3b34739

Please sign in to comment.