We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 3749
    • 24,544 Posts
    I need (if possible) to have a package create a document, get that document’s id number, create a system setting, and use the id number to set the system setting’s value. (Actually, I need to do this all twice).

    I can imagine (sort of) how the whole sequence could be done in a script, but is there an easier way?

      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
      • 22303 MODX Staff
      • 10,725 Posts
      You create the resource with an arbitrary id, set XPDO_TRANSPORT_PRESERVE_KEYS to false, and then use a Resolver to get the id which was inserted and use it to dynamically create your system settings records.
        • 28215
        • 4,149 Posts
        Quote from: BobRay at Oct 03, 2008, 03:10 PM

        I need (if possible) to have a package create a document, get that document’s id number, create a system setting, and use the id number to set the system setting’s value. (Actually, I need to do this all twice).

        I can imagine (sort of) how the whole sequence could be done in a script, but is there an easier way?

        Best way is through a resolver. Put the Resource in a vehicle, add a resolver that then does something like this:

        if ($id = $object->get('id')) {
        
        $setting = $object->xpdo->newObject('modSystemSetting');
        $setting->set('key','keynamehere');
        $setting->set('namespace','nshere');
        $setting->set... // continue with other values
        $setting->set('value',$id);
        
        $setting->save();
        }
        
          shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
          • 3749
          • 24,544 Posts
          Quote from: splittingred at Oct 03, 2008, 03:12 PM

          Quote from: BobRay at Oct 03, 2008, 03:10 PM

          I need (if possible) to have a package create a document, get that document’s id number, create a system setting, and use the id number to set the system setting’s value. (Actually, I need to do this all twice).

          I can imagine (sort of) how the whole sequence could be done in a script, but is there an easier way?

          Best way is through a resolver. Put the Resource in a vehicle, add a resolver that then does something like this:

          if ($id = $object->get('id')) {
          
          $setting = $object->xpdo->newObject('modSystemSetting');
          $setting->set('key','keynamehere');
          $setting->set('namespace','nshere');
          $setting->set... // continue with other values
          $setting->set('value',$id);
          
          $setting->save();
          }
          



          That is unbelievably awesome (and now I see why resolvers need to be tied to vehicles). grin My jaw literally dropped open when I saw how easily this can be done.

          Is there an example somewhere of how to put a Resource in a vehicle one the fly while setting its fields (e.g. title, longtitle, hide from menu, and content)?

          Here’s a tougher one. I’d like to set the parent of a Resource I’m creating to the ID of the one just created.

          PS: It might be time to create a "package building" forum area -- maybe in the team area for now but moved public on beta?

            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
            • 28215
            • 4,149 Posts
            Quote from: BobRay at Oct 03, 2008, 03:28 PM

            Is there an example somewhere of how to put a Resource in a vehicle one the fly while setting its fields (e.g. title, longtitle, hide from menu, and content)?

            Sure. You could do newObject, create the Resource, then add it to a vehicle. Or you could just do newObject in the resolver.


            Here’s a tougher one. I’d like to set the parent of a Resource I’m creating to the ID of the one just created.

            Okay, that does get more complex. There’s also a feature I think you should know about: XPDO_TRANSPORT_PACKAGE_ACTION. This constant is set upon install/uninstall of the package, and can have 2 different values (as constants):


            • XPDO_TRANSPORT_ACTION_INSTALL
            • XPDO_TRANSPORT_ACTION_UPDATE - currently the same as INSTALL, we’ll be enhancing this later
            • XPDO_TRANSPORT_ACTION_UNINSTALL
            • [li]

            These are passed into the resolver when it is run. So...your parent resource would be in the vehicle, and its resolver code would be best like this:

            $success= false;
            if ($id = $object->get('id')) {
            	switch (XPDO_TRANSPORT_PACKAGE_ACTION) {
            		case XPDO_TRANSPORT_ACTION_INSTALL:
            			$child = $object->xpdo->newObject('modResource');
            			$child->set('pagetitle','Child');
            			...
            			$child->set('parent',$object->get('id');
            			$child->save();
            			$success= true;
            			break;
            		case XPDO_TRANSPORT_ACTION_UPDATE:
            			$child = $object->xpdo->getObject('modResource',array(
            				'pagetitle' => 'Child',
            				'parent' => $object->get('id'),
            			));
            			if ($child == null) {
            				$child = $object->xpdo->newObject('modResource');
            			}
            			// if i wanted to change resource settings on update
            			// ...or make sure the child resource exists if it was deleted
            			// ...or reset them if modified...
            			$child->set('longtitle','New longtitle for update');			
            			$child->save();
            			$success= true;
            			break;
            		case XPDO_TRANSPORT_ACTION_UNINSTALL:
                                    // not doing anything b/c we dont want a new object when uninstalling
            			$success= true;
            			break;
            }
            
            return $success;
            


            Edit: The UPDATE part of that isn’t really necessary atm, since Revo doesn’t currently support it - and we’re not sure if we will, since we’re debating the big debate between Update/Reinstall.


            PS: It might be time to create a "package building" forum area -- maybe in the team area for now but moved public on beta?

            I agree.
              shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
              • 3749
              • 24,544 Posts
              Cool. Thanks!

              The update/install/reinstall issue is tough. I’ve found reinstall useful during development, but I can see where "update" might be more trouble than it’s worth (except maybe for the core).
                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
                • 22303 MODX Staff
                • 10,725 Posts

                Here’s a tougher one. I’d like to set the parent of a Resource I’m creating to the ID of the one just created.
                This may also be a case where XPDO_TRANSPORT_RELATED_OBJECTS could be used. If you create the parent object and the child and use the getOne()/addOne()/getMany()/addMany() functions to attach it to the parent, you can include both in one vehicle and it will automatically resolve the foreign key relations on install. For example, here is a complex set of related objects packed and installed from a single Vehicle:
                <?php
                require_once dirname(__FILE__) . '/build.config.php';
                
                require_once (MODX_CORE_PATH . 'model/modx/modx.class.php');
                $modx= new modX();
                $modx->initialize('mgr');
                
                $cacheManager= $modx->getCacheManager();
                $modx->setLogLevel(MODX_LOG_LEVEL_WARN);
                $modx->setLogTarget('FILE');
                
                // load the MODx transport package builder
                $modx->loadClass('transport.modPackageBuilder','',false, true);
                $builder = new modPackageBuilder($modx);
                
                // create the transport with name, version string, and optional release
                $name= 'test';
                $version= '0.0.0';
                $release= '';
                $namespace= 'test';
                $builder->create($name, $version, $release);
                
                $collection = $modx->getCollectionGraph('modResource', '{"modTemplate":{"modTemplateVarTemplate":{}},"modTemplateVarResource":{}}', "modResource.`context_key` IN ('web','test')");
                $attributes = array (
                    XPDO_TRANSPORT_PRESERVE_KEYS => true,
                    XPDO_TRANSPORT_UPDATE_OBJECT => true,
                    XPDO_TRANSPORT_RELATED_OBJECTS => true,
                    XPDO_TRANSPORT_RELATED_OBJECT_ATTRIBUTES => array(
                        'modTemplate' => array(
                            XPDO_TRANSPORT_PRESERVE_KEYS => false,
                            XPDO_TRANSPORT_UPDATE_OBJECT => true,
                            XPDO_TRANSPORT_UNIQUE_KEY => 'templatename',
                        ),
                        'modTemplateVar' => array(
                            XPDO_TRANSPORT_PRESERVE_KEYS => false,
                            XPDO_TRANSPORT_UPDATE_OBJECT => true,
                            XPDO_TRANSPORT_UNIQUE_KEY => 'name',
                        ),
                        'modTemplateVarTemplate' => array(
                            XPDO_TRANSPORT_PRESERVE_KEYS => false,
                            XPDO_TRANSPORT_UPDATE_OBJECT => true,
                        ),
                        'modTemplateVarResource' => array(
                            XPDO_TRANSPORT_PRESERVE_KEYS => false,
                            XPDO_TRANSPORT_UPDATE_OBJECT => true,
                        ),
                    )
                );
                foreach ($collection as $c) {
                    if ($c->modTemplate->modTemplateVarTemplate) {
                        foreach ($c->modTemplate->modTemplateVarTemplate as $k => $tvt) {
                            $tvt->getOne('modTemplateVar');
                        }
                    }
                    $vehicle = $builder->createVehicle($c, $attributes);
                    $builder->putVehicle($vehicle);
                }
                unset ($collection, $c, $vehicle, $attributes);
                
                $builder->pack();
                ?>

                In this example I’m creating a Vehicle for each Resource from two contexts, ’web’ and ’test’, along with all the Templates, TemplateVarTemplate, TemplateVarResource and TemplateVar records that are associated with those Resources.