PageRenderTime 163ms CodeModel.GetById 80ms app.highlight 45ms RepoModel.GetById 32ms app.codeStats 0ms

/lib/Varien/Object.php

https://bitbucket.org/claudiu_marginean/magento-hg-mirror
PHP | 835 lines | 397 code | 64 blank | 374 comment | 52 complexity | 4f1f5be02d88e61362fcaed4ad188a28 MD5 | raw file
  1<?php
  2/**
  3 * Magento
  4 *
  5 * NOTICE OF LICENSE
  6 *
  7 * This source file is subject to the Open Software License (OSL 3.0)
  8 * that is bundled with this package in the file LICENSE.txt.
  9 * It is also available through the world-wide-web at this URL:
 10 * http://opensource.org/licenses/osl-3.0.php
 11 * If you did not receive a copy of the license and are unable to
 12 * obtain it through the world-wide-web, please send an email
 13 * to license@magentocommerce.com so we can send you a copy immediately.
 14 *
 15 * DISCLAIMER
 16 *
 17 * Do not edit or add to this file if you wish to upgrade Magento to newer
 18 * versions in the future. If you wish to customize Magento for your
 19 * needs please refer to http://www.magentocommerce.com for more information.
 20 *
 21 * @category   Varien
 22 * @package    Varien_Object
 23 * @copyright  Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
 24 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 25 */
 26
 27
 28/**
 29 * Varien Object
 30 *
 31 * @category   Varien
 32 * @package    Varien_Object
 33 * @author      Magento Core Team <core@magentocommerce.com>
 34 */
 35class Varien_Object implements ArrayAccess
 36{
 37
 38    /**
 39     * Object attributes
 40     *
 41     * @var array
 42     */
 43    protected $_data = array();
 44
 45    /**
 46     * Data changes flag (true after setData|unsetData call)
 47     * @var $_hasDataChange bool
 48     */
 49    protected $_hasDataChanges = false;
 50
 51    /**
 52    * Original data that was loaded
 53    *
 54    * @var array
 55    */
 56    protected $_origData;
 57
 58    /**
 59     * Name of object id field
 60     *
 61     * @var string
 62     */
 63    protected $_idFieldName = null;
 64
 65    /**
 66     * Setter/Getter underscore transformation cache
 67     *
 68     * @var array
 69     */
 70    protected static $_underscoreCache = array();
 71
 72    /**
 73     * Object delete flag
 74     *
 75     * @var boolean
 76     */
 77    protected $_isDeleted = false;
 78
 79    /**
 80     * Constructor
 81     *
 82     * By default is looking for first argument as array and assignes it as object attributes
 83     * This behaviour may change in child classes
 84     *
 85     */
 86    public function __construct()
 87    {
 88        $args = func_get_args();
 89        if (empty($args[0])) {
 90            $args[0] = array();
 91        }
 92        $this->_data = $args[0];
 93
 94        $this->_construct();
 95    }
 96
 97    /**
 98     * Internal constructor not depended on params. Can be used for object initialization
 99     */
100    protected function _construct()
101    {
102    }
103
104    /**
105     * Set _isDeleted flag value (if $isDeleted param is defined) and return current flag value
106     *
107     * @param boolean $isDeleted
108     * @return boolean
109     */
110    public function isDeleted($isDeleted=null)
111    {
112        $result = $this->_isDeleted;
113        if (!is_null($isDeleted)) {
114            $this->_isDeleted = $isDeleted;
115        }
116        return $result;
117    }
118
119    /**
120     * Get data change status
121     *
122     * @return bool
123     */
124    public function hasDataChanges()
125    {
126        return $this->_hasDataChanges;
127    }
128
129    /**
130     * set name of object id field
131     *
132     * @param   string $name
133     * @return  Varien_Object
134     */
135    public function setIdFieldName($name)
136    {
137        $this->_idFieldName = $name;
138        return $this;
139    }
140
141    /**
142     * Retrieve name of object id field
143     *
144     * @param   string $name
145     * @return  Varien_Object
146     */
147    public function getIdFieldName()
148    {
149        return $this->_idFieldName;
150    }
151
152    /**
153     * Retrieve object id
154     *
155     * @return mixed
156     */
157    public function getId()
158    {
159        if ($this->getIdFieldName()) {
160            return $this->_getData($this->getIdFieldName());
161        }
162        return $this->_getData('id');
163    }
164
165    /**
166     * Set object id field value
167     *
168     * @param   mixed $value
169     * @return  Varien_Object
170     */
171    public function setId($value)
172    {
173        if ($this->getIdFieldName()) {
174            $this->setData($this->getIdFieldName(), $value);
175        } else {
176            $this->setData('id', $value);
177        }
178        return $this;
179    }
180
181    /**
182     * Add data to the object.
183     *
184     * Retains previous data in the object.
185     *
186     * @param array $arr
187     * @return Varien_Object
188     */
189    public function addData(array $arr)
190    {
191        foreach($arr as $index=>$value) {
192            $this->setData($index, $value);
193        }
194        return $this;
195    }
196
197    /**
198     * Overwrite data in the object.
199     *
200     * $key can be string or array.
201     * If $key is string, the attribute value will be overwritten by $value
202     *
203     * If $key is an array, it will overwrite all the data in the object.
204     *
205     * @param string|array $key
206     * @param mixed $value
207     * @return Varien_Object
208     */
209    public function setData($key, $value=null)
210    {
211        $this->_hasDataChanges = true;
212        if(is_array($key)) {
213            $this->_data = $key;
214        } else {
215            $this->_data[$key] = $value;
216        }
217        return $this;
218    }
219
220    /**
221     * Unset data from the object.
222     *
223     * $key can be a string only. Array will be ignored.
224     *
225     * @param string $key
226     * @return Varien_Object
227     */
228    public function unsetData($key=null)
229    {
230        $this->_hasDataChanges = true;
231        if (is_null($key)) {
232            $this->_data = array();
233        } else {
234            unset($this->_data[$key]);
235        }
236        return $this;
237    }
238
239    /**
240     * Retrieves data from the object
241     *
242     * If $key is empty will return all the data as an array
243     * Otherwise it will return value of the attribute specified by $key
244     *
245     * If $index is specified it will assume that attribute data is an array
246     * and retrieve corresponding member.
247     *
248     * @param string $key
249     * @param string|int $index
250     * @return mixed
251     */
252    public function getData($key='', $index=null)
253    {
254        if (''===$key) {
255            return $this->_data;
256        }
257
258        $default = null;
259
260        // accept a/b/c as ['a']['b']['c']
261        if (strpos($key,'/')) {
262            $keyArr = explode('/', $key);
263            $data = $this->_data;
264            foreach ($keyArr as $i=>$k) {
265                if ($k==='') {
266                    return $default;
267                }
268                if (is_array($data)) {
269                    if (!isset($data[$k])) {
270                        return $default;
271                    }
272                    $data = $data[$k];
273                } elseif ($data instanceof Varien_Object) {
274                    $data = $data->getData($k);
275                } else {
276                    return $default;
277                }
278            }
279            return $data;
280        }
281
282        // legacy functionality for $index
283        if (isset($this->_data[$key])) {
284            if (is_null($index)) {
285                return $this->_data[$key];
286            }
287
288            $value = $this->_data[$key];
289            if (is_array($value)) {
290                //if (isset($value[$index]) && (!empty($value[$index]) || strlen($value[$index]) > 0)) {
291                /**
292                 * If we have any data, even if it empty - we should use it, anyway
293                 */
294                if (isset($value[$index])) {
295                    return $value[$index];
296                }
297                return null;
298            } elseif (is_string($value)) {
299                $arr = explode("\n", $value);
300                return (isset($arr[$index]) && (!empty($arr[$index]) || strlen($arr[$index]) > 0)) ? $arr[$index] : null;
301            } elseif ($value instanceof Varien_Object) {
302                return $value->getData($index);
303            }
304            return $default;
305        }
306        return $default;
307    }
308
309    /**
310     * Get value from _data array without parse key
311     *
312     * @param   string $key
313     * @return  mixed
314     */
315    protected function _getData($key)
316    {
317        return isset($this->_data[$key]) ? $this->_data[$key] : null;
318    }
319
320    /**
321     * Set object data with calling setter method
322     *
323     * @param string $key
324     * @param mixed $args
325     * @return Varien_Object
326     */
327    public function setDataUsingMethod($key, $args=array())
328    {
329        $method = 'set'.$this->_camelize($key);
330        $this->$method($args);
331        return $this;
332    }
333
334    /**
335     * Get object data by key with calling getter method
336     *
337     * @param string $key
338     * @param mixed $args
339     * @return mixed
340     */
341    public function getDataUsingMethod($key, $args=null)
342    {
343        $method = 'get'.$this->_camelize($key);
344        return $this->$method($args);
345    }
346
347    /**
348     * Fast get data or set default if value is not available
349     *
350     * @param string $key
351     * @param mixed $default
352     * @return mixed
353     */
354    public function getDataSetDefault($key, $default)
355    {
356        if (!isset($this->_data[$key])) {
357            $this->_data[$key] = $default;
358        }
359        return $this->_data[$key];
360    }
361
362    /**
363     * If $key is empty, checks whether there's any data in the object
364     * Otherwise checks if the specified attribute is set.
365     *
366     * @param string $key
367     * @return boolean
368     */
369    public function hasData($key='')
370    {
371        if (empty($key) || !is_string($key)) {
372            return !empty($this->_data);
373        }
374        return array_key_exists($key, $this->_data);
375    }
376
377    /**
378     * Convert object attributes to array
379     *
380     * @param  array $arrAttributes array of required attributes
381     * @return array
382     */
383    public function __toArray(array $arrAttributes = array())
384    {
385        if (empty($arrAttributes)) {
386            return $this->_data;
387        }
388
389        $arrRes = array();
390        foreach ($arrAttributes as $attribute) {
391            if (isset($this->_data[$attribute])) {
392                $arrRes[$attribute] = $this->_data[$attribute];
393            }
394            else {
395                $arrRes[$attribute] = null;
396            }
397        }
398        return $arrRes;
399    }
400
401    /**
402     * Public wrapper for __toArray
403     *
404     * @param array $arrAttributes
405     * @return array
406     */
407    public function toArray(array $arrAttributes = array())
408    {
409        return $this->__toArray($arrAttributes);
410    }
411
412    /**
413     * Set required array elements
414     *
415     * @param   array $arr
416     * @param   array $elements
417     * @return  array
418     */
419    protected function _prepareArray(&$arr, array $elements=array())
420    {
421        foreach ($elements as $element) {
422            if (!isset($arr[$element])) {
423                $arr[$element] = null;
424            }
425        }
426        return $arr;
427    }
428
429    /**
430     * Convert object attributes to XML
431     *
432     * @param  array $arrAttributes array of required attributes
433     * @param string $rootName name of the root element
434     * @return string
435     */
436    protected function __toXml(array $arrAttributes = array(), $rootName = 'item', $addOpenTag=false, $addCdata=true)
437    {
438        $xml = '';
439        if ($addOpenTag) {
440            $xml.= '<?xml version="1.0" encoding="UTF-8"?>'."\n";
441        }
442        if (!empty($rootName)) {
443            $xml.= '<'.$rootName.'>'."\n";
444        }
445        $xmlModel = new Varien_Simplexml_Element('<node></node>');
446        $arrData = $this->toArray($arrAttributes);
447        foreach ($arrData as $fieldName => $fieldValue) {
448            if ($addCdata === true) {
449                $fieldValue = "<![CDATA[$fieldValue]]>";
450            } else {
451                $fieldValue = $xmlModel->xmlentities($fieldValue);
452            }
453            $xml.= "<$fieldName>$fieldValue</$fieldName>"."\n";
454        }
455        if (!empty($rootName)) {
456            $xml.= '</'.$rootName.'>'."\n";
457        }
458        return $xml;
459    }
460
461    /**
462     * Public wrapper for __toXml
463     *
464     * @param array $arrAttributes
465     * @param string $rootName
466     * @return string
467     */
468    public function toXml(array $arrAttributes = array(), $rootName = 'item', $addOpenTag=false, $addCdata=true)
469    {
470        return $this->__toXml($arrAttributes, $rootName, $addOpenTag, $addCdata);
471    }
472
473    /**
474     * Convert object attributes to JSON
475     *
476     * @param  array $arrAttributes array of required attributes
477     * @return string
478     */
479    protected function __toJson(array $arrAttributes = array())
480    {
481        $arrData = $this->toArray($arrAttributes);
482        $json = Zend_Json::encode($arrData);
483        return $json;
484    }
485
486    /**
487     * Public wrapper for __toJson
488     *
489     * @param array $arrAttributes
490     * @return string
491     */
492    public function toJson(array $arrAttributes = array())
493    {
494        return $this->__toJson($arrAttributes);
495    }
496
497    /**
498     * Convert object attributes to string
499     *
500     * @param  array  $arrAttributes array of required attributes
501     * @param  string $valueSeparator
502     * @return string
503     */
504//    public function __toString(array $arrAttributes = array(), $valueSeparator=',')
505//    {
506//        $arrData = $this->toArray($arrAttributes);
507//        return implode($valueSeparator, $arrData);
508//    }
509
510    /**
511     * Public wrapper for __toString
512     *
513     * Will use $format as an template and substitute {{key}} for attributes
514     *
515     * @param string $format
516     * @return string
517     */
518    public function toString($format='')
519    {
520        if (empty($format)) {
521            $str = implode(', ', $this->getData());
522        } else {
523            preg_match_all('/\{\{([a-z0-9_]+)\}\}/is', $format, $matches);
524            foreach ($matches[1] as $var) {
525                $format = str_replace('{{'.$var.'}}', $this->getData($var), $format);
526            }
527            $str = $format;
528        }
529        return $str;
530    }
531
532    /**
533     * Set/Get attribute wrapper
534     *
535     * @param   string $method
536     * @param   array $args
537     * @return  mixed
538     */
539    public function __call($method, $args)
540    {
541        switch (substr($method, 0, 3)) {
542            case 'get' :
543                //Varien_Profiler::start('GETTER: '.get_class($this).'::'.$method);
544                $key = $this->_underscore(substr($method,3));
545                $data = $this->getData($key, isset($args[0]) ? $args[0] : null);
546                //Varien_Profiler::stop('GETTER: '.get_class($this).'::'.$method);
547                return $data;
548
549            case 'set' :
550                //Varien_Profiler::start('SETTER: '.get_class($this).'::'.$method);
551                $key = $this->_underscore(substr($method,3));
552                $result = $this->setData($key, isset($args[0]) ? $args[0] : null);
553                //Varien_Profiler::stop('SETTER: '.get_class($this).'::'.$method);
554                return $result;
555
556            case 'uns' :
557                //Varien_Profiler::start('UNS: '.get_class($this).'::'.$method);
558                $key = $this->_underscore(substr($method,3));
559                $result = $this->unsetData($key);
560                //Varien_Profiler::stop('UNS: '.get_class($this).'::'.$method);
561                return $result;
562
563            case 'has' :
564                //Varien_Profiler::start('HAS: '.get_class($this).'::'.$method);
565                $key = $this->_underscore(substr($method,3));
566                //Varien_Profiler::stop('HAS: '.get_class($this).'::'.$method);
567                return isset($this->_data[$key]);
568        }
569        throw new Varien_Exception("Invalid method ".get_class($this)."::".$method."(".print_r($args,1).")");
570    }
571
572    /**
573     * Attribute getter (deprecated)
574     *
575     * @param string $var
576     * @return mixed
577     */
578
579    public function __get($var)
580    {
581        $var = $this->_underscore($var);
582        return $this->getData($var);
583    }
584
585    /**
586     * Attribute setter (deprecated)
587     *
588     * @param string $var
589     * @param mixed $value
590     */
591    public function __set($var, $value)
592    {
593        $var = $this->_underscore($var);
594        $this->setData($var, $value);
595    }
596
597    /**
598     * checks whether the object is empty
599     *
600     * @return boolean
601     */
602    public function isEmpty()
603    {
604        if (empty($this->_data)) {
605            return true;
606        }
607        return false;
608    }
609
610    /**
611     * Converts field names for setters and geters
612     *
613     * $this->setMyField($value) === $this->setData('my_field', $value)
614     * Uses cache to eliminate unneccessary preg_replace
615     *
616     * @param string $name
617     * @return string
618     */
619    protected function _underscore($name)
620    {
621        if (isset(self::$_underscoreCache[$name])) {
622            return self::$_underscoreCache[$name];
623        }
624        #Varien_Profiler::start('underscore');
625        $result = strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $name));
626        #Varien_Profiler::stop('underscore');
627        self::$_underscoreCache[$name] = $result;
628        return $result;
629    }
630
631    protected function _camelize($name)
632    {
633        return uc_words($name, '');
634    }
635
636    /**
637     * serialize object attributes
638     *
639     * @param   array $attributes
640     * @param   string $valueSeparator
641     * @param   string $fieldSeparator
642     * @param   string $quote
643     * @return  string
644     */
645    public function serialize($attributes = array(), $valueSeparator='=', $fieldSeparator=' ', $quote='"')
646    {
647        $res  = '';
648        $data = array();
649        if (empty($attributes)) {
650            $attributes = array_keys($this->_data);
651        }
652
653        foreach ($this->_data as $key => $value) {
654            if (in_array($key, $attributes)) {
655                $data[] = $key . $valueSeparator . $quote . $value . $quote;
656            }
657        }
658        $res = implode($fieldSeparator, $data);
659        return $res;
660    }
661
662    /**
663     * Get object loaded data (original data)
664     *
665     * @param string $key
666     * @return mixed
667     */
668    public function getOrigData($key=null)
669    {
670        if (is_null($key)) {
671            return $this->_origData;
672        }
673        return isset($this->_origData[$key]) ? $this->_origData[$key] : null;
674    }
675
676    /**
677     * Initialize object original data
678     *
679     * @param string $key
680     * @param mixed $data
681     * @return Varien_Object
682     */
683    public function setOrigData($key=null, $data=null)
684    {
685        if (is_null($key)) {
686            $this->_origData = $this->_data;
687        } else {
688            $this->_origData[$key] = $data;
689        }
690        return $this;
691    }
692
693    /**
694     * Compare object data with original data
695     *
696     * @param string $field
697     * @return boolean
698     */
699    public function dataHasChangedFor($field)
700    {
701        $newData = $this->getData($field);
702        $origData = $this->getOrigData($field);
703        return $newData!=$origData;
704    }
705
706    /**
707     * Clears data changes status
708     *
709     * @param boolean $value
710     * @return Varien_Object
711     */
712    public function setDataChanges($value)
713    {
714        $this->_hasDataChanges = (bool)$value;
715        return $this;
716    }
717
718    /**
719     * Present object data as string in debug mode
720     *
721     * @param mixed $data
722     * @param array $objects
723     * @return string
724     */
725    public function debug($data=null, &$objects=array())
726    {
727        if (is_null($data)) {
728            $hash = spl_object_hash($this);
729            if (!empty($objects[$hash])) {
730                return '*** RECURSION ***';
731            }
732            $objects[$hash] = true;
733            $data = $this->getData();
734        }
735        $debug = array();
736        foreach ($data as $key=>$value) {
737            if (is_scalar($value)) {
738                $debug[$key] = $value;
739            } elseif (is_array($value)) {
740                $debug[$key] = $this->debug($value, $objects);
741            } elseif ($value instanceof Varien_Object) {
742                $debug[$key.' ('.get_class($value).')'] = $value->debug(null, $objects);
743            }
744        }
745        return $debug;
746    }
747
748    /**
749     * Implementation of ArrayAccess::offsetSet()
750     *
751     * @link http://www.php.net/manual/en/arrayaccess.offsetset.php
752     * @param string $offset
753     * @param mixed $value
754     */
755    public function offsetSet($offset, $value)
756    {
757        $this->_data[$offset] = $value;
758    }
759
760    /**
761     * Implementation of ArrayAccess::offsetExists()
762     *
763     * @link http://www.php.net/manual/en/arrayaccess.offsetexists.php
764     * @param string $offset
765     * @return boolean
766     */
767    public function offsetExists($offset)
768    {
769        return isset($this->_data[$offset]);
770    }
771
772    /**
773     * Implementation of ArrayAccess::offsetUnset()
774     *
775     * @link http://www.php.net/manual/en/arrayaccess.offsetunset.php
776     * @param string $offset
777     */
778    public function offsetUnset($offset)
779    {
780        unset($this->_data[$offset]);
781    }
782
783    /**
784     * Implementation of ArrayAccess::offsetGet()
785     *
786     * @link http://www.php.net/manual/en/arrayaccess.offsetget.php
787     * @param string $offset
788     * @return mixed
789     */
790    public function offsetGet($offset)
791    {
792        return isset($this->_data[$offset]) ? $this->_data[$offset] : null;
793    }
794
795
796    /**
797     * Enter description here...
798     *
799     * @param string $field
800     * @return boolean
801     */
802    public function isDirty($field=null)
803    {
804        if (empty($this->_dirty)) {
805            return false;
806        }
807        if (is_null($field)) {
808            return true;
809        }
810        return isset($this->_dirty[$field]);
811    }
812
813    /**
814     * Enter description here...
815     *
816     * @param string $field
817     * @param boolean $flag
818     * @return Varien_Object
819     */
820    public function flagDirty($field, $flag=true)
821    {
822        if (is_null($field)) {
823            foreach ($this->getData() as $field=>$value) {
824                $this->flagDirty($field, $flag);
825            }
826        } else {
827            if ($flag) {
828                $this->_dirty[$field] = true;
829            } else {
830                unset($this->_dirty[$field]);
831            }
832        }
833        return $this;
834    }
835}