name = $name; $this->alias = $alias; $this->sourceTable = $sourceTable; $this->readOnly = false; $this->defaultValue = null; $this->isAutoincrement = $isAutoincrement; $this->isNotNull = false; } public function SetIsNotNull($value) { $this->isNotNull = $value; } public function GetIsNotNull() { return $this->isNotNull; } public function SetReadOnly($readOnly, $defaultValue = null) { $this->readOnly = $readOnly; $this->defaultValue = $defaultValue; } public function GetIsAutoincrement() { return $this->isAutoincrement; } public function GetReadOnly() { return $this->readOnly; } public function GetDefaultValue() { return $this->defaultValue; } public function GetSourceTable() { return $this->sourceTable; } public function SetSourceTable($value) { $this->sourceTable = $value; } public function GetAlias() { return $this->alias; } public function GetName() { return $this->name; } public function GetNameInDataset() { return $this->GetAlias() == '' ? $this->GetName() : $this->GetAlias(); } /** * @return boolean */ public function SupportsLastInsertId() { return false; } public function SetConnectionFactory($value) { $this->connectionFactory = $value; } public function DoGetDisplayValue($sqlValue) { return $sqlValue; } public function GetDisplayValue($sqlValue) { return !isset($sqlValue) ? null : $this->DoGetDisplayValue($sqlValue); } /** * @param mixed $sqlValue * @return SMDateTime */ public function GetDisplayValueAsDateTime($sqlValue) { assert(false); } protected function GetEmptyValue() { return ''; } protected function DoGetValueForSql($value) { return $value; } public function GetValueForSql($value) { return $value == null ? ($this->GetIsNotNull() ? $this->GetEmptyValue() : $value) : $this->DoGetValueForSql($value); } abstract function GetEngFieldType(); } class BooleanField extends Field { function GetEngFieldType() { return ftBoolean; } } class IntegerField extends Field { function GetEngFieldType() { return ftNumber; } /** * @return bool */ public function SupportsLastInsertId() { return true; } } class StringField extends Field { function GetEngFieldType() { return ftString; } } class BlobField extends Field { function GetEngFieldType() { return ftBlob; } public function GetDisplayValue($sqlValue) { return !isset($sqlValue) ? null : $this->DoGetDisplayValue($sqlValue); } } class DateField extends Field { private $dateFormat; public function __construct($name, $dateFormat = 'Y-m-d', $alias = null, $sourceTable = null, $isAutoincrement = false) { parent::__construct($name, $alias, $sourceTable, $isAutoincrement); $this->dateFormat = $dateFormat; } /** * @param SMDateTime|string $sqlValue * @return null */ public function DoGetDisplayValue($sqlValue) { if (empty($sqlValue)) return null; else return $sqlValue->ToString($this->dateFormat); } public function GetDisplayValueAsDateTime($sqlValue) { return isset($sqlValue) ? $sqlValue : null; } protected function DoGetValueForSql($value) { return SMDateTime::Parse($value, $this->dateFormat); } function GetEngFieldType() { return ftDate; } } class TimeField extends Field { private $timeFormat; public function __construct($name, $timeFormat = 'H:i:s', $alias = null, $sourceTable = null, $isAutoincrement = false) { parent::__construct($name, $alias, $sourceTable, $isAutoincrement); $this->timeFormat = $timeFormat; } /** * @param SMDateTime|string $sqlValue * @return null */ public function DoGetDisplayValue($sqlValue) { if (empty($sqlValue)) return null; else return $sqlValue->ToString($this->timeFormat); } public function GetDisplayValueAsDateTime($sqlValue) { return isset($sqlValue) ? $sqlValue : null; } protected function DoGetValueForSql($value) { return SMDateTime::Parse($value, $this->timeFormat); } function GetEngFieldType() { return ftTime; } } class DateTimeField extends Field { private $dateTimeFormat; public function __construct($name, $dateTimeFormat = 'Y-m-d H:i:s', $alias = null, $sourceTable = null, $isAutoincrement = false) { parent::__construct($name, $alias, $sourceTable, $isAutoincrement); $this->dateTimeFormat = $dateTimeFormat; } /** * @param SMDateTime|string $sqlValue * @return null */ public function DoGetDisplayValue($sqlValue) { if (empty($sqlValue)) return null; else return $sqlValue->ToString($this->dateTimeFormat); } protected function DoGetValueForSql($value) { return SMDateTime::Parse($value, $this->dateTimeFormat); } public function GetDisplayValueAsDateTime($sqlValue) { return isset($sqlValue) ? $sqlValue : null; } function GetEngFieldType() { return ftDateTime; } } interface IDataset { /** * @return bool */ function Next(); /** * @return void */ function Open(); /** * @return void */ function Close(); /** * @param string $fieldName * @return string */ function GetFieldValueByName($fieldName); /** * @param string $fieldName * @param string $value * @param bool $setToDefault * @return void */ function SetFieldValueByName($fieldName, $value, $setToDefault = false); /** @return void */ public function Edit(); /** @return void */ public function Insert(); /** @return void */ public function Delete(); /** @return void */ public function Post(); function SetSingleRecordState($primaryKeyValues); function SetAllRecordsState(); function GetCurrentFieldValues(); function SetOrderBy($fieldName, $orderType); function GetName(); function GetPrimaryKeyValues(); function GetFieldValues(); function GetPrimaryKeyValuesAfterEdit(); function GetInsertFieldValues(); /** * @param string $fieldName * @return Field */ function GetFieldByName($fieldName); /** * @return EngConnection */ function GetConnection(); /** * @return BaseSelectCommand */ function GetSelectCommand(); /** * @return EngCommandImp */ function GetCommandImp(); /** * @param $fieldName * @return bool */ function IsLookupField($fieldName); /** * @param $fieldName * @return bool */ function IsLookupFieldNameByDisplayFieldName($fieldName); /** * @return string[] */ function GetPrimaryKeyFieldNames(); /** * @return string[] */ function GetPrimaryKeyValuesMap(); } abstract class Dataset implements IFilterable, IDataset { /** @var ConnectionFactory */ private $connectionFactory; /** @var EngDataReader */ private $dataReader; /** @var EngConnection */ private $connection; /** @var EngCommandImp */ private $commandImp; /** @var SelectCommand */ private $selectCommand; /** @var Field[] */ private $fields; private $fieldMap; /** @var string[] */ private $primaryKeyFields; protected $fieldFilters; // private $editFieldValues; private $editFieldSetToDefault; // private $insertFieldValues; private $insertFieldSetToDefault; private $clientEncoding; #region Events /** @var \Event */ public $OnNextRecord; /** @var \Event */ public $OnAfterConnect; #endregion private $editMode; private $insertMode; private $insertedMode = false; private $lookupFields = array(); private $masterFieldValue = array(); private $defaultFieldValues; private $singleRecordFilters = array(); private $rowIndex; function __construct($ConnectionFactory, $ConnectionParams) { $this->connectionFactory = $ConnectionFactory; $this->connectionParams = $ConnectionParams; $this->OnAfterConnect = new Event(); $this->OnNextRecord = new Event(); $this->selectCommand = $this->CreateSelectCommand(); $this->fields = array(); $this->fieldMap = array(); $this->primaryKeyFields = array(); $this->fieldFilters = array(); $this->editFieldValues = array(); $this->insertFieldValues = array(); $this->editFieldSetToDefault = array(); $this->insertFieldSetToDefault = array(); $this->clientEncoding = null; $this->defaultFieldValues = array(); } public function DoNotRewriteUnchangedValues() { return true; } private function DoOnNextRecord() { $this->OnNextRecord->Fire(array($this)); } public function SetClientEncoding($value) { $this->clientEncoding = $value; } public function GetPrimaryKeyFields() { return $this->primaryKeyFields; } /** * @abstract * @return SelectCommand */ protected abstract function CreateSelectCommand(); /** * @return SelectCommand */ public function GetSelectCommand() { return $this->selectCommand; } /* /** * @abstract * @return string public abstract function GetName();*/ /** * @abstract * @return UpdateCommand */ protected abstract function DoCreateUpdateCommand(); /** * @abstract * @return InsertCommand */ protected abstract function DoCreateInsertCommand(); /** * @abstract * @return DeleteCommand */ protected abstract function DoCreateDeleteCommand(); /** * @return UpdateCommand */ private function CreateUpdateCommand() { $result = $this->DoCreateUpdateCommand(); return $result; } /** * @return InsertCommand */ private function CreateInsertCommand() { $result = $this->DoCreateInsertCommand(); return $result; } /** * @return DeleteCommand */ private function CreateDeleteCommand() { $result = $this->DoCreateDeleteCommand(); return $result; } /** * @return ConnectionFactory */ public function GetConnectionFactory() { return $this->connectionFactory; } /** * @return EngConnection */ public function GetConnection() { return $this->connection; } /** * @return EngCommandImp */ public function GetCommandImp() { if (!isset($this->commandImp)) $this->commandImp = $this->connectionFactory->CreateEngCommandImp(); return $this->commandImp; } public function Connect() { if (!isset($this->connection)) { $this->connection = $this->connectionFactory->CreateConnection($this->connectionParams); $this->GetConnection()->OnAfterConnect->AddListener('AfterConnectHandler', $this); $this->GetConnection()->Connect(); } } public function AfterConnectHandler($connection) { $this->OnAfterConnect->Fire(array(&$connection)); } public function Open() { $this->Connect(); if (DebugUtils::GetDebugLevel() == 1) echo $this->selectCommand->GetSQL() . '
'; $this->dataReader = $this->selectCommand->Execute($this->GetConnection()); $this->rowIndex = 0; $this->insertedMode = false; } public function Next() { $this->rowIndex++; $result = $this->dataReader->Next(); $this->DoOnNextRecord(); return $result; } public function GetCurrentRowIndex() { return $this->rowIndex; } public function Close() { $this->SetAllRecordsState(); $this->rowIndex = 0; $this->dataReader->Close(); $this->DoAfterClose(); } protected function DoAfterClose() { } // public function Edit() { $this->editMode = true; } public function Insert() { $this->insertedMode = false; $this->insertMode = true; } public function Delete() { $deleteCommand = $this->CreateDeleteCommand(); $primaryKeyValues = $this->GetPrimaryKeyValuesMap(); foreach ($primaryKeyValues as $keyFieldName => $value) { $deleteCommand->SetKeyFieldValue($keyFieldName, $value); } if (DebugUtils::GetDebugLevel() == 1) echo $deleteCommand->GetSQL() . '
'; $deleteCommand->Execute($this->GetConnection()); } public function Post() { if ($this->editMode) { if (count($this->editFieldValues) > 0 || count($this->editFieldSetToDefault) > 0) { $updateCommand = $this->CreateUpdateCommand(); $primaryKeyValues = $this->GetOldPrimaryKeyValuesMap(); foreach ($primaryKeyValues as $keyFieldName => $value) $updateCommand->SetKeyFieldValue($keyFieldName, $value); foreach ($this->editFieldValues as $fieldName => $value) { if (in_array($fieldName, $this->editFieldSetToDefault)) $updateCommand->SetParameterValue($fieldName, null, true); else $updateCommand->SetParameterValue($fieldName, $value); } foreach ($this->GetFields() as $field) if ($field->GetReadOnly()) $updateCommand->SetParameterValue($field->GetNameInDataset(), $field->GetDefaultValue()); if (DebugUtils::GetDebugLevel() >= 1) echo $updateCommand->GetSQL() . '
'; $updateCommand->Execute($this->GetConnection()); } $this->editMode = false; } elseif ($this->insertMode) { $hasValuesForAutoIncrement = false; $insertCommand = $this->CreateInsertCommand() or RaiseError('Could not create InsertCommand'); $this->Connect(); foreach ($this->masterFieldValue as $fieldName => $value) $insertCommand->SetParameterValue($fieldName, $value); foreach ($this->insertFieldValues as $fieldName => $value) { if (in_array($fieldName, $this->insertFieldSetToDefault)) { if (!$this->GetFieldByName($fieldName)->GetIsAutoincrement()) $insertCommand->SetParameterValue($fieldName, null, true); } else { if ($this->GetFieldByName($fieldName)->GetIsAutoincrement()) $hasValuesForAutoIncrement = true; $insertCommand->SetParameterValue($fieldName, $value); } } foreach ($this->GetFields() as $field) if ($field->GetReadOnly()) $insertCommand->SetParameterValue($field->GetNameInDataset(), $field->GetDefaultValue()); foreach ($this->defaultFieldValues as $fieldName => $value) $insertCommand->SetParameterValue($fieldName, $value); $insertCommand->SetAutoincrementInsertion($hasValuesForAutoIncrement); if (DebugUtils::GetDebugLevel() == 1) echo $insertCommand->GetSQL() . '
'; $insertCommand->Execute($this->GetConnection()); $this->UpdatePrimaryKeyAfterInserting(); $this->insertMode = false; $this->insertedMode = true; } } private function UpdatePrimaryKeyAfterInserting() { $primaryKeyColumns = $this->GetPrimaryKeyFieldNames(); if (count($primaryKeyColumns) == 1) { if ($this->GetConnection()->SupportsLastInsertId()) { $field = $this->GetFieldByName($primaryKeyColumns[0]); if ($field != null && $field->SupportsLastInsertId()) { $lastInsertId = $this->GetConnection()->GetLastInsertId(); if ($lastInsertId != null) $this->insertFieldValues[$primaryKeyColumns[0]] = $lastInsertId; } } } } //
public function GetFieldValueAsSQLByNameForInsert($fieldName, $value) { return $this->GetFieldByName($fieldName)->GetValueForSql($value); } public function GetFieldValueAsSQLByNameForUpdate($fieldName, $value) { return $this->GetFieldByName($fieldName)->GetValueForSql($value); } public function GetCurrentFieldValues() { if ($this->editMode) return $this->GetEditFieldValues(); elseif ($this->insertMode || $this->insertedMode) return $this->GetInsertFieldValues(); else return $this->GetFieldValues(); } private function GetEditFieldValues() { return $this->editFieldValues; } public function GetInsertFieldValues() { return $this->insertFieldValues; } public function SetFieldValueByName($fieldName, $value, $setToDefault = false) { if ($this->editMode) { $valueForSql = $this->GetFieldValueAsSQLByNameForUpdate($fieldName, $value); $this->editFieldValues[$fieldName] = $valueForSql; if ($setToDefault) { $this->editFieldValues[$fieldName] = null; $this->editFieldSetToDefault[] = $fieldName; } } else if ($this->insertMode || $this->insertedMode) { $valueForSql = $this->GetFieldValueAsSQLByNameForInsert($fieldName, $value); $this->insertFieldValues[$fieldName] = $valueForSql; if ($setToDefault) { $this->insertFieldValues[$fieldName] = null; $this->insertFieldSetToDefault[] = $fieldName; } } } public function SetFieldValueAsFileNameByName($fieldName, $value, $setToDefault = false) { $this->SetFieldValueByName($fieldName, array($value), $setToDefault); } public function AddDefaultFieldValue($fieldName, $value) { $this->defaultFieldValues[$fieldName] = $value; } public function GetFieldValueByName($fieldName) { if ($this->insertMode || $this->insertedMode) { if (array_key_exists($fieldName, $this->insertFieldValues)) return $this->GetFieldByName($fieldName)->GetDisplayValue($this->insertFieldValues[$fieldName]); else return ''; } else if ($this->editMode) { if (array_key_exists($fieldName, $this->editFieldValues)) return $this->GetFieldByName($fieldName)->GetDisplayValue($this->editFieldValues[$fieldName]); else if (in_array($fieldName, $this->defaultFieldValues)) return $this->defaultFieldValues[$fieldName]; else { return $this->GetFieldByName($fieldName)->GetDisplayValue($this->dataReader->GetFieldValueByName($fieldName)); } } else { if (in_array($fieldName, $this->defaultFieldValues)) return $this->defaultFieldValues[$fieldName]; else { return $this->GetFieldByName($fieldName)->GetDisplayValue($this->dataReader->GetFieldValueByName($fieldName)); } } } /** * @param $fieldName * @return null|SMDateTime */ public function GetFieldValueByNameAsDateTime($fieldName) { if ($this->insertMode || $this->insertedMode) { if (array_key_exists($fieldName, $this->insertFieldValues)) return $this->GetFieldByName($fieldName)->GetDisplayValueAsDateTime($this->insertFieldValues[$fieldName]); else return null; } else { if (in_array($fieldName, $this->defaultFieldValues)) return $this->defaultFieldValues[$fieldName]; else { return $this->GetFieldByName($fieldName)->GetDisplayValueAsDateTime($this->dataReader->GetFieldValueByName($fieldName)); } } } public function GetFieldValues() { $result = array(); foreach ($this->GetFields() as $field) $result[$field->GetNameInDataset()] = $field->GetDisplayValue($this->dataReader->GetFieldValueByName($field->GetNameInDataset())); return $result; } #region Fields /** * @return Field[] */ public function GetFields() { return $this->fields; } /** * @param string $fieldName * @return null|Field */ public function GetFieldByName($fieldName) { if (isset($this->fieldMap[$fieldName])) return $this->fieldMap[$fieldName]; else return null; } public function GetFieldInfoByName($fieldName) { return $this->GetSelectCommand()->GetFieldByName($fieldName); } /** * @param Field $field * @return void */ protected function DoAddField($field) { $this->selectCommand->AddField($field->GetSourceTable(), $field->GetName(), $field->GetEngFieldType(), $field->GetAlias()); } /** * @param Field $field * @param bool $isPrimaryKeyField * @return void */ public function AddField($field, $isPrimaryKeyField = false) { $field->SetConnectionFactory($this->connectionFactory); $this->fields[] = $field; $this->fieldMap[$field->GetNameInDataset()] = $field; $this->DoAddField($field); if ($isPrimaryKeyField) $this->primaryKeyFields[] = $field->GetName(); } public function IsFieldPrimaryKey($fieldName) { return in_array($fieldName, $this->primaryKeyFields); } public function GetPrimaryKeyFieldNames() { return $this->primaryKeyFields; } public function GetPrimaryKeyValues() { $result = array(); foreach ($this->primaryKeyFields as $primaryKeyField) $result[] = $this->GetFieldValueByName($primaryKeyField); return $result; } public function GetPrimaryKeyValuesAfterEdit() { $this->editMode = true; $result = array(); foreach ($this->primaryKeyFields as $primaryKeyField) $result[] = $this->GetFieldValueByName($primaryKeyField); $this->editMode = false; return $result; } public function GetPrimaryKeyValuesAfterInsert() { $this->insertedMode = true; $result = array(); foreach ($this->primaryKeyFields as $primaryKeyField) $result[] = $this->GetFieldValueByName($primaryKeyField); $this->insertedMode = false; return $result; } public function GetOldPrimaryKeyValuesMap() { $this->editMode = false; $result = array(); foreach ($this->primaryKeyFields as $primaryKeyField) $result[$primaryKeyField] = $this->GetFieldValueByName($primaryKeyField); $this->editMode = true; return $result; } public function GetPrimaryKeyValuesMap() { $result = array(); foreach ($this->primaryKeyFields as $primaryKeyField) $result[$primaryKeyField] = $this->GetFieldValueByName($primaryKeyField); return $result; } #endregion #region Data navigation public function SetSingleRecordState($primaryKeyValues) { $primaryKeyFields = $this->GetPrimaryKeyFieldNames(); for ($i = 0; $i < count($primaryKeyFields); $i++) { $filter = new FieldFilter($primaryKeyValues[$i], '='); $this->singleRecordFilters[$primaryKeyFields[$i]] = $filter; $this->GetSelectCommand()->AddFieldFilter( $primaryKeyFields[$i], $filter); } } public function SetAllRecordsState() { foreach ($this->singleRecordFilters as $keyFieldName => $filter) $this->GetSelectCommand()->RemoveFieldFilter($keyFieldName, $filter); } public function SetUpLimit($upLimit) { $this->GetSelectCommand()->SetUpLimit($upLimit); } public function SetLimit($limit) { $this->GetSelectCommand()->SetLimitCount($limit); } protected function CheckConnect() { $this->Connect(); } public function GetTotalRowCount() { $this->CheckConnect(); $result = $this->GetSelectCommand()->GetSelectRecordCountSQL(); return $this->GetConnection()->ExecScalarSQL($result); } #region IFilterable implementation public function AddFieldFilter($fieldName, $fieldFilter) { $this->GetSelectCommand()->AddFieldFilter($fieldName, $fieldFilter); } public function RemoveFieldFilter($fieldName, $fieldFilter) { $this->GetSelectCommand()->RemoveFieldFilter($fieldName, $fieldFilter); } public function ClearFieldFilters() { $this->GetSelectCommand()->ClearFieldFilters(); } public function AddCompositeFieldFilter($filterLinkType, $fieldNames, $fieldFilters) { $this->GetSelectCommand()->AddCompositeFieldFilter( $filterLinkType, $fieldNames, $fieldFilters); } public function AddCustomCondition($condition) { $this->GetSelectCommand()->AddCustomCondition($condition); } #endregion public function SetOrderBy($fieldName, $orderType) { $this->GetSelectCommand()->SetOrderBy($fieldName, $orderType); } #endregion public function SetMasterFieldValue($fieldName, $value) { $this->masterFieldValue[$fieldName] = $value; } public function GetMasterFieldValueByName($fieldName) { return ArrayUtils::GetArrayValueDef($this->masterFieldValue, $fieldName); } /** * @param string $fieldName * @param string $lookUpTable * @param Field $lookUpLinkField * @param Field $lookupDisplayField * @param string $lookUpTableAlias * @return void */ public function AddLookupField($fieldName, $lookUpTable, $lookUpLinkField, $lookupDisplayField, $lookUpTableAlias) { $this->lookupFields[$lookupDisplayField->GetAlias()] = $fieldName; } public function IsLookupField($fieldName) { return array_key_exists($fieldName, $this->lookupFields); } public function IsLookupFieldByPrimaryName($fieldName) { foreach ($this->lookupFields as $displayName => $primaryName) { if ($primaryName == $fieldName) return $displayName; } return null; } public function IsLookupFieldNameByDisplayFieldName($displayFieldName) { return $this->lookupFields[$displayFieldName]; } }