Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Data Model Questions

Duplicate page should duplicate and link dataobjects


Go to End
Reply

14 Posts   3222 Views

Avatar
Nobrainer Web

1 July 2011 at 11:21am Community Member, 135 Posts

Hi,

I constantly keep running in to this issue.

I like to use DataObjects for lists of items on my pgaes, like images or links.
This works fine, no need for the DataObject Manger Module, just a DO.

Problem is when i duplicate a page (context menu in the CMS), the DataObject "references" gets lost and i'm left with adding all DataObjects manually to my page.

Can someone tell me how to get the DataObjects duplicated aswell? I think this most be something that some of you are using in your projects and i hope you will share some code or help me get it working.

I think it should be a matter of overloading the duplicate() method of the SiteTree class, but i dont know how this is done.
I've read all the threads i could find regarding this matter, closest thing i could find is this post: http://www.silverstripe.org/customising-the-cms/show/11571

Hope that someone can help!

Avatar
Nobrainer Web

1 July 2011 at 11:10pm Community Member, 135 Posts

Ok willr answerede this question for me in the irq channel.

Adding the following code to the Page class (or what class you need it in) will duplicate page and the specified Dataobjects, and set the relation to the duplicated page.

(This method overloads the duplicate method from SiteTree.php - it's this function that is called when you right click a menu item in the CMS and choose duplicate this page)

   /**
   * Duplicate this page, and its DataObjects.
   *
   * @return Page
   */
   public function duplicate() {
      $page = parent::duplicate();
      
      // the PageImages (name of the has many relation)
      if($this->PageImages()) {
         foreach($this->PageImages() as $image) {
            $newField = $image->duplicate();
            $newField->PageID = $page->ID; // Important that this is the ID of the relation to the DO's parent page!
                                     // Can be ParentID, PageID atc. - It's the current class name
            $newField->write();
         }
      }
      
      return $page;
   }

Hope this will help someone else to :o)

Thanks for helping willr

Avatar
mco

26 September 2011 at 9:38pm (Last edited: 26 September 2011 9:38pm), Community Member, 14 Posts

Thanks for the input. I had an issue with updating a many_many relation. But then instead of doing a copy of the original items linked to the current page, you need to re-link them to the new object. Here is the modified code:

   /**
    * Duplicate this page and update it's many_many relations
    *
    * @return Page
    */
   public function duplicate() {
      $page = parent::duplicate();

      if($this->Tags()) {
         $page->Tags()->addMany($this->Tags()->getIdList());
      }

      return $page;
   }

where Tags is defined as

   static $many_many = array(
      'Tags' => 'Tag'
   );

Avatar
dendeffe

27 September 2011 at 2:34am Community Member, 135 Posts

This looks great. I was trying to use it on translations, which doesn't use duplicate (as I was thinking). Any idea where I should get started on that?

Avatar
joelg

6 October 2011 at 11:06am Community Member, 129 Posts

Wonderful informations about duplicating relations. Thanks everybody.

Avatar
max5k

6 March 2012 at 11:19am Community Member, 8 Posts

great, thanks for that one.

this is what i ended up with:

duplicate all has_many and many_many relationships of a page dynamically...:

public function duplicate() {

$page = parent::duplicate();

//duplicate has many items
foreach ($this->has_many() as $key => $className) {
foreach ($this->{$key}() as $item) {
$newField = $item->duplicate();
$id = get_class($this) . 'ID';
$newField->{$id} = $page->ID;
$newField->write();
}
}

//duplicate many_many items
foreach( $this->many_many() as $key => $className ){
$page->{$key}()->addMany($this->{$key}()->getIdList());
}

return $page;
}

cheers

Avatar
Nobrainer Web

6 March 2012 at 8:55pm Community Member, 135 Posts

Thank you so much for posting this max5k, this has gone in to my SilverStripe package that i put on all new sites.
So usefull!

Avatar
max5k

6 March 2012 at 9:19pm Community Member, 8 Posts

you might want to add a filter, which relations to duplicate
the above version does a little too much in some cases...

public function duplicate() {

$items_to_duplicate = array(
'Images' //anything you want to duplicate
);

$page = parent::duplicate();

//duplicate has many items
foreach ($this->has_many() as $key => $className) {
if (in_array($key, $items_to_duplicate)) {
foreach ($this->{$key}() as $item) {
$newField = $item->duplicate();
$id = get_class($this) . 'ID';
$newField->{$id} = $page->ID;
$newField->write();
}
}
}

//duplicate many_many items
foreach ($this->many_many() as $key => $className) {
if (in_array($key, $items_to_duplicate)) {
$page->{$key}()->addMany($this->{$key}()->getIdList());
}
}

return $page;
}

Go to Top