Автоматическая установка MODX-сайта

Ребята, сегодня я сотворил бомбу :-))) Может кто-то и не оценит, но это реально классная штука! Кому лень читать много буков, можно просто демку посмотреть. В чем его суть? Это пакет, устанавливающий другие пакеты. Звучит просто, но не все так просто, как кажется. Скрипты автоустановки MODX всплывали и раньше. У безумкина это серверные скрипты, выполняющие установку, обновление или удаление MODX. Здесь Илья про свою сборку пишет. Мой пакет работает по другому принципу: он устанавливается как и обычный пакет. Но в него зашита дополнительная логика. В частности сейчас прописана только малая часть того, что я хочу получить в конечном итоге, а именно установка пакетов из списка. Все работает на уровне API MODX, то есть через $modx я и проверяю уже имеющиеся пакеты, установлены они или нет, качаю их, устанавливаю, проверяю ошибки и т.п. К слову, и в этот раз понадобилась вот эта информация, чтобы не обламывался вывод логов. Так вот, преимущество данного способа в том, что во-первых, не надо вообще доступа к серверу иметь, а во-вторых, ставить можно как на чистый MODX, так и уже на работающий с уже установленными пакетами. В перспективе из скрипта будут сразу выполняться всякие настройки системы, создание типовых разделов и т.п. Забегая немного вперед, скажу, что все это я делаю в рамках своей идеи создания готовых сборок сайтов. Немного разверну мысль: с WordPress я познакомился ровно тогда же, когда и с MODX, а именно в январе-феврале 2009-го. Так как я люблю больше программировать, я уцепился за MODX. Мой же товарищ, не умеющий программировать вообще, но любитель блогосферы, подсел на WP. И хотя я сам ничего не делал с WP, я видел как он легко создает на нем новые сайты и что у него есть реальные посещения и т.п. К чему я это все? К тому, что Да, MODX — это Сила, это практически безграничные возможности, Но: 1) все-таки не так много готовых решений, как хотелось бы, 2) нет вообще стандартов по оформлению сайтов и норм шаблонизации, 3) как следствие — нет готовых сайтов-заготовок вообще. Сайтов на WP создается 100 000 в день. На Livestreet (который гораздо ближе к WP, нежели к MODX) тоже не мало сайтов. При этом на этих сайтах в порядке вещей используются дизайны-клоны. И это нормально. Заходишь на сайт, сразу видишь, что это WP или LS, но если там информация, которая тебя интересует, эти мелочи не берешь во внимание. А главное — простота в установке и обслуживании для тех, кто вообще не умеет программировать. Готовых и понятных решений масса. При чем в MODX тоже пакеты устанавливаются просто, но извините, тот же Wayfinder скачать — это мелочь, его еще воткнуть надо куда положено, и параметры всякие прописать. На тот же LS ставятся плагины, которые как правило не требуют никаких действий от владельца сайта. Скачал плагин, становил его, и тут же на сайте новый функционал, новые кнопочки и т.п. И это классно! Другое дело что дорабатывать это все сложнее, чем в MODX, но эти стандарты позволяют всем, и дизайнерам, и программистам, и конечным сайтовладельцам работать как одна команда. Как раз только вчера читал вот эту статью: www.noupe.com/wordpress/wordpress-or-modx-the-winner-is-73407.html (она на англ. Кто переведет и выложит перевод, респект и уважуха!). Человек пишет сравнительный обзор MODX и WP. И говорит о том же: там есть те плюсы и минусы, а там другие. И нам надо смотреть на сторонние решения и высматривать в них плюсы, и портировать их на MODX. Что я хочу сделать? Я пока не доработал еще все, но скоро представлю комплексный пакет, который будет создавать правильную структуру сайта с запилом под шаблонизацию. Дело в том, что сейчас модель MODX не оконченная. В частности MODX-шаблоны, это на самом деле не шаблоны, а больше контроллеры, так как несколько шаблонов мы как правило создает для того, чтобы задать связи TV с документами и распределить логику (с этим шаблоном мы ленту новостей заложим, с этим у нас карточка товара формироваться будет, и т.д.). Но это не комплексная шаблонизация сайта. Попробуйте разом сменить дизайн сайта, а лучше попереключать несколько вариантов оформления… В модели, которую я закладываю, как я и сказал, MODX-шаблоны будут выполнять только роль контроллеров. Сама же шаблонизация будет выполняться с использованием различных систем-шаблонизаторов. Пакет modxSmarty я уже собрал (но выложу, когда окончательно его обкатаю и дополню). Он не устанавливает Smarty (так как Smarty уже есть в MODX), но он создает плагин, который подключает Smarty для фронтэнда, а так же прописывает настройки пути до папки шаблонов (скинов), используемого шаблона для сайта и т.п., очищает Smarty-кеш, когда очищается кеш всего сайт. А главное — устанавливает дополнительные функции-плагины для Smarty, которые позволяют работать с MODX-элементами. К примеру, чтобы вызвать тот же Wayfinder, можно будет на уровне Smarty-шаблона прописать {snippet name=«Wayfinder»}. В дальнейшем появятся и другие шаблонизаторы. Первый на очереди — Twig. Все это не только откроет дорогу для тех программистов, которые не работали раньше с MODX только потому что им не хотелось связываться с парсером MODX, но и позволит привлечь дизайнеров для разработки готовых копируемых тем для MODX-сайтов. И быть может MODX все-таки войдет и в блогосферу… UPD: Исходники пакета выложу позже, а пока самое интересное из него — резолвер, который и устанавливает пакеты. <?php

if ($object->xpdo) { $modx =& $object->xpdo; // $modelPath = $modx->getOption($pkgName.'.core_path',null,$modx->getOption('core_path').'components/ '.$pkgName.'/').'model/';

switch ($options[xPDOTransport::PACKAGE_ACTION]) {
    case xPDOTransport::ACTION_INSTALL:
    case xPDOTransport::ACTION_UPGRADE:
        
        if ($modx instanceof modX) {
            if(!$modx->loadClass('transport.modTransportPackage')){
                return $modx->log(modX::LOG_LEVEL_ERROR, "Could not load 

modTransportPackage class"); }

            /*
             * Packages need to install
             */
            $packages = array(
                'Wayfinder',
                'getResources',
                'getPage',
                'Ace',
                'TinyMCE',
                'phpTemplates',
                'GoogleSiteMap',
            );
            
            $modx->log(modX::LOG_LEVEL_INFO, "Trying to install packages: ". 

implode(", ", $packages). "<br />\n Be patient. it`s take a several moments.");

            $modx->setLogLevel(modX::LOG_LEVEL_INFO);
            $LogTarget = $modx->getLogTarget();  
            $LogTopic = $LogTarget->subscriptions[0];
            $messages = array();

            
             
            foreach($packages as $packageName){
                if(!$packageName)  continue;
                
                if($packageExists =  $modx->getObject('modTransportPackage', 

array( 'package_name' => $packageName, ))){ $messages[] = array( 'level' => modX::LOG_LEVEL_INFO, 'msg' => "Package '{$packageName}' allready exists" , );

                    /*
                     * Check is installed
                     */
                    if(!$packageExists->get('installed')){
                        $messages[] = array(
                            'level' => modX::LOG_LEVEL_ERROR,
                            'msg'   => "Package '{$packageName}' exists, but not 

installed. Please, install it manually" , ); } continue; } // $modx->log(modX::LOG_LEVEL_INFO, "Try to get '{$packageName}' package.");

                $response = $modx->runProcessor('workspace/packages/rest/getlist', array(
                    'provider' => 1,
                    'query'  => $packageName,
                ));
                
                if($response->isError()){
                    $messages[] = array(
                        'level' => modX::LOG_LEVEL_ERROR,
                        'msg'   => $response->getMessage(),
                    );
                    continue;
                }
                
                if(!$result = json_decode($response->getResponse())){ 
                    $messages[] = array(
                        'level' => modX::LOG_LEVEL_ERROR,
                        'msg'   => "Error while reading results" ,
                    );
                    continue;
                }
                
                /*
                 * Try to find package info
                 */
                foreach($result->results as $r){
                    $package = (array)$r;
                    if($package['name'] == $packageName){
                        goto downloadPackage;
                    }
                }
                
                /*
                 * Info was not found
                 */
                $messages[] = array(
                    'level' => modX::LOG_LEVEL_ERROR,
                    'msg'   => "Package '{$packageName}' was not found. Please try 

to install it manually" , ); continue;

                /*
                 * Download Package
                 */
                downloadPackage: 
                $messages[] = array(
                        'level' => modX::LOG_LEVEL_INFO,
                        'msg'   => "Trying to download '{$packageName}' package" ,
                );
                        
                $response = $modx->runProcessor('workspace/packages/rest/download', array(
                    'provider' => 1,
                    'info'  =>  "{$package['location']}::{$package['signature']}",
                ));
                
                if($response->isError()){
                    $messages[] = array(
                        'level' => modX::LOG_LEVEL_ERROR,
                        'msg'   => "Failed download '{$packageName}'. ".$response->getMessage(),
                    );
                    continue;
                }
                $result = $response->getResponse();
                if($result['success'] == 1){
                    $messages[] = array(
                        'level' => modX::LOG_LEVEL_INFO,
                        'msg'   => "Package '{$packageName}' downloaded success" ,
                    );
                    goto installPackage;
                }
                $messages[] = array(
                    'level' => modX::LOG_LEVEL_ERROR,
                    'msg'   => "Failed download '{$packageName}'.",
                );
                
                
                /*
                 * Installing Package
                 */
                installPackage:
                $messages[] = array(
                        'level' => modX::LOG_LEVEL_INFO,
                        'msg'   => "Trying to install '{$packageName}' package" ,
                );
                
                        
                $response = $modx->runProcessor('workspace/packages/install', array(
                    'signature' => $package['signature'], 
                ));
                
                if($response->isError()){
                    $messages[] = array(
                        'level' => modX::LOG_LEVEL_ERROR,
                        'msg'   => "Failed install '{$packageName}'. ". $response->getMessage(),
                    );
                    continue;
                }
                $messages[] = array(
                    'level' => modX::LOG_LEVEL_INFO,
                    'msg'   => $response->getMessage() ,
                );
            }
             
            $modx->registry->setLogging($LogTarget, $LogTopic);
            // $modx->log(xPDO::LOG_LEVEL_ERROR, '$err');
            // print_r($messages);
            $modx->setLogLevel(modX::LOG_LEVEL_INFO);
            foreach($messages as $msg){
                $modx->log($msg['level'], $msg['msg']);
            }
        }
        break; 
}

} return true;