easyComm - дополнительное поле Изображение

UPD 22.04.2021. Эта публикация устарела!
С версии 1.11.0-pl компонент сразу поддерживает вложение файлов: modx.pro/components/21775


При использовании компонента easyComm встала задача прикрепления к сообщения файла, а точнее изображения. Да еще и так, что бы им удобно можно было управлять через админку.

По результатам работы — небольшая инструкция, как этого добиться:


Шаг 0. Прежде всего, необходимо установить свежую версию easyComm, требуемый функционал появился с версии 1.2.0 (прим.: в версии 1.5.0 добавлена поддержка media source, отличного от default).

В этой версии было добавлено 2 новшества:
1. События на создание, редактирование, публикацию, удаление сообщений, что бы вы могли писать свои плагины.
2. Пара дополнительных функций-утилит для работы с полями-изображениями.

Я сознательно не стал включать описанный ниже функционал непосредственно в компонент, т.к. реализация именно в таком виде нужна не всем, но все весьма неплохо делается плагинами.

Шаг 1. Добавляем согласно инструкции docs.modx.pro/components/easycomm/plugins-and-customization одно или несколько дополнительных полей, у меня поле будет называться photo. При этом код js файла должен быть примерно таким:

easyComm.plugin.myplugin = {
      getFields: function(config) {
            return {
                  photo: {
                        // специальный x-type
                        xtype: 'ec-image-field',
                        fieldLabel: _('ec_message_photo'),
                        anchor: '99%',
			// указываем default_media_source или id нужного, например 2
                        source: MODx.config.default_media_source
                  }
            }
      }
      ,getColumns: function() {
            return {
                  photo: {
                        width:50, 
                        sortable:true, 
                        name: 'photo',
                        // специальный рендер
                        renderer: easyComm.utils.renderImage,
			// указываем default_media_source или id нужного, например 2
                        source: MODx.config.default_media_source
}
            }
      }
};

здесь нужно обратить внимание на «xtype=ec-image-field», и на «renderer: easyComm.utils.renderImage», это то, про что упоминалось в Шаге 0, п.1. Первый — специальный тип ввода, который позволяет использовать файловый менеджер для выбора изображений и поддерживает превью, а второй — отображение картинки в списке.

Шаг 2. Создать плагин, повесить его на событие OnEcMessageSave, код плагина:
<?php
$conf_upload_dir = 'uploads/user_files/';
$conf_upload_path = MODX_BASE_PATH.$conf_upload_dir;
$conf_upload_file_name = 'file_'.date('Y-m-d_H-i-s');
$conf_upload_input_name = 'photo';
$conf_upload_thumbs = array(
    '' => array('w' => 1280,'h' => 720,'zc' => 0, 'bg' => '#fff', 'far' => 0),
    '_thumb' => array('w' => 128,'h' => 72,'zc' => 0, 'bg' => '#fff', 'far' => 0)
);

if($modx->event->name == 'OnEcMessageSave' && $mode == modSystemEvent::MODE_NEW) {
    // $mode: modSystemEvent::MODE_NEW, modSystemEvent::MODE_UPD
    // Объект: $ecMessage->toArray()
    
    if(isset($_FILES[$conf_upload_input_name]) && !empty($_FILES[$conf_upload_input_name]['tmp_name'])){
        $file_info = getimagesize($_FILES[$conf_upload_input_name]['tmp_name']);
        if(empty($file_info)) {
            $modx->log(xPDO::LOG_LEVEL_WARN, 'Не могу сохранить файл'.$_FILES[$conf_upload_input_name]['name'].', так как он не является изображением');
            return;
        }
        $extention = '';
        switch (exif_imagetype($_FILES[$conf_upload_input_name]['tmp_name']))
        {
            case IMAGETYPE_GIF:
                $extention = '.gif';
            break;
            case IMAGETYPE_JPEG:
                $extention = '.jpg';
            break;
            case IMAGETYPE_PNG:
                $extention = '.png';
            break;
        }
        if(empty($extention)) {
            $modx->log(xPDO::LOG_LEVEL_WARN, 'Не могу сохранить файл'.$_FILES[$conf_upload_input_name]['name'].', так как его тип не поддерживается');
            return;
        }
            
        // проверяем каталог
        if(!file_exists($conf_upload_path)){
            $modx->log(xPDO::LOG_LEVEL_ERROR, 'Директория '.$conf_upload_path.' не существует');
            return;
        }
        // перемещаем файл
        $file_name = $conf_upload_file_name.$extention;
        if(!move_uploaded_file($_FILES[$conf_upload_input_name]['tmp_name'], $conf_upload_path.$file_name)){
            $modx->log(xPDO::LOG_LEVEL_ERROR, 'Не удалось переместить загруженный файл по пути '.$conf_upload_path.$file_name);
            return;
        }
        
        // подключаем phpthumb
        require_once MODX_CORE_PATH.'model/phpthumb/phpthumb.class.php';
        foreach($conf_upload_thumbs as $curConfigKey => $curConfig){
            // инициализируем
            $phpThumb = new phpThumb();
            $phpThumb->setSourceFilename($conf_upload_path.$file_name);
            foreach ($curConfig as $k => $v) {
                $phpThumb->setParameter($k, $v);
            }
    
            // генерируем файл
            if ($phpThumb->GenerateThumbnail()) {
                if ($phpThumb->RenderToFile($conf_upload_path.$conf_upload_file_name.$curConfigKey.$extention)) {
                    // устанавливаем права на файл, это опционально, зависит от сервера
                    //chmod($conf_upload_path.$conf_upload_file_name.$curConfigKey.$extention, 0666);
                }
            }
        }
        // сохраняем изменения
        $ecMessage->set('photo', $conf_upload_dir.$file_name);
        $ecMessage->save();
    }
}
Настройки работы плагина находятся в верхней его части. Он умеет сохранять загруженные изображения в каталог uploads/user_files/ (не забудьте его создать!!!) сжимать изображение до определенных размеров, и делать превьюшки. Правда не научил его пока работать с источниками файлов, это было не нужно.
ВАЖНО! Этот плагин — просто пример, как можно сделать! На ваших проектах код может быть совсем другой!!!

Шаг 4. Добавить поле photo в системные настройки ec_message_grid_fields и ec_message_window_layout. Опять же смотрим документацию docs.modx.pro/components/easycomm/plugins-and-customization

Шаг 5. В чанке создания сообщения добавить поле photo, примерно так:
<div class="form-group">
        <label for="ec-photo-[[+fid]]" class="control-label">Файл</label>
        <input type="file" name="photo" id="ec-photo-[[+fid]]">
        <span class="ec-error help-block" id="ec-photo-error-[[+fid]]"></span>
    </div>
и не забыть к форме добавить
enctype="multipart/form-data"
, что бы она могла отправлять файлы.

Вроде как и все =)

В результате:
1. Пользователь сможет прикрепить изображение к сообщению. Это может быть, например, фото или скриншот.
2. Фото будет загружено на сервер.
3. Админ сможет удобно с этим фото работать, будет видеть его превью как в списке сообщений, так и при редактировании сообщения
Наумов Алексей
05 июня 2015, 06:30
modx.pro
17
7 504
+6

Комментарии: 41

Илья
09 июня 2015, 13:17
0
Подскажите, событие OnEcMessageSave создано в версии 1.2.0, и пока эта версия недоступна создание дополнительного поля «изображение» невозможно, или в версии 1.1.2-pl событие OnEcMessageSave нужно создавать самому?
Извиняюсь, если вопрос глупый…
    Наумов Алексей
    09 июня 2015, 14:36
    0
    Версия 1.2.0 вам нужна, надеюсь, что скоро она появится в магазине.
    Илья
    19 июня 2015, 10:53
    0
    Что-то не дождаться никак обновлённой версии…
      Наумов Алексей
      19 июня 2015, 13:06
      0
      Тот, кто выкладывает дополнения, как мне пояснили, — в отпуске =)
      Надеюсь в понедельник мы все увидим.
        Илья
        19 июня 2015, 13:38
        0
        Ждём с нетерпением!!!
      Илья
      23 июня 2015, 12:39
      0
      Сделал всё по инструкции, всё получилось.
      Только теперь в поле subject записываетеся название фото, как и в поле photo



      Не подскажете, где может быть ошибка?

      И ещё, мне требуется выводить изображения в сообщениях с помощью fancybox, делаю так:
      [[+photo:gt=`0`:then=`<a rel="gallery" class="fancybox" href="[[+photo]]" ><img src="[[+photo]]" /></a>`:else=``]]
      Для того чтобы вывести изображение _thumb нужно его записывать в БД, для этого нужно переписывать плагин и добавлять новое поле, я правильно понимаю?
        Наумов Алексей
        23 июня 2015, 14:25
        0
        В плагине ошибка вкралась, найдите на этой странице строчку

        $ecMessage->set('subject', $conf_upload_dir.$file_name);
        она лишняя…

        А по _thumb вы верно поняли, ну либо его вообще можно убрать, а для ресайза пользоваться стандартными phpthumbof или другим сниппетом.
        Илья
        20 июля 2015, 17:57
        0
        Хорошей штукой было бы ответ из админки с возможностью добавить изображение или файл.
        Спасибо за компонент!
          Наумов Алексей
          21 июля 2015, 08:38
          0
          Дык про это и статья. Не понял в чем вопрос. Сделайте поле и заполняйте его из админки.
            Wassi Wassinen
            01 ноября 2015, 18:47
            0
            Алексей, приветствую. Скажите, вы могли бы допилить решение для отправки файлов типа .doc и docx с проверкой на объем? Готов проспонсировать. :)
              Наумов Алексей
              02 ноября 2015, 15:55
              0
              Добрый день!

              Я поставлю себе в TODO этот вопрос. Не уверен, что смогу скоро сделать, работы много, но если сделаю, постараюсь отписать здесь.
                Wassi Wassinen
                02 ноября 2015, 16:08
                0
                Спасибо! Василий помог с реализацией через AjaxForm, но если вы сделаете это в своем компоненте — это многим пригодится. Плюс — удобный интерфейс для просмотра в админке. :)
                  Наумов Алексей
                  02 ноября 2015, 16:23
                  0
                  Ну у меня назначение компонента все же несколько иное…

                  Поэтому если реализую, это будет в виде плагина какого-то, как и с изображениями (про что и эта статья выше)…
          Ksenia
          05 апреля 2017, 20:37
          0
          Алексей, добрый вечер!
          Не могу отловить ошибку. По Вашему туториалу все сделала, чтобы пользователь мог загружать изображения в Отзывах.
          В админке в сообщении строка, где должно быть загружено изображение — пусто. В папке uploads/user_files/ также пусто.
          На каком-то этапе он не загружает изображения. В чем может быть проблема?

            Наумов Алексей
            06 апреля 2017, 09:41
            0
            Нужно детально разбираться, задача не простая.

            Нужно проверять еще все пути, источники файлов. Ошибки в логах сайта, сервера, консоли есть? Угадать в чем причина — сложно
              Ksenia
              06 апреля 2017, 15:32
              0
              Никаких ошибок консоль не выдает. Остался один вопрос с туториала — может в нем причина… docs.modx.pro/components/easycomm/plugins-and-customization
              п. 4. Плагины: 4. Создать поля в таблице modx_ec_messages.
              Где находится данная таблица? Это единственное, что я не сделала…

                Наумов Алексей
                06 апреля 2017, 15:37
                0
                =)))

                без этого 100% ничего не будет работать, ну что вы!

                phpMyAdmin, ищем таблицу modx_ec_messages, создаем в ней нужные колонки.
                  Ksenia
                  06 апреля 2017, 15:53
                  0
                  А какого типа должно быть поле для фотографии?
                    Ksenia
                    06 апреля 2017, 16:05
                    0
                    Нашла, что тип должен быть BLOB. Добавила поле в таблицу. Реакции никакой. Все равно не подгружается в uploads/user_files. и в админке пусто…
                      Наумов Алексей
                      06 апреля 2017, 16:18
                      0
                      Нет, varchar, длинной, допустим 255

                      У нас же просто путь к файлу пишется в поле, а данные сохраняется в файл, а не базу.
                        Ksenia
                        06 апреля 2017, 16:21
                        0
                        Исправила на varchar. Дело видимо не в этом. Надо искать еще…
              Maxim
              28 июля 2017, 00:01
              0
              Всем доброго времени суток!
              Никак не могу добиться отправки изображений в форме.

              Все сделал по инструкции, при отправке пишет error submit!
              В админке появляется неопубликованное сообщение, но без изображения!
              из админки можно добавить изображение к сообщению без проблем. в БД появляется

              В логах и консоле чисто, все пункты интеграции пройдены по списку, проверял несколько раз,

              ощущение что дело в плагине AjaxForm

              Подскажите пожалуйста в какую сторону копать…
                Maxim
                28 июля 2017, 14:36
                0
                Вопрос закрыт.

                Огромное спасибо Наумову Алексею за помощь.

                Для столкнувшихся с подобной ситуацией, могу сказать, что дело было в отключеном php модуле «exif».
                Андрей
                04 февраля 2018, 15:10
                2
                0
                Подскажите, а как нужно поправить плагин, чтобы загружать скажем 3 фото?
                  Виктор
                  26 марта 2018, 12:34
                  0
                  При попытке выставить requiredFields поле photo — выдаёт ошибку даже когда оно заполнено, когда пытаешься отправить форму, убираю из requiredFields — всё нормально.
                  Решил вопрос пока что так: добавил required в input загрузки поля photo.
                    Паша Палиенко
                    25 октября 2018, 20:29
                    0
                    На modx версии 2.6.5 плагин не работает из-за phpthumb.
                    Решение проблемы — закомментировать подключение phpthumb.
                    Игорь
                    19 июня 2019, 18:14
                    0
                    Спасибо за статью, сделал все как указано, все работает!
                    Но все же, присоединяюсь к вопросу выше, что можно сделать, если нужно добавлять несколько фото?
                      Наумов Алексей
                      20 июня 2019, 09:21
                      0
                      Добавить несколько полей. Полноценной фотогалереи ждать в компоненте отзывов не стоит.
                      Можно попробовать хранить ссылки на файле в одном поле, в формате JSON.
                        Dementor218
                        07 февраля 2021, 18:21
                        0
                        Здравствуйте, Алексей! Создал 4 доп поля по аналогии с примером (имена разные, в базе под них тоже создал поля и прочее). Но при отправке формы во все поля записывается один файл. Не хватило мне знаний при доработке плагина, и форма отправляет не корректно. В админке же если заполнять, то все нормально выводится на сайт. не знаю что делать. Посоветуете что-нибудь?
                          Наумов Алексей
                          08 февраля 2021, 09:42
                          0
                          Добрый день.
                          В плагине используется 1 поле с именем photo
                          $conf_upload_file_name = 'photo';
                          у вас несколько должно быть, и код придется переписать соответственно… проверяйте, что я посоветовать
                      alexandr.skyrda
                      25 февраля 2020, 20:11
                      0
                      Здравствуйте, спасибо большое за плагин, все работает кроме отображения фото в админке, где редактируются отзывы
                      вот разметка для ec_message_window_layout, в ec_message_grid_fields добавил просто ec_message_photo
                      {
                          "main": {
                              "name": "main",
                              "columns": {
                                  "column0": ["user_name", "user_email", "ec_message_photo"],
                                  "column1": ["date", "user_contacts", "ec_message_photo"]
                              },
                              "fields": ["subject", "rating", "text", "published", "ec_message_photo"]
                          },
                          "reply": {
                              "name": "reply",
                              "columns": {},
                              "fields": ["reply_author", "reply_text", "notify", "notify_date", "ec_message_photo"]
                          },
                          "settings": {
                              "name": "settings",
                              "columns": {},
                              "fields": ["thread", "ip", "extended", "ec_message_photo"]
                          }
                      }
                        Наумов Алексей
                        26 февраля 2020, 08:55
                        0
                        Вы ec_message_photo желаете 5 раз вывести что ли? =)
                        Ошибки в консоли браузера смотрите.
                          alexandr.skyrda
                          28 февраля 2020, 20:35
                          0
                          а как правильно?
                          Здесь написано:
                          «располагаем поля на 3-х вкладках: main, reply, settings, а внутри вкладки main у нас еще есть 2 колонки.»
                          В консоли браузера ошибок нет
                            Наумов Алексей
                            02 марта 2020, 08:53
                            0
                            Ну не одновременно на всех же вкладках одно и тоже поле…
                            В одном месте, выбираем, где нужно.
                        Dementor218
                        27 сентября 2020, 17:39
                        0
                        Здравствуйте! Скажите, в рамках сайта мне нужно чтобы пользователь мог прикрепить от 0 до 4-х фото. Это можно сделать как-то? Подскажите, в какую сторону «копать»?
                          Николай Савин
                          27 сентября 2020, 18:36
                          +1
                          А что тут копать. Писать код нужно.
                          1. Добавить одну дополнительную таблицу для хранения информации о прикрепленных файлах и создать ее модель
                          2. Добавить связь с этой таблицей других «соседних» моделей компонента
                          3. Чуть-чуть доработать сохранение комментария. Ну… просто добавить методы сохранения изображений.
                          4. Ну и на фронте сделать по вкусу загрузчик.

                          За день можно управиться.
                            Александр Мельник
                            27 сентября 2020, 18:39
                            0
                            А ведь Николай прав. Копать нужно только в самообразование.
                              Dementor218
                              27 сентября 2020, 18:40
                              0
                              Спасибо Вам огромное) Буду пытаться) О результатах сообщу)
                          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                          41