function testGetForObject()
 {
     $object = new ChangeSetItemTest_Versioned(['Foo' => 1]);
     $object->write();
     $item = new ChangeSetItem(['ObjectID' => $object->ID, 'ObjectClass' => $object->baseClass()]);
     $item->write();
     $this->assertEquals(ChangeSetItemTest_Versioned::get()->byID($object->ID)->toMap(), ChangeSetItem::get_for_object($object)->first()->Object()->toMap());
     $this->assertEquals(ChangeSetItemTest_Versioned::get()->byID($object->ID)->toMap(), ChangeSetItem::get_for_object_by_id($object->ID, $object->ClassName)->first()->Object()->toMap());
 }
 public function testSync()
 {
     $this->publishAllFixtures();
     $cs = new ChangeSet();
     $cs->write();
     $base = $this->objFromFixture(ChangeSetTest_Base::class, 'base');
     $cs->addObject($base);
     $cs->sync();
     $this->assertChangeSetLooksLike($cs, ['ChangeSetTest_Base.base' => ChangeSetItem::EXPLICITLY]);
     $end = $this->objFromFixture(ChangeSetTest_End::class, 'end1');
     $end->Baz = 3;
     $end->write();
     $cs->sync();
     $this->assertChangeSetLooksLike($cs, ['ChangeSetTest_Base.base' => ChangeSetItem::EXPLICITLY, 'ChangeSetTest_End.end1' => ChangeSetItem::IMPLICITLY]);
     $baseItem = ChangeSetItem::get_for_object($base)->first();
     $endItem = ChangeSetItem::get_for_object($end)->first();
     $this->assertEquals([$baseItem->ID], $endItem->ReferencedBy()->column("ID"));
     $this->assertDOSEquals([['Added' => ChangeSetItem::EXPLICITLY, 'ObjectClass' => ChangeSetTest_Base::class, 'ObjectID' => $base->ID, 'ChangeSetID' => $cs->ID]], $endItem->ReferencedBy());
 }
 /**
  * Builds a Form that mirrors the parent editForm, but with an extra field to collect the ChangeSet ID
  *
  * @param DataObject $object The object we're going to be adding to whichever ChangeSet is chosen
  * @return Form
  */
 public function Form($object)
 {
     $inChangeSets = array_unique(ChangeSetItem::get_for_object($object)->column('ChangeSetID'));
     $changeSets = $this->getAvailableChangeSets()->map();
     $campaignDropdown = DropdownField::create('Campaign', '', $changeSets);
     $campaignDropdown->setEmptyString(_t('Campaigns.AddToCampaign', 'Select a Campaign'));
     $campaignDropdown->addExtraClass('noborder');
     $campaignDropdown->setDisabledItems($inChangeSets);
     $fields = new FieldList([$campaignDropdown, HiddenField::create('ID', null, $this->data['ID']), HiddenField::create('ClassName', null, $this->data['ClassName'])]);
     $form = new Form($this->editForm->getController(), $this->editForm->getName(), new FieldList($header = new CompositeField(new LiteralField('Heading', sprintf('<h3>%s</h3>', _t('Campaigns.AddToCampaign', 'Add To Campaign')))), $content = new CompositeField($fields)), new FieldList($action = AddToCampaignHandler_FormAction::create()));
     $header->addExtraClass('add-to-campaign__header');
     $content->addExtraClass('add-to-campaign__content');
     $action->addExtraClass('add-to-campaign__action');
     $form->setHTMLID('Form_EditForm_AddToCampaign');
     $form->unsetValidator();
     $form->loadDataFrom($this->data);
     $form->addExtraClass('add-to-campaign__form');
     return $form;
 }
 /**
  * Get the ChangeSetItems that reference a passed DataObject
  *
  * @param int $objectID The ID of the object
  * @param string $objectClass The class of the object (or any parent class)
  * @return DataList
  */
 public static function get_for_object_by_id($objectID, $objectClass)
 {
     return ChangeSetItem::get()->filter(['ObjectID' => $objectID, 'ObjectClass' => static::getSchema()->baseDataClass($objectClass)]);
 }
 /**
  * Add implicit changes that should be included in this changeset
  *
  * When an item is created or changed, all it's owned items which have
  * changes are implicitly added
  *
  * When an item is deleted, it's owner (even if that owner does not have changes)
  * is implicitly added
  */
 public function sync()
 {
     // Start a transaction (if we can)
     DB::get_conn()->withTransaction(function () {
         // Get the implicitly included items for this ChangeSet
         $implicit = $this->calculateImplicit();
         // Adjust the existing implicit ChangeSetItems for this ChangeSet
         /** @var ChangeSetItem $item */
         foreach ($this->Changes()->filter(['Added' => ChangeSetItem::IMPLICITLY]) as $item) {
             $objectKey = $this->implicitKey($item);
             // If a ChangeSetItem exists, but isn't in $implicit, it's no longer required, so delete it
             if (!array_key_exists($objectKey, $implicit)) {
                 $item->delete();
             } else {
                 $item->ReferencedBy()->setByIDList($implicit[$objectKey]['ReferencedBy']);
                 unset($implicit[$objectKey]);
             }
         }
         // Now $implicit is all those items that are implicitly included, but don't currently have a ChangeSetItem.
         // So create new ChangeSetItems to match
         foreach ($implicit as $key => $props) {
             $item = new ChangeSetItem($props);
             $item->Added = ChangeSetItem::IMPLICITLY;
             $item->ChangeSetID = $this->ID;
             $item->ReferencedBy()->setByIDList($props['ReferencedBy']);
             $item->write();
         }
     });
 }
 /**
  * Build item resource from a changesetitem
  *
  * @param ChangeSetItem $changeSetItem
  * @return array
  */
 protected function getChangeSetItemResource(ChangeSetItem $changeSetItem)
 {
     $baseClass = DataObject::getSchema()->baseDataClass($changeSetItem->ObjectClass);
     $baseSingleton = DataObject::singleton($baseClass);
     $thumbnailWidth = (int) $this->config()->thumbnail_width;
     $thumbnailHeight = (int) $this->config()->thumbnail_height;
     $hal = ['_links' => ['self' => ['href' => $this->ItemLink($changeSetItem->ID)]], 'ID' => $changeSetItem->ID, 'Created' => $changeSetItem->Created, 'LastEdited' => $changeSetItem->LastEdited, 'Title' => $changeSetItem->getTitle(), 'ChangeType' => $changeSetItem->getChangeType(), 'Added' => $changeSetItem->Added, 'ObjectClass' => $changeSetItem->ObjectClass, 'ObjectID' => $changeSetItem->ObjectID, 'BaseClass' => $baseClass, 'Singular' => $baseSingleton->i18n_singular_name(), 'Plural' => $baseSingleton->i18n_plural_name(), 'Thumbnail' => $changeSetItem->ThumbnailURL($thumbnailWidth, $thumbnailHeight)];
     // Get preview urls
     $previews = $changeSetItem->getPreviewLinks();
     if ($previews) {
         $hal['_links']['preview'] = $previews;
     }
     // Get edit link
     $editLink = $changeSetItem->CMSEditLink();
     if ($editLink) {
         $hal['_links']['edit'] = ['href' => $editLink];
     }
     // Depending on whether the object was added implicitly or explicitly, set
     // other related objects.
     if ($changeSetItem->Added === ChangeSetItem::IMPLICITLY) {
         $referencedItems = $changeSetItem->ReferencedBy();
         $referencedBy = [];
         foreach ($referencedItems as $referencedItem) {
             $referencedBy[] = ['href' => $this->SetLink($referencedItem->ID)];
         }
         if ($referencedBy) {
             $hal['_links']['referenced_by'] = $referencedBy;
         }
     }
     return $hal;
 }
 /**
  * Builds a Form that mirrors the parent editForm, but with an extra field to collect the ChangeSet ID
  *
  * @param DataObject $object The object we're going to be adding to whichever ChangeSet is chosen
  * @return Form
  */
 public function Form($object)
 {
     $inChangeSets = array_unique(ChangeSetItem::get_for_object($object)->column('ChangeSetID'));
     $changeSets = $this->getAvailableChangeSets()->map();
     $campaignDropdown = DropdownField::create('Campaign', '', $changeSets);
     $campaignDropdown->setEmptyString(_t('Campaigns.AddToCampaignFormFieldLabel', 'Select a Campaign'));
     $campaignDropdown->addExtraClass('noborder');
     $campaignDropdown->addExtraClass('no-chosen');
     $campaignDropdown->setDisabledItems($inChangeSets);
     $fields = new FieldList([$campaignDropdown, HiddenField::create('ID', null, $this->data['ID']), HiddenField::create('ClassName', null, $this->data['ClassName'])]);
     $form = new Form($this->controller, $this->name, $fields, new FieldList($action = AddToCampaignHandler_FormAction::create()));
     $action->addExtraClass('add-to-campaign__action');
     $form->setHTMLID('Form_EditForm_AddToCampaign');
     $form->loadDataFrom($this->data);
     $form->getValidator()->addRequiredField('Campaign');
     $form->addExtraClass('form--no-dividers add-to-campaign__form');
     return $form;
 }