/**
  * Modified version of the SiteTree publish method.
  *
  * @return <type>
  */
 public function doPublish()
 {
     if (!$this->owner->canPublish()) {
         return false;
     }
     $class = $this->owner->class;
     $ownerId = $this->owner->ID;
     $dataClasses = ClassInfo::dataClassesFor($class);
     $dataClasses = array_values($dataClasses);
     $class = $dataClasses[count($dataClasses) - 1];
     $original = Versioned::get_one_by_stage("{$class}", "Live", "\"{$class}\".\"ID\" = {$ownerId}");
     if (!$original) {
         $original = new $class();
     }
     $this->owner->invokeWithExtensions('onBeforePublish', $original);
     // Handle activities undertaken by decorators
     $this->owner->Status = "Published";
     //$this->PublishedByID = Member::currentUser()->ID;
     $this->owner->write();
     $this->owner->publish("Stage", "Live");
     if ($this->owner->hasField('Sort')) {
         // find the table that actually defines the sortable field
         $class = get_class($this->owner);
         if ($this->owner->hasMethod('findClassDefiningSortField')) {
             $class = $this->owner->findClassDefiningSortField();
         }
         DB::query("UPDATE \"{$class}_Live\"\n\t\t\t\tSET \"Sort\" = (SELECT \"{$class}\".\"Sort\" FROM \"{$class}\" WHERE \"{$class}_Live\".\"ID\" = \"{$class}\".\"ID\")");
     }
     // Handle activities undertaken by decorators
     $this->owner->invokeWithExtensions('onAfterPublish', $original);
     return true;
 }
 /**
  * @param FieldSet $actions
  * @parma SiteTree $page
  */
 public static function update_cms_actions(&$actions, $page)
 {
     $openRequest = $page->OpenWorkflowRequest();
     // if user doesn't have publish rights
     if (!$page->canPublish() || $openRequest) {
         // authors shouldn't be able to revert, as this republishes the page.
         // they should rather change the page and re-request publication
         $actions->removeByName('action_revert');
     }
     // Remove the one click publish if they are not an admin/workflow admin.
     if (self::$force_publishers_to_use_workflow && !Permission::checkMember(Member::currentUser(), 'IS_WORKFLOW_ADMIN')) {
         $actions->removeByName('action_publish');
     }
     // Remove the save & publish button if you don't have edit rights
     if (!$page->canEdit()) {
         $actions->removeByName('action_publish');
     }
     $liveVersion = Versioned::get_one_by_stage('SiteTree', 'Live', "\"SiteTree_Live\".\"ID\" = {$page->ID}");
     if ($liveVersion && $liveVersion->ExpiryDate != null && $liveVersion->ExpiryDate != '0000-00-00 00:00:00') {
         if ($page->canApprove()) {
             $actions->push(new FormAction('cms_cancelexpiry', _t('WorkflowPublicationRequest.BUTTONCANCELEXPIRY', 'Cancel expiry')));
         }
     }
     // Optional method
     $isPublishable = $page->hasMethod('isPublishable') ? $page->isPublishable() : true;
     if (!$openRequest && $page->canEdit() && $isPublishable && $page->stagesDiffer('Stage', 'Live') && ($page->Version > 1 || $page->Title != "New Page") && !$page->IsDeletedFromStage && (!$page->canPublish() || self::$publisher_can_create_wf_requests)) {
         $actions->push($requestPublicationAction = new FormAction('cms_requestpublication', _t('SiteTreeCMSWorkflow.BUTTONREQUESTPUBLICATION', 'Request Publication')));
         // don't allow creation of a second request by another author
         if (!self::can_create(null, $page)) {
             $actions->makeFieldReadonly($requestPublicationAction->Name());
         }
     }
 }
 function ItemEditForm()
 {
     $form = parent::ItemEditForm();
     $actions = $form->Actions();
     $majorActions = CompositeField::create()->setName('MajorActions')->setTag('fieldset')->addExtraClass('ss-ui-buttonset');
     $rootTabSet = new TabSet('ActionMenus');
     $moreOptions = new Tab('MoreOptions', _t('SiteTree.MoreOptions', 'More options', 'Expands a view for more buttons'));
     $rootTabSet->push($moreOptions);
     $rootTabSet->addExtraClass('ss-ui-action-tabset action-menus');
     // Render page information into the "more-options" drop-up, on the top.
     $baseClass = ClassInfo::baseDataClass($this->record->class);
     $live = Versioned::get_one_by_stage($this->record->class, 'Live', "\"{$baseClass}\".\"ID\"='{$this->record->ID}'");
     $existsOnLive = $this->record->getExistsOnLive();
     $published = $this->record->isPublished();
     $moreOptions->push(new LiteralField('Information', $this->record->customise(array('Live' => $live, 'ExistsOnLive' => $existsOnLive))->renderWith('SiteTree_Information')));
     $actions->removeByName('action_doSave');
     $actions->removeByName('action_doDelete');
     if ($this->record->canEdit()) {
         if ($this->record->IsDeletedFromStage) {
             if ($existsOnLive) {
                 $majorActions->push(FormAction::create('revert', _t('CMSMain.RESTORE', 'Restore')));
                 if ($this->record->canDelete() && $this->record->canDeleteFromLive()) {
                     $majorActions->push(FormAction::create('unpublish', _t('CMSMain.DELETEFP', 'Delete'))->addExtraClass('ss-ui-action-destructive'));
                 }
             } else {
                 if (!$this->record->isNew()) {
                     $majorActions->push(FormAction::create('restore', _t('CMSMain.RESTORE', 'Restore'))->setAttribute('data-icon', 'decline'));
                 } else {
                     $majorActions->push(FormAction::create('save', _t('SiteTree.BUTTONSAVED', 'Saved'))->addExtraClass('ss-ui-alternate ss-ui-action-constructive')->setAttribute('data-icon', 'accept')->setAttribute('data-icon-alternate', 'addpage')->setAttribute('data-text-alternate', _t('CMSMain.SAVEDRAFT', 'Save draft'))->setUseButtonTag(true));
                     $majorActions->push(FormAction::create('publish', _t('SiteTree.BUTTONPUBLISHED', 'Published'))->addExtraClass('ss-ui-alternate ss-ui-action-constructive')->setAttribute('data-icon', 'accept')->setAttribute('data-icon-alternate', 'disk')->setAttribute('data-text-alternate', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & publish'))->setUseButtonTag(true));
                 }
             }
         } else {
             if ($this->record->canDelete() && !$published) {
                 $moreOptions->push(FormAction::create('delete', _t('SiteTree.BUTTONDELETE', 'Delete draft'))->addExtraClass('ss-ui-action-destructive')->setUseButtonTag(true));
             }
             $majorActions->push(FormAction::create('save', _t('SiteTree.BUTTONSAVED', 'Saved'))->setAttribute('data-icon', 'accept')->setAttribute('data-icon-alternate', 'addpage')->setAttribute('data-text-alternate', _t('CMSMain.SAVEDRAFT', 'Save draft'))->setUseButtonTag(true));
         }
     }
     $publish = FormAction::create('publish', $published ? _t('SiteTree.BUTTONPUBLISHED', 'Published') : _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & publish'))->setAttribute('data-icon', 'accept')->setAttribute('data-icon-alternate', 'disk')->setAttribute('data-text-alternate', _t('SiteTree.BUTTONSAVEPUBLISH', 'Save & publish'))->setUseButtonTag(true);
     if (!$published || $this->record->stagesDiffer('Stage', 'Live') && $published) {
         $publish->addExtraClass('ss-ui-alternate');
     }
     if ($this->record->canPublish() && !$this->record->IsDeletedFromStage) {
         $majorActions->push($publish);
     }
     if ($published && $this->record->canPublish() && !$this->record->IsDeletedFromStage && $this->record->canDeleteFromLive()) {
         $moreOptions->push(FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete')->addExtraClass('ss-ui-action-destructive')->setUseButtonTag(true));
     }
     if ($this->record->stagesDiffer('Stage', 'Live') && !$this->record->IsDeletedFromStage && $this->record->isPublished() && $this->record->canEdit()) {
         $moreOptions->push(FormAction::create('rollback', _t('SiteTree.BUTTONCANCELDRAFT', 'Cancel draft changes'))->setDescription(_t('SiteTree.BUTTONCANCELDRAFTDESC', 'Delete your draft and revert to the currently published page'))->setUseButtonTag(true));
     }
     $actions->push($majorActions);
     $actions->push($rootTabSet);
     if ($this->record->hasMethod('getCMSValidator')) {
         $form->setValidator($this->record->getCMSValidator());
     }
     return $form;
 }
Exemplo n.º 4
0
 /**
  * To process this job, we need to get the next page whose ID is the next greater than the last
  * processed. This way we don't need to remember a bunch of data about what we've processed
  */
 public function process()
 {
     if (ClassInfo::exists('Subsite')) {
         Subsite::disable_subsite_filter();
     }
     $class = $this->reindexType;
     $pages = $class::get();
     $pages = $pages->filter(array('ID:GreaterThan' => $this->lastIndexedID));
     $pages = $pages->limit(Config::inst()->get(__CLASS__, 'at_a_time'));
     $pages = $pages->sort('ID ASC');
     if (ClassInfo::exists('Subsite')) {
         Subsite::$disable_subsite_filter = false;
     }
     if (!$pages || !$pages->count()) {
         $this->isComplete = true;
         return;
     }
     $mode = Versioned::get_reading_mode();
     Versioned::reading_stage('Stage');
     // index away
     $service = singleton('SolrSearchService');
     $live = array();
     $stage = array();
     $all = array();
     foreach ($pages as $page) {
         // Make sure the current page is not orphaned.
         if ($page->ParentID > 0) {
             $parent = $page->getParent();
             if (is_null($parent) || $parent === false) {
                 continue;
             }
         }
         // Appropriately index the current page, taking versioning into account.
         if ($page->hasExtension('Versioned')) {
             $stage[] = $page;
             $base = $page->baseTable();
             $idField = '"' . $base . '_Live"."ID"';
             $livePage = Versioned::get_one_by_stage($page->ClassName, 'Live', $idField . ' = ' . $page->ID);
             if ($livePage) {
                 $live[] = $livePage;
             }
         } else {
             $all[] = $page;
         }
         $this->lastIndexedID = $page->ID;
     }
     if (count($all)) {
         $service->indexMultiple($all);
     }
     if (count($stage)) {
         $service->indexMultiple($stage, 'Stage');
     }
     if (count($live)) {
         $service->indexMultiple($live, 'Live');
     }
     Versioned::set_reading_mode($mode);
     $this->lastIndexedID = $page->ID;
     $this->currentStep += $pages->count();
 }
 /**
  * Test version support. If an object has versioned then both the live and
  * staging tables should be updated. Other live records should be removed
  * as well.
  */
 public function testVersionedObjects()
 {
     $versioned = $this->objFromFixture('PopulateFactoryTest_TestVersionedObject', 'objV1');
     $versioned->publish('Stage', 'Live');
     $obj = $this->factory->createObject('PopulateFactoryTest_TestVersionedObject', 'test', array('Content' => 'Updated Version Foo', 'PopulateMergeWhen' => "Title = 'Version Foo'"));
     $this->assertEquals($versioned->ID, $obj->ID);
     $this->assertEquals('Updated Version Foo', $obj->Content);
     $check = Versioned::get_one_by_stage('PopulateFactoryTest_TestVersionedObject', 'Live', "Title = 'Version Foo'");
     $this->assertEquals('Updated Version Foo', $check->Content);
 }
 public function testFileDelete()
 {
     \Versioned::reading_stage('Stage');
     /** @var AssetControlExtensionTest_VersionedObject $object1 */
     $object1 = AssetControlExtensionTest_VersionedObject::get()->filter('Title', 'My object')->first();
     /** @var AssetControlExtensionTest_Object $object2 */
     $object2 = AssetControlExtensionTest_Object::get()->filter('Title', 'Unversioned')->first();
     /** @var AssetControlExtensionTest_ArchivedObject $object3 */
     $object3 = AssetControlExtensionTest_ArchivedObject::get()->filter('Title', 'Archived')->first();
     $this->assertTrue($object1->Download->exists());
     $this->assertTrue($object1->Header->exists());
     $this->assertTrue($object2->Image->exists());
     $this->assertTrue($object3->Header->exists());
     $this->assertEquals(AssetStore::VISIBILITY_PUBLIC, $object1->Download->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PUBLIC, $object1->Header->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PUBLIC, $object2->Image->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PUBLIC, $object3->Header->getVisibility());
     // Check live stage for versioned objects
     $object1Live = Versioned::get_one_by_stage('AssetControlExtensionTest_VersionedObject', 'Live', array('"ID"' => $object1->ID));
     $object3Live = Versioned::get_one_by_stage('AssetControlExtensionTest_ArchivedObject', 'Live', array('"ID"' => $object3->ID));
     $this->assertTrue($object1Live->Download->exists());
     $this->assertTrue($object1Live->Header->exists());
     $this->assertTrue($object3Live->Header->exists());
     $this->assertEquals(AssetStore::VISIBILITY_PUBLIC, $object1Live->Download->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PUBLIC, $object1Live->Header->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PUBLIC, $object3Live->Header->getVisibility());
     // Delete live records; Should cause versioned records to be protected
     $object1Live->deleteFromStage('Live');
     $object3Live->deleteFromStage('Live');
     $this->assertTrue($object1->Download->exists());
     $this->assertTrue($object1->Header->exists());
     $this->assertTrue($object3->Header->exists());
     $this->assertTrue($object1Live->Download->exists());
     $this->assertTrue($object1Live->Header->exists());
     $this->assertTrue($object3Live->Header->exists());
     $this->assertEquals(AssetStore::VISIBILITY_PROTECTED, $object1->Download->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PROTECTED, $object1->Header->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PROTECTED, $object3->Header->getVisibility());
     // Delete draft record; Should remove all records
     // Archived assets only should remain
     $object1->delete();
     $object2->delete();
     $object3->delete();
     $this->assertFalse($object1->Download->exists());
     $this->assertFalse($object1->Header->exists());
     $this->assertFalse($object2->Image->exists());
     $this->assertTrue($object3->Header->exists());
     $this->assertFalse($object1Live->Download->exists());
     $this->assertFalse($object1Live->Header->exists());
     $this->assertTrue($object3Live->Header->exists());
     $this->assertNull($object1->Download->getVisibility());
     $this->assertNull($object1->Header->getVisibility());
     $this->assertNull($object2->Image->getVisibility());
     $this->assertEquals(AssetStore::VISIBILITY_PROTECTED, $object3->Header->getVisibility());
 }
 function testUnpublishing()
 {
     $id = $this->form->ID;
     $this->form->Fields()->removeAll();
     $this->form->Fields()->add(new EditableFormField());
     $this->form->doUnPublish();
     $live = Versioned::get_one_by_stage("UserDefinedForm", "Live", "\"UserDefinedForm_Live\".\"ID\" = {$id}");
     $stage = Versioned::get_one_by_stage("UserDefinedForm", "Stage", "\"UserDefinedForm\".\"ID\" = {$id}");
     $this->assertEquals($live, false);
     $this->assertEquals($stage->Fields()->Count(), 1);
 }
 function testDeletedPagesFilter()
 {
     $deletedPage = $this->objFromFixture('Page', 'page2');
     $deletedPage->publish('Stage', 'Live');
     $deletedPageID = $deletedPage->ID;
     $deletedPage->delete();
     $deletedPage = Versioned::get_one_by_stage('SiteTree', 'Live', sprintf('"SiteTree_Live"."ID" = %d', $deletedPageID));
     $f = new CMSSiteTreeFilter_DeletedPages();
     $results = $f->pagesIncluded();
     $this->assertTrue($f->isPageIncluded($deletedPage));
 }
 function onBeforeDelete()
 {
     // check if Page still exists in live mode
     $className = $this->ClassName;
     $livePage = Versioned::get_one_by_stage($className, "Live", "\"{$className}_Live\".\"ID\" = {$this->ID}");
     // check if Page still exists in stage mode
     $stagePage = Versioned::get_one_by_stage($className, "Stage", "\"{$className}\".\"ID\" = {$this->ID}");
     // if Page only exists in Live OR Stage mode -> Page will be deleted completely
     if (!($livePage && $stagePage)) {
         // delete existing Albums
         $this->Albums()->removeAll();
     }
     parent::onBeforeDelete();
 }
 /**
  * Migrate a versioned field in all stages
  *
  * @param EditableFormField $field
  */
 protected function upgradeField(EditableFormField $field)
 {
     $this->log("Upgrading formfield ID = " . $field->ID);
     // Check versions this field exists on
     $filter = sprintf('"EditableFormField"."ID" = \'%d\' AND "Migrated" = 0', $field->ID);
     $stageField = Versioned::get_one_by_stage('EditableFormField', 'Stage', $filter);
     $liveField = Versioned::get_one_by_stage('EditableFormField', 'Live', $filter);
     if ($stageField) {
         $this->upgradeFieldInStage($stageField, 'Stage');
     }
     if ($liveField) {
         $this->upgradeFieldInStage($liveField, 'Live');
     }
 }
	public function doPublish() {
		if ($this->owner->hasMethod('canPublish') &&
				!$this->owner->canPublish())
			return false;
		
		$original = Versioned::get_one_by_stage($this->owner->ClassName, 'Live',
			"\"{$this->owner->ClassName}\".\"ID\" = {$this->owner->ID}");
		$original = $original? $original: new $this->owner->ClassName;
		$this->owner->invokeWithExtensions('onBeforePublish', $original);
		$this->owner->publish('Stage', 'Live');
		$this->owner->invokeWithExtensions('onAfterPublish', $original);
		
		return true;
	}
Exemplo n.º 12
0
 function testRollbackTo()
 {
     $page1 = $this->objFromFixture('Page', 'page1');
     $page1->Content = 'orig';
     $page1->write();
     $page1->publish('Stage', 'Live');
     $origVersion = $page1->Version;
     $page1->Content = 'changed';
     $page1->write();
     $page1->publish('Stage', 'Live');
     $changedVersion = $page1->Version;
     $page1->doRollbackTo($origVersion);
     $page1 = Versioned::get_one_by_stage('Page', 'Stage', sprintf('"SiteTree"."ID" = %d', $page1->ID));
     $this->assertTrue($page1->Version > $changedVersion, 'Create a new higher version number');
     $this->assertEquals('orig', $page1->Content, 'Copies the content from the old version');
 }
 /**
  * @param SS_HTTPRequest $request
  *
  * @return string|HTMLText
  */
 public function preview(SS_HTTPRequest $request)
 {
     $key = $request->param('Key');
     $token = $request->param('Token');
     /**
      * @var ShareToken $shareToken
      */
     $shareToken = ShareToken::get()->filter('token', $token)->first();
     if (!$shareToken) {
         return $this->errorPage();
     }
     $page = Versioned::get_one_by_stage('SiteTree', 'Stage', sprintf('"SiteTree"."ID" = \'%d\'', $shareToken->PageID));
     $latest = Versioned::get_latest_version('SiteTree', $shareToken->PageID);
     $controller = $this->getControllerFor($page);
     if (!$shareToken->isExpired() && $page->generateKey($shareToken->Token) === $key) {
         Requirements::css(SHAREDRAFTCONTENT_DIR . '/css/top-bar.css');
         // Temporarily un-secure the draft site and switch to draft
         $oldSecured = Session::get('unsecuredDraftSite');
         $oldMode = Versioned::get_reading_mode();
         $restore = function () use($oldSecured, $oldMode) {
             Session::set('unsecuredDraftSite', $oldSecured);
             Versioned::set_reading_mode($oldMode);
         };
         // Process page inside an unsecured draft container
         try {
             Session::set('unsecuredDraftSite', true);
             Versioned::reading_stage('Stage');
             // Create mock request; Simplify request to single top level reqest
             $pageRequest = new SS_HTTPRequest('GET', $page->URLSegment);
             $pageRequest->match('$URLSegment//$Action/$ID/$OtherID', true);
             $rendered = $controller->handleRequest($pageRequest, $this->model);
             // Render draft heading
             $data = new ArrayData(array('Page' => $page, 'Latest' => $latest));
             $include = (string) $data->renderWith('Includes/TopBar');
         } catch (Exception $ex) {
             $restore();
             throw $ex;
         }
         $restore();
         return str_replace('</body>', $include . '</body>', (string) $rendered->getBody());
     } else {
         return $this->errorPage();
     }
 }
    function testImportPublishAll()
    {
        $data = <<<YML
Parent1
Parent2
\tChild2_1
\t\tGrandchild2_1_1
\tChild2_2
Parent3
YML;
        $this->import($data, array('PublishAll' => 1));
        $parent1 = Versioned::get_one_by_stage('Page', 'Live', "\"Title\" = 'Parent1'");
        $parent2 = Versioned::get_one_by_stage('Page', 'Live', "\"Title\" = 'Parent2'");
        $parent3 = Versioned::get_one_by_stage('Page', 'Live', "\"Title\" = 'Parent3'");
        $child2_1 = Versioned::get_one_by_stage('Page', 'Live', "\"Title\" = 'Child2_1'");
        $child2_2 = Versioned::get_one_by_stage('Page', 'Live', "\"Title\" = 'Child2_2'");
        $grandchild2_1_1 = Versioned::get_one_by_stage('Page', 'Live', "\"Title\" = 'Grandchild2_1_1'");
        $this->assertInstanceOf('Page', $parent1);
        $this->assertInstanceOf('Page', $parent2);
        $this->assertInstanceOf('Page', $parent3);
        $this->assertInstanceOf('Page', $child2_1);
        $this->assertInstanceOf('Page', $child2_2);
        $this->assertInstanceOf('Page', $grandchild2_1_1);
    }
 function run($request)
 {
     $ids = array();
     echo "#################################\n";
     echo "# Adding translation groups to existing records" . "\n";
     echo "#################################\n";
     $allSiteTreeIDs = DB::query('SELECT `ID` FROM `SiteTree`')->column();
     if ($allSiteTreeIDs) {
         foreach ($allSiteTreeIDs as $id) {
             $original = DataObject::get_by_id('SiteTree', $id);
             $existingGroupID = $original->getTranslationGroup();
             if (!$existingGroupID) {
                 $original->addTranslationGroup($original->ID);
             }
             $original->destroy();
             unset($original);
         }
     }
     DataObject::flush_and_destroy_cache();
     echo sprintf("Created translation groups for %d records\n", count($allSiteTreeIDs));
     foreach (array('Stage', 'Live') as $stage) {
         echo "\n\n#################################\n";
         echo "# Migrating stage {$stage}" . "\n";
         echo "#################################\n";
         $suffix = $stage == 'Live' ? '_Live' : '';
         // First get all entries in SiteTree_lang
         // This should be all translated pages
         $trans = DB::query(sprintf('SELECT * FROM `_obsolete_SiteTree_lang%s`', $suffix));
         // Iterate over each translated pages
         foreach ($trans as $oldtrans) {
             $newLocale = i18n::get_locale_from_lang($oldtrans['Lang']);
             echo sprintf("Migrating from %s to %s translation of '%s' (#%d)\n", $oldtrans['Lang'], $newLocale, Convert::raw2xml($oldtrans['Title']), $oldtrans['OriginalLangID']);
             // Get the untranslated page
             $original = Versioned::get_one_by_stage($oldtrans['ClassName'], $stage, '`SiteTree`.`ID` = ' . $oldtrans['OriginalLangID']);
             if (!$original) {
                 echo sprintf("Couldn't find original for #%d", $oldtrans['OriginalLangID']);
                 continue;
             }
             // write locale to $original
             $original->Locale = i18n::get_locale_from_lang(Translatable::default_lang());
             $original->writeToStage($stage);
             // Clone the original, and set it up as a translation
             $existingTrans = $original->getTranslation($newLocale, $stage);
             if ($existingTrans) {
                 echo sprintf("Found existing new-style translation for #%d. Already merged? Skipping.\n", $oldtrans['OriginalLangID']);
                 continue;
             }
             // Doesn't work with stage/live split
             //$newtrans = $original->createTranslation($newLocale);
             $newtrans = $original->duplicate(false);
             $newtrans->OriginalID = $original->ID;
             // we have to "guess" a locale based on the language
             $newtrans->Locale = $newLocale;
             if ($stage == 'Live' && array_key_exists($original->ID, $ids)) {
                 $newtrans->ID = $ids[$original->ID];
             }
             // Look at each class in the ancestry, and see if there is a _lang table for it
             foreach (ClassInfo::ancestry($oldtrans['ClassName']) as $classname) {
                 $oldtransitem = false;
                 // If the class is SiteTree, we already have the DB record, else check for the table and get the record
                 if ($classname == 'SiteTree') {
                     $oldtransitem = $oldtrans;
                 } elseif (in_array(strtolower($classname) . '_lang', DB::tableList())) {
                     $oldtransitem = DB::query(sprintf('SELECT * FROM `_obsolete_%s_lang%s` WHERE `OriginalLangID` = %d AND `Lang` = \'%s\'', $classname, $suffix, $original->ID, $oldtrans['Lang']))->first();
                 }
                 // Copy each translated field into the new translation
                 if ($oldtransitem) {
                     foreach ($oldtransitem as $key => $value) {
                         if (!in_array($key, array('ID', 'OriginalLangID'))) {
                             $newtrans->{$key} = $value;
                         }
                     }
                 }
             }
             // Write the new translation to the database
             $sitelang = Translatable::get_current_locale();
             Translatable::set_current_locale($newtrans->Locale);
             $newtrans->writeToStage($stage);
             Translatable::set_current_locale($sitelang);
             $newtrans->addTranslationGroup($original->getTranslationGroup(), true);
             if ($stage == 'Stage') {
                 $ids[$original->ID] = $newtrans->ID;
             }
         }
     }
     echo "\n\n#################################\n";
     echo "Done!\n";
 }
Exemplo n.º 16
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 testRevertToLiveFixesBrokenLinks()
 {
     // Create page and virutal page
     $p = new Page();
     $p->Title = "source";
     $p->write();
     $pageID = $p->ID;
     $this->assertTrue($p->doPublish());
     // Content links are one kind of link to pages
     $p2 = new Page();
     $p2->Title = "regular link";
     $p2->Content = "<a href=\"[sitetree_link,id={$p->ID}]\">test</a>";
     $p2->write();
     $this->assertTrue($p2->doPublish());
     // Virtual pages are another
     $vp = new VirtualPage();
     $vp->CopyContentFromID = $p->ID;
     $vp->write();
     // Redirector links are a third
     $rp = new RedirectorPage();
     $rp->Title = "redirector";
     $rp->LinkType = 'Internal';
     $rp->LinkToID = $p->ID;
     $rp->write();
     $this->assertTrue($rp->doPublish());
     // Confirm that there are no broken links to begin with
     $this->assertFalse($p2->HasBrokenLink);
     $this->assertFalse($vp->HasBrokenLink);
     $this->assertFalse($rp->HasBrokenLink);
     // Delete from draft and confirm that broken links are marked
     $pID = $p->ID;
     $p->delete();
     $vp->flushCache();
     $vp = DataObject::get_by_id('SiteTree', $vp->ID);
     $p2->flushCache();
     $p2 = DataObject::get_by_id('SiteTree', $p2->ID);
     $rp->flushCache();
     $rp = DataObject::get_by_id('SiteTree', $rp->ID);
     $this->assertEquals(1, $p2->HasBrokenLink);
     $this->assertEquals(1, $vp->HasBrokenLink);
     $this->assertEquals(1, $rp->HasBrokenLink);
     // Call doRevertToLive and confirm that broken links are restored
     $pLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $pID);
     $pLive->doRevertToLive();
     $p2->flushCache();
     $p2 = DataObject::get_by_id('SiteTree', $p2->ID);
     $vp->flushCache();
     $vp = DataObject::get_by_id('SiteTree', $vp->ID);
     $rp->flushCache();
     $rp = DataObject::get_by_id('SiteTree', $rp->ID);
     $this->assertFalse((bool) $p2->HasBrokenLink);
     $this->assertFalse((bool) $vp->HasBrokenLink);
     $this->assertFalse((bool) $rp->HasBrokenLink);
 }
 protected function getLivePage()
 {
     $baseTable = ClassInfo::baseDataClass($this->record->class);
     return Versioned::get_one_by_stage($baseTable, 'Live', array("\"{$baseTable}\".\"ID\"" => $this->record->ID));
 }
 /**
  * Reverts a page by publishing it to live.
  * Use {@link restorepage()} if you want to restore a page
  * which was deleted from draft without publishing.
  *
  * @uses SiteTree->doRevertToLive()
  */
 public function revert($data, $form)
 {
     if (!isset($data['ID'])) {
         return new SS_HTTPResponse("Please pass an ID in the form content", 400);
     }
     $id = (int) $data['ID'];
     $restoredPage = Versioned::get_latest_version("ContentModule", $id);
     if (!$restoredPage) {
         return new SS_HTTPResponse("ContentModule #{$id} not found", 400);
     }
     $record = Versioned::get_one_by_stage('SiteTree', 'Live', sprintf("\"SiteTree_Live\".\"ID\" = '%d'", (int) $data['ID']));
     // a user can restore a page without publication rights, as it just adds a new draft state
     // (this action should just be available when page has been "deleted from draft")
     if ($record && !$record->canEdit()) {
         return Security::permissionFailure($this);
     }
     if (!$record || !$record->ID) {
         throw new SS_HTTPResponse_Exception("Bad record ID #{$id}", 404);
     }
     $record->doRevertToLive();
     $this->response->addHeader('X-Status', rawurlencode(_t('CMSMain.RESTORED', "Restored '{title}' successfully", 'Param %s is a title', array('title' => $record->Title))));
     return $this->getResponseNegotiator()->respond($this->request);
 }
Exemplo n.º 20
0
 public function run(SS_List $pages)
 {
     Deprecation::notice('4.0', 'Delete From Live is deprecated. Use Unpublish instead');
     $status = array('modified' => array(), 'deleted' => array());
     foreach ($pages as $page) {
         $id = $page->ID;
         // Perform the action
         if ($page->canDelete()) {
             $page->doDeleteFromLive();
         }
         // check to see if the record exists on the stage site, if it doesn't remove the tree node
         $stageRecord = Versioned::get_one_by_stage('SiteTree', 'Stage', array('"SiteTree"."ID"' => $id));
         if ($stageRecord) {
             $status['modified'][$stageRecord->ID] = array('TreeTitle' => $stageRecord->TreeTitle);
         } else {
             $status['deleted'][$id] = array();
         }
     }
     return $this->response(_t('CMSBatchActions.DELETED_PAGES', 'Deleted %d pages from published site, %d failures'), $status);
 }
 /**
  * Returns the old record that will be replaced by this publication.
  */
 public function fromRecord()
 {
     $bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`";
     return Versioned::get_one_by_stage('SiteTree', 'Live', "{$bt}SiteTree_Live{$bt}.{$bt}ID{$bt} = {$this->PageID}", true, "\"Created\" DESC");
 }
Exemplo n.º 22
0
 /**
  * Return a few pieces of information about a change to a page
  *  - Send the new status message
  *  - Update the action buttons
  *  - Update the treenote
  *  - Send a status message
  */
 function tellBrowserAboutPublicationChange($page, $statusMessage)
 {
     $JS_title = Convert::raw2js($page->TreeTitle());
     $JS_stageURL = $page->IsDeletedFromStage ? '' : Convert::raw2js($page->AbsoluteLink());
     $liveRecord = Versioned::get_one_by_stage('SiteTree', 'Live', "\"SiteTree\".\"ID\" = {$page->ID}");
     $JS_liveURL = $liveRecord ? Convert::raw2js($liveRecord->AbsoluteLink()) : '';
     FormResponse::add($this->getActionUpdateJS($page));
     FormResponse::update_status($page->Status);
     if ($JS_stageURL || $JS_liveURL) {
         FormResponse::add("\$('sitetree').setNodeTitle({$page->ID}, '{$JS_title}');");
     } else {
         FormResponse::add("var node = \$('sitetree').getTreeNodeByIdx('{$page->ID}');");
         FormResponse::add("if(node && node.parentTreeNode) node.parentTreeNode.removeTreeNode(node);");
         FormResponse::add("\$('Form_EditForm').reloadIfSetTo({$page->ID});");
     }
     if ($statusMessage) {
         FormResponse::status_message($statusMessage, 'good');
     }
     FormResponse::add("\$('Form_EditForm').elements.StageURLSegment.value = '{$JS_stageURL}';");
     FormResponse::add("\$('Form_EditForm').elements.LiveURLSegment.value = '{$JS_liveURL}';");
     FormResponse::add("\$('Form_EditForm').notify('PagePublished', \$('Form_EditForm').elements.ID.value);");
     return FormResponse::respond();
 }
 protected function rebaseOrphans($orphanIDs)
 {
     $holder = new SiteTree();
     $holder->ShowInMenus = 0;
     $holder->ShowInSearch = 0;
     $holder->ParentID = 0;
     $holder->Title = $this->rebaseHolderTitle();
     $holder->write();
     $removedOrphans = array();
     foreach ($orphanIDs as $id) {
         $stageRecord = Versioned::get_one_by_stage($this->orphanedSearchClass, 'Stage', sprintf("\"%s\".\"ID\" = %d", ClassInfo::baseDataClass($this->orphanedSearchClass), $id));
         if ($stageRecord) {
             $removedOrphans[$stageRecord->ID] = sprintf('Rebased %s (#%d)', $stageRecord->Title, $stageRecord->ID);
             $stageRecord->ParentID = $holder->ID;
             $stageRecord->ShowInMenus = 0;
             $stageRecord->ShowInSearch = 0;
             $stageRecord->write();
             $stageRecord->doUnpublish();
             $stageRecord->destroy();
             //unset($stageRecord);
         }
         $liveRecord = Versioned::get_one_by_stage($this->orphanedSearchClass, 'Live', sprintf("\"%s\".\"ID\" = %d", ClassInfo::baseDataClass($this->orphanedSearchClass), $id));
         if ($liveRecord) {
             $removedOrphans[$liveRecord->ID] = sprintf('Rebased %s (#%d)', $liveRecord->Title, $liveRecord->ID);
             $liveRecord->ParentID = $holder->ID;
             $liveRecord->ShowInMenus = 0;
             $liveRecord->ShowInSearch = 0;
             $liveRecord->write();
             if (!$stageRecord) {
                 $liveRecord->doRestoreToStage();
             }
             $liveRecord->doUnpublish();
             $liveRecord->destroy();
             unset($liveRecord);
         }
         if ($stageRecord) {
             unset($stageRecord);
         }
     }
     return $removedOrphans;
 }
Exemplo n.º 24
0
 function testDoRevertToLive()
 {
     $this->logInWithPermission('ADMIN');
     $form = $this->objFromFixture('UserDefinedForm', 'basic-form-page');
     $field = $form->Fields()->First();
     $field->Title = 'Title';
     $field->write();
     $form->doPublish();
     $field->Title = 'Edited title';
     $field->write();
     // check that the published version is not updated
     $live = Versioned::get_one_by_stage("EditableFormField", "Live", "\"EditableFormField_Live\".\"ID\" = {$field->ID}");
     $this->assertEquals('Title', $live->Title);
     // revert back to the live data
     $form->doRevertToLive();
     $form->flushCache();
     $check = Versioned::get_one_by_stage("EditableFormField", "Stage", "\"EditableFormField\".\"ID\" = {$field->ID}");
     $this->assertEquals('Title', $check->Title);
 }
	function testLinkTrackingOnExtraContentFields() {
		$page1 = $this->objFromFixture('Page', 'page1');
		$page2 = $this->objFromFixture('Page', 'page2');
		$page1->doPublish();
		$page2->doPublish();
		
		// assert backlink to page 2 doesn't exist
		$this->assertNotContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 doesn\'t exist');
		
		// add hyperlink to page 1 on page 2
		$page2->ExtraContent .= '<p><a href="[sitetree_link id='.$page1->ID.']">Testing page 1 link</a></p>';
		$page2->write();
		$page2->doPublish();

		// assert backlink to page 2 exists
		$this->assertContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 exists');

		// update page1 url
		$page1 = $this->objFromFixture('Page', 'page1');
		$page1->URLSegment = "page1-new-url";
		$page1->write();

		// confirm that draft link on page2 has been rewritten
		$page2 = $this->objFromFixture('Page', 'page2');
		$this->assertEquals('<p><a href="'.Director::baseURL().'page1-new-url/">Testing page 1 link</a></p>', $page2->obj('ExtraContent')->forTemplate());

		// confirm that published link hasn't
		$page2Live = Versioned::get_one_by_stage("Page", "Live", "\"SiteTree\".\"ID\" = $page2->ID");
		Versioned::reading_stage('Live');
		$this->assertEquals('<p><a href="'.Director::baseURL().'page1/">Testing page 1 link</a></p>', $page2Live->obj('ExtraContent')->forTemplate());
		
		// publish page1 and confirm that the link on the published page2 has now been updated
		$page1->doPublish();
		$page2Live = Versioned::get_one_by_stage("Page", "Live", "\"SiteTree\".\"ID\" = $page2->ID");
		$this->assertEquals('<p><a href="'.Director::baseURL().'page1-new-url/">Testing page 1 link</a></p>', $page2Live->obj('ExtraContent')->forTemplate());
		

		// remove hyperlink to page 1
		$page2->ExtraContent = '<p>No links anymore!</p>';
		$page2->write();

		// assert backlink to page 2 no longer exists
		$this->assertNotContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 has been removed');
	}
 function getHTML($page)
 {
     if (Versioned::current_archived_date()) {
         return "<a class=\"current\">" . _t('ContentController.ARCHIVEDSITE', 'Archived Site') . "</a>";
     } else {
         // Display the archive link if the page currently displayed in the CMS is other version than live and draft
         $currentDraft = Versioned::get_one_by_stage('SiteTree', 'Draft', '"SiteTree"."ID" = ' . $page->ID);
         $currentLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $page->ID);
         if ((!$currentDraft || $currentDraft && $page->Version != $currentDraft->Version) && (!$currentLive || $currentLive && $page->Version != $currentLive->Version)) {
             $pageLink = $page->AbsoluteLink();
             return "<a href=\"{$pageLink}?archiveDate={$page->LastEdited}\" class=\"newWindow\" target=\"site\" style=\"left : -3px;\">" . _t('ContentController.ARCHIVEDSITE', 'Archived Site') . "</a>";
         }
     }
 }
 public function testPageTypeChangePropagatesToLive()
 {
     $page = new SiteTree();
     $page->MySharedNonVirtualField = 'original';
     $page->write();
     $page->publish('Stage', 'Live');
     $virtual = new VirtualPageTest_VirtualPageSub();
     $virtual->CopyContentFromID = $page->ID;
     $virtual->write();
     $virtual->publish('Stage', 'Live');
     $page->Title = 'original';
     // 'Title' is a virtual field
     // Publication would causes the virtual field to copy through onBeforeWrite(),
     // but we want to test that it gets copied on class name change instead
     $page->write();
     $nonVirtual = $virtual;
     $nonVirtual->ClassName = 'VirtualPageTest_ClassA';
     $nonVirtual->MySharedNonVirtualField = 'changed on new type';
     $nonVirtual->write();
     // not publishing the page type change here
     $this->assertEquals('original', $nonVirtual->Title, 'Copies virtual fields from original draft into new instance on type change ');
     $nonVirtualLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree_Live"."ID" = ' . $nonVirtual->ID);
     $this->assertNotNull($nonVirtualLive);
     $this->assertEquals('VirtualPageTest_ClassA', $nonVirtualLive->ClassName);
     $this->assertEquals('changed on new type', $nonVirtualLive->MySharedNonVirtualField);
     $page->MySharedNonVirtualField = 'changed only on original';
     $page->write();
     $page->publish('Stage', 'Live');
     $nonVirtualLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree_Live"."ID" = ' . $nonVirtual->ID, false);
     $this->assertEquals('changed on new type', $nonVirtualLive->MySharedNonVirtualField, 'No field copying from previous original after page type changed');
 }
Exemplo n.º 28
0
 public function testURLSegmentMultiByte()
 {
     $origAllow = Config::inst()->get('URLSegmentFilter', 'default_allow_multibyte');
     Config::inst()->update('URLSegmentFilter', 'default_allow_multibyte', true);
     $sitetree = new SiteTree();
     $sitetree->write();
     $sitetree->URLSegment = 'brötchen';
     $sitetree->write();
     $sitetree = DataObject::get_by_id('SiteTree', $sitetree->ID, false);
     $this->assertEquals($sitetree->URLSegment, rawurlencode('brötchen'));
     $sitetree->publish('Stage', 'Live');
     $sitetree = DataObject::get_by_id('SiteTree', $sitetree->ID, false);
     $this->assertEquals($sitetree->URLSegment, rawurlencode('brötchen'));
     $sitetreeLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $sitetree->ID, false);
     $this->assertEquals($sitetreeLive->URLSegment, rawurlencode('brötchen'));
     Config::inst()->update('URLSegmentFilter', 'default_allow_multibyte', $origAllow);
 }
Exemplo n.º 29
0
 /**
  * Test that a draft-deleted page can still be opened in the CMS
  */
 function testDraftDeletedPageCanBeOpenedInCMS()
 {
     $this->session()->inst_set('loggedInAs', $this->idFromFixture('Member', 'admin'));
     // Set up a page that is delete from live
     $page = $this->objFromFixture('Page', 'page1');
     $pageID = $page->ID;
     $page->doPublish();
     $page->delete();
     $response = $this->get('admin/cms/getitem?ID=' . $pageID . '&ajax=1');
     $livePage = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = {$pageID}");
     $this->assertType('SiteTree', $livePage);
     $this->assertTrue($livePage->canDelete());
     // Check that the 'restore' button exists as a simple way of checking that the correct page is returned.
     $this->assertRegExp('/<input[^>]+type="submit"[^>]+name="action_(restore|revert)"/i', $response->getBody());
 }
Exemplo n.º 30
0
 /**
  * Test that publishing processes respects lazy loaded fields
  */
 public function testLazyLoadFields()
 {
     $originalMode = Versioned::get_reading_mode();
     // Generate staging record and retrieve it from stage in live mode
     Versioned::reading_stage('Stage');
     $obj = new VersionedTest_Subclass();
     $obj->Name = 'bob';
     $obj->ExtraField = 'Field Value';
     $obj->write();
     $objID = $obj->ID;
     $filter = sprintf('"VersionedTest_DataObject"."ID" = \'%d\'', Convert::raw2sql($objID));
     Versioned::reading_stage('Live');
     // Check fields are unloaded prior to access
     $objLazy = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', $filter, false);
     $lazyFields = $objLazy->getQueriedDatabaseFields();
     $this->assertTrue(isset($lazyFields['ExtraField_Lazy']));
     $this->assertEquals('VersionedTest_Subclass', $lazyFields['ExtraField_Lazy']);
     // Check lazy loading works when viewing a Stage object in Live mode
     $this->assertEquals('Field Value', $objLazy->ExtraField);
     // Test that writeToStage respects lazy loaded fields
     $objLazy = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', $filter, false);
     $objLazy->writeToStage('Live');
     $objLive = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Live', $filter, false);
     $liveLazyFields = $objLive->getQueriedDatabaseFields();
     // Check fields are unloaded prior to access
     $this->assertTrue(isset($liveLazyFields['ExtraField_Lazy']));
     $this->assertEquals('VersionedTest_Subclass', $liveLazyFields['ExtraField_Lazy']);
     // Check that live record has original value
     $this->assertEquals('Field Value', $objLive->ExtraField);
     Versioned::set_reading_mode($originalMode);
 }