/** * Construct a new DataObject. * * @param array|null $record This will be null for a new database record. Alternatively, you can pass an array of * field values. Normally this contructor is only used by the internal systems that get objects from the database. * @param boolean $isSingleton This this to true if this is a singleton() object, a stub for calling methods. Singletons * don't have their defaults set. */ function __construct($record = null, $isSingleton = false) { // Set the fields data. if (!$record) { $record = array("ID" => 0); } if (!is_array($record)) { if (is_object($record)) { $passed = "an object of type '{$record->class}'"; } else { $passed = "The value '{$record}'"; } user_error("DataObject::__construct passed {$passed}. It's supposed to be passed an array,\n\t\t\t\ttaken straight from the database. Perhaps you should use DataObject::get_one instead?", E_USER_WARNING); $record = null; } $this->record = $this->original = $record; // Keep track of the modification date of all the data sourced to make this page // From this we create a Last-Modified HTTP header if (isset($record['LastEdited'])) { HTTP::register_modification_date($record['LastEdited']); } parent::__construct(); // Must be called after parent constructor if (!$isSingleton && (!isset($this->record['ID']) || !$this->record['ID'])) { $this->populateDefaults(); } // prevent populateDefaults() and setField() from marking overwritten defaults as changed $this->changed = array(); }
/** * Construct a new DataObject. * * @param array|null $record This will be null for a new database record. Alternatively, you can pass an array of * field values. Normally this contructor is only used by the internal systems that get objects from the database. * @param boolean $isSingleton This this to true if this is a singleton() object, a stub for calling methods. Singletons * don't have their defaults set. */ function __construct($record = null, $isSingleton = false, $model = null) { parent::__construct(); // Set the fields data. if (!$record) { $record = array('ID' => 0, 'ClassName' => get_class($this), 'RecordClassName' => get_class($this)); } if (!is_array($record)) { if (is_object($record)) { $passed = "an object of type '{$record->class}'"; } else { $passed = "The value '{$record}'"; } user_error("DataObject::__construct passed {$passed}. It's supposed to be passed an array,\n\t\t\ttaken straight from the database. Perhaps you should use DataList::create()->First(); instead?", E_USER_WARNING); $record = null; } // Set $this->record to $record, but ignore NULLs $this->record = array(); foreach ($record as $k => $v) { // Ensure that ID is stored as a number and not a string // To do: this kind of clean-up should be done on all numeric fields, in some relatively // performant manner if ($v !== null) { if ($k == 'ID' && is_numeric($v)) { $this->record[$k] = (int) $v; } else { $this->record[$k] = $v; } } } // Identify fields that should be lazy loaded, but only on existing records if (!empty($record['ID'])) { $currentObj = get_class($this); while ($currentObj != 'DataObject') { $fields = self::custom_database_fields($currentObj); foreach ($fields as $field => $type) { if (!array_key_exists($field, $record)) { $this->record[$field . '_Lazy'] = $currentObj; } } $currentObj = get_parent_class($currentObj); } } $this->original = $this->record; // Keep track of the modification date of all the data sourced to make this page // From this we create a Last-Modified HTTP header if (isset($record['LastEdited'])) { HTTP::register_modification_date($record['LastEdited']); } // Must be called after parent constructor if (!$isSingleton && (!isset($this->record['ID']) || !$this->record['ID'])) { $this->populateDefaults(); } // prevent populateDefaults() and setField() from marking overwritten defaults as changed $this->changed = array(); $this->model = $model ? $model : DataModel::inst(); }
/** * Construct a new DataObject. * * @param array|null $record This will be null for a new database record. Alternatively, you can pass an array of * field values. Normally this contructor is only used by the internal systems that get objects from the database. * @param boolean $isSingleton This this to true if this is a singleton() object, a stub for calling methods. Singletons * don't have their defaults set. */ function __construct($record = null, $isSingleton = false, $model = null) { // Set the fields data. if(!$record) { $record = array( 'ID' => 0, 'ClassName' => get_class($this), 'RecordClassName' => get_class($this) ); } if(!is_array($record)) { if(is_object($record)) $passed = "an object of type '$record->class'"; else $passed = "The value '$record'"; user_error("DataObject::__construct passed $passed. It's supposed to be passed an array, taken straight from the database. Perhaps you should use DataList::create()->First(); instead?", E_USER_WARNING); $record = null; } // Convert PostgreSQL boolean values // TODO: Implement this more elegantly, for example by writing a more intelligent SQL SELECT query prior to object construction if(DB::getConn() instanceof PostgreSQLDatabase) { $this->class = get_class($this); foreach($record as $k => $v) { if($this->db($k) == 'Boolean' && $v == 'f') $record[$k] = '0'; } } // TODO: MSSQL has a convert function that can do this on the SQL end. We just need a // nice way of telling the database how we want to get the value out on a per-fieldtype basis if(DB::getConn() instanceof MSSQLDatabase) { $this->class = get_class($this); foreach($record as $k => $v) { if($v) { if($k == 'Created' || $k == 'LastEdited') { $fieldtype = 'SS_Datetime'; } else { $fieldtype = $this->db($k); } // MSSQLDatabase::date() uses datetime for the data type for "Date" and "SS_Datetime" switch($fieldtype) { case "Date": $v = preg_replace('/:[0-9][0-9][0-9]([ap]m)$/i', ' \\1', $v); $record[$k] = date('Y-m-d', strtotime($v)); break; case "Datetime": case "SS_Datetime": $v = preg_replace('/:[0-9][0-9][0-9]([ap]m)$/i', ' \\1', $v); $record[$k] = date('Y-m-d H:i:s', strtotime($v)); break; } } } } // Set $this->record to $record, but ignore NULLs $this->record = array(); foreach($record as $k => $v) { // Ensure that ID is stored as a number and not a string // To do: this kind of clean-up should be done on all numeric fields, in some relatively // performant manner if($v !== null) { if($k == 'ID' && is_numeric($v)) $this->record[$k] = (int)$v; else $this->record[$k] = $v; } } $this->original = $this->record; // Keep track of the modification date of all the data sourced to make this page // From this we create a Last-Modified HTTP header if(isset($record['LastEdited'])) { HTTP::register_modification_date($record['LastEdited']); } parent::__construct(); // Must be called after parent constructor if(!$isSingleton && (!isset($this->record['ID']) || !$this->record['ID'])) { $this->populateDefaults(); } // prevent populateDefaults() and setField() from marking overwritten defaults as changed $this->changed = array(); $this->model = $model ? $model : DataModel::inst(); }