PageRenderTime 808ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/core/classes/format.php

https://bitbucket.org/codeyash/bootstrap
PHP | 520 lines | 392 code | 37 blank | 91 comment | 26 complexity | 445d58ebe10a07c03de466986f23be53 MD5 | raw file
Possible License(s): MIT, Apache-2.0
  1. <?php
  2. /**
  3. * Part of the Fuel framework.
  4. *
  5. * @package Fuel
  6. * @version 1.5
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2013 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. /**
  14. * Format class
  15. *
  16. * Help convert between various formats such as XML, JSON, CSV, etc.
  17. *
  18. * @package Fuel
  19. * @category Core
  20. * @author Fuel Development Team
  21. * @copyright 2010 - 2012 Fuel Development Team
  22. * @link http://docs.fuelphp.com/classes/format.html
  23. */
  24. class Format
  25. {
  26. /**
  27. * @var array|mixed input to convert
  28. */
  29. protected $_data = array();
  30. /**
  31. * Returns an instance of the Format object.
  32. *
  33. * echo Format::forge(array('foo' => 'bar'))->to_xml();
  34. *
  35. * @param mixed general date to be converted
  36. * @param string data format the file was provided in
  37. * @return Format
  38. */
  39. public static function forge($data = null, $from_type = null)
  40. {
  41. return new static($data, $from_type);
  42. }
  43. /**
  44. * Do not use this directly, call forge()
  45. */
  46. public function __construct($data = null, $from_type = null)
  47. {
  48. // If the provided data is already formatted we should probably convert it to an array
  49. if ($from_type !== null)
  50. {
  51. if (method_exists($this, '_from_' . $from_type))
  52. {
  53. $data = call_user_func(array($this, '_from_' . $from_type), $data);
  54. }
  55. else
  56. {
  57. throw new \FuelException('Format class does not support conversion from "' . $from_type . '".');
  58. }
  59. }
  60. $this->_data = $data;
  61. }
  62. // FORMATING OUTPUT ---------------------------------------------------------
  63. /**
  64. * To array conversion
  65. *
  66. * Goes through the input and makes sure everything is either a scalar value or array
  67. *
  68. * @param mixed $data
  69. * @return array
  70. */
  71. public function to_array($data = null)
  72. {
  73. if ($data === null)
  74. {
  75. $data = $this->_data;
  76. }
  77. $array = array();
  78. if (is_object($data) and ! $data instanceof \Iterator)
  79. {
  80. $data = get_object_vars($data);
  81. }
  82. if (empty($data))
  83. {
  84. return array();
  85. }
  86. foreach ($data as $key => $value)
  87. {
  88. if (is_object($value) or is_array($value))
  89. {
  90. $array[$key] = $this->to_array($value);
  91. }
  92. else
  93. {
  94. $array[$key] = $value;
  95. }
  96. }
  97. return $array;
  98. }
  99. /**
  100. * To XML conversion
  101. *
  102. * @param mixed $data
  103. * @param null $structure
  104. * @param null|string $basenode
  105. * @return string
  106. */
  107. public function to_xml($data = null, $structure = null, $basenode = 'xml')
  108. {
  109. if ($data == null)
  110. {
  111. $data = $this->_data;
  112. }
  113. // turn off compatibility mode as simple xml throws a wobbly if you don't.
  114. if (ini_get('zend.ze1_compatibility_mode') == 1)
  115. {
  116. ini_set('zend.ze1_compatibility_mode', 0);
  117. }
  118. if ($structure == null)
  119. {
  120. $structure = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$basenode />");
  121. }
  122. // Force it to be something useful
  123. if ( ! is_array($data) and ! is_object($data))
  124. {
  125. $data = (array) $data;
  126. }
  127. foreach ($data as $key => $value)
  128. {
  129. // no numeric keys in our xml please!
  130. if (is_numeric($key))
  131. {
  132. // make string key...
  133. $key = (\Inflector::singularize($basenode) != $basenode) ? \Inflector::singularize($basenode) : 'item';
  134. }
  135. // replace anything not alpha numeric
  136. $key = preg_replace('/[^a-z_\-0-9]/i', '', $key);
  137. // if there is another array found recrusively call this function
  138. if (is_array($value) or is_object($value))
  139. {
  140. $node = $structure->addChild($key);
  141. // recursive call if value is not empty
  142. if( ! empty($value))
  143. {
  144. $this->to_xml($value, $node, $key);
  145. }
  146. }
  147. else
  148. {
  149. // add single node.
  150. $value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, "UTF-8");
  151. $structure->addChild($key, $value);
  152. }
  153. }
  154. // pass back as string. or simple xml object if you want!
  155. return $structure->asXML();
  156. }
  157. /**
  158. * To CSV conversion
  159. *
  160. * @param mixed $data
  161. * @param mixed $delimiter
  162. * @return string
  163. */
  164. public function to_csv($data = null, $delimiter = null)
  165. {
  166. // csv format settings
  167. $newline = \Config::get('format.csv.newline', "\n");
  168. $delimiter or $delimiter = \Config::get('format.csv.delimiter', ',');
  169. $enclosure = \Config::get('format.csv.enclosure', '"');
  170. $escape = \Config::get('format.csv.escape', '\\');
  171. // escape function
  172. $escaper = function($items) use($enclosure, $escape) {
  173. return array_map(function($item) use($enclosure, $escape){
  174. return str_replace($enclosure, $escape.$enclosure, $item);
  175. }, $items);
  176. };
  177. if ($data === null)
  178. {
  179. $data = $this->_data;
  180. }
  181. if (is_object($data) and ! $data instanceof \Iterator)
  182. {
  183. $data = $this->to_array($data);
  184. }
  185. // Multi-dimensional array
  186. if (is_array($data) and \Arr::is_multi($data))
  187. {
  188. $data = array_values($data);
  189. if (\Arr::is_assoc($data[0]))
  190. {
  191. $headings = array_keys($data[0]);
  192. }
  193. else
  194. {
  195. $headings = array_shift($data);
  196. }
  197. }
  198. // Single array
  199. else
  200. {
  201. $headings = array_keys((array) $data);
  202. $data = array($data);
  203. }
  204. $output = $enclosure.implode($enclosure.$delimiter.$enclosure, $escaper($headings)).$enclosure.$newline;
  205. foreach ($data as $row)
  206. {
  207. $output .= $enclosure.implode($enclosure.$delimiter.$enclosure, $escaper((array) $row)).$enclosure.$newline;
  208. }
  209. return rtrim($output, $newline);
  210. }
  211. /**
  212. * To JSON conversion
  213. *
  214. * @param mixed $data
  215. * @param bool wether to make the json pretty
  216. * @return string
  217. */
  218. public function to_json($data = null, $pretty = false)
  219. {
  220. if ($data == null)
  221. {
  222. $data = $this->_data;
  223. }
  224. // To allow exporting ArrayAccess objects like Orm\Model instances they need to be
  225. // converted to an array first
  226. $data = (is_array($data) or is_object($data)) ? $this->to_array($data) : $data;
  227. return $pretty ? static::pretty_json($data) : json_encode($data);
  228. }
  229. /**
  230. * To JSONP conversion
  231. *
  232. * @param mixed $data
  233. * @param bool $pretty wether to make the json pretty
  234. * @param string $callback JSONP callback
  235. * @return string formatted JSONP
  236. */
  237. public function to_jsonp($data = null, $pretty = false, $callback = null)
  238. {
  239. $callback or $callback = \Input::param('callback');
  240. is_null($callback) and $callback = 'response';
  241. return $callback.'('.$this->to_json($data, $pretty).')';
  242. }
  243. /**
  244. * Serialize
  245. *
  246. * @param mixed $data
  247. * @return string
  248. */
  249. public function to_serialized($data = null)
  250. {
  251. if ($data == null)
  252. {
  253. $data = $this->_data;
  254. }
  255. return serialize($data);
  256. }
  257. /**
  258. * Return as a string representing the PHP structure
  259. *
  260. * @param mixed $data
  261. * @return string
  262. */
  263. public function to_php($data = null)
  264. {
  265. if ($data == null)
  266. {
  267. $data = $this->_data;
  268. }
  269. return var_export($data, true);
  270. }
  271. /**
  272. * Convert to YAML
  273. *
  274. * @param mixed $data
  275. * @return string
  276. */
  277. public function to_yaml($data = null)
  278. {
  279. if ($data == null)
  280. {
  281. $data = $this->_data;
  282. }
  283. if ( ! function_exists('spyc_load'))
  284. {
  285. import('spyc/spyc', 'vendor');
  286. }
  287. return \Spyc::YAMLDump($data);
  288. }
  289. /**
  290. * Import XML data
  291. *
  292. * @param string $string
  293. * @return array
  294. */
  295. protected function _from_xml($string)
  296. {
  297. $_arr = is_string($string) ? simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA) : $string;
  298. $arr = array();
  299. // Convert all objects SimpleXMLElement to array recursively
  300. foreach ((array)$_arr as $key => $val)
  301. {
  302. $arr[$key] = (is_array($val) or is_object($val)) ? $this->_from_xml($val) : $val;
  303. }
  304. return $arr;
  305. }
  306. /**
  307. * Import YAML data
  308. *
  309. * @param string $string
  310. * @return array
  311. */
  312. protected function _from_yaml($string)
  313. {
  314. if ( ! function_exists('spyc_load'))
  315. {
  316. import('spyc/spyc', 'vendor');
  317. }
  318. return \Spyc::YAMLLoadString($string);
  319. }
  320. /**
  321. * Import CSV data
  322. *
  323. * @param string $string
  324. * @return array
  325. */
  326. protected function _from_csv($string)
  327. {
  328. $data = array();
  329. $rows = preg_split('/(?<='.preg_quote(\Config::get('format.csv.enclosure', '"')).')'.\Config::get('format.csv.regex_newline', '\n').'/', trim($string));
  330. // csv config
  331. $delimiter = \Config::get('format.csv.delimiter', ',');
  332. $enclosure = \Config::get('format.csv.enclosure', '"');
  333. $escape = \Config::get('format.csv.escape', '\\');
  334. // Get the headings
  335. $headings = str_replace($escape.$enclosure, $enclosure, str_getcsv(array_shift($rows), $delimiter, $enclosure, $escape));
  336. foreach ($rows as $row)
  337. {
  338. $data_fields = str_replace($escape.$enclosure, $enclosure, str_getcsv($row, $delimiter, $enclosure, $escape));
  339. if (count($data_fields) == count($headings))
  340. {
  341. $data[] = array_combine($headings, $data_fields);
  342. }
  343. }
  344. return $data;
  345. }
  346. /**
  347. * Import JSON data
  348. *
  349. * @param string $string
  350. * @return mixed
  351. */
  352. private function _from_json($string)
  353. {
  354. return json_decode(trim($string));
  355. }
  356. /**
  357. * Import Serialized data
  358. *
  359. * @param string $string
  360. * @return mixed
  361. */
  362. private function _from_serialize($string)
  363. {
  364. return unserialize(trim($string));
  365. }
  366. /**
  367. * Makes json pretty the json output.
  368. * Barrowed from http://www.php.net/manual/en/function.json-encode.php#80339
  369. *
  370. * @param string $json json encoded array
  371. * @return string|false pretty json output or false when the input was not valid
  372. */
  373. protected static function pretty_json($data)
  374. {
  375. $json = json_encode($data);
  376. if ( ! $json)
  377. {
  378. return false;
  379. }
  380. $tab = "\t";
  381. $newline = "\n";
  382. $new_json = "";
  383. $indent_level = 0;
  384. $in_string = false;
  385. $len = strlen($json);
  386. for ($c = 0; $c < $len; $c++)
  387. {
  388. $char = $json[$c];
  389. switch($char)
  390. {
  391. case '{':
  392. case '[':
  393. if ( ! $in_string)
  394. {
  395. $new_json .= $char.$newline.str_repeat($tab, $indent_level+1);
  396. $indent_level++;
  397. }
  398. else
  399. {
  400. $new_json .= $char;
  401. }
  402. break;
  403. case '}':
  404. case ']':
  405. if ( ! $in_string)
  406. {
  407. $indent_level--;
  408. $new_json .= $newline.str_repeat($tab, $indent_level).$char;
  409. }
  410. else
  411. {
  412. $new_json .= $char;
  413. }
  414. break;
  415. case ',':
  416. if ( ! $in_string)
  417. {
  418. $new_json .= ','.$newline.str_repeat($tab, $indent_level);
  419. }
  420. else
  421. {
  422. $new_json .= $char;
  423. }
  424. break;
  425. case ':':
  426. if ( ! $in_string)
  427. {
  428. $new_json .= ': ';
  429. }
  430. else
  431. {
  432. $new_json .= $char;
  433. }
  434. break;
  435. case '"':
  436. if ($c > 0 and $json[$c-1] !== '\\')
  437. {
  438. $in_string = ! $in_string;
  439. }
  440. default:
  441. $new_json .= $char;
  442. break;
  443. }
  444. }
  445. return $new_json;
  446. }
  447. /**
  448. * Loads Format config.
  449. */
  450. public static function _init()
  451. {
  452. \Config::load('format', true);
  453. }
  454. }