custom/plugins/WbmTagManagerAnalytics/src/Services/DataLayerRenderer.php line 52

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Wbm\TagManagerAnalytics\Services;
  3. use Doctrine\DBAL\Connection;
  4. use Twig\Environment;
  5. class DataLayerRenderer implements DataLayerRendererInterface
  6. {
  7.     const STRING_VALUES = [
  8.         'item_name',
  9.         'item_id',
  10.         'item_brand',
  11.         'item_category',
  12.     ];
  13.     /**
  14.      * @var Environment
  15.      */
  16.     private $twig;
  17.     /**
  18.      * @var Connection
  19.      */
  20.     private $connection;
  21.     /**
  22.      * @var array
  23.      */
  24.     private $variables = [];
  25.     /**
  26.      * @var array
  27.      */
  28.     private $dataLayer = [];
  29.     public function __construct(
  30.         Environment $twig,
  31.         Connection $connection
  32.     ) {
  33.         $this->twig = clone $twig;
  34.         $this->connection $connection;
  35.     }
  36.     public function renderDataLayer(string $route): DataLayerRendererInterface
  37.     {
  38.         $properties $this->getChildrenList(null$route);
  39.         $dataLayer $this->fillValues($properties);
  40.         try {
  41.             $template $this->twig->createTemplate($dataLayer);
  42.             $dataLayer $template->render($this->getVariables($route));
  43.             $dataLayer preg_replace('/[[:cntrl:]]/'''$dataLayer);
  44.             $dataLayer json_decode($dataLayertrue);
  45.             if (json_last_error() > 0) {
  46.                 throw new \Exception(json_last_error_msg(), 1620985321);
  47.             }
  48.             if (!empty($dataLayer)) {
  49.                 array_walk_recursive($dataLayer, [$this'castArrayValues']);
  50.             }
  51.         } catch (\Exception $e) {
  52.             $dataLayer = [];
  53.             $dataLayer['default'] = json_encode(['error' => $e->getMessage()]);
  54.         }
  55.         if (!empty($dataLayer['default'])) {
  56.             if (!empty($dataLayer['onEvent']) && !empty($dataLayer['default']['event'])) {
  57.                 unset($dataLayer['default']['event']);
  58.             }
  59.             $this->dataLayer[$route]['default'] = json_encode($dataLayer['default']);
  60.         }
  61.         if (!empty($dataLayer['onEvent'])) {
  62.             $dataLayer['onEvent']['event'] = $dataLayer['onEvent']['event'] ?? ucfirst(array_key_first($dataLayer['onEvent'])) . 'Push';
  63.             $this->dataLayer[$route]['onEvent'] = json_encode($dataLayer['onEvent']);
  64.         }
  65.         return $this;
  66.     }
  67.     public function getVariables(string $route): array
  68.     {
  69.         return $this->variables[$route];
  70.     }
  71.     public function setVariables(string $route$variables): DataLayerRendererInterface
  72.     {
  73.         $this->variables[$route] = $variables;
  74.         return $this;
  75.     }
  76.     public function getDataLayer($route): ?array
  77.     {
  78.         return $this->dataLayer[$route] ?? null;
  79.     }
  80.     public function fillValues(array $dataLayer): string
  81.     {
  82.         $dataLayer json_encode($dataLayerJSON_UNESCAPED_SLASHES);
  83.         $search = [',{"endArrayOf":true}'];
  84.         $replace = ['{% endverbatim %}{% if not loop.last %},{% endif %}{% endfor %}{% verbatim %}'];
  85.         $dataLayer str_replace($search$replace$dataLayer);
  86.         while (preg_match('/({"startArrayOf":".*?"},)/i'$dataLayer$matches)) {
  87.             foreach ($matches as $match) {
  88.                 $foreachObj json_decode(rtrim($match','));
  89.                 if ($foreachObj->startArrayOf) {
  90.                     $arguments explode(' in '$foreachObj->startArrayOf);
  91.                     $dataLayer str_replace(
  92.                         $match,
  93.                         '{% endverbatim %}{% for ' . @$arguments[0] . ' in ' . @$arguments[1] . ' %}{% verbatim %}',
  94.                         $dataLayer
  95.                     );
  96.                 }
  97.             }
  98.         }
  99.         $dataLayer '{% verbatim %}' $dataLayer '{% endverbatim %}';
  100.         return $dataLayer;
  101.     }
  102.     public function getChildrenList($id null$module null): array
  103.     {
  104.         $qb $this->connection->createQueryBuilder();
  105.         $qb->from('wbm_data_layer_properties''property');
  106.         if ($id !== null) {
  107.             $qb->where('property.parent_id = :parentId')
  108.                 ->setParameter(':parentId'$id);
  109.         } else {
  110.             $qb->where('property.parent_id IS NULL');
  111.         }
  112.         $qb->andWhere('property.module = :moduleName')
  113.             ->setParameter(':moduleName'$module);
  114.         $qb->select(
  115.             [
  116.                 'property.name',
  117.                 'property.value',
  118.                 'property.id',
  119.                 'property.child_count',
  120.                 'property.on_event',
  121.                 'property.event_name',
  122.                 'property.parent_id',
  123.             ]
  124.         );
  125.         $properties $qb->execute()->fetchAll(\PDO::FETCH_ASSOC);
  126.         $namedProperties = [];
  127.         foreach ($properties as $key => &$property) {
  128.             $root = ($property['parent_id'] === null);
  129.             $onEvent = ($property['on_event'] === '1');
  130.             $eventName trim($property['event_name']);
  131.             $subProperties null;
  132.             if ((int) $property['child_count'] > 0) {
  133.                 $subProperties $this->getChildrenList($property['id'], $module);
  134.             }
  135.             $value $property['value'];
  136.             $name $property['name'];
  137.             unset(
  138.                 $property['name'],
  139.                 $property['value'],
  140.                 $property['id'],
  141.                 $property['child_count'],
  142.                 $property['on_event'],
  143.                 $property['event_name'],
  144.                 $property['parent_id']
  145.             );
  146.             if (!empty($subProperties)) {
  147.                 if (empty($value)) {
  148.                     $property $subProperties;
  149.                 } else {
  150.                     $property = [
  151.                         ['startArrayOf' => $value],
  152.                         $subProperties,
  153.                         ['endArrayOf' => true],
  154.                     ];
  155.                 }
  156.             } else {
  157.                 $property '{% endverbatim %}' $value '{% verbatim %}';
  158.             }
  159.             if ($root) {
  160.                 $key = ($onEvent 'onEvent' 'default');
  161.                 if ($key === 'onEvent' && !empty($eventName)) {
  162.                     $namedProperties[$key]['event'] = $eventName;
  163.                 }
  164.                 $namedProperties[$key][$name] = $property;
  165.             } else {
  166.                 $namedProperties[$name] = $property;
  167.             }
  168.         }
  169.         return $namedProperties;
  170.     }
  171.     private function castArrayValues(&$value$key): void
  172.     {
  173.         if (in_array($keyself::STRING_VALUEStrue)) {
  174.             return;
  175.         }
  176.         if (preg_match('/^\"(.*)\"$/'$value)) {
  177.             $value json_decode($value);
  178.             return;
  179.         }
  180.         switch (true) {
  181.             case is_array(json_decode($value)):
  182.             case is_int(json_decode($value)):
  183.             case is_float(json_decode($value)):
  184.             case is_bool(json_decode($value)):
  185.                 $value json_decode($value);
  186.         }
  187.     }
  188. }