Ferreteria/v0.3/class/tSaveableRow

From Woozle Writes Code
< Ferreteria‎ | v0.3‎ | class
Jump to navigation Jump to search

Template:Page/obsolete

trait tSaveableRow {

    // ++ SETUP ++ //

    abstract protected function GetSelfFilter();
    
    // -- SETUP -- //
    // ++ STORAGE VALUES ++ //

    /*----
      FX(): GetInsertStorageOverrides(), GetUpdateStorageOverrides()
      INPUT: $ar (optional) = list of key-value pairs (values, not SQL-formatted) to be included
      RETURNS array of record values to set, formatted for $this->Insert()/Update().
      PURPOSE: Mainly so it can be overridden to calculate specific fields
	when a record is inserted or updated.
      FORMAT: Sanitized SQL; can include expressions like "NOW()".
	Default is just to return all changed values, sanitized.
      TODO:
      * Find out if anyone is using the $ar parameter.
      * This won't work with keyless or multi-key tables because of GetKeyName(). Fix when needed.
      HISTORY:
	2017-05-24 Sanitizing is insufficient to make this data reliably writable; form storage objects must do the translation.
	  Removing Sanitize_andQuote().
	2017-05-25 Renamed for clarity: call GetChangedStorableValues() (was GetChangedNativeValues), with no argument.
	  * Possibly we also need to write GetChangeStorageValues()...?
	2017-06-15 
	  * Finally sorted things out, I hope. We now have Get*NativeValues() and Get*StorageValues().
	  * eliminated $ar parameter
	  * and then (I guess?) renamed from Get*StorageValues() to Get*StorageOverrides().
    */
    
    /*----
      STUB
    */
    public function GetInsertStorageOverrides() {
	return array();
    }
    /*----
      STUB
    */
    public function GetUpdateStorageOverrides() {
	return array();
    }

    // -- STORAGE VALUES -- //
    // ++ OUTPUT ++ //

    public function Update(array $arChg,$isNativeData=FALSE) {
	$sqlFilt = $this->GetSelfFilter();
	$tbl = $this->GetSourceObject();
	$tbl->Update($arChg,$sqlFilt,$isNativeData);
	$this->sql = $tbl->sql;
    }
    protected function Insert(array $arRow) {
	$tbl = $this->GetSourceObject();  // in v2, this used GetTableWrapper_Insertable() - might need something like that
	$id = $tbl->Insert($arRow);
	$this->sql = $tbl->sql;
	if ($id === FALSE) {
	    $id = NULL;
	} else {
	    $this->SetKeyValue($id);	// remember new record's ID
	}
	return $id;
    }

    // -- OUTPUT -- //
    // ++ DEPRECATED ++ //

    /*----
      ACTION: modify the local field values from the given array, AND keep track of what has changed
	Same as SetFieldValues() but also touches each field that is being set.
      FUTURE: should we only Touch if the new value is different?
    */
    public function ChangeFieldValues(array $ar) {
        throw new exception('2018-10-26 ChangeFieldValues() is under review to see if it is actually needed.');
    
	foreach ($ar as $key => $value) {
	    $this->SetFieldValue($key,$value);
	    $this->TouchField($key);
	}
    }
    /*----
      ACTION: Takes list of fields which have been changed, fetches the corresponding values, and returns an array of both.
      RETURNS: array of key-value pairs
      PUBLIC because Form objects need to access it.
    */
    public function GetStorableValues_Changed() {
        throw new exception('2018-10-26 GetStorableValues_Changed() is under review to see if it is actually needed.');
	$arTouch = $this->TouchedArray();	// just a list; no values
	$arOut = NULL;
	$db = $this->GetConnection();
	if (is_array($arTouch)) {
	    $sKey = $this->GetTableWrapper()->GetKeyName();
	    foreach ($arTouch as $sField) {
		if ($sField != $sKey) {		// don't write to the key field
		    $v = $this->GetFieldValue($sField);
		    $sqlVal = $db->SanitizeValue($v);
		    $arOut[$sField] = $sqlVal;
		}
	    }
	}
	return $arOut;
    }

    /*====
      FX() GROUP: GetStorableValues_to{$op}()
      RETURNS array of values to use for db writes, formatted for $this->Insert() (i.e. SQL-format.
      PURPOSE: originally so it can be overridden to calculate specific fields
	when a record is updated, e.g. set WhenCreated or WhenEdited
	but this is now probably better accomplished with Get{$op}StorageOverrides() in most cases.
      HISTORY:
	2016-04-19 This couldn't have been working reliably until now, because the values
	  were not being sanitize-and-quoted. (Now they are.)
	2017-05-25 API changes:
	  * Renamed from {$op}Array() to Get{$op}Values() and then Get{$op}NativeValues()
	  * Removed array parameter
	  * Made public so Form object can access (replacing functionality of $this->Save())
	2017-09-16 Renamed from Get{$op}NativeValues to GetStorableValues_to{$op}
      PUBLIC so Form object can use it when saving received values to database
    */
      /*----
	DEFAULT
	VERSION: {$op} = INSERT
	RETURNS: array of values formatted for $this->Insert()
	HISTORY:
	  2016-10-16 Now defaults to ChangeArray() instead of UpdateArray().
      */
    public function GetStorableValues_toInsert() {
        throw new exception('2018-10-26 GetStorableValues_toInsert() is under review to see if it is actually needed.');
	return $this->GetStorableValues_Changed();
    }
      /*----
	DEFAULT
	VERSION: $op = UPDATE
	RETURNS: array of values formatted for $this->Update()
	HISTORY:
	  2016-10-16 Calculations moved to ChangeArray().
      */
    public function GetStorableValues_toUpdate() {
        throw new exception('2018-10-26 GetStorableValues_toUpdate() is under review to see if it is actually needed.');
	return $this->GetStorableValues_Changed();
    }
    /*----
      HISTORY:
	2017-05-28 This *was* "public function Insert(...)", with the note:
	  "PUBLIC OVERRIDE so form can save new records"
	  ...but it turns out that this conflicts with other traits in some way
	  that I don't know how to resolve, so I've given the public version
	  a different name (PublicInsert()). That should make it easier to find
	  usages.
	2017-08-30 It turns out that actually, it's good that we have a different name
	  to use when external entities (usually forms) want to insert things, because
	  sometimes we don't want to just stick the data in a record. Wiki Nodes need
	  to be able to create a complex set of records in different tables in response
	  to an insert request from a form, for example.
	  
	  Therefore: renaming this from PublicInsert() to FormInsert(), and also
	    creating FormUpdate().
    */
    public function FormInsert(array $arRow) {
        throw new exception('2018-10-26 FormInsert() is under review to see if it is actually needed.');
	return parent::Insert($arRow);
    }
    /*----
      HISTORY:
	2017-08-30 created to be overridable by classes that need to do more complicated things
	  than just sticking the data in a single record
    */
    public function FormUpdate(array $arRow) {
        throw new exception('2018-10-26 FormUpdate() is under review to see if it is actually needed.');
	return parent::Update($arRow);
    }
    /*----
      INPUT: $arSave (optional) is a list of key-sqlvalue pairs to include in the save.
      HISTORY:
	2016-06-04 I'm not sure why this was private; it seems like a good general-use function.
	  I specifically needed it to be public when loading up Customer Address records via either
	  of two different methods. I *could* have written public SaveThis() and SaveThat() methods,
	  but that would have increased the amount of special coding needed for This and That yet again.
	2016-10-12 Added $arSave argument so forms could inject additional SQL-format data to save.
	  Isn't there some other way to do this? Can't think of it.
	2017-04-26 I'm pretty sure this was not in a trait until sometime in the last few months.
	  Not sure exactly where it was before that, or exactly when it was moved.
	2017-05-24 This now seems unnecessary; functionality should be in Form object. Commented out.
	2018-02-19 ...but apparently shopping carts need it, so re-enabling.
	2018-02-21 After much documentation, I suddenly realized this is a perfect opportunity to get rid
	  of the $arSave input parameter.
    */
    public function Save() {
        throw new exception('2018-10-26 Save() is under review to see if it is actually needed.');
	//$out = NULL;
	//$sql = NULL;	// for debugging
	if ($this->IsNew()) {
	    $ar = $this->GetStorableValues_toInsert();
	    if (is_array($ar)) {
		$ar = array_merge($ar,$this->GetInsertStorageOverrides());
		$this->Insert($ar);
	    }
	} else {
	    $ar = $this->GetStorableValues_toUpdate();
	    if (is_array($ar)) {
		$ar = array_merge($ar,$this->GetUpdateStorageOverrides());
		$this->Update($ar);
	    }
	}
    }

    // -- DEPRECATED -- //
}