Fi1osof 07 мая 2015 2 2

В MODX есть один довольно неприятный подводный камень — есть настройка политик безопасности view_unpublished (Видеть неопубликованные документы), но нет возможности дать пользователю видеть конкретно его страницы, даже если они не опубликованы. То есть или все (давать право видеть в принципе не опубликованные, что понятно по ряду причин не круто), или не ясно как извращаться.

Это особенно важно, если у вас, к примеру, какая-то небольшая социалочка или типа того, когда сторонние пользователи создают свои собственные документы, но есть премодерация и эти документы изначально не опубликованные. Конечно можно сделать фейковую страницу для просмотра таких не опубликованных страниц, но это годится только для мелких проектов и когда всего один-два шаблона выводов таких страниц. Еже ли проект крупный, и для просмотра страницы важно, чтобы страница отображалась ровно так, как она отображалась бы, если бы была опубликована (с учетом шаблона, ее места в структуре и т.п.), то тут уже такой номер не пройдет. Надо именно дать возможность пользователям видеть их документы, даже если они не опубликованы.

Проблема в том, что если у пользователя нет прав видеть неопубликованные страницы, то modRequest в принципе исключает не опубликованные страницы еще на уровне SQL-запроса условием published = 1. Если modRequest не находит запрошенный по УРЛу документ, он отбрасывает $modx->sendErrorPage(), который в свою очередь вызывает событие OnPageNotFound, на который мы можем навесить плагин и рулить не найденные страницы, но проблема в том, что мы там могли бы перенаправить $modx->sendForward($id) только на опубликованную страницу. С неопубликованной страницей такой номер не пройдет. Я исследовал различные варианты решения этой проблемы и для себя нашел только один вариант — переопределение реквест-класса. Благо, что проблем с этим нет. Делаем так:
1. Создаем свой пакет и добавляем его в ExtensionPackages. Если данный шаг не понятен, можно сделать еще проще: если не установлен пакет modxSite, устанавливаем его.
2. В папке core/components/{component}/model/{package} создаем свой файл, к примеру myrequest.class.php
3. В нем прописываем код (особое внимание обратите на то, что маска файла обязана быть такой: strtolower($className).class.php). Например, если у вас класс называется MyRequest, то файл должен называться myrequest.class.php

<?php

class myRequest extends modRequest{
    
    public function getResource($method, $identifier, array $options = array()) {
        $resource = parent::getResource($method, $identifier, $options);
        
        if(!$resource){
            // Доступ к собственным ресурсам, даже если они не опубликованы
            if(
                $this->modx->user->id
                AND is_numeric($this->modx->resourceIdentifier)
            ){
                $resource = $this->modx->getObject('modResource', array(
                    "id"    => $this->modx->resourceIdentifier,
                    "createdby" => $this->modx->user->id,
                ));
            }
        }
        
        return $resource;
    }
}


4. В системных настройках создаем новую настройку modRequest.class со значением имени вашего класса (в нашем случае myRequest).

Всё. Теперь при запросе страницы, наш переопределенный класс будет сначала получить объект ресурса от родительского класса, а если не получит, будет пытаться в БД получить документ с таким ID и текущим пользователем. Получив объект ресурса MODX не проверяет опубликован он или нет. Есть — ОК, выводим. Конечно же здесь и прочую свою логику можно дописать.

2 комментария
n
niibaca-nah 07 мая 2015г в 21:16 #
БлагоДарю, Николай! Очень нужный момент, мне он определённо скоро пригодится.

Я правильно понимаю, что подобной системной настройкой можно расширить любой класс в MODX Revo?
Fi1osof1
Fi1osof 07 мая 2015г в 21:50 #
Пожалуйста!
Нет, не правильно. В данном случае нам API MODx это позволяет сделать.
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.