PageRenderTime 59ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/class/bootstrap/System.class.php

https://bitbucket.org/stk2k/charcoalphp2.1
PHP | 994 lines | 652 code | 86 blank | 256 comment | 57 complexity | 3066f1cf783a8d906aaa963afa8e3bea MD5 | raw file
  1. <?php
  2. /**
  3. * Low level functions substituting for global functions
  4. *
  5. * PHP version 5
  6. *
  7. * @package class.bootstrap
  8. * @author CharcoalPHP Development Team
  9. * @copyright 2008 stk2k, sazysoft
  10. */
  11. class Charcoal_System
  12. {
  13. /** length of output in string conversion methods */
  14. const TOSTRING_MAX_LENGTH = 9999;
  15. /** length of output in dump methods */
  16. const DUMP_MAX_LENGTH = 4096;
  17. /** Used at isBitSet(), means test if any of bit field is set */
  18. const BITTEST_MODE_ALL = 1;
  19. /** Used at isBitSet(), means test if any of bit field is set */
  20. const BITTEST_MODE_ANY = 2;
  21. /**
  22. * Get all defined constants
  23. *
  24. */
  25. public static function getUserDefinedConstants()
  26. {
  27. $all = get_defined_constants(TRUE);
  28. return isset($all['user']) ? $all['user'] : array();
  29. }
  30. /**
  31. * Test if specified bit flag is set
  32. *
  33. * @param int $target target value to test
  34. * @param int $flag target flag to test
  35. * @param int $mode test mode(see BITTEST_MODE_XXX constants)
  36. *
  37. * @return boolean
  38. */
  39. public static function isBitSet( $target, $flag, $mode )
  40. {
  41. switch( ui($mode) ){
  42. case self::BITTEST_MODE_ALL:
  43. return ($target & $flag) === $flag;
  44. break;
  45. case self::BITTEST_MODE_ANY:
  46. return ($target & $flag) != 0;
  47. }
  48. return false;
  49. }
  50. /**
  51. * Test if specified bit flag is set(any bit set returns true)
  52. *
  53. * @param int $target target value to test
  54. * @param int $flag target flag to test
  55. *
  56. * @return boolean
  57. */
  58. public static function isAnyBitSet( $target, $flag )
  59. {
  60. return self::isBitSet( $target, $flag, self::BITTEST_MODE_ANY );
  61. }
  62. /**
  63. * Test if specified bit flag is set(all bits set returns true)
  64. *
  65. * @param int $target target value to test
  66. * @param int $flag target flag to test
  67. *
  68. * @return boolean
  69. */
  70. public static function isAllBitSet( $target, $flag )
  71. {
  72. return self::isBitSet( $target, $flag, self::BITTEST_MODE_ALL );
  73. }
  74. /*
  75. * Convert PHP error number to string
  76. */
  77. public static function phpErrorString( $errno )
  78. {
  79. // Charcoal_ParamTrait::validateInteger( 1, $errno );
  80. $errors = array(
  81. E_ERROR => "E_ERROR",
  82. E_WARNING => "E_WARNING",
  83. E_PARSE => "E_PARSE",
  84. E_NOTICE => "E_NOTICE",
  85. E_CORE_ERROR => "E_CORE_ERROR",
  86. E_CORE_WARNING => "E_CORE_WARNING",
  87. E_COMPILE_ERROR => "E_COMPILE_ERROR",
  88. E_COMPILE_WARNING => "E_COMPILE_WARNING",
  89. E_USER_ERROR => "E_USER_ERROR",
  90. E_USER_NOTICE => "E_USER_NOTICE",
  91. E_STRICT => "E_STRICT",
  92. E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
  93. );
  94. $errors[8192] = "E_DEPRECATED"; // PHP 5.3.0
  95. $errors[16384] = "E_USER_DEPRECATED"; // PHP 5.3.0
  96. $errors_desc = array();
  97. foreach( $errors as $key => $value ){
  98. if ( self::isAnyBitSet($errno,$key) ){
  99. $errors_desc[] = $value;
  100. }
  101. }
  102. return implode( "|", $errors_desc );
  103. }
  104. /*
  105. * 配列の最後に別の配列の要素すべてを追加
  106. */
  107. public static function appendArray( $a, $b )
  108. {
  109. if ( $a === NULL ){
  110. $a = array();
  111. }
  112. array_splice($a,count($a),0,$b);
  113. return $a;
  114. }
  115. /**
  116. * swap two values
  117. *
  118. * @param mixed $a
  119. * @param mixed $b
  120. *
  121. * @return array
  122. */
  123. public static function swap( $a, $b )
  124. {
  125. return array( $b, $a );
  126. }
  127. /**
  128. * make a string to snake case
  129. *
  130. * @param string $str
  131. *
  132. * @return string
  133. */
  134. public static function snakeCase( $str )
  135. {
  136. return strtolower(preg_replace('/([a-z0-9])([A-Z])/', "$1_$2", $str));
  137. }
  138. /**
  139. * make a string to pascal case
  140. *
  141. * @param string $str
  142. *
  143. * @return string
  144. */
  145. public static function pascalCase( $str )
  146. {
  147. return implode(array_map('ucfirst',array_map('strtolower',explode( '_', $str ))));
  148. }
  149. /**
  150. * format byte size
  151. *
  152. * @param int $size
  153. * @param int $precision
  154. * @param array $symbols
  155. *
  156. * @return string
  157. */
  158. public static function formatByteSize( $size, $precision = 1, $symbols = NULL )
  159. {
  160. if ( $symbols === NULL ){
  161. $symbols = array('B', 'Kb', 'Mb', 'Gb', 'Tb', 'Pb');
  162. }
  163. $i=0;
  164. while (($size/1024)>1) {
  165. $size=$size/1024;
  166. $i++;
  167. }
  168. return (round($size,$precision)." ".$symbols[$i]);
  169. }
  170. /**
  171. * generate hash value
  172. *
  173. * @param string $algorithm
  174. *
  175. * @return string
  176. */
  177. public static function hash( $algorithm = 'sha1' )
  178. {
  179. switch( $algorithm )
  180. {
  181. case 'sha1':
  182. return sha1(microtime().uniqid(mt_rand(),1));
  183. case 'md5':
  184. return md5(microtime().uniqid(mt_rand(),1));
  185. }
  186. return NULL;
  187. }
  188. /**
  189. * escape variable for HTML
  190. *
  191. * @param mixed $value
  192. *
  193. * @return mixed
  194. */
  195. public static function escape( $value )
  196. {
  197. if ( is_string($value) ){
  198. $res = htmlspecialchars($value, ENT_QUOTES, mb_internal_encoding());
  199. //log_debug( "debug", "escape:" . print_r($res,true) );
  200. return $res;
  201. }
  202. elseif ( is_array($value) ){
  203. $ret = array();
  204. foreach( $value as $key => $item ){
  205. $ret[$key] = self::escape( $item );
  206. }
  207. return $ret;
  208. }
  209. elseif ( is_object($value) ){
  210. $object = $value;
  211. $vars = get_object_vars($object);
  212. foreach( $vars as $key => $value ){
  213. $object->$key = self::escape( $value );
  214. }
  215. return $object;
  216. }
  217. return $value;
  218. }
  219. /**
  220. * decode escaped value
  221. *
  222. * @param mixed $value
  223. *
  224. * @return mixed
  225. */
  226. public static function decode( $value )
  227. {
  228. if ( is_string($value) ){
  229. //log_debug( "debug", "decode before:" . print_r($value,true) );
  230. $res = htmlspecialchars_decode($value, ENT_QUOTES);
  231. //log_debug( "debug", "decode after:" . print_r($res,true) );
  232. return $res;
  233. }
  234. elseif ( is_array($value) ){
  235. return array_map('Charcoal_System::decode', $value);
  236. }
  237. elseif ( is_object($value) ){
  238. $object = $value;
  239. $vars = get_object_vars($object);
  240. foreach( $vars as $key => $value ){
  241. $object->$key = self::decode( $value );
  242. }
  243. return $object;
  244. }
  245. return $value;
  246. }
  247. /**
  248. * remove HTML tags
  249. *
  250. * @param mixed $value
  251. * @param string $allowable_tags
  252. *
  253. * @return mixed
  254. */
  255. public static function stripTags( $value, $allowable_tags = NULL )
  256. {
  257. if ( is_string($value) ){
  258. $res = strip_tags($value, $allowable_tags);
  259. return $res;
  260. }
  261. elseif ( is_array($value) ){
  262. $array = $value;
  263. foreach( $array as $key => $value ){
  264. $array[$key] = self::stripTags( $value, $allowable_tags );
  265. }
  266. return $array;
  267. }
  268. elseif ( is_object($value) ){
  269. $object = $value;
  270. $vars = get_object_vars($object);
  271. foreach( $vars as $key => $value ){
  272. $object->$key = self::stripTags( $value );
  273. }
  274. return $object;
  275. }
  276. return $value;
  277. }
  278. /**
  279. * remove backslashes
  280. *
  281. * @param mixed $value
  282. *
  283. * @return mixed
  284. */
  285. public static function stripSlashes( $value )
  286. {
  287. if ( is_string($value) ){
  288. return stripslashes($value);
  289. }
  290. elseif ( is_array($value) ){
  291. $array = $value;
  292. foreach( $array as $key => $value ){
  293. $array[$key] = self::stripSlashes( $value );
  294. }
  295. return $array;
  296. }
  297. elseif ( is_object($value) ){
  298. $object = $value;
  299. $vars = get_object_vars($object);
  300. foreach( $vars as $key => $value ){
  301. $object->$key = self::stripSlashes( $value );
  302. }
  303. return $object;
  304. }
  305. return $value;
  306. }
  307. /**
  308. * escape string for HTML
  309. *
  310. * @param string $string_data
  311. * @param array $options
  312. *
  313. * @return mixed
  314. */
  315. public static function escapeString( $string_data, $options = NULL )
  316. {
  317. if ( !$options ){
  318. $options = array(
  319. 'quote_style' => 'ENT_QUOTES',
  320. );
  321. }
  322. $quote_style = ENT_NOQUOTES;
  323. if ( isset($options['quote_style']) && $options['quote_style'] == 'ENT_QUOTES' ){
  324. $quote_style = ENT_QUOTES;
  325. }
  326. $str = htmlspecialchars( $string_data, $quote_style );
  327. return $str;
  328. }
  329. /**
  330. * make random string
  331. *
  332. * @param int $length
  333. * @param string $char_set
  334. *
  335. * @return string
  336. */
  337. public static function makeRandomString( $length, $char_set = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' )
  338. {
  339. $ret = '';
  340. $char_set_cnt = strlen($char_set);
  341. mt_srand();
  342. for($i = 0; $i < $length; $i++){
  343. $idx = mt_rand(0, $char_set_cnt - 1);
  344. $ret .= $char_set[ $idx ];
  345. }
  346. return $ret;
  347. }
  348. /**
  349. * return file and line number of called position
  350. *
  351. * @param int $back
  352. *
  353. * @return array
  354. */
  355. public static function caller( $back = 0 )
  356. {
  357. $bt = (version_compare(PHP_VERSION,'5.4.0') >= 0 ) ?
  358. debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,5) : debug_backtrace();
  359. $trace = isset($bt[1 + $back]) ? $bt[1 + $back] : NULL;
  360. $file = isset($trace['file']) ? $trace['file'] : "";
  361. $line = isset($trace['line']) ? $trace['line'] : "";
  362. return array( $file, $line );
  363. }
  364. /**
  365. * return file and line number of called position as string
  366. *
  367. * @param int $back
  368. * @param boolean $fullpath
  369. *
  370. * @return string
  371. */
  372. public static function callerAsString( $back = 0, $fullpath = FALSE )
  373. {
  374. list( $file, $line ) = self::caller( $back );
  375. if ( $fullpath ){
  376. return "$file($line)";
  377. }
  378. $file = basename($file);
  379. return "$file($line)";
  380. }
  381. /**
  382. * get type of primitive, resource, array, or object
  383. *
  384. * @param mixed $value
  385. *
  386. * @return string
  387. */
  388. public static function getType( $value )
  389. {
  390. $type = gettype($value);
  391. switch( $type ){
  392. case 'string':
  393. return $type . '(' . strlen($value) . ')';
  394. break;
  395. case 'integer':
  396. case 'float':
  397. case 'boolean':
  398. return $type . '(' . $value . ')';
  399. break;
  400. case 'NULL':
  401. case 'unknown type':
  402. return $type;
  403. break;
  404. case 'array':
  405. return $type . '(' . count($value) . ')';
  406. break;
  407. case 'object':
  408. if ( $value instanceof Countable ){
  409. return get_class( $value ) . '(' . count($value) . ')';
  410. }
  411. elseif ( $value instanceof Charcoal_Object ){
  412. return get_class( $value ) . '(hash=' . $value->hash() . ')';
  413. }
  414. return get_class( $value );
  415. break;
  416. }
  417. return '';
  418. }
  419. /**
  420. * make string expression about a variable
  421. *
  422. * @param mixed $value
  423. * @param boolean $with_type
  424. * @param int $max_size
  425. * @param string $tostring_methods
  426. *
  427. * @return string
  428. */
  429. public static function toString( $value, $with_type = FALSE, $max_size = self::TOSTRING_MAX_LENGTH, $tostring_methods = '__toString,toString' )
  430. {
  431. $ret = '';
  432. if ( $value === NULL ){
  433. $ret = 'NULL';
  434. }
  435. else{
  436. $type = gettype($value);
  437. switch( $type ){
  438. case 'string':
  439. case 'integer':
  440. case 'double':
  441. case 'boolean':
  442. case 'NULL':
  443. case 'unknown type':
  444. $ret = strval($value);
  445. if ( $with_type ){
  446. $ret .= '(' . $type . ')';
  447. }
  448. break;
  449. case 'array':
  450. $ret = '';
  451. foreach( $value as $k => $v ){
  452. if ( strlen($ret) > 0 ) $ret .= '/';
  453. $ret .= "$k=" . self::toString( $v );
  454. if ( $with_type ){
  455. $ret .= '(' . gettype($v) . ')';
  456. }
  457. }
  458. break;
  459. case 'object':
  460. {
  461. $methods = explode( ',', $tostring_methods );
  462. foreach( $methods as $method ){
  463. if ( method_exists($value, $method) ){
  464. $ret = $value->{$method}();
  465. break;
  466. }
  467. }
  468. if ( $with_type ){
  469. $ret .= '(' . get_class($value) . ')';
  470. }
  471. }
  472. break;
  473. }
  474. }
  475. if ( $max_size > 0 ){
  476. return strlen($ret) > $max_size ? substr($ret,0,$max_size) . '...' : $ret;
  477. }
  478. else{
  479. return $ret;
  480. }
  481. }
  482. /**
  483. * implodeのラッパー(5.1.6でクラスの__toStringが自動で呼ばれないため
  484. *
  485. * @param string $glue
  486. * @param array $pieces
  487. * @param boolean $with_type
  488. * @param int $max_size
  489. * @param string $tostring_methods
  490. *
  491. * @return string
  492. */
  493. public static function implodeArray( $glue, $pieces, $with_type = FALSE, $max_size = self::TOSTRING_MAX_LENGTH, $tostring_methods = '__toString,toString' )
  494. {
  495. $ret = '';
  496. if ( $pieces && is_array($pieces) )
  497. {
  498. foreach( $pieces as $p ){
  499. if ( strlen($ret) > 0 ){
  500. $ret .= $glue;
  501. }
  502. $value = self::toString($p, $with_type, $max_size, $tostring_methods);
  503. $ret .= $value;
  504. }
  505. }
  506. return $ret;
  507. }
  508. /**
  509. * implodeのラッパー(5.1.6でクラスの__toStringが自動で呼ばれないため
  510. *
  511. * @param string $glue
  512. * @param array $pieces
  513. * @param boolean $with_type
  514. * @param int $max_size
  515. * @param string $tostring_methods
  516. *
  517. * @return string
  518. */
  519. public static function implodeAssoc( $glue, array $pieces, $with_type = FALSE, $max_size = self::TOSTRING_MAX_LENGTH, $tostring_methods = '__toString,toString' )
  520. {
  521. $ret = '';
  522. foreach( $pieces as $key => $value ){
  523. if ( strlen($ret) > 0 ){
  524. $ret .= $glue;
  525. }
  526. $ret .= self::toString($key, $with_type, $max_size, $tostring_methods) . '=' . self::toString($value, $with_type, $max_size, $tostring_methods);
  527. }
  528. return $ret;
  529. }
  530. /**
  531. * dump a variable
  532. *
  533. * @param mixed $var
  534. * @param int $back
  535. * @param array $options
  536. * @param boolean $return
  537. * @param int $max_depth
  538. *
  539. * @return string
  540. */
  541. public static function dump( $var, $back = 0, $options = NULL, $return = FALSE, $max_depth = 6 )
  542. {
  543. list( $file, $line ) = self::caller( $back );
  544. if ( !$options ){
  545. $options = array();
  546. }
  547. $default_options = array(
  548. 'output' => defined('CHARCOAL_DEBUG_OUTPUT') ? CHARCOAL_DEBUG_OUTPUT : 'shell',
  549. 'title' => 'system dump',
  550. 'font_size' => 11,
  551. 'max_string_length' => self::DUMP_MAX_LENGTH,
  552. 'type' => 'textarea',
  553. );
  554. $options = array_merge( $default_options, $options );
  555. $output = $options['output'];
  556. $title = $options['title'];
  557. $font_size = $options['font_size'];
  558. $max_string_length = $options['max_string_length'];
  559. $type = $options['type'];
  560. $lines = array();
  561. $recursion = array();
  562. self::_dump( '-', $var, 0, $max_string_length, $lines, $max_depth, $recursion );
  563. switch( $output )
  564. {
  565. case "html":
  566. switch( $type ){
  567. case 'div':
  568. $output = "<div style=\"font-size:12px; margin: 2px\"> $title:" . implode('',$lines) . " @$file($line)</div>";
  569. break;
  570. case 'textarea':
  571. default:
  572. $output = "<h3 style=\"font-size:12px; margin: 0px; color:black; background-color:white; text-align: left\"> $title @$file($line)</h3>";
  573. $output .= "<textarea rows=14 style=\"width:100%; font-size:{$font_size}px; margin: 0px; color:black; background-color:white; border: 1px solid silver;\">";
  574. $output .= implode(PHP_EOL,$lines);
  575. $output .= "</textarea>";
  576. break;
  577. }
  578. break;
  579. case "shell":
  580. default:
  581. $output = "$title @$file($line)" . PHP_EOL;
  582. $output .= implode(PHP_EOL,$lines) . PHP_EOL;
  583. break;
  584. }
  585. if ( $return ){
  586. return $output;
  587. }
  588. else{
  589. echo $output;
  590. return null;
  591. }
  592. }
  593. private static function _dump( $key, $value, $depth, $max_string_length, &$lines, $max_depth, &$recursion )
  594. {
  595. if ( $depth > $max_depth ){
  596. $lines[] = str_repeat( '.', $depth * 4 ) . "----(max depth over:$max_depth)";
  597. return;
  598. }
  599. $type = gettype($value);
  600. switch( $type ){
  601. case 'string':
  602. {
  603. $str = $value;
  604. if ( strlen($str) > $max_string_length ){
  605. $str = substr( $str, 0, $max_string_length ) . '...(total:' . strlen($str) . 'bytes)';
  606. }
  607. // $str = htmlspecialchars( $str, ENT_QUOTES );
  608. $lines[] = str_repeat( '.', $depth * 4 ) . "[$key:$type]$str";
  609. }
  610. break;
  611. case 'integer':
  612. case 'double':
  613. case 'boolean':
  614. case 'NULL':
  615. case 'unknown type':
  616. {
  617. $str = strval($value);
  618. if ( strlen($str) > $max_string_length ){
  619. $str = substr( $str, 0, $max_string_length ) . '...(total:' . strlen($str) . 'bytes)';
  620. }
  621. // $str = htmlspecialchars( $str, ENT_QUOTES );
  622. $lines[] = str_repeat( '.', $depth * 4 ) . "[$key:$type]$str";
  623. }
  624. break;
  625. case 'array':
  626. {
  627. $lines[] = str_repeat( '.', $depth * 4 ) . "[$key:array(" . count($value) . ')]';
  628. foreach( $value as $_key => $_value ){
  629. self::_dump( $_key, $_value, $depth + 1, $max_string_length, $lines, $max_depth, $recursion );
  630. }
  631. }
  632. break;
  633. case 'object':
  634. {
  635. $clazz = get_class( $value );
  636. $id = function_exists('spl_object_hash') ? spl_object_hash($value) : 'unknown';
  637. $line = str_repeat( '.', $depth * 4 ) . "[$key:object($clazz)@$id]";
  638. $hash = spl_object_hash( $value );
  639. if ( isset($recursion[$hash]) ){
  640. $lines[] = $line . "----[RECURSION]";
  641. return;
  642. }
  643. $recursion[$hash] = 1;
  644. $lines[] = $line;
  645. if ( $value instanceof Traversable ){
  646. foreach( $value as $_key => $_value ){
  647. self::_dump( $_key, $_value, $depth + 1, $max_string_length, $lines, $max_depth, $recursion );
  648. }
  649. }
  650. else{
  651. $vars = self::getObjectVars( $value );
  652. foreach( $vars as $_key => $_value ){
  653. self::_dump( $_key, $_value, $depth + 1, $max_string_length, $lines, $max_depth, $recursion );
  654. }
  655. }
  656. }
  657. break;
  658. }
  659. }
  660. /**
  661. * dump a tree structured variable
  662. *
  663. * @param mixed $var
  664. * @param int $back
  665. * @param array $options
  666. * @param boolean $return
  667. * @param int $max_depth
  668. *
  669. * @return string
  670. */
  671. public static function tree_dump( $var, $back = 1, $options = NULL, $return = FALSE, $max_depth = 6 )
  672. {
  673. list( $file, $line ) = self::caller( $back );
  674. if ( !$options ){
  675. $options = array();
  676. }
  677. $default_options = array(
  678. 'title' => 'system tree dump',
  679. 'font_size' => 11,
  680. 'max_string_length' => self::DUMP_MAX_LENGTH,
  681. 'type' => 'textarea',
  682. );
  683. $options = array_merge( $default_options, $options );
  684. $title = $options['title'];
  685. $font_size = $options['font_size'];
  686. $max_string_length = $options['max_string_length'];
  687. $type = $options['type'];
  688. $lines = array();
  689. self::_tree_dump( '-', $var, 0, $max_string_length, $lines, $max_depth );
  690. $output = '';
  691. switch( CHARCOAL_RUNMODE )
  692. {
  693. case "shell":
  694. $output = "$title @$file($line)" . PHP_EOL;
  695. $output .= implode(PHP_EOL,$lines) . PHP_EOL;
  696. break;
  697. case "http":
  698. switch( $type ){
  699. case 'textarea':
  700. $output = "<h3 style=\"font-size:12px; margin: 2px\"> $title @$file($line)</h3>";
  701. $output .= "<textarea rows=14 style=\"width:100%; font-size:{$font_size}px; margin: 2px\">" . implode(PHP_EOL,$lines) . "</textarea>";
  702. break;
  703. case 'div':
  704. $output = "<div style=\"font-size:12px; margin: 2px\"> $title:" . implode('',$lines) . " @$file($line)</div>";
  705. break;
  706. }
  707. }
  708. if ( $return ){
  709. return $output;
  710. }
  711. else{
  712. echo $output;
  713. return null;
  714. }
  715. }
  716. private static function _tree_dump( $key, $value, $depth, $max_string_length, &$lines, $max_depth )
  717. {
  718. if ( $depth > $max_depth ){
  719. return;
  720. }
  721. $type = gettype($value);
  722. switch( $type ){
  723. case 'string':
  724. case 'integer':
  725. case 'double':
  726. case 'boolean':
  727. case 'NULL':
  728. case 'unknown type':
  729. {
  730. $lines[] = str_repeat( '-', $depth * 4 ) . "[$key:$type]$value";
  731. }
  732. break;
  733. case 'array':
  734. {
  735. $lines[] = str_repeat( '-', $depth * 4 ) . "[$key:array(" . count($value) . ')]';
  736. foreach( $value as $k => $v ){
  737. $type = gettype($v);
  738. if ( $type == 'array' || $type == 'object' ){
  739. self::_tree_dump( $k, $v, $depth + 1, $max_string_length, $lines, $max_depth );
  740. }
  741. }
  742. }
  743. break;
  744. case 'object':
  745. {
  746. $clazz = get_class( $value );
  747. $id = function_exists('spl_object_hash') ? spl_object_hash($value) : 'unknown';
  748. $lines[] = str_repeat( '-', $depth * 4 ) . "[$key:object($clazz)@$id]";
  749. if ( $value instanceof Traversable ){
  750. foreach( $value as $_key => $_value ){
  751. $_type = gettype($_value);
  752. if ( $_type == 'array' || $_type == 'object' ){
  753. self::_tree_dump( $_key, $_value, $depth + 1, $max_string_length, $lines, $max_depth );
  754. }
  755. }
  756. }
  757. else{
  758. $vars = self::getObjectVars( $value );
  759. foreach( $vars as $_key => $_value ){
  760. $_type = gettype($_value);
  761. if ( $_type == 'array' || $_type == 'object' ){
  762. self::_tree_dump( $_key, $_value, $depth + 1, $max_string_length, $lines, $max_depth );
  763. }
  764. }
  765. }
  766. }
  767. break;
  768. }
  769. }
  770. /**
  771. * get object's property using reflection
  772. *
  773. * @param mixed $obj
  774. * @param string $field
  775. *
  776. * @return mixed
  777. */
  778. public static function getObjectVar( $obj, $field )
  779. {
  780. $ref = new ReflectionObject( $obj );
  781. $p = $ref->getProperty( $field );
  782. if ( version_compare(PHP_VERSION, '5.3.0') >= 0 ){
  783. $p->setAccessible( true ); // ReflectionProperty#setAccessible is implemented PHP 5.3.0 or later
  784. }
  785. $value = $p->getValue( $obj );
  786. return $value;
  787. }
  788. /**
  789. * improved version of get_object_vars
  790. *
  791. * @param mixed $obj
  792. *
  793. * @return array
  794. */
  795. public static function getObjectVars( $obj )
  796. {
  797. $ref = new ReflectionObject( $obj );
  798. $vars = self::_getObjectVars( $obj, $ref );
  799. return $vars;
  800. }
  801. /**
  802. * recursive function for getObjectVars
  803. *
  804. * @param mixed $obj
  805. * @param ReflectionClass $class_obj
  806. *
  807. * @return array
  808. */
  809. public static function _getObjectVars( $obj, ReflectionClass $class_obj )
  810. {
  811. $vars = array();
  812. $filter = ( version_compare(PHP_VERSION, '5.3.0') >= 0 ) ?
  813. ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE :
  814. ReflectionProperty::IS_PUBLIC;
  815. $props = $class_obj->getProperties($filter);
  816. foreach( $props as $p ){
  817. if ( version_compare(PHP_VERSION, '5.3.0') >= 0 ){
  818. $p->setAccessible(true); // ReflectionProperty#setAccessible is implemented PHP 5.3.0 or later
  819. }
  820. $key = $p->getName();
  821. $value = $p->getValue($obj);
  822. if ( !$p->isStatic() ){
  823. $vars[$key] = $value;
  824. }
  825. }
  826. $parent = $class_obj->getParentClass();
  827. if ( $parent !== FALSE ){
  828. $vars_parent = self::_getObjectVars( $obj, $parent );
  829. $vars = array_merge( $vars_parent, $vars );
  830. }
  831. return $vars;
  832. }
  833. /**
  834. * convert encoding
  835. *
  836. * @param string $str
  837. * @param string $to_encoding
  838. * @param string $from_encoding
  839. *
  840. * @return string
  841. */
  842. public static function convertEncoding( $str, $to_encoding = NULL, $from_encoding = NULL )
  843. {
  844. if ( is_string($str) && $to_encoding ){
  845. // エンコードあり
  846. return mb_convert_encoding($str,$to_encoding, $from_encoding);
  847. }
  848. // エンコード無し
  849. return $str;
  850. }
  851. /**
  852. * convert encoding recursively
  853. *
  854. * @param mixed $var
  855. * @param string $to_encoding
  856. * @param string $from_encoding
  857. *
  858. * @return mixed
  859. */
  860. public static function convertEncodingRecursive( $var, $to_encoding = NULL, $from_encoding = NULL )
  861. {
  862. $type = gettype($var);
  863. switch( $type ){
  864. case 'string':
  865. {
  866. return mb_convert_encoding($var,$to_encoding, $from_encoding);
  867. }
  868. break;
  869. case 'integer':
  870. case 'double':
  871. case 'boolean':
  872. case 'NULL':
  873. case 'unknown type':
  874. break;
  875. case 'array':
  876. {
  877. $newArray = array();
  878. foreach( $var as $key => $value ){
  879. $value = self::convertEncodingRecursive( $value, $to_encoding, $from_encoding );
  880. $newArray[ $key ] = $value;
  881. }
  882. return $newArray;
  883. }
  884. break;
  885. case 'object':
  886. {
  887. $newObject = clone $var;
  888. if ( $var instanceof Traversable ){
  889. foreach( $var as $key => $value ){
  890. $value = self::convertEncodingRecursive( $value, $to_encoding, $from_encoding );
  891. $newObject->$key = $value;
  892. }
  893. return $newObject;
  894. }
  895. else{
  896. $obj_vars = get_object_vars( $var );
  897. foreach( $obj_vars as $key => $value ){
  898. $value = self::convertEncodingRecursive( $value, $to_encoding, $from_encoding );
  899. $newObject->$key = $value;
  900. }
  901. return $newObject;
  902. }
  903. }
  904. break;
  905. }
  906. return $var;
  907. }
  908. }