We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 24865
    • 289 Posts
    Hey guys,

    I’m trying to create a installer package for my component/snippet so that people can put twitfeeds on there website through many methods. Currently supported is RSS, PHP and JavaScript. I’ve been creating my own package for about 2 hours now but the tutorial is strangly though to read through. It seems like Shaun is pulling files out of no where, and I can’t find a sample package that would fill in the blanks for me. (this is the tutorial I’m talking about: http://rtfm.modx.com/display/revolution20/Creating+a+3rd+Party+Component+Build+Script)

    Now, I’m still a fresh one when it comes down to MODx but I think I grasp the core very well and it’s time to move to the next level; creating plugins and components for the MODx community to use. So, please help me obtain this goal and provide some insight into this problem... There still are hardly any tutorials online about Revo.

    Thanks a bunch, and oh yea; included is my current transport file. I don’t need corrections on it, I need a thorough tutorial or sample zip.

    <?php
    
    	/**
    	* @author ReSpawN
    	* @copyright 2010
    	*/
    	
    	set_time_limit(0);
    	
    	list($sec, $mcs) = explode(' ', microtime());
    	$tstart = ($mcs + $sec);
    	
    	$root = dirname(dirname(__FILE__));
    	$sources = array(
    		'root' => $root,
    	 	'build' => $root.'_build/',
    		'resolvers' => $root.'_build/resolvers/',
    		'data' => $root.'_build/data/',
    		'source_core' => $root.'core/components/twitfeed/',
    		'lexicon' => $root.'core/components/twitfeed/lexicon/',
    		'source_assets' => $root.'assets/components/twitfeed/',
    		'docs' => $root.'core/components/twitfeed/docs/'
    	);
    	
    	unset($root, $sec, $mcs); 
    	
    	require_once(dirname(__FILE__).'/build.config.php');
    	require_once(MODX_CORE_PATH.'model/modx/modx.class.php');
    	$modx = new modX();
    	
    	$modx->initialize('mgr');
    	$modx->setLogLevel(modX::LOG_LEVEL_INFO);
    	$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
    	
    	$modx->loadClass('transport.modPackageBuilder', '', false, true);
    	$builder = new modPackageBuilder($modx);
    	$builder->createPackage('twitfeed', '1.0', 'alpha1');
    	$builder->registerNamespace('twitfeed', false, true, '{core_path}components/twitfeed/');
    	
    	// Include and build the menu
    	$menu = include($settings['data'].'transport.menu.php');
    	$vehicle = $builder->createVehicle($menu, array(
    		xPDOTransport::PRESERVE_KEYS => true,
    		xPDOTransport::UPDATE_OBJECT => true,
    		xPDOTransport::UNIQUE_KEY => 'text',
    		xPDOTransport::RELATED_OBJECTS => true,
    		xPDOTransport::RELATED_OBJECT_ATTRIBUTES => array(
    			'Action' => array(
    				xPDOTransport::PRESERVE_KEYS => false,
    				xPDOTransport::UPDATE_OBJECT => true,
    				xPDOTransport::UNIQUE_KEY => array('namespace', 'controller')
    			)
    		)
    	));
    	
    	$builder->putVehicle($vehicle);
    	unset($vehicle, $action, $menu);
    	
    	$settings = array();
    	include($sources['data'].'transport.settings.php');
    	
    	$attributes = array(
    		xPDOTransport::UNIQUE_KEY => 'key',
    		xPDOTransport::PRESERVE_KEYS => true,
    		xPDOTransport::UPDATE_OBJECT => false
    	);
    	
    	foreach($settings as $setting) {
    		$vehicle = $builder->createVehicle($setting, $attributes);
    		$builder->putVehicle($vehicle);
    	}
    	
    	unset($settings, $setting, $attributes);
    	
    	$category = $modx->newObject('modCategory');
    	$category->set('id', 1);
    	$category->set('category', 'twitFeed');
    	
    	$snippet = $modx->newObject('modSnippet');
    	$snippet->set('id', 1);
    	$snippet->set('name', 'twitFeed');
    	$snippet->set('description', 'twitFeed Snippet');
    	$snippet->set('snippet', file_get_contents($sources['source_core'].'snippet.twitfeed.php'));
    	
    	$properties = include($sources['data'].'properties.inc.php');
    	$snippet->setProperties($properties);
    	$category->addMany($snippet);
    	
    	/* Below this is where I kinda lost it... */
    	
    	$chunks = include($sources['data'].'transport.chunks.php');
    	if (is_array($chunks)) {
    		$category->addMany($chunks);
    	} else {
    		$modx->log(modX::LOG_LEVEL_FATAL, 'Adding chunks failed');
    	}
    	
    	
    	$vehicle = $builder->createVehicle($snippet, array(
    		xPDOTransport::UNIQUE_KEY => 'name',
    		xPDOTransport::UPDATE_OBJECT => true,
    		xPDOTransport::PRESERVE_KEYS => false
    	));
    	
    ?>
      @MarkGHErnst

      Developer at Adwise Internetmarketing, the Netherlands.
      • 26903
      • 1,336 Posts
      You may be better looking at existing transport files as well as the docs here, Shaun has some good ones in his GitHub area, the demo site one is fairly comprehensive, they are usually under the _build directory.
        Use MODx, or the cat gets it!
        • 1778
        • 659 Posts
        You should have a look at
        http://rtfm.modx.com/display/ADDON/modExtra

        For myself, i found this post very useful too, to understand the "why" of some files, and the "how" it works...
        http://modxcms.com/forums/index.php/topic,48952.msg286100.html (especially the post from Splittingred with detailed explanations on how he works outside modx in the development of 3PC components)

        Hope this will help you too...
        Cheers
          • 24865
          • 289 Posts
          Thanks guys, I’m gonna look into that after my break. I’ll get back to you.
            @MarkGHErnst

            Developer at Adwise Internetmarketing, the Netherlands.
            • 3749
            • 24,544 Posts
            Here’s the SPForm build script, which uses categories (if you don’t need another php script to do stuff after the pieces are installed or to interact with the user during the install, you won’t need the install-script or user-input parts):

            <?php
            /**
             * SPform Build Script
             *
             * @name SPform
             * @version 3.1.2
             * @release beta
             * @author BobRay <[email protected]>
             */
            global $modx;
            
            $mtime = microtime();
            $mtime = explode(" ", $mtime);
            $mtime = $mtime[1] + $mtime[0];
            $tstart = $mtime;
            set_time_limit(0);
            
            $root = dirname(dirname(__FILE__)).'/';
            $sources= array (
                'root' => $root,
                'build' => $root . '_build/',
                'data' => $root . '_build/data/',
                'lexicon' => $root . 'core/components/spform/lexicon/',
                'docs' => $root . 'core/components/spform/docs/',
                'source_assets' => $root . 'assets/components/spform',
                'source_core' => $root . 'core/components/spform',
            );
            unset($root);
            
            
            $packageNamespace = 'spform';
            
            
            /* The name of the package as it will appear in Package Manager will be this plus
             * the next two variables */
            define('PKG_NAME','spform');
            define('PKG_NAME_LOWER','spform');
            define('PKG_VERSION','3.1.2');
            define('PKG_RELEASE','beta1');
            
            
            /* override with your own defines here (see build.config.sample.php */
            require_once dirname(__FILE__).'/build.config.php';
            require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
            
            $modx= new modX();
            $modx->initialize('mgr');
            echo '<pre>'; /* used for nice formatting for log messages  */
            $modx->setLogLevel(modX::LOG_LEVEL_INFO);
            $modx->setLogTarget('ECHO');
                /* $modx->setDebug(true); */
            
            $modx->loadClass('transport.modPackageBuilder','',false, true);
            $builder = new modPackageBuilder($modx);
            $builder->createPackage(PKG_NAME_LOWER,PKG_VERSION,PKG_RELEASE);
            $builder->registerNamespace(PKG_NAME_LOWER,false,true,'{core_path}components/'.PKG_NAME_LOWER.'/');
            
            /* create category */
            $attr = array(
                xPDOTransport::UNIQUE_KEY => 'category',
                xPDOTransport::PRESERVE_KEYS => false,
                xPDOTransport::UPDATE_OBJECT => true,
                xPDOTransport::RELATED_OBJECTS => true,
                xPDOTransport::RELATED_OBJECT_ATTRIBUTES => array (
                    'Snippets' => array (
                        xPDOTransport::PRESERVE_KEYS => false,
                        xPDOTransport::UPDATE_OBJECT => true,
                        xPDOTransport::UNIQUE_KEY => 'name',
                    ),
                    'Chunks' => array (
                        xPDOTransport::PRESERVE_KEYS => false,
                        xPDOTransport::UPDATE_OBJECT => true,
                        xPDOTransport::UNIQUE_KEY => 'name',
                    ),
                )
            );
            $categoryObject= $modx->newObject('modCategory');
            $categoryObject->set('id',1);
            $categoryObject->set('category','SPForm');
            
            /* add snippets to category */
            $snippets = require_once $sources['data'].'transport.snippets.php';
            $categoryObject->addMany($snippets,'Snippets');
            
            /* add chunks to category */
            $chunks = require_once $sources['data'].'transport.chunks.php';
            $categoryObject->addMany($chunks,'Chunks');
            
            /* build category */
            $vehicle = $builder->createVehicle($categoryObject,$attr);
            $vehicle->resolve('file',array(
                'source' => $sources['source_assets'],
                'target' => "return MODX_ASSETS_PATH . 'components/';",
            ));
            $vehicle->resolve('file',array(
                'source' => $sources['source_core'],
                'target' => "return MODX_CORE_PATH . 'components/';",
            ));
            
            /* Add the resources (documents) */
            $vehicle->resolve('php',array(
                'type' => 'php',
                'source' => $sources['data'] . 'transport.resources.php',
                'target' => "return '" . $sources['build'] . "';"
            ));
            
            $vehicle->resolve('php',array(
                'type' => 'php',
                'source' => $sources['build'] . 'install-script.php',
                'target' => "return '" . $sources['build'] . "';"
            ));
            
            
            $builder->putVehicle($vehicle);
            
            /* done setting category/snippets/chunks */
            
            
            /* Add the resources (documents)
            $resources = require_once $sources['data'].'transport.resources.php';
            $attributes= array(
                xPDOTransport::UNIQUE_KEY => 'pagetitle',
                xPDOTransport::UPDATE_OBJECT => false,
                xPDOTransport::PRESERVE_KEYS => false,
            );
            foreach ($resources as $k => $resource) {
                $vehicle = $builder->createVehicle($resource,$attributes);
                if ($resource->get('pagetitle') == 'Thank You') {
                    $modx->log(modX::LOG_LEVEL_INFO,'Packaging install script.<br />');
                    $vehicle->resolve('php',array(
                        'type' => 'php',
                        'source' => $sources['build'] . 'install-script.php',
                        'target' => "return '" . $sources['build'] . "';"
                    ));
                }
                $builder->putVehicle($vehicle);
            }
            
            */
            
            /* done building package */
            /* now pack in the license file, readme and setup options */
            $builder->setPackageAttributes(array(
                'readme' => file_get_contents($sources['docs'] . 'readme.txt'),
                'license' => file_get_contents($sources['docs'] . 'license.txt'),
                'setup-options' => array(
                    'source' => $sources['build'] . 'user_input.php',
                ),
            ));
            
            
            /* zip up the package  */
            $builder->pack();
            
            $mtime= microtime();
            $mtime= explode(" ", $mtime);
            $mtime= $mtime[1] + $mtime[0];
            $tend= $mtime;
            $totalTime= ($tend - $tstart);
            $totalTime= sprintf("%2.4f s", $totalTime);
            
            $modx->log(MODX_LOG_LEVEL_INFO,'Package completed.<br />Execution time: '
                    . $totalTime . '<br />');
            
            exit();


            This is the transport.chunks.php file (the transport.snippets.php file is similar):

            <?php
            /**
             * @package spform
             * @subpackage build
             */
            $chunks = array();
            
            $chunks[1]= $modx->newObject('modChunk');
            $chunks[1]->fromArray(array(
                'id' => 1,
                'name' => 'spformTpl',
                'description' => 'SPForm contact form template',
            ),'',true,true);
            $chunks[1]->setContent(file_get_contents($sources['source_core'] . '/templates/spform.tpl'));
            
            $chunks[2]= $modx->newObject('modChunk');
            $chunks[2]->fromArray(array(
                'id' => 2,
                'name' => 'spformprocTpl',
                'description' => 'SPForm error page template',
            ),'',true,true);
            $chunks[2]->setContent(file_get_contents($sources['source_core'] . '/templates/spformproc.tpl'));
            
            $chunks[3]= $modx->newObject('modChunk');
            $chunks[3]->fromArray(array(
                'id' => 3,
                'name' => 'spfresponseTpl',
                'description' => 'SPForm "Thank You" page template',
            ),'',true,true);
            $chunks[3]->setContent(file_get_contents($sources['source_core'] . '/templates/spfresponse.tpl'));
            
            $chunks[4]= $modx->newObject('modChunk');
            $chunks[4]->fromArray(array(
                'id' => 4,
                'name' => 'spfcaptchaTpl',
                'description' => 'SPForm captcha template',
            ),'',true,true);
            $chunks[4]->setContent(file_get_contents($sources['source_core'] . '/templates/spfcaptcha.tpl'));
            
            return $chunks;
              Did I help you? Buy me a beer
              Get my Book: MODX:The Official Guide
              MODX info for everyone: http://bobsguides.com/modx.html
              My MODX Extras
              Bob's Guides is now hosted at A2 MODX Hosting