diff options
Diffstat (limited to 'framework/Data/ActiveRecord')
6 files changed, 123 insertions, 9 deletions
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php index a792aeb9..14b4098a 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php @@ -17,9 +17,11 @@ Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase'); /**
* Template control for editing an Active Record instance.
+ * The <b>RecordClass</b> determines the Active Record class to be edited.
+ * A particular record can be edited by specifying the {@link setRecordPk RecordPk}
+ * value (may be an array for composite keys).
*
* The default editor input controls are created based on the column types.
- *
* The editor layout can be specified by a renderer. A renderer is an external
* template control that implements IScaffoldEditRenderer.
*
@@ -33,9 +35,10 @@ Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase'); * (the edit view instance is the <b>Parent</b> of the IScaffoldEditRenderer in most
* cases.
*
- * The <b>RecordClass</b> determines the Active Record class to be edited.
- * A particular record can be edited by specifying the {@link setRecordPk RecordPk}
- * value (may be an array for composite keys).
+ * Cosmetic changes to the default editor should be done using Cascading Stylesheets.
+ * For example, a particular field/property can be hidden by specifying "display:none" for
+ * the corresponding style (each field/property has unique Css class name as "property_xxx", where
+ * xxx is the property name).
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @version $Id$
diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php index 2ac3fe99..62bf351b 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldListView.php @@ -16,7 +16,15 @@ Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase');
/**
- * TScaffoldListView displays instance of Active Record class.
+ * TScaffoldListView displays a list of Active Records.
+ *
+ * The {@link getHeader Header} property is a TRepeater displaying the
+ * Active Record property/field names. The {@link getSort Sort} property
+ * is a drop down list displaying the combination of properties and its possible
+ * ordering. The {@link getPager Pager} property is a TPager control that
+ * determines the number of records display in one page (e.g. Page..
+ *
+ *
*
* @author Wei Zhuo <weizho[at]gmail[dot]com>
* @version $Id$
@@ -25,6 +33,9 @@ Prado::using('System.Data.ActiveRecord.Scaffold.TScaffoldBase'); */
class TScaffoldListView extends TScaffoldBase
{
+ /**
+ * Initialize the sort drop down list in non post back mode (i.e. GET requests).
+ */
public function onLoad($param)
{
parent::onLoad($param);
@@ -32,6 +43,9 @@ class TScaffoldListView extends TScaffoldBase $this->initializeSort();
}
+ /**
+ * Initialize the sort drop down list and the column names repeater.
+ */
protected function initializeSort()
{
$table = $this->getTableMetaData();
@@ -50,12 +64,18 @@ class TScaffoldListView extends TScaffoldBase $this->_header->dataBind();
}
+ /**
+ * Loads and display the data.
+ */
public function onPreRender($param)
{
parent::onPreRender($param);
$this->loadRecordData();
}
+ /**
+ * Fetch the records and data bind it to the list.
+ */
protected function loadRecordData()
{
$this->_list->setVirtualItemCount($this->getRecordFinder()->count());
@@ -65,6 +85,9 @@ class TScaffoldListView extends TScaffoldBase $this->_list->dataBind();
}
+ /**
+ * @return TActiveRecordCriteria sort/search/paging criteria
+ */
protected function getRecordCriteria()
{
$total = $this->_list->getVirtualItemCount();
@@ -81,26 +104,41 @@ class TScaffoldListView extends TScaffoldBase return $criteria;
}
+ /**
+ * @param string search condition, the SQL string after the WHERE clause.
+ */
public function setSearchCondition($value)
{
$this->setViewState('SearchCondition', $value);
}
+ /**
+ * @param string SQL search condition for list display.
+ */
public function getSearchCondition()
{
return $this->getViewState('SearchCondition');
}
+ /**
+ * @param array search parameters
+ */
public function setSearchParameters($value)
{
$this->setViewState('SearchParameters', TPropertyValue::ensureArray($value),array());
}
+ /**
+ * @return array search parameters
+ */
public function getSearchParameters()
{
return $this->getViewState('SearchParameters', array());
}
+ /**
+ * Continue bubbling the "edit" command, "delete" command is handled in this class.
+ */
public function bubbleEvent($sender, $param)
{
switch(strtolower($param->getCommandName()))
@@ -114,6 +152,9 @@ class TScaffoldListView extends TScaffoldBase return true;
}
+ /**
+ * Initialize the edit view control form when EditViewID is set.
+ */
protected function initializeEdit($sender, $param)
{
if(($ctrl=$this->getEditViewControl())!==null)
@@ -127,6 +168,9 @@ class TScaffoldListView extends TScaffoldBase }
}
+ /**
+ * Deletes an Active Record.
+ */
protected function deleteRecord($sender, $param)
{
if($param instanceof TRepeaterCommandEventParameter)
@@ -136,6 +180,9 @@ class TScaffoldListView extends TScaffoldBase }
}
+ /**
+ * Initialize the default display for each Active Record item.
+ */
protected function listItemCreated($sender, $param)
{
$item = $param->getItem();
@@ -147,6 +194,10 @@ class TScaffoldListView extends TScaffoldBase }
}
+ /**
+ * Sets the Record primary key to the current repeater item's CustomData.
+ * Binds the inner repeater with properties of the current Active Record.
+ */
protected function populateField($sender, $param)
{
$item = $param->getItem();
@@ -161,45 +212,69 @@ class TScaffoldListView extends TScaffoldBase }
}
+ /**
+ * Updates repeater page index with the pager new index value.
+ */
protected function pageChanged($sender, $param)
{
$this->_list->setCurrentPageIndex($param->getNewPageIndex());
}
+ /**
+ * @return TRepeater Repeater control for Active Record instances.
+ */
public function getList()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_list');
}
+ /**
+ * @return TPager List pager control.
+ */
public function getPager()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_pager');
}
+ /**
+ * @return TDropDownList Control that displays and controls the record ordering.
+ */
public function getSort()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_sort');
}
+ /**
+ * @return TRepeater Repeater control for record property names.
+ */
public function getHeader()
{
$this->ensureChildControls();
return $this->getRegisteredObject('_header');
}
+ /**
+ * @return string TScaffoldEditView control ID for editing selected Active Record.
+ */
public function getEditViewID()
{
return $this->getViewState('EditViewID');
}
+ /**
+ * @param string TScaffoldEditView control ID for editing selected Active Record.
+ */
public function setEditViewID($value)
{
$this->setViewState('EditViewID', $value);
}
+ /**
+ * @return TScaffoldEditView control for editing selected Active Record, null if EditViewID is not set.
+ */
protected function getEditViewControl()
{
if(($id=$this->getEditViewID())!==null)
diff --git a/framework/Data/ActiveRecord/TActiveRecord.php b/framework/Data/ActiveRecord/TActiveRecord.php index bdb03596..ea33035d 100644 --- a/framework/Data/ActiveRecord/TActiveRecord.php +++ b/framework/Data/ActiveRecord/TActiveRecord.php @@ -172,6 +172,16 @@ abstract class TActiveRecord extends TComponent */
public function save()
{
+ $this->commitChanges();
+ }
+
+ /**
+ * Commit changes to the record, may insert, update or delete depending
+ * on the record state given in TObjectStateRegistery.
+ * @return boolean true if changes were made.
+ */
+ protected function commitChanges()
+ {
$registry = $this->getRecordManager()->getObjectStateRegistry();
$gateway = $this->getRecordManager()->getRecordGateway();
if(!$this->_readOnly)
@@ -190,7 +200,7 @@ abstract class TActiveRecord extends TComponent {
$registry = $this->getRecordManager()->getObjectStateRegistry();
$registry->registerRemoved($this);
- return $this->save();
+ return $this->commitChanges();
}
/**
diff --git a/framework/Data/ActiveRecord/TActiveRecordCriteria.php b/framework/Data/ActiveRecord/TActiveRecordCriteria.php index 968a2691..6adfe4ce 100644 --- a/framework/Data/ActiveRecord/TActiveRecordCriteria.php +++ b/framework/Data/ActiveRecord/TActiveRecordCriteria.php @@ -153,6 +153,11 @@ class TActiveRecordCriteria extends TComponent {
return $this->getCondition();
}
+
+ public function repr()
+ {
+ return var_export($this->getParameters()->toArray(),true);
+ }
}
?>
\ No newline at end of file diff --git a/framework/Data/ActiveRecord/TActiveRecordGateway.php b/framework/Data/ActiveRecord/TActiveRecordGateway.php index 7bcd0eb2..1486e9c3 100644 --- a/framework/Data/ActiveRecord/TActiveRecordGateway.php +++ b/framework/Data/ActiveRecord/TActiveRecordGateway.php @@ -143,11 +143,12 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getFindByPkCommand($record->getDbConnection(),$keys);
$this->raiseCommandEvent(TActiveRecordStatementType::Select,$command,$record,$keys);
+ Prado::trace(get_class($record).'::FindRecordByPk('.var_export($keys,true).')', 'System.Data.ActiveRecord');
return $meta->postQueryRow($command->queryRow());
}
/**
- * Returns records matching the list of given primary keys.
+ * Returns records matching the list of given primary keys.
* @param TActiveRecord active record instance.
* @param array list of primary name value pairs
* @return array matching data.
@@ -157,9 +158,10 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getFindInPksCommand($record->getDbConnection(), $keys);
$this->raiseCommandEvent(TActiveRecordStatementType::Select,$command,$record,$keys);
+ Prado::trace(get_class($record).'::FindRecordsByPks('.var_export($keys,true).')', 'System.Data.ActiveRecord');
return $meta->postQuery($command->query());
}
-
+
/**
* Returns record data matching the given critera. If $iterator is true, it will
@@ -174,6 +176,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getFindByCriteriaCommand($record->getDbConnection(),$criteria);
$this->raiseCommandEvent(TActiveRecordStatementType::Select,$command,$record,$criteria);
+ Prado::trace(get_class($record).'::FindRecordsByCriteria('.is_string($criteria) ? $criteria : $criteria->repr().')', 'System.Data.ActiveRecord');
return $iterator ? $meta->postQuery($command->query()) : $meta->postQueryRow($command->queryRow());
}
@@ -189,6 +192,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getFindBySqlCommand($record->getDbConnection(),$sql,$parameters);
$this->raiseCommandEvent(TActiveRecordStatementType::Select,$command,$record,$parameters);
+ Prado::trace(get_class($record).'::FindRecordsBySql('.var_export($parameters,true).')', 'System.Data.ActiveRecord');
return $meta->postQuery($command->query());
}
@@ -203,6 +207,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getCountRecordsCommand($record->getDbConnection(),$criteria);
$this->raiseCommandEvent(TActiveRecordStatementType::Select,$command,$record,$criteria);
+ Prado::trace(get_class($record).'::CountRecords('.is_string($criteria) ? $criteria : $criteria->repr().')', 'System.Data.ActiveRecord');
return intval($command->queryScalar());
}
@@ -216,6 +221,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getInsertCommand($record->getDbConnection(),$record);
$this->raiseCommandEvent(TActiveRecordStatementType::Insert,$command,$record);
+ Prado::trace(get_class($record).'::Insert()', 'System.Data.ActiveRecord');
$rowsAffected = $command->execute();
if($rowsAffected===1)
$meta->updatePostInsert($record->getDbConnection(),$record);
@@ -232,6 +238,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getUpdateCommand($record->getDbConnection(),$record);
$this->raiseCommandEvent(TActiveRecordStatementType::Update,$command,$record);
+ Prado::trace(get_class($record).'::Update()', 'System.Data.ActiveRecord');
return $command->execute();
}
@@ -245,6 +252,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getDeleteCommand($record->getDbConnection(),$record);
$this->raiseCommandEvent(TActiveRecordStatementType::Delete,$command,$record);
+ Prado::trace(get_class($record).'::Delete()', 'System.Data.ActiveRecord');
return $command->execute();
}
@@ -258,6 +266,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getDeleteByPkCommand($record->getDBConnection(),$keys);
$this->raiseCommandEvent(TActiveRecordStatementType::Delete,$command,$record,$keys);
+ Prado::trace(get_class($record).'::DeleteRecordsByPk('.var_export($keys,true).')', 'System.Data.ActiveRecord');
return $command->execute();
}
@@ -272,6 +281,7 @@ class TActiveRecordGateway extends TComponent $meta = $this->getMetaData($record);
$command = $meta->getDeleteByCriteriaCommand($record->getDBConnection(),$criteria);
$this->raiseCommandEvent(TActiveRecordStatementType::Delete,$command,$record,$criteria);
+ Prado::trace(get_class($record).'::DeleteRecordsByCriteria('.is_string($criteria) ? $criteria : $criteria->repr().')', 'System.Data.ActiveRecord');
return $command->execute();
}
diff --git a/framework/Data/ActiveRecord/Vendor/TDbMetaData.php b/framework/Data/ActiveRecord/Vendor/TDbMetaData.php index 3a959ba4..a3a13120 100644 --- a/framework/Data/ActiveRecord/Vendor/TDbMetaData.php +++ b/framework/Data/ActiveRecord/Vendor/TDbMetaData.php @@ -212,15 +212,26 @@ abstract class TDbMetaData extends TComponent /**
* Gets the columns that can be inserted into the database.
+ * Missing properties are assumed to be null.
* @param TActiveRecord record object to be inserted.
* @return array name value pairs of fields to be added.
+ * @throws TActiveRecordException if property is null and table column is
+ * defined as not null unless primary key column.
*/
protected function getInsertableColumns($record)
{
$columns = array();
foreach($this->getColumns() as $name=>$column)
{
- $value = $record->{$name};
+ try
+ {
+ $value = $record->{$name};
+ }
+ catch (TInvalidOperationException $e) //ignore missing properties
+ {
+ $value = null;
+ }
+
if($column->getNotNull() && $value===null && !$column->getIsPrimaryKey())
{
throw new TActiveRecordException(
|