[Solar-svn] Revision 2763

pmjones at solarphp.com pmjones at solarphp.com
Thu Sep 20 13:23:45 CDT 2007


branch: Model and Record changes

Solar_Sql_Model
---------------

* [CHG] Methods insert(), update(), and delete() now accept a Record object
  instead of only an array, and work just as with insertRecord() et al. from
  previous versions.

* [CHG] Methods insert() and update(), when a Record object is passed in, now
  call the filter() method on that Record.


Solar_Sql_Model_Record
----------------------

* [CHG] Method load() now completely overrides the parent method.  Put 
  unserializing back in, reordered internal logic a bit.

* [CHG] Methods _insert()/_update()/delete() internal logic is somewhat
  modified to go with new Model code.

* [BRK] Renamed all validate() methods to filter() (_preFilter(), filter(), and
  _postFilter()).

* [BRK] Methods _serializeCols() and _unserializeCols() are now public, and no
  longer have the underscore prefix.





Modified: branches/orm/Solar/Sql/Model/Record.php
===================================================================
--- branches/orm/Solar/Sql/Model/Record.php	2007-09-20 18:13:11 UTC (rev 2762)
+++ branches/orm/Solar/Sql/Model/Record.php	2007-09-20 18:23:45 UTC (rev 2763)
@@ -240,6 +240,8 @@
      * 
      * Also unserializes columns per the "serialize_cols" model property.
      * 
+     * This is a complete override from the parent load() method.
+     * 
      * @param array|Solar_Struct $spec The data to load into the object.
      * 
      * @param array $cols Load only these columns.
@@ -249,29 +251,44 @@
      */
     public function load($spec, $cols = null)
     {
+        // force to array
+        if ($spec instanceof Solar_Struct) {
+            // we can do this because $spec is of the same class
+            $data = $spec->_data;
+        } elseif (is_array($spec)) {
+            $data = $spec;
+        } else {
+            $data = array();
+        }
+        
         // remove columns not in the whitelist
         if (! empty($cols)) {
             $cols = (array) $cols;
-            foreach ($spec as $key => $val) {
+            foreach ($data as $key => $val) {
                 if (! in_array($key, $cols)) {
-                    unset($spec[$key]);
+                    unset($data[$key]);
                 }
             }
         }
         
-        // do the "real" load
-        parent::load($spec);
-        
-        // pull out belongs_to/has_one related data
-        foreach ($this->_data as $key => $val) {
+        // pull out belongs_to/has_one related data.
+        foreach ($data as $key => $val) {
             // if the key has double-underscores, it's an eager-load record.
             if (strpos($key, '__') !== false) {
                 list($rel_name, $rel_key) = explode('__', $key);
                 $this->_data[$rel_name][$rel_key] = $val;
-                unset($this->_data[$key]);
+                unset($data[$key]);
             }
         }
         
+        // unserialize as needed, then add remaining "real" columns.
+        // it's not enough to just merge the data.  although slower, we need
+        // to loop so that __set() is honored.
+        $this->_model->unserializeCols($data);
+        foreach ($data as $key => $val) {
+            $this->$key = $val;
+        }
+        
         // load related data as records and collections
         foreach ($this->_model->related as $name => $opts) {
             
@@ -504,56 +521,32 @@
     
     protected function _insert()
     {
-        // filter the data (sanitize and validate)
-        $this->_preValidate();
-        $this->validate();
-        $this->_postValidate();
-        
-        // convert to array for the SQL command
-        $data = $this->toArray();
-        
-        // attempt to insert the record, and catch SQL exceptions.
         try {
-            // pre-logic, insert, reload, status, post-logic
             $this->_preInsert();
-            $result = $this->_model->insert($data);
-            $this->load($result);
+            $this->_model->insert($this);
             $this->setStatus('inserted');
             $this->_postInsert();
         } catch (Solar_Sql_Adapter_Exception_QueryFailed $e) {
-            // something went wrong at the database
+            // failed at at the database for some reason
             $this->setStatus('invalid');
             $this->setInvalid('*', $e->getInfo('pdo_text'));
+            throw $e;
         }
     }
     
     protected function _update()
     {
-        // filter the data (sanitize and validate)
-        $this->_preValidate();
-        $this->validate();
-        $this->_postValidate();
-        
-        // convert to array for the SQL command
-        $data = $this->toArray();
-        
-        // remove primary-key column from the data and build a WHERE clause
-        $primary = $this->_model->primary_col;
-        unset($data[$primary]);
-        $where = array("$primary = ?" => $this->$primary);
-        
-        // attempt the update logic
         try {
-            // pre-logic, insert, reload, status, post-logic
             $this->_preUpdate();
-            $result = $this->_model->update($data, $where);
-            $this->load($result);
+            $where = null;
+            $this->_model->update($this, $where);
             $this->setStatus('updated');
             $this->_postUpdate();
         } catch (Solar_Sql_Adapter_Exception_QueryFailed $e) {
-            // something went wrong at the database
+            // failed at at the database for some reason
             $this->setStatus('invalid');
             $this->setInvalid('*', $e->getInfo('pdo_text'));
+            throw $e;
         }
     }
     
@@ -581,11 +574,11 @@
     {
     }
     
-    protected function _preValidate()
+    protected function _preFilter()
     {
     }
     
-    protected function _postValidate()
+    protected function _postFilter()
     {
     }
     
@@ -599,12 +592,8 @@
     public function delete()
     {
         $this->_checkDeleted();
-        
-        $primary = $this->_model->primary_col;
-        $where = array("$primary = ?" => $this->$primary);
-        
         $this->_preDelete();
-        $this->_model->delete($where);
+        $this->_model->delete($this);
         $this->_postDelete();
     }
     
@@ -776,13 +765,15 @@
     
     /**
      * 
-     * Validate and sanitize the data.
+     * Filter the data.
      * 
-     * @return bool
+     * @return void
      * 
      */
-    public function validate()
+    public function filter()
     {
+        $this->_preFilter();
+        
         // create a filter object based on the model's filter class
         $filter = Solar::factory($this->_model->filter_class);
         
@@ -819,7 +810,8 @@
             throw $this->_exception('ERR_INVALID', array($this->_invalid));
         }
         
-        return $valid;
+        // post-logic, and done
+        $this->_postFilter();
     }
     
     public function form($cols = null)

Modified: branches/orm/Solar/Sql/Model.php
===================================================================
--- branches/orm/Solar/Sql/Model.php	2007-09-20 18:13:11 UTC (rev 2762)
+++ branches/orm/Solar/Sql/Model.php	2007-09-20 18:23:45 UTC (rev 2763)
@@ -1601,72 +1601,89 @@
      * 
      * Inserts one row to the model table.
      * 
-     * While this method automatically sets some values, and handles 
-     * serializing of columns where requested, it *does not* validate the
-     * data in any way.
+     * @param array|Solar_Sql_Model_Record $spec The row data to insert.
      * 
-     * @param array|Solar_Struct $data The row data to insert.
+     * @return array The data as inserted, including auto-incremented values,
+     * auto-sequence values, created/updated/inherit values, etc.
      * 
-     * @return array The data as inserted, including auto-increment value if
-     * one is defined.
-     * 
      */
-    public function insert($data)
+    public function insert($spec)
     {
-        // make sure we have an array
-        if ($data instanceof Solar_Struct) {
-            $data = $data->toArray();
-        } else {
-            $data = (array) $data;
+        if (! is_array($spec) && ! ($spec instanceof Solar_Sql_Model_Record)) {
+            throw $this->_exception('ERR_NOT_ARRAY_OR_RECORD');
         }
         
-        // remove non-existent table columns from the data
-        foreach ($data as $key => $val) {
-            if (empty($this->_table_cols[$key])) {
-                unset($data[$key]);
-            }
-            
-            // remove empty autoinc columns to soothe postgres, which won't
-            // take explicit NULLs in SERIAL cols.
-            if ($this->_table_cols[$key]['autoinc'] && empty($val)) {
-                unset($data[$key]);
-            }
-        }
-        
+        /**
+         * Force or auto-set special columns
+         */
         // force the 'created' value if there is a 'created' column
         $now = date('Y-m-d H:i:s');
         $key = $this->_created_col;
         if ($key) {
-            $data[$key] = $now;
+            $spec[$key] = $now;
         }
         
         // force the 'updated' value if there is an 'updated' column (same as
         // the 'created' timestamp)
         $key = $this->_updated_col;
         if ($key) {
-            $data[$key] = $now;
+            $spec[$key] = $now;
         }
         
         // if inheritance is turned on, auto-set the inheritance value,
         // if not already set.
         $key = $this->_inherit_col;
-        if ($key && $this->_inherit_model && empty($data[$key])) {
-            $data[$key] = $this->_inherit_model;
+        if ($key && $this->_inherit_model && empty($spec[$key])) {
+            $spec[$key] = $this->_inherit_model;
         }
         
         // auto-set sequence values if needed
         foreach ($this->_sequence_cols as $key => $val) {
-            if (empty($data[$key])) {
+            if (empty($spec[$key])) {
                 // no value given for the key.
                 // add a new sequence value.
-                $data[$key] = $this->_sql->nextSequence($val);
+                $spec[$key] = $this->_sql->nextSequence($val);
             }
         }
         
-        // serialize cols and insert
-        $this->_serializeCols($data);
+        /**
+         * Record filtering
+         */
+        if ($spec instanceof Solar_Sql_Model_Record) {
+            // apply record filters and convert to array
+            $spec->filter();
+            $data = $spec->toArray();
+        } else {
+            // already an array
+            $data = $spec;
+        }
+        
+        /**
+         * Final prep, then insert
+         */
+        // remove non-existent table columns from the data
+        foreach ($data as $key => $val) {
+            if (empty($this->_table_cols[$key])) {
+                unset($data[$key]);
+                // not in the table, so no need to check for autoinc
+                continue;
+            }
+            
+            // remove empty autoinc columns to soothe postgres, which won't
+            // take explicit NULLs in SERIAL cols.
+            if ($this->_table_cols[$key]['autoinc'] && empty($val)) {
+                unset($data[$key]);
+            }
+        }
+        
+        // do the insert
+        $this->serializeCols($data);
         $this->_sql->insert($this->_table_name, $data);
+        $this->unserializeCols($data);
         
+        /**
+         * Post-insert
+         */
         // no exception thrown, so it must have worked.
         // if there was an autoincrement column, set its value in the data.
         foreach ($this->_table_cols as $key => $val) {
@@ -1677,8 +1694,12 @@
             }
         }
         
-        // unserialize cols and return the data as inserted
-        $this->_unserializeCols($data);
+        // reload the data into the record if needed
+        if ($spec instanceof Solar_Sql_Model_Record) {
+            $spec->load($data);
+        }
+        
+        // return the data as inserted
         return $data;
     }
     
@@ -1686,62 +1707,87 @@
      * 
      * Updates rows in the model table.
      * 
-     * While this method automatically sets some values, and handles 
-     * serializing of columns where requested, it *does not* validate the
-     * data in any way.
+     * @param array|Solar_Sql_Model_Record $spec The row data to insert.
      * 
-     * @param array|Solar_Struct $data The row data to insert.
-     * 
      * @param string|array $where The WHERE clause to identify which rows to 
      * update.
      * 
      * @return array The data as updated.
      * 
      */
-    public function update($data, $where)
+    public function update($spec, $where)
     {
-        // make sure we have an array
-        if ($data instanceof Solar_Struct) {
-            $data = $data->toArray();
-        } else {
-            $data = (array) $data;
+        if (! is_array($spec) && ! ($spec instanceof Solar_Sql_Model_Record)) {
+            throw $this->_exception('ERR_NOT_ARRAY_OR_RECORD');
         }
         
-        // remove non-existent table columns from the data
-        foreach ($data as $key => $val) {
-            if (empty($this->_table_cols[$key])) {
-                unset($data[$key]);
-            }
-        }
-        
+        /**
+         * Force or auto-set special columns
+         */
         // force the 'updated' value
         $key = $this->_updated_col;
         if ($key) {
-            $data[$key] = date('Y-m-d H:i:s');
+            $spec[$key] = date('Y-m-d H:i:s');
         }
         
         // if inheritance is turned on, auto-set the inheritance value,
         // if not already set.
         $key = $this->_inherit_col;
         if ($key && $this->_inherit_model && empty($this->$key)) {
-            $data[$key] = $this->_inherit_model;
+            $spec[$key] = $this->_inherit_model;
         }
         
         // auto-set sequences where keys exist and values are empty
         foreach ($this->_sequence_cols as $key => $val) {
-            if (array_key_exists($key, $data) && empty($data[$key])) {
+            // hack to to account for arrays *and* Record/Struct objects
+            $exists = array_key_exists($key, $spec) || isset($spec[$key]);
+            if ($exists && empty($spec[$key])) {
                 // key is present but no value is given.
                 // add a new sequence value.
-                $data[$key] = $this->_sql->nextSequence($val);
+                $spec[$key] = $this->_sql->nextSequence($val);
             }
         }
         
-        // serialize cols and do the update
-        $this->_serializeCols($data);
+        /**
+         * Record filtering and WHERE clause
+         */
+        if ($spec instanceof Solar_Sql_Model_Record) {
+            // apply record filters and convert to array
+            $spec->filter();
+            $data = $spec->toArray();
+            
+            // force the WHERE clause
+            $primary = $this->_primary_col;
+            $where = array("$primary = ?" => $data[$primary]);
+            
+            // don't update the primary key
+            unset($data[$primary]);
+        } else {
+            // already an array
+            $data = $spec;
+        }
+        
+        /**
+         * Final prep, then update
+         */
+        // remove non-existent table columns from the data
+        foreach ($data as $key => $val) {
+            if (empty($this->_table_cols[$key])) {
+                unset($data[$key]);
+            }
+        }
+        
+        // perform the update
+        $this->serializeCols($data);
         $this->_sql->update($this->_table_name, $data, $where);
+        $this->unserializeCols($data);
         
+        // reload the data into the record if needed
+        if ($spec instanceof Solar_Sql_Model_Record) {
+            $spec->load($data);
+        }
+        
         // unserialize cols and return the data as updated
-        $this->_unserializeCols($data);
         return $data;
     }
     
@@ -1749,14 +1795,21 @@
      * 
      * Deletes rows from the model table.
      * 
-     * @param string|array $where The WHERE clause to identify which rows to 
-     * delete.
+     * @param string|array|Solar_Sql_Model_Record $spec The WHERE clause to
+     * identify which rows to delete, or a record to delete.
      * 
-     * @return array The data as updated.
+     * @return void
      * 
      */
-    public function delete($where)
+    public function delete($spec)
     {
+        if ($spec instanceof Solar_Sql_Model_Record) {
+            $primary = $this->_primary_col;
+            $where = array("$primary = ?" => $spec->$primary);
+        } else {
+            $where = $spec;
+        }
+        
         return $this->_sql->delete($this->_table_name, $where);
     }
     
@@ -1773,7 +1826,7 @@
      * @return void
      * 
      */
-    protected function _serializeCols(&$data)
+    public function serializeCols(&$data)
     {
         foreach ($this->_serialize_cols as $key) {
             if (! empty($data[$key]) && $data[$key] !== null) {
@@ -1799,7 +1852,7 @@
      * @return void
      * 
      */
-    protected function _unserializeCols(&$data)
+    public function unserializeCols(&$data)
     {
         // unseralize columns as-needed
         foreach ($this->_serialize_cols as $key) {




More information about the Solar-svn mailing list