/**

* Copyright 2010-2013 Craig Campbell

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

/**

* Server Side Chrome PHP debugger class

*

* @package ChromePhp

* @author Craig Campbell

*/

class ChromePhp

{

/**

* @var string

*/

const VERSION = '4.1.0';

/**

* @var string

*/

const HEADER_NAME = 'X-ChromeLogger-Data';

/**

* @var string

*/

const BACKTRACE_LEVEL = 'backtrace_level';

/**

* @var string

*/

const LOG = 'log';

/**

* @var string

*/

const WARN = 'warn';

/**

* @var string

*/

const ERROR = 'error';

/**

* @var string

*/

const GROUP = 'group';

/**

* @var string

*/

const INFO = 'info';

/**

* @var string

*/

const GROUP_END = 'groupEnd';

/**

* @var string

*/

const GROUP_COLLAPSED = 'groupCollapsed';

/**

* @var string

*/

const TABLE = 'table';

/**

* @var string

*/

protected $_php_version;

/**

* @var int

*/

protected $_timestamp;

/**

* @var array

*/

protected $_json = array(

'version' => self::VERSION,

'columns' => array('log', 'backtrace', 'type'),

'rows' => array()

);

/**

* @var array

*/

protected $_backtraces = array();

/**

* @var bool

*/

protected $_error_triggered = false;

/**

* @var array

*/

protected $_settings = array(

self::BACKTRACE_LEVEL => 1

);

/**

* @var ChromePhp

*/

protected static $_instance;

/**

* Prevent recursion when working with objects referring to each other

*

* @var array

*/

protected $_processed = array();

/**

* constructor

*/

private function __construct()

{

$this->_php_version = phpversion();

$this->_timestamp = $this->_php_version >= 5.1 ? $_SERVER['REQUEST_TIME'] : time();

$this->_json['request_uri'] = $_SERVER['REQUEST_URI'];

}

/**

* gets instance of this class

*

* @return ChromePhp

*/

public static function getInstance()

{

if (self::$_instance === null) {

self::$_instance = new self();

}

return self::$_instance;

}

/**

* logs a variable to the console

*

* @param mixed $data,... unlimited OPTIONAL number of additional logs [...]

* @return void

*/

public static function log()

{

$args = func_get_args();

return self::_log('', $args);

}

/**

* logs a warning to the console

*

* @param mixed $data,... unlimited OPTIONAL number of additional logs [...]

* @return void

*/

public static function warn()

{

$args = func_get_args();

return self::_log(self::WARN, $args);

}

/**

* logs an error to the console

*

* @param mixed $data,... unlimited OPTIONAL number of additional logs [...]

* @return void

*/

public static function error()

{

$args = func_get_args();

return self::_log(self::ERROR, $args);

}

/**

* sends a group log

*

* @param string value

*/

public static function group()

{

$args = func_get_args();

return self::_log(self::GROUP, $args);

}

/**

* sends an info log

*

* @param mixed $data,... unlimited OPTIONAL number of additional logs [...]

* @return void

*/

public static function info()

{

$args = func_get_args();

return self::_log(self::INFO, $args);

}

/**

* sends a collapsed group log

*

* @param string value

*/

public static function groupCollapsed()

{

$args = func_get_args();

return self::_log(self::GROUP_COLLAPSED, $args);

}

/**

* ends a group log

*

* @param string value

*/

public static function groupEnd()

{

$args = func_get_args();

return self::_log(self::GROUP_END, $args);

}

/**

* sends a table log

*

* @param string value

*/

public static function table()

{

$args = func_get_args();

return self::_log(self::TABLE, $args);

}

/**

* internal logging call

*

* @param string $type

* @return void

*/

protected static function _log($type, array $args)

{

// nothing passed in, don't do anything

if (count($args) == 0 && $type != self::GROUP_END) {

return;

}

$logger = self::getInstance();

$logger->_processed = array();

$logs = array();

foreach ($args as $arg) {

$logs[] = $logger->_convert($arg);

}

$backtrace = debug_backtrace(false);

$level = $logger->getSetting(self::BACKTRACE_LEVEL);

$backtrace_message = 'unknown';

if (isset($backtrace[$level]['file']) && isset($backtrace[$level]['line'])) {

$backtrace_message = $backtrace[$level]['file'] . ' : ' . $backtrace[$level]['line'];

}

$logger->_addRow($logs, $backtrace_message, $type);

}

/**

* converts an object to a better format for logging

*

* @param Object

* @return array

*/

protected function _convert($object)

{

// if this isn't an object then just return it

if (!is_object($object)) {

return $object;

}

//Mark this object as processed so we don't convert it twice and it

//Also avoid recursion when objects refer to each other

$this->_processed[] = $object;

$object_as_array = array();

// first add the class name

$object_as_array['___class_name'] = get_class($object);

// loop through object vars

$object_vars = get_object_vars($object);

foreach ($object_vars as $key => $value) {

// same instance as parent object

if ($value === $object || in_array($value, $this->_processed, true)) {

$value = 'recursion - parent object [' . get_class($value) . ']';

}

$object_as_array[$key] = $this->_convert($value);

}

$reflection = new ReflectionClass($object);

// loop through the properties and add those

foreach ($reflection->getProperties() as $property) {

// if one of these properties was already added above then ignore it

if (array_key_exists($property->getName(), $object_vars)) {

continue;

}

$type = $this->_getPropertyKey($property);

if ($this->_php_version >= 5.3) {

$property->setAccessible(true);

}

try {

$value = $property->getValue($object);

} catch (ReflectionException $e) {

$value = 'only PHP 5.3 can access private/protected properties';

}

// same instance as parent object

if ($value === $object || in_array($value, $this->_processed, true)) {

$value = 'recursion - parent object [' . get_class($value) . ']';

}

$object_as_array[$type] = $this->_convert($value);

}

return $object_as_array;

}

/**

* takes a reflection property and returns a nicely formatted key of the property name

*

* @param ReflectionProperty

* @return string

*/

protected function _getPropertyKey(ReflectionProperty $property)

{

$static = $property->isStatic() ? ' static' : '';

if ($property->isPublic()) {

return 'public' . $static . ' ' . $property->getName();

}

if ($property->isProtected()) {

return 'protected' . $static . ' ' . $property->getName();

}

if ($property->isPrivate()) {

return 'private' . $static . ' ' . $property->getName();

}

}

/**

* adds a value to the data array

*

* @var mixed

* @return void

*/

protected function _addRow(array $logs, $backtrace, $type)

{

// if this is logged on the same line for example in a loop, set it to null to save space

if (in_array($backtrace, $this->_backtraces)) {

$backtrace = null;

}

// for group, groupEnd, and groupCollapsed

// take out the backtrace since it is not useful

if ($type == self::GROUP || $type == self::GROUP_END || $type == self::GROUP_COLLAPSED) {

$backtrace = null;

}

if ($backtrace !== null) {

$this->_backtraces[] = $backtrace;

}

$row = array($logs, $backtrace, $type);

$this->_json['rows'][] = $row;

$this->_writeHeader($this->_json);

}

protected function _writeHeader($data)

{

header(self::HEADER_NAME . ': ' . $this->_encode($data));

}

/**

* encodes the data to be sent along with the request

*

* @param array $data

* @return string

*/

protected function _encode($data)

{

return base64_encode(utf8_encode(json_encode($data)));

}

/**

* adds a setting

*

* @param string key

* @param mixed value

* @return void

*/

public function addSetting($key, $value)

{

$this->_settings[$key] = $value;

}

/**

* add ability to set multiple settings in one call

*

* @param array $settings

* @return void

*/

public function addSettings(array $settings)

{

foreach ($settings as $key => $value) {

$this->addSetting($key, $value);

}

}

/**

* gets a setting

*

* @param string key

* @return mixed

*/

public function getSetting($key)

{

if (!isset($this->_settings[$key])) {

return null;

}

return $this->_settings[$key];

}

}

一键复制

编辑

Web IDE

原始数据

按行查看

历史

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐