PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/elimu-ui/elimu-web/elimusms/plugins/debug_kit/vendors/fire_cake.php

https://github.com/mngdiouf/elimusys
PHP | 546 lines | 345 code | 11 blank | 190 comment | 40 complexity | 43b8a4429d9c49da0f041be7608c2d7a MD5 | raw file
  1. <?php
  2. /**
  3. * FirePHP Class for CakePHP
  4. *
  5. * Provides most of the functionality offered by FirePHPCore
  6. * Interoperates with FirePHP extension for firefox
  7. *
  8. * For more information see: http://www.firephp.org/
  9. *
  10. * PHP versions 4 and 5
  11. *
  12. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  13. * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. *
  15. * Licensed under The MIT License
  16. * Redistributions of files must retain the above copyright notice.
  17. *
  18. * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
  19. * @link http://cakephp.org
  20. * @package debug_kit
  21. * @subpackage debug_kit.views.helpers
  22. * @since DebugKit 0.1
  23. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  24. **/
  25. App::import('Core', 'Debugger');
  26. if (!function_exists('firecake')) {
  27. function firecake($message, $label = null) {
  28. FireCake::fb($message, $label, 'log');
  29. }
  30. }
  31. class FireCake extends Object {
  32. /**
  33. * Options for FireCake.
  34. *
  35. * @see _defaultOptions and setOptions();
  36. * @var string
  37. */
  38. var $options = array();
  39. /**
  40. * Default Options used in CakeFirePhp
  41. *
  42. * @var string
  43. * @access protected
  44. */
  45. var $_defaultOptions = array(
  46. 'maxObjectDepth' => 10,
  47. 'maxArrayDepth' => 20,
  48. 'useNativeJsonEncode' => true,
  49. 'includeLineNumbers' => true,
  50. );
  51. /**
  52. * Message Levels for messages sent via FirePHP
  53. *
  54. * @var array
  55. */
  56. var $_levels = array(
  57. 'log' => 'LOG',
  58. 'info' => 'INFO',
  59. 'warn' => 'WARN',
  60. 'error' => 'ERROR',
  61. 'dump' => 'DUMP',
  62. 'trace' => 'TRACE',
  63. 'exception' => 'EXCEPTION',
  64. 'table' => 'TABLE',
  65. 'groupStart' => 'GROUP_START',
  66. 'groupEnd' => 'GROUP_END',
  67. );
  68. var $_version = '0.2.1';
  69. /**
  70. * internal messageIndex counter
  71. *
  72. * @var int
  73. * @access protected
  74. */
  75. var $_messageIndex = 1;
  76. /**
  77. * stack of objects encoded by stringEncode()
  78. *
  79. * @var array
  80. **/
  81. var $_encodedObjects = array();
  82. /**
  83. * methodIndex to include in tracebacks when using includeLineNumbers
  84. *
  85. * @var array
  86. **/
  87. var $_methodIndex = array('info', 'log', 'warn', 'error', 'table', 'trace');
  88. /**
  89. * FireCake output status
  90. *
  91. * @var bool
  92. **/
  93. var $_enabled = true;
  94. /**
  95. * get Instance of the singleton
  96. *
  97. * @param string $class Class instance to store in the singleton. Used with subclasses and Tests.
  98. * @access public
  99. * @static
  100. * @return void
  101. */
  102. function &getInstance($class = null) {
  103. static $instance = array();
  104. if (!empty($class)) {
  105. if (!$instance || strtolower($class) != strtolower(get_class($instance[0]))) {
  106. $instance[0] =& new $class();
  107. $instance[0]->setOptions();
  108. }
  109. }
  110. if (!isset($instance[0]) || !$instance[0]) {
  111. $instance[0] =& new FireCake();
  112. $instance[0]->setOptions();
  113. }
  114. return $instance[0];
  115. }
  116. /**
  117. * setOptions
  118. *
  119. * @param array $options Array of options to set.
  120. * @access public
  121. * @static
  122. * @return void
  123. */
  124. function setOptions($options = array()) {
  125. $_this =& FireCake::getInstance();
  126. if (empty($_this->options)) {
  127. $_this->options = array_merge($_this->_defaultOptions, $options);
  128. } else {
  129. $_this->options = array_merge($_this->options, $options);
  130. }
  131. }
  132. /**
  133. * Return boolean based on presence of FirePHP extension
  134. *
  135. * @access public
  136. * @return boolean
  137. **/
  138. function detectClientExtension() {
  139. $ua = FireCake::getUserAgent();
  140. if (!preg_match('/\sFirePHP\/([\.|\d]*)\s?/si', $ua, $match) || !version_compare($match[1], '0.0.6', '>=')) {
  141. return false;
  142. }
  143. return true;
  144. }
  145. /**
  146. * Get the Current UserAgent
  147. *
  148. * @access public
  149. * @static
  150. * @return string UserAgent string of active client connection
  151. **/
  152. function getUserAgent() {
  153. return env('HTTP_USER_AGENT');
  154. }
  155. /**
  156. * Disable FireCake output
  157. * All subsequent output calls will not be run.
  158. *
  159. * @return void
  160. **/
  161. function disable() {
  162. $_this =& FireCake::getInstance();
  163. $_this->_enabled = false;
  164. }
  165. /**
  166. * Enable FireCake output
  167. *
  168. * @return void
  169. **/
  170. function enable() {
  171. $_this =& FireCake::getInstance();
  172. $_this->_enabled = true;
  173. }
  174. /**
  175. * Convenience wrapper for LOG messages
  176. *
  177. * @param string $message Message to log
  178. * @param string $label Label for message (optional)
  179. * @access public
  180. * @static
  181. * @return void
  182. */
  183. function log($message, $label = null) {
  184. FireCake::fb($message, $label, 'log');
  185. }
  186. /**
  187. * Convenience wrapper for WARN messages
  188. *
  189. * @param string $message Message to log
  190. * @param string $label Label for message (optional)
  191. * @access public
  192. * @static
  193. * @return void
  194. */
  195. function warn($message, $label = null) {
  196. FireCake::fb($message, $label, 'warn');
  197. }
  198. /**
  199. * Convenience wrapper for INFO messages
  200. *
  201. * @param string $message Message to log
  202. * @param string $label Label for message (optional)
  203. * @access public
  204. * @static
  205. * @return void
  206. */
  207. function info($message, $label = null) {
  208. FireCake::fb($message, $label, 'info');
  209. }
  210. /**
  211. * Convenience wrapper for ERROR messages
  212. *
  213. * @param string $message Message to log
  214. * @param string $label Label for message (optional)
  215. * @access public
  216. * @static
  217. * @return void
  218. */
  219. function error($message, $label = null) {
  220. FireCake::fb($message, $label, 'error');
  221. }
  222. /**
  223. * Convenience wrapper for TABLE messages
  224. *
  225. * @param string $message Message to log
  226. * @param string $label Label for message (optional)
  227. * @access public
  228. * @static
  229. * @return void
  230. */
  231. function table($label, $message) {
  232. FireCake::fb($message, $label, 'table');
  233. }
  234. /**
  235. * Convenience wrapper for DUMP messages
  236. *
  237. * @param string $message Message to log
  238. * @param string $label Unique label for message
  239. * @access public
  240. * @static
  241. * @return void
  242. */
  243. function dump($label, $message) {
  244. FireCake::fb($message, $label, 'dump');
  245. }
  246. /**
  247. * Convenience wrapper for TRACE messages
  248. *
  249. * @param string $label Label for message (optional)
  250. * @access public
  251. * @return void
  252. */
  253. function trace($label) {
  254. FireCake::fb($label, 'trace');
  255. }
  256. /**
  257. * Convenience wrapper for GROUP messages
  258. * Messages following the group call will be nested in a group block
  259. *
  260. * @param string $label Label for group (optional)
  261. * @access public
  262. * @return void
  263. */
  264. function group($label) {
  265. FireCake::fb(null, $label, 'groupStart');
  266. }
  267. /**
  268. * Convenience wrapper for GROUPEND messages
  269. * Closes a group block
  270. *
  271. * @param string $label Label for group (optional)
  272. * @access public
  273. * @return void
  274. */
  275. function groupEnd() {
  276. FireCake::fb(null, null, 'groupEnd');
  277. }
  278. /**
  279. * fb - Send messages with FireCake to FirePHP
  280. *
  281. * Much like FirePHP's fb() this method can be called with various parameter counts
  282. * fb($message) - Just send a message defaults to LOG type
  283. * fb($message, $type) - Send a message with a specific type
  284. * fb($message, $label, $type) - Send a message with a custom label and type.
  285. *
  286. * @param mixed $message Message to output. For other parameters see usage above.
  287. * @static
  288. * @return void
  289. **/
  290. function fb($message) {
  291. $_this =& FireCake::getInstance();
  292. if (headers_sent($filename, $linenum)) {
  293. trigger_error(sprintf(__d('debug_kit', 'Headers already sent in %s on line %s. Cannot send log data to FirePHP.', true), $filename, $linenum), E_USER_WARNING);
  294. return false;
  295. }
  296. if (!$_this->_enabled || !$_this->detectClientExtension()) {
  297. return false;
  298. }
  299. $args = func_get_args();
  300. $type = $label = null;
  301. switch (count($args)) {
  302. case 1:
  303. $type = $_this->_levels['log'];
  304. break;
  305. case 2:
  306. $type = $args[1];
  307. break;
  308. case 3:
  309. $type = $args[2];
  310. $label = $args[1];
  311. break;
  312. default:
  313. trigger_error(__d('debug_kit', 'Incorrect parameter count for FireCake::fb()', true), E_USER_WARNING);
  314. return false;
  315. }
  316. if (isset($_this->_levels[$type])) {
  317. $type = $_this->_levels[$type];
  318. } else {
  319. $type = $_this->_levels['log'];
  320. }
  321. $meta = array();
  322. $skipFinalObjectEncode = false;
  323. if ($type == $_this->_levels['trace']) {
  324. $trace = debug_backtrace();
  325. if (!$trace) {
  326. return false;
  327. }
  328. $message = $_this->_parseTrace($trace, $args[0]);
  329. $skipFinalObjectEncode = true;
  330. }
  331. if ($_this->options['includeLineNumbers']) {
  332. if (!isset($meta['file']) || !isset($meta['line'])) {
  333. $trace = debug_backtrace();
  334. for ($i = 0, $len = count($trace); $i < $len ; $i++) {
  335. $keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
  336. $selfCall = ($keySet &&
  337. strtolower($trace[$i]['class']) == 'firecake' &&
  338. in_array($trace[$i]['function'], $_this->_methodIndex)
  339. );
  340. if ($selfCall) {
  341. $meta['File'] = isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '';
  342. $meta['Line'] = isset($trace[$i]['line']) ? $trace[$i]['line'] : '';
  343. break;
  344. }
  345. }
  346. }
  347. }
  348. $structureIndex = 1;
  349. if ($type == $_this->_levels['dump']) {
  350. $structureIndex = 2;
  351. $_this->_sendHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
  352. } else {
  353. $_this->_sendHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
  354. }
  355. $_this->_sendHeader('X-Wf-Protocol-1', 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
  356. $_this->_sendHeader('X-Wf-1-Plugin-1', 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'. $_this->_version);
  357. if ($type == $_this->_levels['groupStart']) {
  358. $meta['Collapsed'] = 'true';
  359. }
  360. if ($type == $_this->_levels['dump']) {
  361. $dump = $_this->jsonEncode($message);
  362. $msg = '{"' . $label .'":' . $dump .'}';
  363. } else {
  364. $meta['Type'] = $type;
  365. if ($label !== null) {
  366. $meta['Label'] = $label;
  367. }
  368. $msg = '[' . $_this->jsonEncode($meta) . ',' . $_this->jsonEncode($message, $skipFinalObjectEncode).']';
  369. }
  370. $lines = explode("\n", chunk_split($msg, 5000, "\n"));
  371. foreach ($lines as $i => $line) {
  372. if (empty($line)) {
  373. continue;
  374. }
  375. $header = 'X-Wf-1-' . $structureIndex . '-1-' . $_this->_messageIndex;
  376. if (count($lines) > 2) {
  377. $first = ($i == 0) ? strlen($msg) : '';
  378. $end = ($i < count($lines) - 2) ? '\\' : '';
  379. $message = $first . '|' . $line . '|' . $end;
  380. $_this->_sendHeader($header, $message);
  381. } else {
  382. $_this->_sendHeader($header, strlen($line) . '|' . $line . '|');
  383. }
  384. $_this->_messageIndex++;
  385. if ($_this->_messageIndex > 99999) {
  386. trigger_error(__d('debug_kit', 'Maximum number (99,999) of messages reached!', true), E_USER_WARNING);
  387. }
  388. }
  389. $_this->_sendHeader('X-Wf-1-Index', $_this->_messageIndex - 1);
  390. return true;
  391. }
  392. /**
  393. * Parse a debug backtrace
  394. *
  395. * @param array $trace Debug backtrace output
  396. * @access protected
  397. * @return array
  398. **/
  399. function _parseTrace($trace, $messageName) {
  400. $message = array();
  401. for ($i = 0, $len = count($trace); $i < $len ; $i++) {
  402. $keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
  403. $selfCall = ($keySet && $trace[$i]['class'] == 'FireCake');
  404. if (!$selfCall) {
  405. $message = array(
  406. 'Class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : '',
  407. 'Type' => isset($trace[$i]['type']) ? $trace[$i]['type'] : '',
  408. 'Function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : '',
  409. 'Message' => $messageName,
  410. 'File' => isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '',
  411. 'Line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : '',
  412. 'Args' => isset($trace[$i]['args']) ? $this->stringEncode($trace[$i]['args']) : '',
  413. 'Trace' => $this->_escapeTrace(array_splice($trace, $i + 1))
  414. );
  415. break;
  416. }
  417. }
  418. return $message;
  419. }
  420. /**
  421. * Fix a trace for use in output
  422. *
  423. * @param mixed $trace Trace to fix
  424. * @access protected
  425. * @static
  426. * @return string
  427. **/
  428. function _escapeTrace($trace) {
  429. for ($i = 0, $len = count($trace); $i < $len; $i++) {
  430. if (isset($trace[$i]['file'])) {
  431. $trace[$i]['file'] = Debugger::trimPath($trace[$i]['file']);
  432. }
  433. if (isset($trace[$i]['args'])) {
  434. $trace[$i]['args'] = $this->stringEncode($trace[$i]['args']);
  435. }
  436. }
  437. return $trace;
  438. }
  439. /**
  440. * Encode non string objects to string.
  441. * Filter out recursion, so no errors are raised by json_encode or $javascript->object()
  442. *
  443. * @param mixed $object Object or variable to encode to string.
  444. * @param int $objectDepth Current Depth in object chains.
  445. * @param int $arrayDepth Current Depth in array chains.
  446. * @static
  447. * @return void
  448. **/
  449. function stringEncode($object, $objectDepth = 1, $arrayDepth = 1) {
  450. $_this =& FireCake::getInstance();
  451. $return = array();
  452. if (is_resource($object)) {
  453. return '** ' . (string)$object . '**';
  454. }
  455. if (is_object($object)) {
  456. if ($objectDepth == $_this->options['maxObjectDepth']) {
  457. return '** Max Object Depth (' . $_this->options['maxObjectDepth'] . ') **';
  458. }
  459. foreach ($_this->_encodedObjects as $encoded) {
  460. if ($encoded === $object) {
  461. return '** Recursion (' . get_class($object) . ') **';
  462. }
  463. }
  464. $_this->_encodedObjects[] =& $object;
  465. $return['__className'] = $class = get_class($object);
  466. $properties = (array)$object;
  467. foreach ($properties as $name => $property) {
  468. $return[$name] = FireCake::stringEncode($property, 1, $objectDepth + 1);
  469. }
  470. array_pop($_this->_encodedObjects);
  471. }
  472. if (is_array($object)) {
  473. if ($arrayDepth == $_this->options['maxArrayDepth']) {
  474. return '** Max Array Depth ('. $_this->options['maxArrayDepth'] . ') **';
  475. }
  476. foreach ($object as $key => $value) {
  477. $return[$key] = FireCake::stringEncode($value, 1, $arrayDepth + 1);
  478. }
  479. }
  480. if (is_string($object) || is_numeric($object) || is_bool($object) || is_null($object)) {
  481. return $object;
  482. }
  483. return $return;
  484. }
  485. /**
  486. * Encode an object into JSON
  487. *
  488. * @param mixed $object Object or array to json encode
  489. * @param boolean $doIt
  490. * @access public
  491. * @static
  492. * @return string
  493. **/
  494. function jsonEncode($object, $skipEncode = false) {
  495. $_this =& FireCake::getInstance();
  496. if (!$skipEncode) {
  497. $object = FireCake::stringEncode($object);
  498. }
  499. if (function_exists('json_encode') && $_this->options['useNativeJsonEncode']) {
  500. return json_encode($object);
  501. } else {
  502. return FireCake::_jsonEncode($object);
  503. }
  504. }
  505. /**
  506. * jsonEncode Helper method for PHP4 compatibility
  507. *
  508. * @param mixed $object Something to encode
  509. * @access protected
  510. * @static
  511. * @return string
  512. **/
  513. function _jsonEncode($object) {
  514. if (!class_exists('JavascriptHelper')) {
  515. App::import('Helper', 'Javascript');
  516. }
  517. $javascript =& new JavascriptHelper();
  518. $javascript->useNative = false;
  519. if (is_string($object)) {
  520. return '"' . $javascript->escapeString($object) . '"';
  521. }
  522. return $javascript->object($object);
  523. }
  524. /**
  525. * Send Headers - write headers.
  526. *
  527. * @access protected
  528. * @return void
  529. **/
  530. function _sendHeader($name, $value) {
  531. header($name . ': ' . $value);
  532. }
  533. }