/TypeConverter.php

https://bitbucket.org/adek23/type-converter · PHP · 508 lines · 263 code · 79 blank · 166 comment · 82 complexity · 39edaa5ce6d19a293667ce900492d81c MD5 · raw file

  1. <?php
  2. /**
  3. * @copyright Copyright 2006-2012, Miles Johnson - http://milesj.me
  4. * @license http://opensource.org/licenses/mit-license.php - Licensed under the MIT License
  5. * @link http://milesj.me/code/php/type-converter
  6. */
  7. namespace mjohnson\utility;
  8. /**
  9. * A class that handles the detection and conversion of certain resource formats / content types into other formats.
  10. * The current formats are supported: XML, JSON, Array, Object, Serialized
  11. *
  12. * @version 2.0.0
  13. * @package mjohnson.utility
  14. */
  15. class TypeConverter {
  16. /**
  17. * Disregard XML attributes and only return the value.
  18. */
  19. const XML_NONE = 0;
  20. /**
  21. * Merge attributes and the value into a single dimension; the values key will be "value".
  22. */
  23. const XML_MERGE = 1;
  24. /**
  25. * Group the attributes into a key "attributes" and the value into a key of "value".
  26. */
  27. const XML_GROUP = 2;
  28. /**
  29. * Attributes will only be returned.
  30. */
  31. const XML_OVERWRITE = 3;
  32. /**
  33. * Returns a string for the detected type.
  34. *
  35. * @access public
  36. * @param mixed $data
  37. * @return string
  38. * @static
  39. */
  40. public static function is($data) {
  41. if (self::isArray($data)) {
  42. return 'array';
  43. } else if (self::isObject($data)) {
  44. return 'object';
  45. } else if (self::isJson($data)) {
  46. return 'json';
  47. } else if (self::isSerialized($data)) {
  48. return 'serialized';
  49. } else if (self::isXml($data)) {
  50. return 'xml';
  51. }
  52. return 'other';
  53. }
  54. /**
  55. * Check to see if data passed is an array.
  56. *
  57. * @access public
  58. * @param mixed $data
  59. * @return boolean
  60. * @static
  61. */
  62. public static function isArray($data) {
  63. return is_array($data);
  64. }
  65. /**
  66. * Check to see if data passed is a JSON object.
  67. *
  68. * @access public
  69. * @param mixed $data
  70. * @return boolean
  71. * @static
  72. */
  73. public static function isJson($data) {
  74. return (@json_decode($data) !== null);
  75. }
  76. /**
  77. * Check to see if data passed is an object.
  78. *
  79. * @access public
  80. * @param mixed $data
  81. * @return boolean
  82. * @static
  83. */
  84. public static function isObject($data) {
  85. return is_object($data);
  86. }
  87. /**
  88. * Check to see if data passed has been serialized.
  89. *
  90. * @access public
  91. * @param mixed $data
  92. * @return boolean
  93. * @static
  94. */
  95. public static function isSerialized($data) {
  96. $ser = @unserialize($data);
  97. return ($ser !== false) ? $ser : false;
  98. }
  99. /**
  100. * Check to see if data passed is an XML document.
  101. *
  102. * @access public
  103. * @param mixed $data
  104. * @return boolean
  105. * @static
  106. */
  107. public static function isXml($data) {
  108. $xml = @simplexml_load_string($data);
  109. return ($xml instanceof SimpleXmlElement) ? $xml : false;
  110. }
  111. /**
  112. * Transforms a resource into an array.
  113. *
  114. * @access public
  115. * @param mixed $resource
  116. * @return array
  117. * @static
  118. */
  119. public static function toArray($resource) {
  120. if (self::isArray($resource)) {
  121. return $resource;
  122. } else if (self::isObject($resource)) {
  123. return self::buildArray($resource);
  124. } else if (self::isJson($resource)) {
  125. return json_decode($resource, true);
  126. } else if ($ser = self::isSerialized($resource)) {
  127. return self::toArray($ser);
  128. } else if ($xml = self::isXml($resource)) {
  129. return self::xmlToArray($xml);
  130. }
  131. return $resource;
  132. }
  133. /**
  134. * Transforms a resource into a JSON object.
  135. *
  136. * @access public
  137. * @param mixed $resource
  138. * @return string (json)
  139. * @static
  140. */
  141. public static function toJson($resource) {
  142. if (self::isJson($resource)) {
  143. return $resource;
  144. }
  145. if ($xml = self::isXml($resource)) {
  146. $resource = self::xmlToArray($xml);
  147. } else if ($ser = self::isSerialized($resource)) {
  148. $resource = $ser;
  149. }
  150. return json_encode($resource);
  151. }
  152. /**
  153. * Transforms a resource into an object.
  154. *
  155. * @access public
  156. * @param mixed $resource
  157. * @return object
  158. * @static
  159. */
  160. public static function toObject($resource) {
  161. if (self::isObject($resource)) {
  162. return $resource;
  163. } else if (self::isArray($resource)) {
  164. return self::buildObject($resource);
  165. } else if (self::isJson($resource)) {
  166. return json_decode($resource);
  167. } else if ($ser = self::isSerialized($resource)) {
  168. return self::toObject($ser);
  169. } else if ($xml = self::isXml($resource)) {
  170. return $xml;
  171. }
  172. return $resource;
  173. }
  174. /**
  175. * Transforms a resource into a serialized form.
  176. *
  177. * @access public
  178. * @param mixed $resource
  179. * @return string
  180. * @static
  181. */
  182. public static function toSerialize($resource) {
  183. if (!self::isArray($resource)) {
  184. $resource = self::toArray($resource);
  185. }
  186. return serialize($resource);
  187. }
  188. /**
  189. * Transforms a resource into an XML document.
  190. *
  191. * @access public
  192. * @param mixed $resource
  193. * @param string $root
  194. * @return string (xml)
  195. * @static
  196. */
  197. public static function toXml($resource, $root = 'root') {
  198. if (self::isXml($resource)) {
  199. return $resource;
  200. }
  201. $array = self::toArray($resource);
  202. if (!empty($array)) {
  203. $xml = simplexml_load_string('<?xml version="1.0" encoding="utf-8"?><'. $root .'></'. $root .'>');
  204. $response = self::buildXml($xml, $array);
  205. return $response->asXML();
  206. }
  207. return $resource;
  208. }
  209. /**
  210. * Turn an object into an array. Alternative to array_map magic.
  211. *
  212. * @access public
  213. * @param object $object
  214. * @return array
  215. */
  216. public static function buildArray($object) {
  217. $array = array();
  218. foreach ($object as $key => $value) {
  219. if (is_object($value)) {
  220. $array[$key] = self::buildArray($value);
  221. } else {
  222. $array[$key] = $value;
  223. }
  224. }
  225. return $array;
  226. }
  227. /**
  228. * Turn an array into an object. Alternative to array_map magic.
  229. *
  230. * @access public
  231. * @param array $array
  232. * @return object
  233. */
  234. public static function buildObject($array) {
  235. $obj = new \stdClass();
  236. foreach ($array as $key => $value) {
  237. if (is_array($value)) {
  238. $obj->{$key} = self::buildObject($value);
  239. } else {
  240. $obj->{$key} = $value;
  241. }
  242. }
  243. return $obj;
  244. }
  245. /**
  246. * Turn an array into an XML document. Alternative to array_map magic.
  247. *
  248. * @access public
  249. * @param object $xml
  250. * @param array $array
  251. * @return object
  252. */
  253. public static function buildXml(&$xml, $array) {
  254. if (is_array($array)) {
  255. foreach ($array as $key => $value) {
  256. // XML_NONE
  257. if (!is_array($value)) {
  258. $xml->addChild($key, $value);
  259. continue;
  260. }
  261. // Multiple nodes of the same name
  262. if (isset($value[0])) {
  263. foreach ($value as $kValue) {
  264. if (is_array($kValue)) {
  265. self::buildXml($xml, array($key => $kValue));
  266. } else {
  267. $xml->addChild($key, $kValue);
  268. }
  269. }
  270. // XML_GROUP
  271. } else if (isset($value['attributes'])) {
  272. if (is_array($value['value'])) {
  273. $node = $xml->addChild($key);
  274. self::buildXml($node, $value['value']);
  275. } else {
  276. $node = $xml->addChild($key, $value['value']);
  277. }
  278. if (!empty($value['attributes'])) {
  279. foreach ($value['attributes'] as $aKey => $aValue) {
  280. $node->addAttribute($aKey, $aValue);
  281. }
  282. }
  283. // XML_MERGE
  284. } else if (isset($value['value'])) {
  285. $node = $xml->addChild($key, $value['value']);
  286. unset($value['value']);
  287. if (!empty($value)) {
  288. foreach ($value as $aKey => $aValue) {
  289. if (is_array($aValue)) {
  290. self::buildXml($node, array($aKey => $aValue));
  291. } else {
  292. $node->addAttribute($aKey, $aValue);
  293. }
  294. }
  295. }
  296. // XML_OVERWRITE
  297. } else {
  298. $node = $xml->addChild($key);
  299. if (!empty($value)) {
  300. foreach ($value as $aKey => $aValue) {
  301. if (is_array($aValue)) {
  302. self::buildXml($node, array($aKey => $aValue));
  303. } else {
  304. $node->addChild($aKey, $aValue);
  305. }
  306. }
  307. }
  308. }
  309. }
  310. }
  311. return $xml;
  312. }
  313. /**
  314. * Convert a SimpleXML object into an array.
  315. *
  316. * @access public
  317. * @param object $xml
  318. * @param int $format
  319. * @return array
  320. */
  321. public static function xmlToArray($xml, $format = self::XML_GROUP) {
  322. // moje głupie dodatki
  323. if (is_string($xml)) {
  324. $xml = @simplexml_load_string($xml);
  325. $root = true;
  326. } else {
  327. $root = false;
  328. }
  329. if (count($xml->children()) <= 0) {
  330. return (string)$xml;
  331. }
  332. foreach ($xml->children() as $element => $node) {
  333. $data = array();
  334. if (!isset($array[$element])) {
  335. $array[$element] = "";
  336. }
  337. if (!$node->attributes() || $format === self::XML_NONE) {
  338. $data = self::xmlToArray($node, $format);
  339. } else {
  340. switch ($format) {
  341. case self::XML_GROUP:
  342. $data = array(
  343. 'attributes' => array(),
  344. 'value' => (string)$node
  345. );
  346. if (count($node->children()) > 0) {
  347. $data['value'] = self::xmlToArray($node, $format);
  348. }
  349. foreach ($node->attributes() as $attr => $value) {
  350. $data['attributes'][$attr] = (string)$value;
  351. }
  352. break;
  353. case self::XML_MERGE:
  354. case self::XML_OVERWRITE:
  355. if ($format === self::XML_MERGE) {
  356. if (count($node->children()) > 0) {
  357. $data = $data + self::xmlToArray($node, $format);
  358. } else {
  359. $data['value'] = (string)$node;
  360. }
  361. }
  362. foreach ($node->attributes() as $attr => $value) {
  363. $data[$attr] = (string)$value;
  364. }
  365. break;
  366. }
  367. }
  368. if (count($xml->{$element}) > 1) {
  369. $array[$element][] = $data;
  370. } else {
  371. $array[$element] = $data;
  372. }
  373. }
  374. // moje głupie dodatki
  375. if ($root) {
  376. $array = array($xml->getName() => array(
  377. 'value' => $array
  378. ));
  379. foreach ($xml->attributes() as $attr => $value) {
  380. $array[$xml->getName()]['attributes'][$attr] = (string)$value;
  381. }
  382. }
  383. return $array;
  384. }
  385. /**
  386. * Encode a resource object for UTF-8.
  387. *
  388. * @access public
  389. * @param mixed $data
  390. * @return array|string
  391. * @static
  392. */
  393. public static function utf8Encode($data) {
  394. if (is_string($data)) {
  395. return utf8_encode($data);
  396. } else if (is_array($data)) {
  397. foreach ($data as $key => $value) {
  398. $data[utf8_encode($key)] = self::utf8Encode($value);
  399. }
  400. } else if (is_object($data)) {
  401. foreach ($data as $key => $value) {
  402. $data->{$key} = self::utf8Encode($value);
  403. }
  404. }
  405. return $data;
  406. }
  407. /**
  408. * Decode a resource object for UTF-8.
  409. *
  410. * @access public
  411. * @param mixed $data
  412. * @return array|string
  413. * @static
  414. */
  415. public static function utf8Decode($data) {
  416. if (is_string($data)) {
  417. return utf8_decode($data);
  418. } else if (is_array($data)) {
  419. foreach ($data as $key => $value) {
  420. $data[utf8_decode($key)] = self::utf8Decode($value);
  421. }
  422. } else if (is_object($data)) {
  423. foreach ($data as $key => $value) {
  424. $data->{$key} = self::utf8Decode($value);
  425. }
  426. }
  427. return $data;
  428. }
  429. }