2
0

FirePhp.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Wildfire
  17. * @subpackage Plugin
  18. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /** Zend_Controller_Request_Abstract */
  22. require_once('Zend/Controller/Request/Abstract.php');
  23. /** Zend_Controller_Response_Abstract */
  24. require_once('Zend/Controller/Response/Abstract.php');
  25. /** Zend_Wildfire_Channel_HttpHeaders */
  26. require_once 'Zend/Wildfire/Channel/HttpHeaders.php';
  27. /** Zend_Wildfire_Protocol_JsonStream */
  28. require_once 'Zend/Wildfire/Protocol/JsonStream.php';
  29. /** Zend_Wildfire_Plugin_Interface */
  30. require_once 'Zend/Wildfire/Plugin/Interface.php';
  31. /**
  32. * Primary class for communicating with the FirePHP Firefox Extension.
  33. *
  34. * @category Zend
  35. * @package Zend_Wildfire
  36. * @subpackage Plugin
  37. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  38. * @license http://framework.zend.com/license/new-bsd New BSD License
  39. */
  40. class Zend_Wildfire_Plugin_FirePhp implements Zend_Wildfire_Plugin_Interface
  41. {
  42. /**
  43. * Plain log style.
  44. */
  45. const LOG = 'LOG';
  46. /**
  47. * Information style.
  48. */
  49. const INFO = 'INFO';
  50. /**
  51. * Warning style.
  52. */
  53. const WARN = 'WARN';
  54. /**
  55. * Error style that increments Firebug's error counter.
  56. */
  57. const ERROR = 'ERROR';
  58. /**
  59. * Trace style showing message and expandable full stack trace.
  60. */
  61. const TRACE = 'TRACE';
  62. /**
  63. * Exception style showing message and expandable full stack trace.
  64. * Also increments Firebug's error counter.
  65. */
  66. const EXCEPTION = 'EXCEPTION';
  67. /**
  68. * Table style showing summary line and expandable table
  69. */
  70. const TABLE = 'TABLE';
  71. /**
  72. * Dump variable to Server panel in Firebug Request Inspector
  73. */
  74. const DUMP = 'DUMP';
  75. /**
  76. * Start a group in the Firebug Console
  77. */
  78. const GROUP_START = 'GROUP_START';
  79. /**
  80. * End a group in the Firebug Console
  81. */
  82. const GROUP_END = 'GROUP_END';
  83. /**
  84. * The plugin URI for this plugin
  85. */
  86. const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/ZendFramework/FirePHP/1.6.2';
  87. /**
  88. * The protocol URI for this plugin
  89. */
  90. const PROTOCOL_URI = Zend_Wildfire_Protocol_JsonStream::PROTOCOL_URI;
  91. /**
  92. * The structure URI for the Dump structure
  93. */
  94. const STRUCTURE_URI_DUMP = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1';
  95. /**
  96. * The structure URI for the Firebug Console structure
  97. */
  98. const STRUCTURE_URI_FIREBUGCONSOLE = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
  99. /**
  100. * Singleton instance
  101. * @var Zend_Wildfire_Plugin_FirePhp
  102. */
  103. protected static $_instance = null;
  104. /**
  105. * Flag indicating whether FirePHP should send messages to the user-agent.
  106. * @var boolean
  107. */
  108. protected $_enabled = true;
  109. /**
  110. * The channel via which to send the encoded messages.
  111. * @var Zend_Wildfire_Channel_Interface
  112. */
  113. protected $_channel = null;
  114. /**
  115. * Messages that are buffered to be sent when protocol flushes
  116. * @var array
  117. */
  118. protected $_messages = array();
  119. /**
  120. * Options for the object
  121. * @var array
  122. */
  123. protected $_options = array(
  124. 'traceOffset' => 1, /* The offset in the trace which identifies the source of the message */
  125. 'maxTraceDepth' => 99, /* Maximum depth for stack traces */
  126. 'maxObjectDepth' => 10, /* The maximum depth to traverse objects when encoding */
  127. 'maxArrayDepth' => 20, /* The maximum depth to traverse nested arrays when encoding */
  128. 'includeLineNumbers' => true /* Whether to include line and file info for each message */
  129. );
  130. /**
  131. * Filters used to exclude object members when encoding
  132. * @var array
  133. */
  134. protected $_objectFilters = array();
  135. /**
  136. * A stack of objects used during encoding to detect recursion
  137. * @var array
  138. */
  139. protected $_objectStack = array();
  140. /**
  141. * Create singleton instance.
  142. *
  143. * @param string $class OPTIONAL Subclass of Zend_Wildfire_Plugin_FirePhp
  144. * @return Zend_Wildfire_Plugin_FirePhp Returns the singleton Zend_Wildfire_Plugin_FirePhp instance
  145. * @throws Zend_Wildfire_Exception
  146. */
  147. public static function init($class = null)
  148. {
  149. if (self::$_instance !== null) {
  150. require_once 'Zend/Wildfire/Exception.php';
  151. throw new Zend_Wildfire_Exception('Singleton instance of Zend_Wildfire_Plugin_FirePhp already exists!');
  152. }
  153. if ($class !== null) {
  154. if (!is_string($class)) {
  155. require_once 'Zend/Wildfire/Exception.php';
  156. throw new Zend_Wildfire_Exception('Third argument is not a class string');
  157. }
  158. if (!class_exists($class)) {
  159. require_once 'Zend/Loader.php';
  160. Zend_Loader::loadClass($class);
  161. }
  162. self::$_instance = new $class();
  163. if (!self::$_instance instanceof Zend_Wildfire_Plugin_FirePhp) {
  164. self::$_instance = null;
  165. require_once 'Zend/Wildfire/Exception.php';
  166. throw new Zend_Wildfire_Exception('Invalid class to third argument. Must be subclass of Zend_Wildfire_Plugin_FirePhp.');
  167. }
  168. } else {
  169. self::$_instance = new self();
  170. }
  171. return self::$_instance;
  172. }
  173. /**
  174. * Constructor
  175. * @return void
  176. */
  177. protected function __construct()
  178. {
  179. $this->_channel = Zend_Wildfire_Channel_HttpHeaders::getInstance();
  180. $this->_channel->getProtocol(self::PROTOCOL_URI)->registerPlugin($this);
  181. }
  182. /**
  183. * Get or create singleton instance
  184. *
  185. * @param $skipCreate boolean True if an instance should not be created
  186. * @return Zend_Wildfire_Plugin_FirePhp
  187. */
  188. public static function getInstance($skipCreate=false)
  189. {
  190. if (self::$_instance===null && $skipCreate!==true) {
  191. return self::init();
  192. }
  193. return self::$_instance;
  194. }
  195. /**
  196. * Destroys the singleton instance
  197. *
  198. * Primarily used for testing.
  199. *
  200. * @return void
  201. */
  202. public static function destroyInstance()
  203. {
  204. self::$_instance = null;
  205. }
  206. /**
  207. * Enable or disable sending of messages to user-agent.
  208. * If disabled all headers to be sent will be removed.
  209. *
  210. * @param boolean $enabled Set to TRUE to enable sending of messages.
  211. * @return boolean The previous value.
  212. */
  213. public function setEnabled($enabled)
  214. {
  215. $previous = $this->_enabled;
  216. $this->_enabled = $enabled;
  217. if (!$this->_enabled) {
  218. $this->_messages = array();
  219. $this->_channel->getProtocol(self::PROTOCOL_URI)->clearMessages($this);
  220. }
  221. return $previous;
  222. }
  223. /**
  224. * Determine if logging to user-agent is enabled.
  225. *
  226. * @return boolean Returns TRUE if logging is enabled.
  227. */
  228. public function getEnabled()
  229. {
  230. return $this->_enabled;
  231. }
  232. /**
  233. * Set a single option
  234. *
  235. * @param string $key The name of the option
  236. * @param mixed $value The value of the option
  237. * @return mixed The previous value of the option
  238. */
  239. public function setOption($key, $value)
  240. {
  241. if (!array_key_exists($key,$this->_options)) {
  242. throw new Zend_Wildfire_Exception('Option with name "'.$key.'" does not exist!');
  243. }
  244. $previous = $this->_options[$key];
  245. $this->_options[$key] = $value;
  246. return $previous;
  247. }
  248. /**
  249. * Retrieve a single option
  250. *
  251. * @param string $key The name of the option
  252. * @return mixed The value of the option
  253. */
  254. public function getOption($key)
  255. {
  256. if (!array_key_exists($key,$this->_options)) {
  257. throw new Zend_Wildfire_Exception('Option with name "'.$key.'" does not exist!');
  258. }
  259. return $this->_options[$key];
  260. }
  261. /**
  262. * Retrieve all options
  263. *
  264. * @return array All options
  265. */
  266. public function getOptions()
  267. {
  268. return $this->_options;
  269. }
  270. /**
  271. * Specify a filter to be used when encoding an object
  272. *
  273. * Filters are used to exclude object members.
  274. *
  275. * @param string $Class The class name of the object
  276. * @param array $Filter An array of members to exclude
  277. * @return void
  278. */
  279. public function setObjectFilter($class, $filter) {
  280. $this->_objectFilters[$class] = $filter;
  281. }
  282. /**
  283. * Starts a group in the Firebug Console
  284. *
  285. * @param string $title The title of the group
  286. * @return TRUE if the group instruction was added to the response headers or buffered.
  287. */
  288. public static function group($title)
  289. {
  290. return self::send(null, $title, self::GROUP_START);
  291. }
  292. /**
  293. * Ends a group in the Firebug Console
  294. *
  295. * @return TRUE if the group instruction was added to the response headers or buffered.
  296. */
  297. public static function groupEnd()
  298. {
  299. return self::send(null, null, self::GROUP_END);
  300. }
  301. /**
  302. * Logs variables to the Firebug Console
  303. * via HTTP response headers and the FirePHP Firefox Extension.
  304. *
  305. * @param mixed $var The variable to log.
  306. * @param string $label OPTIONAL Label to prepend to the log event.
  307. * @param string $style OPTIONAL Style of the log event.
  308. * @param array $options OPTIONAL Options to change how messages are processed and sent
  309. * @return boolean Returns TRUE if the variable was added to the response headers or buffered.
  310. * @throws Zend_Wildfire_Exception
  311. */
  312. public static function send($var, $label=null, $style=null, $options=array())
  313. {
  314. $firephp = self::getInstance();
  315. if (!$firephp->getEnabled()) {
  316. return false;
  317. }
  318. if ($var instanceof Zend_Wildfire_Plugin_FirePhp_Message) {
  319. if ($var->getBuffered()) {
  320. if (!in_array($var, self::$_instance->_messages)) {
  321. self::$_instance->_messages[] = $var;
  322. }
  323. return true;
  324. }
  325. if ($var->getDestroy()) {
  326. return false;
  327. }
  328. $style = $var->getStyle();
  329. $label = $var->getLabel();
  330. $options = $var->getOptions();
  331. $var = $var->getMessage();
  332. }
  333. if (!self::$_instance->_channel->isReady()) {
  334. return false;
  335. }
  336. foreach ($options as $name => $value) {
  337. if ($value===null) {
  338. unset($options[$name]);
  339. }
  340. }
  341. $options = array_merge($firephp->getOptions(), $options);
  342. $trace = null;
  343. $skipFinalEncode = false;
  344. $meta = array();
  345. $meta['Type'] = $style;
  346. if ($var instanceof Exception) {
  347. $eTrace = $var->getTrace();
  348. $eTrace = array_splice($eTrace, 0, $options['maxTraceDepth']);
  349. $var = array('Class'=>get_class($var),
  350. 'Message'=>$var->getMessage(),
  351. 'File'=>$var->getFile(),
  352. 'Line'=>$var->getLine(),
  353. 'Type'=>'throw',
  354. 'Trace'=>$firephp->_encodeTrace($eTrace));
  355. $meta['Type'] = self::EXCEPTION;
  356. $skipFinalEncode = true;
  357. } else
  358. if ($meta['Type']==self::TRACE) {
  359. if (!$label && $var) {
  360. $label = $var;
  361. $var = null;
  362. }
  363. if (!$trace) {
  364. $trace = $firephp->_getStackTrace(array_merge($options,
  365. array('maxTraceDepth'=>$options['maxTraceDepth']+1)));
  366. }
  367. $var = array('Class'=>$trace[0]['class'],
  368. 'Type'=>$trace[0]['type'],
  369. 'Function'=>$trace[0]['function'],
  370. 'Message'=>$label,
  371. 'File'=>isset($trace[0]['file'])?$trace[0]['file']:'',
  372. 'Line'=>isset($trace[0]['line'])?$trace[0]['line']:'',
  373. 'Args'=>isset($trace[0]['args'])?$firephp->_encodeObject($trace[0]['args']):'',
  374. 'Trace'=>$firephp->_encodeTrace(array_splice($trace,1)));
  375. $skipFinalEncode = true;
  376. } else
  377. if ($meta['Type']==self::TABLE) {
  378. $var = $firephp->_encodeTable($var);
  379. $skipFinalEncode = true;
  380. } else {
  381. if ($meta['Type']===null) {
  382. $meta['Type'] = self::LOG;
  383. }
  384. }
  385. if ($label!=null) {
  386. $meta['Label'] = $label;
  387. }
  388. switch ($meta['Type']) {
  389. case self::LOG:
  390. case self::INFO:
  391. case self::WARN:
  392. case self::ERROR:
  393. case self::EXCEPTION:
  394. case self::TRACE:
  395. case self::TABLE:
  396. case self::DUMP:
  397. case self::GROUP_START:
  398. case self::GROUP_END:
  399. break;
  400. default:
  401. require_once 'Zend/Wildfire/Exception.php';
  402. throw new Zend_Wildfire_Exception('Log style "'.$meta['Type'].'" not recognized!');
  403. break;
  404. }
  405. if ($meta['Type'] != self::DUMP && $options['includeLineNumbers']) {
  406. if (!isset($meta['File']) || !isset($meta['Line'])) {
  407. if (!$trace) {
  408. $trace = $firephp->_getStackTrace($options);
  409. }
  410. $meta['File'] = isset($trace[0]['file'])?$trace[0]['file']:'';
  411. $meta['Line'] = isset($trace[0]['line'])?$trace[0]['line']:'';
  412. }
  413. } else {
  414. unset($meta['File']);
  415. unset($meta['Line']);
  416. }
  417. if ($meta['Type'] == self::DUMP) {
  418. return $firephp->_recordMessage(self::STRUCTURE_URI_DUMP,
  419. array('key'=>$meta['Label'],
  420. 'data'=>$var),
  421. $skipFinalEncode);
  422. } else {
  423. return $firephp->_recordMessage(self::STRUCTURE_URI_FIREBUGCONSOLE,
  424. array('data'=>$var,
  425. 'meta'=>$meta),
  426. $skipFinalEncode);
  427. }
  428. }
  429. /**
  430. * Gets a stack trace
  431. *
  432. * @param array $options Options to change how the stack trace is returned
  433. * @return array The stack trace
  434. */
  435. protected function _getStackTrace($options)
  436. {
  437. $trace = debug_backtrace();
  438. return array_splice($trace, $options['traceOffset'], $options['maxTraceDepth']);
  439. }
  440. /**
  441. * Record a message with the given data in the given structure
  442. *
  443. * @param string $structure The structure to be used for the data
  444. * @param array $data The data to be recorded
  445. * @param boolean $skipEncode TRUE if variable encoding should be skipped
  446. * @return boolean Returns TRUE if message was recorded
  447. * @throws Zend_Wildfire_Exception
  448. */
  449. protected function _recordMessage($structure, $data, $skipEncode=false)
  450. {
  451. switch($structure) {
  452. case self::STRUCTURE_URI_DUMP:
  453. if (!isset($data['key'])) {
  454. require_once 'Zend/Wildfire/Exception.php';
  455. throw new Zend_Wildfire_Exception('You must supply a key.');
  456. }
  457. if (!array_key_exists('data',$data)) {
  458. require_once 'Zend/Wildfire/Exception.php';
  459. throw new Zend_Wildfire_Exception('You must supply data.');
  460. }
  461. $value = $data['data'];
  462. if (!$skipEncode) {
  463. $value = $this->_encodeObject($data['data']);
  464. }
  465. return $this->_channel->getProtocol(self::PROTOCOL_URI)->
  466. recordMessage($this,
  467. $structure,
  468. array($data['key']=>$value));
  469. case self::STRUCTURE_URI_FIREBUGCONSOLE:
  470. if (!isset($data['meta']) ||
  471. !is_array($data['meta']) ||
  472. !array_key_exists('Type',$data['meta'])) {
  473. require_once 'Zend/Wildfire/Exception.php';
  474. throw new Zend_Wildfire_Exception('You must supply a "Type" in the meta information.');
  475. }
  476. if (!array_key_exists('data',$data)) {
  477. require_once 'Zend/Wildfire/Exception.php';
  478. throw new Zend_Wildfire_Exception('You must supply data.');
  479. }
  480. $value = $data['data'];
  481. if (!$skipEncode) {
  482. $value = $this->_encodeObject($data['data']);
  483. }
  484. return $this->_channel->getProtocol(self::PROTOCOL_URI)->
  485. recordMessage($this,
  486. $structure,
  487. array($data['meta'],
  488. $value));
  489. default:
  490. require_once 'Zend/Wildfire/Exception.php';
  491. throw new Zend_Wildfire_Exception('Structure of name "'.$structure.'" is not recognized.');
  492. break;
  493. }
  494. return false;
  495. }
  496. /**
  497. * Encodes a table by encoding each row and column with _encodeObject()
  498. *
  499. * @param array $Table The table to be encoded
  500. * @return array
  501. */
  502. protected function _encodeTable($table)
  503. {
  504. if (!$table) {
  505. return $table;
  506. }
  507. for ($i=0 ; $i<count($table) ; $i++) {
  508. if (is_array($table[$i])) {
  509. for ($j=0 ; $j<count($table[$i]) ; $j++) {
  510. $table[$i][$j] = $this->_encodeObject($table[$i][$j]);
  511. }
  512. }
  513. }
  514. return $table;
  515. }
  516. /**
  517. * Encodes a trace by encoding all "args" with _encodeObject()
  518. *
  519. * @param array $Trace The trace to be encoded
  520. * @return array The encoded trace
  521. */
  522. protected function _encodeTrace($trace)
  523. {
  524. if (!$trace) {
  525. return $trace;
  526. }
  527. for ($i=0 ; $i<sizeof($trace) ; $i++) {
  528. if (isset($trace[$i]['args'])) {
  529. $trace[$i]['args'] = $this->_encodeObject($trace[$i]['args']);
  530. }
  531. }
  532. return $trace;
  533. }
  534. /**
  535. * Encode an object by generating an array containing all object members.
  536. *
  537. * All private and protected members are included. Some meta info about
  538. * the object class is added.
  539. *
  540. * @param mixed $object The object/array/value to be encoded
  541. * @return array The encoded object
  542. */
  543. protected function _encodeObject($object, $objectDepth = 1, $arrayDepth = 1)
  544. {
  545. $return = array();
  546. if (is_resource($object)) {
  547. return '** '.(string)$object.' **';
  548. } else
  549. if (is_object($object)) {
  550. if ($objectDepth > $this->_options['maxObjectDepth']) {
  551. return '** Max Object Depth ('.$this->_options['maxObjectDepth'].') **';
  552. }
  553. foreach ($this->_objectStack as $refVal) {
  554. if ($refVal === $object) {
  555. return '** Recursion ('.get_class($object).') **';
  556. }
  557. }
  558. array_push($this->_objectStack, $object);
  559. $return['__className'] = $class = get_class($object);
  560. $reflectionClass = new ReflectionClass($class);
  561. $properties = array();
  562. foreach ( $reflectionClass->getProperties() as $property) {
  563. $properties[$property->getName()] = $property;
  564. }
  565. $members = (array)$object;
  566. foreach ($properties as $just_name => $property) {
  567. $name = $raw_name = $just_name;
  568. if ($property->isStatic()) {
  569. $name = 'static:'.$name;
  570. }
  571. if ($property->isPublic()) {
  572. $name = 'public:'.$name;
  573. } else
  574. if ($property->isPrivate()) {
  575. $name = 'private:'.$name;
  576. $raw_name = "\0".$class."\0".$raw_name;
  577. } else
  578. if ($property->isProtected()) {
  579. $name = 'protected:'.$name;
  580. $raw_name = "\0".'*'."\0".$raw_name;
  581. }
  582. if (!(isset($this->_objectFilters[$class])
  583. && is_array($this->_objectFilters[$class])
  584. && in_array($just_name,$this->_objectFilters[$class]))) {
  585. if (array_key_exists($raw_name,$members)
  586. && !$property->isStatic()) {
  587. $return[$name] = $this->_encodeObject($members[$raw_name], $objectDepth + 1, 1);
  588. } else {
  589. if (method_exists($property,'setAccessible')) {
  590. $property->setAccessible(true);
  591. $return[$name] = $this->_encodeObject($property->getValue($object), $objectDepth + 1, 1);
  592. } else
  593. if ($property->isPublic()) {
  594. $return[$name] = $this->_encodeObject($property->getValue($object), $objectDepth + 1, 1);
  595. } else {
  596. $return[$name] = '** Need PHP 5.3 to get value **';
  597. }
  598. }
  599. } else {
  600. $return[$name] = '** Excluded by Filter **';
  601. }
  602. }
  603. // Include all members that are not defined in the class
  604. // but exist in the object
  605. foreach($members as $just_name => $value) {
  606. $name = $raw_name = $just_name;
  607. if ($name{0} == "\0") {
  608. $parts = explode("\0", $name);
  609. $name = $parts[2];
  610. }
  611. if (!isset($properties[$name])) {
  612. $name = 'undeclared:'.$name;
  613. if (!(isset($this->objectFilters[$class])
  614. && is_array($this->objectFilters[$class])
  615. && in_array($just_name,$this->objectFilters[$class]))) {
  616. $return[$name] = $this->_encodeObject($value, $objectDepth + 1, 1);
  617. } else {
  618. $return[$name] = '** Excluded by Filter **';
  619. }
  620. }
  621. }
  622. array_pop($this->_objectStack);
  623. } elseif (is_array($object)) {
  624. if ($arrayDepth > $this->_options['maxArrayDepth']) {
  625. return '** Max Array Depth ('.$this->_options['maxArrayDepth'].') **';
  626. }
  627. foreach ($object as $key => $val) {
  628. // Encoding the $GLOBALS PHP array causes an infinite loop
  629. // if the recursion is not reset here as it contains
  630. // a reference to itself. This is the only way I have come up
  631. // with to stop infinite recursion in this case.
  632. if ($key=='GLOBALS'
  633. && is_array($val)
  634. && array_key_exists('GLOBALS',$val)) {
  635. $val['GLOBALS'] = '** Recursion (GLOBALS) **';
  636. }
  637. $return[$key] = $this->_encodeObject($val, 1, $arrayDepth + 1);
  638. }
  639. } else {
  640. return $object;
  641. }
  642. return $return;
  643. }
  644. /*
  645. * Zend_Wildfire_Plugin_Interface
  646. */
  647. /**
  648. * Get the unique indentifier for this plugin.
  649. *
  650. * @return string Returns the URI of the plugin.
  651. */
  652. public function getUri()
  653. {
  654. return self::PLUGIN_URI;
  655. }
  656. /**
  657. * Flush any buffered data.
  658. *
  659. * @param string $protocolUri The URI of the protocol that should be flushed to
  660. * @return void
  661. */
  662. public function flushMessages($protocolUri)
  663. {
  664. if (!$this->_messages || $protocolUri!=self::PROTOCOL_URI) {
  665. return;
  666. }
  667. foreach( $this->_messages as $message ) {
  668. if (!$message->getDestroy()) {
  669. $this->send($message->getMessage(),
  670. $message->getLabel(),
  671. $message->getStyle(),
  672. $message->getOptions());
  673. }
  674. }
  675. $this->_messages = array();
  676. }
  677. }