Наверх

Реализация админки во фронтэнде сайта на MODX Revo

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

Начал я с того, что написал сниппет addResource, который будет создавать новый ресурс с указанным заголовком и прочими параметрами:

// Сниппет будет получать данные из формы методом POST
$title       =  $_POST['title'];
$content     =  $_POST['content'];
$introtext   =  $_POST['introtext'];
$description =  $_POST['description'];
$parent      =  $_POST['parent'];
$template    =  $_POST['template'];
$color       =  $_POST['color']; // Это значение будем заносить
                                 // в TV-параметр color

// Если некоторые значения не будут указаны,
// они будут установлены по умолчанию
if (!$introtext)   $introtext = $title;
if (!$description) $description = $introtext;
if (!$parent)      $parent = 1;
if (!$template)    $template = 1;


// Создаем ресурс
$response = $modx->runProcessor('resource/create', array(
        'pagetitle' => $title,
        'longtitle' => $title,
        'description' => $description,
        'introtext' => $introtext,
        'content' => $content,
        'template' => $template,
	'published' => 1,
	'parent' => $parent));
if ($response->isError()) {
    return $modx->error->failure($response->getMessage());
}

$newResource = $response->response['object'];

// Устанавливаем значение TV-параметра color
$tv = 3; // id-шник TV-параметра
$value = $_POST['color']; // значение TV-параметра

$tvar = $modx->newObject('modTemplateVarResource');
$tvar->set('contentid', $newResource['id']);
$tvar->set('tmplvarid', $tv);
$tvar->set('value', $value);
$tvar->save();

// Очищаем кеш, чтобы изменения были видны сразу
  $modx->cacheManager->refresh();
  return true;
Кроме него у меня есть сниппет editResource, соответственно для редактирования ресурсов, созданных ранее:

// Получаем данные из формы
$title   =  $_POST['title'];
$content =  $_POST['content'];
$resId   =  $_POST['resId'];

// Получаем ресурс по id ресурса
$resource = $modx->getObject('modResource',array('id'=>$resId));

// Устанавливаем нужные значения
$resource->set('pagetitle',$title);
$resource->set('longtitle',$title);
$resource->set('content',$content);

// Сохраняем ресурс
if ($resource->save()) {
  
// Очищаем кеш, чтобы изменения были видны сразу
  $modx->cacheManager->clearCache();
  return true;
} 

return false;
Теперь нам надо в эти сниппеты значения все-таки передать. Создаем две странички – страница добавления материала и страница редактирования материала. Для форм я использовал сниппет FormIt.
Страница добавления материалов:

[[!FormIt?
   &hooks=`addResource,redirect`
   &validate=`title:required`
   &redirectTo=`218`]]
   
<form action="[[~[[*id]]]]" method="post" class="form">
    <input type="hidden" name="template" id="template" value="9" />
    <label for="title">Заголовок:<br />
    <span style="color:#cc0000">[[!+fi.error.title]]</span><br /> 
    </label>
    <input type="text" name="title" id="title" /><br />
	<label for="introtext">Аннотация:<br /></label>
	<input type="text" name="introtext" id="introtext" /><br />
        <label for="color">Цвет (TV-параметр):<br /></label>
	<input type="text" name="color" id="color" /><br />
        <label for=" content ">Полный текст:<br /></label>
	<textarea id="content" name="content"></textarea><br />
	<input type="submit" value="Отправить!" />
</form>
  • &hooks — то, что будет выполняться при отправке формы. В данном случае, это сниппет addResource и перенаправление на страницу с сообщением об успехе.
  • &validate — проверка значений формы. У нас title обязательно должен быть заполнен.
  • &redirectTo — id ресурса, на который будет перенаправляться пользователь, если сниппет addResource вернет true.

Для страницы редактирования материалов я написал сниппет getContent, который возвращает текущие значения параметров редактируемого ресурса (хотя, как я сейчас уже знаю, можно было не изобретать велосипед, а воспользоваться сниппетом getResourceField):

$output = '';
// Получаем ресурс по его id
$res = $modx->getObject('modResource',array('id'=>$id));

// В зависимости от того, что нам нужно получаем то или иное значение
switch ($need) {
  case "title": $output = $res->get('pagetitle'); break;
  case "content": $output = $res->get('content'); break;
  case "introtext": $output = $res->get('introtext'); break;
}
return $output;
Страница редактирования материалов:

[[!FormIt?
   &hooks=`editResource,redirect`
   &validate=`title:required`
   &redirectTo=`221`]]

<form action="[[~[[*id]]]]" method="post" class="form">

    <input type="hidden" name="resId" id="resId" value="3" />

    <label for="title">Заголовок:<br />
     <span style="color: #cc0000;">[[!+fi.error.title]]</span><br />
    </label>
    <input type="text" name="title" id="title"
      value="[[!getContent? &need=`title` &id=`3`]]" /><br />
    <label for="introtext">Аннотация:<br /></label>
    <input type="text" name="introtext" id="introtext"
      value="[[!getContent? &need=`introtext` &id=`3`]]" /><br />
    <label for=" content ">Полный текст:<br /></label>
    <textarea id="content" name="content">
     [[!getContent? &need=`content` &id=`3`]]
    </textarea><br />
    <input type="submit" value="Сохранить!" />
</form>
Далее нам необходимо создать группу ресурсов (Безопасность -> Группы ресурсов), к которой нужно ограничить доступ, после чего добавить в эту группу обе наши странички и установить сниппет Login для того, чтобы можно было авторизоваться прямо на сайте.

Получилась такая вот симпатичная админка:


UPD. Обновил топик, отредактировал код сниппетов благодаря советам в комментариях. Огромное спасибо bezumkin и valikras. G+

Оригинал статьи community.modx-cms.ru/blog/tips_and_tricks/7489.html


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

  1. Илья Кондитеров 01 октября 2013, 18:25(Комментарий был изменён) # 0
    Я выполнил всё по статье, не получается создать/отредактировать.
    При добавлении валидация срабатывает, но в итоге пишет ошибка сервера, опыта мало с ModX, может что не так делаю? подскажите.
    1. Илья Уткин 02 октября 2013, 10:08(Комментарий был изменён) # 0
      Ошибка может быть где угодно. Я же не экстрасенс… Даже не знаю, чем вам помочь
      1. Илья Кондитеров 02 октября 2013, 12:27(Комментарий был изменён) # 0
        Простите, херню сморозил =)
        Перекапываю заново
      2. Евгений 03 апреля 2014, 00:08 # 0
        Учи php и SQL и у тя все получиться и не будешь пользоваться разными модх а будешь делать сам свои модули и тд и тп
        1. Александр 03 марта 2018, 13:37 # 0
          угу сам. напиши, кэширование, политику безопастности,……… потом сравни код О да это же modx :)

          да я не спорю свой велосипед всегда чище едет, Но он как правило заточен под конкретную задачу.

          любой cms как таковой имеет избыточный код. следовательно работает медленнее нативного решения.

          modx чем то схож с gentoo — делай что хочешь но знай что ты хочешь — отсюда выше требования к знаниям.
      3. Александр Фоменко 09 октября 2013, 12:02(Комментарий был изменён) # 0
        Подскажите, как добавить несколько ТВ параметров?
        1. Илья Уткин 09 октября 2013, 12:07(Комментарий был изменён) # 0
          Смотрите в примере обработку переменной $color — она записывается именно в TV. По аналогии и делайте остальные.
          1. Александр Фоменко 09 октября 2013, 12:17(Комментарий был изменён) # 0
            // Устанавливаем значение TV-параметра color
            $tv = 3; // id-шник TV-параметра
            $value = $_POST['color']; // значение TV-параметра
            
            $tvar = $modx->newObject('modTemplateVarResource');
            $tvar->set('contentid', $newResource['id']);
            $tvar->set('tmplvarid', $tv);
            $tvar->set('value', $value);
            $tvar->save();
            то есть нужно повторить нужное количество раз данный кусок кода?
            1. Илья Уткин 09 октября 2013, 13:57(Комментарий был изменён) # 0
              Да, можно несколько раз написать, а можно пройтись циклом, чтобы один и тот же код не был дважды написан. Как-то так:
              $tvsArr = array(
                3 => 'color',
                5 => 'font',
                6 => 'list'
              );
              
              foreach ($tvsArr as $tv => $name) {
              	$value = $_POST[$name]; // значение TV-параметра
              
              	$tvar = $modx->newObject('modTemplateVarResource');
              	$tvar->set('contentid', $newResource['id']);
              	$tvar->set('tmplvarid', $tv);
              	$tvar->set('value', $value);
              	$tvar->save();
              }
              1. Alex Lotz 07 июля 2016, 01:15 # 0
                а как сохранить в tv путь для загружаемой картинки?
                1. Илья Уткин 07 июля 2016, 10:33 # +1
                  Точно так же, как и значение любого ТВ
                  $resource->setTVValue('image', $path);
                  1. Alex Lotz 07 июля 2016, 10:58 # 0
                    Эм, а где это ставить в addResource?
                    1. Илья Уткин 07 июля 2016, 11:20 # +1
                      Ну готового решения у меня нет. Файл надо сначала загрузить на сервер, поместить путь к файлу в переменную $path и сохранить это значение в ТВ.
        2. Михаил Лавронов 16 октября 2013, 12:34(Комментарий был изменён) # 0
          Илья привет!
          Слушай вопрос. Вот редактирование документа:
          <form action="[[~[[*id]]]]" method="post" class="form">
          
              <input type="hidden" name="resId" id="resId" value="3" />
          
              <label for="title">Заголовок:<br />
               <span style="color: #cc0000;">[[!+fi.error.title]]</span><br />
              </label>
              <input type="text" name="title" id="title"
                value="[[!getContent? &need=`title` &id=`3`]]" /><br />
              <label for="introtext">Аннотация:<br /></label>
              <input type="text" name="introtext" id="introtext"
                value="[[!getContent? &need=`introtext` &id=`3`]]" /><br />
              <label for=" content ">Полный текст:<br /></label>
              <textarea id="content" name="content">
               [[!getContent? &need=`content` &id=`3`]]
              </textarea><br />
              <input type="submit" value="Сохранить!" />
          </form>
          
          Это твой который.
          У меня 2 вопроса:
          1. Выставляем id в примере на 3, т.е. ресурс номер 3. А это от какого ресурса id. Я вот тут не въехал.
          2. И подскажи как проводить валидацию xpdo а то все что не введешь в формы то и попадает.
          1. Илья Уткин 16 октября 2013, 12:49(Комментарий был изменён) # 0
            1. Это id ресурса, который надо отредактировать. Его можно узнать разными способами. Я, например, передавал в get параметре. То есть, на странице для менеджеров делал ссылку:
            <a href="edit/?id=[[*id]]">Редактировать</a>
            А на странице edit/ в тех местах, где надо указать id, писал
            [[!get? &need=`id`]]
            Сниппет get возвращал значение нужного get-параметра как-то так:
            <?php
            return (int) $_GET[$need];
            2. Валидацию проводи в сниппетах addResource и editResource — проверяй значение приходящих в $_POST значений в самом начале сниппета.
            1. Михаил Лавронов 16 октября 2013, 13:02(Комментарий был изменён) # 0
              А понял, ты просто для примера поставил. ок ясно.
              А по поводу проверки, мне свои проверки писать или можно использовать какие то встроенные в Modx? Я вот только не нашел встроенных или просто плохо искал
              1. Илья Уткин 16 октября 2013, 13:12(Комментарий был изменён) # 0
                Ну в MODX xPDO используется, кроме всего прочего, и для предотвращения инъекций — все данные заботливо экранируются. Так что тут надо именно свои проверки писать, ведь никто не знает, что конкретно ты хочешь проверять и какие данные разрешать пользователю вносить. Попробуй использовать Jevix для фильтрации вывода — он поможет избежать XSS, тогда, если человек напишет в любом месте
                "><script>alert('XSS')</script>
                он не увидит никакого алерта и не сможет ни забрать куки, ни как-то украсть данные пользователей.

                По умолчанию Jevix вырезает все теги script, iframe вместе с их содержимым.
          2. Павел Пустота 13 декабря 2013, 22:08(Комментарий был изменён) # 0
            Приветствую!
            Решаю аналогичную задачу. Форму отправляю через Formit, сниппет публикующий ресурсы свой. Проблема в следующем:
            Formit вырезает весь html код из формы. А мне нужно в форме использовать wysiwyg-редактор для контента. У тебя, как я вижу, тоже используется wysiwyg. Как ты обошёл эту проблему?
            1. Илья Уткин 13 декабря 2013, 22:28(Комментарий был изменён) # 0
              В настройках системы есть параметр «Вырезать HTML из массива POST», вот его нужно отключить.
            2. Михаил 18 марта 2014, 15:09 # 0
              Добрый день!
              Интересует возможность предоставить выбор шаблона (выпадающий список) из определенной категории, не смог найти в официальной документации.
              Заранее благодарю за наводки.
              1. Илья Уткин 18 марта 2014, 15:15 # 0
                Возможно, можно создать плагин, который будет удалять из списка шаблонов те, которые не принадлежат нужной категории. Но как это сделать я не знаю, к сожалению.

                По умолчанию в MODX такой функции нет.
              2. Михаил 19 марта 2014, 08:38 # 0
                Скорее всего надо формировать запрос с условием если брать напрямую из БД, а список всех шаблонов возможно как то получить?
                1. Михаил 19 марта 2014, 10:18 # 0
                  <?php
                  $templates = $modx->getCollection('modTemplate', array('category' => 1));
                  // где 1 - ID категории
                  
                  // Для нескольких категорий
                  $templates = $modx->getCollection('modTemplate', array('category:IN' => array(1,2,3)));
                  
                  $templatesNames = array();
                  foreach ($templates as $t) {
                      $templatesNames[$t->id] = $t->templatename;
                  }
                  помог с решением vanchelo
                  1. Илья Уткин 19 марта 2014, 10:37 # 0
                    Ну можно было и самому разобраться) По крайней мере, на будущее, с xPDO лучше дружить.
                  2. Михаил 19 марта 2014, 11:05 # 0
                    Будем копать) главное «знать направление»
                    1. Сергей Кутковец 27 мая 2014, 17:44(Комментарий был изменён) # 0
                      Сделал все как написано.

                      Указал дефолтные значения $parent и $tamplate в addResource, прописал имя и айдишник своего tv
                      При добавлении ресурса редирект выполняется, то есть addResource возвращает true,

                      Но якобы созданный ресурс не появляется.

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

                      В группу ресурсов, доступных этим пользователям страница с формой добавления ресурса добавлена.

                      Что не так?
                      1. Илья Уткин 27 мая 2014, 17:53 # +1
                        А у пользователей есть права на создание ресурсов?
                        1. Сергей Кутковец 27 мая 2014, 18:23 # 0
                          Поставил ради эксперимента группе юзверей минимальную роль Super User — 0 и политику доступа Resource.

                          Все равно не добавляется публикация
                      2. Сергей Кутковец 27 мая 2014, 17:54 # 0
                        пля…
                        хороший вопрос
                        1. Илья Уткин 27 мая 2014, 17:56 # +1
                          Этот вариант подходит больше именно для кастомной админки для клиента. Если надо дать пользователям создавать странички, используйте лучше Tickets
                          1. Сергей Кутковец 29 мая 2014, 14:21 # 0
                            в том то и соль, что нужен кастом.
                            Но даже при правах Super User — 0 и дефолтной политике Resource форма отрабатывает, addResource отрабатывает, а ресурс не создается.

                            Уже все перелопатил(
                            1. Сергей Кутковец 20 октября 2014, 20:52 # 0
                              Ларчик просто открывался.
                              Нужно было назначить alias
                            2. Сергей Кутковец 20 октября 2014, 20:50(Комментарий был изменён) # 0
                              Подскажите пожалуйста!
                              В форме добавления ресурса нужна такая конструкция для ввода TV:

                              <select name="ingredients" id="ingredients" multiple="multiple" > 
                              [[!getResources? 
                              &parents=`2` 
                              &limit=`0` 
                              &tvFilters=`groupe==2||3` 
                              &tpl=`@INLINE <option class="listoption" value="[[+id]]">[[+pagetitle]]</option>` 
                              &hideContainers=`1`
                              ]]
                              </select><br />
                              Возвращает только одно значение, не смотря на то, что это multiselect.
                              т.е. не зависимо от того сколько позиций выбрано, публикуется только одна (похоже последняя)

                              Мучусь уже почти сутки, не могу понять как получить все введенные значения.
                              Прошу помощи.
                          2. Сергей Кутковец 22 октября 2014, 11:17(Комментарий был изменён) # 0
                            Насколько я понимаю
                            Во-первых селект должен быть таким:
                            <select name="ingredients[ ]" id="ingredients" multiple="multiple" >
                            И во-вторых в «первой части» addResource переменную нужно обрабатывать как массив:

                            $ingredients       =  array();
                            	foreach ($_POST['ingredients'] as $t) {
                            }
                            
                            Как-то так?
                            1. Илья Уткин 22 октября 2014, 11:25 # 0
                              Ну, видимо, да. Я не знаю, что у вас там за ТВ и в каком формате он ждет данные. Может, нужно преобразовывать в JSON вообще…
                              1. Сергей Кутковец 22 октября 2014, 11:36 # 0
                                и что потом с этим $t делать?
                                записывать ее в переменную на стадии записи значения в ТВ?
                                но как это сделать не понятно.

                                В ТВ в конечном итоге должны попасть значения из мультиселекта через запятую
                                1. Илья Уткин 22 октября 2014, 11:39 # 0
                                  Не знаю. Так просто в это все не вникнуть. Надо бы развернуть пример на test.modx.pro и написать вопрос, например, на modx.pro У кого будет время посмотреть, тот и ответит.
                            2. Сергей Кутковец 22 октября 2014, 11:33 # 0
                              TB — мультиселект, который должен выдать айдишники ресурсов через запятую
                              1. Сергей Кутковец 23 октября 2014, 16:24 # 0
                                Нашел простое решение, если кому интересно как множественные значения записать в ТВ в виде строки значений через запятую.

                                Удобно в случае если эта ТВ потом используется для вывода ресурсов по их ID, скажем с помощью какого-то getResouces.

                                Имя поля обозначаем так:
                                name="name[]"
                                А запись значения в ТВ делаем так: в addResouces

                                $tv = 3; // id-шник TV-параметра
                                $value = implode ( "," , $_POST [ 'name' ]); // значение TV-параметра
                                вот и все!
                                1. Сергей Кутковец 19 декабря 2014, 13:47 # 0
                                  С добавлением норм.
                                  При редактировании выдало такое:

                                  Fatal error: Call to a member function save() on a non-object in
                                  .../core/cache/includes/elements/modsnippet/37.include.cache.php on line 27
                                  1. Илья Уткин 19 декабря 2014, 14:13 # 0
                                    Это значит, что вы пытаетесь сохранить несуществующий ресурс. Либо не передали id-шник, либо он неверный.
                                  2. Сергей Кутковец 19 декабря 2014, 13:52 # 0
                                    37 — это у меня как раз editResource
                                    а строка 27 — это сброс кеша
                                    1. Сергей Кутковец 19 декабря 2014, 13:56 # 0
                                      но если убрать сброс кеша, ничего не меняется
                                      1. Сергей Кутковец 19 декабря 2014, 14:04 # 0
                                        Если это:
                                        if ($newResource->save()) {
                                          $modx->cacheManager->clearCache();
                                          return true;
                                        }


                                        Заменить на это:
                                        $resource->save();
                                        $modx->cacheManager->clearCache();
                                        редактирует, но почему-то не редиректит formit
                                        1. Илья Уткин 19 декабря 2014, 14:14 # 0
                                          Чтобы был редирект, обязательно должна быть строчка
                                          return true;
                                        2. Сергей Кутковец 19 декабря 2014, 14:17 # 0
                                          ок!
                                          вместо этого:
                                          if ($newResource->save()) {
                                            $modx->cacheManager->clearCache();
                                            return true;
                                          }


                                          работает это:
                                          if ($resource->save()) {
                                            $modx->cacheManager->clearCache();
                                            return true;
                                          }
                                          1. Илья Уткин 19 декабря 2014, 14:22 # 0
                                            Ну, конечно, это была опечатка в коде )))
                                          2. Сергей Кутковец 22 декабря 2014, 10:58 # 0
                                            Вы забыли еще добавить:
                                            В editResource (где устанавливаем нужные значения), что TV записываем так:

                                            $resource->setTVValue('tv_name',$tv_name);
                                            ну а из get их получаем так же.

                                            P.S. Хотя это наверное очевидно
                                            1. Alexander 17 февраля 2015, 22:13 # 0
                                              добрый день, а как правильно прописать управление pub_date и unpub_date соответственно? Т.е. что бы ресурсы публиковались по расписанию.
                                              1. Илья Уткин 18 февраля 2015, 07:42 # 0
                                                Точно так же, как прописываете управление и любым другим полем. Они ничем не отличаются от того же publeshedon.
                                              2. Alexander 18 февраля 2015, 08:32(Комментарий был изменён) # 0
                                                // Создаем ресурс
                                                $response = $modx->runProcessor('resource/create', array(
                                                        'pagetitle' => $title,
                                                	.......
                                                
                                                	'pub_date' => $pub_date,
                                                
                                                	.......
                                                	'published' => 1,
                                                	'parent' => $parent,
                                                	
                                                ));
                                                if ($response->isError()) {
                                                    return $modx->error->failure($response->getMessage());
                                                }
                                                
                                                $newResource = $response->response['object'];
                                                
                                                или я не правильно понял?

                                                1. Илья Уткин 18 февраля 2015, 08:35 # 0
                                                  Да, совершенно верно
                                                  1. Alexander 18 февраля 2015, 09:22 # 0
                                                    тогда надо подправить только вызов FormIt

                                                    [[!FormIt?
                                                       &hooks=`editResource,redirect`
                                                       &validate=`title:required`
                                                       &redirectTo=`221`]]
                                                    
                                                    <form action="[[~[[*id]]]]" method="post" class="form">
                                                    
                                                        <input type="hidden" name="resId" id="resId" value="3" />
                                                    
                                                        <label for="title">Заголовок:<br />
                                                         <span style="color: #cc0000;">[[!+fi.error.title]]</span><br />
                                                        </label>
                                                        <input type="text" name="title" id="title"
                                                          value="[[!getContent? &need=`title` &id=`3`]]" /><br />
                                                        <label for="introtext">Аннотация:<br /></label>
                                                    ................................
                                                        	<input type="text" name="pub_date" id="pub_date" /><br />
                                                    	<label for="pub_date">Дата публикации:<br /></label>
                                                    ................................
                                                        <input type="text" name="introtext" id="introtext"
                                                          value="[[!getContent? &need=`introtext` &id=`3`]]" /><br />
                                                        <label for=" content ">Полный текст:<br /></label>
                                                        <textarea id="content" name="content">
                                                         [[!getContent? &need=`content` &id=`3`]]
                                                        </textarea><br />
                                                        <input type="submit" value="Сохранить!" />
                                                    </form>
                                                    
                                                    как я понял тут я что-то не то сделал, т.к. pub_date сохранился в Описании и Аннотации.
                                                    1. Илья Уткин 18 февраля 2015, 09:32 # +1
                                                      [[!FormIt?
                                                         &hooks=`editResource,redirect`
                                                         &validate=`title:required`
                                                         &redirectTo=`221`]]
                                                      
                                                      <form action="[[~[[*id]]]]" method="post" class="form">
                                                      
                                                          <input type="hidden" name="resId" id="resId" value="3" />
                                                      
                                                          <label for="title">Заголовок:<br />
                                                           <span style="color: #cc0000;">[[!+fi.error.title]]</span><br />
                                                          </label>
                                                          <input type="text" name="title" id="title"
                                                            value="[[!getContent? &need=`title` &id=`3`]]" /><br />
                                                      ................................
                                                      	<label for="pub_date">Дата публикации:<br /></label>
                                                          	<input type="text" name="pub_date" id="pub_date" /><br />
                                                      ................................
                                                          <label for="introtext">Аннотация:<br /></label>
                                                          <input type="text" name="introtext" id="introtext"
                                                            value="[[!getContent? &need=`introtext` &id=`3`]]" /><br />
                                                          <label for=" content ">Полный текст:<br /></label>
                                                          <textarea id="content" name="content">
                                                           [[!getContent? &need=`content` &id=`3`]]
                                                          </textarea><br />
                                                          <input type="submit" value="Сохранить!" />
                                                      </form>
                                                      1. Alexander 18 февраля 2015, 09:41 # 0
                                                        Большое спасибо, понял ошибку, всё работает.
                                                        1. Alexander 21 февраля 2015, 14:15 # 0
                                                          Добрый день, вопрос касается системы удаления ресурсов: как организовать удаление ресурса которым, например, со дня их снятия с публикации 10 дней?
                                                          1. Илья Уткин 24 февраля 2015, 07:45 # 0
                                                            Скорее всего, вам понадобится плагин на событие onHandleRequest, который будет искать такие ресурсы и удалять их.
                                                  2. Роман 19 июня 2015, 08:01(Комментарий был изменён) # 0
                                                    Всем привет!

                                                    Илья подскажи пожалуйста, как можно запелить добавление файла?

                                                    В addResource указал id-ки ТВ и иего имя
                                                    Форму добавил:
                                                    <input type="file" name="tplfile" id="tplfile" class="file-imput" />
                                                    Прошу помощи, спасибо!
                                                    1. Илья Уткин 19 июня 2015, 08:46 # 0
                                                      Дело в том, что загрузка файла на сервер не такая уж простая задача, как кажется на первый взгляд.

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

                                                      Кроме того нужно учесть, что:
                                                      • Пользователь может начать грузить «тяжелые» файлы — так память сервера быстро кончится, да и не каждый сервер позволит загружать большие объемы данных — иначе начнутся ошибки или сервер начнет «отваливаться»;
                                                      • Пользователь может загрузить вместо, например, картинки файл с фильмом. Формат файлов тоже надо учесть;
                                                      • Пользователь может загрузить файл php и взломать сервер. От этого нужна защита;

                                                      А ещё, файлы надо позволить менять (загружать новые), а, значит, старые надо как-то удалять. Тут тоже нужен свой алгоритм.

                                                      Так что если нет большого опыта в программировании, проще найти кого-то, кто сделает это за деньги. Разместите объявление о работе на https://modx.pro/ — там вам наверняка помогут.

                                                      Есть еще один вариант — использовать Tickets. В этом компоненте загрузка файлов уже предусмотрена «из коробки»
                                                      1. Роман 19 июня 2015, 09:38 # 0
                                                        Спасибо, наверно пойду за «Tickets»!
                                                    2. Илья 02 августа 2015, 17:38 # 0
                                                      Подскажите, как сделать редирект на страницу, которую только что отредактировал.
                                                      Настроил всё по статье + добавил это из комментария
                                                      1. Илья Уткин 03 августа 2015, 08:27 # 0
                                                        В конце сниппета (перед return) написать что-то типа такого:
                                                        $url = $modx->makeUrl($resource->get('id'));
                                                        if ($url) {
                                                            $modx->sendRedirect($url);
                                                        }
                                                        1. Илья 03 августа 2015, 09:43 # 0
                                                          Добавил в конец сниппета editResource, сделал вызов:
                                                             &hooks=`addResource`
                                                             &validate=`title:required`
                                                          
                                                          Работает, обновляет страницу /edit/ (аналогично &redirectTo=`[[*id]]`)

                                                          Я имел ввиду обновлять эту /edit/?id=12 или после редактирования редиректило на только что отредактированную страницу
                                                          Пробовал такое: &redirectTo=`[[!get? &need=`id`]]`, почему не заработало еще не разобрался
                                                          1. Илья Уткин 03 августа 2015, 10:06 # 0
                                                            &hooks=`addResource`
                                                            Должно быть editResource
                                                            1. Илья 03 августа 2015, 11:14 # 0
                                                              Да, это увидел, сменил на editResource, работает так, как описал выше.
                                                              1. Илья Уткин 03 августа 2015, 12:25 # 0
                                                                Тогда не знаю, надо искать, где не срабатывает…
                                                                1. Илья 03 августа 2015, 13:55 # 0
                                                                  Я попробовал изменить сниппет get:
                                                                  <?php
                                                                  if (!empty($_GET)) {
                                                                  	$modx->setPlaceholders($_GET);
                                                                  }
                                                                  сделал плейсхолдер [[+id]], на результат не повлияло.
                                                                  Ладно, буду смотреть в сторону ajaxform
                                                      2. Андрей Владимирович 11 января 2016, 11:36(Комментарий был изменён) # 0
                                                        Илья, здравствуйте!
                                                        Есть ли решение для создания и редактирования тикетов от Василия во фронтенде?
                                                        Стандартный не устраивает отсутствием выбора каталогов тикета.
                                                        Спасибо
                                                        1. Илья Уткин 11 января 2016, 12:16 # 0
                                                          Хм… С такой задачей не сталкивался, не могу подсказать, к сожалению
                                                        2. Владимир 11 марта 2016, 23:27 # 0
                                                          Здравствуйте!
                                                          Нашел код динамического добавлений изображений:
                                                          <?php
                                                          //Создадим пару вспомагательных функций
                                                          function exit_status($str){
                                                          	echo json_encode(array('status'=>$str));
                                                          	exit;
                                                          }
                                                          
                                                          function get_extension($file_name){
                                                          	$ext = explode('.', $file_name);
                                                          	$ext = array_pop($ext);
                                                          	return strtolower($ext);
                                                          }
                                                          
                                                          $upload_dir = 'img/'; //Создадим папку для хранения изображений
                                                          $allowed_ext = array('jpg','jpeg','png','gif'); //форматы для загрузки
                                                          
                                                          
                                                          if(strtolower($_SERVER['REQUEST_METHOD']) != 'post'){
                                                          	exit_status('Ошибка при отправке запроса на сервер!');
                                                          }
                                                          
                                                          
                                                          if(array_key_exists('pic',$_FILES) && $_FILES['pic']['error'] == 0 ){
                                                          	
                                                          	$pic = $_FILES['pic'];
                                                          	
                                                          	if(!in_array(get_extension($pic['name']),$allowed_ext)){
                                                          		exit_status('Разрешена загрузка следующих форматов: '.implode(',',$allowed_ext));
                                                          	}	
                                                          
                                                          //Загружаем файл во на сервер в нашу папку и посылаем команду о том, что все ОК и файл загружен
                                                          	if(move_uploaded_file($pic['tmp_name'], $upload_dir.$pic['name'])){
                                                          		exit_status('Файл Был успешно загружен!');
                                                          	}
                                                          	
                                                          }
                                                          
                                                          exit_status('Во время загрузки произошли ошибки');
                                                          его можно переделать под MODX?
                                                          1. Илья Уткин 15 марта 2016, 14:47 # 0
                                                            Ну в общем, его можно прям вставить в сниппет и вызывать на странице некешированным, по идее должен заработать.
                                                            1. Владимир 15 марта 2016, 15:42 # 0
                                                              В принципе да, он работает, но тут дело не в нем. Он вызывается JS скриптом:
                                                              $(function(){
                                                              	
                                                              	var dropbox = $('#dropbox'),
                                                              		message = $('.message', dropbox);
                                                              	
                                                              	dropbox.filedrop({
                                                              		paramname:'pic',
                                                              		
                                                              		maxfiles: 5,
                                                                  	maxfilesize: 2,
                                                              		url: 'post_file.php',
                                                              		
                                                              		uploadFinished:function(i,file,response){
                                                              			$.data(file).addClass('done');
                                                              		},
                                                              		
                                                                  	error: function(err, file) {
                                                              			switch(err) {
                                                              				case 'BrowserNotSupported':
                                                              					showMessage('Ваш Браузер не поддерживает HTML5!');
                                                              					break;
                                                              				case 'TooManyFiles':
                                                              					alert('Разрешено загружать за 1 раз не более 5 изображений');
                                                              					break;
                                                              				case 'FileTooLarge':
                                                              					alert(file.name+' Слишком большой.Разрешена загрузка файлов не более 2мб.');
                                                              					break;
                                                              				default:
                                                              					break;
                                                              			}
                                                              		},
                                                              
                                                              		beforeEach: function(file){
                                                              			if(!file.type.match(/^image\//)){
                                                              				alert('Разрешена загрузка только изображений!!!!');
                                                              				return false;
                                                              			}
                                                              		},
                                                              		
                                                              		uploadStarted:function(i, file, len){
                                                              			createImage(file);
                                                              		},
                                                              		
                                                              		progressUpdated: function(i, file, progress) {
                                                              			$.data(file).find('.progress').width(progress);
                                                              		}
                                                                  	 
                                                              	});
                                                              	
                                                              	var template = '<div class="preview">'+
                                                              						'<span class="imageHolder">'+
                                                              							'<img />'+
                                                              							'<span class="uploaded"></span>'+
                                                              						'</span>'+
                                                              						'<div class="progressHolder">'+
                                                              							'<div class="progress"></div>'+
                                                              						'</div>'+
                                                              					'</div>'; 
                                                              	
                                                              	
                                                              	function createImage(file){
                                                              
                                                              		var preview = $(template), 
                                                              			image = $('img', preview);
                                                              			
                                                              		var reader = new FileReader();
                                                              		
                                                              		image.width = 100;
                                                              		image.height = 100;
                                                              		
                                                              		reader.onload = function(e){
                                                              
                                                              			image.attr('src',e.target.result);
                                                              		};
                                                              		
                                                              		reader.readAsDataURL(file);
                                                              		
                                                              		message.hide();
                                                              		preview.appendTo(dropbox);
                                                              		
                                                              		$.data(file,preview);
                                                              	}
                                                              
                                                              	function showMessage(msg){
                                                              		message.html(msg);
                                                              	}
                                                              
                                                              });
                                                              и по идеи работает на jquery.filedrop.js. Именно когда я пытаюсь загрузить на хостинг фотографии через modx, то там выскакивает ошибка самого скрипта (jquery.filedrop.js). Если без modx, то работает замечательно.
                                                              Так что буду думать как исправить.
                                                              P.S. Все равно спасибо за совет.
                                                              1. Илья Уткин 16 марта 2016, 10:09 # 0
                                                                попробуй вместо URL написать так
                                                                url: document.location.href,
                                                                1. Владимир 16 марта 2016, 10:37 # 0
                                                                  Попробовал, не вышло.
                                                                  Консоль браузера пишет ошибку:
                                                                  Uncaught SyntaxError: Unexpected token <
                                                                  e.extend.parseJSON @ jquery-1.7.1.min.js:2
                                                                  $.fn.filedrop.xhr.onload @ jquery.filedrop.js:342
                                                                  1. Владимир 16 марта 2016, 22:25 # 0
                                                                    Решил вопрос другим способом, нашел дополнение AjaxUpload, работает нормально.
                                                                    Но теперь возник другой вопрос. Когда перехожу на страницу редактирование, то все параметры передаются нормально, но при сохранении изменений выдает ошибку

                                                                    Fatal error: Call to a member function get() on a non-object in ....ru/core/cache/includes/elements/modsnippet/46.include.cache.php on line 8

                                                                    как я понял ошибка в сниппете getContent, он у меня 46, брал его с этой статьи, только добавил еще несколько полей. Так же пытался поменять его на getresourcefield, так же все значения полей передает, но при сохранении он перебрасывает меня с edit/?id=140 на просто edit/, при этом изменения не сохраняет.
                                                                    1. Илья Уткин 17 марта 2016, 08:54 # 0
                                                                      Надо дописать проверку просто, я думаю
                                                                      $output = '';
                                                                      // Получаем ресурс по его id
                                                                      $res = $modx->getObject('modResource',array('id'=>$id));
                                                                      if (!$res) return;
                                                                      1. Владимир 17 марта 2016, 10:51 # 0
                                                                        Ошибка больше не выскакивает, но изменения не сохраняет.
                                                            2. Антон 14 апреля 2016, 08:51 # 0
                                                              Здравствуйте Илья! Я реализовал на сайте доску объявлений, добавление ресурсов из фронтэнда с помощью formit и снипетов. Такой вопрос: как реализовать кнопку удаления (своего объявления)ресурса?
                                                              1. Илья Уткин 14 апреля 2016, 11:55 # 0
                                                                Удаление — это такое же действие, как и редактирование. Только надо установить галочку «Удален» (deleted)
                                                              2. Сергей 26 апреля 2016, 19:59 # 0
                                                                Не могли бы вы привести пример кода добавления WYSIWYG-редактора?
                                                                1. Илья Уткин 26 апреля 2016, 20:35 # 0
                                                                  На скриншоте старая версия редактора Imperavi. Тогда он еще был бесплатным.
                                                                  Из бесплатных могу посоветовать CKEditor

                                                                  Каждый редактор устанавливается по-своему, на каждом сайте есть инструкция и документация.
                                                                  1. Сергей 26 апреля 2016, 20:38 # 0
                                                                    Эх. Жаль. Imperavi идеален для контент-менеджера. Ничего лишнего.
                                                                    Спасибо за ответ.
                                                                2. Anton 28 апреля 2016, 11:32 # 0
                                                                  Добрый день, подскажите как сделать проверку в снипете является ли юзер автором ресурса? Спасибо.
                                                                  1. Илья Уткин 28 апреля 2016, 11:42 # 0
                                                                    if ($modx->user->id == $resource->get('createdby')) {
                                                                      // является
                                                                    }
                                                                    Только надо следить за тем, чтобы поле createdby корректно заполнялось у ресурса
                                                                  2. Anton 28 апреля 2016, 14:38(Комментарий был изменён) # 0
                                                                    Сделал вот так вроде работает, но если например вручную прописать в адресе от другого пользователя то вылетает
                                                                    Fatal error: Call to a member function get() on a non-object in ...\core\cache\includes\elements\modsnippet\87.include.cache.php on line 4
                                                                    
                                                                    и ресурс не удаляется, в принципе это и нужно было.

                                                                    Делаю так:
                                                                    $docId=intval($_GET['docid']);
                                                                    $doc = $modx->getObject('modResource', $docId);
                                                                    if ($modx->user->id == $doc->get('createdby')) {
                                                                      $doc->set('deleted', '1');
                                                                      $doc->save();
                                                                    } else {
                                                                        return'error';
                                                                    }
                                                                    
                                                                    Я новичок)) Подскажи правильно ли я делаю, и как эту ошибку обработать.
                                                                    Еще планирую это:
                                                                    $doc->set('deleted', '1');
                                                                    $doc->save();
                                                                    
                                                                    заменить на $doc->remove(); так наверно правильней чтобы с корзины сразу удалялось?
                                                                    1. Илья Уткин 28 апреля 2016, 14:40 # 0
                                                                      Надо еще проверять, существует ли такой ресурс в принципе
                                                                      $doc = $modx->getObject('modResource', $docId);
                                                                      if (!$doc) return 'error';
                                                                    2. Anton 28 апреля 2016, 14:49 # 0
                                                                      Все получилось. Спасибо за отзывчивость Илья, и отдельное Спасибище за твои статьи, очень помогают разобраться как все устроено в modx)
                                                                      1. Anton 04 мая 2016, 10:18 # 0
                                                                        Привет, подскажи еще такой вопрос пожалуйста, для редактирования ресурсов использую такой снипет:
                                                                        <?php
                                                                        if (isset($_GET['resId'])){
                                                                            if ($doc=$modx->getObject('modResource',array('id'=>$_GET['resId']))){
                                                                                $docarray=$doc->toArray();
                                                                                $fields = explode(',',$scriptProperties['resource2formitfields']);
                                                                                $fields[] = 'id';
                                                                        
                                                                                foreach ($fields as $field){
                                                                        
                                                                                    if ($doc->getFieldName($field) === null) {
                                                                                        /* if field isnt defined, look for TV value */
                                                                                        $tvValue = $doc->getTVValue($field);
                                                                                        if ($tvValue !== null) {
                                                                                            $hook->setValue($field,$tvValue);
                                                                                        }
                                                                                    } else {
                                                                                        /* otherwise get field value */
                                                                                        $hook->setValue($field,$docarray[$field]);
                                                                                    }    
                                                                                }
                                                                            }
                                                                         
                                                                            //$errorMsg = '<pre>'.print_r($docarray,true).'</pre>';  
                                                                           // $hook->addError('error_message',$errorMsg);  
                                                                        }
                                                                        
                                                                        Но он не заполняет поля где есть чекбоксы или селекты с множественными значениями, как сделать чтобы он брал массив значений и заполнял форму корректно? Спасибо заранее.
                                                                        1. Илья Уткин 05 мая 2016, 14:28 # 0
                                                                          Ну, я думаю, надо разбирать полученные POST-значения и самостоятельно записывать их в ТВ-поля. Можно посмотреть, как они в базе хранятся, и делать такие же записи
                                                                        2. Alex Lotz 23 июня 2016, 23:18 # 0
                                                                          А как сделать кнопку «удалить ресурс»?
                                                                          Допустим через pdoTools выводятся ресурсы, как к каждому прикрутить кнопку?
                                                                          1. Илья Уткин 24 июня 2016, 10:12 # +1
                                                                            Удалить ресурс в корзину можно так:
                                                                            $resource->set('deleted', true);
                                                                            $resource->save();
                                                                            А удалить навсегда так:
                                                                            $resource->remove();
                                                                            1. Alex Lotz 24 июня 2016, 13:29 # 0
                                                                              это нужно зайти на ресурс и тогда через хук можно удалить, а ески через pdoTools выведено х количество, как тогда правильно подключить кнопку?
                                                                              1. Илья Уткин 24 июня 2016, 19:11 # 0
                                                                                Я сам с такой задачей не сталкивался, готового примера нет под рукой. Но я думаю, надо делать так же, как и кнопку «купить» в интернет-магазинах
                                                                          2. amsterdam 21 сентября 2016, 06:52 # 0
                                                                            А можно так добавлять информацию, только совсем не авторизованным пользователям? что бы для всех сразу была форма добавления, без логина?
                                                                            1. Илья Уткин 21 сентября 2016, 08:12 # 0
                                                                              Можно. Для этого надо писать собственный процессор, который не будет проверять права доступа.
                                                                              1. amsterdam 21 сентября 2016, 11:53 # 0
                                                                                а на сколько это безопасно?
                                                                                1. Илья Уткин 21 сентября 2016, 11:56 # 0
                                                                                  Ну, конечно, нужно дописать свою систему безопасности — чтобы ресурсы создавались только в определенном разделе, чтобы между отправками формы была задержка (чтобы не спамили)

                                                                            Авторизация

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


                                                                            Шаблоны MODX

                                                                            1 2 Дальше »

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