Created
June 5, 2014 21:08
-
-
Save ianmstew/e7928f7b57ccf480ed18 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Magento | |
* | |
* NOTICE OF LICENSE | |
* | |
* This source file is subject to the Open Software License (OSL 3.0) | |
* that is bundled with this package in the file LICENSE.txt. | |
* It is also available through the world-wide-web at this URL: | |
* http://opensource.org/licenses/osl-3.0.php | |
* If you did not receive a copy of the license and are unable to | |
* obtain it through the world-wide-web, please send an email | |
* to [email protected] so we can send you a copy immediately. | |
* | |
* DISCLAIMER | |
* | |
* Do not edit or add to this file if you wish to upgrade Magento to newer | |
* versions in the future. If you wish to customize Magento for your | |
* needs please refer to http://www.magentocommerce.com for more information. | |
* | |
* @category Varien | |
* @package Varien_Object | |
* @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com) | |
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) | |
*/ | |
/** | |
* Varien Object | |
* | |
* @category Varien | |
* @package Varien_Object | |
* @author Magento Core Team <[email protected]> | |
*/ | |
class Varien_Object implements ArrayAccess | |
{ | |
/** | |
* Object attributes | |
* | |
* @var array | |
*/ | |
protected $_data = array(); | |
/** | |
* Data changes flag (true after setData|unsetData call) | |
* @var $_hasDataChange bool | |
*/ | |
protected $_hasDataChanges = false; | |
/** | |
* Original data that was loaded | |
* | |
* @var array | |
*/ | |
protected $_origData; | |
/** | |
* Name of object id field | |
* | |
* @var string | |
*/ | |
protected $_idFieldName = null; | |
/** | |
* Setter/Getter underscore transformation cache | |
* | |
* @var array | |
*/ | |
protected static $_underscoreCache = array(); | |
/** | |
* Object delete flag | |
* | |
* @var boolean | |
*/ | |
protected $_isDeleted = false; | |
/** | |
* Map short fields names to its full names | |
* | |
* @var array | |
*/ | |
protected $_oldFieldsMap = array(); | |
/** | |
* Map of fields to sync to other fields upon changing their data | |
*/ | |
protected $_syncFieldsMap = array(); | |
/** | |
* Constructor | |
* | |
* By default is looking for first argument as array and assignes it as object attributes | |
* This behaviour may change in child classes | |
* | |
*/ | |
public function __construct() | |
{ | |
$this->_initOldFieldsMap(); | |
if ($this->_oldFieldsMap) { | |
$this->_prepareSyncFieldsMap(); | |
} | |
$args = func_get_args(); | |
if (empty($args[0])) { | |
$args[0] = array(); | |
} | |
$this->_data = $args[0]; | |
$this->_addFullNames(); | |
$this->_construct(); | |
} | |
protected function _addFullNames() | |
{ | |
$existedShortKeys = array_intersect($this->_syncFieldsMap, array_keys($this->_data)); | |
if (!empty($existedShortKeys)) { | |
foreach ($existedShortKeys as $key) { | |
$fullFieldName = array_search($key, $this->_syncFieldsMap); | |
$this->_data[$fullFieldName] = $this->_data[$key]; | |
} | |
} | |
} | |
/** | |
* Inits mapping array of object's previously used fields to new fields. | |
* Must be overloaded by descendants to set concrete fields map. | |
* | |
* @return Varien_Object | |
*/ | |
protected function _initOldFieldsMap() | |
{ | |
} | |
/** | |
* Called after old fields are inited. Forms synchronization map to sync old fields and new fields | |
* between each other. | |
* | |
* @return Varien_Object | |
*/ | |
protected function _prepareSyncFieldsMap() | |
{ | |
$old2New = $this->_oldFieldsMap; | |
$new2Old = array_flip($this->_oldFieldsMap); | |
$this->_syncFieldsMap = array_merge($old2New, $new2Old); | |
return $this; | |
} | |
/** | |
* Internal constructor not depended on params. Can be used for object initialization | |
*/ | |
protected function _construct() | |
{ | |
} | |
/** | |
* Set _isDeleted flag value (if $isDeleted param is defined) and return current flag value | |
* | |
* @param boolean $isDeleted | |
* @return boolean | |
*/ | |
public function isDeleted($isDeleted=null) | |
{ | |
$result = $this->_isDeleted; | |
if (!is_null($isDeleted)) { | |
$this->_isDeleted = $isDeleted; | |
} | |
return $result; | |
} | |
/** | |
* Get data change status | |
* | |
* @return bool | |
*/ | |
public function hasDataChanges() | |
{ | |
return $this->_hasDataChanges; | |
} | |
/** | |
* set name of object id field | |
* | |
* @param string $name | |
* @return Varien_Object | |
*/ | |
public function setIdFieldName($name) | |
{ | |
$this->_idFieldName = $name; | |
return $this; | |
} | |
/** | |
* Retrieve name of object id field | |
* | |
* @param string $name | |
* @return Varien_Object | |
*/ | |
public function getIdFieldName() | |
{ | |
return $this->_idFieldName; | |
} | |
/** | |
* Retrieve object id | |
* | |
* @return mixed | |
*/ | |
public function getId() | |
{ | |
if ($this->getIdFieldName()) { | |
return $this->_getData($this->getIdFieldName()); | |
} | |
return $this->_getData('id'); | |
} | |
/** | |
* Set object id field value | |
* | |
* @param mixed $value | |
* @return Varien_Object | |
*/ | |
public function setId($value) | |
{ | |
if ($this->getIdFieldName()) { | |
$this->setData($this->getIdFieldName(), $value); | |
} else { | |
$this->setData('id', $value); | |
} | |
return $this; | |
} | |
/** | |
* Add data to the object. | |
* | |
* Retains previous data in the object. | |
* | |
* @param array $arr | |
* @return Varien_Object | |
*/ | |
public function addData(array $arr) | |
{ | |
foreach($arr as $index=>$value) { | |
$this->setData($index, $value); | |
} | |
return $this; | |
} | |
/** | |
* Overwrite data in the object. | |
* | |
* $key can be string or array. | |
* If $key is string, the attribute value will be overwritten by $value | |
* | |
* If $key is an array, it will overwrite all the data in the object. | |
* | |
* @param string|array $key | |
* @param mixed $value | |
* @return Varien_Object | |
*/ | |
public function setData($key, $value=null) | |
{ | |
$this->_hasDataChanges = true; | |
if(is_array($key)) { | |
$this->_data = $key; | |
$this->_addFullNames(); | |
} else { | |
$this->_data[$key] = $value; | |
if (isset($this->_syncFieldsMap[$key])) { | |
$fullFieldName = $this->_syncFieldsMap[$key]; | |
$this->_data[$fullFieldName] = $value; | |
} | |
} | |
return $this; | |
} | |
/** | |
* Unset data from the object. | |
* | |
* $key can be a string only. Array will be ignored. | |
* | |
* @param string $key | |
* @return Varien_Object | |
*/ | |
public function unsetData($key=null) | |
{ | |
$this->_hasDataChanges = true; | |
if (is_null($key)) { | |
$this->_data = array(); | |
} else { | |
unset($this->_data[$key]); | |
if (isset($this->_syncFieldsMap[$key])) { | |
$fullFieldName = $this->_syncFieldsMap[$key]; | |
unset($this->_data[$fullFieldName]); | |
} | |
} | |
return $this; | |
} | |
/** | |
* Unset old fields data from the object. | |
* | |
* $key can be a string only. Array will be ignored. | |
* | |
* @param string $key | |
* @return Varien_Object | |
*/ | |
public function unsetOldData($key=null) | |
{ | |
if (is_null($key)) { | |
foreach ($this->_oldFieldsMap as $key => $newFieldName) { | |
unset($this->_data[$key]); | |
} | |
} else { | |
unset($this->_data[$key]); | |
} | |
return $this; | |
} | |
/** | |
* Retrieves data from the object | |
* | |
* If $key is empty will return all the data as an array | |
* Otherwise it will return value of the attribute specified by $key | |
* | |
* If $index is specified it will assume that attribute data is an array | |
* and retrieve corresponding member. | |
* | |
* @param string $key | |
* @param string|int $index | |
* @return mixed | |
*/ | |
public function getData($key='', $index=null) | |
{ | |
if (''===$key) { | |
return $this->_data; | |
} | |
$default = null; | |
// accept a/b/c as ['a']['b']['c'] | |
if (strpos($key,'/')) { | |
$keyArr = explode('/', $key); | |
$data = $this->_data; | |
foreach ($keyArr as $i=>$k) { | |
if ($k==='') { | |
return $default; | |
} | |
if (is_array($data)) { | |
if (!isset($data[$k])) { | |
return $default; | |
} | |
$data = $data[$k]; | |
} elseif ($data instanceof Varien_Object) { | |
$data = $data->getData($k); | |
} else { | |
return $default; | |
} | |
} | |
return $data; | |
} | |
// legacy functionality for $index | |
if (isset($this->_data[$key])) { | |
if (is_null($index)) { | |
return $this->_data[$key]; | |
} | |
$value = $this->_data[$key]; | |
if (is_array($value)) { | |
//if (isset($value[$index]) && (!empty($value[$index]) || strlen($value[$index]) > 0)) { | |
/** | |
* If we have any data, even if it empty - we should use it, anyway | |
*/ | |
if (isset($value[$index])) { | |
return $value[$index]; | |
} | |
return null; | |
} elseif (is_string($value)) { | |
$arr = explode("\n", $value); | |
return (isset($arr[$index]) && (!empty($arr[$index]) || strlen($arr[$index]) > 0)) | |
? $arr[$index] : null; | |
} elseif ($value instanceof Varien_Object) { | |
return $value->getData($index); | |
} | |
return $default; | |
} | |
return $default; | |
} | |
/** | |
* Get value from _data array without parse key | |
* | |
* @param string $key | |
* @return mixed | |
*/ | |
protected function _getData($key) | |
{ | |
return isset($this->_data[$key]) ? $this->_data[$key] : null; | |
} | |
/** | |
* Set object data with calling setter method | |
* | |
* @param string $key | |
* @param mixed $args | |
* @return Varien_Object | |
*/ | |
public function setDataUsingMethod($key, $args=array()) | |
{ | |
$method = 'set'.$this->_camelize($key); | |
$this->$method($args); | |
return $this; | |
} | |
/** | |
* Get object data by key with calling getter method | |
* | |
* @param string $key | |
* @param mixed $args | |
* @return mixed | |
*/ | |
public function getDataUsingMethod($key, $args=null) | |
{ | |
$method = 'get'.$this->_camelize($key); | |
return $this->$method($args); | |
} | |
/** | |
* Fast get data or set default if value is not available | |
* | |
* @param string $key | |
* @param mixed $default | |
* @return mixed | |
*/ | |
public function getDataSetDefault($key, $default) | |
{ | |
if (!isset($this->_data[$key])) { | |
$this->_data[$key] = $default; | |
} | |
return $this->_data[$key]; | |
} | |
/** | |
* If $key is empty, checks whether there's any data in the object | |
* Otherwise checks if the specified attribute is set. | |
* | |
* @param string $key | |
* @return boolean | |
*/ | |
public function hasData($key='') | |
{ | |
if (empty($key) || !is_string($key)) { | |
return !empty($this->_data); | |
} | |
return array_key_exists($key, $this->_data); | |
} | |
/** | |
* Convert object attributes to array | |
* | |
* @param array $arrAttributes array of required attributes | |
* @return array | |
*/ | |
public function __toArray(array $arrAttributes = array()) | |
{ | |
if (empty($arrAttributes)) { | |
return $this->_data; | |
} | |
$arrRes = array(); | |
foreach ($arrAttributes as $attribute) { | |
if (isset($this->_data[$attribute])) { | |
$arrRes[$attribute] = $this->_data[$attribute]; | |
} | |
else { | |
$arrRes[$attribute] = null; | |
} | |
} | |
return $arrRes; | |
} | |
/** | |
* Public wrapper for __toArray | |
* | |
* @param array $arrAttributes | |
* @return array | |
*/ | |
public function toArray(array $arrAttributes = array()) | |
{ | |
return $this->__toArray($arrAttributes); | |
} | |
/** | |
* Set required array elements | |
* | |
* @param array $arr | |
* @param array $elements | |
* @return array | |
*/ | |
protected function _prepareArray(&$arr, array $elements=array()) | |
{ | |
foreach ($elements as $element) { | |
if (!isset($arr[$element])) { | |
$arr[$element] = null; | |
} | |
} | |
return $arr; | |
} | |
/** | |
* Convert object attributes to XML | |
* | |
* @param array $arrAttributes array of required attributes | |
* @param string $rootName name of the root element | |
* @return string | |
*/ | |
protected function __toXml(array $arrAttributes = array(), $rootName = 'item', $addOpenTag=false, $addCdata=true) | |
{ | |
$xml = ''; | |
if ($addOpenTag) { | |
$xml.= '<?xml version="1.0" encoding="UTF-8"?>'."\n"; | |
} | |
if (!empty($rootName)) { | |
$xml.= '<'.$rootName.'>'."\n"; | |
} | |
$xmlModel = new Varien_Simplexml_Element('<node></node>'); | |
$arrData = $this->toArray($arrAttributes); | |
foreach ($arrData as $fieldName => $fieldValue) { | |
if ($addCdata === true) { | |
$fieldValue = "<![CDATA[$fieldValue]]>"; | |
} else { | |
$fieldValue = $xmlModel->xmlentities($fieldValue); | |
} | |
$xml.= "<$fieldName>$fieldValue</$fieldName>"."\n"; | |
} | |
if (!empty($rootName)) { | |
$xml.= '</'.$rootName.'>'."\n"; | |
} | |
return $xml; | |
} | |
/** | |
* Public wrapper for __toXml | |
* | |
* @param array $arrAttributes | |
* @param string $rootName | |
* @return string | |
*/ | |
public function toXml(array $arrAttributes = array(), $rootName = 'item', $addOpenTag=false, $addCdata=true) | |
{ | |
return $this->__toXml($arrAttributes, $rootName, $addOpenTag, $addCdata); | |
} | |
/** | |
* Convert object attributes to JSON | |
* | |
* @param array $arrAttributes array of required attributes | |
* @return string | |
*/ | |
protected function __toJson(array $arrAttributes = array()) | |
{ | |
$arrData = $this->toArray($arrAttributes); | |
$json = Zend_Json::encode($arrData); | |
return $json; | |
} | |
/** | |
* Public wrapper for __toJson | |
* | |
* @param array $arrAttributes | |
* @return string | |
*/ | |
public function toJson(array $arrAttributes = array()) | |
{ | |
return $this->__toJson($arrAttributes); | |
} | |
/** | |
* Convert object attributes to string | |
* | |
* @param array $arrAttributes array of required attributes | |
* @param string $valueSeparator | |
* @return string | |
*/ | |
// public function __toString(array $arrAttributes = array(), $valueSeparator=',') | |
// { | |
// $arrData = $this->toArray($arrAttributes); | |
// return implode($valueSeparator, $arrData); | |
// } | |
/** | |
* Public wrapper for __toString | |
* | |
* Will use $format as an template and substitute {{key}} for attributes | |
* | |
* @param string $format | |
* @return string | |
*/ | |
public function toString($format='') | |
{ | |
if (empty($format)) { | |
$str = implode(', ', $this->getData()); | |
} else { | |
preg_match_all('/\{\{([a-z0-9_]+)\}\}/is', $format, $matches); | |
foreach ($matches[1] as $var) { | |
$format = str_replace('{{'.$var.'}}', $this->getData($var), $format); | |
} | |
$str = $format; | |
} | |
return $str; | |
} | |
/** | |
* Set/Get attribute wrapper | |
* | |
* @param string $method | |
* @param array $args | |
* @return mixed | |
*/ | |
public function __call($method, $args) | |
{ | |
switch (substr($method, 0, 3)) { | |
case 'get' : | |
//Varien_Profiler::start('GETTER: '.get_class($this).'::'.$method); | |
$key = $this->_underscore(substr($method,3)); | |
$data = $this->getData($key, isset($args[0]) ? $args[0] : null); | |
//Varien_Profiler::stop('GETTER: '.get_class($this).'::'.$method); | |
return $data; | |
case 'set' : | |
//Varien_Profiler::start('SETTER: '.get_class($this).'::'.$method); | |
$key = $this->_underscore(substr($method,3)); | |
$result = $this->setData($key, isset($args[0]) ? $args[0] : null); | |
//Varien_Profiler::stop('SETTER: '.get_class($this).'::'.$method); | |
return $result; | |
case 'uns' : | |
//Varien_Profiler::start('UNS: '.get_class($this).'::'.$method); | |
$key = $this->_underscore(substr($method,3)); | |
$result = $this->unsetData($key); | |
//Varien_Profiler::stop('UNS: '.get_class($this).'::'.$method); | |
return $result; | |
case 'has' : | |
//Varien_Profiler::start('HAS: '.get_class($this).'::'.$method); | |
$key = $this->_underscore(substr($method,3)); | |
//Varien_Profiler::stop('HAS: '.get_class($this).'::'.$method); | |
return isset($this->_data[$key]); | |
} | |
throw new Varien_Exception("Invalid method ".get_class($this)."::".$method."(".print_r($args,1).")"); | |
} | |
/** | |
* Attribute getter (deprecated) | |
* | |
* @param string $var | |
* @return mixed | |
*/ | |
public function __get($var) | |
{ | |
$var = $this->_underscore($var); | |
return $this->getData($var); | |
} | |
/** | |
* Attribute setter (deprecated) | |
* | |
* @param string $var | |
* @param mixed $value | |
*/ | |
public function __set($var, $value) | |
{ | |
$var = $this->_underscore($var); | |
$this->setData($var, $value); | |
} | |
/** | |
* checks whether the object is empty | |
* | |
* @return boolean | |
*/ | |
public function isEmpty() | |
{ | |
if (empty($this->_data)) { | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Converts field names for setters and geters | |
* | |
* $this->setMyField($value) === $this->setData('my_field', $value) | |
* Uses cache to eliminate unneccessary preg_replace | |
* | |
* @param string $name | |
* @return string | |
*/ | |
protected function _underscore($name) | |
{ | |
if (isset(self::$_underscoreCache[$name])) { | |
return self::$_underscoreCache[$name]; | |
} | |
#Varien_Profiler::start('underscore'); | |
$result = strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $name)); | |
#Varien_Profiler::stop('underscore'); | |
self::$_underscoreCache[$name] = $result; | |
return $result; | |
} | |
protected function _camelize($name) | |
{ | |
return uc_words($name, ''); | |
} | |
/** | |
* serialize object attributes | |
* | |
* @param array $attributes | |
* @param string $valueSeparator | |
* @param string $fieldSeparator | |
* @param string $quote | |
* @return string | |
*/ | |
public function serialize($attributes = array(), $valueSeparator='=', $fieldSeparator=' ', $quote='"') | |
{ | |
$res = ''; | |
$data = array(); | |
if (empty($attributes)) { | |
$attributes = array_keys($this->_data); | |
} | |
foreach ($this->_data as $key => $value) { | |
if (in_array($key, $attributes)) { | |
$data[] = $key . $valueSeparator . $quote . $value . $quote; | |
} | |
} | |
$res = implode($fieldSeparator, $data); | |
return $res; | |
} | |
/** | |
* Get object loaded data (original data) | |
* | |
* @param string $key | |
* @return mixed | |
*/ | |
public function getOrigData($key=null) | |
{ | |
if (is_null($key)) { | |
return $this->_origData; | |
} | |
return isset($this->_origData[$key]) ? $this->_origData[$key] : null; | |
} | |
/** | |
* Initialize object original data | |
* | |
* @param string $key | |
* @param mixed $data | |
* @return Varien_Object | |
*/ | |
public function setOrigData($key=null, $data=null) | |
{ | |
if (is_null($key)) { | |
$this->_origData = $this->_data; | |
} else { | |
$this->_origData[$key] = $data; | |
} | |
return $this; | |
} | |
/** | |
* Compare object data with original data | |
* | |
* @param string $field | |
* @return boolean | |
*/ | |
public function dataHasChangedFor($field) | |
{ | |
$newData = $this->getData($field); | |
$origData = $this->getOrigData($field); | |
return $newData!=$origData; | |
} | |
/** | |
* Clears data changes status | |
* | |
* @param boolean $value | |
* @return Varien_Object | |
*/ | |
public function setDataChanges($value) | |
{ | |
$this->_hasDataChanges = (bool)$value; | |
return $this; | |
} | |
/** | |
* Present object data as string in debug mode | |
* | |
* @param mixed $data | |
* @param array $objects | |
* @return string | |
*/ | |
public function debug($data=null, &$objects=array()) | |
{ | |
if (is_null($data)) { | |
$hash = spl_object_hash($this); | |
if (!empty($objects[$hash])) { | |
return '*** RECURSION ***'; | |
} | |
$objects[$hash] = true; | |
$data = $this->getData(); | |
} | |
$debug = array(); | |
foreach ($data as $key=>$value) { | |
if (is_scalar($value)) { | |
$debug[$key] = $value; | |
} elseif (is_array($value)) { | |
$debug[$key] = $this->debug($value, $objects); | |
} elseif ($value instanceof Varien_Object) { | |
$debug[$key.' ('.get_class($value).')'] = $value->debug(null, $objects); | |
} | |
} | |
return $debug; | |
} | |
/** | |
* Implementation of ArrayAccess::offsetSet() | |
* | |
* @link http://www.php.net/manual/en/arrayaccess.offsetset.php | |
* @param string $offset | |
* @param mixed $value | |
*/ | |
public function offsetSet($offset, $value) | |
{ | |
$this->_data[$offset] = $value; | |
} | |
/** | |
* Implementation of ArrayAccess::offsetExists() | |
* | |
* @link http://www.php.net/manual/en/arrayaccess.offsetexists.php | |
* @param string $offset | |
* @return boolean | |
*/ | |
public function offsetExists($offset) | |
{ | |
return isset($this->_data[$offset]); | |
} | |
/** | |
* Implementation of ArrayAccess::offsetUnset() | |
* | |
* @link http://www.php.net/manual/en/arrayaccess.offsetunset.php | |
* @param string $offset | |
*/ | |
public function offsetUnset($offset) | |
{ | |
unset($this->_data[$offset]); | |
} | |
/** | |
* Implementation of ArrayAccess::offsetGet() | |
* | |
* @link http://www.php.net/manual/en/arrayaccess.offsetget.php | |
* @param string $offset | |
* @return mixed | |
*/ | |
public function offsetGet($offset) | |
{ | |
return isset($this->_data[$offset]) ? $this->_data[$offset] : null; | |
} | |
/** | |
* Enter description here... | |
* | |
* @param string $field | |
* @return boolean | |
*/ | |
public function isDirty($field=null) | |
{ | |
if (empty($this->_dirty)) { | |
return false; | |
} | |
if (is_null($field)) { | |
return true; | |
} | |
return isset($this->_dirty[$field]); | |
} | |
/** | |
* Enter description here... | |
* | |
* @param string $field | |
* @param boolean $flag | |
* @return Varien_Object | |
*/ | |
public function flagDirty($field, $flag=true) | |
{ | |
if (is_null($field)) { | |
foreach ($this->getData() as $field=>$value) { | |
$this->flagDirty($field, $flag); | |
} | |
} else { | |
if ($flag) { | |
$this->_dirty[$field] = true; | |
} else { | |
unset($this->_dirty[$field]); | |
} | |
} | |
return $this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment