# Описание

Модуль для Evolution CMS.

Данный модуль предназначен для

* быстрого редактирования основных полей документа (pagetitle, longtitle и тд.) и своих TV
* импорта данных из таблицы Excel (Calc) или csv
* импорта данных для MultiTV
* экспорта данных по основным полям и ТВ в .xlsx и csv
* массового переноса документов от одного родителя (папки) к другому

ссылка на [GitHub](https://github.com/Grinyaha/editDocs)

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

Perhaps someone would like to help with translating the module's interface into other languages. Send PR, I will add.&#x20;


# Установка и настройка

Модуль протестирован на разных версиях Evolution c PHP от 7.4 до 8.2. С остальными версиями могут быть проблемы.\
\
Для установки данного модуля заходим в Модули, далее Extras, далее в поисковую строку вводим editdocs. Нажимаем установить.

Для Evolution 3 необходимо предварительно установить компонент **DocLister.**

![](/files/-MZCjq-kGFHBwGow4OA8)

После того как модуль успешно установился перезагружаем страницу и идем в настройки модулей (для Evolution 1.4 это там же где и запуск модулей, для Evolution 3 это в элементах -> модули  и возле названия editDocs жмем иконку

для Evo 1.4

![](/files/-MZCkroTkF-bX0m4sMVv)

В контекстном меню выбираем **редактировать**

![](/files/-MZClHwKcATwBeDwG72v)

для evo 3

<figure><img src="/files/36gS6QG0fjmzxdDRmV9n" alt=""><figcaption></figcaption></figure>

Далее при необходимости можно поменять настройки модуля. Например прописать только нужные шаблоны или TV и тд. Для каждой опции присутствуют подсказки.&#x20;

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

<figure><img src="/files/Zb7bFUyjLbYInlpFJfEk" alt=""><figcaption></figcaption></figure>

<mark style="color:red;">**Для пользователей Evolution 3 у которых включен Tracy:**</mark>

Необходимо добавить в ваш конфиг константу NO\_TRACY, как на примере ниже: иначе возможны ошибки в работе модуля.

```
<?php
if(defined('NO_TRACY'))
{
    return false;
}
return 'adminfrontonly';
?>
```


# Редактирование документов

Редактирование документов

## Простое редактирование

Вкладка "Редактирование" открывается в модуле по умолчанию. Основные поля это ID родителя, от которого мы будем редактировать дочерние ресурсы и выбор полей или ТВ документа которые будем редактировать.&#x20;

<figure><img src="/files/o1o8fZDPTPEF2XplMlhL" alt=""><figcaption></figcaption></figure>

Опционально можно выбрать другие параметры для работы.&#x20;

* уровень вложенности
* сортировку
* пагинацию
* редактирование неопубликованных документов
* фильтрацию по TV
* имя ТВ картинки (например товара)
* рендер ТВ полей (отображать выбор параметров из возможных)
* мультикатегории

На скрине ниже показан вариант с отображением картинок, которые, например, используются для товаров в магазинах. Чтобы визуально было легче ориентироваться, можно подключить отображение картинок через опцию "имя TV-image".\
Столбец с полем id присутствует всегда по умолчанию.

<figure><img src="/files/1jcqtEvhql1NsKhuT0HT" alt=""><figcaption></figcaption></figure>

## Фильтрация

Допустим документов в ветках очень много и нам понадобилось найти и отредактировать документы по какому-то критерию. Например все документы с ценой от 1000 до 2000. Скорее всего наш TV с ценой называется прайс. Поэтому в поле "Фильтрация по ТВ" вы запишем **AND(tvd:price:>=:1000;tvd:price:<=:2000)**

![](/files/-M_LpKxwHEZt6wIPvRFU)

Таким же образом можно сделать фильтрацию по основным полям документа. Например, нам надо найти все документы, где встречается слово "кольцо". Запишем в поле "Фильтрация по основным полям" следующее: **c.pagetitle LIKE "%кольцо%"**

![](/files/-M_LrAcgQHXeOZdyb2Wy)

Или, например надо вывести все документы с id шаблона = &#x35;**,** тогда запишем **c.template=5**\
Можно комбинировать с фильтрацией по ТВ. В модуле присутствуют ссылки на документацию по фильтрации у компонента DocLister, на котором создан модуль.

## Мультикатегории

Если у вас установлен плагин "Мультикатегории", который позволяет показывать на фронте один документ в нескольких разных ветках, то вы можете быстро редактировать этот параметр с помощью модуля editDocs.

Для этого необходимо поставить соответствующую галочку.

<figure><img src="/files/AtPNoUpDflMqsd6zOlxj" alt=""><figcaption></figcaption></figure>

Далее вы можете указать id родителей-документов(папок) где будет выводиться дополнительно данный документ. Несколько id указываются через запятую.&#x20;

![](/files/-M_LwkIX91jqylAVY_TU)

**Чтобы не было конфликта, у вас на сайте НЕ ДОЛЖНО БЫТЬ TV с именем category!**


# Импорт документов

## Простой импорт

Переключаемся на вторую вкладку «ИМПОРТ/ОБНОВЛЕНИЕ»\
Для начала импорта необходимо подготовить файл-таблицу Excel от MS Office, либо таблицу Calc в Libre Office, либо файл csv в кодировке UTF-8 или Windows 1251. Пример простой таблицы ниже

![](/files/-M_Lyci3f-vWIC4kLBJn)

Столбец А и В это основные поля документа, а столбец С, соответственно ТВ-параметр. **Очередность расположения столбцов может быть любая.**

Далее кликаем на заштрихованную область мышкой, либо перетаскиваем наш файл на данную область в модуле.

<figure><img src="/files/ZVrmlXREZViN922vHbZm" alt=""><figcaption></figcaption></figure>

**В случае успеха, у нас отобразится таблица и функционал для начала импорта.** Работоспособность модуля не гарантируется в случае сложных таблиц с пустыми столбцами, строками, сложными таблицами с объединёнными ячейками и тд.

<figure><img src="/files/ffR2eOuPqJ8ThyNaXWt4" alt=""><figcaption></figcaption></figure>

* **ID родителя.** Вы можете указать одного родителя для импорта всех документов в таблице
* **Шаблон**. Вы можете указать один шаблон для всех импортируемых документов.
* **Поле по которому сверяемся.** В случае импорта только с учетом обновления данных, вы можете указать поле по которому будет происходить проверка.
* **Поля соответствия из XLS-таблицы в БД.** Сопоставляем поля из файла и поля в базе. Либо ничего не меняем, если столбцы названы именами полей.
* **Поле/TV для замены данных.** Дает возможность найти какие то вхождения и заменить их на лету перед импортом в БД сайта.
* **Снять с публикации перед импортом документы с шаблонами**. Опция позволяет перед импортом все документы с определенным шаблоном снять с публикации.
* **Не добавлять, если нет совпадений.** Вы можете запретить добавление новых документов, в случае, если таких документов нет в базе сайта, а вам нужно просто обновить документы, которые есть эксель-таблице и в базе сайта. Например при обновлении прайса на сайте.
* **Тестовый режим.** Импорт без обновления, например посмотреть какие документы совпали по базе, какие нет.
* **Импорт для MultiCategories.** Если у вас установлен плагин MultiCategories, который позволяет выводить один документ в разных категориях (ветках, папках), то вы можете прописать в таблице id данных категорий (через запятую), столбец должен называться **category**. Также важно чтобы у вас на сайте не было ТВ с именем category.

## Импорт с разными parent и template

Допустим вы делаете импорт с документами, у которых разные шаблоны и родители. Тогда просто указываете эти данные в таблице. **Данные в таблице имеют больший приоритет** чем параметры шаблон и id родителя для всех документов. Даже если они будут указаны, все равно будут использоваться данные из таблицы.

![](/files/-M_M3J3QFb7zY5AYeMbi)

Результат работы импорта в тестовом режиме.

![](/files/-M_M4XCOlrgTndpWVjXQ)

Результат работы импорта в боевом режиме.

![](/files/-M_M4czTWicfOqDJxdKB)

## Импорт с указанием разделов и подразделов (начиная с версии 2.2.0)

Данный модуль умеет определять конечного родителя для непосредственного документам в таблице. Для этого в таблице XLS-файла должны быть  указаны специальные названия столбцов: ed\_category1#3, ed\_category2#4, ed\_category3#3 и тд.,  в зависимости от вложенности,  где после разделителя # указывается ID шаблона категории. Последний и окажется конечным родителем для документа. Названия в БД ищутся по полю pagetitle раздела (подраздела). Рассмотрим пример из которого сразу все станет понятно при внимательном рассмотрении.

Это наш файл XLS

<figure><img src="/files/wmjK6vkniEO90JW65zQq" alt=""><figcaption></figcaption></figure>

А это вид админки с модулем где мы сделали импорт в каталог из 3 уровней вложенности

<figure><img src="/files/drUJKZZk56s1cp5wPOPB" alt=""><figcaption></figcaption></figure>

Таким образом, если даже для какого-то документа нам нужна вложенность два уровня, а третий остается пустой, то для документа сохранится родитель от 2-го уровня.&#x20;

**При использовании хоть одного специального столбца с именем&#x20;**<mark style="color:red;">**ed\_category**</mark>**&#x20;- параметр ID родителя из общих параметров будет игнорироваться!**

## Сложный импорт с использованием prepare

Для чего нужно использовать prepare-сниппет? Допустим у вас есть прайс где цены указаны в долларах, а вам нужно чтобы на сайте цены записались в рублях. То есть при импорте перед обновлением prepare-сниппет изменяет данные. \
\
При установке модуля у нас создается сниппет-пример, которые можно переименовать и использовать для своих нужд. Сниппетов может быть сколько угодно, в зависимости от ваших задач. Важно чтобы в имени сниппета была запись editDocs. Созданные сниппеты можно в дальнейшем выбрать из выпадающего списка.

<figure><img src="/files/UM2uzx3S9rSmja1G9qJ5" alt=""><figcaption></figcaption></figure>

Ниже код где показаны какой фрагмент кода срабатывает при каких ситуациях.

```php
<?php
//Не используйте данный сниппет как боевой, скопируйте как новый и пропишите его в настройках, иначе при обновление данный сниппет перезапишется на дефолтный example! 

$process = isset($process) ? $process : '';
$mode = isset($mode) ? $mode : '';
$total = $_SESSION['import_total']-2; //последняя итерация

switch ($process) {
	case 'import':
		//обработчик импорта

		//первая итерация
		//if ($iteration == 1) { }

		//последняя итерация
		//if ($iteration == $total) { }

		switch ($mode) {
			case 'upd':
				//обновляем ресурс
				//$data['pagetitle'] = 'import upd ' .  $data['pagetitle'];
				break;
			case 'new':
				//добавляем новый ресурс
				//$data['pagetitle'] = 'import new ' .  $data['pagetitle'];
				break;
			default:
				break;
		}
		break;
	case 'export':
		//обработчик экспорта
		//$data['pagetitle'] = 'export ' .  $data['pagetitle'];
		break;
	case 'after':
		//пост-обработка, $data['id'] - ID отредактированного или только что созданного документа.

		break;
	default:
		break;
}
return $data;


```

Давайте в тестовом режиме сделаем конвертацию на примере простой таблицы. И если данные в тестовом режиме нас устроят можно переключить конвертацию в боевой режим.

![](/files/-M_N0FCfZHeeyKm8nlA8)

```php
<?php
//Не используйте данный сниппет как боевой, скопируйте как новый и пропишите его в настройках, иначе при обновление данный сниппет перезапишется на дефолтный example!

$kurs = 100;	//курс валюты

$process = isset($process) ? $process : '';
$mode = isset($mode) ? $mode : '';
$total = $_SESSION['import_total']-2; //последняя итерация

switch ($process) {
    case 'import':
        //обработчик импорта

        //первая итерация
        //if ($iteration == 1) { }

        //последняя итерация
        //if ($iteration == $total) { }

        switch ($mode) {
            case 'upd':
                //обновляем ресурс

                $data['price'] = round($data['price'] * $kurs); //меняем цену на рубли

                break;
            case 'new':
                //добавляем новый ресурс
                //$data['pagetitle'] = 'import new ' .  $data['pagetitle'];
                break;
            default:
                break;
        }
        break;
    case 'export':
        //обработчик экспорта
        //$data['pagetitle'] = 'export ' .  $data['pagetitle'];
        break;
    case 'after':
        //пост-обработка, $data['id'] - ID отредактированного или только что созданного документа.

        break;
    default:
        break;
}
return $data;


```

Строка 4 - задаем курс валюты. Строка 29 - меняем данные. Все. В данном примере мы цена будет меняться только при апдейте данных, но не при добавлении новых документов. Из кода видно что нужно сделать чтобы данные обрабатывались и при добавлении новых документов.

![](/files/-M_N7_DoT71yfrtrkgxG)

Таким образом мы можем при помощи prepare-сниппета создавать на лету категории для товаров, если их не существует.&#x20;

Импорт по количеству товаров не ограничен, но надо понимать, что вывод таблицы в браузере в 20 000 строк, например, притормозит работу браузера.

Обработка 5 000 документов занимает примерно минуту.

Событие **after** в prepare-сниппете нужно для того, чтобы после обработки каждой строки таблицы вы получили ID редактируемого(нового) документа. В случае, если есть потребность отредактировать какие то таблицы для компонента PageBuilder, например.

## Сложный импорт с использованием prepare для сравнения полей

Бывают такие ситуации, например, когда вам отдают выгрузку с базой кодов из 1С, а там коды в верхнем регистре, а коды в базе сайта в нижнем регистре. Или в выгрузке есть пробелы в данных по которым хотим делать сравнение. На сайте код **ААББ**, а в табличке **аАБб**, например. Либо из-за формата ячеек в числах может точка стоять. Да что угодно. \
\
В сниппет у нас передается массив **$data** с ключами **db\_srav** и **xls\_srav.** Первый это данные из базы сайта, второй это из загружаемой таблички. Для манипулирования данными открываем наш prepare сниппет и добавляем туда код ниже:

```php
if ($process == 'srav') {
	
$data['db_srav'] = mb_strtolower($data['db_srav']);
$data['xls_srav'] = mb_strtolower($data['xls_srav']);

$data['xls_srav'] = str_replace('_','',$data['xls_srav']);	
	
}
```

&#x20;Не забываем проверку переменной $process и далее из кода видно что мы переводим значения в нижний регистр и в параметре из таблицы убираем нижнее подчеркивание.

## Импорт данных для MultiTV

Рассмотрим импорт на следующем примере:

<figure><img src="/files/S60FmsbkW8mBufJ8Yxiw" alt=""><figcaption></figcaption></figure>

Для этого нам необходим эксель-файл в следующем виде:

<figure><img src="/files/LArTfSpk0AVvh3SUIdeV" alt=""><figcaption></figcaption></figure>

где первый столбец у нас будет называться **mtv:param1:0**, второй **mtv:param2:0** и тд., \
где **mtv** - имя ТВ параметра (MultiTV), **param1** - заголовок (caption) параметра из конфига\
(НЕ имя, см. скрин ниже),  а **0** - номер строки.

\
![](/files/1L802lBd7zkFzjNyxMJ0)\
\
После нажатия кнопки "Начать импорт" финальная таблица перестроится с показом какие данные будут загружены в базу.

<figure><img src="/files/rVviUqNjJjFyJWcbuRTw" alt=""><figcaption></figcaption></figure>


# Экспорт документов

Для осуществления экспорта переключаемся на соответствующую вкладку. Как и при редактировании здесь два обязательных поля **ID родителя** и **необходимые поля** для экспорта.

<figure><img src="/files/NlrQDspOMaGVzbOfPu1R" alt=""><figcaption></figcaption></figure>

Экспорт производится одновременно в два формата: CSV и XLSX. После завершения экспорта файлы (на ваше усмотрение)  можно скачать по соответствующей ссылке.&#x20;

Для .xlsx рекомендуется кодировка utf-8. Для .csv какая удобнее для вашей задачи.

Фильтрация при экспорте аналогична фильтрации при редактировании.


# Массовый перенос документов

Если Вам необходимо массово из одно перенести документы из одной ветки в другую, а простыми словами, сменить родителя у документов, то можно воспользоваться опцией **Массовый перенос.** Для этого переключаемся на соответствующую вкладку.

![](/files/-M_P1bodXQQYkeKQ6kTH)

Вписываем id родителя откуда переносим документы и id родителя куда переносим документы. Все достаточно просто.


# Конфигурационные файлы

В модуле есть возможность сохранять и загружать конфиги для удобства, чтобы не заполнять постоянно много полей данными. Все поля заполнятся данными при загрузке нужного конфига.&#x20;

Сохранять конфиги можно в трех режимах, редактировании документов, импорта и экспорта.

<figure><img src="/files/kINB0QqhWhvFwUdmBPFF" alt=""><figcaption></figcaption></figure>

Сначала пишем имя конфига и жмем сохранить. Далее будет доступен выбор сохраненных конфигов в виде выпадающего списка. Далее необходимо выбрать нужный из списка и нажать загрузить.&#x20;


