+416.50
Рейтинг

Борисов Евгений

Нашел парочку небольших багов, о которых сразу не подумал. Фиксятся легко хаком через расширение класса.
1) Свойство $config не доступно для внешних обращений
2) При возникновении ошибки SQL запроса сайт падает из-за Exception. Это и хорошо и плохо. Хорошо, т.к. теперь можно оформить красивую страничку 500 ошибки. Плохо — по умолчанию не обрабатывается стандартными средствами движка. Как исправить смотрите ниже метод query().
3) Метод insert приводит параметр $fields по таким же правилам, как и в других методах. Соответственно из подобных запросов
$modx->getDatabase()->insert(
        array(
                'name'=>'',
                'description'=>'',
                'disabled'=>'',
                'moduleguid'=>'',
                'plugincode'=>'',
                'properties'=>'',
                'category'=>'',
                ), $modx->getDatabase()->getFullTableName('site_plugins'), // Insert into
        "CONCAT(name, ' {$_lang['duplicated_el_suffix']}{$count}') AS name, description, '1' AS disabled, moduleguid, plugincode, properties, category", $modx->getDatabase()->getFullTableName('site_plugins'), "id='{$id}'");


Мы получаем запрос на вставку данных с пустыми именами полей. Лечится так же подменой insertFrom метода.
Итого получается следующий класс
<?php namespace App;

use AgelxNash\Modx\Evo\Database\LegacyDatabase;
use AgelxNash\Modx\Evo\Database\Exceptions;

class Database extends LegacyDatabase
{
    public $config;

    public function query($sql)
    {
        try {
            return parent::query($sql);
        } catch (Exceptions\QueryException $exception) {
            $core = evolutionCMS();
            /**
             * Ошибка запроса лежит тут $exception->getMessage()
             * Код ошибки $exception->getCode()
             * Сам запрос $exception->getQuery()
             * Вместо $core->messageQuit оформляем свою страницу и делаем die();
             */
            $core->messageQuit($exception->getMessage());
        } catch (Exceptions\ConnectException $exception) {
            $core = evolutionCMS();
            /**
             * Ошибка подключения к базе. Текст ошибки $exception->getMessage()
             * Код ошибки $exception->getCode()
             * Вместо $core->messageQuit оформляем свою страницу и делаем die();
             */
            $core->messageQuit($exception->getMessage());
        } catch (\Exception $exception) {
            $core = evolutionCMS();
            $core->messageQuit($exception->getMessage());
        }
    }

    public function insertFrom(
        $fields,
        $table,
        $fromFields = '*',
        $fromTable = '',
        $where = '',
        $limit = ''
    ) {
        if (is_array($fields)) {
            $onlyKeys = true;
            foreach ($fields as $key => $value) {
                if (!empty($value)) {
                    $onlyKeys = false;
                    break;
                }
            }
            if ($onlyKeys) {
                $fields = array_keys($fields);
            }
        }

        return parent::insertFrom($fields, $table, $fromFields, $fromTable, $where, $limit);
    }
}


Именно App\Database::class нужно будет указать вместо AgelxNash\Modx\Evo\Database\LegacyDatabase::class при подмене
В том месте где был ранее подключался композер, мы обязаны были следить за всеми index и ajax скриптами, чтобы они тоже не забывали это делать. Помимо этого от туда нет доступа ни к одной переменной. Так что config mutator это не просто место для инклюда кастомного автозагрузчика. Собственно это я и хотел показать в статье.
Раньше подключался. Теперь нет, т.к.
— Место подключения выбрано из корня сайта. Лично мне, да я думаю и многим другим это не нравится. Возня с конфигами nginx или .htaccess это не дело. Сейчас же я могу самостоятельно выбирать место где буде располагаться сие чудо.
— composer.json по умолчанию лежит в корне сайта. Многие обновляются перезаписью файлов и может возникнуть много боли, когда по запарке перезатрутся нужные зависимости (composer.lock? А если в этой же запаре уже успели выполнить composer update?)
— Несмотря на подключение автозагрузчика, зависимостей у проекта нет. Даже PHPMailer, PHPThumb до сих пор в ручную обновляют. Целесообразность подобного внедрения вызывает большие вопросы.
На сайтах шлеп-шлеп это и не нужно. Разве только ради самообразования.
Данное решение ориентировано в первую очередь на разработчиков дополнений.

А преимущества — чистота кода, стабильность и предсказуемость работы.
Код покрыт тестами с проверкой ответа от mysqli и pdo. По итогу полная совместимость. В том числе и на escape.
Но вообще, PDO действительно экскейпит по другому. Поэтому пришлось сделать такой хак для обратной совместимости. Но замечу, что этот хак работает только в случае если вы пытаетесь использовать PDO в режиме DBAPI. Для Eloquent стиля все работает как и задумано в Laravel.
ааа, фи… судя по коду это под revo. Удачи в поисках идеала;-)
Еще немного и дойдете до связки LoadElement + evoTwig.
Код сниппет в студию
&tpl=`@T_CODE:<p>{{ data.pagetitle }}</p>`
Нужно понимать, что data.pagetitle это тоже самое, что data[«pagetitle»]. Поэтому для доступа к dl.wrap или tv.image например, нужно использовать data[«dl.wrap»]
Проверьте фикс github.com/evolution-cms/evolution/issues/548
Все ответы на почте
1) Почему тут не используется switch?
2) Почему ключи массива не заключаются в кавычки? По логике пхп, mgrInternalKey, value, etc должны быть константами.
3) этот файл возможно использовать в уязвимости типа LFI и добиться записи произвольных данных в PHP файл

Дальше не стал смотреть, но webber правильно задал направление
Обновил топик
Спасибо. Но если бы изначально я не оглядывался на Ditto и CatalogView, то многое было бы по другому. Многое было бы в разы лучше, хотя и сложнее для понимания:-(
Если найдется желающий взяться за подобное и сообщество одобрит — так тому и быть. Я уже давно с MODX не имел ничего общего — это одна из основных причин почему закончить начатый проект проблематично. В любом случае, всем желающим я верну средства. А то, что останется — можно распределить как угодно.
В общем если есть файл, то просто обновляйте.
Хотелось освежить код при этом иметь максимальную обратную совместимость. А развивать MODX Evo на базе одного класса DocumentParser и кучи-кучи include в админке с кашей из html + php… хм… Что принципиально то изменится? Да ничего, работа ради работы. Более того, когда это будет проделано — тренд modx сойдет в точку zero.

Нужен composer, репозиторий, миграции и сиды? Да пожалуйста:
— Плагин из 1 строчки для подключения autoload.php
— Плагин LoadElement для сохранения чанков и сниппетов в файлах
— EvoTwig для хранения шаблонов в файлах, а не в базе
— Подключаем для миграций самое простое, что только есть github.com/dlevsha/nasgrate
— Накидываем скрипт для сидов. При желании можно даже github.com/fzaninotto/Faker подключить

Я долго к этому шел и наконец постиг ДАО. При желании, можно все ваши хотелки использовать уже сейчас и переписывать ничего не нужно. Или вам не хватает четких примеров с пошаговой инструкцией как и что делать?
Выпадал на некоторое время из MODX сообщества. Но работа идет, далеко не расходимся.