1 Отредактировано CMS Admin (09-02-2017 13:53:24)

Тема: Двойная автозагрузка модулей в админке при редактировании товара

Чтобы на вкладке "Дополнения модулей" при редактировании товаров выводились данные модуля необходимо добавить функцию:

public static function adminAutoload() {
    Events::create()->onShopProductPreUpdate()->setListener('_extendProduct');
  }

При этом когда функция _extendProduct пытается вернуть отрендеренный шаблон возникает, двойная автозагрузка в админке, т.е. при редактировании товара все модули автозагрузки отображаются дважды.

Это происходит только когда в автозагрузке на данное событие (onShopProductPreUpdate) висит больше одного модуля

Кто знает как с этим бороться?

2

Re: Двойная автозагрузка модулей в админке при редактировании товара

Товарищ Админ, если в классе BaseEvents внутри метода runFactory добавить:

dump(Events::create()->storage);

то видно, что в хранилище событий уже дублируются модули:

"ShopAdminProducts:preEdit" => array:3 [▼
    "collable" => array:5 [▼
      0 => array:3 [▼
        "collMethod" => "setUpdatedUrl"
        "collClass" => "Sitemap"
        "isClosure" => false
      ]
      1 => array:3 [▼
        "collMethod" => "_extendProduct"
        "collClass" => "Aggregator"
        "isClosure" => false
      ]
      2 => array:3 [▼
        "collMethod" => "_extendProduct"
        "collClass" => "Vendors"
        "isClosure" => false
      ]
      3 => array:3 [▼
        "collMethod" => "_extendProduct"
        "collClass" => "Aggregator"
        "isClosure" => false
      ]
      4 => array:3 [▼
        "collMethod" => "_extendProduct"
        "collClass" => "Vendors"
        "isClosure" => false
      ]
    ]
    "run" => true
    "params" => array:3 [▶]
  ]

3

Re: Двойная автозагрузка модулей в админке при редактировании товара

В общем, временное решение такое. В классе BaseEvents добавил метод, который удаляет дубликаты из хранилища событий (но нагружает сервер):

/**
   * Временное решение, которое убирает дублирование из хранилища событий
   * @param type $storage = Events::create()->storage
   * @return array - массив, очищенный от уникальных значений
   * @author Alexander Erko
   * @copyright CMSAdmin (c) 2017, Alexander Erko <info@cms-admin.ru>
   */
  public static function uniqueEventStorage($storage) {
    
    foreach ($storage as $storageKey => $storageValue) {
      unset($unique);
      foreach($storageValue['collable'] as $colKey => $colData){
        $method = (get_class($colData['collMethod'])) ? get_class($colData['collMethod']) : $colData['collMethod'];
        $class = (get_class($colData['collClass'])) ? get_class($colData['collClass']) : $colData['collClass'];
        $unique[$colKey] = 'method: '.$method.' class: '.$class;
      }
      
      $unique = array_unique($unique);
      
      foreach ($storageValue['collable'] as $uKey => $uValue) {
        if(array_key_exists($uKey, $unique ) === FALSE){
          unset($storageValue['collable'][$uKey]);
        }
      }

      $Events[$storageKey] = $storageValue;
    }
    
    return $Events;
  }

А в методе runFactory изменил следующим образом:

/**
   * Run Behavior factory when controller is completely loaded
   * @param string $eventAlias
   * @param bool $cleanQueue
   * @access public
   * @author Kaero
   * @copyright ImageCMS (c) 2012, Kaero <dev@imagecms.net>
   */
  public static function runFactory($eventAlias = null, $cleanQueue = false) {
    
    (defined('BASEPATH')) OR exit('No direct script access allowed');
    // очищаем хранилище событий от дубликатов
    $events = BaseEvents::uniqueEventStorage(Events::create()->storage);
    
    foreach ($events as $storageKey => $value) {
      if ($eventAlias !== null && $eventAlias != $storageKey) {
        continue;
    }
      
    if (isset($value['run'])) {
      if ($value['run'] === TRUE && isset($value['collable'])) {
        foreach ($value['collable'] as $collableKey => $run) {
          Events::create()->storage[$storageKey]['run'] = false;
            if ($run['isClosure'] === false) {
              call_user_func([$run['collClass'], $run['collMethod']], $value['params']);
            } else {
              call_user_func($run['collMethod'], $value['params']);
            }
            if ($cleanQueue === true) {
              unset(Events::create()->storage[$storageKey]['collable'][$collableKey]);
            }
          }
        }
      }
    }
  }

Так как это костыль, прошу разработчиков обратить внимание на проблему