title: silverstripe, how to use the doPublish()
body: <p>I am working with SilverStripe, and I am working on making a newspage. 
  I use the DataObjectAsPage Module( <a href="http://www.ssbits.com/tutorials/2012/dataobject-as-pages-the-module/" rel="nofollow">http://www.ssbits.com/tutorials/2012/dataobject-as-pages-the-module/</a> ), I got it working when I use the admin to publish newsitems. 
  Now I want to use the DataObjectManager Module instead of the admin module to manage my news items. But this is where the problem exists. Everything works fine in draft mode, I can make a new newsitem and it shows up in draft. But when I want to publish a newsitem, it won't show up in the live or published mode. </p>
  
  <p>I'm using the following tables:<br>
  -Dataobjectaspage table,<br>
  -Dataobjectaspage_live table,<br>
  -NewsArticle table,<br>
  -NewsArticle_Live table   </p>
  
  <p>The Articles have been inserted while publishing in the Dataobjectaspage table and in the NewsArticle table...   But not in the _Live tables...  </p>
  
  <p>Seems the doPublish() function hasn't been used while 'Publishing'. 
  So I'm trying the use the following:  </p>
  
  <pre><code>function onAfterWrite() {
      parent::onAfterWrite();   
      DataObjectAsPage::doPublish();
  }
  </code></pre>
  
  <p>But when I use this, it gets an error:
  <a href="http://i.imgur.com/pSDtR.png" rel="nofollow">here is this picture</a></p>
  
  <p>It seems to be in a loop....
  I've got the NewsArticle.php file where I use this function:  </p>
  
  <pre><code> function onAfterWrite() {
      parent::onAfterWrite();   
      DataObjectAsPage::doPublish();
  }
  </code></pre>
  
  <p>This function calls the DataObjectAsPage.php file and uses this code: </p>
  
  <pre><code>function doPublish() {
          if (!$this-&gt;canPublish()) return false;
  
          $original = Versioned::get_one_by_stage("DataObjectAsPage", "Live", "\"DataObjectAsPage\".\"ID\" = $this-&gt;ID");
          if(!$original) $original = new DataObjectAsPage();
  
          // Handle activities undertaken by decorators
          $this-&gt;invokeWithExtensions('onBeforePublish', $original);
          $this-&gt;Status = "Published";
          //$this-&gt;PublishedByID = Member::currentUser()-&gt;ID;
          $this-&gt;write();
          $this-&gt;publish("Stage", "Live");
  
          // Handle activities undertaken by decorators
          $this-&gt;invokeWithExtensions('onAfterPublish', $original);
  
          return true;
      }
  </code></pre>
  
  <p>And then it goes to DataObject.php file and uses the write function ():</p>
  
  <pre><code>public function write($showDebug = false, $forceInsert = false, $forceWrite = false, $writeComponents = false) {
      $firstWrite = false;
      $this-&gt;brokenOnWrite = true;
      $isNewRecord = false;
  
      if(self::get_validation_enabled()) {
          $valid = $this-&gt;validate();
          if(!$valid-&gt;valid()) {
              // Used by DODs to clean up after themselves, eg, Versioned
              $this-&gt;extend('onAfterSkippedWrite');
              throw new ValidationException($valid, "Validation error writing a $this-&gt;class object: " . $valid-&gt;message() . ".  Object not written.", E_USER_WARNING);
              return false;
          }
      }
  
      $this-&gt;onBeforeWrite();
      if($this-&gt;brokenOnWrite) {
          user_error("$this-&gt;class has a broken onBeforeWrite() function.  Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);
      }
  
      // New record = everything has changed
  
      if(($this-&gt;ID &amp;&amp; is_numeric($this-&gt;ID)) &amp;&amp; !$forceInsert) {
          $dbCommand = 'update';
  
          // Update the changed array with references to changed obj-fields
          foreach($this-&gt;record as $k =&gt; $v) {
              if(is_object($v) &amp;&amp; method_exists($v, 'isChanged') &amp;&amp; $v-&gt;isChanged()) {
                  $this-&gt;changed[$k] = true;
              }
          }
  
      } else{
          $dbCommand = 'insert';
  
          $this-&gt;changed = array();
          foreach($this-&gt;record as $k =&gt; $v) {
              $this-&gt;changed[$k] = 2;
          }
  
          $firstWrite = true;
      }
  
      // No changes made
      if($this-&gt;changed) {
          foreach($this-&gt;getClassAncestry() as $ancestor) {
              if(self::has_own_table($ancestor))
              $ancestry[] = $ancestor;
          }
  
          // Look for some changes to make
          if(!$forceInsert) unset($this-&gt;changed['ID']);
  
          $hasChanges = false;
          foreach($this-&gt;changed as $fieldName =&gt; $changed) {
              if($changed) {
                  $hasChanges = true;
                  break;
              }
          }
  
          if($hasChanges || $forceWrite || !$this-&gt;record['ID']) {
  
              // New records have their insert into the base data table done first, so that they can pass the
              // generated primary key on to the rest of the manipulation
              $baseTable = $ancestry[0];
  
              if((!isset($this-&gt;record['ID']) || !$this-&gt;record['ID']) &amp;&amp; isset($ancestry[0])) {  
  
                  DB::query("INSERT INTO \"{$baseTable}\" (\"Created\") VALUES (" . DB::getConn()-&gt;now() . ")");
                  $this-&gt;record['ID'] = DB::getGeneratedID($baseTable);
                  $this-&gt;changed['ID'] = 2;
  
                  $isNewRecord = true;
              }
  
              // Divvy up field saving into a number of database manipulations
              $manipulation = array();
              if(isset($ancestry) &amp;&amp; is_array($ancestry)) {
                  foreach($ancestry as $idx =&gt; $class) {
                      $classSingleton = singleton($class);
  
                      foreach($this-&gt;record as $fieldName =&gt; $fieldValue) {
                          if(isset($this-&gt;changed[$fieldName]) &amp;&amp; $this-&gt;changed[$fieldName] &amp;&amp; $fieldType = $classSingleton-&gt;hasOwnTableDatabaseField($fieldName)) {
                              $fieldObj = $this-&gt;dbObject($fieldName);
                              if(!isset($manipulation[$class])) $manipulation[$class] = array();
  
                              // if database column doesn't correlate to a DBField instance...
                              if(!$fieldObj) {
                                  $fieldObj = DBField::create('Varchar', $this-&gt;record[$fieldName], $fieldName);
                              }
  
                              // Both CompositeDBFields and regular fields need to be repopulated
                              $fieldObj-&gt;setValue($this-&gt;record[$fieldName], $this-&gt;record);
  
                              if($class != $baseTable || $fieldName!='ID')
                                  $fieldObj-&gt;writeToManipulation($manipulation[$class]);
                          }
                      }
  
                      // Add the class name to the base object
                      if($idx == 0) {
                          $manipulation[$class]['fields']["LastEdited"] = "'".SS_Datetime::now()-&gt;Rfc2822()."'";
                          if($dbCommand == 'insert') {
                              $manipulation[$class]['fields']["Created"] = "'".SS_Datetime::now()-&gt;Rfc2822()."'";
                              //echo "&lt;li&gt;$this-&gt;class - " .get_class($this);
                              $manipulation[$class]['fields']["ClassName"] = "'$this-&gt;class'";
                          }
                      }
  
                      // In cases where there are no fields, this 'stub' will get picked up on
                      if(self::has_own_table($class)) {
                          $manipulation[$class]['command'] = $dbCommand;
                          $manipulation[$class]['id'] = $this-&gt;record['ID'];
                      } else {
                          unset($manipulation[$class]);
                      }
                  }
              }
              $this-&gt;extend('augmentWrite', $manipulation);
  
              // New records have their insert into the base data table done first, so that they can pass the
              // generated ID on to the rest of the manipulation
              if(isset($isNewRecord) &amp;&amp; $isNewRecord &amp;&amp; isset($manipulation[$baseTable])) {
                  $manipulation[$baseTable]['command'] = 'update';
              }
  
              DB::manipulate($manipulation);
  
              if(isset($isNewRecord) &amp;&amp; $isNewRecord) {
                  DataObjectLog::addedObject($this);
              } else {
                  DataObjectLog::changedObject($this);
              }
  
              $this-&gt;onAfterWrite();
  
              $this-&gt;changed = null;
          } elseif ( $showDebug ) {
              echo "&lt;b&gt;Debug:&lt;/b&gt; no changes for DataObject&lt;br /&gt;";
              // Used by DODs to clean up after themselves, eg, Versioned
              $this-&gt;extend('onAfterSkippedWrite');
          }
  
          // Clears the cache for this object so get_one returns the correct object.
          $this-&gt;flushCache();
  
          if(!isset($this-&gt;record['Created'])) {
              $this-&gt;record['Created'] = SS_Datetime::now()-&gt;Rfc2822();
          }
          $this-&gt;record['LastEdited'] = SS_Datetime::now()-&gt;Rfc2822();
      } else {
          // Used by DODs to clean up after themselves, eg, Versioned
          $this-&gt;extend('onAfterSkippedWrite');
      }
  
      // Write ComponentSets as necessary
      if($writeComponents) {
          $this-&gt;writeComponents(true);
      }
      return $this-&gt;record['ID'];
  }
  </code></pre>
  
  <p>Look at the $this->onAfterWrite();<br>
  It probably goes to my own function on NewsArticle.php and there starts the loop!    I'm not sure though, so i could need some help!!   </p>
  
  <p>Does anyone knows how to use the doPublish() function?</p>