We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 16895
    • 87 Posts
    Using MODx Revo 2.0.6-pl I cannot find a way to make new duplicate resources and their children publish on creation. I have publish_default set to Yes, but although this makes brand new resources published by default, it does not affect new duplicated resources.

    Is this a bug in the core, and is there a quick fix?

    Thanks,
    Ross
      • 3749
      • 24,544 Posts
      Duplicated resources should have the published status of the resource you’re duplicating. If it doesn’t do that, it’s a bug, but since that’s what people would most often want, publish_default doesn’t figure in.

      If you don’t want to show the document you’re duplicating, you can make it published, but check the "Hide From Menus" checkbox on the page settings tab.

      If you really don’t want to publish the original, you can create a plugin that sets the published status connected to OnResourceDuplicate -- something like this:

      <?php
      $pubStatus = $modx->getOption('publish_default');
      // or
      // $pubStatus = 1;
      
      $newResource->set('published', $pubStatus);
        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
        • 16895
        • 87 Posts
        Using either
        <?php
        $pubStatus = 1;
        $newResource->set('published', $pubStatus);


        or

        <?php
        $pubStatus = $modx->getOption('publish_default');
        $newResource->set('published', $pubStatus);


        doesn’t seem to work.

        I have noticed that modresource.class.php contains the following, though:

        public function duplicate(array $options = array()) {
        [do stuff]
         $newResource->set('published',false);
         $newResource->set('publishedon',0);
         $newResource->set('publishedby',0);
        [more stuff]
        }
        


        I thought it might be the zeroed publishedon date that was stopping it publishing, but
        <?php
        $pubStatus = 1; //$modx->getOption('publish_default');
        $now = time();
        $newResource->set('published', $pubStatus);
        $newResource->set('publishedon', $now);


        also fails.

        Is the onResourceDuplicate event firing properly, or am I doing something wrong?

        Thanks for the help.
          • 3749
          • 24,544 Posts
          I see what you mean. OnResourceDuplicate fires *after* the duplicate has been saved and there’s no OnBeforeResourceDuplicate that I can see.

          Try adding $newResource->save() to the end of your plugin code. That should save the new value for published.
            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
            • 16895
            • 87 Posts
            Adding the save works perfectly for setting the top resource to published smiley, but all the children remain unpublished. I’m hardly familiar with PHP, let alone all of the OO and XPDO stuff, so I tried the following:

            <?php
            $pubStatus = 1; //$modx->getOption('publish_default');
            $now = time();
            $newResource->set('published', $pubStatus);
            $newResource->set('publishedon', $now);
            $newResource->save();
              
            // Create criteria to find children of $newResource
            $criteria = $modx->newQuery('modResource');
            $criteria->where(array(
               'parent' => $newResource->get('id'),
            ));
            // Get children as array
            $children = $modx->resource->getMany('Children',$criteria);
              
            // Set children to published
              foreach ($children as $child) {
                $child->set('published', $pubStatus);
                $child->set('publishedon', $now);
                $child->save();
              }
            ?>
            ​


            However, it never finishes saving the duplicates and on reloading the manager nothing apart from the top resource has been made published. Is there a way of publishing the children recursively?

            Thanks.
              • 3749
              • 24,544 Posts
              Try it this way:

              <?php
              $pubStatus = 1; //$modx->getOption('publish_default');
              
              $newResource->set('published', $pubStatus);
              $newResource->save();
                
              // Get children as array
              $children = $modx->newResource->getMany('Children');
                
              // Set children to published
                foreach ($children as $child) {
                  $child->set('published', $pubStatus);
                  $child->save();
                }
              ?>
              ​


              It’s possible that publishedon is messing you up. It’s definitely not necessary, and I think the processor is actually expecting a string (e.g., 01/04/2011 2:00 pm) there rather than a timestamp.
                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
                • 16895
                • 87 Posts
                I’ve got it almost working now grin

                <?php
                $pubStatus = $modx->getOption('publish_default');
                  
                // Set top-level resource to pubStatus
                $newResource->set('published', $pubStatus);
                $newResource->save();
                  
                function iterateChildren($children,$pubStatus) {
                  foreach ($children as $child) {
                    $child->set('published', $pubStatus);
                    $child->save();
                    $childChildren = $child->getMany('Children');
                    iterateChildren($childChildren,$pubStatus);
                  }
                }
                  
                // Get children as array
                $children = $newResource->getMany('Children');
                  
                // Recursively set children to pubStatus
                  iterateChildren($children,$pubStatus);​
                ?>
                


                This takes the publish_default setting and on duplicating a resource recursively sets all of the new resources to that setting. The only thing I can’t work out is how to set pubStatus to the pubStatus of the original(s). I’ve tried:

                $pubStatus = $modx->resource->get('published'); 


                but it doesn’t seem to work. Any ideas?
                  • 3749
                  • 24,544 Posts
                  That gets the published status of the current document (the manager page?), so it’s not going to help.

                  This should work:

                  $pubStatus = $oldResource->get('published');
                    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
                    • 16895
                    • 87 Posts
                    That works perfectly. I had a go at adding the oldResource children ’published’ statuses to an array and then using that to set the new children, but I can’t figure out why that isn’t working. Here’s the code I’m using:

                    <?php
                    $pubStatus = $oldResource->get('published');
                    // Publish top-level resource
                    $newResource->set('published', $pubStatus);
                    $newResource->save();
                      /*function iterateChildren($children,$pubStatus) {
                      foreach ($children as $child) {
                        $child->set('published', $pubStatus);
                        $child->save();
                        $childChildren = $child->getMany('Children');
                        iterateChildren($childChildren,$pubStatus);
                      }
                      }*/
                    function iterateChildren($children,$pubStatuses,$counter) {
                      foreach ($children as $child) {
                        // Get pubStatus for current child
                        $pubStatus = $pubStatuses[$counter];
                        // Set child to its pubStatus
                        $child->set('published', $pubStatus);
                        $child->save();
                        $counter++;
                        // Find children of child
                        $childChildren = $child->getMany('Children');
                        // Recursively iterate through children and set counter to eventual value
                        $counter = iterateChildren($childChildren,$pubStatuses,$counter);
                      }
                      return $counter;
                    }
                    function getChildrenPubStatus($oldResourceChildren,$childrenPubStatus) {
                      // Loop through each oldResource child
                      foreach ($oldResourceChildren as $oldResourceChild) {
                        // Append oldResource child pubStatus to childrenPubStatus array
                        $childrenPubStatus[] = $oldResourceChild->get('published');
                        // Get children of child
                        $oldResourceChildChildren = $oldResourceChild->getMany('Children');
                        // Loop recursively
                        getChildrenPubStatus($oldResourceChildChildren,$childrenPubStatus);
                        return $childrenPubStatus;
                      }
                    }
                    // Get children as array
                    $children = $newResource->getMany('Children');
                    // Set children to published
                      //iterateChildren($children,$pubStatus);
                    // Get children of oldResource
                    $oldResourceChildren = $oldResource->getMany('Children');
                    $childrenPubStatus = array();
                    // Put pubStatuses into an array
                    $childrenPubStatus = getChildrenPubStatus($oldResourceChildren,$childrenPubStatus);
                    // Recursively loop through children, setting them to original pubStatus value
                    iterateChildren($children,$childrenPubStatuses,0);


                    If anyone needs the working version that sets everything to the published status of the top-level oldResource, this works:
                    <?php
                    $pubStatus = $oldResource->get('published');
                    // Publish top-level resource
                    $newResource->set('published', $pubStatus);
                    $newResource->save();
                    function iterateChildren($children,$pubStatus) {
                      foreach ($children as $child) {
                        $child->set('published', $pubStatus);
                        $child->save();
                        $childChildren = $child->getMany('Children');
                        iterateChildren($childChildren,$pubStatus);
                      }
                      }
                    // Get children as array
                    $children = $newResource->getMany('Children');
                    // Set children to published
                    iterateChildren($children,$pubStatus);
                    


                    Thanks for all the help; I can only hope that one day I will have learnt enough PHP to be as helpful to the community as BobRay is...
                      • 20413
                      • 2,877 Posts
                      Quote from: BobRay at Jan 07, 2011, 05:48 PM

                      Duplicated resources should have the published status of the resource you’re duplicating. If it doesn’t do that, it’s a bug, but since that’s what people would most often want, publish_default doesn’t figure in.

                      Aha! I like it better in EVO where duplicated resources don’t publish right away. Gives you time to work on them first.
                        @hawproductions | http://mrhaw.com/

                        Infograph: MODX Advanced Install in 7 steps:
                        http://forums.modx.com/thread/96954/infograph-modx-advanced-install-in-7-steps

                        Recap: Portland, OR (PDX) MODX CMS Meetup, Oct 6, 2015. US Bancorp Tower
                        http://mrhaw.com/modx_portland_oregon_pdx_modx_cms_meetup_oct_2015_us_bancorp_tower