├── README.markdown ├── YiiDebug.php ├── YiiDebugComponentProxy.php ├── YiiDebugController.php ├── YiiDebugToolbar.php ├── YiiDebugToolbarPanel.php ├── YiiDebugToolbarRoute.php ├── YiiDebugViewHelper.php ├── YiiDebugViewRenderer.php ├── assets ├── fonts │ ├── yii-debug.eot │ ├── yii-debug.svg │ ├── yii-debug.ttf │ └── yii-debug.woff ├── icons-reference.html ├── main.css ├── main.js └── styles.css ├── composer.json ├── messages ├── ru │ └── yii-debug-toolbar.php └── simple │ └── yii-debug-toolbar.php ├── panels ├── YiiDebugToolbarPanelLogging.php ├── YiiDebugToolbarPanelRequest.php ├── YiiDebugToolbarPanelSettings.php ├── YiiDebugToolbarPanelSql.php └── YiiDebugToolbarPanelViews.php ├── views ├── index.php ├── layouts │ └── main.php ├── main.php └── panels │ ├── asset.php │ ├── logging.php │ ├── request.php │ ├── settings.php │ ├── sql.php │ ├── sql │ ├── callstack.php │ ├── servers.php │ └── summary.php │ └── views.php └── widgets ├── YiiDebugToolbarResourceUsage.php └── views └── resources.php /README.markdown: -------------------------------------------------------------------------------- 1 | Yii Debug Toolbar 2 | ================= 3 | 4 | The Yii Debug Toolbar is a configurable set of panels that display various 5 | debug information about the current request/response and when clicked, display 6 | more details about the panel's content. 7 | 8 | It is a ported to PHP famous [Django Debug Toolbar](/django-debug-toolbar/django-debug-toolbar/). 9 | 10 | Currently, the following panels have been written and are working: 11 | 12 | * Server info 13 | * Request timer 14 | * A list of superglobals 15 | * Application settings 16 | * SQL queries including time to execute and param bindings 17 | * Logging output via Yii built-in logging 18 | 19 | 20 | ## Installation 21 | 22 | Extract the [yii-debug-toolbar](/malyshev/yii-debug-toolbar/) from archive under protected/extensions 23 | 24 | ## Usage and Configuration 25 | 26 | For use [yii-debug-toolbar](/malyshev/yii-debug-toolbar/) need to specify new `route` in `log` component: 27 | 28 | ```php 29 | array( 32 | 'class'=>'CLogRouter', 33 | 'routes'=>array( 34 | array( 35 | 'class'=>'ext.yii-debug-toolbar.YiiDebugToolbarRoute', 36 | // Access is restricted by default to the localhost 37 | //'ipFilters'=>array('127.0.0.1','192.168.1.*', 88.23.23.0/24), 38 | ), 39 | ), 40 | ), 41 | ``` 42 | 43 | * Make sure your IP is listed in the `ipFilters` setting. If you are working locally this option not required. 44 | * Enable [Profiling](http://www.yiiframework.com/doc/api/1.1/CDbConnection#enableProfiling-detail "") and [ParamLogging](http://www.yiiframework.com/doc/api/1.1/CDbConnection#enableParamLogging-detail "") for all used DB connections. 45 | 46 | ```php 47 | array( 50 | 'connectionString' => 'mysql:host=localhost;dbname=test', 51 | //... 52 | 'enableProfiling'=>true, 53 | 'enableParamLogging'=>true, 54 | ), 55 | ``` 56 | 57 | ## TODOs and BUGS 58 | 59 | See: [issues](https://github.com/malyshev/yii-debug-toolbar/issues) 60 | 61 | ## Working preview 62 | Screenshot1 63 | Screenshot2 64 | Screenshot3 65 | 66 | 67 | -------------------------------------------------------------------------------- /YiiDebug.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | 9 | /** 10 | * YiiDebug class. 11 | * 12 | * @author Sergey Malyshev 13 | * @version $Id$ 14 | * @package YiiDebugToolbar 15 | * @since 1.1.7 16 | */ 17 | 18 | class YiiDebug extends CComponent 19 | { 20 | 21 | /** 22 | * Displays a variable. 23 | * This method achieves the similar functionality as var_dump and print_r 24 | * but is more robust when handling complex objects such as Yii controllers. 25 | * @param mixed $var variable to be dumped 26 | */ 27 | public static function dump() 28 | { 29 | $args = func_get_args(); 30 | 31 | if (php_sapi_name() == "cli") { 32 | foreach ($args as $k => $var) { 33 | var_dump($var); 34 | echo "\n"; 35 | } 36 | return; 37 | } else if (empty($_SERVER['SERVER_ADDR']) || empty($_SERVER['REMOTE_ADDR']) || $_SERVER['SERVER_ADDR'] !== $_SERVER['REMOTE_ADDR']) { 38 | return; 39 | } 40 | 41 | $backTrace = debug_backtrace(); 42 | $backTrace = array_shift($backTrace); 43 | echo '
'; 44 | if (is_array($backTrace) && isset($backTrace['file']) && isset($backTrace['function']) && $backTrace['function'] === __FUNCTION__) { 45 | echo "{$backTrace['file']} in line {$backTrace['line']}
"; 46 | echo '
'; 47 | } 48 | 49 | foreach ($args as $k => $var) { 50 | echo CVarDumper::dump($var, 10, true), '
'; 51 | } 52 | 53 | echo "
"; 54 | } 55 | 56 | /** 57 | * Writes a trace dump. 58 | * @param string $msg message to be logged 59 | */ 60 | public static function trace($message) 61 | { 62 | Yii::trace(self::dump($message), 'dump'); 63 | } 64 | 65 | public static function getClass($class) 66 | { 67 | return new ReflectionClass($class); 68 | } 69 | 70 | public static function getClassMethod($class,$name) 71 | { 72 | $class = self::getClass($class); 73 | $method = $class->getMethod($name); 74 | $method->setAccessible(true); 75 | return $method; 76 | } 77 | 78 | public static function t($str,$params=array(),$dic='yii-debug-toolbar') { 79 | return Yii::t("YiiDebug.".$dic, $str, $params); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /YiiDebugComponentProxy.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | /** 9 | * ProxyComponent represents an ... 10 | * 11 | * Description of ProxyComponent 12 | * 13 | * @author Sergey Malyshev 14 | * @version $Id$ 15 | * @package 16 | * @since 1.1.7 17 | */ 18 | class YiiDebugComponentProxy extends CComponent 19 | { 20 | 21 | private $_instance; 22 | 23 | private $_isProxy; 24 | 25 | protected $abstract = array(); 26 | 27 | public function init() 28 | { 29 | } 30 | 31 | public function getIsProxy() 32 | { 33 | if (null === $this->_isProxy) 34 | { 35 | $this->_isProxy = (null !== $this->_instance && !($this->_instance instanceof $this)); 36 | } 37 | return $this->_isProxy; 38 | } 39 | 40 | public function setInstance($value) 41 | { 42 | if (null === $this->_instance && false !== is_object($value)) 43 | { 44 | $this->abstract = array_merge($this->abstract, get_object_vars($value)); 45 | $this->_instance = $value; 46 | } 47 | } 48 | 49 | public function getInstance() 50 | { 51 | return $this->_instance; 52 | } 53 | 54 | public function __call($name, $parameters) 55 | { 56 | if (false !== $this->getIsProxy() && false !== method_exists($this->_instance, $name)) 57 | { 58 | return call_user_func_array(array($this->_instance, $name), $parameters); 59 | } 60 | 61 | return parent::__call($name, $parameters); 62 | } 63 | 64 | public function __set($name, $value) 65 | { 66 | $setter='set'.$name; 67 | if (false !== method_exists($this, $setter)) 68 | { 69 | return call_user_func_array(array($this, $setter), array($value)); 70 | } 71 | else if (false !== property_exists($this, $name)) 72 | { 73 | return $this->$name = $value; 74 | } 75 | else if (false !== $this->getIsProxy() && false !== method_exists($this->_instance, $setter)) 76 | { 77 | return call_user_func_array(array($this->_instance, $setter), array($value)); 78 | } 79 | else if (false !== $this->getIsProxy() && false !== property_exists($this->_instance, $name)) 80 | { 81 | return $this->_instance->$name = $value; 82 | } 83 | else if (false === $this->getIsProxy() && false !== array_key_exists ($name, $this->abstract)) 84 | { 85 | return $this->abstract[$name] = $value; 86 | } 87 | 88 | return parent::__set($name, $value); 89 | } 90 | 91 | public function __get($name) 92 | { 93 | $getter='get'.$name; 94 | 95 | if (false !== method_exists($this, $getter)) 96 | { 97 | return call_user_func(array($this, $getter)); 98 | } 99 | else if (false !== property_exists($this, $name)) 100 | { 101 | return $this->$name; 102 | } 103 | else if (false !== $this->getIsProxy() && false !== method_exists($this->_instance, $getter)) 104 | { 105 | return call_user_func(array($this->_instance, $getter)); 106 | } 107 | else if (false !== $this->getIsProxy() && false !== property_exists($this->_instance, $name)) 108 | { 109 | return $this->_instance->$name; 110 | } 111 | else if (false === $this->getIsProxy() && false !== array_key_exists ($name, $this->abstract)) 112 | { 113 | return $this->abstract[$name]; 114 | } 115 | 116 | return parent::__get($name); 117 | } 118 | } -------------------------------------------------------------------------------- /YiiDebugController.php: -------------------------------------------------------------------------------- 1 | render('index'); 9 | } 10 | 11 | 12 | public function getViewPath() 13 | { 14 | return __DIR__ . '/views'; 15 | } 16 | 17 | public function getLayoutFile($layoutName) 18 | { 19 | return $this->getViewPath() . '/layouts/main.php'; 20 | } 21 | 22 | 23 | } -------------------------------------------------------------------------------- /YiiDebugToolbar.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | Yii::import('yii-debug-toolbar.panels.*'); 9 | Yii::import('yii-debug-toolbar.widgets.*'); 10 | 11 | /** 12 | * YiiDebugToolbar represents an ... 13 | * 14 | * Description of YiiDebugToolbar 15 | * 16 | * @author Sergey Malyshev 17 | * @author Igor Golovanov 18 | * @version $Id$ 19 | * @package YiiDebugToolbar 20 | * @since 1.1.7 21 | */ 22 | class YiiDebugToolbar extends CWidget 23 | { 24 | /** 25 | * The URL of assets. 26 | * 27 | * @var string 28 | */ 29 | private $_assetsUrl; 30 | 31 | /** 32 | * Panels. 33 | * 34 | * @var array 35 | */ 36 | private $_panels; 37 | 38 | /** 39 | * Setup toolbar panels. 40 | * 41 | * @param array $panels Panels. 42 | * @return YiiDebugToolbar 43 | */ 44 | public function setPanels(array $panels = array()) 45 | { 46 | $this->_panels = $panels; 47 | return $this; 48 | } 49 | 50 | /** 51 | * Get toolbar panels. 52 | * 53 | * @return array 54 | */ 55 | public function getPanels() 56 | { 57 | if(null === $this->_panels) 58 | { 59 | $this->_panels = array(); 60 | } 61 | return $this->_panels; 62 | } 63 | 64 | /** 65 | * Get the URL of assets. 66 | * The base URL that contains all published asset files of yii-debug-toolbar. 67 | * @return string 68 | */ 69 | public function getAssetsUrl() 70 | { 71 | if (null === $this->_assetsUrl && 'cli' !== php_sapi_name()) { 72 | $linkAssets = Yii::app()->getAssetManager()->linkAssets; 73 | $this->_assetsUrl = Yii::app() 74 | ->getAssetManager() 75 | ->publish(dirname(__FILE__) . '/assets', false, -1, YII_DEBUG and !$linkAssets); 76 | } 77 | return $this->_assetsUrl; 78 | } 79 | 80 | public function getLogs() 81 | { 82 | return $this->owner->logs; 83 | } 84 | 85 | /** 86 | * Set the URL of assets. 87 | * The base URL that contains all published asset files of yii-debug-toolbar. 88 | * 89 | * @param string $value 90 | */ 91 | public function setAssetsUrl($value) 92 | { 93 | $this->_assetsUrl = $value; 94 | } 95 | 96 | /** 97 | * Initialization. 98 | */ 99 | public function init() 100 | { 101 | if (false === ($this->owner instanceof CLogRoute)) { 102 | throw new CException(YiiDebug::t('YiiDebugToolbar owner must be instance of CLogRoute')); 103 | } 104 | 105 | $this->createPanels() 106 | ->registerClientScripts(); 107 | } 108 | 109 | /** 110 | * Run. 111 | */ 112 | public function run() 113 | { 114 | $this->render('main', array( 115 | 'panels' => $this->getPanels() 116 | )); 117 | } 118 | 119 | /** 120 | * Register client scripts. 121 | * 122 | * @return YiiDebugToolbar 123 | */ 124 | private function registerClientScripts() 125 | { 126 | $cs = Yii::app()->getClientScript() 127 | ->registerCoreScript('jquery'); 128 | $cs->registerCssFile($this->assetsUrl . '/main.css'); 129 | 130 | $cs->registerScriptFile($this->assetsUrl . '/main.js', 131 | CClientScript::POS_END); 132 | 133 | return $this; 134 | } 135 | 136 | /** 137 | * Create panels. 138 | * 139 | * @return YiiDebugToolbar 140 | */ 141 | private function createPanels() 142 | { 143 | foreach ($this->getPanels() as $id => $config) { 144 | if (!is_object($config)) { 145 | if (is_string($config)) { 146 | $config = array('class' => $config); 147 | } 148 | 149 | if(is_array($config)) { 150 | if (is_array($config) && !isset($config['class'])) { 151 | $config['class'] = $id; 152 | } 153 | 154 | if (isset($config['enabled']) && false === $config['enabled']) { 155 | unset($this->_panels[$id]); 156 | continue; 157 | } else if (isset($config['enabled']) && true === $config['enabled']) { 158 | unset($config['enabled']); 159 | } 160 | } 161 | $panel = Yii::createComponent($config, $this); 162 | 163 | if (false === ($panel instanceof YiiDebugToolbarPanelInterface)) { 164 | throw new CException(Yii::t('yii-debug-toolbar', 165 | 'The %class% class must be compatible with YiiDebugToolbarPanelInterface', array( 166 | '%class%' => get_class($panel) 167 | ))); 168 | } 169 | $panel->init(); 170 | $this->_panels[$id] = $panel; 171 | } 172 | } 173 | return $this; 174 | } 175 | } 176 | 177 | /** 178 | * YiiDebugToolbarPanelInterface 179 | * 180 | * @author Sergey Malyshev 181 | * @author Igor Golovanov 182 | * @version $Id$ 183 | * @package YiiDebugToolbar 184 | * @since 1.1.7 185 | */ 186 | interface YiiDebugToolbarPanelInterface 187 | { 188 | /** 189 | * Get the title of menu. 190 | * 191 | * @return string 192 | */ 193 | function getMenuTitle(); 194 | 195 | /** 196 | * Get the subtitle of menu. 197 | * 198 | * @return string 199 | */ 200 | function getMenuSubTitle(); 201 | 202 | /** 203 | * Get the title. 204 | * 205 | * @return string 206 | */ 207 | function getTitle(); 208 | 209 | /** 210 | * Get the subtitle. 211 | * 212 | * @return string 213 | */ 214 | function getSubTitle(); 215 | } 216 | -------------------------------------------------------------------------------- /YiiDebugToolbarPanel.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | 9 | /** 10 | * YiiDebugToolbarPanel represents an ... 11 | * 12 | * Description of YiiDebugToolbarPanel 13 | * 14 | * @author Sergey Malyshev 15 | * @author Igor Golovanov 16 | * @version $Id$ 17 | * @package YiiDebugToolbar 18 | * @since 1.1.7 19 | */ 20 | abstract class YiiDebugToolbarPanel extends CWidget 21 | implements YiiDebugToolbarPanelInterface 22 | { 23 | 24 | public $i = 'n'; 25 | 26 | const VIEWS_PATH = '/views/panels'; 27 | 28 | private $_enabled = true; 29 | private $_id; 30 | private static $_counter = 0; 31 | 32 | /** 33 | * Returns the ID of the panel or generates a new one if requested. 34 | * It uses 'dt' as prefix to avoid clashes with autogenerated IDs from Yii widgets 35 | * @param boolean $autoGenerate whether to generate an ID if it is not set previously 36 | * @return string id of the panel. 37 | */ 38 | public function getId($autoGenerate=true) 39 | { 40 | if($this->_id!==null) 41 | return $this->_id; 42 | elseif($autoGenerate) 43 | return $this->_id='ydtb-panel-'.self::$_counter++; 44 | } 45 | 46 | /** 47 | * @param boolean $value set is panel enabled 48 | */ 49 | public function setEnabled($value) 50 | { 51 | $this->_enabled = CPropertyValue::ensureBoolean($value); 52 | } 53 | 54 | /** 55 | * @return boolean $value is panel enabled 56 | */ 57 | public function getEnabled() 58 | { 59 | return $this->_enabled; 60 | } 61 | 62 | /** 63 | * Displays a variable. 64 | * This method achieves the similar functionality as var_dump and print_r 65 | * but is more robust when handling complex objects such as Yii controllers. 66 | * @param mixed $var variable to be dumped 67 | */ 68 | public function dump($var) 69 | { 70 | YiiDebug::dump($var); 71 | } 72 | 73 | /** 74 | * {@inheritdoc} 75 | */ 76 | public function getSubTitle() 77 | { 78 | return null; 79 | } 80 | 81 | /** 82 | * {@inheritdoc} 83 | */ 84 | public function getMenuSubTitle() 85 | { 86 | return null; 87 | } 88 | 89 | /** 90 | * Returns the directory containing the view files for this widget. 91 | * @param boolean $checkTheme not implemented. Only for inheriting CWidget interface. 92 | * @return string the directory containing the view files for this widget. 93 | */ 94 | public function getViewPath($checkTheme = false) 95 | { 96 | return dirname(__FILE__) . self::VIEWS_PATH; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /YiiDebugToolbarRoute.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | /** 9 | * YiiDebugToolbarRouter represents an ... 10 | * 11 | * Description of YiiDebugToolbarRouter 12 | * 13 | * @author Sergey Malyshev 14 | * @version $Id$ 15 | * @package YiiDebugToolbar 16 | * @since 1.1.7 17 | */ 18 | class YiiDebugToolbarRoute extends CLogRoute 19 | { 20 | 21 | private $_panels = array( 22 | //'YiiDebugToolbarPanelServer', 23 | 'YiiDebugToolbarPanelRequest', 24 | 'YiiDebugToolbarPanelSettings', 25 | 'YiiDebugToolbarPanelViews', 26 | 'YiiDebugToolbarPanelSql', 27 | 'YiiDebugToolbarPanelLogging', 28 | ); 29 | 30 | /** 31 | * The filters are given in an array, each filter being: 32 | * - a normal IP (192.168.0.10 or '::1') 33 | * - an incomplete IP (192.168.0.* or 192.168.0.) 34 | * - a CIDR mask (192.168.0.0/24) 35 | * - "*" for everything. 36 | */ 37 | public $ipFilters=array('127.0.0.1','::1'); 38 | 39 | /** 40 | * Whitelist for response content types. DebugToolbarRoute won't write any 41 | * output if the server generates output that isn't listed here (json, xml, 42 | * files, ...) 43 | * @var array of content type strings (in lower case) 44 | */ 45 | public $contentTypeWhitelist = array( 46 | // Yii framework doesn't seem to send content-type header by default. 47 | '', 48 | 'text/html', 49 | 'application/xhtml+xml', 50 | ); 51 | 52 | private $_toolbarWidget, 53 | $_startTime, 54 | $_endTime; 55 | 56 | 57 | private $_proxyMap = array( 58 | 'viewRenderer' => 'YiiDebugViewRenderer' 59 | ); 60 | 61 | public function setPanels(array $pannels) 62 | { 63 | $selfPanels = array_fill_keys($this->_panels, array()); 64 | $this->_panels = array_merge($selfPanels, $pannels); 65 | } 66 | 67 | public function getPanels() 68 | { 69 | return $this->_panels; 70 | } 71 | 72 | public function getStartTime() 73 | { 74 | return $this->_startTime; 75 | } 76 | 77 | public function getEndTime() 78 | { 79 | return $this->_endTime; 80 | } 81 | 82 | public function getLoadTime() 83 | { 84 | return ($this->endTime-$this->startTime); 85 | } 86 | 87 | protected function getToolbarWidget() 88 | { 89 | if (null === $this->_toolbarWidget) 90 | { 91 | $this->_toolbarWidget = Yii::createComponent(array( 92 | 'class'=>'YiiDebugToolbar', 93 | 'panels'=> $this->panels 94 | ), $this); 95 | } 96 | return $this->_toolbarWidget; 97 | } 98 | 99 | public function init() 100 | { 101 | Yii::app()->controllerMap = array_merge(array( 102 | 'debug' => array( 103 | 'class' => 'YiiDebugController' 104 | ) 105 | ), Yii::app()->controllerMap); 106 | 107 | Yii::setPathOfAlias('yii-debug-toolbar', dirname(__FILE__)); 108 | 109 | Yii::app()->setImport(array( 110 | 'yii-debug-toolbar.*' 111 | )); 112 | 113 | $route = Yii::app()->getUrlManager()->parseUrl(Yii::app()->getRequest()); 114 | 115 | $this->enabled = strpos(trim($route, '/'), 'debug') !== 0; 116 | 117 | $this->enabled && $this->enabled = ($this->allowIp(Yii::app()->request->userHostAddress) 118 | && !Yii::app()->getRequest()->getIsAjaxRequest() && (Yii::app() instanceof CWebApplication)) 119 | && $this->checkContentTypeWhitelist(); 120 | 121 | if ($this->enabled) { 122 | Yii::app()->attachEventHandler('onBeginRequest', array($this, 'onBeginRequest')); 123 | Yii::app()->attachEventHandler('onEndRequest', array($this, 'onEndRequest')); 124 | 125 | $this->categories = ''; 126 | $this->levels=''; 127 | } 128 | 129 | $this->_startTime = microtime(true); 130 | 131 | parent::init(); 132 | } 133 | 134 | protected function onBeginRequest(CEvent $event) 135 | { 136 | $this->initComponents(); 137 | 138 | $this->getToolbarWidget() 139 | ->init(); 140 | } 141 | 142 | protected function initComponents() 143 | { 144 | foreach ($this->_proxyMap as $name=>$class) { 145 | $instance = Yii::app()->getComponent($name); 146 | if (null !== ($instance)) { 147 | Yii::app()->setComponent($name, null); 148 | } 149 | 150 | $this->_proxyMap[$name] = array( 151 | 'class'=>$class, 152 | 'instance' => $instance 153 | ); 154 | } 155 | 156 | Yii::app()->setComponents($this->_proxyMap, false); 157 | } 158 | 159 | 160 | /** 161 | * Processes the current request. 162 | * It first resolves the request into controller and action, 163 | * and then creates the controller to perform the action. 164 | */ 165 | private function processRequest() 166 | { 167 | if (is_array(Yii::app()->catchAllRequest) && isset(Yii::app()->catchAllRequest[0])) { 168 | $route = Yii::app()->catchAllRequest[0]; 169 | foreach(array_splice(Yii::app()->catchAllRequest,1) as $name=>$value) 170 | $_GET[$name] = $value; 171 | } else { 172 | $route = Yii::app()->getUrlManager()->parseUrl(Yii::app()->getRequest()); 173 | } 174 | 175 | Yii::app()->runController($route); 176 | } 177 | 178 | protected function onEndRequest(CEvent $event) 179 | { 180 | $this->_endTime = microtime(true); 181 | } 182 | 183 | public function collectLogs($logger, $processLogs=false) 184 | { 185 | $logs = $logger->getLogs(); 186 | $this->logs = empty($this->logs) ? $logs : array_merge($this->logs, $logs); 187 | $this->processLogs($this->logs); 188 | $this->logs = array(); 189 | } 190 | 191 | protected function processLogs($logs) 192 | { 193 | $this->getToolbarWidget()->run(); 194 | } 195 | 196 | private function checkContentTypeWhitelist() 197 | { 198 | $contentType = ''; 199 | 200 | foreach (headers_list() as $header) { 201 | list($key, $value) = explode(':', $header); 202 | $value = ltrim($value, ' '); 203 | if (strtolower($key) === 'content-type') { 204 | // Split encoding if exists 205 | $contentType = explode(";", strtolower($value)); 206 | $contentType = current($contentType); 207 | break; 208 | } 209 | } 210 | 211 | return in_array( $contentType, $this->contentTypeWhitelist ); 212 | } 213 | 214 | /** 215 | * Checks to see if the user IP is allowed by {@link ipFilters}. 216 | * @param string $ip the user IP 217 | * @return boolean whether the user IP is allowed by {@link ipFilters}. 218 | */ 219 | protected function allowIp($ip) 220 | { 221 | foreach ($this->ipFilters as $filter) 222 | { 223 | $filter = trim($filter); 224 | // normal or incomplete IPv4 225 | if (preg_match('/^[\d\.]*\*?$/', $filter)) { 226 | $filter = rtrim($filter, '*'); 227 | if (strncmp($ip, $filter, strlen($filter)) === 0) 228 | { 229 | return true; 230 | } 231 | } 232 | // CIDR 233 | else if (preg_match('/^([\d\.]+)\/(\d+)$/', $filter, $match)) 234 | { 235 | if (self::matchIpMask($ip, $match[1], $match[2])) 236 | { 237 | return true; 238 | } 239 | } 240 | // IPv6 241 | else if ($ip === $filter) 242 | { 243 | return true; 244 | } 245 | } 246 | return false; 247 | } 248 | 249 | /** 250 | * Check if an IP matches a CIDR mask. 251 | * 252 | * @param integer|string $ip IP to check. 253 | * @param integer|string $matchIp Radical of the mask (e.g. 192.168.0.0). 254 | * @param integer $maskBits Size of the mask (e.g. 24). 255 | */ 256 | protected static function matchIpMask($ip, $maskIp, $maskBits) 257 | { 258 | $mask =~ (pow(2, 32-$maskBits)-1); 259 | if (false === is_int($ip)) 260 | { 261 | $ip = ip2long($ip); 262 | } 263 | if (false === is_int($maskIp)) 264 | { 265 | $maskIp = ip2long($maskIp); 266 | } 267 | if (($ip & $mask) === ($maskIp & $mask)) 268 | { 269 | return true; 270 | } else { 271 | return false; 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /YiiDebugViewHelper.php: -------------------------------------------------------------------------------- 1 | 0) { 28 | $details = '\n"; 31 | } 32 | return '
' . $first ."
\n" . $details; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /YiiDebugViewRenderer.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | /** 9 | * YiiDebugViewRenderer represents an ... 10 | * 11 | * Description of YiiDebugViewRenderer 12 | * 13 | * @author Sergey Malyshev 14 | * @version $Id$ 15 | * @package 16 | * @since 1.1.7 17 | */ 18 | class YiiDebugViewRenderer extends YiiDebugComponentProxy 19 | { 20 | 21 | protected $abstract = array( 22 | 'fileExtension' => '.php', 23 | ); 24 | 25 | protected $_debugStackTrace = array(); 26 | 27 | public function getDebugStackTrace() 28 | { 29 | return $this->_debugStackTrace; 30 | } 31 | 32 | public function renderFile($context, $sourceFile, $data, $return) 33 | { 34 | $this->collectDebugInfo($context, $sourceFile, $data); 35 | 36 | if (false !== $this->getIsProxy()) 37 | { 38 | return $this->instance->renderFile($context,$sourceFile,$data,$return); 39 | } 40 | return $context->renderInternal($sourceFile,$data,$return); 41 | } 42 | 43 | public function generateViewFile($sourceFile, $viewFile) 44 | { 45 | if (false !== $this->getIsProxy()) 46 | { 47 | return $this->instance->generateViewFile($sourceFile, $viewFile); 48 | } 49 | } 50 | 51 | protected function getDebugBacktrace() 52 | { 53 | // @see "http://www.php.net/manual/en/function.debug-backtrace.php" 54 | // 55 | // debug_backtrace Changelog 56 | // 57 | // Version Description 58 | // 5.4.0 Added the optional parameter limit. 59 | // 5.3.6 The parameter provide_object changed to options and 60 | // additional option DEBUG_BACKTRACE_IGNORE_ARGS is added. 61 | // 5.2.5 Added the optional parameter provide_object. 62 | // 5.1.1 Added the current object as a possible return element. 63 | if (version_compare(PHP_VERSION, '5.4.0', '>=')) 64 | { 65 | // signature is: 66 | // array debug_backtrace ([ int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT [, int $limit = 0 ]] ) 67 | // 68 | // possible values for $options: 69 | // - DEBUG_BACKTRACE_PROVIDE_OBJECT 70 | // - DEBUG_BACKTRACE_IGNORE_ARGS 71 | // - DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS 72 | $debugBacktrace = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT ); 73 | } 74 | elseif (version_compare(PHP_VERSION, '5.3.6', '>=')) 75 | { 76 | // signature is: 77 | // array debug_backtrace ([ int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT ] ) 78 | // 79 | // possible values for $options: 80 | // - DEBUG_BACKTRACE_PROVIDE_OBJECT 81 | // - DEBUG_BACKTRACE_IGNORE_ARGS 82 | // - DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS 83 | $debugBacktrace = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT ); 84 | } 85 | elseif (version_compare(PHP_VERSION, '5.2.5', '>=')) 86 | { 87 | // signature is: 88 | // array debug_backtrace ([ bool $provide_object = TRUE ] ) 89 | $debugBacktrace = debug_backtrace( true ); 90 | } 91 | else /* version < 5.2.5 */ 92 | { 93 | // signature is: 94 | // array debug_backtrace ( ) 95 | $debugBacktrace = debug_backtrace(); 96 | } 97 | 98 | return $debugBacktrace; 99 | } 100 | 101 | protected function collectDebugInfo($context, $sourceFile, $data) 102 | { 103 | if($context instanceof YiiDebugToolbar || false !== ($context instanceof YiiDebugToolbarPanel)) 104 | return; 105 | 106 | $backTrace = $this->getDebugBacktrace(); 107 | $backTraceItem = null; 108 | 109 | while($backTraceItem = array_shift($backTrace)) 110 | { 111 | if(isset($backTraceItem['object']) && $backTraceItem['object'] && ($backTraceItem['object'] instanceof $context) && in_array($backTraceItem['function'], array( 112 | 'render', 113 | 'renderPartial' 114 | )) ) 115 | { 116 | break; 117 | } 118 | } 119 | 120 | array_push($this->_debugStackTrace, array( 121 | 'context'=>$context, 122 | 'contextProperties'=> get_object_vars($context), 123 | 'action'=> $context instanceof CController ? $context->action : null, 124 | 'actionParams'=> ($context instanceof CController && method_exists($context, 'getActionParams')) 125 | ? $context->actionParams 126 | : null, 127 | 'route'=> $context instanceof CController ? $context->route : null, 128 | 'sourceFile'=>$sourceFile, 129 | 'data'=>$data, 130 | 'backTrace'=>$backTraceItem, 131 | 'reflection' => new ReflectionObject($context) 132 | )); 133 | } 134 | 135 | } -------------------------------------------------------------------------------- /assets/fonts/yii-debug.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malyshev/yii-debug-toolbar/afcb27ca748a554089df1eeb0aaea6c537d9fccc/assets/fonts/yii-debug.eot -------------------------------------------------------------------------------- /assets/fonts/yii-debug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This SVG font generated by Fontastic.me 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /assets/fonts/yii-debug.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malyshev/yii-debug-toolbar/afcb27ca748a554089df1eeb0aaea6c537d9fccc/assets/fonts/yii-debug.ttf -------------------------------------------------------------------------------- /assets/fonts/yii-debug.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malyshev/yii-debug-toolbar/afcb27ca748a554089df1eeb0aaea6c537d9fccc/assets/fonts/yii-debug.woff -------------------------------------------------------------------------------- /assets/icons-reference.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Font Reference - yii-debug 8 | 9 | 10 | 41 | 42 | 43 |
44 |

yii-debug

45 |

This font was created with Fontastic

46 |

Character mapping

47 |
    48 |
  • 49 |
    50 | 51 |
  • 52 |
  • 53 |
    54 | 55 |
  • 56 |
  • 57 |
    58 | 59 |
  • 60 |
  • 61 |
    62 | 63 |
  • 64 |
  • 65 |
    66 | 67 |
  • 68 |
  • 69 |
    70 | 71 |
  • 72 |
  • 73 |
    74 | 75 |
  • 76 |
  • 77 |
    78 | 79 |
  • 80 |
  • 81 |
    82 | 83 |
  • 84 |
  • 85 |
    86 | 87 |
  • 88 |
  • 89 |
    90 | 91 |
  • 92 |
  • 93 |
    94 | 95 |
  • 96 |
  • 97 |
    98 | 99 |
  • 100 |
  • 101 |
    102 | 103 |
  • 104 |
  • 105 |
    106 | 107 |
  • 108 |
  • 109 |
    110 | 111 |
  • 112 |
  • 113 |
    114 | 115 |
  • 116 |
  • 117 |
    118 | 119 |
  • 120 |
  • 121 |
    122 | 123 |
  • 124 |
  • 125 |
    126 | 127 |
  • 128 |
  • 129 |
    130 | 131 |
  • 132 |
  • 133 |
    134 | 135 |
  • 136 |
137 |

CSS mapping

138 |
    139 |
  • 140 |
    141 | 142 |
  • 143 |
  • 144 |
    145 | 146 |
  • 147 |
  • 148 |
    149 | 150 |
  • 151 |
  • 152 |
    153 | 154 |
  • 155 |
  • 156 |
    157 | 158 |
  • 159 |
  • 160 |
    161 | 162 |
  • 163 |
  • 164 |
    165 | 166 |
  • 167 |
  • 168 |
    169 | 170 |
  • 171 |
  • 172 |
    173 | 174 |
  • 175 |
  • 176 |
    177 | 178 |
  • 179 |
  • 180 |
    181 | 182 |
  • 183 |
  • 184 |
    185 | 186 |
  • 187 |
  • 188 |
    189 | 190 |
  • 191 |
  • 192 |
    193 | 194 |
  • 195 |
  • 196 |
    197 | 198 |
  • 199 |
  • 200 |
    201 | 202 |
  • 203 |
  • 204 |
    205 | 206 |
  • 207 |
  • 208 |
    209 | 210 |
  • 211 |
  • 212 |
    213 | 214 |
  • 215 |
  • 216 |
    217 | 218 |
  • 219 |
  • 220 |
    221 | 222 |
  • 223 |
  • 224 |
    225 | 226 |
  • 227 |
228 |
244 | 245 | -------------------------------------------------------------------------------- /assets/main.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | @font-face { 4 | font-family:"yii-debug"; 5 | src:url("fonts/yii-debug.eot"); 6 | src:url("fonts/yii-debug.eot?#iefix") format("embedded-opentype"), 7 | url("fonts/yii-debug.ttf") format("truetype"), 8 | url("fonts/yii-debug.svg#yii-debug") format("svg"), 9 | url("fonts/yii-debug.woff") format("woff"); 10 | font-weight:normal; 11 | font-style:normal; 12 | } 13 | 14 | #ydtb-toolbar * { 15 | background:#FFF; 16 | margin:0; 17 | padding:0; 18 | outline:0; 19 | vertical-align:baseline; 20 | background:transparent; 21 | text-align:left; 22 | list-style:none; 23 | list-style-type:none; 24 | font:16px/1.3 "Trebuchet MS", Helvetica, sans-serif; 25 | line-height:20px; 26 | text-decoration:none; 27 | border:0 none; 28 | color:#333; 29 | } 30 | 31 | #ydtb-toolbar div[data-ydtb-container] {padding: 20px;} 32 | 33 | #ydtb-toolbar .clearfix:after{content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;} 34 | #ydtb-toolbar .clearfix {display:block;} 35 | #ydtb-toolbar .clear {clear:both;} 36 | 37 | #ydtb-toolbar { 38 | position:fixed; 39 | z-index:10000000; 40 | top:0; 41 | right:0; 42 | bottom:0; 43 | overflow:hidden; 44 | background:transparent; 45 | -webkit-transition:all 0.3s ease-in-out; 46 | -moz-transition:all 0.3s ease-in-out; 47 | -o-transition:all 0.3s ease-in-out; 48 | transition:all 0.3s ease-in-out; 49 | } 50 | 51 | #ydtb-toolbar h2 { 52 | color: #42B3E5; 53 | padding: 10px 10px; 54 | } 55 | 56 | #ydtb-toolbar.ydtb-collapse { 57 | width:10px; 58 | right:-10px; 59 | } 60 | 61 | #ydtb-toolbar a[data-ydtb-toggle]{ 62 | z-index:10000100; 63 | display:block; 64 | position:fixed; 65 | top:0px; 66 | right:0px; 67 | height:24px; 68 | width:24px; 69 | bottom:0; 70 | background: #42B3E5 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QsODwEuO+qYwAAAAHNJREFUWMNjdNr89D8DbgCTY2SgMWAhIE9zB8AAE8MgAYPKIf8Hi0MYR6NmMDqEhRLNe32kUPjOW56NRs2oQ0YdMniyL3oWJSdbE5O1R6Nm0DqEkUBTcTTXjFZ6ow4ZnomVksQ5GjWjDhl1CK0d8p9enXQAt4YV/tNRncAAAAAASUVORK5CYII=) no-repeat scroll center center; 71 | text-indent:-999999px; 72 | display:block; 73 | color:#fff; 74 | } 75 | 76 | #ydtb-toolbar.ydtb-collapse a[data-ydtb-toggle] { 77 | -moz-opacity:0.30; 78 | opacity:0.30; 79 | -ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=30); 80 | -webkit-transition:all 300ms ease-in-out; 81 | -moz-transition:all 300ms ease-in-out; 82 | -o-transition:all 300ms ease-in-out; 83 | transition:all 300ms ease-in-out; 84 | } 85 | 86 | #ydtb-toolbar.ydtb-collapse a[data-ydtb-toggle]:hover, 87 | #ydtb-toolbar:not(.ydtb-collapse) a[data-ydtb-toggle] { 88 | height:64px; 89 | width:64px; 90 | -moz-opacity:1; 91 | opacity:1; 92 | -ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=100); 93 | } 94 | 95 | #ydtb-toolbar [data-ydtb-icon] {vertical-align: middle;} 96 | #ydtb-toolbar [data-ydtb-icon]:before { 97 | font-family:"yii-debug" !important; 98 | content:attr(data-ydtb-icon); 99 | font-style:normal !important; 100 | font-weight:normal !important; 101 | font-variant:normal !important; 102 | text-transform:none !important; 103 | speak:none; 104 | line-height:1; 105 | -webkit-font-smoothing:antialiased; 106 | -moz-osx-font-smoothing:grayscale; 107 | } 108 | 109 | #ydtb-toolbar a { 110 | transition-delay:100ms; 111 | -webkit-transition-delay:100ms; 112 | -webkit-transition:background-color 200ms ease-in-out,z-index 200ms ease-in-out; 113 | transition:background-color 200ms ease-in-out,z-index 200ms ease-in-out; 114 | text-decoration:none; 115 | } 116 | 117 | #ydtb-toolbar a:hover{text-decoration:none;} 118 | #ydtb-toolbar div[data-ydtb-options] { 119 | position:fixed; 120 | right: 216px; 121 | bottom:0; 122 | width: 64px; 123 | height: 64px; 124 | z-index:10000110; 125 | -webkit-transition:all 0.2s ease-in-out; 126 | -moz-transition:all 0.2s ease-in-out; 127 | -o-transition:all 0.2s ease-in-out; 128 | transition:all 0.2s ease-in-out; 129 | } 130 | 131 | #ydtb-toolbar div[data-ydtb-options] i { 132 | height: 64px; 133 | line-height: 64px; 134 | text-align: center; 135 | color: #fff; 136 | font-size:40px; 137 | cursor: pointer; 138 | } 139 | 140 | #ydtb-toolbar.ydtb-slim div[data-ydtb-options] {right:0;} 141 | 142 | #ydtb-toolbar.ydtb-slim div[data-ydtb-options] i[data-ydtb-icon="t"], 143 | #ydtb-toolbar div[data-ydtb-options] i[data-ydtb-icon="u"] {display: none;} 144 | #ydtb-toolbar.ydtb-slim div[data-ydtb-options] i[data-ydtb-icon="u"], 145 | #ydtb-toolbar div[data-ydtb-options] i[data-ydtb-icon="t"] {display: block;} 146 | 147 | #ydtb-toolbar div[data-ydtb-sidebar] { 148 | position:fixed; 149 | -webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.15); 150 | box-shadow:0 1px 2px rgba(0, 0, 0, 0.15); 151 | z-index:10000010; 152 | top:0px; 153 | right:0; 154 | width:280px; 155 | bottom:0; 156 | background:#42B3E5; 157 | -webkit-transition:all 0.2s ease-in-out; 158 | -moz-transition:all 0.2s ease-in-out; 159 | -o-transition:all 0.2s ease-in-out; 160 | transition:all 0.2s ease-in-out; 161 | } 162 | 163 | #ydtb-toolbar.ydtb-collapse div[data-ydtb-sidebar] {display:none;} 164 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] {width:64px;} 165 | #ydtb-toolbar div[data-ydtb-sidebar] * {color:#fff;} 166 | #ydtb-toolbar div[data-ydtb-sidebar] h1 { 167 | height:64px; 168 | line-height:64px; 169 | font-size:24px; 170 | display:block; 171 | color:#fff; 172 | padding:0 20px; 173 | } 174 | 175 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] h1 {text-indent:-999999px;} 176 | 177 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-dashboard] { 178 | display:block; 179 | overflow:hidden; 180 | width:100%; 181 | } 182 | 183 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] ul[data-ydtb-dashboard] {display:none;} 184 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-dashboard] li { 185 | display:block; 186 | width:30%; 187 | margin:0 5px 5px 0; 188 | overflow:hidden; 189 | float:left; 190 | text-align:center; 191 | padding:10px 0px; 192 | color:#fff; 193 | } 194 | 195 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-dashboard] li i{ 196 | font-size:40px; 197 | display:block; 198 | text-align:center; 199 | height:55px; 200 | line-height:55px; 201 | } 202 | 203 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-dashboard] li em{ 204 | display:block; 205 | text-align:center; 206 | font-size:14px; 207 | font-weight:normal; 208 | } 209 | 210 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-dashboard] li small{ 211 | display:block; 212 | text-align:center; 213 | font-weight:normal; 214 | font-size:13px; 215 | } 216 | 217 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] { 218 | display:block; 219 | padding:0px; 220 | overflow:hidden; 221 | clear:both; 222 | display:block; 223 | width:280px; 224 | -webkit-transition:all 0.2s ease-in-out; 225 | -moz-transition:all 0.2s ease-in-out; 226 | -o-transition:all 0.2s ease-in-out; 227 | transition:all 0.2s ease-in-out; 228 | overflow: auto; 229 | overflow-x: hidden; 230 | position: fixed; 231 | top: 180px; 232 | bottom: 64px; 233 | } 234 | 235 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a { 236 | display:block; 237 | height:64px; 238 | line-height:64px; 239 | margin:0; 240 | font-size:18px; 241 | padding:0 10px; 242 | color:#fff; 243 | } 244 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] ul[data-ydtb-menu]{top: 64px;} 245 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] ul[data-ydtb-menu] li a {padding:0;} 246 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] ul[data-ydtb-menu] li a span, 247 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] ul[data-ydtb-menu] li a small {display:none;} 248 | 249 | #ydtb-toolbar.ydtb-slim div[data-ydtb-sidebar] ul[data-ydtb-menu] li a i { 250 | width:64px; 251 | float:none; 252 | text-align:center; 253 | } 254 | 255 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a i { 256 | color:#fff; 257 | font-size:28px; 258 | display:block; 259 | height:64px; 260 | line-height:64px; 261 | float:left; 262 | margin:0 8px 0 0; 263 | } 264 | 265 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a:hover, 266 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a.active { 267 | background:#fff; 268 | color:#42B3E5; 269 | } 270 | 271 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a:hover i, 272 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a.active i, 273 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a:hover span, 274 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a.active span {color:#42B3E5;} 275 | 276 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a:hover small, 277 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a.active small { 278 | color:#fff; 279 | background:#42B3E5; 280 | } 281 | 282 | #ydtb-toolbar div[data-ydtb-sidebar] ul[data-ydtb-menu] li a small { 283 | display:block; 284 | float:right; 285 | height:20px; 286 | line-height:20px; 287 | margin-top:25px; 288 | color:#42B3E5; 289 | background:#fff; 290 | padding:0 10px; 291 | -webkit-border-radius:3px; 292 | -moz-border-radius:3px; 293 | border-radius:3px; 294 | font-size:11px; 295 | } 296 | 297 | /** panels */ 298 | #ydtb-toolbar div[data-ydtb-panel] { 299 | position:fixed; 300 | z-index:10000000; 301 | top:0px; 302 | left:0; 303 | right: 280px; 304 | bottom:0; 305 | background:#fff; 306 | -webkit-transition:all 0.2s ease-in-out; 307 | -moz-transition:all 0.2s ease-in-out; 308 | -o-transition:all 0.2s ease-in-out; 309 | transition:all 0.2s ease-in-out; 310 | min-width: 500px; 311 | overflow-x: hidden; 312 | } 313 | 314 | #ydtb-toolbar div[data-ydtb-panel] div[data-ydtb-panel-content] { 315 | position:fixed; 316 | top:64px; 317 | bottom:0; 318 | left:0px; 319 | right: 280px; 320 | color:#666; 321 | z-index:100000000; 322 | -webkit-transition:all 0.2s ease-in-out; 323 | -moz-transition:all 0.2s ease-in-out; 324 | -o-transition:all 0.2s ease-in-out; 325 | transition:all 0.2s ease-in-out; 326 | } 327 | 328 | #ydtb-toolbar.ydtb-slim div[data-ydtb-panel] div[data-ydtb-panel-content] {right:64px;} 329 | #ydtb-toolbar.ydtb-slim div[data-ydtb-panel] {right:64px;} 330 | #ydtb-toolbar.ydtb-collapse div[data-ydtb-panel] {display:none;} 331 | #ydtb-toolbar div[data-ydtb-panel].ydtb-collapse {display:none;} 332 | #ydtb-toolbar div[data-ydtb-panel] i[data-ydtb-icon] {color:#42B3E5;} 333 | 334 | #ydtb-toolbar div[data-ydtb-panel] > div:first-child { 335 | position:absolute; 336 | background-color:#fff; 337 | color:#42B3E5; 338 | top:0; 339 | right:0; 340 | left:0; 341 | height:64px; 342 | line-height:64px; 343 | font-size:24px; 344 | padding:0 20px; 345 | border-bottom:1px solid #42B3E5; 346 | white-space: nowrap; 347 | min-width: 500px; 348 | overflow-x: hidden; 349 | overflow: hidden; 350 | } 351 | 352 | #ydtb-toolbar div[data-ydtb-panel] > div:first-child ul, 353 | #ydtb-toolbar div[data-ydtb-panel] > div:first-child ul li { 354 | display:block; 355 | float:right; 356 | } 357 | 358 | #ydtb-toolbar div[data-ydtb-panel] > div:first-child ul li {display:inline;} 359 | 360 | #ydtb-toolbar div[data-ydtb-panel] div[data-ydtb-panel-header] i { 361 | font-size:34px; 362 | line-height:64px; 363 | vertical-align: middle; 364 | margin:0 15px 0 0px; 365 | } 366 | 367 | #ydtb-toolbar div[data-ydtb-panel] > div:first-child ul li i { 368 | font-size:24px; 369 | cursor:pointer; 370 | display:block; 371 | margin:0 0 0 10px; 372 | } 373 | 374 | #ydtb-toolbar div[data-ydtb-panel].ydtb-panel-lock > div:first-child ul li i[data-ydtb-icon="z"] {color:#ff8729;} 375 | 376 | #ydtb-toolbar div[data-ydtb-tabs] ul { 377 | border-top: 1px solid none; 378 | border-bottom: 1px solid #42B3E5; 379 | display: block; 380 | height: 48px; 381 | line-height: 48px; 382 | text-align: right; 383 | padding: 0 20px; 384 | padding-bottom: 3px; 385 | } 386 | 387 | #ydtb-toolbar div[data-ydtb-tabs] ul li { 388 | display:inline-block; 389 | padding-left: 5px; 390 | } 391 | 392 | #ydtb-toolbar div[data-ydtb-tabs] ul li i[data-ydtb-icon] { 393 | padding: 0 5px 0 0; 394 | font-size: 11px; 395 | vertical-align: 5%; 396 | } 397 | 398 | #ydtb-toolbar div[data-ydtb-tabs] ul li a { 399 | display:block; 400 | color:#42B3E5; 401 | height:34px; 402 | line-height:34px; 403 | padding:0 5px; 404 | border:0px solid transparent; 405 | border-width:3px 0; 406 | background:none; 407 | -moz-opacity:0.70; 408 | opacity:0.70; 409 | -ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=70); 410 | -webkit-transition:all 100ms ease-in-out; 411 | -moz-transition:all 100ms ease-in-out; 412 | -o-transition:all 100ms ease-in-out; 413 | transition:all 100ms ease-in-out; 414 | } 415 | 416 | #ydtb-toolbar div[data-ydtb-tabs] ul li a:hover, 417 | #ydtb-toolbar div[data-ydtb-tabs] ul li a[data-ydtb-tab-state="open"] { 418 | border-bottom-color:#42B3E5; 419 | -moz-opacity:1; 420 | opacity:1; 421 | -ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=100); 422 | } 423 | 424 | #ydtb-toolbar div[data-ydtb-panel-data] { 425 | position:fixed; 426 | z-index:10000000; 427 | top:64px; 428 | left:0; 429 | right: 280px; 430 | bottom:0; 431 | -webkit-transition:all 0.2s ease-in-out; 432 | -moz-transition:all 0.2s ease-in-out; 433 | -o-transition:all 0.2s ease-in-out; 434 | transition:all 0.2s ease-in-out; 435 | min-width: 500px; 436 | overflow-x: hidden; 437 | } 438 | 439 | #ydtb-toolbar.ydtb-slim div[data-ydtb-panel-data] {right: 64px;} 440 | #ydtb-toolbar div[data-ydtb-tabs] div[data-ydtb-panel-data] {top:116px;} 441 | 442 | #ydtb-toolbar div[data-ydtb-panel-data] > div{ 443 | overflow-y: auto; 444 | height: 100%; 445 | } 446 | 447 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading] { 448 | border-top: 1px solid none; 449 | border-bottom: 1px solid #42B3E5; 450 | display: block; 451 | height: 48px; 452 | line-height: 48px; 453 | padding: 0 20px; 454 | cursor: pointer; 455 | white-space: nowrap; 456 | } 457 | 458 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading] * { 459 | color:#42B3E5; 460 | } 461 | 462 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading] i[data-ydtb-icon="q"], 463 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading] i[data-ydtb-icon="t"] { 464 | float: right; 465 | font-size: 24px; 466 | vertical-align: middle; 467 | height: 48px; 468 | line-height: 48px; 469 | } 470 | 471 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading][data-ydtb-data-size="0"] { 472 | cursor: default; 473 | } 474 | 475 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading][data-ydtb-data-size="0"] * { 476 | -moz-opacity:0.30; 477 | opacity:0.30; 478 | -ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=30); 479 | } 480 | 481 | 482 | 483 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-heading] i:first-child {margin-right: 10px;} 484 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group="collapsed"] div[data-ydtb-accordion-heading] i[data-ydtb-icon="q"] {display: none;} 485 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group="expanded"] div[data-ydtb-accordion-heading] i[data-ydtb-icon="t"] {display: none;} 486 | 487 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading][data-ydtb-data-size="0"] i[data-ydtb-icon="q"], 488 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-heading][data-ydtb-data-size="0"] i[data-ydtb-icon="t"] { 489 | display: none; 490 | } 491 | 492 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group] div[data-ydtb-accordion-body] { 493 | -webkit-transition: height 0.3s ease-in-out; 494 | -moz-transition: height 0.3s ease-in-out; 495 | -o-transition: height 0.3s ease-in-out; 496 | transition: height 0.3s ease-in-out; 497 | overflow: hidden; 498 | border-bottom: 1px solid #42B3E5; 499 | } 500 | 501 | #ydtb-toolbar div[data-ydtb-accordion] div[data-ydtb-accordion-group="collapsed"] div[data-ydtb-accordion-body] { 502 | height: 0px; 503 | border-bottom: 1px solid #fff; 504 | } 505 | 506 | 507 | #ydtb-toolbar table[data-ydtb-data-table] { 508 | width:100%; 509 | border-collapse: collapse; 510 | } 511 | 512 | #ydtb-toolbar table[data-ydtb-data-table="fixed"] { 513 | table-layout:fixed; 514 | } 515 | 516 | 517 | #ydtb-toolbar table[data-ydtb-data-table] * { 518 | font-size: 14px; 519 | } 520 | 521 | #ydtb-toolbar table[data-ydtb-data-table] tr { 522 | border: 1px solid #E7F8FF; 523 | border-right: 0 none; 524 | } 525 | 526 | #ydtb-toolbar table[data-ydtb-data-table] th { 527 | background: #E7F8FF; 528 | color: #42B3E5; 529 | padding: 5px 10px 5px 10px; 530 | } 531 | 532 | #ydtb-toolbar table[data-ydtb-data-table] tbody tr th { 533 | width: 20%; 534 | text-align: right; 535 | overflow: hidden; 536 | font-weight: bold; 537 | } 538 | 539 | #ydtb-toolbar table[data-ydtb-data-table] tr td { 540 | padding: 5px 10px 5px 10px; 541 | vertical-align: middle; 542 | overflow: hidden; 543 | } 544 | 545 | #ydtb-toolbar table[data-ydtb-data-table] tr.ydtb-hover, 546 | #ydtb-toolbar table[data-ydtb-data-table] tbody tr.ydtb-hover th { 547 | background: #E7F8EE; 548 | border: 1px solid #E7F8EE; 549 | } 550 | 551 | #ydtb-toolbar table[data-ydtb-data-table] tr td[data-ydtb-data-type="varchar"] { 552 | width: 100%; 553 | } 554 | 555 | #ydtb-toolbar table[data-ydtb-data-table] tr td[data-ydtb-data-type="char"] { 556 | white-space: nowrap; 557 | } 558 | 559 | 560 | #ydtb-toolbar table[data-ydtb-data-table] tr td[data-ydtb-data-type="number"] { 561 | text-align: right; 562 | white-space: nowrap; 563 | } 564 | 565 | 566 | -------------------------------------------------------------------------------- /assets/main.js: -------------------------------------------------------------------------------- 1 | (function($){ 2 | YiiDebugToolbar = { 3 | 4 | ic : function(id, s) { 5 | id = 'collapse:' + id; 6 | var r = localStorage.getItem(id); 7 | if (null == r) { 8 | localStorage.setItem(id, true); 9 | } else if(typeof s != 'undefined'){ 10 | localStorage.setItem(id, s); 11 | } 12 | return localStorage.getItem(id) == 'false' ? false : true; 13 | }, 14 | 15 | init : function() { 16 | var lockedPanel = localStorage.getItem('ydtb-panel-lock'); 17 | if (null != lockedPanel) { 18 | this.ic('[data-ydtb-toolbar]', false); 19 | $('div[data-ydtb-panel]').removeClass('ydtb-panel-lock'); 20 | $('div[data-ydtb-panel="'+lockedPanel+'"]').addClass('ydtb-panel-lock').toggleClass('ydtb-collapse', false); 21 | $('[data-ydtb-expand-panel="'+lockedPanel+'"]').addClass('active'); 22 | } 23 | 24 | $('#ydtb-toolbar').toggleClass('ydtb-collapse', this.ic('[data-ydtb-toolbar]')); 25 | $('#ydtb-toolbar').toggleClass('ydtb-slim', this.ic('.ydtb-slim')); 26 | 27 | 28 | $('[data-ydtb-data-table] tr').mouseenter(function(){ 29 | $(this).addClass('ydtb-hover'); 30 | }).mouseleave(function(){ 31 | $(this).removeClass('ydtb-hover'); 32 | }); 33 | 34 | $('[data-ydtb-toggle]').bind('click', $.proxy(function(e) { 35 | var $el = $(e.currentTarget); 36 | var $target = $($el.data('ydtb-toggle')); 37 | $target.toggleClass('ydtb-collapse', !$target.hasClass('ydtb-collapse')); 38 | this.ic($el.data('ydtb-toggle'), $target.hasClass('ydtb-collapse')); 39 | localStorage.removeItem('ydtb-panel-lock'); 40 | $('div[data-ydtb-panel]').removeClass('ydtb-panel-lock'); 41 | }, this)); 42 | 43 | $('[data-ydtb-expand-panel]').bind('click', function(){ 44 | var $el = $(this); 45 | $('[data-ydtb-menu] *').removeClass('active'); 46 | localStorage.removeItem('ydtb-panel-lock'); 47 | $('div[data-ydtb-panel]').removeClass('ydtb-panel-lock').addClass('ydtb-collapse'); 48 | $('div[data-ydtb-panel="'+$el.data('ydtb-expand-panel')+'"]').removeClass('ydtb-collapse'); 49 | $el.addClass('active'); 50 | }); 51 | 52 | $('div[data-ydtb-panel] i[data-ydtb-icon="f"], div[data-ydtb-panel] i[data-ydtb-icon="e"]').bind('click', $.proxy(function(e) { 53 | var $target = $('#ydtb-toolbar'); 54 | $target.toggleClass('ydtb-slim'); 55 | this.ic('.ydtb-slim', $target.hasClass('ydtb-slim')); 56 | }, this)); 57 | 58 | 59 | $('div[data-ydtb-options] i[data-ydtb-icon="t"], div[data-ydtb-options] i[data-ydtb-icon="u"]').bind('click', $.proxy(function(e) { 60 | var $target = $('#ydtb-toolbar'); 61 | $target.toggleClass('ydtb-slim'); 62 | this.ic('.ydtb-slim', $target.hasClass('ydtb-slim')); 63 | }, this)); 64 | 65 | $('div[data-ydtb-panel] i[data-ydtb-icon="z"]').bind('click', $.proxy(function(e){ 66 | var $el = $(e.currentTarget); 67 | localStorage.setItem('ydtb-panel-lock', $el.data('ydtb-panel-lock')); 68 | $('div[data-ydtb-panel]').removeClass('ydtb-panel-lock'); 69 | $('div[data-ydtb-panel="'+$el.data('ydtb-panel-lock')+'"]').addClass('ydtb-panel-lock'); 70 | }, this)); 71 | 72 | $('div[data-ydtb-panel] i[data-ydtb-icon="h"]').bind('click', $.proxy(function(e) { 73 | $('[data-ydtb-menu] *').removeClass('active'); 74 | localStorage.removeItem('ydtb-panel-lock'); 75 | $('div[data-ydtb-panel]').removeClass('ydtb-panel-lock').addClass('ydtb-collapse'); 76 | })); 77 | 78 | $('div[data-ydtb-tabs] ul li a').bind('click', function(e) { 79 | e.preventDefault(); 80 | var $context = $(this).closest('div[data-ydtb-tabs]'); 81 | $('ul li a', $context).attr('data-ydtb-tab-state', 'closed'); 82 | $(this).attr('data-ydtb-tab-state', 'open'); 83 | $('div[data-ydtb-tab]', $context).hide(); 84 | $('div[data-ydtb-tab="'+ $(this).attr('href').replace(/^#/, '') +'"]', $context).show(); 85 | }).first().click(); 86 | 87 | $('div[data-ydtb-accordion-heading]').not('[data-ydtb-data-size="0"]').click(function(){ 88 | var $el = $(this), 89 | $owner = $el.closest('div[data-ydtb-accordion-group]'), 90 | $body = $owner.find('div[data-ydtb-accordion-body]'); 91 | 92 | $('div[data-ydtb-accordion-group]').not($owner).attr('data-ydtb-accordion-group', 'collapsed').data('ydtb-accordion-group', 'collapsed') 93 | .find('div[data-ydtb-accordion-body]').css({'height' : '0px'}); 94 | 95 | if ($owner.data('ydtb-accordion-group') != 'expanded') { 96 | $body.css({'height' : ($body.find(':first-child').outerHeight() + 'px')}); 97 | $owner.attr('data-ydtb-accordion-group', 'expanded').data('ydtb-accordion-group', 'expanded'); 98 | } else { 99 | $owner.attr('data-ydtb-accordion-group', 'collapsed').data('ydtb-accordion-group', 'collapsed'); 100 | $body.css({'height' : '0px'}); 101 | } 102 | }); 103 | } 104 | }; 105 | 106 | $(function() { 107 | YiiDebugToolbar.init(); 108 | }); 109 | 110 | })( jQuery ); 111 | -------------------------------------------------------------------------------- /assets/styles.css: -------------------------------------------------------------------------------- 1 | 2 | @charset "UTF-8"; 3 | 4 | @font-face { 5 | font-family: "yii-debug"; 6 | src:url("fonts/yii-debug.eot"); 7 | src:url("fonts/yii-debug.eot?#iefix") format("embedded-opentype"), 8 | url("fonts/yii-debug.ttf") format("truetype"), 9 | url("fonts/yii-debug.svg#yii-debug") format("svg"), 10 | url("fonts/yii-debug.woff") format("woff"); 11 | font-weight: normal; 12 | font-style: normal; 13 | 14 | } 15 | 16 | [data-icon]:before { 17 | font-family: "yii-debug" !important; 18 | content: attr(data-icon); 19 | font-style: normal !important; 20 | font-weight: normal !important; 21 | font-variant: normal !important; 22 | text-transform: none !important; 23 | speak: none; 24 | line-height: 1; 25 | -webkit-font-smoothing: antialiased; 26 | -moz-osx-font-smoothing: grayscale; 27 | } 28 | 29 | [class^="icon-"]:before, 30 | [class*=" icon-"]:before { 31 | font-family: "yii-debug" !important; 32 | font-style: normal !important; 33 | font-weight: normal !important; 34 | font-variant: normal !important; 35 | text-transform: none !important; 36 | speak: none; 37 | line-height: 1; 38 | -webkit-font-smoothing: antialiased; 39 | -moz-osx-font-smoothing: grayscale; 40 | } 41 | 42 | 43 | .icon-arrow-cycle:before { 44 | content: "c"; 45 | } 46 | 47 | .icon-arrow-down:before { 48 | content: "d"; 49 | } 50 | 51 | .icon-arrow-right:before { 52 | content: "f"; 53 | } 54 | 55 | .icon-arrow-up-thin:before { 56 | content: "g"; 57 | } 58 | 59 | .icon-arrow-left-thin:before { 60 | content: "e"; 61 | } 62 | 63 | .icon-cross:before { 64 | content: "h"; 65 | } 66 | 67 | .icon-coins:before { 68 | content: "i"; 69 | } 70 | 71 | .icon-block-menu:before { 72 | content: "j"; 73 | } 74 | 75 | .icon-settings:before { 76 | content: "k"; 77 | } 78 | 79 | .icon-eye:before { 80 | content: "l"; 81 | } 82 | 83 | .icon-female-symbol:before { 84 | content: "m"; 85 | } 86 | 87 | .icon-hdd-raid:before { 88 | content: "n"; 89 | } 90 | 91 | .icon-bolt:before { 92 | content: "o"; 93 | } 94 | 95 | .icon-stopwatch:before { 96 | content: "a"; 97 | } 98 | 99 | .icon-gauge:before { 100 | content: "b"; 101 | } 102 | 103 | .icon-chart-line:before { 104 | content: "p"; 105 | } 106 | 107 | .icon-down-open-mini:before { 108 | content: "q"; 109 | } 110 | 111 | .icon-up-open-mini:before { 112 | content: "r"; 113 | } 114 | 115 | .icon-locked:before { 116 | content: "z"; 117 | } 118 | 119 | .icon-content-44:before { 120 | content: "s"; 121 | } 122 | 123 | .icon-right-open-mini:before { 124 | content: "t"; 125 | } 126 | 127 | .icon-left-open-mini:before { 128 | content: "u"; 129 | } 130 | 131 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "malyshev/yii-debug-toolbar", 3 | "description": "A configurable set of panels that display various debug information about the current request/response.", 4 | "keywords": ["yii", "debug", "extension"], 5 | "license": "BSD-3-Clause", 6 | "authors": [ 7 | { 8 | "name": "Sergey Malyshev", 9 | "email": "malyshev.php@gmail.com", 10 | "homepage": "http://www.yiiframework.com/extension/yii-debug-toolbar/" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /messages/ru/yii-debug-toolbar.php: -------------------------------------------------------------------------------- 1 | 'ТУЛБАР', 5 | 6 | // Blank 7 | 'Blank' => 'Заготовка', 8 | 'Example panel' => 'Пример панели', 9 | 'Blank page' => 'Пустая страница', 10 | 11 | // server 12 | 'Server' => 'Сервер', 13 | 'Yii {n}' => 'Yii {n}', 14 | 'Server Info' => 'Серверная информация', 15 | 16 | // resource 17 | 'Resources' => 'Системные ресурсы', 18 | 'Total time: {n} s.' => 'Общее время: {n} с.', 19 | 'Resource Usage' => 'Использованные ресурсы', 20 | 'Page Load Time' => 'Время формирования страницы', 21 | 'Elapsed Time' => 'Время загрузки страницы', 22 | 'Memory Usage' => 'Использованно памяти', 23 | 'Memory Peak Usage' => 'Пик использования памяти', 24 | 'Session Size' => 'Размер сессии', 25 | 26 | // globals 27 | 'Globals' => 'Информация окружения', 28 | 'Global Variables' => 'Параметры окружения', 29 | 'Variables' => 'Переменные', 30 | 'No COOKIE data' => 'Массив COOKIE пуст', 31 | 'No SESSION data' => 'Массив SESSION пуст', 32 | 'No GET data' => 'Массив GET пуст', 33 | 'No POST data' => 'Массив POST пуст', 34 | 'No FILES data' => 'Массив FILES пуст', 35 | 36 | // settings 37 | 'Settings' => 'Параметры', 38 | 'ON' => 'Вкл.', 39 | 'OFF' => 'Выкл.', 40 | 'Application Settings' => 'Параметры приложения', 41 | 'Application Properties' => 'Свойства приложения', 42 | 'Property' => 'Свойство', 43 | 'Modules' => 'Модули', 44 | 'Module ID' => 'Модуль ID', 45 | 'Configuration' => 'Конфигурация', 46 | 'Application Params' => 'Параметры приложения', 47 | 'Components' => 'Компоненты', 48 | 'Component ID' => 'ID компонента', 49 | 50 | // SQL 51 | 'SQL' => 'SQL', 52 | '{n} query in {s} s.|{n} queries in {s} s.' => '{n} запрос за {s} с.|{n} запроса за {s} с.|{n} запросов за {s} с.', 53 | 'SQL Queries from {n} connection|SQL Queries from {n} connections' => 'SQL запросы из {n} соединения|SQL запросы из {n} соединений', 54 | 'Connection ID' => 'ID соединения', 55 | 'Query' => 'Запрос', 56 | 'ID' => 'ID', 57 | 'Count' => 'Количество', 58 | 'Total (s)' => 'Всего (сек)', 59 | 'Avg. (s)' => 'Средн. (сек)', 60 | 'Min. (s)' => 'Мин. (сек)', 61 | 'Max. (s)' => 'Макс. (сек)', 62 | 'Time (s)' => 'Время (сек)', 63 | 'Driver' => 'Драйвер', 64 | 'Server Version' => 'Версия сервера', 65 | 'Uptime' => 'Время работы', 66 | 'Threads' => 'Потоков', 67 | 'Questions' => '', 68 | 'Slow queries' => 'Медленных запросов', 69 | 'Opens' => 'Открыто', 70 | 'Flush tables' => '', 71 | 'Open tables' => '', 72 | 'Queries per second avg' => 'Запросов в секунду', 73 | 'Mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.' => '', 74 | 'Summary' => 'Общая информация', 75 | 'Callstack' => 'Стек вызовов', 76 | 'Servers' => 'Сервер', 77 | 'No SQL queries were recorded during this request or profiling the SQL is DISABLED.' => 'Запросо к базе не было, либо профилирование SQL отключено.', 78 | 79 | // logging 80 | 'Logging' => 'Логирование', 81 | '{n} message|{n} messages' => '{n} сообщение|{n} сообщения|{n} сообщений', 82 | 'Log Messages' => 'Лог сообщений', 83 | 'Message (details)' => 'Сообщения', 84 | 'Level' => 'Уровень', 85 | 'Category' => 'Категория', 86 | 'Time' => 'Время', 87 | 88 | // asset 89 | 'Assets' => 'Ресурсы', 90 | 'Manage assets files' => 'Управление ресурсами', 91 | 'Assets Manager' => 'Менеджер ресурсов', 92 | 'Assets path' => 'Папка с ресурсами', 93 | 'Exclude files' => 'Исключения', 94 | 'New dir mode' => 'Права на новые папки', 95 | 'New file mode' => 'Права на новые файлы', 96 | 'Load assets' => 'Загруженные ресурсы', 97 | 'Date create' => 'Дата создания', 98 | 'Show files' => 'Показать файлы', 99 | '{n} file|{n} files' => '{n} файл|{n} файла|{n} файлов', 100 | 'Clean' => 'Очистить', 101 | 'Path not found.' => 'Путь не найден', 102 | 'Unknow error.' => 'Неизвестная ошибка', 103 | 'Files' => 'Файлы', 104 | 'Properties' => 'Свойства', 105 | 106 | // other 107 | 'Failed to delete folder.' => 'Ошибка удаления папки', 108 | 'YiiDebugToolbar owner must be instance of CLogRoute' => 'YiiDebugToolbar должен наследоваться от CLogRoute', 109 | 'The %class% class must be compatible with YiiDebugToolbarPanelInterface' => '%class% должен иметь интерфейс YiiDebugToolbarPanelInterface', 110 | 'Path' => 'Путь', 111 | 'Name' => 'Название', 112 | 'Value' => 'Значение', 113 | 'Close' => 'Закрыть', 114 | ); -------------------------------------------------------------------------------- /messages/simple/yii-debug-toolbar.php: -------------------------------------------------------------------------------- 1 | '', 5 | 6 | // Blank 7 | 'Blank' => '', 8 | 'Example panel' => '', 9 | 'Blank page' => '', 10 | 11 | // server 12 | 'Server' => '', 13 | 'Yii {n}' => '', 14 | 'Server Info' => '', 15 | 16 | // resource 17 | 'Resources' => '', 18 | 'Total time: {n} s.' => ' ', 19 | 'Resource Usage' => '', 20 | 'Page Load Time' => '', 21 | 'Elapsed Time' => '', 22 | 'Memory Usage' => '', 23 | 'Memory Peak Usage' => '', 24 | 'Session Size' => '', 25 | 26 | // globals 27 | 'Globals' => '', 28 | 'Global Variables' => '', 29 | 'Variables' => '', 30 | 'No COOKIE data' => '', 31 | 'No SESSION data' => '', 32 | 'No GET data' => '', 33 | 'No POST data' => '', 34 | 'No FILES data' => '', 35 | 36 | // settings 37 | 'Settings' => '', 38 | 'ON' => '', 39 | 'OFF' => '', 40 | 'Application Settings' => '', 41 | 'Application Properties' => '', 42 | 'Property' => '', 43 | 'Modules' => '', 44 | 'Module ID' => '', 45 | 'Configuration' => '', 46 | 'Application Params' => '', 47 | 'Components' => '', 48 | 'Component ID' => '', 49 | 50 | // SQL 51 | 'SQL' => 'SQL', 52 | '{n} query in {s} s.|{n} queries in {s} s.' => '', 53 | 'SQL Queries from {n} connection|SQL Queries from {n} connections' => '', 54 | 'Connection ID' => '', 55 | 'Query' => '', 56 | 'ID' => '', 57 | 'Count' => '', 58 | 'Total (s)' => '', 59 | 'Avg. (s)' => '', 60 | 'Min. (s)' => '', 61 | 'Max. (s)' => '', 62 | 'Time (s)' => '', 63 | 'Driver' => '', 64 | 'Server Version' => '', 65 | 'Uptime' => '', 66 | 'Threads' => '', 67 | 'Questions' => '', 68 | 'Slow queries' => '', 69 | 'Opens' => '', 70 | 'Flush tables' => '', 71 | 'Open tables' => '', 72 | 'Queries per second avg' => '', 73 | 'Mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.' => '', 74 | 'Summary' => '', 75 | 'Callstack' => '', 76 | 'Servers' => '', 77 | 'No SQL queries were recorded during this request or profiling the SQL is DISABLED.' => '', 78 | 79 | // logging 80 | 'Logging' => '', 81 | '{n} message|{n} messages' => '', 82 | 'Log Messages' => '', 83 | 'Message (details)' => '', 84 | 'Level' => '', 85 | 'Category' => '', 86 | 'Time' => '', 87 | 88 | // asset 89 | 'Assets' => '', 90 | 'Manage assets files' => '', 91 | 'Assets Manager' => '', 92 | 'Assets path' => '', 93 | 'Exclude files' => '', 94 | 'New dir mode' => '', 95 | 'New file mode' => '', 96 | 'Load assets' => '', 97 | 'Date create' => '', 98 | 'Show files' => '', 99 | '{n} file|{n} files' => '', 100 | 'Clean' => '', 101 | 'Path not found.' => '', 102 | 'Unknow error.' => '', 103 | 'Files' => '', 104 | 'Properties' => '', 105 | 106 | // other 107 | 'Failed to delete folder.' => '', 108 | 'YiiDebugToolbar owner must be instance of CLogRoute' => '', 109 | 'The %class% class must be compatible with YiiDebugToolbarPanelInterface' => '', 110 | 'Path' => '', 111 | 'Name' => '', 112 | 'Value' => '', 113 | 'Close' => '', 114 | ); -------------------------------------------------------------------------------- /panels/YiiDebugToolbarPanelLogging.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | 9 | /** 10 | * YiiDebugToolbarPanelLogging represents an ... 11 | * 12 | * Description of YiiDebugToolbarPanelLogging 13 | * 14 | * @author Sergey Malyshev 15 | * @author Igor Golovanov 16 | * @version $Id$ 17 | * @package YiiDebugToolbar 18 | * @since 1.1.7 19 | */ 20 | class YiiDebugToolbarPanelLogging extends YiiDebugToolbarPanel 21 | { 22 | public $i = 'j'; 23 | 24 | /** 25 | * Message count. 26 | * 27 | * @var integer 28 | */ 29 | private $_countMessages; 30 | 31 | /** 32 | * Logs. 33 | * 34 | * @var array 35 | */ 36 | private $_logs; 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | public function getMenuTitle() 42 | { 43 | return YiiDebug::t('Logging'); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getMenuSubTitle() 50 | { 51 | return $this->countMessages; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function getTitle() 58 | { 59 | return YiiDebug::t('Log Messages'); 60 | } 61 | 62 | /** 63 | * Get logs. 64 | * 65 | * @return array 66 | */ 67 | public function getLogs() 68 | { 69 | if (null === $this->_logs) 70 | { 71 | $this->_logs = $this->filterLogs(); 72 | } 73 | return $this->_logs; 74 | } 75 | 76 | /** 77 | * Get count of messages. 78 | * 79 | * @return integer 80 | */ 81 | public function getCountMessages() 82 | { 83 | if (null === $this->_countMessages) 84 | { 85 | $this->_countMessages = count($this->logs); 86 | } 87 | return $this->_countMessages; 88 | } 89 | 90 | /** 91 | * {@inheritdoc} 92 | */ 93 | public function run() 94 | { 95 | $this->render('logging', array( 96 | 'logs' => $this->logs 97 | )); 98 | } 99 | 100 | /** 101 | * Get filter logs. 102 | * 103 | * @return array 104 | */ 105 | protected function filterLogs() 106 | { 107 | $logs = array(); 108 | foreach ($this->owner->getLogs() as $entry) 109 | { 110 | if (CLogger::LEVEL_PROFILE !== $entry[1] && false === strpos($entry[2], 'system.db.CDbCommand')) 111 | { 112 | $logs[] = $entry; 113 | } 114 | } 115 | return $logs; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /panels/YiiDebugToolbarPanelRequest.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | 9 | /** 10 | * YiiDebugToolbarPanelRequest class 11 | * 12 | * Description of YiiDebugToolbarPanelRequest 13 | * 14 | * @author Sergey Malyshev 15 | * @author Igor Golovanov 16 | * @version $Id$ 17 | * @package YiiDebugToolbar 18 | * @since 1.1.7 19 | */ 20 | class YiiDebugToolbarPanelRequest extends YiiDebugToolbarPanel 21 | { 22 | public $i = 'o'; 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function getMenuTitle() 28 | { 29 | return YiiDebug::t('Request'); 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function getTitle() 36 | { 37 | return YiiDebug::t('Request'); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function init() 44 | {} 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function run() 50 | { 51 | $this->render('request', array( 52 | 'server' => $_SERVER, 53 | 'cookies' => $_COOKIE, 54 | 'session' => isset($_SESSION) ? $_SESSION : array(), 55 | 'post' => $_POST, 56 | 'get' => $_GET, 57 | 'files' => $_FILES, 58 | )); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /panels/YiiDebugToolbarPanelSettings.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | 9 | /** 10 | * YiiDebugToolbarPanelSettings class 11 | * 12 | * Description of YiiDebugToolbarPanelSettings 13 | * 14 | * @author Sergey Malyshev 15 | * @author Igor Golovanov 16 | * @version $Id$ 17 | * @package YiiDebugToolbar 18 | * @since 1.1.7 19 | */ 20 | class YiiDebugToolbarPanelSettings extends YiiDebugToolbarPanel 21 | { 22 | public $i = 'k'; 23 | 24 | public function getMenuTitle() 25 | { 26 | return YiiDebug::t('Settings'); 27 | } 28 | 29 | public function getMenuSubTitle() 30 | { 31 | return 'YII_DEBUG ' . (YII_DEBUG ? YiiDebug::t('ON') : YiiDebug::t('OFF')); 32 | } 33 | 34 | public function getTitle() 35 | { 36 | return YiiDebug::t('Application Settings'); 37 | } 38 | 39 | public function getSubTitle() 40 | { 41 | return ''; 42 | } 43 | 44 | public function init() 45 | { 46 | 47 | } 48 | 49 | protected function getApplicationData() 50 | { 51 | return $this->prepareData(get_object_vars(Yii::app())); 52 | } 53 | 54 | protected function getModulesData() 55 | { 56 | return $this->prepareData(Yii::app()->modules); 57 | } 58 | 59 | protected function getApplicationParams() 60 | { 61 | return $this->prepareData(Yii::app()->params); 62 | } 63 | 64 | protected function getComponentsData() 65 | { 66 | return $this->prepareData(Yii::app()->components); 67 | } 68 | 69 | public function run() 70 | { 71 | 72 | $this->render('settings', array( 73 | 'application' => $this->getApplicationData(), 74 | 'params' => $this->getApplicationParams(), 75 | 'modules' => $this->getModulesData(), 76 | 'components' => $this->getComponentsData(), 77 | 78 | )); 79 | } 80 | 81 | private function prepareData($data) 82 | { 83 | $result = array(); 84 | $skip = array(); 85 | foreach ($data as $key => $value){ 86 | if (in_array($key, $skip)) 87 | continue; 88 | 89 | if (is_object($value)){ 90 | $value = array_merge(array( 91 | 'class' => get_class($value) 92 | ), get_object_vars($value)); 93 | 94 | } 95 | $result[$key] = $value; 96 | } 97 | return $result; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /panels/YiiDebugToolbarPanelSql.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | 9 | /** 10 | * YiiDebugToolbarPanelSql class. 11 | * 12 | * Description of YiiDebugToolbarPanelSql 13 | * 14 | * @author Sergey Malyshev 15 | * @author Igor Golovanov 16 | * @package YiiDebugToolbar 17 | * @since 1.1.7 18 | */ 19 | class YiiDebugToolbarPanelSql extends YiiDebugToolbarPanel 20 | { 21 | public $i = 'i'; 22 | 23 | /** 24 | * If true, the sql query in the list will use syntax highlighting. 25 | * 26 | * @var boolean 27 | */ 28 | public $highlightSql = true; 29 | 30 | private $_countLimit = 1; 31 | 32 | private $_timeLimit = 0.01; 33 | 34 | private $_groupByToken = true; 35 | 36 | private $_dbConnections; 37 | 38 | private $_dbConnectionsCount; 39 | 40 | private $_textHighlighter; 41 | 42 | public function __construct($owner = null) 43 | { 44 | parent::__construct($owner); 45 | 46 | try { 47 | Yii::app()->db; 48 | } catch (Exception $e) { 49 | $this->_dbConnections = false; 50 | } 51 | } 52 | 53 | public function getCountLimit() 54 | { 55 | return $this->_countLimit; 56 | } 57 | 58 | public function setCountLimit($value) 59 | { 60 | $this->_countLimit = CPropertyValue::ensureInteger($value); 61 | } 62 | 63 | public function getTimeLimit() 64 | { 65 | return $this->_timeLimit; 66 | } 67 | 68 | public function setTimeLimit($value) 69 | { 70 | $this->_timeLimit = CPropertyValue::ensureFloat($value); 71 | } 72 | 73 | public function getDbConnectionsCount() 74 | { 75 | if (null === $this->_dbConnectionsCount) 76 | { 77 | $this->_dbConnectionsCount = count($this->getDbConnections()); 78 | } 79 | return $this->_dbConnectionsCount; 80 | } 81 | 82 | public function getDbConnections() 83 | { 84 | if (null === $this->_dbConnections) 85 | { 86 | $this->_dbConnections = array(); 87 | foreach (Yii::app()->components as $id=>$component) 88 | { 89 | if (false !== is_object($component) 90 | && false !== ($component instanceof CDbConnection)) 91 | { 92 | $this->_dbConnections[$id] = $component; 93 | } 94 | } 95 | } 96 | return $this->_dbConnections; 97 | } 98 | 99 | /** 100 | * {@inheritdoc} 101 | */ 102 | public function getMenuTitle() 103 | { 104 | return YiiDebug::t('SQL'); 105 | } 106 | 107 | /** 108 | * {@inheritdoc} 109 | */ 110 | public function getMenuSubTitle($f=4) 111 | { 112 | if (false !== $this->_dbConnections) { 113 | list ($count, $time) = Yii::app()->db->getStats(); 114 | return $count . ($count > 0 ? ('/'. vsprintf('%0.'.$f.'F', $time) . 's') : ''); 115 | } 116 | return YiiDebug::t('No active connections'); 117 | } 118 | 119 | /** 120 | * {@inheritdoc} 121 | */ 122 | public function getTitle() 123 | { 124 | if (false !== $this->_dbConnections) 125 | { 126 | $conn=$this->getDbConnectionsCount(); 127 | return YiiDebug::t('SQL Queries from {n} connection|SQL Queries from {n} connections', array($conn)); 128 | } 129 | return YiiDebug::t('No active connections'); 130 | } 131 | 132 | /** 133 | * {@inheritdoc} 134 | */ 135 | public function getSubTitle() 136 | { 137 | return false !== $this->_dbConnections 138 | ? ('(' . self::getMenuSubTitle(6) . ')') 139 | : null; 140 | } 141 | 142 | /** 143 | * Initialize panel 144 | */ 145 | public function init() 146 | { 147 | 148 | } 149 | 150 | /** 151 | * {@inheritdoc} 152 | */ 153 | public function run() 154 | { 155 | if (false === $this->_dbConnections) { 156 | return; 157 | } 158 | 159 | $logs = $this->filterLogs(); 160 | $this->render('sql', array( 161 | 'connections' => $this->getDbConnections(), 162 | 'connectionsCount' => $this->getDbConnectionsCount(), 163 | 'summary' => $this->processSummary($logs), 164 | 'callstack' => $this->processCallstack($logs) 165 | )); 166 | } 167 | 168 | private function duration($secs) 169 | { 170 | $vals = array( 171 | 'w' => (int) ($secs / 86400 / 7), 172 | 'd' => $secs / 86400 % 7, 173 | 'h' => $secs / 3600 % 24, 174 | 'm' => $secs / 60 % 60, 175 | 's' => $secs % 60 176 | ); 177 | $result = array(); 178 | $added = false; 179 | foreach ($vals as $k => $v) 180 | { 181 | if ($v > 0 || false !== $added) 182 | { 183 | $added = true; 184 | $result[] = $v . $k; 185 | } 186 | } 187 | return implode(' ', $result); 188 | } 189 | 190 | /** 191 | * Returns the DB server info by connection ID. 192 | * @param string $connectionId 193 | * @return mixed 194 | */ 195 | public function getServerInfo($connectionId) 196 | { 197 | if (null !== ($connection = Yii::app()->getComponent($connectionId)) 198 | && false !== ($connection instanceof CDbConnection) 199 | && !in_array($connection->driverName, array('sqlite', 'oci', 'dblib')) 200 | && '' !== ($serverInfo = $connection->getServerInfo())) 201 | { 202 | $info = array( 203 | YiiDebug::t('Driver') => $connection->getDriverName(), 204 | YiiDebug::t('Server Version') => $connection->getServerVersion() 205 | ); 206 | 207 | $lines = explode(' ', $serverInfo); 208 | foreach($lines as $line) { 209 | list($key, $value) = explode(': ', $line, 2); 210 | $info[YiiDebug::t($key)] = $value; 211 | } 212 | 213 | if(!empty($info[YiiDebug::t('Uptime')])) { 214 | $info[YiiDebug::t('Uptime')] = $this->duration($info[YiiDebug::t('Uptime')]); 215 | } 216 | 217 | return $info; 218 | } 219 | return null; 220 | } 221 | 222 | /** 223 | * Processing callstack. 224 | * 225 | * @param array $logs Logs. 226 | * @return array 227 | */ 228 | protected function processCallstack(array $logs) 229 | { 230 | if (empty($logs)) 231 | { 232 | return $logs; 233 | } 234 | 235 | $stack = array(); 236 | $results = array(); 237 | $n = 0; 238 | 239 | foreach ($logs as $log) 240 | { 241 | if(CLogger::LEVEL_PROFILE !== $log[1]) 242 | continue; 243 | 244 | $message = $log[0]; 245 | 246 | if (0 === strncasecmp($message,'begin:',6)) 247 | { 248 | $log[0] = substr($message,6); 249 | $log[4] = $n; 250 | $stack[] = $log; 251 | $n++; 252 | } 253 | else if (0 === strncasecmp($message, 'end:', 4)) 254 | { 255 | $token = substr($message,4); 256 | if(null !== ($last = array_pop($stack)) && $last[0] === $token) 257 | { 258 | $delta = $log[3] - $last[3]; 259 | $results[$last[4]] = array($token, $delta, count($stack)); 260 | } 261 | else 262 | throw new CException(Yii::t('yii-debug-toolbar', 263 | 'Mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.', 264 | array('{token}' => $token) 265 | )); 266 | } 267 | } 268 | // remaining entries should be closed here 269 | $now = microtime(true); 270 | while (null !== ($last = array_pop($stack))){ 271 | $results[$last[4]] = array($last[0], $now - $last[3], count($stack)); 272 | } 273 | 274 | ksort($results); 275 | return array_map(array($this, 'formatLogEntry'), $results); 276 | } 277 | 278 | /** 279 | * Processing summary. 280 | * 281 | * @param array $logs Logs. 282 | * @return array 283 | */ 284 | protected function processSummary(array $logs) 285 | { 286 | if (empty($logs)) 287 | { 288 | return $logs; 289 | } 290 | $stack = array(); 291 | foreach($logs as $log) 292 | { 293 | $message = $log[0]; 294 | if(0 === strncasecmp($message, 'begin:', 6)) 295 | { 296 | $log[0] =substr($message, 6); 297 | $stack[] =$log; 298 | } 299 | else if(0 === strncasecmp($message,'end:',4)) 300 | { 301 | $token = substr($message,4); 302 | if(null !== ($last = array_pop($stack)) && $last[0] === $token) 303 | { 304 | $delta = $log[3] - $last[3]; 305 | 306 | if(isset($results[$token])) 307 | $results[$token] = $this->aggregateResult($results[$token], $delta); 308 | else{ 309 | $results[$token] = array($token, 1, $delta, $delta, $delta); 310 | } 311 | } 312 | else 313 | throw new CException(Yii::t('yii-debug-toolbar', 314 | 'Mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.', 315 | array('{token}' => $token))); 316 | } 317 | } 318 | 319 | $now = microtime(true); 320 | while(null !== ($last = array_pop($stack))) 321 | { 322 | $delta = $now - $last[3]; 323 | $token = $last[0]; 324 | 325 | if(isset($results[$token])) 326 | $results[$token] = $this->aggregateResult($results[$token], $delta); 327 | else{ 328 | $results[$token] = array($token, 1, $delta, $delta, $delta); 329 | } 330 | } 331 | 332 | $entries = array_values($results); 333 | $func = create_function('$a,$b','return $a[4]<$b[4]?1:0;'); 334 | 335 | usort($entries, $func); 336 | 337 | return array_map(array($this, 'formatLogEntry'), $entries); 338 | } 339 | 340 | /** 341 | * Format log entry 342 | * 343 | * @param array $entry 344 | * @return array 345 | */ 346 | public function formatLogEntry(array $entry) 347 | { 348 | // extract query from the entry 349 | $queryString = $entry[0]; 350 | $sqlStart = strpos($queryString, '(') + 1; 351 | $sqlEnd = strrpos($queryString , ')'); 352 | $sqlLength = $sqlEnd - $sqlStart; 353 | 354 | $queryString = substr($queryString, $sqlStart, $sqlLength); 355 | 356 | if (false !== strpos($queryString, '. Bound with ')) 357 | { 358 | list($query, $params) = explode('. Bound with ', $queryString); 359 | 360 | $binds = array(); 361 | $matchResult = preg_match_all("/(?[a-z0-9\.\_\-\:]+)=(?[\d\.e\-\+]+|''|'.+?(?highlightSql)) 378 | { 379 | $entry[0] = $this->getTextHighlighter()->highlight($entry[0]); 380 | } 381 | 382 | $entry[0] = strip_tags($entry[0], '
,'); 383 | return $entry; 384 | } 385 | 386 | 387 | /** 388 | * @return CTextHighlighter the text highlighter 389 | */ 390 | private function getTextHighlighter() 391 | { 392 | if (null === $this->_textHighlighter) 393 | { 394 | $this->_textHighlighter = Yii::createComponent(array( 395 | 'class' => 'CTextHighlighter', 396 | 'language' => 'sql', 397 | 'showLineNumbers' => false, 398 | )); 399 | } 400 | return $this->_textHighlighter; 401 | } 402 | 403 | 404 | /** 405 | * Aggregates the report result. 406 | * 407 | * @param array $result log result for this code block 408 | * @param float $delta time spent for this code block 409 | * @return array 410 | */ 411 | protected function aggregateResult($result, $delta) 412 | { 413 | list($token, $calls, $min, $max, $total) = $result; 414 | 415 | switch (true) 416 | { 417 | case ($delta < $min): 418 | $min = $delta; 419 | break; 420 | case ($delta > $max): 421 | $max = $delta; 422 | break; 423 | default: 424 | // nothing 425 | break; 426 | } 427 | 428 | $calls++; 429 | $total += $delta; 430 | 431 | return array($token, $calls, $min, $max, $total); 432 | } 433 | 434 | /** 435 | * Get filter logs. 436 | * 437 | * @return array 438 | */ 439 | protected function filterLogs() 440 | { 441 | $logs = array(); 442 | foreach ($this->owner->getLogs() as $entry) 443 | { 444 | if (CLogger::LEVEL_PROFILE === $entry[1] && 0 === strpos($entry[2], 'system.db.CDbCommand')) 445 | { 446 | $logs[] = $entry; 447 | } 448 | } 449 | return $logs; 450 | } 451 | 452 | } 453 | -------------------------------------------------------------------------------- /panels/YiiDebugToolbarPanelViews.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | Yii::import('yii-debug-toolbar.YiiDebugViewRenderer'); 9 | 10 | /** 11 | * YiiDebugToolbarPanelViews represents an ... 12 | * 13 | * Description of YiiDebugToolbarPanelViews 14 | * 15 | * @author Sergey Malyshev 16 | * @version $Id$ 17 | * @package 18 | * @since 1.1.7 19 | */ 20 | class YiiDebugToolbarPanelViews extends YiiDebugToolbarPanel 21 | { 22 | public $i = 'l'; 23 | 24 | private $_viewsCount = 0; 25 | 26 | private $_viewRenderer; 27 | 28 | public function getViewsCount() 29 | { 30 | return count($this->_viewRenderer->debugStackTrace); 31 | } 32 | 33 | public function init() 34 | { 35 | parent::init(); 36 | $this->_viewRenderer = Yii::app()->getComponent('viewRenderer'); 37 | } 38 | 39 | public function run() 40 | { 41 | $data = array(); 42 | $viewRenderer = $this->_viewRenderer; 43 | 44 | if ($viewRenderer instanceof YiiDebugViewRenderer) { 45 | $data = $this->_viewRenderer->debugStackTrace; 46 | } 47 | 48 | $this->render('views', array('data'=>$data)); 49 | } 50 | 51 | public function getInheritance(ReflectionClass $class) 52 | { 53 | $data = array(); 54 | 55 | while($class = $class->getParentClass()) 56 | { 57 | $data[] = $class->name; 58 | if('CBaseController' === $class->name) 59 | break; 60 | } 61 | 62 | return implode(' » ', $data); 63 | } 64 | 65 | public function getFilePath($file) 66 | { 67 | return trim(str_replace(Yii::getPathOfAlias('webroot'), '', $file), '\\/'); 68 | } 69 | 70 | public function getFileAlias($file) 71 | { 72 | return str_replace(DIRECTORY_SEPARATOR, '.', 73 | dirname(trim(str_replace(Yii::getPathOfAlias('webroot'), '', $file), '\\/')) . '/' 74 | . basename(trim(str_replace(Yii::getPathOfAlias('webroot'), '', $file), '\\/'), '.php')); 75 | } 76 | 77 | 78 | public function getWidgetsData() 79 | { 80 | 81 | } 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | public function getMenuTitle() 87 | { 88 | return YiiDebug::t('Views Rendering'); 89 | } 90 | 91 | /** 92 | * {@inheritdoc} 93 | */ 94 | public function getMenuSubTitle() 95 | { 96 | return $this->viewsCount; 97 | } 98 | 99 | /** 100 | * {@inheritdoc} 101 | */ 102 | public function getTitle() 103 | { 104 | return YiiDebug::t('Views Rendering'); 105 | } 106 | 107 | /** 108 | * {@inheritdoc} 109 | */ 110 | public function getSubTitle() 111 | { 112 | return false; 113 | } 114 | } -------------------------------------------------------------------------------- /views/index.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | debug index -------------------------------------------------------------------------------- /views/layouts/main.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /views/main.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

Yii

5 | widget('YiiDebugToolbarResourceUsage'); ?> 6 | 16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | title); ?> 27 | subTitle) : ?> 28 | subTitle); ?> 29 | 30 |
    31 |
  • 32 |
  • 33 |
34 |
35 |
36 | run(); ?> 37 |
38 |
39 | 40 |
41 | -------------------------------------------------------------------------------- /views/panels/asset.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
getBasePath()?>
excludeFiles)?>
newDirMode?>
newFileMode?>
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | sourceLanguage); 38 | $i=0; 39 | foreach($assets as $asset){ 40 | $i++; 41 | 42 | $path = $AM->getBasePath().'/'.$asset; 43 | $files = CFileHelper::findFiles($path); 44 | $fileList = implode('
', $files); 45 | 46 | $blockAll = false; 47 | if(preg_match('|yii\.debug\.toolbar\.js|is', $fileList)) $blockAll = true; 48 | 49 | ?> 50 | 51 | 52 | 59 | 60 | 61 | 66 | 67 | 68 | 69 |
53 | 55 | 58 | formatDateTime(filemtime($path))?> 62 | 64 | 65 |
70 | 71 | -------------------------------------------------------------------------------- /views/panels/logging.php: -------------------------------------------------------------------------------- 1 | '#DFFFE0', 4 | CLogger::LEVEL_INFO=>'#FFFFDF', 5 | CLogger::LEVEL_WARNING=>'#FFDFE5', 6 | CLogger::LEVEL_ERROR=>'#FFC0CB', 7 | ); 8 | ?> 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | $entry): ?> 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 | 35 | -------------------------------------------------------------------------------- /views/panels/request.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 14 | 15 | $value) : ?> 16 | 17 | 18 | 19 | 20 | 21 | 22 |
dump($value); ?>
23 |
24 |
25 | 26 |
27 |
28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 | 36 | 37 | $value) : ?> 38 | 39 | 40 | 41 | 42 | 43 | 44 |
dump($value); ?>
45 |
46 |
47 | 48 |
49 |
50 | 51 | 52 | 53 | 54 |
55 |
56 |
57 | 58 | 59 | $value) : ?> 60 | 61 | 62 | 63 | 64 | 65 | 66 |
dump($value); ?>
67 |
68 |
69 | 70 | 71 |
72 |
73 | 74 | 75 | 76 | 77 |
78 |
79 |
80 | 81 | 82 | $value) : ?> 83 | 84 | 85 | 86 | 87 | 88 | 89 |
dump($value); ?>
90 |
91 |
92 | 93 | 94 |
95 |
96 | 97 | 98 | 99 | 100 |
101 |
102 |
103 | 104 | 105 | $value) : ?> 106 | 107 | 108 | 109 | 110 | 111 | 112 |
dump($value); ?>
113 |
114 |
115 | 116 | 117 |
118 |
119 | 120 | 121 | 122 | 123 |
124 |
125 |
126 | 127 | 128 | $value) : ?> 129 | 130 | 131 | 132 | 133 | 134 | 135 |
dump($value); ?>
136 |
137 |
138 | 139 |
140 |
141 |
142 | 143 | -------------------------------------------------------------------------------- /views/panels/settings.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 14 | 15 | $value) : ?> 16 | 17 | 18 | 19 | 20 | 21 | 22 |
dump($value); ?>
23 |
24 |
25 |
26 |
27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 | 35 | 36 | $value) : ?> 37 | 38 | 39 | 40 | 41 | 42 | 43 |
dump($value); ?>
44 |
45 |
46 |
47 |
48 | 49 | 50 | 51 | 52 |
53 |
54 |
55 | 56 | 57 | $value) : ?> 58 | 59 | 60 | 61 | 62 | 63 | 64 |
dump($value); ?>
65 |
66 |
67 |
68 |
69 | 70 | 71 | 72 | 73 |
74 |
75 |
76 | 77 | 78 | $value) : ?> 79 | 80 | 81 | 82 | 83 | 84 | 85 |
dump($value); ?>
86 |
87 |
88 |
89 |
90 |
91 | -------------------------------------------------------------------------------- /views/panels/sql.php: -------------------------------------------------------------------------------- 1 |
2 |
    3 |
  • 4 |
  • 5 |
  • 6 |
7 |
8 |
9 |
10 | render('sql/servers', array( 11 | 'connections'=>$connections 12 | )) ?> 13 |
14 |
15 | render('sql/summary', array( 16 | 'summary'=>$summary 17 | )) ?> 18 |
19 |
20 | render('sql/callstack', array( 21 | 'callstack'=>$callstack 22 | )) ?> 23 |
24 |
25 |
26 |
27 | -------------------------------------------------------------------------------- /views/panels/sql/callstack.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | $entry):?> 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
#
20 | 21 |

22 | 23 |

24 | -------------------------------------------------------------------------------- /views/panels/sql/servers.php: -------------------------------------------------------------------------------- 1 | $connection): ?> 2 |

: ()

3 | getServerInfo($id);?> 4 | 5 | 6 | 7 | $value): ?> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
Used DB driver doesn't provide info.
20 | 21 | 22 | No SQL Servers used during this request. 23 | 24 | -------------------------------------------------------------------------------- /views/panels/sql/summary.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | $entry):?> 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 |

28 | 29 |

30 | -------------------------------------------------------------------------------- /views/panels/views.php: -------------------------------------------------------------------------------- 1 | 8 | * @version $Id$ 9 | * @package 10 | * @since 1.1.7 11 | */ 12 | 13 | 14 | $index = 1; 15 | ?> 16 | 17 |
18 |
19 |
20 | $item) : ?> 21 |
22 |
23 | 24 | 25 | getFileAlias($item['sourceFile']) ?> 26 | 27 | 28 |
29 |
30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 117 | 118 | 119 | 120 |
Context class
InheritancegetInheritance($item['reflection'])?>
Defined in filegetFilePath($item['reflection']->getFileName()) ?>
Context properties 49 |
    50 | $value) : ?> 51 |
  • 52 | 53 |  =>  54 | 55 |
  • 56 | 57 |
58 | 59 | 60 | 61 |
Route
ActiongetId() , ')' ?>
Action params 77 |
    78 | $value) : ?> 79 |
  • 80 | 81 |  =>  82 | 83 |
  • 84 | 85 |
86 | 87 | 88 | 89 |
Render method
View filegetFilePath($item['sourceFile']) ?>
View data 104 |
    105 | $value) : ?> 106 |
  • 107 | 108 |  =>  109 | 110 |
  • 111 | 112 |
113 | 114 | 115 | 116 |
121 |
122 |
123 | 124 |
125 |
126 |
127 | 128 | 129 | -------------------------------------------------------------------------------- /widgets/YiiDebugToolbarResourceUsage.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | /** 10 | * YiiDebugToolbarResourceUsage represents an ... 11 | * 12 | * Description of YiiDebugToolbarResourceUsage 13 | * 14 | * @author Sergey Malyshev 15 | * @package 16 | * @since 1.1.7 17 | */ 18 | class YiiDebugToolbarResourceUsage extends CWidget 19 | { 20 | 21 | public $htmlOptions = array(); 22 | private $_loadTime; 23 | 24 | public function getLoadTime() 25 | { 26 | if (null === $this->_loadTime) { 27 | $this->_loadTime = $this->owner->owner->getLoadTime(); 28 | } 29 | return $this->_loadTime; 30 | } 31 | 32 | public function getRequestLoadTime() 33 | { 34 | return ($this->owner->owner->getEndTime() - $_SERVER['REQUEST_TIME']); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function run() 41 | { 42 | 43 | $data = array(); 44 | 45 | $data[] = array( 46 | 'i' => 'b', 47 | 'value' => sprintf('%0.4F', $this->getLoadTime()), 48 | 'unit' => 'seconds' 49 | ); 50 | 51 | $data[] = array( 52 | 'i' => 'a', 53 | 'value' => sprintf('%0.4F', $this->getRequestLoadTime()), 54 | 'unit' => 'seconds' 55 | ); 56 | 57 | $memoryUsage = number_format(Yii::getLogger()->getMemoryUsage() / 1024 / 1024, 2); 58 | 59 | if (function_exists('memory_get_peak_usage')) { 60 | $memoryUsage .= '/' . number_format(memory_get_peak_usage() / 1024 / 1024, 2); 61 | } 62 | 63 | $data[] = array( 64 | 'i' => 'p', 65 | 'value' => $memoryUsage, 66 | 'unit' => 'megabytes' 67 | ); 68 | 69 | 70 | $this->render('resources', array( 71 | 'data' => $data 72 | )); 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /widgets/views/resources.php: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
  • 4 | 5 | 6 | 7 |
  • 8 | 9 |
--------------------------------------------------------------------------------