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; }