+1306.48
Рейтинг

Дмитрий

  • avatar ZoRg
  • 0
Обнаружил глюк с SSL (https), в версии 1.2.1-d9.1.0
Параметр шаблона [(site_url)] всегда выдаёт ссылку с http ане https, в настройках включил что сайт с https.
Остальные настройки на хостинге уже настроены так, что сайт по умолчанию всегда открывается с https.
.htaccess тоже настроен, не помогло.

Много глюков и неработающих плагинов (ManagerManager, CodeMirror), дерево рессурсов пустое.

Помогло жесткое прописывание в config.inc.php строк:
Было:
// assign site_url
$site_url= ((isset ($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') || $_SERVER['SERVER_PORT'] == $https_port) ? 'https://' : 'http://';
Заменил на:
$site_url= 'https://';


Может кому тоже пригодится :)
Нужно добавить prepareProcess-сниппет с таким кодом:
<?php
if(function_exists('populateOrderData')){
	$fields=array();
	populateOrderData($fields);
	$FormLister->setFields($fields);
}
if(function_exists('sendOrderToManager')){
	sendOrderToManager($data);
}

Вызывать FormLister, как и в случае с eForm, нужно после вызова Shopkeeper'а.
Можно загружать любой файл в любую папку:

$dir=mkdir("uploads/$_POST[sex]/$_POST[ses]");
$subdir=mkdir("uploads/$_POST[sex]/$_POST[ses]/preview", 0777);
        if($_FILES["filename"]["size"] > 1024*1*1024)
   {
     echo ("Размер файла превышает лимит. Фото #1 не прикреплено. Объявление отправлено на премодерацию без фотоc");
     exit;
   }
        if($_FILES["filename1"]["size"] > 1024*1*1024)
   {
     echo ("Размер файла превышает лимит. Фото #2 не прикреплено. Объявление отправлено на премодерацию без фотоc");
     exit;
   }
        if($_FILES["filename2"]["size"] > 1024*1*1024)
   {
     echo ("Размер файла превышает лимит. Фото #3 не прикреплено. Объявление отправлено на премодерацию без фото <br />");
     exit;
   }
   // Проверяем загружен ли файл
        if(is_uploaded_file($_FILES["filename"]["tmp_name"]))
   {
     // Если файл загружен успешно, перемещаем его
     // из временной директории в конечную
           move_uploaded_file($_FILES["filename"]["tmp_name"], "uploads/$_POST[sex]/$_POST[ses]/".$_FILES["filename"]["name"]);
   } 
Корзину не сложно сделать с нуля (:

<?php
class sCart {
        private $cart = array();
        private $modx = null;

    /**
     * @param DocumentParser $modx
     * @param array $cfg
     * @throws Exception
     */
    public function __construct($modx, $cfg = array()) {
                if ($modx instanceof DocumentParser) {
                    $this->modx = $modx;
            } else {
                throw new Exception('MODX var is not instaceof DocumentParser');
            }
                $this->cart = &$_SESSION['cart'];
        if (empty($this->cart)) {
            $this->cart = array();
        }
        }

    /**
     * @param $id
     * @param int $count
     * @param array $options
     * @return bool
     */
    public function add($id, $count = 1, $options = array()) {
                if (!$id || !is_numeric($id)) return false;
                $out = true;
                $key = md5($id.serialize($options));
                if (!isset($this->cart[$key])) {
                        $this->cart[$key] = array(
                                'id' => $id,
                                'count' => $count,
                                'options' => $options
                                );
                } else {
                        if (!$this->update($key, $this->cart[$key]['count'] + $count)) $out = false;
                }
                return $out;
        }

    /**
     * @param $key
     * @return bool
     */
    public function remove($key) {
                if (!is_scalar($key)) {
                        $out = false;
                } else {
                        unset($this->cart[$key]);
                        $out = true;
                }
                return $out;
        }

    /**
     * @return bool
     */
    public function clear() {
                $this->cart = array();
                return true;
        }

    /**
     * @param $key
     * @param int $count
     * @return bool
     */
    public function update($key, $count = 0) {
                if (!is_scalar($key) || !isset($this->cart[$key])) return false;
        if ($count <= 0) {
                        $out = $this->remove($key);
                } else {
                        $this->cart[$key]['count'] = $count;
                        $out = true;
                }
                return $out;
        }

    /**
     * @return array
     */
    public function status() {
                $total = 0;
                foreach ($this->cart as $item) {
                        $total = $total + $item['count'];
                }
                $out = array(
                        'total'=>$total,
                        'cart'=>$this->cart
                        );
                return $out;
        }

    /**
     * @param $num
     * @param array $forms
     * @return mixed
     */
    public function formatPlural($num,$forms = array()) {
        $n = abs($num) % 100;
        $n1 = $n % 10;
        if (!$n || ($n > 10 && $n < 20)) return $forms[2];
        if ($n1 > 1 && $n1 < 5) return $forms[1];
        if ($n1 == 1) return $forms[0];
        return $forms[2];
    }
}

Немного обвеса на сервере:

cat ajax.php
<?php
define('MODX_API_MODE', true);
include_once("../../../index.php");
/** @var DocumentParser $modx */
$modx->db->connect();
if (empty ($modx->config)) {
    $modx->getSettings();
}
if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest')){
    $modx->sendRedirect($modx->config['site_url']);
}
include_once(MODX_BASE_PATH.'assets/snippets/cart/cart.class.php');
$cart = new sCart($modx);
$result = array('success'=>false);
switch ($_REQUEST['action']) {
        case 'add':
                $id = (int)$_REQUEST['id'];
                $count = (int)$_REQUEST['count'];
        if (!$count || $count < 1) $count = 1;
                $result['success'] = $cart->add($id,$count);
                break;
        case 'remove':
                $key = $_REQUEST['key'];
                $result['success'] = $cart->remove($key);
                break;
    case 'update':
        $key = $_REQUEST['key'];
        $qnt = (int)$_REQUEST['qnt'];
        $result['success'] = $cart->update($key,$qnt);
        break;
        case 'clear':
                $result['success'] = $cart->clear();
                break;
        default:
                $result['success'] = true;
                break;
}
if ($result['success']) $result['status'] = $cart->status();
echo json_encode($result);

И на фронте:

var itemName = [' товар', ' товара', ' товаров'];
var cartHelper;
cartHelper = {
    add: function (e) {
        var _id = $(e).data('id-product');
        if ($(e).data('qnt-field') !== undefined) {
            _qnt = $('input[name='+$(e).data('qnt-field')+']').val();
            if (_qnt < 1) {
                _qnt = 1;
                $('input[name='+$(e).data('qnt-field')+']').val(_qnt);
            }
        } else {
            _qnt = 1;
        }
        $.ajax({
            url: _cartUrl,
            type: 'POST',
            data: {
                action: 'add',
                id: _id,
                count: _qnt
            },
            success: function (data) {
                cartHelper.updateCartStatus(data);
                $.growl.notice({title: '',message: "Товар добавлен в корзину"});
            }
        });
    },
    remove: function (e) {
        var _key = $(e).data('item-key');
        $.ajax({
            url: _cartUrl,
            type: 'POST',
            data: {
                action: 'remove',
                key: _key
            },
            success: function (data) {
                cartHelper.updateCartStatus(data);
                $(e).parent().parent().parent().remove();
                data = $.parseJSON(data);
                if (!data.status.total) {
                    cartHelper.clear();
                } else {
                    $.growl.notice({title: '',message: "Товар удален из корзины"});
                }
            }
        });
    },
    clear: function () {
        $.ajax({
            url: _cartUrl,
            type: 'POST',
            data: {
                action: 'clear'
            },
            success: function (data) {
                document.location.href = document.location.href;
            }
        });
    },
    update: function (e) {
        var _key = $(e).data('item-key');
        var _qnt = $('.cart_quantity_input',$(e).parent()).val();
        if (_qnt <= 0)
            {
                this.remove(e);
            } else {
            $.ajax({
                url: _cartUrl,
                type: 'POST',
                data: {
                    action: 'update',
                    key: _key,
                    qnt: _qnt
                },
                success: function (data) {
                    cartHelper.updateCartStatus(data);
                    data = $.parseJSON(data);
                    $.growl.notice({title: '', message: "Обновлено"});
                }
            })
        }
    },
    getStatus: function () {
        $.ajax({
            url: _cartUrl,
            type: 'POST',
            success: function (data) {
                cartHelper.updateCartStatus(data);
            }
        });
    },
    format: function (number, titles) {
        cases = [2, 0, 1, 1, 1, 2];
        return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
    },
    updateCartStatus: function (data) {
        data = $.parseJSON(data);
        if (data.success) {
            $('#cart-status').text(data.status.total + this.format(data.status.total, itemName));
        }
    }
};

Вот и вся корзина (:
Не цепляет русский язык, здесь в условии
github.com/dmi3yy/modx.evo.custom/blob/master/assets/plugins/tinymce4/plugin.class.inc.php#L83
не хватает $cfg['language'] = $lang_code;
Добавил в комплект плагин и сниппет для работы с превьюшками. Оба называются sgThumb. В плагине нужно вручную установить события OnFileBrowserUpload, OnSimpleGalleryDelete и OnSimpleGallerySave и вписать конфигурацию в json — пример конфигурации в коде плагина.
Например, конфигурация:

[
{"template":3,"options":"w=1140&h=400&zc=1&q=96&f=jpg","folder":"slider"}
]

Будет создавать при загрузке превьюшки размером 1140х400 и складывать их в папку slider. Jpg будет дополнительно обрабатываться с помощью jpegtran.
Можно указать несколько конфигураций:

[
{"template":3,"options":"w=1140&h=400&zc=1&q=96&f=jpg","folder":"slider"},
{"template":8,"options":"w=355&h=270&far=C&bg=FFFFFF&q=96&f=jpg","folder":"small"}
]

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

[[sgLister? &thumbSnippet=`sgThumb` &thumbOptions=`slider` 
&ownerTPL=`@CODE:
<div class="col-md-12 hidden-xs hidden-sm">
    <div class="slider">[+dl.wrap+]
    </div>
</div>
&tpl=`@CODE:
<div class="slide">
    <img class="img-responsive" src="[+thumb.sg_image+]" alt="[+e.sg_title+]">
    <div class="slide-text">
	<p class="title">[+e.sg_title+]</p>
	<p class="desc">[+e.sg_description+]</p>
    </div>
</div>
`]]

При удалении картинок будут удаляться и превьюшки. Можно менять конфигурацию в плагине и пересоздавать их. В общем phpthumb для галерей больше не нужен.
нет под рукой мака, вот если несложно, посмотри такой вариант

$e = & $modx->Event;
if ($e->name == "OnDocFormRender") {
        $html = "
           <script type='text/javascript'>      
             document.body.addEventListener('keydown', function (e) {
                           if ((e.which == '115' || e.which == '83' ) && (e.ctrlKey || e.metaKey)) {
                                  documentDirty=false; document.mutate.save.click();
                                  e.preventDefault();
                           }
                        });
           </script>
      ";
        $e->output($html);
}


Если сработает, обновлю топик.
  • avatar webber
  • 2
Проблемы, как выяснилось, сразу две:
1. Сниппет star_rating любой ajax-запрос обрабатывает как запрос на голосование без всякого различия — ему это был запрос или это пришел ajax -запрос от фильтров.
2. После перегрузки куска страницы с помощью ajax не происходит переинициализации фильтра (ну и как следствие он не появляется).
Решение, соответственно, тоже состоит из двух этапов. Для решения пункта 1 необходимо определиться идет запрос ajax к фильтру или к рейтингу. Для этого:
1.1. Немного модифицируем метод ajax() класса StarRating () файл assets/snippets/star_rating/starrating.class.php — т.е. добавляем проверку доп.параметра $_REQUEST['no_ajax_for_star_rating'] — он и будет нам говорить о том, что это хоть и запрос ajax, но он не касается фильтра.
Было
public function ajax() {
		return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ? true : false;
    }

Стало
public function ajax() {
		return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' && !isset($_REQUEST['no_ajax_for_star_rating']) ? true : false;
    }

1.2. вносим небольшие правки в наш файл js от eFilter, чтобы он отправлял нужную переменную и таким образом предупреждал star-rating, что это запрос не ему.

Для решения второго вопроса (переинициализации рейтинга) нам нужно
2.1. Еще немного правок в js нашего фильтра (в том числе добавляем файлик js, который и будет осуществлять переинициализацию нашего рейтинга ratyupdate.js
2.2. завершающий этап. Поскольку рейтинг добавляет свои скрипты в самый конец файла, то и мы добавим свои скрипты по его переинициализации в еще более поздний конец. Для этого создаем сниппет, который будет грузить наш файл ratyupdate.js. Назовем его ratyupdate с кодом
<?php
$modx->regClientHTMLBlock('<script src="/assets/snippets/eFilter/html/js/ratyupdate.js"></script>');
?>
и вызовем перед самым закрывающим тегом
[!ratyupdate!]</body>


Теперь рейтинги работают. Поскольку все необходимые «правки» со стороны eFilter я добавил, то помимо загрузки актуальной версии остается реализовать только пункт 1.1 и 2.2 :)
D phpthumb можно добавить в начало: $input = urldecode($input);
imgmap.googlecode.com/files/plugin_tinymce3_108.zip — вот есть плагин для tinymce.
Ну тогда тут нет ничего сложного.

Вот небольшой сниппет для авторизации. Код предельно понятен и прост.
include_once(MODX_BASE_PATH."assets/lib/MODxAPI/modUsers.php");
$USER = new modUsers($modx);
$userLogin = $error = null;
if($_SERVER['REQUEST_METHOD']=='POST' && isset($_POST[$password]) && !empty($_POST['email'])){
	if(is_scalar($_POST['email']) && !$USER->emailValidate($_POST['email'], false)){
		$userLogin = $_POST['email'];
	}
	$error = 'Пользователь не обнаружен или заблокирован';
    if(!empty($userLogin) && $USER->edit($userLogin)!==false && !$USER->checkBlock($USER->getID())){
        $error = 'Указанный вами пароль не подходит';
        if($USER->testAuth($USER->getID(), $_POST[$password], 0)){
            $USER->authUser($USER->getID(), true);
			$modx->sendRedirect($modx->makeUrl($modx->config['site_start']), 0, 'REDIRECT_HEADER', 'HTTP/1.1 307 Temporary Redirect');
        }
    }
}
if($tpl!=''){
    return $modx->parseChunk($tpl, array(
        'loginValue' => $userLogin,
        'error' => $error
    ), '[+', '+]');
}


и шаблон

[+error+]
<form id="user_reg_data" method="POST">
	Email: <input type="text" name="email" value="[+loginValue+]">
	Pass: <input type="password" name="password">
	<input name="send" type="submit" value="/">	
</form>


Редактирование профиля делается аналогично редактированию документов. У меня в блоге на эту тему по тегу MODxAPI хватает информации, чтобы разобраться тем, кто знаком с php.

$USER = new modUsers($modx);
$USER->edit(1)->set('fullname', $_POST['username'])->save();


Т.е. по сути все сводится только к формированию формы с нужными полями и написанию небольшого сниппета которые раскидает $_POST данные по нужным полям пользователя. Лично для меня это не составляет большого труда. Тем более, что программировать тегами MODX уже давно осточертело.
  • avatar 64j
  • 4
создаёте плагин KCFINDER_SESSION на событие OnDocFormRender
//KCFINDER_SESSION
$e = &$modx->Event;

global $content;

if ($e->name == 'OnDocFormRender') {
	$_SESSION['KCFINDER']['browser.dir'] = "uploads/".$content['id'];
	$_SESSION['KCFINDER']['uploadDir'] = MODX_BASE_PATH."assets/uploads/".$content['id'];
$e->output($output);
}

и в файле manager/media/browser/mcpuk/tpl/tpl_javascript.php
находите строчку
browser.dir = "<?php echo text::jsValue($this->session['dir']) ?>";

и меняете на
browser.dir = "<?php echo text::jsValue($_SESSION['KCFINDER']['browser.dir']) ?>";

по сути значение в сессии должно меняться, но что то там не так.

Теперь для каждого документа отдельно создаётся папка с его ID ($content['id'])
в папке создаются папки — images для картинок и files для файлов.
Если плагин выше оставите без изменений, то не забудьте создать в папке assets, папку uploads.
Далее вручную переносите файлы, либо пишите скрипт, чтобы раскидал по папкам все картинки
Попробуйте с DocLister. На таких объемах и работать должно быстрее и сортировка будет корректней.
<?php
/** Параметры при вызове сниппета */
$params = is_array($modx->Event->params) ? $modx->Event->params : array();

/** Параметры по умолчанию */
$params = array_merge(array(
	'idType' => 'parents',
	'parents' => $modx->documentObject['id'],
	'tpl' => 'priceTpl',
	'tvList' => 'Список используемых ТВшек'
        'showNoPublish' => '1',
	'sortDir' => 'ASC'
	'addWHereList' => array(
		'`c`.`hidemenu` = 0',
		'`c`.`deleted` = 0'
	)
), $params);

/** Выборка по наличию */
$skl = isset($_POST['sklad']) ? $_POST['sklad'] : 'est';
switch($skl){
	case 'est':{
	    $params['addWHereList'][] = "(`c`.`introtext` = 'склад' OR `c`.`introtext` = 'много')"; 
	    break;
	}
	case 'net':{
		$params['addWHereList'][] = "(`c`.`introtext` = 'Нет' OR `c`.`introtext` = 'транзит')"; 
		break;
	}
}

/** Выборка по содержимому */
if(!empty($_POST['word'])){
	require_once("assets/snippets/DocLister/lib/sqlHelper.class.php");
	/** Экранирование данных для защиты от SQL Injection */
	$params['addWHereList'][] = sqlHelper::LikeEscape($modx, 'c.content', $_POST['word'], '=', '%[+value+]%');
}

/** Сортировка */
$srt = isset($_POST['sort']) ? $_POST['sort'] : "";
switch($srt){
	case 'alf':{
		$params['sortBy'] = 'price';
		$params['tvSortWithDefault'] = 'price';
		$params['tvSortType'] = 'SIGNED';
		break;
	}
	default:{
		$params['sortBy'] = 'content';
	}
}

/** Подготовка параметров */
$params['addWHereList'] = implode(' AND ', $params['addWHereList']);

/** Вызов сниппета */
return $modx->runSnippet('DocLister', $params);
  • avatar Fr3ddy
  • 0
в смысл на отдельных страницах, лучше вообще на всех — исключая дубли на всем сайте.
сниппет
<?php
/* Canonical snippet */
/* Author Bob Ray */
/* produces an appropriate canonical tag for home and other pages */
/* put the snippet tag [[canonical]]  in the <head> section of your template(s) */
return $modx->documentIdentifier == $modx->config['site_start'] ? '<link rel="canonical" href="[(site_url)]" />' : '<link rel="canonical" href="[(site_url)][~[*id*]~]" />';
?>
  • avatar webber
  • 0
Ну если вы туда загнали несколько сотен похожих статей, то возможно ) Вообще, понятие «тяжелый запрос» очень растяжимое. Сделайте плагин вида

<code>if ($modx->isFrontend() && isset ($_SESSION['mgrValidated']))
        $modx->dumpSQL = true;</code>

на событии OnWebPageInit и посмотрите на нужной странице сайта (предварительно авторизовавшись в админке) статистику по запросам — время

Также напишите куда-нибудь в подвал строчку

<code>Mem : [^m^], MySQL: [^qt^], [^q^] request(s), PHP: [^p^], total: [^t^], document from [^s^].</code>

увидите общее время исполнения php и mysql.

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

А вообще проще дитто на доклистер заменить :)
  • avatar malroz
  • 0
Модуль заработал когда поменял значение $idPriceTV = 4, ошибок больше не выдает, но визуально выводит две цены сразу, старую и новую, что не есть хорошо! Подскажите, плиз, где подправить код? (код и скрин с ошибкой прилагается)

как убрать стару цену?

$idPriceTV = 4; //ID TV-параметра, который указывает цену (поле tmplvarid в таблице modx_site_tmplvar_contentvalues)
$ceil = 10; //Округляем до 100 рублей. Если поставить 10 - округлим до 10 рублей.
$arrFolders = $modx->runSnippet ('Ditto', array ('startID'=>0, 'depth'=>3, 'where'=>'isfolder=1', 'sortBy'=>'{"id":"ASC"}', 'tpl'=>'tplCatList')); //Категории для выбора (чекбоксы)
 
echo $modx->getChunk('catListScriptCheckbox');
 
echo '<h1>Автоменятор цен</h1>';
echo '<form  action="" method="post">';
echo '  <label for="percent">На сколько процентов изменить цены: </label><input type="text" id="percent" name="percent" value="10"> <b>КНОПКА ВНИЗУ</b>
        <p>Количество процентов, на которые меняем цену. Если указать <em><b>ПОЛОЖИТЕЛЬНОЕ</b> число - <b>увеличит</b></em>. Если <em><b>ОТРИЦАТЕЛЬНОЕ</b> - <b>уменьшит</b></em>.</p>
        <p>Число становится ЦЕЛЫМ. Если введена абракадабра - берется ближайшее целое, иначе НОЛЬ.</p>';
echo '  <hr />';
    echo '<p><input id="one" type="checkbox" name="one" value="all" onclick="checkAll(this)" /><label for="one">Отметить все / Снять отметку со всех</label></p>';
    echo $arrFolders;
echo '  <input type="submit">';
echo '</form>';
 
$percent = empty($_POST['percent']) ? $percent=0 : $percent=(int)$_POST['percent']; //Количество процентов, на которые меняем цену. Если указать ПОЛОЖИТЕЛЬНОЕ число - увеличит. Если ОТРИЦАТЕЛЬНОЕ - уменьшит.
unset($_POST['percent']);
$arrCatId = $_POST; //категории с товарами, которые надо менять
 
if (!empty($arrCatId)) {
  // Собираем цену и ID из указанных категорий
  foreach ($arrCatId as $catId) {
    $result = $modx->db->query('
        SELECT t1.id, t2.value FROM '.$modx->db->config['table_prefix'].'site_content AS t1, '.$modx->db->config['table_prefix'].'site_tmplvar_contentvalues AS t2
        WHERE t1.id = t2.contentid
        AND
        tmplvarid='.$idPriceTV.'
        AND
        parent='.$catId.';');
    while( $row = $modx->db->getRow( $result ) ) {
      $arrProductIds[] = $row;//['id'];
    }
  }
  //print_r($arrProductIds);
 
  ksort($arrProductIds);
 
  // Изменяем цены
  foreach ($arrProductIds as $arrPrice) {
    $productId = $arrPrice['id'];
    $strTv = $arrPrice['value'];
 
    //Разбиваем TV в массив
    $arrTvOne = explode('||', $strTv);
 
    foreach ($arrTvOne as $arrTvSub) {
 
      $arrTv = explode('==', $arrTvSub);
      foreach ($arrTv as $tvValue) {
        //И сразу меняем цену на $percent
        if ( preg_match('/\d/', $tvValue) && ($tvValue != '0' || $tvValue != '00' )) {
          $arrTv[1] = $tvValue + $tvValue/100 * $percent;
          $arrTv[1] = ceil($arrTv[1]/$ceil) * $ceil;
        }
      }
      //Собираем обратно строку со значением TV
      $strTv = implode("==", $arrTv);
 
      $arrIdTvs[$productId][] = $arrTv;
 
    $arrTvSTR[] .= $strTv;
    }
 
  $strIdTv = implode("||", $arrTvSTR);
  unset($arrTvSTR);
 
  $arrNewPrice[$productId] = $strIdTv;
  }
 
  //print_r($arrNewPrice);
 
  // Записываем новые цены в базу
  foreach ($arrNewPrice as $id => $tv) {
    $result = $modx->db->query("UPDATE ".$modx->db->config['table_prefix']."site_tmplvar_contentvalues SET value = '".$tv."' WHERE contentid = '".$id."' AND tmplvarid = '".$idPriceTV."';");
    //echo $result."\n";
  }
}
Самый лучший способ это
define('MODX_API_MODE', true);
include_once(dirname(__FILE__)."/index.php");
$modx->db->connect();
if (empty($modx->config)) {
    $modx->getSettings();
}
echo $modx->RunSnippet('Ditto',array('parent'=>$modx->db->escape($_POST['parent'])));
// вот тут мы выполняем сниппет по нашим данным

А то все эти файлики с повторными инициализациями DocumentParser только усложняют подмену класса. Возможно кто-то назовет мой способ костылем, но в таком случае встречный вопрос — нахрена в MODX константа MODX_API_MODE?
  • avatar danik
  • 1
Кстати, удобно делать таким же образом смену шаблона для AJAX-запросов.
/**
* @events OnWebPageInit
*/
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
// Получаем ресурс
if (!is_object($modx->resource)) {
$modx->resource = $modx->request->getResource($modx->resourceMethod, $modx->resourceIdentifier);
}
// Меняем шаблон у ресурса
$modx->resource->template = 0;
// Делаем ресурс не кэшируемым
$modx->resource->cacheable = false;
}
Таким образом, если URL открыт напрямую во вкладке, то отобразится полная страница, а если будет запрошен через XHR, например для отображения в модальном окне — будет пустой шаблон.
Очень удобно для NoScript пользователей.
Почему одни люди должны за проверку своих сайтов платить деньги, а другие должны качать уже какие-то сборки без дырок которые мне известны? Хотите обезопасить свои сайты — велком в скайп. Расценки тут.
  • avatar akool
  • 0
Вероятно, вы кому-то поможете своими доработками этого модуля. Люди периодически ищут.
Но я, вроде с каким-то опытом, когда взглянул на этот модуль в админке, понял что это совсем не Easy. Куча какой-то лишней информации и настроек. Разбираться замучаешься. Уж не знаю как с этим справляются менеджеры сайтов.
Выкинул его поставил другой модуль со сниппетом. Polls Module
Он, конечно, не идеален, но он проще и понятнее. После доработки вполне можно использовать.