123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework;
- /**
- * Universal data container with array access implementation
- *
- * @api
- * @SuppressWarnings(PHPMD.NumberOfChildren)
- * @since 100.0.2
- */
- class DataObject implements \ArrayAccess
- {
- /**
- * Object attributes
- *
- * @var array
- */
- protected $_data = [];
- /**
- * Setter/Getter underscore transformation cache
- *
- * @var array
- */
- protected static $_underscoreCache = [];
- /**
- * Constructor
- *
- * By default is looking for first argument as array and assigns it as object attributes
- * This behavior may change in child classes
- *
- * @param array $data
- */
- public function __construct(array $data = [])
- {
- $this->_data = $data;
- }
- /**
- * Add data to the object.
- *
- * Retains previous data in the object.
- *
- * @param array $arr
- * @return $this
- */
- public function addData(array $arr)
- {
- foreach ($arr as $index => $value) {
- $this->setData($index, $value);
- }
- return $this;
- }
- /**
- * Overwrite data in the object.
- *
- * The $key parameter 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 $this
- */
- public function setData($key, $value = null)
- {
- if ($key === (array)$key) {
- $this->_data = $key;
- } else {
- $this->_data[$key] = $value;
- }
- return $this;
- }
- /**
- * Unset data from the object.
- *
- * @param null|string|array $key
- * @return $this
- */
- public function unsetData($key = null)
- {
- if ($key === null) {
- $this->setData([]);
- } elseif (is_string($key)) {
- if (isset($this->_data[$key]) || array_key_exists($key, $this->_data)) {
- unset($this->_data[$key]);
- }
- } elseif ($key === (array)$key) {
- foreach ($key as $element) {
- $this->unsetData($element);
- }
- }
- return $this;
- }
- /**
- * Object data getter
- *
- * If $key is not defined will return all the data as an array.
- * Otherwise it will return value of the element specified by $key.
- * It is possible to use keys like a/b/c for access nested array data
- *
- * If $index is specified it will assume that attribute data is an array
- * and retrieve corresponding member. If data is the string - it will be explode
- * by new line character and converted to array.
- *
- * @param string $key
- * @param string|int $index
- * @return mixed
- */
- public function getData($key = '', $index = null)
- {
- if ('' === $key) {
- return $this->_data;
- }
- /* process a/b/c key as ['a']['b']['c'] */
- if (strpos($key, '/') !== false) {
- $data = $this->getDataByPath($key);
- } else {
- $data = $this->_getData($key);
- }
- if ($index !== null) {
- if ($data === (array)$data) {
- $data = isset($data[$index]) ? $data[$index] : null;
- } elseif (is_string($data)) {
- $data = explode(PHP_EOL, $data);
- $data = isset($data[$index]) ? $data[$index] : null;
- } elseif ($data instanceof \Magento\Framework\DataObject) {
- $data = $data->getData($index);
- } else {
- $data = null;
- }
- }
- return $data;
- }
- /**
- * Get object data by path
- *
- * Method consider the path as chain of keys: a/b/c => ['a']['b']['c']
- *
- * @param string $path
- * @return mixed
- */
- public function getDataByPath($path)
- {
- $keys = explode('/', $path);
- $data = $this->_data;
- foreach ($keys as $key) {
- if ((array)$data === $data && isset($data[$key])) {
- $data = $data[$key];
- } elseif ($data instanceof \Magento\Framework\DataObject) {
- $data = $data->getDataByKey($key);
- } else {
- return null;
- }
- }
- return $data;
- }
- /**
- * Get object data by particular key
- *
- * @param string $key
- * @return mixed
- */
- public function getDataByKey($key)
- {
- return $this->_getData($key);
- }
- /**
- * Get value from _data array without parse key
- *
- * @param string $key
- * @return mixed
- */
- protected function _getData($key)
- {
- if (isset($this->_data[$key])) {
- return $this->_data[$key];
- }
- return null;
- }
- /**
- * Set object data with calling setter method
- *
- * @param string $key
- * @param mixed $args
- * @return $this
- */
- public function setDataUsingMethod($key, $args = [])
- {
- $method = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $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' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
- return $this->{$method}($args);
- }
- /**
- * 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 bool
- */
- public function hasData($key = '')
- {
- if (empty($key) || !is_string($key)) {
- return !empty($this->_data);
- }
- return array_key_exists($key, $this->_data);
- }
- /**
- * Convert array of object data with to array with keys requested in $keys array
- *
- * @param array $keys array of required keys
- * @return array
- */
- public function toArray(array $keys = [])
- {
- if (empty($keys)) {
- return $this->_data;
- }
- $result = [];
- foreach ($keys as $key) {
- if (isset($this->_data[$key])) {
- $result[$key] = $this->_data[$key];
- } else {
- $result[$key] = null;
- }
- }
- return $result;
- }
- /**
- * The "__" style wrapper for toArray method
- *
- * @param array $keys
- * @return array
- */
- public function convertToArray(array $keys = [])
- {
- return $this->toArray($keys);
- }
- /**
- * Convert object data into XML string
- *
- * @param array $keys array of keys that must be represented
- * @param string $rootName root node name
- * @param bool $addOpenTag flag that allow to add initial xml node
- * @param bool $addCdata flag that require wrap all values in CDATA
- * @return string
- */
- public function toXml(array $keys = [], $rootName = 'item', $addOpenTag = false, $addCdata = true)
- {
- $xml = '';
- $data = $this->toArray($keys);
- foreach ($data as $fieldName => $fieldValue) {
- if ($addCdata === true) {
- $fieldValue = "<![CDATA[{$fieldValue}]]>";
- } else {
- $fieldValue = str_replace(
- ['&', '"', "'", '<', '>'],
- ['&', '"', ''', '<', '>'],
- $fieldValue
- );
- }
- $xml .= "<{$fieldName}>{$fieldValue}</{$fieldName}>\n";
- }
- if ($rootName) {
- $xml = "<{$rootName}>\n{$xml}</{$rootName}>\n";
- }
- if ($addOpenTag) {
- $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $xml;
- }
- return $xml;
- }
- /**
- * The "__" style wrapper for toXml method
- *
- * @param array $arrAttributes array of keys that must be represented
- * @param string $rootName root node name
- * @param bool $addOpenTag flag that allow to add initial xml node
- * @param bool $addCdata flag that require wrap all values in CDATA
- * @return string
- */
- public function convertToXml(
- array $arrAttributes = [],
- $rootName = 'item',
- $addOpenTag = false,
- $addCdata = true
- ) {
- return $this->toXml($arrAttributes, $rootName, $addOpenTag, $addCdata);
- }
- /**
- * Convert object data to JSON
- *
- * @param array $keys array of required keys
- * @return bool|string
- * @throws \InvalidArgumentException
- */
- public function toJson(array $keys = [])
- {
- $data = $this->toArray($keys);
- return \Magento\Framework\Serialize\JsonConverter::convert($data);
- }
- /**
- * The "__" style wrapper for toJson
- *
- * @param array $keys
- * @return bool|string
- * @throws \InvalidArgumentException
- */
- public function convertToJson(array $keys = [])
- {
- return $this->toJson($keys);
- }
- /**
- * Convert object data into string with predefined format
- *
- * Will use $format as an template and substitute {{key}} for attributes
- *
- * @param string $format
- * @return string
- */
- public function toString($format = '')
- {
- if (empty($format)) {
- $result = 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);
- }
- $result = $format;
- }
- return $result;
- }
- /**
- * Set/Get attribute wrapper
- *
- * @param string $method
- * @param array $args
- * @return mixed
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function __call($method, $args)
- {
- switch (substr($method, 0, 3)) {
- case 'get':
- $key = $this->_underscore(substr($method, 3));
- $index = isset($args[0]) ? $args[0] : null;
- return $this->getData($key, $index);
- case 'set':
- $key = $this->_underscore(substr($method, 3));
- $value = isset($args[0]) ? $args[0] : null;
- return $this->setData($key, $value);
- case 'uns':
- $key = $this->_underscore(substr($method, 3));
- return $this->unsetData($key);
- case 'has':
- $key = $this->_underscore(substr($method, 3));
- return isset($this->_data[$key]);
- }
- throw new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase('Invalid method %1::%2', [get_class($this), $method])
- );
- }
- /**
- * Checks whether the object is empty
- *
- * @return bool
- */
- public function isEmpty()
- {
- if (empty($this->_data)) {
- return true;
- }
- return false;
- }
- /**
- * Converts field names for setters and getters
- *
- * $this->setMyField($value) === $this->setData('my_field', $value)
- * Uses cache to eliminate unnecessary preg_replace
- *
- * @param string $name
- * @return string
- */
- protected function _underscore($name)
- {
- if (isset(self::$_underscoreCache[$name])) {
- return self::$_underscoreCache[$name];
- }
- $result = strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
- self::$_underscoreCache[$name] = $result;
- return $result;
- }
- /**
- * Convert object data into string with defined keys and values.
- *
- * Example: key1="value1" key2="value2" ...
- *
- * @param array $keys array of accepted keys
- * @param string $valueSeparator separator between key and value
- * @param string $fieldSeparator separator between key/value pairs
- * @param string $quote quoting sign
- * @return string
- */
- public function serialize($keys = [], $valueSeparator = '=', $fieldSeparator = ' ', $quote = '"')
- {
- $data = [];
- if (empty($keys)) {
- $keys = array_keys($this->_data);
- }
- foreach ($this->_data as $key => $value) {
- if (in_array($key, $keys)) {
- $data[] = $key . $valueSeparator . $quote . $value . $quote;
- }
- }
- $res = implode($fieldSeparator, $data);
- return $res;
- }
- /**
- * Present object data as string in debug mode
- *
- * @param mixed $data
- * @param array &$objects
- * @return array
- */
- public function debug($data = null, &$objects = [])
- {
- if ($data === null) {
- $hash = spl_object_hash($this);
- if (!empty($objects[$hash])) {
- return '*** RECURSION ***';
- }
- $objects[$hash] = true;
- $data = $this->getData();
- }
- $debug = [];
- 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 \Magento\Framework\DataObject) {
- $debug[$key . ' (' . get_class($value) . ')'] = $value->debug(null, $objects);
- }
- }
- return $debug;
- }
- /**
- * Implementation of \ArrayAccess::offsetSet()
- *
- * @param string $offset
- * @param mixed $value
- * @return void
- * @link http://www.php.net/manual/en/arrayaccess.offsetset.php
- */
- public function offsetSet($offset, $value)
- {
- $this->_data[$offset] = $value;
- }
- /**
- * Implementation of \ArrayAccess::offsetExists()
- *
- * @param string $offset
- * @return bool
- * @link http://www.php.net/manual/en/arrayaccess.offsetexists.php
- */
- public function offsetExists($offset)
- {
- return isset($this->_data[$offset]) || array_key_exists($offset, $this->_data);
- }
- /**
- * Implementation of \ArrayAccess::offsetUnset()
- *
- * @param string $offset
- * @return void
- * @link http://www.php.net/manual/en/arrayaccess.offsetunset.php
- */
- public function offsetUnset($offset)
- {
- unset($this->_data[$offset]);
- }
- /**
- * Implementation of \ArrayAccess::offsetGet()
- *
- * @param string $offset
- * @return mixed
- * @link http://www.php.net/manual/en/arrayaccess.offsetget.php
- */
- public function offsetGet($offset)
- {
- if (isset($this->_data[$offset])) {
- return $this->_data[$offset];
- }
- return null;
- }
- }
|