Помнится мне, когда я хотел сделать такой же плагин, то также решил обработать все возможные события. Но натолкнулся на ворох багов, которые побороть не удалось. Коль, ты на них не натыкался? Если да, то учитываешь как-нибудь? Просто исправление этих багов - это серия пуллреквестов в modx репозиторий, которые я в своё время не осилил, а потом как-то и не вспоминал даже. Проще запулить небольшой коммит, чтобы в методе modResource::refreshURIs() или modResource::save() вызывалось какое-нибудь событие, которые решило бы все проблемы. Но не факт, что такой коммит примут разработчики modx'а. А ещё, помнится мне, точно тогда же, на три дня позже, у нас с тобой развернулась полемика на эту тему, после чего ты мне доказывал, что такой плагин - на хрен не нужная хрень, аппелируя авторитетностью Носика, ибо seo. А сейчас вон оно как :-)

Топик: modRedirect

Сегодня я писал про то, что на сайте MODX-Клуба реализованы настройки уведомлений о новых топика и комментариях. И теперь пользователи всегда будут в курсе о том, что что-то новое на сайте появилось. Но тут возникла другая, вполне предполагаемая, проблема - долгое выполнение запроса при создании топика. И ничего удивительного, отправить несколько сотен писем за раз - требует не мало времени. Не круто... По этой причине я и заморочился написать систему отложенных очередей рассылки емейлов. Суть ее в том, что при создании топика (конечно, это может быть использовано не только в этому случае, но все-таки), пользователям не отправляются сразу письма, а складываются они в специальную табличку. Это происходит значительно быстрее, чем если сразу слать письма. А потом по крону каждые 5 минут (кто как настроит) вызывается процессор рассылки, который уже и рассылает эти письма. Данный процесс никак никому не мешает. Таким образом можно запросто обслуживать проект с тысячами активных пользователей :)

Не за что :)

Топик: modRedirect

Очень своевременно, давно искал что-то похожее... Спасибо!

Топик: modRedirect

но поддержка финансовая сейчас такая слабая, что пакет никак не попадает в паблик (надо выделить не мало часов, чтобы еще еще причесать). )))

Вообще, я даже уже сборку блога сделал (копию MODX-Клуба) а как можно было бы эту сборку рассмотреть ближе? )

Сегодня была очень продуктивная ночь :) Во-первых, были выполнены очередные исследования по MODX-у. На этот раз в области политик безопасности, а именно проверка прав на объект сразу нескольких пользователей. Как оказалось, этого из коробки в MODX-е просто нет, права проверяются только для текущего авторизованного пользователя. Но про это я напишу в отдельном топике чуть позже. А во-вторых, я таки напрограммировал систему уведомлений на сайте MODX-Клуба :) Как раз для этого и выполнял описанные выше исследования. Ведь чтобы отправить письма тем, кто желает знать о новых топиках, надо убедиться, что эти пользователи имеют доступ к данным топикам. Да-да, ведь на сайте есть и закрытые разделы, доступные только определенным группам пользователей. В общем, теперь каждый может зайти в настройки своего профиля (вверху пункт Профиль), и там указать те типы уведомлений, которые интересуют. В настоящий момент есть 5 типов уведомлений: Получать уведомления о новых топиках. Пользователь получит уведомление о новом топике, созданном в доступном для пользователя блоге. Получать уведомления о новых ответах на мои комментарии. Пользователь получит уведомление о новом ответном комментарии, опубликованном другим пользователем. Получать уведомления о новых комментариях в моих топиках. Если кто-то написал новый комментарий в топике, уведомление будет отправлено автору топика. Получать уведомления о новых комментариях в топиках, где я принимал участие. Если пользователь писал комментарии в каком-то топике, то в дальнейшем будет получать уведомления о новых комментариях в этом топике, даже если они не адресованы непосредственно этому пользователю. Получать новости от администрации MODX-Клуба. Крайне редкие уведомления о каких-то важных новостях. Это чтобы даже если пользователь отписался от всех уведомлений, чтобы не надоедали ему, оставался еще канал для связи.

Сегодня ночью я писал про теги для топиков, и вот теперь на сайте Клуба у топиков появились теги :) На самом деле это отличный инструмент для SEO, так как для одного тематического документа можно задать сразу несколько ключевиков, каждый из которых будет иметь свою собственную страницу с ЧПУ и т.п. Поисковики такое очень любят, не раз проверенно статистикой. В дальнейшем теги будут добавлены и в сам modSociety. Как скоро? Зависит от количества поступаемых донейтов :) Как я и писал уже, донейты поступают оочень тяжко. Вообще, я даже уже сборку блога сделал (копию MODX-Клуба), но поддержка финансовая сейчас такая слабая, что пакет никак не попадает в паблик (надо выделить не мало часов, чтобы еще еще причесать). ?

Материал для экспертов. Многие сложные моменты не будут подробно объясняться, требуется хорошее знание xPDO. Небольшое вступление. Заморочился я тут на сайте реализовать теги для топиков (для SEO отличная штука). Создал новый класс SocietyTopicTag со следующими колонками: id, topic_id, tag, active. Какие тут главные моменты, побудившие написать топик? Поле tag не может быть пустым. Поле topic_id так же не может быть пустым. И вот далее мы разберемся с тем, как это предусмотреть, и какие тут есть подводные камни... Начнем с простого - с проверки поля tag и запрета сохранения. Сразу посмотрим конечный код класса SocietyTopicTag: <php

class SocietyTopicTag extends xPDOSimpleObject {

public function save($cacheFlag= null) {

    $this->tag = trim($this->tag);

    if(!$this->tag){

        $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "[- ". __CLASS__ ." -]. Column tag can not be empty");

        return false;

    }

    if(!$this->getOne('Topic')){

        $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "[- ". __CLASS__ ." -]. Topic required");

        return false;

    }

    return parent::save($cacheFlag);

}    

} 1. Перегружаем оригинальный метод save(). Теперь, если что-то не так, мы можем вернуть false, что будет означать, что объект не был сохранен. 2. Проверяем наличие значения у поля tag. if(!$this->tag){

        $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "[- ". __CLASS__ ." -]. Column tag can not be empty");

        return false;

    } Теперь вот такой код не создаст нового объекта: <php

$tag = $modx->newObject('SocietyTopicTag', array(

"tag"   => "",

));

if(!$tag->save()){

print "Error";

}

else{

print "Saved";

} Так как tag не заполнен, то сохранение объекта прервется. Это исключит сохранение объекта с незаполненым полем. А вот с topic_id несколько сложнее... Почему вот мы не стали проверять поле topic_id так же, как и tag, просто на наличие значения? Во-первых, топик для этого тега может быть еще новый и не сохранен в БД, и соответственно у него и не будет id. А если у топика нет id, то мы просто не можем записать его в качестве topic_id. К примеру, в таком случае бы вот этот код не сработал: <php

$tag = $modx->newObject('SocietyTopicTag', [

"tag"   => "DSfdsfdsF", 

]);

$r = $modx->newObject('modResource');

$r->addMany($tag);

$r->save(); Во-вторых, можно было бы указать id несуществующего топика. В случае проверки $this->topic_id у нас просто выполняется проверка значения на наличие, но нет проверки наличия документа. А вот в случае проверки объекта $this->Topic, даже если мы просто передали значение topic_id, xPDO попытается выполнить запрос к БД и получить объект топика, и если его не получит, то тег не будет сохранен. В итоге, представленная проверка сработает во всех случаях попытки сохранения как нового тега, так и обновления существующего. P.S. Понятное дело, что в данном случае важную роль играет описание composite/aggregates-связей классов modResource и SocietyTopicTag. В SocietyTopicTag map-файл дописываем: 'aggregates' =>

array (

'Topic' => 

array (

  'class' => 'modResource',

  'local' => 'topic_id',

  'foreign' => 'id',

  'cardinality' => 'one',

  'owner' => 'foreign',

),

), А вот в modResource мы просто так не вклинимся, так как это ядро MODX-а, и мы его не можем трогать. Но есть лазейка - meta-файл пакета (metadata.mysql.php). Вот туда мы и дописываем связь для modResource: $this->map['modResource']['composites']['TopicTags'] = array(

'class' => 'SocietyTopicTag',

'local' => 'id',

'foreign' => 'topic_id',

'cardinality' => 'many',

'owner' => 'local',

); Чтобы этот момент был чуть более понятен, я специально перенес свой старый топик.