TRangeValidator verifies whether an input value is within a specified range. TRangeValidator uses three key properties to perform its validation. The MinValue and MaxValue properties specify the minimum and maximum values of the valid range. The DataType property specifies the data type of the value being validated. The value will be first converted into the specified type and then compare with the valid range. The data types that can be checked against are the same as those in TCompareValidator.
+ ++If StrictComparison property is set to true, then the ranges +are compared as strictly less than the MaxValue and/or strictly greater than the +MinValue. +
+N.B. If validating against a TDatePicker the DataType must be equal to "Date" and the DateFormat property of the validator must be equal to the DateFormat of the TDatePicker.
diff --git a/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php b/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php index 45a575dd..8654c35c 100644 --- a/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php +++ b/framework/Data/ActiveRecord/Exceptions/TActiveRecordException.php @@ -18,7 +18,7 @@ * @package System.Data.ActiveRecord * @since 3.1 */ -class TActiveRecordException extends TException +class TActiveRecordException extends TDbException { /** * @return string path to the error message file diff --git a/framework/Data/ActiveRecord/Exceptions/messages.txt b/framework/Data/ActiveRecord/Exceptions/messages.txt index 9ab1693e..b3d567e4 100644 --- a/framework/Data/ActiveRecord/Exceptions/messages.txt +++ b/framework/Data/ActiveRecord/Exceptions/messages.txt @@ -16,4 +16,5 @@ ar_pk_value_count_mismatch = Composite key value count mismatch in forming I ar_must_copy_from_array_or_object = $data in {0}::copyFrom($data) must be an object or an array. ar_mismatch_column_names = In dynamic __call() method '{0}', no matching columns were found, valid columns for table '{2}' are '{1}'. ar_invalid_table = Missing, invalid or no permission for table/view '{0}'. -ar_invalid_finder_class_name = Class name for finder($className) method must not be 'TActiveRecord', you should override the finder() method in your record class or pass in a valid record class name. \ No newline at end of file +ar_invalid_finder_class_name = Class name for finder($className) method must not be 'TActiveRecord', you should override the finder() method in your record class or pass in a valid record class name. +ar_invalid_criteria = Invalid criteria object, must be a string or instance of TSqlCriteria. diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php index ada2091e..2c315468 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TIbmScaffoldInput.php @@ -13,7 +13,7 @@ class TIbmScaffoldInput extends TScaffoldInputCommon { protected function createControl($container, $column, $record) { - switch(strtolower($column->getType())) + switch(strtolower($column->getDbType())) { case 'date': return $this->createDateControl($container, $column, $record); @@ -34,7 +34,7 @@ class TIbmScaffoldInput extends TScaffoldInputCommon protected function getControlValue($container, $column, $record) { - switch(strtolower($column->getType())) + switch(strtolower($column->getDbType())) { case 'date': return $container->findControl(self::DEFAULT_ID)->getDate(); @@ -43,7 +43,7 @@ class TIbmScaffoldInput extends TScaffoldInputCommon case 'timestamp': return $this->getDateTimeValue($container, $column, $record); default: - return $this->getDefaultControlValue($container,$column, $record); + return $this->getDefaultControlValue($container,$column, $record); } } } diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMssqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMssqlScaffoldInput.php new file mode 100644 index 00000000..840e5b63 --- /dev/null +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMssqlScaffoldInput.php @@ -0,0 +1,43 @@ +getDbType())) + { + case 'bit': + return $this->createBooleanControl($container, $column, $record); + case 'text': + return $this->createMultiLineControl($container, $column, $record); + case 'smallint': case 'int': case 'bigint': case 'tinyint': + return $this->createIntegerControl($container, $column, $record); + case 'decimal': case 'float': case 'money': case 'numeric': case 'real': case 'smallmoney': + return $this->createFloatControl($container, $column, $record); + case 'datetime': case 'smalldatetime': + return $this->createDateTimeControl($container, $column, $record); + default: + $control = $this->createDefaultControl($container,$column, $record); + if($column->getIsExcluded()) + $control->setEnabled(false); + return $control; + } + } + + protected function getControlValue($container, $column, $record) + { + switch(strtolower($column->getDbType())) + { + case 'boolean': + return $container->findControl(self::DEFAULT_ID)->getChecked(); + case 'datetime': case 'smalldatetime': + return $this->getDateTimeValue($container,$column, $record); + default: + return $this->getDefaultControlValue($container,$column, $record); + } + } +} + +?> \ No newline at end of file diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php index 89df0f2e..42f8cead 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TMysqlScaffoldInput.php @@ -6,7 +6,8 @@ class TMysqlScaffoldInput extends TScaffoldInputCommon { protected function createControl($container, $column, $record) { - switch(strtolower($column->getType())) + $dbtype = trim(str_replace(array('unsigned', 'zerofill'),array('','',),strtolower($column->getDbType()))); + switch($dbtype) { case 'date': return $this->createDateControl($container, $column, $record); @@ -34,7 +35,8 @@ class TMysqlScaffoldInput extends TScaffoldInputCommon protected function getControlValue($container, $column, $record) { - switch(strtolower($column->getType())) + $dbtype = trim(str_replace(array('unsigned', 'zerofill'),array('','',),strtolower($column->getDbType()))); + switch($dbtype) { case 'date': return $container->findControl(self::DEFAULT_ID)->getDate(); @@ -57,7 +59,7 @@ class TMysqlScaffoldInput extends TScaffoldInputCommon protected function createIntegerControl($container, $column, $record) { - if($column->getLength()==1) + if($column->getColumnSize()==1) return $this->createBooleanControl($container, $column, $record); else parent::createIntegerControl($container, $column, $record); @@ -65,7 +67,7 @@ class TMysqlScaffoldInput extends TScaffoldInputCommon protected function getIntBooleanValue($container,$column, $record) { - if($column->getLength()==1) + if($column->getColumnSize()==1) return (int)$container->findControl(self::DEFAULT_ID)->getChecked(); else return $this->getDefaultControlValue($container,$column, $record); diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php index f5e11eae..a024c73b 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TPgsqlScaffoldInput.php @@ -6,7 +6,7 @@ class TPgsqlScaffoldInput extends TScaffoldInputCommon { protected function createControl($container, $column, $record) { - switch(strtolower($column->getType())) + switch(strtolower($column->getDbType())) { case 'boolean': return $this->createBooleanControl($container, $column, $record); @@ -29,7 +29,7 @@ class TPgsqlScaffoldInput extends TScaffoldInputCommon protected function getControlValue($container, $column, $record) { - switch(strtolower($column->getType())) + switch(strtolower($column->getDbType())) { case 'boolean': return $container->findControl(self::DEFAULT_ID)->getChecked(); diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php index 05e83157..f9ca9180 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputBase.php @@ -27,6 +27,9 @@ class TScaffoldInputBase case 'pgsql': require_once(dirname(__FILE__).'/TPgsqlScaffoldInput.php'); return new TPgsqlScaffoldInput($conn); + case 'mssql': + require_once(dirname(__FILE__).'/TMssqlScaffoldInput.php'); + return new TMssqlScaffoldInput($conn); case 'ibm': require_once(dirname(__FILE__).'/TIbmScaffoldInput.php'); return new TIbmScaffoldInput($conn); @@ -39,7 +42,7 @@ class TScaffoldInputBase public function createScaffoldInput($parent, $item, $column, $record) { $this->_parent=$parent; - $item->setCustomData($column->getProperty()); + $item->setCustomData($column->getColumnId()); $this->createControl($item->_input, $column, $record); if($item->_input->findControl(self::DEFAULT_ID)) $this->createControlLabel($item->_label, $column, $record); @@ -47,7 +50,7 @@ class TScaffoldInputBase protected function createControlLabel($label, $column, $record) { - $fieldname = ucwords(str_replace('_', ' ', $column->getProperty())).':'; + $fieldname = ucwords(str_replace('_', ' ', $column->getColumnId())).':'; $label->setText($fieldname); $label->setForControl(self::DEFAULT_ID); } @@ -57,7 +60,7 @@ class TScaffoldInputBase $this->_parent=$parent; if($this->getIsEnabled($column, $record)) { - $prop = $column->getProperty(); + $prop = $column->getColumnId(); $record->{$prop} = $this->getControlValue($item->_input, $column, $record); } } @@ -70,7 +73,11 @@ class TScaffoldInputBase protected function getRecordPropertyValue($column, $record) { - return $record->{$column->getProperty()}; + $value = $record->{$column->getColumnId()}; + if($column->getDefaultValue()!==TDbTableColumn::UNDEFINED_VALUE && $value===null) + return $column->getDefaultValue(); + else + return $value; } protected function setRecordPropertyValue($item, $record, $input) diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php index 049ceb1f..e1d57124 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TScaffoldInputCommon.php @@ -12,7 +12,7 @@ class TScaffoldInputCommon extends TScaffoldInputBase protected function setNotNullProperty($container, $control, $column, $record) { $this->setDefaultProperty($container, $control, $column, $record); - if($column->getNotNull() && !$column->hasSequence()) + if(!$column->getAllowNull() && !$column->hasSequence()) $this->createRequiredValidator($container, $column, $record); } @@ -32,7 +32,7 @@ class TScaffoldInputCommon extends TScaffoldInputBase $control = new TTextBox(); $control->setText($value); $control->setCssClass('default-textbox scaffold_input'); - if(($len=$column->getLength())!==null) + if(($len=$column->getColumnSize())!==null) $control->setMaxLength($len); $this->setNotNullProperty($container, $control, $column, $record); return $control; @@ -89,6 +89,14 @@ class TScaffoldInputCommon extends TScaffoldInputBase $val = $this->createTypeValidator($container, $column, $record); $val->setDataType(TValidationDataType::Float); $val->setErrorMessage('Please entery a decimal number.'); + if(($max= $column->getMaxiumNumericConstraint())!==null) + { + $val = $this->createRangeValidator($container,$column,$record); + $val->setDataType(TValidationDataType::Float); + $val->setMaxValue($max); + $val->setStrictComparison(true); + $val->setErrorMessage('Please entery a decimal number strictly less than '.$max.'.'); + } return $control; } @@ -117,6 +125,18 @@ class TScaffoldInputCommon extends TScaffoldInputBase return $val; } + protected function createRangeValidator($container, $column, $record) + { + $val = new TRangeValidator(); + $val->setControlCssClass('required-input3'); + $val->setCssClass('required'); + $val->setControlToValidate(self::DEFAULT_ID); + $val->setValidationGroup($this->getParent()->getValidationGroup()); + $val->setDisplay(TValidatorDisplayStyle::Dynamic); + $container->Controls[] = $val; + return $val; + } + protected function createTimeControl($container, $column, $record) { $value = $this->getRecordPropertyValue($column, $record); @@ -222,10 +242,10 @@ class TScaffoldInputCommon extends TScaffoldInputBase $value = $this->getRecordPropertyValue($column, $record); $selectedValues = preg_split('/\s*,\s*/', $value); $control = new TCheckBoxList(); - $values = $column->getTypeValues(); + $values = $column->getDbTypeValues(); $control->setDataSource($values); $control->dataBind(); - $control->setSelectedIndices($this->getMatchingIndices($selectedValues, $values)); + $control->setSelectedIndices($this->getMatchingIndices($values,$selectedValues)); $control->setID(self::DEFAULT_ID); $control->setCssClass('set-checkboxes'); $this->setNotNullProperty($container, $control, $column, $record); @@ -248,10 +268,10 @@ class TScaffoldInputCommon extends TScaffoldInputBase $value = $this->getRecordPropertyValue($column, $record); $selectedValues = preg_split('/\s*,\s*/', $value); $control = new TRadioButtonList(); - $values = $column->getTypeValues(); + $values = $column->getDbTypeValues(); $control->setDataSource($values); $control->dataBind(); - $index = $this->getMatchingIndices($selectedValues, $values); + $index = $this->getMatchingIndices($values,$selectedValues); if(count($index) > 0) $control->setSelectedIndex($index[0]); $control->setID(self::DEFAULT_ID); diff --git a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php index b26d44fd..a61da1f3 100644 --- a/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php +++ b/framework/Data/ActiveRecord/Scaffold/InputBuilder/TSqliteScaffoldInput.php @@ -6,7 +6,7 @@ class TSqliteScaffoldInput extends TScaffoldInputCommon { protected function createControl($container, $column, $record) { - switch(strtolower($column->getType())) + switch(strtolower($column->getDbType())) { case 'boolean': return $this->createBooleanControl($container, $column, $record); @@ -32,7 +32,7 @@ class TSqliteScaffoldInput extends TScaffoldInputCommon protected function getControlValue($container, $column, $record) { - switch(strtolower($column->getType())) + switch(strtolower($column->getDbType())) { case 'boolean': return $container->findControl(self::DEFAULT_ID)->getChecked(); @@ -53,7 +53,7 @@ class TSqliteScaffoldInput extends TScaffoldInputCommon { $control = parent::createDateControl($container, $column, $record); $value = $this->getRecordPropertyValue($column, $record); - if(!empty($value) && preg_match('/timestamp/i', $column->getType())) + if(!empty($value) && preg_match('/timestamp/i', $column->getDbType())) $control->setTimestamp(intval($value)); return $control; } @@ -62,7 +62,7 @@ class TSqliteScaffoldInput extends TScaffoldInputCommon { $value = $this->getRecordPropertyValue($column, $record); $time = parent::createDateTimeControl($container, $column, $record); - if(!empty($value) && preg_match('/timestamp/i', $column->getType())) + if(!empty($value) && preg_match('/timestamp/i', $column->getDbType())) { $s = Prado::createComponent('System.Util.TDateTimeStamp'); $date = $s->getDate(intval($value)); @@ -75,7 +75,7 @@ class TSqliteScaffoldInput extends TScaffoldInputCommon protected function getDateTimeValue($container, $column, $record) { - if(preg_match('/timestamp/i', $column->getType())) + if(preg_match('/timestamp/i', $column->getDbType())) { $time = $container->findControl(self::DEFAULT_ID)->getTimestamp(); $s = Prado::createComponent('System.Util.TDateTimeStamp'); diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php index 266d4346..a9bf2d59 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldBase.php @@ -36,23 +36,15 @@ abstract class TScaffoldBase extends TTemplateControl * @var TActiveRecord record instance (may be new or retrieved from db) */ private $_record; - /** - * @var TDbMetaData table/view information. - */ - private $_meta; /** * @return TDbMetaData table/view information */ - protected function getTableMetaData() + protected function getTableInfo() { - if($this->_meta===null) - { - $finder = $this->getRecordFinder(); - $gateway = $finder->getRecordManager()->getRecordGateWay(); - $this->_meta = $gateway->getMetaData($finder); - } - return $this->_meta; + $finder = $this->getRecordFinder(); + $gateway = $finder->getRecordManager()->getRecordGateWay(); + return $gateway->getRecordTableInfo($finder); } /** @@ -62,7 +54,7 @@ abstract class TScaffoldBase extends TTemplateControl protected function getRecordPropertyValues($record) { $data = array(); - foreach($this->getTableMetaData()->getColumns() as $name=>$column) + foreach($this->getTableInfo()->getColumns() as $name=>$column) $data[] = $record->{$name}; return $data; } @@ -73,7 +65,7 @@ abstract class TScaffoldBase extends TTemplateControl */ protected function getRecordPkValues($record) { - foreach($this->getTableMetaData()->getColumns() as $name=>$column) + foreach($this->getTableInfo()->getColumns() as $name=>$column) { if($column->getIsPrimaryKey()) $data[] = $record->{$name}; @@ -106,7 +98,6 @@ abstract class TScaffoldBase extends TTemplateControl protected function copyFrom(TScaffoldBase $obj) { $this->_record = $obj->_record; - $this->_meta = $obj->_meta; $this->setRecordClass($obj->getRecordClass()); } @@ -116,7 +107,6 @@ abstract class TScaffoldBase extends TTemplateControl protected function clearRecordObject() { $this->_record=null; - $this->_meta=null; } /** diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php index efc356f5..0550864b 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.php @@ -114,7 +114,7 @@ class TScaffoldEditView extends TScaffoldBase $classPath = $this->getEditRenderer(); if($classPath === '') { - $columns = $this->getTableMetaData()->getColumns(); + $columns = $this->getTableInfo()->getColumns(); $this->getInputRepeater()->setDataSource($columns); $this->getInputRepeater()->dataBind(); } @@ -199,7 +199,7 @@ class TScaffoldEditView extends TScaffoldBase $record = $this->getCurrentRecord(); if($this->_editRenderer===null) { - $table = $this->getTableMetaData(); + $table = $this->getTableInfo(); $builder = $this->getScaffoldInputBuilder($record); foreach($this->getInputRepeater()->getItems() as $item) { diff --git a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl index 884ec2a3..b3289c09 100644 --- a/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl +++ b/framework/Data/ActiveRecord/Scaffold/TScaffoldEditView.tpl @@ -3,7 +3,7 @@
+ * SELECT * FROM (
+ * SELECT TOP n * FROM (
+ * SELECT TOP z columns -- (z=n+skip)
+ * FROM tablename
+ * ORDER BY key ASC
+ * ) AS FOO ORDER BY key DESC -- ('FOO' may be anything)
+ * ) AS BAR ORDER BY key ASC -- ('BAR' may be anything)
+ *
+ *
+ * Regular expressions are used to alter the SQL query. The resulting SQL query
+ * may be malformed for complex queries. The following restrictions apply
+ *
+ *