Наверх

Работа с полями ресурса после сохранения (пример создания плагина)

В MODX существует система плагинов и событий. Одно из интересных событий — OnDocFormSave. Это событие на сохранение ресурса.

Простыми словами — если мы создадим плагин, у которого отметим на вкладке «Системные события» галочку OnDocFormSave, то код этого плагина будет запущен после сохранения любого ресурса.

В коде плагина мы легко можем определить, какой ресурс был сохранён — только что созданный или уже существовавший ранее. Это нужно, если мы захотим обрабатывать только поля новых ресурсов, но ничего не менять, если в ресурс просто вносятся какие-то изменения. Для этой цели MODX передаёт нам параметр $mode:
<?php
if ($mode == 'new') {
    // Здесь пишем наш код
}

Такой плагин позволит нам упростить добавление видео-роликов на сайт в виде ресурсов. При создании ресурса в поле pagetitle мы будем вставлять ссылку на видео с YouTube, а плагин будет получать название видео, его описание и сохранять это всё в полях ресурса.

<?php
if ($mode == 'new') {
  // Будем обрабатывать только те ресурсы, в заголовке которых нет пробела
  if (strpos(trim($resource->pagetitle), ' ') === false) {

    // Пытаемся получить ID видео из заголовка ресурса
    preg_match('#(\.be/|/embed/|/v/|/watch\?v=)([A-Za-z0-9_-]{5,11})#', $resource->pagetitle, $matches);
    
    if(isset($matches[2]) && $matches[2] != ''){
      // Если ID получено, сохраняем его в переменной
      $code = $matches[2];
    } else {
      // Если ID видео не удалось получить, ничего не делаем
      return true;
    }
    
    // Сохраняем ID видео в ТВ-поле (например, чтобы в шаблоне вывести сам ролик)
    $resource->setTVValue('video', $code);
    
    // Получаем название видео и описание
    $key = 'AIzaSyDXK7dCc4C3rjOCY6H5JXDeKqiVO20sQ0U'; // Ключ API YouTube
    $url = 'https://www.googleapis.com/youtube/v3/videos?part=snippet&id=' . $code . '&key=' . $key;
    $json = file_get_contents($url);
    $video = $modx->fromJSON($json);
    
    // Заголовок
    $pagetitle = $video['items'][0]['snippet']['title'];
    
    // Описание (+ разбиваем на параграфы)
    $content = explode(PHP_EOL, $video['items'][0]['snippet']['description']);
    
    // Записываем полученные данные в ресурс
    $resource->set('pagetitle', $pagetitle);
    $resource->set('content', '<p>' . implode('</p>'.PHP_EOL.'<p>', $content) . '</p>');
    
    // Генерируем новый псевдоним
    $resource->set('alias', $resource->cleanAlias($pagetitle));
    
    // И сохраняем ресурс
    $resource->save();
  }
}

В коде плагина можно ограничить обрабатываемые ресурсы каким-нибудь разделом через $resource->parent или шаблоном через $resource->template, а можно оставить как есть — плагин всё равно будет обрабатывать только те ресурсы, в заголовок которых вставлена ссылка на YouTube.

Кстати, для этой же цели можно использовать дополнение VideoGallery. Данный плагин представлен только как пример — вы можете обрабатывать поля ресурса как вам подскажет фантазия.


6 комментариев

  1. Denis Efremov 05 августа 2017, 10:45 # 0
    ^(?:(?:https?://)?(?:www\.)?youtube\.com/)(?:watch\?v=|v/)([a-zA-Z0-9_-]*)
    На первый матч отдает.
    1. Denis Efremov 05 августа 2017, 10:51 # 0
      А в чем, забыл, принципиальное отличие
      $modx->fromJSON($json)
      от
      json_decode($json, true)
      ???

      Просто decode, относительно безопасен, в отличии от
      $video['items'][0]['snippet']['description']
      такой манипуляции над непровалидированым массивом.
      1. Илья Уткин 05 августа 2017, 10:57 # 0
        Если на сервере не работает функция json_decode, fromJSON подключает дополнительную библиотеку. Но, это бывает редко, так что, думаю, разницы в них никакой.
        1. Denis Efremov 05 августа 2017, 10:58(Комментарий был изменён) # 0
          А второй параметр она берет?
          Вижу
          Пардон

          А аналогов array_get и array_set нету же у Modx? Уже все позабыл…
          1. Илья Уткин 05 августа 2017, 11:03 # 0
            Нет, таких функций не встречал.
      2. Denis Efremov 05 августа 2017, 11:08(Комментарий был изменён) # 0
                echo "\n\033[37;5;228mStarting products seeder!\n";
        
                $contentJson = __DIR__.'/../../resources/json/content.json';
                $tvsJson     = __DIR__.'/../../resources/json/tvs.json';
        
                if (!$content = json_decode(file_get_contents($contentJson), true))
                {
                    echo "\033[35;5;228mError parse content data!\n";
        
                    dd($content);
                }
        
                if (!$tvs = json_decode(file_get_contents($tvsJson), true))
                {
                    echo "\033[35;5;228mError parse tvs data!\n";
        
                    dd($tvs);
                }
        
                $this->products->truncate();
        
                $repository = new EntryRepository();
        
                $repository->setModel(new BookStoreGeneralProductsEntryModel());
                $repository->truncate();
                $repository->setModel(new BookStoreOccasionProductsEntryModel());
                $repository->truncate();
                $repository->setModel(new BookStoreDocumentProductsEntryModel());
                $repository->truncate();
                $repository->setModel(new BookStoreLabelProductsEntryModel());
                $repository->truncate();
                $repository->setModel(new BookStoreLiteratureProductsEntryModel());
                $repository->truncate();
        
                echo "\033[35;5;228mProducts truncated!\n";
        
                $products = array_where($content, function ($item) use ($cats)
                {
                    $parent = array_get($item, 'parent');
        
                    foreach ($cats as $id)
                    {
                        //if ($id == $parent && $id!=274 )
                        if ($id == $parent)
                        {
                            return true;
                        }
                    }
        
                    return false;
                });
        
                foreach ($products as $item)
                {
                    $html ="hmmm";
                    $parent = array_get($item, 'parent');
                    $id     = array_get($item, 'id');
                    $title  = array_get($item, 'pagetitle');
                    $slug   = array_get($item, 'alias');
        
        
                    $itemTvs = array_where($tvs, function ($tv) use ($id)
                    {
                        return array_get($tv, 'contentid') == $id;
                    });
        
                    $html = array_get(array_first($itemTvs, function ($tv)
                    {
                        return array_get($tv, 'tmplvarid') == 29;
                    }), 'value');
        
                    $price = array_get(array_first($itemTvs, function ($tv)
                    {
                        return array_get($tv, 'tmplvarid') == 33;
                    }), 'value');
        
                    $categorySlug = array_get(array_flip($cats), $parent);
                    $typeSlug     = array_get($this->map, $categorySlug);
        
                    /* @var TypeInterface $type */
                    $type = $this->types->findBySlug($typeSlug);
        
                    /* @var EntryInterface $entry */
                    $entry = app()->make(
                        'Anomaly\Streams\Platform\Model\BookStore\BookStore'
                        .ucfirst($typeSlug).'ProductsEntryModel'
                    )->create([]);
        
                    $fields = [
                        'sv'            => [
                            'title'       => $title,
                            'description' => $html,
                        ],
                        'en'            => [
                            'title'       => $title,
                            'description' => $html,
                        ],
                        'slug'          => $slug,
                        'price'         => $price,
                        'vat_id'        => 1,
                        'created_by_id' => 1,
                        'type'          => $type,
                        'entry'         => $entry,
                        'enabled'       => true,
                    ];
        
                    if ($this->products->create($fields))
                    {
                        echo "\033[36;5;228mCreated product \033[31;5;228m{$title}"
                            ."\t\033[36;5;228mof type \033[31;5;228m{$typeSlug}\n";
                            //."width content: {$html}";
                    }
                }
        
                echo "\033[32;5;228mAll products have been seeded successfully!\n";
        
        Переезд с Modx )))

        Авторизация

        через сервис Loginza:


        Шаблоны MODX

        1 2 Дальше »

        Объектная
        модель
        MODX