public function testHasOnes()
 {
     $obj1 = $this->objFromFixture('DataDifferencerTest_Object', 'obj1');
     $image1 = $this->objFromFixture('DataDifferencerTest_MockImage', 'image1');
     $image2 = $this->objFromFixture('DataDifferencerTest_MockImage', 'image2');
     $relobj1 = $this->objFromFixture('DataDifferencerTest_HasOneRelationObject', 'relobj1');
     $relobj2 = $this->objFromFixture('DataDifferencerTest_HasOneRelationObject', 'relobj2');
     // in order to ensure the Filename path is correct, append the correct FRAMEWORK_DIR to the start
     // this is only really necessary to make the test pass when FRAMEWORK_DIR is not "framework"
     $image1->Filename = FRAMEWORK_DIR . substr($image1->Filename, 9);
     $image2->Filename = FRAMEWORK_DIR . substr($image2->Filename, 9);
     $origUpdateFilesystem = Config::inst()->get('File', 'update_filesystem');
     // we don't want the filesystem being updated on write, as we're only dealing with mock files
     Config::inst()->update('File', 'update_filesystem', false);
     $image1->write();
     $image2->write();
     Config::inst()->update('File', 'update_filesystem', $origUpdateFilesystem);
     // create a new version
     $obj1->ImageID = $image2->ID;
     $obj1->HasOneRelationID = $relobj2->ID;
     $obj1->write();
     $obj1v1 = Versioned::get_version('DataDifferencerTest_Object', $obj1->ID, $obj1->Version - 1);
     $obj1v2 = Versioned::get_version('DataDifferencerTest_Object', $obj1->ID, $obj1->Version);
     $differ = new DataDifferencer($obj1v1, $obj1v2);
     $obj1Diff = $differ->diffedData();
     $this->assertContains($image1->Filename, $obj1Diff->getField('Image'));
     $this->assertContains($image2->Filename, $obj1Diff->getField('Image'));
     $this->assertContains('<ins>obj2</ins><del>obj1</del>', str_replace(' ', '', $obj1Diff->getField('HasOneRelationID')));
 }
 public function testHasOnes()
 {
     /** @var DataDifferencerTest_Object $obj1 */
     $obj1 = $this->objFromFixture('DataDifferencerTest_Object', 'obj1');
     $image1 = $this->objFromFixture('Image', 'image1');
     $image2 = $this->objFromFixture('Image', 'image2');
     $relobj1 = $this->objFromFixture('DataDifferencerTest_HasOneRelationObject', 'relobj1');
     $relobj2 = $this->objFromFixture('DataDifferencerTest_HasOneRelationObject', 'relobj2');
     // create a new version
     $beforeVersion = $obj1->Version;
     $obj1->ImageID = $image2->ID;
     $obj1->HasOneRelationID = $relobj2->ID;
     $obj1->write();
     $afterVersion = $obj1->Version;
     $this->assertNotEquals($beforeVersion, $afterVersion);
     /** @var DataDifferencerTest_Object $obj1v1 */
     $obj1v1 = Versioned::get_version('DataDifferencerTest_Object', $obj1->ID, $beforeVersion);
     /** @var DataDifferencerTest_Object $obj1v2 */
     $obj1v2 = Versioned::get_version('DataDifferencerTest_Object', $obj1->ID, $afterVersion);
     $differ = new DataDifferencer($obj1v1, $obj1v2);
     $obj1Diff = $differ->diffedData();
     $this->assertContains($image1->Name, $obj1Diff->getField('Image'));
     $this->assertContains($image2->Name, $obj1Diff->getField('Image'));
     $this->assertContains('<ins>obj2</ins><del>obj1</del>', str_replace(' ', '', $obj1Diff->getField('HasOneRelationID')));
 }
 public function handleItem($gridField, $request)
 {
     $controller = $gridField->getForm()->Controller();
     if (is_numeric($request->param('ID')) && is_numeric($request->param('Version'))) {
         $record = Versioned::get_version($gridField->getModelClass(), $request->param('ID'), $request->param('Version'));
     } elseif (is_numeric($request->param('ID'))) {
         $record = Versioned::get_latest_version($gridField->getModelClass(), $request->param('ID'));
     } else {
         $record = Object::create($gridField->getModelClass());
     }
     $class = $this->getItemRequestClass();
     $handler = Object::create($class, $gridField, $this, $record, $controller, $this->name);
     $handler->setTemplate($this->template);
     return $handler->handleRequest($request, DataModel::inst());
 }
Exemplo n.º 4
0
 function testHasOnes()
 {
     $obj1 = $this->objFromFixture('DataDifferencerTest_Object', 'obj1');
     $image1 = $this->objFromFixture('DataDifferencerTest_MockImage', 'image1');
     $image2 = $this->objFromFixture('DataDifferencerTest_MockImage', 'image2');
     $relobj1 = $this->objFromFixture('DataDifferencerTest_HasOneRelationObject', 'relobj1');
     $relobj2 = $this->objFromFixture('DataDifferencerTest_HasOneRelationObject', 'relobj2');
     // create a new version
     $obj1->ImageID = $image2->ID;
     $obj1->HasOneRelationID = $relobj2->ID;
     $obj1->write();
     $obj1v1 = Versioned::get_version('DataDifferencerTest_Object', $obj1->ID, $obj1->Version - 1);
     $obj1v2 = Versioned::get_version('DataDifferencerTest_Object', $obj1->ID, $obj1->Version);
     $differ = new DataDifferencer($obj1v1, $obj1v2);
     $obj1Diff = $differ->diffedData();
     $this->assertContains($image1->Filename, $obj1Diff->getField('Image'));
     $this->assertContains($image2->Filename, $obj1Diff->getField('Image'));
     $this->assertContains('<ins>obj2</ins><del>obj1</del>', $obj1Diff->getField('HasOneRelationID'));
 }
 public function ProductVariation($current = false)
 {
     if ($current) {
         return DataObject::get_by_id('ProductVariation', $this->_productVariationID);
     } else {
         return Versioned::get_version('ProductVariation', $this->_productVariationID, $this->_productVariationVersion);
     }
 }
Exemplo n.º 6
0
 /**
  * Get related product
  *  - live version if in cart, or
  *  - historical version if order is placed
  *
  * @param boolean $forcecurrent - force getting latest version of the product.
  * @return Product
  */
 public function Product($forcecurrent = false)
 {
     //TODO: this might need some unit testing to make sure it compliles with comment description
     //ie use live if in cart (however I see no logic for checking cart status)
     if ($this->ProductID && $this->ProductVersion && !$forcecurrent) {
         return Versioned::get_version('Product', $this->ProductID, $this->ProductVersion);
     } elseif ($this->ProductID && ($product = Versioned::get_one_by_stage("Product", "Live", "\"Product\".\"ID\"  = " . $this->ProductID))) {
         return $product;
     }
     return false;
 }
 public function addVersionViewer(FieldList $fields)
 {
     if ($this->owner->hasExtension('Versioned') || $this->owner->hasExtension('VersionedDataObject')) {
         // Get the object where this function was called for reference purposes
         $object = $this->owner;
         // Get all tabs in the current model admin and prepart to put within a tabset called "Current"
         $current_tabs = $fields->find('Name', 'Root')->Tabs();
         $fields = FieldList::create(TabSet::create("Root", $currenttab = TabSet::create("Current"), $historytab = TabSet::create("History")->addExtraClass("vertical-tabs")));
         // Add all existing tabs to "Current" tabset
         $first = true;
         foreach ($current_tabs as $tab) {
             // If we have the getVersionedState function,
             // add a notice regarding the versioned state to the first tab
             // TODO incorporate VersionedDataObjectState extension into this module
             if ($first && $object->hasMethod('getVersionedState')) {
                 $fields->addFieldToTab("Root.Current." . $tab->title, LiteralField::create('VersionedState', '<div class="message notice"><p>' . $object->getVersionedState() . '</p></div>'));
                 $first = false;
             }
             $fields->addFieldsToTab("Root.Current." . $tab->title, $tab->Fields());
         }
         // Remove any fields that have VersionViewerVisibility turned off
         foreach ($current_tabs as &$tab) {
             foreach ($tab->Fields() as $field) {
                 // echo '<pre>'.$field->Name.' Viewable? '; print_r($field->versionViewerVisibility);
                 if (!$field->versionViewerVisibility && $tab->fieldByName($field->Name)) {
                     $tab->removeByName($field->Name);
                 }
             }
         }
         // die();
         // Also, as of now, Versioned does not track has_many or many_many relationships
         // So find fields relating to those relationships, remove them,
         // and add a message regarding this
         $untracked_msg = "";
         foreach ($current_tabs as &$tab) {
             foreach ($tab->Fields() as $field) {
                 $rel_class = $object->getRelationClass($field->Name);
                 if ($rel_class) {
                     if (in_array($rel_class, $object->has_many()) || in_array($rel_class, $object->many_many())) {
                         if ($tab->fieldByName($field->Name)) {
                             $tab->removeByName($field->Name);
                             if (!$untracked_msg) {
                                 // $untracked_msg = '<div class="message notice"><p>Note: the following relationships are not tracked by versioning because they involve multiple records:<br />';
                                 $untracked_msg = '<p>' . $field->Title();
                             } else {
                                 $untracked_msg .= "<br />" . $field->Title();
                             }
                         }
                     }
                 }
             }
         }
         if ($untracked_msg) {
             $untracked_msg .= '</p>';
         }
         // Get all past versions of this data object and put the relevant data in a set of tabs
         // within a tabset called "History"
         $versions = $object->allVersions();
         foreach ($versions as $version) {
             // Get a record of this version of the object
             $record = Versioned::get_version($object->ClassName, $object->ID, $version->Version);
             // Make a set of read-only fields for use in assembling the History tabs
             $read_fields = $current_tabs->makeReadonly();
             // Make a form using the relevant fields and load it with data from this record
             $form = new Form($object, "old_version", $read_fields, $object->getCMSActions());
             $form->loadDataFrom($record);
             // Add the version number to each field name so we don't have duplicate field names
             if ($form->fields->dataFields()) {
                 foreach ($form->fields->dataFields() as $field) {
                     $field->Name = $field->Name . "version" . $version->Version;
                 }
             }
             // Generate some heading strings describing this version
             $was_published = $version->WasPublished ? "P" : "D";
             $was_published_full = $version->WasPublished ? "Published" : "Saved as draft";
             $publishedby = Member::get()->byId($version->PublisherID);
             $authoredby = Member::get()->byId($version->AuthorID);
             $publisher_heading = "";
             $author_heading = "";
             if ($publishedby) {
                 $publisher_heading = " by " . $publishedby->getName();
             }
             if ($authoredby) {
                 $author_heading = " (Authored by " . $authoredby->getName() . ")";
             }
             $up_date = new SS_Datetime('update');
             $up_date->setValue($version->LastEdited);
             $nice_date = $up_date->FormatFromSettings();
             $tab_title = $version->Version . " - " . $nice_date . " (" . $was_published . ")";
             $latest_version_notice = "";
             if ($version->isLatestVersion()) {
                 $latest_version_notice = " (latest version)";
             }
             $tab_heading = "<div class='message notice'><p><strong>Viewing version " . $version->Version . $latest_version_notice . ".</strong><br>" . $was_published_full . $publisher_heading . " on " . $nice_date . $author_heading . "</p></div>";
             // Add fields to a tab headed with a description of this version
             $fields->addFieldsToTab('Root.History.' . $tab_title, LiteralField::create('versionHeader' . $version->Version, $tab_heading));
             $fields->addFieldsToTab('Root.History.' . $tab_title, $form->fields);
             // Add notice regarding untracked relationships
             if ($untracked_msg) {
                 $fields->addFieldsToTab('Root.History.' . $tab_title, HeaderField::create('untrackedMessageHeader' . $version->Version, 'Note: the relationships listed below are not tracked by versioning because they involve multiple records', 4));
                 $fields->addFieldsToTab('Root.History.' . $tab_title, LiteralField::create('untrackedMessage' . $version->Version, $untracked_msg));
                 // $fields->addFieldsToTab('Root.History.' . $tab_title, LiteralField::create('untrackedMessage'.$version->Version, $untracked_msg));
             }
         }
     }
     return $fields;
 }
Exemplo n.º 8
0
 /**
  * Compare two version, and return the diff between them.
  * @param string $from The version to compare from.
  * @param string $to The version to compare to.
  * @return DataObject
  */
 function compareVersions($from, $to)
 {
     $fromRecord = Versioned::get_version($this->owner->class, $this->owner->ID, $from);
     $toRecord = Versioned::get_version($this->owner->class, $this->owner->ID, $to);
     $diff = new DataDifferencer($fromRecord, $toRecord);
     return $diff->diffedData();
 }
 /**
  * @return Form
  */
 function CompareVersionsForm($versionID, $otherVersionID)
 {
     if ($versionID > $otherVersionID) {
         $toVersion = $versionID;
         $fromVersion = $otherVersionID;
     } else {
         $toVersion = $otherVersionID;
         $fromVersion = $versionID;
     }
     if (!$toVersion || !$toVersion) {
         return false;
     }
     $id = $this->currentPageID();
     $page = DataObject::get_by_id("SiteTree", $id);
     if ($page && !$page->canView()) {
         return Security::permissionFailure($this);
     }
     $record = $page->compareVersions($fromVersion, $toVersion);
     $fromVersionRecord = Versioned::get_version('SiteTree', $id, $fromVersion);
     $toVersionRecord = Versioned::get_version('SiteTree', $id, $toVersion);
     if (!$fromVersionRecord) {
         user_error("Can't find version {$fromVersion} of page {$id}", E_USER_ERROR);
     }
     if (!$toVersionRecord) {
         user_error("Can't find version {$toVersion} of page {$id}", E_USER_ERROR);
     }
     if ($record) {
         $form = $this->getEditForm($id, null, null, true);
         $form->setActions(new FieldList());
         $form->addExtraClass('compare');
         // Comparison views shouldn't be editable.
         // Its important to convert fields *before* loading data,
         // as the comparison output is HTML and not valid values for the various field types
         $readonlyFields = $form->Fields()->makeReadonly();
         $form->setFields($readonlyFields);
         $form->loadDataFrom($record);
         $form->loadDataFrom(array("ID" => $id, "Version" => $fromVersion));
         foreach ($form->Fields()->dataFields() as $field) {
             $field->dontEscape = true;
         }
         return $form;
     }
 }
 /**
  * Push a content changeset to a syncro node
  * 
  * @param ContentChangeset $changeset
  * @param RemoteSyncroNode $node
  * 
  */
 public function pushChangeset($changeset, $node)
 {
     $cs = $changeset->ChangesetItems();
     $update = array('changes' => array(), 'deletes' => array(), 'rels' => array());
     foreach ($cs as $changesetItem) {
         $record = null;
         // if it's a delete, we create a syncro delete, otherwise get the versioned item
         if ($changesetItem->ChangeType == 'Draft Deleted') {
             // find the syncrodelete record
             $record = DataList::create('SyncroDelete')->filter(array('ContentID' => $changesetItem->OtherContentID))->first();
             $del = array('SYNCRODELETE' => 'DELETE', 'ContentID' => $record->ContentID, 'Type' => $record->Type, 'MasterNode' => SiteConfig::current_site_config()->SystemID, 'Deleted' => $record->Created);
             $update['deletes'][] = $del;
         } else {
             $record = Versioned::get_version($changesetItem->OtherClass, $changesetItem->OtherID, $changesetItem->ContentVersion);
             $syncd = $this->syncroObject($record);
             $syncd['ClassName'] = $record->ClassName;
             if (count($syncd['has_one']) || count($syncd['many_many'])) {
                 $relInfo = new stdClass();
                 $relInfo->SYNCROREL = true;
                 $relInfo->Type = $record->ClassName;
                 $relInfo->ContentID = $record->ContentID;
                 $relInfo->MasterNode = SiteConfig::current_site_config()->SystemID;
                 $relInfo->has_one = $syncd['has_one'];
                 $relInfo->many_many = $syncd['many_many'];
                 $update['rels'][] = $relInfo;
             }
             unset($syncd['has_one']);
             unset($syncd['many_many']);
             $update['changes'][] = $syncd;
         }
     }
     if ($update && $node) {
         $url = $node->NodeURL;
         $service = new RestfulService($url, -1);
         $params = array('changes' => $update['changes'], 'deletes' => $update['deletes'], 'rels' => $update['rels']);
         $headers = array('X-Auth-Token: ' . $node->APIToken, 'Content-Type: application/json');
         $body = json_encode($params);
         $response = $service->request(self::PUSH_URL, 'POST', $body, $headers);
         //, $headers, $curlOptions);
         if ($response && $response->isError()) {
             $body = $response->getBody();
             if ($body) {
                 $this->log->logError($body);
             }
             return array(false, "Deployment failed to {$url}: status {$response->getStatusCode()}");
         }
         $body = $response->getBody();
         if ($body) {
             return array(true, 'Deployment successful');
         }
     }
 }
Exemplo n.º 11
0
 /**
  * Get the product for the item
  * 
  * @return Mixed Product if it exists, otherwise null
  */
 function Product()
 {
     return Versioned::get_version('Product', $this->ProductID, $this->ProductVersion);
 }
Exemplo n.º 12
0
 function compareversions()
 {
     $id = $this->request->param('ID') ? $this->request->param('ID') : $this->request->requestVar('ID');
     $versions = $this->request->requestVar('Versions');
     $version1 = $versions && isset($versions[0]) ? $versions[0] : $this->request->getVar('From');
     $version2 = $versions && isset($versions[1]) ? $versions[1] : $this->request->getVar('To');
     if ($version1 > $version2) {
         $toVersion = $version1;
         $fromVersion = $version2;
     } else {
         $toVersion = $version2;
         $fromVersion = $version1;
     }
     if (!$toVersion || !$toVersion) {
         return false;
     }
     $page = DataObject::get_by_id("SiteTree", $id);
     if ($page && !$page->canView()) {
         return Security::permissionFailure($this);
     }
     $record = $page->compareVersions($fromVersion, $toVersion);
     $fromVersionRecord = Versioned::get_version('SiteTree', $id, $fromVersion);
     $toVersionRecord = Versioned::get_version('SiteTree', $id, $toVersion);
     if (!$fromVersionRecord) {
         user_error("Can't find version {$fromVersion} of page {$id}", E_USER_ERROR);
     }
     if (!$toVersionRecord) {
         user_error("Can't find version {$toVersion} of page {$id}", E_USER_ERROR);
     }
     if ($record) {
         $fromDateNice = $fromVersionRecord->obj('LastEdited')->Ago();
         $toDateNice = $toVersionRecord->obj('LastEdited')->Ago();
         $fromAuthor = DataObject::get_by_id('Member', $fromVersionRecord->AuthorID);
         if (!$fromAuthor) {
             $fromAuthor = new ArrayData(array('Title' => 'Unknown author'));
         }
         $toAuthor = DataObject::get_by_id('Member', $toVersionRecord->AuthorID);
         if (!$toAuthor) {
             $toAuthor = new ArrayData(array('Title' => 'Unknown author'));
         }
         $fields = $record->getCMSFields($this);
         $fields->push(new HiddenField("ID"));
         $fields->push(new HiddenField("Version"));
         $fields->insertBefore(new LiteralField('YouAreComparingHeader', '<p class="message notice">' . sprintf(_t('CMSMain.COMPARINGV', "Comparing versions %s and %s"), "<a href=\"admin/getversion/{$id}/{$fromVersionRecord->Version}\" title=\"{$fromAuthor->Title}\">{$fromVersionRecord->Version}</a> <small>({$fromDateNice})</small>", "<a href=\"admin/getversion/{$id}/{$toVersionRecord->Version}\" title=\"{$toAuthor->Title}\">{$toVersionRecord->Version}</a> <small>({$toDateNice})</small>") . '</p>'), "Root");
         $actions = new FieldSet();
         $form = new Form($this, "EditForm", $fields, $actions);
         $form->loadDataFrom($record);
         $form->loadDataFrom(array("ID" => $id, "Version" => $fromVersion));
         $form->addExtraClass('compare');
         // comparison views shouldn't be editable
         $readonlyFields = $form->Fields()->makeReadonly();
         $form->setFields($readonlyFields);
         foreach ($form->Fields()->dataFields() as $field) {
             $field->dontEscape = true;
         }
         if ($this->isAjax()) {
             return $form->formHtmlContent();
         } else {
             $templateData = $this->customise(array("EditForm" => $form));
             return $templateData->renderWith('LeftAndMain');
         }
     }
 }
 /**
  * HACK: Versioned is BROKEN this method helps in fixing it.
  * Basically, in Versioned, you get a hard-coded error
  * when you retrieve an older version of a DataObject.
  * This method returns null if it does not exist.
  *
  * Idea is from Jeremy: https://github.com/burnbright/silverstripe-shop/blob/master/code/products/FixVersioned.php
  * @param String $class
  * @param Int $id
  * @param Int $version
  * @return DataObject | Null
  */
 public static function get_version($class, $id, $version)
 {
     $oldMode = Versioned::get_reading_mode();
     Versioned::set_reading_mode('');
     $versionedObject = Versioned::get_version($class, $id, $version);
     Versioned::set_reading_mode($oldMode);
     return $versionedObject;
 }
 /**
  * @see Versioned::doRollBackTo
  * @param string $version Either the string 'Live' or a version number
  *
  * @return null
  */
 public function onAfterRollback($version)
 {
     // get the owner data for this version
     if (is_numeric($version)) {
         $page = Versioned::get_version($this->owner->ClassName, $this->owner->ID, $version);
     } else {
         $this->owner->flushCache();
         $baseTable = $this->owner->baseTable();
         $page = Versioned::get_one_by_stage($this->owner->ClassName, $version, "\"{$baseTable}\".\"ID\"={$this->owner->ID}");
     }
     $date = $page->LastEdited;
     $oldMode = Versioned::get_reading_mode();
     // get the current items
     Versioned::set_reading_mode('Stage.Stage');
     $current_items = array();
     foreach ($this->getItemsToPublish() as $field) {
         $current_items[] = $field;
     }
     // Get items in the version that we want by setting reading mode to date of version
     if (is_numeric($version)) {
         Versioned::set_reading_mode('Archive.' . $date);
     } else {
         Versioned::set_reading_mode('Stage.Live');
     }
     $version_items = array();
     $version_ids = array();
     foreach ($this->getItemsToPublish() as $field) {
         $version_items[] = $field;
         $version_ids[] = $field->ClassName . '_' . $field->ID;
     }
     Versioned::set_reading_mode($oldMode);
     // rollback version items
     foreach ($version_items as $field) {
         $fieldVersion = is_numeric($version) ? $field->Version : 'Live';
         if ($field->hasMethod('doDoRollBackTo')) {
             $field->doDoRollBackTo($fieldVersion);
         } else {
             $field->doRollBackTo($fieldVersion);
         }
     }
     // delete items not in version
     foreach ($current_items as $field) {
         if (!in_array($field->ClassName . '_' . $field->ID, $version_ids)) {
             $clone = clone $field;
             if ($clone->hasMethod('doDeleteFromStage')) {
                 $clone->doDeleteFromStage('Stage');
             } else {
                 $clone->deleteFromStage('Stage');
             }
         }
     }
 }
Exemplo n.º 15
0
 /**
  * Compare two version, and return the diff between them.
  * @param string $from The version to compare from.
  * @param string $to The version to compare to.
  * @return DataObject
  */
 function compareVersions($from, $to)
 {
     $fromRecord = Versioned::get_version($this->owner->class, $this->owner->ID, $from);
     $toRecord = Versioned::get_version($this->owner->class, $this->owner->ID, $to);
     $fields = array_keys($fromRecord->getAllFields());
     foreach ($fields as $field) {
         if (in_array($field, array("ID", "Version", "RecordID", "AuthorID", "ParentID"))) {
             continue;
         }
         $fromRecord->{$field} = Diff::compareHTML($fromRecord->{$field}, $toRecord->{$field});
     }
     return $fromRecord;
 }
 /**
  * Retrieve the object this item represents, usually a {@link Variation}.
  * Uses the object version so that the correct object details such as price are
  * retrieved.
  * 
  * @return DataObject 
  */
 function Object()
 {
     return Versioned::get_version($this->ObjectClass, $this->ObjectID, $this->ObjectVersion);
 }
Exemplo n.º 17
0
 public function onAfterWrite()
 {
     // Need to flush cache to avoid outdated versionnumber references
     $this->flushCache();
     $linkedPages = $this->VirtualPages();
     if ($linkedPages) {
         // The only way after a write() call to determine if it was triggered by a writeWithoutVersion(),
         // which we have to pass on to the virtual page writes as well.
         $previous = $this->Version > 1 ? Versioned::get_version($this->class, $this->ID, $this->Version - 1) : null;
         $withoutVersion = $this->getExtensionInstance('Versioned')->_nextWriteWithoutVersion;
         foreach ($linkedPages as $page) {
             $page->copyFrom($page->CopyContentFrom());
             if ($withoutVersion) {
                 $page->writeWithoutVersion();
             } else {
                 $page->write();
             }
         }
     }
     parent::onAfterWrite();
 }
 public function getCMSFields()
 {
     $fields = parent::getCMSFields();
     // Remove defailt item admin
     $fields->removeByName('Items');
     $fields->removeByName('EmailDispatchSent');
     $fields->removeByName('PostageID');
     $fields->removeByName('PaymentID');
     $fields->removeByName('GatewayData');
     // Remove Billing Details
     $fields->removeByName('Address1');
     $fields->removeByName('Address2');
     $fields->removeByName('City');
     $fields->removeByName('PostCode');
     $fields->removeByName('Country');
     // Remove Delivery Details
     $fields->removeByName('DeliveryFirstnames');
     $fields->removeByName('DeliverySurname');
     $fields->removeByName('DeliveryAddress1');
     $fields->removeByName('DeliveryAddress2');
     $fields->removeByName('DeliveryCity');
     $fields->removeByName('DeliveryPostCode');
     $fields->removeByName('DeliveryCountry');
     // Remove default postage fields
     $fields->removeByName('PostageType');
     $fields->removeByName('PostageCost');
     $fields->removeByName('PostageTax');
     $fields->addFieldToTab('Root.Main', ReadonlyField::create('OrderNumber', "#"), 'Status');
     $fields->addFieldToTab('Root.Main', ReadonlyField::create('Created'));
     $fields->addFieldToTab('Root.Main', ReadonlyField::create('LastEdited', 'Last time order was saved'));
     // Structure billing details
     $billing_fields = ToggleCompositeField::create('BillingDetails', 'Billing Details', array(TextField::create('Address1', 'Address 1'), TextField::create('Address2', 'Address 2'), TextField::create('City', 'City'), TextField::create('PostCode', 'Post Code'), TextField::create('Country', 'Country')))->setHeadingLevel(4);
     // Structure delivery details
     $delivery_fields = ToggleCompositeField::create('DeliveryDetails', 'Delivery Details', array(TextField::create('DeliveryFirstnames', 'First Name(s)'), TextField::create('DeliverySurname', 'Surname'), TextField::create('DeliveryAddress1', 'Address 1'), TextField::create('DeliveryAddress2', 'Address 2'), TextField::create('DeliveryCity', 'City'), TextField::create('DeliveryPostCode', 'Post Code'), TextField::create('DeliveryCountry', 'Country')))->setHeadingLevel(4);
     // Postage details
     // Structure billing details
     $postage_fields = ToggleCompositeField::create('Postage', 'Postage Details', array(ReadonlyField::create('PostageType'), ReadonlyField::create('PostageCost'), ReadonlyField::create('PostageTax')))->setHeadingLevel(4);
     $fields->addFieldToTab('Root.Main', $billing_fields);
     $fields->addFieldToTab('Root.Main', $delivery_fields);
     $fields->addFieldToTab('Root.Main', $postage_fields);
     // Add order items and totals
     $fields->addFieldToTab('Root.Items', GridField::create('Items', "Order Items", $this->Items(), GridFieldConfig::create()->addComponents(new GridFieldSortableHeader(), new GridFieldDataColumns())));
     $fields->addFieldToTab("Root.Items", ReadonlyField::create("SubTotal")->setValue($this->getSubTotal()));
     $fields->addFieldToTab("Root.Items", ReadonlyField::create("DiscountAmount")->setValue($this->DiscountAmount));
     $fields->addFieldToTab("Root.Items", ReadonlyField::create("Tax")->setValue($this->getTaxTotal()));
     $fields->addFieldToTab("Root.Items", ReadonlyField::create("Total")->setValue($this->getTotal()));
     $member = Member::currentUser();
     if (Permission::check('ADMIN', 'any', $member)) {
         // Add non-editable payment ID
         $paymentid_field = TextField::create('PaymentID', "Payment gateway ID number")->setReadonly(true)->performReadonlyTransformation();
         $gateway_data = LiteralField::create("FormattedGatewayData", "<strong>Data returned from the payment gateway:</strong><br/><br/>" . str_replace(",", ",<br/>", $this->GatewayData));
         $fields->addFieldToTab('Root.Gateway', $paymentid_field);
         $fields->addFieldToTab("Root.Gateway", $gateway_data);
     }
     if (Permission::check(array('COMMERCE_ORDER_HISTORY', 'ADMIN'), 'any', $member)) {
         // Setup basic history of this order
         $versions = $this->AllVersions();
         $curr_version = $versions->First()->Version;
         $message = "";
         foreach ($versions as $version) {
             $i = $version->Version;
             $name = "History_{$i}";
             if ($i > 1) {
                 $frm = Versioned::get_version($this->class, $this->ID, $i - 1);
                 $to = Versioned::get_version($this->class, $this->ID, $i);
                 $diff = new DataDifferencer($frm, $to);
                 if ($version->Author()) {
                     $message = "<p>{$version->Author()->FirstName} ({$version->LastEdited})</p>";
                 } else {
                     $message = "<p>Unknown ({$version->LastEdited})</p>";
                 }
                 if ($diff->ChangedFields()->exists()) {
                     $message .= "<ul>";
                     // Now loop through all changed fields and track as message
                     foreach ($diff->ChangedFields() as $change) {
                         if ($change->Name != "LastEdited") {
                             $message .= "<li>{$change->Title}: {$change->Diff}</li>";
                         }
                     }
                     $message .= "</ul>";
                 }
             }
             $fields->addFieldToTab("Root.History", LiteralField::create($name, "<div class=\"field\">{$message}</div>"));
         }
     }
     $this->extend("updateCMSFields", $fields);
     return $fields;
 }
 public function testLazyLoadedFieldsOnVersionedRecords()
 {
     // Save another record, sanity check that we're getting the right one
     $obj2 = new VersionedTest_Subclass();
     $obj2->Name = "test2";
     $obj2->ExtraField = "foo2";
     $obj2->write();
     // Save the actual inspected record
     $obj1 = new VersionedTest_Subclass();
     $obj1->Name = "test";
     $obj1->ExtraField = "foo";
     $obj1->write();
     $version1 = $obj1->Version;
     $obj1->Name = "test2";
     $obj1->ExtraField = "baz";
     $obj1->write();
     $version2 = $obj1->Version;
     $reloaded = Versioned::get_version('VersionedTest_Subclass', $obj1->ID, $version1);
     $this->assertEquals($reloaded->Name, 'test');
     $this->assertEquals($reloaded->ExtraField, 'foo');
     $reloaded = Versioned::get_version('VersionedTest_Subclass', $obj1->ID, $version2);
     $this->assertEquals($reloaded->Name, 'test2');
     $this->assertEquals($reloaded->ExtraField, 'baz');
     $reloaded = Versioned::get_latest_version('VersionedTest_Subclass', $obj1->ID);
     $this->assertEquals($reloaded->Version, $version2);
     $this->assertEquals($reloaded->Name, 'test2');
     $this->assertEquals($reloaded->ExtraField, 'baz');
     $allVersions = Versioned::get_all_versions('VersionedTest_Subclass', $obj1->ID);
     $this->assertEquals(2, $allVersions->Count());
     $this->assertEquals($allVersions->First()->Version, $version1);
     $this->assertEquals($allVersions->First()->Name, 'test');
     $this->assertEquals($allVersions->First()->ExtraField, 'foo');
     $this->assertEquals($allVersions->Last()->Version, $version2);
     $this->assertEquals($allVersions->Last()->Name, 'test2');
     $this->assertEquals($allVersions->Last()->ExtraField, 'baz');
     $obj1->delete();
 }
Exemplo n.º 20
0
 /**
  * Overloaded relationship, for getting versioned variations
  * @param boolean $current
  */
 public function ProductVariation($forcecurrent = false)
 {
     if ($this->ProductVariationID && $this->ProductVariationVersion && !$forcecurrent) {
         return Versioned::get_version('ProductVariation', $this->ProductVariationID, $this->ProductVariationVersion);
     } elseif ($this->ProductVariationID && ($product = DataObject::get_by_id('ProductVariation', $this->ProductVariationID))) {
         return $product;
     }
     return false;
 }
Exemplo n.º 21
0
	function testActionsViewingOldVersion() {
		$p = new Page();
		$p->Content = 'test page first version';
		$p->write();
		$p->Content = 'new content';
		$p->write();

		// Looking at the old version, the ability to rollback to that version is available
		$version = DB::query('SELECT "Version" FROM "SiteTree_versions" WHERE "Content" = \'test page first version\'')->value();
		$old = Versioned::get_version('Page', $p->ID, $version);
		$actions = $old->getCMSActions();
		$this->assertNull($actions->dataFieldByName('action_save'));
		$this->assertNull($actions->dataFieldByName('action_publish'));
		$this->assertNull($actions->dataFieldByName('action_unpublish'));
		$this->assertNull($actions->dataFieldByName('action_delete'));
		$this->assertNotNull($actions->dataFieldByName('action_email'));
		$this->assertNotNull($actions->dataFieldByName('action_rollback'));
	}
 public function ItemEditForm()
 {
     Requirements::javascript("orders/javascript/entwine.orders.js");
     $form = parent::ItemEditForm();
     $fields = $form->Fields();
     $actions = $form->Actions();
     $record = $this->record;
     $member = Member::currentUser();
     $can_view = $this->record->canView();
     $can_edit = $this->record->canEdit();
     $can_change_status = $this->record->canChangeStatus();
     $can_delete = $this->record->canDelete();
     $can_create = $this->record->canCreate();
     // First remove the delete button
     $actions->removeByName("action_doDelete");
     // Deal with Estimate objects
     if ($record->ClassName == "Estimate") {
         if ($record->ID && $record->AccessKey) {
             $frontend_url = Controller::join_links(Director::absoluteBaseUrl(), "OrdersFront", "quote", $record->ID, $record->AccessKey);
             $html = '<a href="' . $frontend_url . '" ';
             $html .= 'target="_blank" ';
             $html .= 'class="action ss-ui-button ui-button ui-corner-all open-external" ';
             $html .= '>' . _t('Orders.ViewQuote', 'View Quote') . '</a>';
             $actions->insertAfter(LiteralField::create('openQuote', $html), "action_doSave");
         }
         if ($record->ID && $can_edit) {
             $actions->insertAfter(FormAction::create('doConvert', _t('Orders.ConvertToOrder', 'Convert To Order'))->setUseButtonTag(true), "action_doSave");
         }
     }
     // Deal with Order objects
     if ($record->ClassName == "Order") {
         // Set our status field as a dropdown (has to be here to
         // ignore canedit)
         // Allow users to change status (as long as they have permission)
         if ($can_edit || $can_change_status) {
             $status_field = DropdownField::create('Status', null, $record->config()->statuses);
             // Set default status if we can
             if (!$record->Status && !$record->config()->default_status) {
                 $status_field->setValue($record->config()->default_status);
             } else {
                 $status_field->setValue($record->Status);
             }
             $fields->replaceField("Status", $status_field);
         }
         // Setup order history
         if (Permission::check(array('COMMERCE_ORDER_HISTORY', 'ADMIN'), 'any', $member)) {
             $versions = $record->AllVersions();
             $first_version = $versions->First();
             $curr_version = $first_version ? $versions->First() : null;
             $message = "";
             foreach ($versions as $version) {
                 $i = $version->Version;
                 $name = "History_{$i}";
                 if ($i > 0) {
                     $frm = Versioned::get_version($record->class, $record->ID, $i - 1);
                     $to = Versioned::get_version($record->class, $record->ID, $i);
                     $diff = new DataDifferencer($frm, $to);
                     if ($version->Author()) {
                         $message = "<p>{$version->Author()->FirstName} ({$version->LastEdited})</p>";
                     } else {
                         $message = "<p>Unknown ({$version->LastEdited})</p>";
                     }
                     if ($diff->ChangedFields()->exists()) {
                         $message .= "<ul>";
                         // Now loop through all changed fields and track as message
                         foreach ($diff->ChangedFields() as $change) {
                             if ($change->Name != "LastEdited") {
                                 $message .= "<li>{$change->Title}: {$change->Diff}</li>";
                             }
                         }
                         $message .= "</ul>";
                     }
                     $fields->addFieldToTab("Root.History", LiteralField::create($name, "<div class=\"field\">{$message}</div>"));
                 }
             }
         }
         // Is user cannot edit, but can change status, add change
         // status button
         if ($record->ID && !$can_edit && $can_change_status) {
             $actions->push(FormAction::create('doChangeStatus', _t('Orders.Save', 'Save'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept'));
         }
         if ($record->ID && $record->AccessKey) {
             $frontend_url = Controller::join_links(Director::absoluteBaseUrl(), "OrdersFront", "invoice", $record->ID, $record->AccessKey);
             $html = '<a href="' . $frontend_url . '" ';
             $html .= 'target="_blank" ';
             $html .= 'class="action ss-ui-button ui-button ui-corner-all open-external" ';
             $html .= '>' . _t('Orders.ViewInvoice', 'View Invoice') . '</a>';
             $link_field = LiteralField::create('openQuote', $html);
             if ($actions->find("Name", "action_doSave")) {
                 $actions->insertAfter($link_field, "action_doSave");
             }
             if ($actions->find("Name", "action_doChangeStatus")) {
                 $actions->insertAfter($link_field, "action_doChangeStatus");
             }
         }
     }
     // Add a duplicate button, either after the save button or
     // the change status "save" button.
     if ($record->ID) {
         $duplicate_button = FormAction::create('doDuplicate', _t('Orders.Duplicate', 'Duplicate'))->setUseButtonTag(true);
         if ($actions->find("Name", "action_doSave")) {
             $actions->insertAfter($duplicate_button, "action_doSave");
         }
         if ($actions->find("Name", "action_doChangeStatus")) {
             $actions->insertAfter($duplicate_button, "action_doChangeStatus");
         }
     }
     // Finally, if allowed, re-add the delete button (so it is last)
     if ($record->ID && $can_delete) {
         $actions->push(FormAction::create('doDelete', _t('GridFieldDetailForm.Delete', 'Delete'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-destructive action-delete'));
     }
     // Set our custom template
     $form->setTemplate("OrdersItemEditForm");
     $this->extend("updateItemEditForm", $form);
     return $form;
 }
Exemplo n.º 23
0
 function compareversions()
 {
     $id = (int) $this->urlParams['ID'];
     $version1 = (int) $_REQUEST['From'];
     $version2 = (int) $_REQUEST['To'];
     if ($version1 > $version2) {
         $toVersion = $version1;
         $fromVersion = $version2;
     } else {
         $toVersion = $version2;
         $fromVersion = $version1;
     }
     $page = DataObject::get_by_id("SiteTree", $id);
     if ($page && !$page->canView()) {
         return Security::permissionFailure($this);
     }
     $record = $page->compareVersions($fromVersion, $toVersion);
     $fromVersionRecord = Versioned::get_version('SiteTree', $id, $fromVersion);
     $toVersionRecord = Versioned::get_version('SiteTree', $id, $toVersion);
     if (!$fromVersionRecord) {
         user_error("Can't find version {$fromVersion} of page {$id}", E_USER_ERROR);
     }
     if (!$toVersionRecord) {
         user_error("Can't find version {$toVersion} of page {$id}", E_USER_ERROR);
     }
     if ($record) {
         $fromDateNice = $fromVersionRecord->obj('LastEdited')->Ago();
         $toDateNice = $toVersionRecord->obj('LastEdited')->Ago();
         $fromAuthor = DataObject::get_by_id('Member', $fromVersionRecord->AuthorID);
         if (!$fromAuthor) {
             $fromAuthor = new ArrayData(array('Title' => 'Unknown author'));
         }
         $toAuthor = DataObject::get_by_id('Member', $toVersionRecord->AuthorID);
         if (!$toAuthor) {
             $toAuthor = new ArrayData(array('Title' => 'Unknown author'));
         }
         $fields = $record->getCMSFields($this);
         $fields->push(new HiddenField("ID"));
         $fields->push(new HiddenField("Version"));
         $fields->insertBefore(new LiteralField('YouAreComparingHeader', '<p class="message notice">' . sprintf(_t('CMSMain.COMPARINGV', "Comparing versions %s and %s"), "<a href=\"admin/getversion/{$id}/{$fromVersionRecord->Version}\" title=\"{$fromAuthor->Title}\">{$fromVersionRecord->Version}</a> <small>({$fromDateNice})</small>", "<a href=\"admin/getversion/{$id}/{$toVersionRecord->Version}\" title=\"{$toAuthor->Title}\">{$toVersionRecord->Version}</a> <small>({$toDateNice})</small>") . '</p>'), "Root");
         $actions = new FieldSet();
         $form = new Form($this, "EditForm", $fields, $actions);
         $form->loadDataFrom($record);
         $form->loadDataFrom(array("ID" => $id, "Version" => $fromVersion));
         // comparison views shouldn't be editable
         $readonlyFields = $form->Fields()->makeReadonly();
         $form->setFields($readonlyFields);
         foreach ($form->Fields()->dataFields() as $field) {
             $field->dontEscape = true;
         }
         return $this->sendFormToBrowser(array("EditForm" => $form));
     }
 }
Exemplo n.º 24
0
 /**
  * Overloaded Product accessor method.
  *
  * Overloaded from the default has_one accessor to
  * retrieve a product by it's version, this is extremely
  * useful because we can set in stone the version of
  * a product at the time when the user adds the item to
  * their cart, so if the CMS admin changes the price, it
  * remains the same for this order.
  *
  * @param boolean $current If set to TRUE, returns the latest published version of the Product,
  * 								If set to FALSE, returns the set version number of the Product
  * 						 		(instead of the latest published version)
  * @return Product object
  */
 public function Product($current = false)
 {
     if ($current) {
         return DataObject::get_by_id('Product', $this->_productID);
     } elseif ($this->_productID && $this->_productVersion) {
         return Versioned::get_version('Product', $this->_productID, $this->_productVersion);
     }
 }
Exemplo n.º 25
0
 public function testGetVersionWhenClassnameChanged()
 {
     $obj = new VersionedTest_DataObject();
     $obj->Name = "test";
     $obj->write();
     $obj->Name = "test2";
     $obj->ClassName = "VersionedTest_Subclass";
     $obj->write();
     $subclassVersion = $obj->Version;
     $obj->Name = "test3";
     $obj->ClassName = "VersionedTest_DataObject";
     $obj->write();
     // We should be able to pass the subclass and still get the correct class back
     $obj2 = Versioned::get_version("VersionedTest_Subclass", $obj->ID, $subclassVersion);
     $this->assertInstanceOf("VersionedTest_Subclass", $obj2);
     $this->assertEquals("test2", $obj2->Name);
     $obj3 = Versioned::get_latest_version("VersionedTest_Subclass", $obj->ID);
     $this->assertEquals("test3", $obj3->Name);
     $this->assertInstanceOf("VersionedTest_DataObject", $obj3);
 }
Exemplo n.º 26
0
 function getversion()
 {
     $id = $this->urlParams['ID'];
     $version = str_replace('&ajax=1', '', $this->urlParams['OtherID']);
     $record = Versioned::get_version("SiteTree", $id, $version);
     if ($record) {
         $fields = $record->getCMSFields($this);
         $fields->removeByName("Status");
         $fields->push(new HiddenField("ID"));
         $fields->push(new HiddenField("Version"));
         $fields->push(new HeaderField(sprintf(_t('CMSMain.VIEWING', "You are viewing version #%d, created %s"), $version, $record->obj('LastEdited')->Ago())));
         $actions = new FieldSet(new FormAction("email", _t('CMSMain.EMAIL', "Email")), new FormAction("print", _t('CMSMain.PRINT', "Print")), new FormAction("rollback", _t('CMSMain.ROLLBACK', "Roll back to this version")));
         // encode the message to appear in the body of the email
         $archiveURL = Director::absoluteBaseURL() . $record->URLSegment . '?archiveDate=' . $record->obj('LastEdited')->URLDatetime();
         $archiveEmailMessage = urlencode($this->customise(array('ArchiveDate' => $record->obj('LastEdited'), 'ArchiveURL' => $archiveURL))->renderWith('ViewArchivedEmail'));
         $archiveEmailMessage = preg_replace('/\\+/', '%20', $archiveEmailMessage);
         $fields->push(new HiddenField('ArchiveEmailMessage', '', $archiveEmailMessage));
         $fields->push(new HiddenField('ArchiveEmailSubject', '', preg_replace('/\\+/', '%20', urlencode('Archived version of ' . $record->Title))));
         $fields->push(new HiddenField('ArchiveURL', '', $archiveURL));
         $form = new Form($this, "EditForm", $fields, $actions);
         $form->loadDataFrom($record);
         $form->loadDataFrom(array("ID" => $id, "Version" => $version));
         $form->makeReadonly();
         $templateData = $this->customise(array("EditForm" => $form));
         SSViewer::setOption('rewriteHashlinks', false);
         $result = $templateData->renderWith($this->class . '_right');
         $parts = split('</?form[^>]*>', $result);
         return $parts[sizeof($parts) - 2];
     }
 }
 /**
  * Get a database record to be managed by the CMS.
  *
  * @param int $id Record ID
  * @param int $versionID optional Version id of the given record
  */
 public function getRecord($id, $versionID = null)
 {
     $treeClass = $this->stat('tree_class');
     if ($id instanceof $treeClass) {
         return $id;
     } else {
         if ($id && is_numeric($id)) {
             if ($this->request->getVar('Version')) {
                 $versionID = (int) $this->request->getVar('Version');
             }
             if ($versionID) {
                 $record = Versioned::get_version($treeClass, $id, $versionID);
             } else {
                 $record = DataObject::get_one($treeClass, "\"{$treeClass}\".\"ID\" = {$id}");
             }
             // Then, try getting a record from the live site
             if (!$record) {
                 // $record = Versioned::get_one_by_stage($treeClass, "Live", "\"$treeClass\".\"ID\" = $id");
                 Versioned::reading_stage('Live');
                 singleton($treeClass)->flushCache();
                 $record = DataObject::get_one($treeClass, "\"{$treeClass}\".\"ID\" = {$id}");
                 if ($record) {
                     Versioned::set_reading_mode('');
                 }
             }
             // Then, try getting a deleted record
             if (!$record) {
                 $record = Versioned::get_latest_version($treeClass, $id);
             }
             // Don't open a page from a different locale
             /** The record's Locale is saved in database in 2.4, and not related with Session,
              *  we should not check their locale matches the Translatable::get_current_locale,
              *    here as long as we all the HTTPRequest is init with right locale.
              *    This bit breaks the all FileIFrameField functions if the field is used in CMS
              *  and its relevent ajax calles, like loading the tree dropdown for TreeSelectorField.
              */
             /* if($record && Object::has_extension('SiteTree', 'Translatable') && $record->Locale && $record->Locale != Translatable::get_current_locale()) {
             				$record = null;
             			}*/
             return $record;
         } else {
             if (substr($id, 0, 3) == 'new') {
                 return $this->getNewItem($id);
             }
         }
     }
 }
 public function dataObj()
 {
     if (is_numeric($this->itemID) && is_numeric($this->versionID)) {
         return Versioned::get_version(ClassInfo::baseDataClass(Object::getCustomClass($this->ctf->sourceClass())), $this->itemID, $this->versionID);
     }
 }