/**
  *	Instantiate a search page, should one not exist.
  */
 public function requireDefaultRecords()
 {
     parent::requireDefaultRecords();
     $mode = Versioned::get_reading_mode();
     Versioned::reading_stage('Stage');
     // Determine whether pages should be created.
     if (self::config()->create_default_pages) {
         // Determine whether an extensible search page already exists.
         if (!ExtensibleSearchPage::get()->first()) {
             // Instantiate an extensible search page.
             $page = ExtensibleSearchPage::create();
             $page->Title = 'Search Page';
             $page->write();
             DB::alteration_message('"Default" Extensible Search Page', 'created');
         }
     } else {
         if (ClassInfo::exists('Multisites')) {
             foreach (Site::get() as $site) {
                 // Determine whether an extensible search page already exists.
                 if (!ExtensibleSearchPage::get()->filter('SiteID', $site->ID)->first()) {
                     // Instantiate an extensible search page.
                     $page = ExtensibleSearchPage::create();
                     $page->ParentID = $site->ID;
                     $page->Title = 'Search Page';
                     $page->write();
                     DB::alteration_message("\"{$site->Title}\" Extensible Search Page", 'created');
                 }
             }
         }
     }
     Versioned::set_reading_mode($mode);
 }
 /**
  * Perform migration
  *
  * @param string $base Absolute base path (parent of assets folder). Will default to BASE_PATH
  * @return int Number of files successfully migrated
  */
 public function run($base = null)
 {
     if (empty($base)) {
         $base = BASE_PATH;
     }
     // Check if the File dataobject has a "Filename" field.
     // If not, cannot migrate
     if (!DB::get_schema()->hasField('File', 'Filename')) {
         return 0;
     }
     // Set max time and memory limit
     increase_time_limit_to();
     increase_memory_limit_to();
     // Loop over all files
     $count = 0;
     $originalState = \Versioned::get_reading_mode();
     \Versioned::reading_stage('Stage');
     $filenameMap = $this->getFilenameArray();
     foreach ($this->getFileQuery() as $file) {
         // Get the name of the file to import
         $filename = $filenameMap[$file->ID];
         $success = $this->migrateFile($base, $file, $filename);
         if ($success) {
             $count++;
         }
     }
     \Versioned::set_reading_mode($originalState);
     return $count;
 }
 public function tearDown()
 {
     AssetStoreTest_SpyStore::reset();
     if ($this->oldReadingMode) {
         Versioned::set_reading_mode($this->oldReadingMode);
     }
     parent::tearDown();
 }
예제 #4
0
 public function provideGridSheetData($modelClass)
 {
     if (self::ModelClass == $modelClass) {
         $mode = static::own_config('products_reading_mode');
         Versioned::set_reading_mode($mode);
         $products = Product::get();
         return $products;
     }
 }
 /**
  * Returns an array with 2 elements, one with a list of Page on the site (and all subsites if
  * applicable) and another with files.
  *
  * @return array
  */
 public function sourceRecords()
 {
     if (class_exists('Subsite') && Subsite::get()->count() > 0) {
         $origMode = Versioned::get_reading_mode();
         Versioned::set_reading_mode('Stage.Stage');
         $items = array('Pages' => Subsite::get_from_all_subsites('SiteTree'), 'Files' => Subsite::get_from_all_subsites('File'));
         Versioned::set_reading_mode($origMode);
         return $items;
     } else {
         return array('Pages' => Versioned::get_by_stage('SiteTree', 'Stage'), 'Files' => File::get());
     }
 }
 /**
  * 
  * @return DataList
  */
 protected function getAllLivePages($subsiteID = 0)
 {
     ini_set('memory_limit', '200M');
     $oldMode = Versioned::get_reading_mode();
     if (class_exists('Subsite')) {
         Subsite::disable_subsite_filter(true);
     }
     Versioned::reading_stage('Live');
     $pages = DataObject::get("SiteTree");
     Versioned::set_reading_mode($oldMode);
     if (class_exists('Subsite')) {
         return $pages->filter(array('SubsiteID' => $subsiteID));
     }
     return $pages;
 }
 /**
  * @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();
     }
 }
 public function doSavePost($data, $form)
 {
     $post = false;
     if (isset($data['ID']) && $data['ID']) {
         $post = BlogPost::get()->byID($data['ID']);
     }
     if (!$post) {
         $post = BlogPost::create();
     }
     $form->saveInto($post);
     $post->ParentID = $this->owner->ID;
     $this->owner->extend("onBeforeSavePost", $blogentry);
     $oldMode = Versioned::get_reading_mode();
     Versioned::reading_stage('Stage');
     $post->write();
     $post->publish("Stage", "Live");
     Versioned::set_reading_mode($oldMode);
     $this->owner->extend("onAfterSavePost", $post);
     $this->owner->redirect($this->owner->Link());
 }
 /**
  *	Update the searchable content tagging for a specific fusion tag.
  *
  *	@parameter <{FUSION_TAG_ID}> integer
  */
 public function updateTagging($fusionID)
 {
     // Determine any data objects with the tagging extension.
     $classes = ClassInfo::subclassesFor('DataObject');
     unset($classes['DataObject']);
     $configuration = Config::inst();
     foreach ($classes as $class) {
         // Determine the specific data object extensions.
         $extensions = $configuration->get($class, 'extensions', Config::UNINHERITED);
         if (is_array($extensions) && in_array('TaggingExtension', $extensions)) {
             // Determine whether this fusion tag is being used.
             $mode = Versioned::get_reading_mode();
             Versioned::reading_stage('Stage');
             $objects = $class::get()->filter('FusionTags.ID', $fusionID);
             // Update the searchable content tagging for these data objects.
             if ($class::has_extension($class, 'Versioned')) {
                 // These data objects are versioned.
                 foreach ($objects as $object) {
                     // Update the staging version.
                     $object->writeWithoutVersion();
                 }
                 Versioned::reading_stage('Live');
                 $objects = $class::get()->filter('FusionTags.ID', $fusionID);
                 foreach ($objects as $object) {
                     // Update the live version.
                     $object->writeWithoutVersion();
                 }
             } else {
                 // These data objects are not versioned.
                 foreach ($objects as $object) {
                     $object->write();
                 }
             }
             Versioned::set_reading_mode($mode);
         }
     }
 }
예제 #10
0
 /**
  * @return DataObject
  */
 static function get_version($class, $id, $version)
 {
     $oldMode = Versioned::get_reading_mode();
     Versioned::set_reading_mode('');
     $baseTable = ClassInfo::baseDataClass($class);
     $query = singleton($class)->buildVersionSQL("\"{$baseTable}\".\"RecordID\" = {$id} AND \"{$baseTable}\".\"Version\" = {$version}");
     $record = $query->execute()->record();
     $className = $record['ClassName'];
     if (!$className) {
         Debug::show($query->sql());
         Debug::show($record);
         user_error("Versioned::get_version: Couldn't get {$class}.{$id}, version {$version}", E_USER_ERROR);
     }
     Versioned::set_reading_mode($oldMode);
     return new $className($record);
 }
 /**
  * Build the database with default records, see {@link DataObject->requireDefaultRecords()}.
  */
 public function requireDefaultRecords()
 {
     $dbAdmin = new DatabaseAdmin();
     Versioned::set_reading_mode('');
     $dbAdmin->doBuild(true, true);
 }
예제 #12
0
 public function run($request)
 {
     increase_time_limit_to();
     $type = Convert::raw2sql($request->getVar('type'));
     if ($type) {
         $this->types[] = $type;
     } elseif (!$this->types) {
         foreach (ClassInfo::subclassesFor('DataObject') as $class) {
             if ($class::has_extension('SolrIndexable')) {
                 $this->types[] = $class;
             }
         }
     }
     $search = singleton('SolrSearchService');
     if (isset($_GET['delete_all'])) {
         $search->getSolr()->deleteByQuery('*:*');
         $search->getSolr()->commit();
     }
     $count = 0;
     foreach ($this->types as $type) {
         $search->getSolr()->deleteByQuery('ClassNameHierarchy_ms:' . $type);
         $search->getSolr()->commit();
         if (ClassInfo::exists('QueuedJob') && !isset($_GET['direct'])) {
             $job = new SolrReindexJob($type);
             $svc = singleton('QueuedJobService');
             $svc->queueJob($job);
             $this->log("Reindexing job for {$type} has been queued");
         } else {
             $mode = Versioned::get_reading_mode();
             Versioned::reading_stage('Stage');
             // get the holders first, see if we have any that AREN'T in the root (ie we've already partitioned everything...)
             $pages = $type::get();
             $pages = $pages->filter(array('ClassName' => $type));
             /* @var $search SolrSearchService */
             $this->log("------------------------------");
             $this->log("Start reindexing job for {$type} (Count: " . $pages->count() . "):");
             $this->log("------------------------------");
             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')) {
                     $search->index($page, 'Stage');
                     $baseTable = $page->baseTable();
                     $live = Versioned::get_one_by_stage($page->ClassName, 'Live', "\"{$baseTable}\".\"ID\" = {$page->ID}");
                     if ($live) {
                         $search->index($live, 'Live');
                         $this->log("Reindexed Live version of {$live->Title}");
                     }
                     $this->log("Reindexed (#{$page->ID}) {$page->Title}");
                     $count++;
                 } else {
                     $search->index($page);
                     $this->log("Reindexed {$type} ID#{$page->ID}");
                     $count++;
                 }
             }
             Versioned::set_reading_mode($mode);
         }
     }
     $this->log("------------------------------");
     $this->log("Reindex complete, {$count} objects re-indexed");
     $this->log("------------------------------");
 }
예제 #13
0
 /**
  * Publish this page.
  * 
  * @uses SiteTreeDecorator->onBeforePublish()
  * @uses SiteTreeDecorator->onAfterPublish()
  */
 function doPublish()
 {
     if (!$this->canPublish()) {
         return false;
     }
     $original = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = {$this->ID}");
     if (!$original) {
         $original = new SiteTree();
     }
     // Handle activities undertaken by decorators
     $this->invokeWithExtensions('onBeforePublish', $original);
     $this->Status = "Published";
     //$this->PublishedByID = Member::currentUser()->ID;
     $this->write();
     $this->publish("Stage", "Live");
     DB::query("UPDATE \"SiteTree_Live\"\n\t\t\tSET \"Sort\" = (SELECT \"SiteTree\".\"Sort\" FROM \"SiteTree\" WHERE \"SiteTree_Live\".\"ID\" = \"SiteTree\".\"ID\")\n\t\t\tWHERE EXISTS (SELECT \"SiteTree\".\"Sort\" FROM \"SiteTree\" WHERE \"SiteTree_Live\".\"ID\" = \"SiteTree\".\"ID\") AND \"ParentID\" = " . sprintf('%d', $this->ParentID));
     // Publish any virtual pages that might need publishing
     $linkedPages = $this->VirtualPages();
     if ($linkedPages) {
         foreach ($linkedPages as $page) {
             $page->copyFrom($page->CopyContentFrom());
             $page->write();
             if ($page->ExistsOnLive) {
                 $page->doPublish();
             }
         }
     }
     // Need to update pages linking to this one as no longer broken, on the live site
     $origMode = Versioned::get_reading_mode();
     Versioned::reading_stage('Live');
     foreach ($this->DependentPages(false) as $page) {
         // $page->write() calls syncLinkTracking, which does all the hard work for us.
         $page->write();
     }
     Versioned::set_reading_mode($origMode);
     // Check to write CMS homepage map.
     $usingStaticPublishing = false;
     foreach (ClassInfo::subclassesFor('StaticPublisher') as $class) {
         if ($this->hasExtension($class)) {
             $usingStaticPublishing = true;
         }
     }
     // NOTE: if you change the path here, you must also change it in sapphire/static-main.php
     if (self::$write_homepage_map) {
         if ($usingStaticPublishing && ($map = SiteTree::generate_homepage_domain_map())) {
             @file_put_contents(BASE_PATH . '/' . ASSETS_DIR . '/_homepage-map.php', "<?php\n\$homepageMap = " . var_export($map, true) . "; ?>");
         } else {
             if (file_exists(BASE_PATH . '/' . ASSETS_DIR . '/_homepage-map.php')) {
                 unlink(BASE_PATH . '/' . ASSETS_DIR . '/_homepage-map.php');
             }
         }
     }
     // Handle activities undertaken by decorators
     $this->invokeWithExtensions('onAfterPublish', $original);
     return true;
 }
예제 #14
0
 public function testArchiveVersion()
 {
     // In 2005 this file was created
     SS_Datetime::set_mock_now('2005-01-01 00:00:00');
     $testPage = new VersionedTest_Subclass();
     $testPage->Title = 'Archived page';
     $testPage->Content = 'This is the content from 2005';
     $testPage->ExtraField = '2005';
     $testPage->write();
     // In 2007 we updated it
     SS_Datetime::set_mock_now('2007-01-01 00:00:00');
     $testPage->Content = "It's 2007 already!";
     $testPage->ExtraField = '2007';
     $testPage->write();
     // In 2009 we updated it again
     SS_Datetime::set_mock_now('2009-01-01 00:00:00');
     $testPage->Content = "I'm enjoying 2009";
     $testPage->ExtraField = '2009';
     $testPage->write();
     // End mock, back to the present day:)
     SS_Datetime::clear_mock_now();
     // Test 1 - 2006 Content
     singleton('VersionedTest_Subclass')->flushCache(true);
     Versioned::set_reading_mode('Archive.2006-01-01 00:00:00');
     $testPage2006 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
     $this->assertInstanceOf("VersionedTest_Subclass", $testPage2006);
     $this->assertEquals("2005", $testPage2006->ExtraField);
     $this->assertEquals("This is the content from 2005", $testPage2006->Content);
     // Test 2 - 2008 Content
     singleton('VersionedTest_Subclass')->flushCache(true);
     Versioned::set_reading_mode('Archive.2008-01-01 00:00:00');
     $testPage2008 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
     $this->assertInstanceOf("VersionedTest_Subclass", $testPage2008);
     $this->assertEquals("2007", $testPage2008->ExtraField);
     $this->assertEquals("It's 2007 already!", $testPage2008->Content);
     // Test 3 - Today
     singleton('VersionedTest_Subclass')->flushCache(true);
     Versioned::set_reading_mode('Stage.Stage');
     $testPageCurrent = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
     $this->assertInstanceOf("VersionedTest_Subclass", $testPageCurrent);
     $this->assertEquals("2009", $testPageCurrent->ExtraField);
     $this->assertEquals("I'm enjoying 2009", $testPageCurrent->Content);
 }
 /**
  * 
  * @return DataList
  */
 protected function getAllLivePages()
 {
     ini_set('memory_limit', '512M');
     $oldMode = Versioned::get_reading_mode();
     if (class_exists('Subsite')) {
         Subsite::disable_subsite_filter(true);
     }
     if (class_exists('Translatable')) {
         Translatable::disable_locale_filter();
     }
     Versioned::reading_stage('Live');
     $pages = DataObject::get("SiteTree");
     Versioned::set_reading_mode($oldMode);
     return $pages;
 }
 public function tearDown()
 {
     Versioned::set_reading_mode($this->oldMode);
     Config::unnest();
     parent::tearDown();
 }
 /**
  * Return a dataobject based on the `id` and `tree_class`.
  *
  * @param  int $id
  * @return DataObject
  */
 public function getRecord($id)
 {
     $treeClass = $this->stat('tree_class');
     $record = DataObject::get_one($treeClass, "\"{$treeClass}\".\"ID\" = {$id}");
     // Then, try getting a record from the live site
     if (!$record) {
         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);
     }
     return $record;
 }
 /**
  * Test that orphaned pages are handled correctly
  */
 public function testOrphanedPages()
 {
     $origStage = Versioned::get_reading_mode();
     // Setup user who can view draft content, but lacks cms permission.
     // To users such as this, orphaned pages should be inaccessible. canView for these pages is only
     // necessary for admin / cms users, who require this permission to edit / rearrange these pages.
     $permission = new Permission();
     $permission->Code = 'VIEW_DRAFT_CONTENT';
     $group = new Group(array('Title' => 'Staging Users'));
     $group->write();
     $group->Permissions()->add($permission);
     $member = new Member();
     $member->Email = '*****@*****.**';
     $member->write();
     $member->Groups()->add($group);
     // both pages are viewable in stage
     Versioned::reading_stage('Stage');
     $about = $this->objFromFixture('Page', 'about');
     $staff = $this->objFromFixture('Page', 'staff');
     $this->assertFalse($about->isOrphaned());
     $this->assertFalse($staff->isOrphaned());
     $this->assertTrue($about->canView($member));
     $this->assertTrue($staff->canView($member));
     // Publishing only the child page to live should orphan the live record, but not the staging one
     $staff->publish('Stage', 'Live');
     $this->assertFalse($staff->isOrphaned());
     $this->assertTrue($staff->canView($member));
     Versioned::reading_stage('Live');
     $staff = $this->objFromFixture('Page', 'staff');
     // Live copy of page
     $this->assertTrue($staff->isOrphaned());
     // because parent isn't published
     $this->assertFalse($staff->canView($member));
     // Publishing the parent page should restore visibility
     Versioned::reading_stage('Stage');
     $about = $this->objFromFixture('Page', 'about');
     $about->publish('Stage', 'Live');
     Versioned::reading_stage('Live');
     $staff = $this->objFromFixture('Page', 'staff');
     $this->assertFalse($staff->isOrphaned());
     $this->assertTrue($staff->canView($member));
     // Removing staging page should not prevent live page being visible
     $about->deleteFromStage('Stage');
     $staff->deleteFromStage('Stage');
     $staff = $this->objFromFixture('Page', 'staff');
     $this->assertFalse($staff->isOrphaned());
     $this->assertTrue($staff->canView($member));
     // Cleanup
     Versioned::set_reading_mode($origStage);
 }
 /**
  * 
  * Physically runs the task which - dependent on QueuedJobs being installed and
  * not skipped via script params - will queue-up chunks of pages to be cached,
  * or just attempt to cache call objects at once.
  * 
  * @param SS_HTTPRequest $request
  * @return void
  */
 public function run($request)
 {
     // Increase memory to max-allowable
     CacheableConfig::configure_memory_limit();
     $startTime = time();
     $skipQueue = $request->getVar('SkipQueue');
     $currentStage = Versioned::current_stage();
     /*
      * Restrict cache rebuild to the given stage - useful for debugging or
      * "Poor Man's" chunking.
      */
     if ($paramStage = $request->getVar('Stage')) {
         $stage_mode_mapping = array(ucfirst($paramStage) => strtolower($paramStage));
         // All stages
     } else {
         $stage_mode_mapping = array("Stage" => "stage", "Live" => "live");
     }
     $canQueue = interface_exists('QueuedJob');
     $siteConfigs = DataObject::get('SiteConfig');
     foreach ($stage_mode_mapping as $stage => $mode) {
         Versioned::set_reading_mode('Stage.' . $stage);
         if (class_exists('Subsite')) {
             Subsite::disable_subsite_filter(true);
             Config::inst()->update("CacheableSiteConfig", 'cacheable_fields', array('SubsiteID'));
             Config::inst()->update("CacheableSiteTree", 'cacheable_fields', array('SubsiteID'));
         }
         foreach ($siteConfigs as $config) {
             $service = new CacheableNavigationService($mode, $config);
             if ($service->refreshCachedConfig()) {
                 echo 'Caching: SiteConfig object ' . trim($config->ID) . ' (' . $config->Title . ') with mode: ' . $mode . self::new_line(2);
             } else {
                 echo 'Caching fails: SiteConfig object ' . trim($config->ID) . ' (' . $config->Title . ') with mode: ' . $mode . self::new_line(2);
             }
             if (class_exists('Subsite')) {
                 $pages = DataObject::get("Page", "SubsiteID = '" . $config->SubsiteID . "'");
             } else {
                 $pages = DataObject::get("Page");
             }
             $pageCount = $pages->count();
             /*
              * 
              * Queueing should only occur if:
              * - QueuedJob module is available
              * - SkipQueue param is not set
              * - Total no. pages is greater than the chunk divisor
              */
             $lowPageCount = self::$chunk_divisor > $pageCount;
             $doQueue = $canQueue && !$skipQueue && !$lowPageCount;
             if ($pageCount) {
                 $i = 0;
                 $chunkNum = 0;
                 $chunk = array();
                 foreach ($pages as $page) {
                     $i++;
                     // If QueuedJobs exists and isn't user-disabled: Chunk
                     if ($doQueue) {
                         // Start building a chunk of pages to be refreshed
                         $chunk[] = $page;
                         $chunkSize = count($chunk);
                         /*
                          * Conditions of chunking:
                          * - Initial chunks are chunk-size == self::$chunk_divisor
                          * - Remaining object count equals no. objects in current $chunk
                          */
                         $doChunking = $this->chunkForQueue($pageCount, $chunkSize, $i);
                         if ($doChunking) {
                             $chunkNum++;
                             $this->queue($service, $chunk, $stage, $config->SubsiteID);
                             echo "Queued chunk #" . $chunkNum . ' (' . $chunkSize . ' objects).' . self::new_line();
                             $chunk = array();
                         }
                         // Default to non-chunking if no queuedjobs or script instructed to skip queuing
                     } else {
                         $percentComplete = $this->percentageComplete($i, $pageCount);
                         $service->set_model($page);
                         if ($service->refreshCachedPage(true)) {
                             echo 'Caching: ' . trim($page->Title) . ' (' . $percentComplete . ') ' . self::new_line();
                         } else {
                             echo 'Caching fails: ' . trim($page->Title) . ' (' . $percentComplete . ') ' . self::new_line();
                         }
                     }
                     $page->flushCache();
                 }
             }
             $service->completeBuild();
             // Completion message
             $msg = self::new_line() . $pageCount . ' ' . $stage . ' pages in subsite ' . $config->ID;
             if ($doQueue) {
                 $msg .= ' queued for caching.' . self::new_line();
             } else {
                 $msg .= ' objects cached.' . self::new_line();
             }
             echo $msg . self::new_line();
         }
         if (class_exists('Subsite')) {
             Subsite::disable_subsite_filter(false);
         }
     }
     Versioned::set_reading_mode($currentStage);
     $endTime = time();
     $totalTime = $endTime - $startTime;
     $this->showConfig($totalTime, $request, $lowPageCount);
 }
 /**
  * Confirm that DataObject::get_one() gets records from SiteTree_Live
  */
 function testGetOneFromLive()
 {
     $s = new SiteTree();
     $s->Title = "V1";
     $s->URLSegment = "get-one-test-page";
     $s->write();
     $s->publish("Stage", "Live");
     $s->Title = "V2";
     $s->write();
     $oldMode = Versioned::get_reading_mode();
     Versioned::reading_stage('Live');
     $checkSiteTree = DataObject::get_one("SiteTree", "\"URLSegment\" = 'get-one-test-page'");
     $this->assertEquals("V1", $checkSiteTree->Title);
     Versioned::set_reading_mode($oldMode);
 }
 /**
  * @todo Find more appropriate place to hook into database building
  */
 public function requireDefaultRecords()
 {
     // @todo This relies on the Locale attribute being on the base data class, and not any subclasses
     if ($this->owner->class != ClassInfo::baseDataClass($this->owner->class)) {
         return false;
     }
     // Permissions: If a group doesn't have any specific TRANSLATE_<locale> edit rights,
     // but has CMS_ACCESS_CMSMain (general CMS access), then assign TRANSLATE_ALL permissions as a default.
     // Auto-setting permissions based on these intransparent criteria is a bit hacky,
     // but unavoidable until we can determine when a certain permission code was made available first
     // (see http://open.silverstripe.org/ticket/4940)
     $groups = Permission::get_groups_by_permission(array('CMS_ACCESS_CMSMain', 'CMS_ACCESS_LeftAndMain', 'ADMIN'));
     if ($groups) {
         foreach ($groups as $group) {
             $codes = $group->Permissions()->column('Code');
             $hasTranslationCode = false;
             foreach ($codes as $code) {
                 if (preg_match('/^TRANSLATE_/', $code)) {
                     $hasTranslationCode = true;
                 }
             }
             // Only add the code if no more restrictive code exists
             if (!$hasTranslationCode) {
                 Permission::grant($group->ID, 'TRANSLATE_ALL');
             }
         }
     }
     // If the Translatable extension was added after the first records were already
     // created in the database, make sure to update the Locale property if
     // if wasn't set before
     $idsWithoutLocale = DB::query(sprintf('SELECT "ID" FROM "%s" WHERE "Locale" IS NULL OR "Locale" = \'\'', ClassInfo::baseDataClass($this->owner->class)))->column();
     if (!$idsWithoutLocale) {
         return;
     }
     if (class_exists('SiteTree') && $this->owner->class == 'SiteTree') {
         foreach (array('Stage', 'Live') as $stage) {
             foreach ($idsWithoutLocale as $id) {
                 $obj = Versioned::get_one_by_stage($this->owner->class, $stage, sprintf('"SiteTree"."ID" = %d', $id));
                 if (!$obj || $obj->ObsoleteClassName) {
                     continue;
                 }
                 $obj->Locale = Translatable::default_locale();
                 $oldMode = Versioned::get_reading_mode();
                 Versioned::reading_stage($stage);
                 $obj->writeWithoutVersion();
                 Versioned::set_reading_mode($oldMode);
                 $obj->addTranslationGroup($obj->ID);
                 $obj->destroy();
                 unset($obj);
             }
         }
     } else {
         foreach ($idsWithoutLocale as $id) {
             $obj = DataObject::get_by_id($this->owner->class, $id);
             if (!$obj || $obj->ObsoleteClassName) {
                 continue;
             }
             $obj->Locale = Translatable::default_locale();
             $obj->write();
             $obj->addTranslationGroup($obj->ID);
             $obj->destroy();
             unset($obj);
         }
     }
     DB::alteration_message(sprintf("Added default locale '%s' to table %s", "changed", Translatable::default_locale(), $this->owner->class));
 }
 /**
  * Will publish all pages of the SiteTree for the defined translationLocale
  *
  * @param int $parentID ID of the parent to get pages for
  * 
  * @return void
  *
  * @author Sebastian Diel <*****@*****.**>
  * @since 03.05.2012
  */
 public function publishSiteTree($parentID = 0)
 {
     $translationLocale = $this->getTranslationLocale();
     Translatable::disable_locale_filter();
     Versioned::set_reading_mode('Stage.Stage');
     $pages = SiteTree::get()->filter(array("ParentID" => $parentID, "Locale" => $translationLocale));
     if ($pages->exists()) {
         foreach ($pages as $page) {
             $page->publish("Stage", "Live");
             $this->publishSiteTree($page->ID);
         }
     }
 }
 public function testUnpublishedPage()
 {
     if (!class_exists('SiteTree')) {
         $this->markTestSkipped('Test skipped; CMS module required for testUnpublishedPage');
     }
     $orphanedPage = new SiteTree();
     $orphanedPage->ParentID = 999999;
     // missing parent id
     $orphanedPage->write();
     $orphanedPage->publish("Stage", "Live");
     $rootPage = new SiteTree();
     $rootPage->ParentID = 0;
     $rootPage->write();
     $rootPage->publish("Stage", "Live");
     $oldMode = Versioned::get_reading_mode();
     Versioned::reading_stage('Live');
     try {
         $this->assertEmpty($orphanedPage->hasPublishedParent());
         $this->assertEmpty($orphanedPage->canIncludeInGoogleSitemap());
         $this->assertNotEmpty($rootPage->hasPublishedParent());
         $this->assertNotEmpty($rootPage->canIncludeInGoogleSitemap());
     } catch (Exception $ex) {
         Versioned::set_reading_mode($oldMode);
         throw $ex;
     }
     // finally {
     Versioned::set_reading_mode($oldMode);
     // }
 }
예제 #24
0
 function writeToStage($stage, $forceInsert = false)
 {
     $oldMode = Versioned::get_reading_mode();
     Versioned::reading_stage($stage);
     $result = $this->owner->write(false, $forceInsert);
     Versioned::set_reading_mode($oldMode);
     return $result;
 }
 /**
  * @inheritdoc
  *
  * @return array
  */
 function check()
 {
     $origStage = Versioned::get_reading_mode();
     Versioned::set_reading_mode('Live');
     $files = $this->getFiles();
     if ($files) {
         $fileTypeValidateFunc = $this->fileTypeValidateFunc;
         if (method_exists($this, $fileTypeValidateFunc)) {
             $invalidFiles = array();
             $validFiles = array();
             foreach ($files as $file) {
                 if ($this->{$fileTypeValidateFunc}($file)) {
                     $validFiles[] = $file;
                 } else {
                     $invalidFiles[] = $file;
                 }
             }
             // If at least one file was valid, count as passed
             if ($this->checkType == self::CHECK_SINGLE && count($invalidFiles) < count($files)) {
                 $validFileList = "\n";
                 foreach ($validFiles as $vf) {
                     $validFileList .= $vf . "\n";
                 }
                 if ($fileTypeValidateFunc == 'noVidation') {
                     $checkReturn = array(EnvironmentCheck::OK, sprintf('At least these file(s) accessible: %s', $validFileList));
                 } else {
                     $checkReturn = array(EnvironmentCheck::OK, sprintf('At least these file(s) passed file type validate function "%s": %s', $fileTypeValidateFunc, $validFileList));
                 }
             } else {
                 if (count($invalidFiles) == 0) {
                     $checkReturn = array(EnvironmentCheck::OK, 'All files valideted');
                 } else {
                     $invalidFileList = "\n";
                     foreach ($invalidFiles as $vf) {
                         $invalidFileList .= $vf . "\n";
                     }
                     if ($fileTypeValidateFunc == 'noVidation') {
                         $checkReturn = array(EnvironmentCheck::ERROR, sprintf('File(s) not accessible: %s', $invalidFileList));
                     } else {
                         $checkReturn = array(EnvironmentCheck::ERROR, sprintf('File(s) not passing the file type validate function "%s": %s', $fileTypeValidateFunc, $invalidFileList));
                     }
                 }
             }
         } else {
             $checkReturn = array(EnvironmentCheck::ERROR, sprintf("Invalid file type validation method name passed: %s ", $fileTypeValidateFunc));
         }
     } else {
         $checkReturn = array(EnvironmentCheck::ERROR, sprintf("No files accessible at path %s", $this->path));
     }
     Versioned::set_reading_mode($origStage);
     return $checkReturn;
 }
 /**
  * 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();
     }
     $pages = DataObject::get($this->reindexType, '"' . $this->reindexType . '"."ID" > ' . $this->lastIndexedID, 'ID ASC', '', '0, ' . self::$at_a_time);
     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 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);
 }
 public function run($request)
 {
     increase_time_limit_to();
     $readingMode = Versioned::get_reading_mode();
     Versioned::reading_stage('Stage');
     // Make sure that we have something to migrate.
     if (!ClassInfo::hasTable('SolrSearchPage')) {
         echo "Nothing to Migrate!";
         die;
     }
     // Retrieve the search tree relationships to migrate.
     $relationships = array();
     if (DB::getConn()->hasTable('SolrSearchPage_SearchTrees')) {
         foreach (DB::query('SELECT * FROM SolrSearchPage_SearchTrees') as $relationship) {
             $relationships[$relationship['SolrSearchPageID']] = $relationship['PageID'];
         }
     }
     // Store the current live page migration state to avoid duplicates.
     $created = array();
     // Migrate any live pages to begin with.
     $query = DB::query('SELECT * FROM SiteTree_Live st, SolrSearchPage_Live ssp WHERE st.ID = ssp.ID');
     $queryCount = $query->numRecords();
     $writeCount = 0;
     foreach ($query as $results) {
         $searchPage = ExtensibleSearchPage::create();
         $searchPage->SearchEngine = 'SolrSearch';
         // Migrate the key site tree and solr search fields across.
         $fields = array('ParentID', 'URLSegment', 'Title', 'MenuTitle', 'Content', 'ShowInMenus', 'ShowInSearch', 'Sort', 'ResultsPerPage', 'SortBy', 'BoostFieldsValue', 'SearchOnFieldsValue', 'SearchTypeValue', 'StartWithListing', 'QueryType', 'ListingTemplateID', 'FilterFieldsValue', 'MinFacetCount', 'FacetQueriesValue', 'FacetMappingValue', 'CustomFacetFieldsValue', 'FacetFieldsValue', 'BoostMatchFieldsValue');
         foreach ($fields as $fname) {
             if (isset($results[$fname])) {
                 $searchPage->{$fname} = $results[$fname];
             }
         }
         // This field name no longer matches the original.
         if ($results['SortDir']) {
             $searchPage->SortDirection = $results['SortDir'];
         }
         if (isset($relationships[$results['ID']])) {
             $searchPage->SearchTrees()->add($relationships[$results['ID']]);
         }
         // Attempt to publish these new pages.
         $searchPage->doPublish();
         if ($searchPage->ID) {
             echo "<strong>{$results['ID']}</strong> Published<br>";
             $writeCount++;
         }
         $created[] = $results['ID'];
     }
     // Confirm that the current user had permission to publish these new pages.
     $this->checkPermissions($queryCount, $writeCount);
     // Migrate any remaining draft pages.
     $query = DB::query('SELECT * FROM SiteTree st, SolrSearchPage ssp WHERE st.ID = ssp.ID');
     $queryCount = $query->numRecords();
     $writeCount = 0;
     foreach ($query as $results) {
         // Make sure this search page doesn't already exist.
         if (!in_array($results['ID'], $created)) {
             $searchPage = ExtensibleSearchPage::create();
             $searchPage->SearchEngine = 'SolrSearch';
             // Migrate the key site tree and solr search fields across.
             $searchPage->ParentID = $results['ParentID'];
             $searchPage->URLSegment = $results['URLSegment'];
             $searchPage->Title = $results['Title'];
             $searchPage->MenuTitle = $results['MenuTitle'];
             $searchPage->Content = $results['Content'];
             $searchPage->ShowInMenus = $results['ShowInMenus'];
             $searchPage->ShowInSearch = $results['ShowInSearch'];
             $searchPage->Sort = $results['Sort'];
             $searchPage->ResultsPerPage = $results['ResultsPerPage'];
             $searchPage->SortBy = $results['SortBy'];
             $searchPage->SortDirection = $results['SortDir'];
             $searchPage->QueryType = $results['QueryType'];
             $searchPage->StartWithListing = $results['StartWithListing'];
             $searchPage->SearchTypeValue = $results['SearchTypeValue'];
             $searchPage->SearchOnFieldsValue = $results['SearchOnFieldsValue'];
             $searchPage->BoostFieldsValue = $results['BoostFieldsValue'];
             $searchPage->BoostMatchFieldsValue = $results['BoostMatchFieldsValue'];
             $searchPage->FacetFieldsValue = $results['FacetFieldsValue'];
             $searchPage->CustomFacetFieldsValue = $results['CustomFacetFieldsValue'];
             $searchPage->FacetMappingValue = $results['FacetMappingValue'];
             $searchPage->FacetQueriesValue = $results['FacetQueriesValue'];
             $searchPage->MinFacetCount = $results['MinFacetCount'];
             $searchPage->FilterFieldsValue = $results['FilterFieldsValue'];
             $searchPage->ListingTemplateID = $results['ListingTemplateID'];
             if (isset($relationships[$results['ID']])) {
                 $searchPage->SearchTrees()->add($relationships[$results['ID']]);
             }
             $searchPage->write();
             if ($searchPage->ID) {
                 echo "<strong>{$results['ID']}</strong> Saved<br>";
                 $writeCount++;
             }
         } else {
             $writeCount++;
         }
     }
     // Confirm that the current user had permission to write these new pages.
     $this->checkPermissions($queryCount, $writeCount);
     // Remove the previous search page tables, as they are now obsolete (and may not be marked as such).
     $remove = array('SiteTree', 'SiteTree_Live', 'Page', 'Page_Live');
     foreach ($remove as $table) {
         foreach ($created as $ID) {
             DB::query("DELETE FROM {$table} WHERE ID = {$ID}");
         }
     }
     $remove = array('SolrSearchPage', 'SolrSearchPage_Live', 'SolrSearchPage_SearchTrees', 'SolrSearchPage_versions');
     foreach ($remove as $table) {
         DB::query("DROP TABLE {$table}");
     }
     Versioned::set_reading_mode($readingMode);
     echo 'Migration Complete!';
 }
 /**
  * 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);
             }
         }
     }
 }
예제 #30
0
 /**
  * Publish this page.
  * 
  * @uses SiteTreeExtension->onBeforePublish()
  * @uses SiteTreeExtension->onAfterPublish()
  */
 public function doPublish()
 {
     if (!$this->canPublish()) {
         return false;
     }
     $original = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = {$this->ID}");
     if (!$original) {
         $original = new SiteTree();
     }
     // Handle activities undertaken by extensions
     $this->invokeWithExtensions('onBeforePublish', $original);
     //$this->PublishedByID = Member::currentUser()->ID;
     $this->write();
     $this->publish("Stage", "Live");
     DB::query("UPDATE \"SiteTree_Live\"\n\t\t\tSET \"Sort\" = (SELECT \"SiteTree\".\"Sort\" FROM \"SiteTree\" WHERE \"SiteTree_Live\".\"ID\" = \"SiteTree\".\"ID\")\n\t\t\tWHERE EXISTS (SELECT \"SiteTree\".\"Sort\" FROM \"SiteTree\" WHERE \"SiteTree_Live\".\"ID\" = \"SiteTree\".\"ID\") AND \"ParentID\" = " . sprintf('%d', $this->ParentID));
     // Publish any virtual pages that might need publishing
     $linkedPages = $this->VirtualPages();
     if ($linkedPages) {
         foreach ($linkedPages as $page) {
             $page->copyFrom($page->CopyContentFrom());
             $page->write();
             if ($page->ExistsOnLive) {
                 $page->doPublish();
             }
         }
     }
     // Need to update pages linking to this one as no longer broken, on the live site
     $origMode = Versioned::get_reading_mode();
     Versioned::reading_stage('Live');
     foreach ($this->DependentPages(false) as $page) {
         // $page->write() calls syncLinkTracking, which does all the hard work for us.
         $page->write();
     }
     Versioned::set_reading_mode($origMode);
     // Handle activities undertaken by extensions
     $this->invokeWithExtensions('onAfterPublish', $original);
     return true;
 }