[SendIt 2.0.0] Пагинация и обновлённая загрузка файлов

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

Общие изменения
1. Основные классы переехали в папку services.

2. Сессии больше не используются, потому что периодически при обновлении страницы это вызывало ошибку «Невалидный токен». Вместо них я добавил отдельную таблицу для хранения временных данных. Вы можете использовать её для своих нужд.Например так
<?php
switch($modx->event->name){
    case 'OnHandleRequest':
        if(file_exists(MODX_CORE_PATH . 'components/sendit/services/sendit.class.php')){
            include_once MODX_CORE_PATH . 'components/sendit/services/sendit.class.php';
            $session = SendIt::getSession($modx, session_id(), 'MyClass');
            $session['myparam'] = 'value';
            SendIt::setSession($modx, $session, session_id(), 'MyClass');
        }
        break;    
}
Статический метод getSession первым параметром принимает объект $modx, вторым параметром — идентификатор сессии можно использовать стандартный или любую строку, третьим параметром вы можете передать идентификатор именно ваших записей, если не указать будет использовано значение 'SendIt'.

Статический метод setSession принимает все те же параметры с той лишь разницей, что вторым параметром нужно передать массив данных, которые вы хотите сохранить.

Есть ещё статический метод clearSession, который принимает два параметра объект $modx и идентификатор ваших записей, он позволяет очистить все сохранённые вами данные, для которых истёк срок хранения указанный в системной настройке si_storage_time.

3. Проверка частоты и количества отправок больше не работает для форм без хуков Email или FormItAutoResponder. Если этих хуков нет, но проверка частоты нужна добавьте в пресет параметр antispam. Так же с помощью параметров можно изменять общие настройки частоты (pauseBetweenSending) и количества (sendingPerSession) отправок.

4. Чтобы была возможность создавать несколько плагинов изменяющих параметры вызова на событие OnGetFormParams в параметры события был добавлен объект SendIt.
<?php
switch ($modx->event->name) {
    case 'OnGetFormParams':
        if ($presetName === 'mypreset') {
            $SendIt->pluginParams['mykey'] = 'myvalue';
        }
        break;
}

5. Если вы использовали API компонента для отправки данных, а именно метод prepareSendParams(), то при обновлении имейте в виду, что количество и порядок необязательных параметров изменились.
Было
prepareSendParams(root, preset = '', event = 'submit', action = 'send', params = new FormData())
Стало
prepareSendParams(root, preset = '', params = new FormData(), action = 'send')
6. Наследование параметров пресета теперь работает между файлами, для этого нужно указать в параметре extends значение в формате имя_файла_без_расширения.имя_пресета.

7. Теперь SendIt умеет сам вставлять результат работы сниппета вызванного через ajax, если этот результат представляет собой строку. Чтобы это работало пресет должен содержать параметры
  • resultBlockSelector — CSS-селектор блока показа результатов
  • resultShowMethod — метод показа результатов insert — вставка, append — добавление
И конечно же ваш сниппет должен возвращать ответ в нужном формате.
$html = $modx->runSnippet('pdoResources', $SendIt->params)
return $SendIt->success('Ваше сообщение', ['html' => $html]);

Загрузка файлов
1. Добавил очередь загрузки. Пользователь может добавлять файлы в очередь до тех пор, пока их количество не достигнет максимально разрешённого. При этом, пока загрузка файла не началась, его можно удалить из очереди кликом по прогресс-бару с именем файла.

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

3. Сообщение об удалении файлов больше не будет показано при отправке основной формы.

4. Теперь можно указывать желаемые единицы измерения прогресса загрузки. По умолчанию прогресс показывается в процентах, однако с помощью параметра пресета loadedUnit можно поменять значение на одно из следующих b, mb, kb, gb, gb, при этом регистр значения не имеет.

5. Вы можете управлять точностью округления значений прогресса с помощью системной настройки si_precision

Квизы
1. Добавил в квиз JS событие si:quiz:progress, с его помощью можно корректировать отображение прогресса.

2. Добавил возможность убирать не нужные кнопки в квизе, теперь это не вызывает ошибок в консоли браузера.

Идентификация
1. Изменил метод сброса пароля. Теперь сброс пароля нужно подтверждать, переходом по ссылке из письма. Для активации нового пароля нужно вызвать сниппет ResetPassword на странице из параметра activationResourceId.
2. Для проверки существования пользователя добавил валидатор userExists. Его можно использовать если в ЛК у пользователя есть возможность менять username.

Пагинация
Это абсолютно новая функциональность для данного компонента. Использовать её можно с любыми сниппетами, главное, чтобы они устанавливали плейсхолдер с общим количеством результатов. На одной странице можно использовать сколько угодно пагинаций. Есть возможность динамически менять параметры сниппета и пользоваться пагинацией. Например можно реализовать поиск по результатам работы сниппета. Для этого понадобится вот такая разметка
<section class="py-160-80 w-100 overflow_hidden">
    <div class="container">
        <form action="#" class="bs_big_shadow border-1 border_main radius_small p-30-15 bg_body mb-30" id="searchForm" data-si-form data-si-nosave>
            <div class="mb-100 d_flex flex_column">
                <p class="mb-30 fs-24-18 ts_default">
                    Пример реализации кастомного поиска и вывода результатов с пагинацией. Начните вводить любую часть ФИО из списка ниже.
                </p>
                <label class="mb-30">
                    <input type="text" name="query" data-si-event="input" data-si-preset="pagination-search"
                           class="form__input radius_pill border-1 border_primary focus_shadow_primary px-15 py-15 color_primary fs-18-16 w-100 bs_small_shadow"
                           placeholder="Поисковый запрос">
                </label>
            </div>
        </form>


        <div data-pn-result="three" style="display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));grid-template-rows: auto; gap:15px; margin-bottom: 50px;">
            {'!Pagination' | snippet: [
            'parents' => 7,
            'query' => '',
            'snippet' => '!Pagination',
            'render' => '!pdoResources',
            'presetName' => 'pagination-search',
            'tpl' => '@FILE chunks/pdoresources/item.tpl',
            'tplEmpty' => '@FILE chunks/pdoresources/empty.tpl',
            'limit' => 6,
            'includeContent' => 1,
            'setTotal' => 1,
            'pagination' => 'three',
            'resultBlockSelector' => '[data-pn-result="three"]',
            'resultShowMethod' => 'insert'
            ]}
        </div>
        <!-- PAGINATION -->
        {set $totalPages = 'three.totalPages' | placeholder}
        {set $currentPage = 'three.currentPage' | placeholder}
        {set $limit = 'three.limit' | placeholder}
        <div style="display:flex;justify-content:space-between;align-items: center" data-pn-pagination="three" data-pn-type="" class="{$totalPages < 2 ? 'v_hidden' : ''}">
            <button style="padding:10px;" type="button" data-pn-more="">Загрузить ещё</button>
            <div style="display:flex;gap:10px;">
                <button style="padding:10px" type="button" data-pn-first="1"><<</button>
                <button style="padding:10px" type="button" data-pn-prev=""><</button>
                <input style="width: 60px;" type="number" name="threepage" data-pn-current data-si-preset="pagination-search" form="searchForm" min="1" max="{$totalPages}"
                       value="{$currentPage?:1}">

                <p style="display:flex;align-items: center;gap:5px;">из
                    <span data-pn-total="">{$totalPages?:1}</span>
                </p>
                <button style="padding:10px" type="button" data-pn-next="">></button>
                <button style="padding:10px" type="button" data-pn-last="{$totalPages}">>></button>
            </div>

            <p>Показывать по <input type="number" name="limit" data-pn-limit form="searchForm" min="1" max="96" value="{$limit?:12}"></p>
        </div>
    </div>
</section>
и плагин
<?php
switch($modx->event->name) {
    case 'OnBeforePageRender':
        if($_REQUEST['query']){
            $SendIt->params['where']['pagetitle:LIKE'] = '%' . $_REQUEST['query'] . '%';
        }
        break;
}
Перемещение по страницам можно осуществлять как кнопками, так и прокруткой (data-pn-type=«scroll»). Для отслеживания прокрутки используется Intersection Observer API.

Спасибо за внимание. Донаты приветствуются.
Артур Шевченко
10 июня 2024, 21:11
modx.pro
1
1 634
+8
Поблагодарить автора Отправить деньги

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

Сергей
22 июля 2024, 14:18
0
Артур, добрый день!
Можно хотя бы один пример создания простой формы с защитой от спама?
Просто если посмотреть в документацию, адрес tpl не тот, presetName тоже не тот.
Тут вы пишете в пункте 2, что больше нет ошибки «Невалидный токен», а я получается ставлю версию 2.1.0 (ранее не было ни какой) и ловлю эту ошибку) и не как не могу понять, как решить эту проблему)

Хотя я нашел проблему.
Could not create table `si_sessions` SQL: CREATE TABLE `si_sessions` (`id` INTEGER unsigned NOT NULL AUTO_INCREMENT, `session_id` VARCHAR(100) NOT NULL, `class_name` VARCHAR(100) NOT NULL, `data` JSON NULL, `createdon` DATETIME NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `app_session` (`session_id`,`class_name`), INDEX `createdon` (`createdon`)) ENGINE=MyISAM ERROR: Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'JSON NULL, `createdon` DATETIME NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `app_se' at line 1 )
Почему-то не создается таблица

Версия php 7.4, версия modx 2.8.7
    Артур Шевченко
    22 июля 2024, 19:55
    0
    Можно хотя бы один пример создания простой формы с защитой от спама?
    Любая форма по умолчанию защищена от спама если в пресете есть хук email или FormItAutoResponder.

    Почему-то не создается таблица
    Во-первых проверьте версию сервера баз данных MySQL 5.7 или MariaDB 10.4. Во-вторых, попробуйте удалить все вервии пакета и установить самую свежую заново.
      Сергей
      22 июля 2024, 19:58
      0
      У меня устаревшая MariaDB, это я уже выяснил, что бы установить надо переходить на другой хостинг.
        Николай Савин
        23 июля 2024, 09:46
        0
        Ой, а можно поинтересоваться — устаревшая это какая? Так то десятая версия тоже не свежа давно. Уже 12 есть.
          Сергей
          23 июля 2024, 09:49
          0
          У меня VPS
          centOS 7
          5.5.68-MariaDB
          Там просто много сайтов и придется похоже все переносить.
            Николай Савин
            23 июля 2024, 13:37
            0
            Ужас )) Да, пора бы обновиться. Это все древнее даже для древнего MODX2
              Сергей
              24 июля 2024, 10:42
              0
              Как вы считаете, что лучше Debian и Ubuntu для modx? Я бы выбрал centos. но там нет поддержки isp6.
                Вячеслав Варов
                24 июля 2024, 17:44
                0
                У меня Ubuntu и настроил все на NGINX — работает норм
    Konstantin
    28 июля 2024, 10:29
    0
    Подскажите как быть если по соображениям безопастности папка core находится в другом месте и переименована? при установке пакета sendit белый экран. Простой перенос файлов из автосозданной при установке пакета папки core в мою core ничего не изменилось — белый экран, заработало только когда вернул папку core в корень сайта. Но теперь эта папка доступна извне что не безопасно, Подскажите как решаете этот вопрос вы?
      Артур Шевченко
      28 июля 2024, 10:47
      0
      Не выношу папку core и, должен сказать, за 6 лет проблем с безопасностью не было.

      теперь эта папка доступна извне
      Эта проблема решается настройкой конфигурации сервера.
        Konstantin
        06 августа 2024, 17:51
        0
        На свой страх и риск вы можете не выносить core, однако создатели движка настоятельно рекомендуют это сделать и у меня несколько сайтов так работают. Хочется перейти на sendit, но без риска для сайтов. Сайты работают на обычных shared хостингах так что особенно там ничего не «сконфигурируешь».
          Артур Шевченко
          06 августа 2024, 23:31
          1
          0
          создатели движка настоятельно рекомендуют это сделать
          Что мешает сделать так же (см. под заголовком Protect the Core and Other Locations) со второй версией?

          Я не отрицаю наличие проблемы, просто не знаю как её решить со стороны компонента.
            Konstantin
            07 августа 2024, 08:38
            0
            А вот это уже дело говорите. Добавил в корневой htaccess эти правила и закрыл core с глаз долой:

            # Закрыть доступ к core и другим чувствительным файлам/директориям
            RewriteCond %{REQUEST_URI} ^/(core|config\.core\.php|_build|_gitify|_backup) [NC]
            RewriteRule ^.*$ - [F,L]
            # Установить пользовательскую страницу ошибки для 403
            ErrorDocument 403 /error401
      Konstantin
      08 августа 2024, 08:35
      0
      Профиксите пожалуйста баг — при загрузке файлов валидатор ругается на файлы у которых в названии присутствуют точки считая что после них должно быть сразу расширение, не найдя нужного расширения после них выдает ошибку — что может смутить человека который отправляет файлы с фронта
        Артур Шевченко
        08 августа 2024, 13:58
        0
        Исправил. Потратил своё обеденное время, только чтобы ты доволен был.
        Ivan K.
        21 августа 2024, 10:34
        +2
        Здравствуйте.
        Решил на новом проекте использовать ваш замечательный компонент.
        Отлично все реализовано, спасибо вам за труд.
        Но в документации нашел опечатку:
        docs.modx.pro/components/sendit/development
        Раздел «Свой сниппет для обработки данных „
        У вас
        return $SendIt->error($validationErrorMessage, ['erorrs' => ['fieldName' => 'Тут текст ошибки']]);
        Так не работает, так как опечатка в “erorrs» нужно «errors».
          Ivan K.
          16 сентября 2024, 18:43
          0
          Здравствуйте.
          Не подскажите как корректно получить id ресурса, с которого идет отправка формы. Использую свой сниппет для обработки данных, в нем хотел применить вот такой код:
          $res_id = $modx->resource->get('id');
          Ранее использовал FetchIt, там такой подход работал.
          С SendIt, что не получилось и в логах пусто. Получается если только передать id ресурса в самой форме в скрытом поле, но я не уверен, что это верный и корректный способ.
          <input type="hidden" name="res_id" value="[[*id]]">
            Артур Шевченко
            16 сентября 2024, 19:46
            0
            Вполне корректный способ, передавайте через скрытое поле.
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            18