debugBar = $debugBar; $this->baseUrl = $baseUrl; if ($basePath === null) { $basePath = __DIR__ . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, array('..', '..', '..', 'web')); } $this->basePath = $basePath; // bitwise operations cannot be done in class definition :( $this->initialization = self::INITIALIZE_CONSTRUCTOR | self::INITIALIZE_CONTROLS; } /** * Sets the path which assets are relative to * * @param string $path */ public function setBasePath($path) { $this->basePath = $path; return $this; } /** * Returns the path which assets are relative to * * @return string */ public function getBasePath() { return $this->basePath; } /** * Sets the base URL from which assets will be served * * @param string $url */ public function setBaseUrl($url) { $this->baseUrl = $url; return $this; } /** * Returns the base URL from which assets will be served * * @return string */ public function getBaseUrl() { return $this->baseUrl; } /** * Whether to include vendor assets * * @param boolean $enabled */ public function setIncludeVendors($enabled = true) { $this->includeVendors = $enabled; return $this; } /** * Checks if vendors assets are included * * @return boolean */ public function areVendorsIncluded() { return $this->includeVendors; } /** * Sets the javascript class name * * @param string $className */ public function setJavascriptClass($className) { $this->javascriptClass = $className; return $this; } /** * Returns the javascript class name * * @return string */ public function getJavascriptClass() { return $this->javascriptClass; } /** * Sets the variable name of the class instance * * @param string $name */ public function setVariableName($name) { $this->variableName = $name; return $this; } /** * Returns the variable name of the class instance * * @return string */ public function getVariableName() { return $this->variableName; } /** * Sets what should be initialized * * - INITIALIZE_CONSTRUCTOR: only initializes the instance * - INITIALIZE_CONTROLS: initializes the controls and data mapping * - INITIALIZE_CONSTRUCTOR | INITIALIZE_CONTROLS: initialize everything (default) * * @param integer $init */ public function setInitialization($init) { $this->initialization = $init; return $this; } /** * Returns what should be initialized * * @return integer */ public function getInitialization() { return $this->initialization; } /** * Adds a control to initialize * * Possible options: * - icon: icon name * - tooltip: string * - widget: widget class name * - map: a property name from the data to map the control to * - default: a js string, default value of the data map * * "icon" or "widget" are at least needed * * @param string $name * @param array $options */ public function addControl($name, $options) { if (!isset($options['icon']) || !isset($options['widget'])) { throw new DebugBarException("Missing 'icon' or 'widget' option for control '$name'"); } $this->controls[$name] = $options; return $this; } /** * Returns the list of asset files * * @return array */ protected function getAssetFiles() { $cssFiles = $this->cssFiles; $jsFiles = $this->jsFiles; if ($this->includeVendors) { $cssFiles = array_merge($this->cssVendors, $cssFiles); $jsFiles = array_merge($this->jsVendors, $jsFiles); } return array($cssFiles, $jsFiles); } /** * Returns a tuple where the both items are Assetic AssetCollection, * the first one being css files and the second js files * * @return array or \Assetic\Asset\AssetCollection */ public function getAsseticCollection() { list($cssFiles, $jsFiles) = $this->getAssetFiles(); return array( $this->createAsseticCollection($cssFiles), $this->createAsseticCollection($jsFiles) ); } /** * Create an Assetic AssetCollection with the given files. * Filenames will be converted to absolute path using * the base path. * * @param array $files * @return \Assetic\Asset\AssetCollection */ protected function createAsseticCollection($files) { $assets = array(); foreach ($files as $file) { $assets[] = new \Assetic\Asset\FileAsset($this->makeUriRelativeTo($file, $this->basePath)); } return new \Assetic\Asset\AssetCollection($assets); } /** * Renders the html to include needed assets * * Only useful if Assetic is not used * * @return string */ public function renderHead() { list($cssFiles, $jsFiles) = $this->getAssetFiles(); $html = ''; foreach ($cssFiles as $file) { $html .= sprintf('' . "\n", $this->makeUriRelativeTo($file, $this->baseUrl)); } foreach ($jsFiles as $file) { $html .= sprintf('' . "\n", $this->makeUriRelativeTo($file, $this->baseUrl)); } return $html; } /** * Makes a URI relative to another * * @param string $uri * @param string $root * @return string */ protected function makeUriRelativeTo($uri, $root) { if (substr($uri, 0, 1) === '/' || preg_match('/^([a-z]+:\/\/|[a-zA-Z]:\/)/', $uri)) { return $uri; } return rtrim($root, '/') . "/$uri"; } /** * Returns the code needed to display the debug bar * * AJAX request should not render the initialization code. * * @param boolean $initialize Whether to render the de bug bar initialization code * @return string */ public function render($initialize = true) { $js = ''; if ($initialize) { $js = $this->getJsInitializationCode(); } $js .= sprintf("%s.addDataSet(%s);\n", $this->variableName, json_encode($this->debugBar->getData())); return "\n"; } /** * Returns the js code needed to initialize the debug bar * * @return string */ protected function getJsInitializationCode() { $js = ''; if (($this->initialization & self::INITIALIZE_CONSTRUCTOR) === self::INITIALIZE_CONSTRUCTOR) { $js = sprintf("var %s = new %s();\n", $this->variableName, $this->javascriptClass); } if (($this->initialization & self::INITIALIZE_CONTROLS) === self::INITIALIZE_CONTROLS) { $js .= $this->getJsControlsDefinitionCode($this->variableName); } return $js; } /** * Returns the js code needed to initialized the controls and data mapping of the debug bar * * Controls can be defined by collectors themselves or using {@see addControl()} * * @param string $varname Debug bar's variable name * @return string */ protected function getJsControlsDefinitionCode($varname) { $js = ''; $dataMap = array(); $controls = $this->controls; // finds controls provided by collectors foreach ($this->debugBar->getCollectors() as $collector) { if ($collector instanceof Renderable) { $controls = array_merge($controls, $collector->getWidgets()); } } foreach ($controls as $name => $options) { if (isset($options['widget'])) { $js .= sprintf("%s.createTab(\"%s\", new %s());\n", $varname, $name, $options['widget'] ); } else { $js .= sprintf("%s.createIndicator(\"%s\", \"%s\", \"%s\");\n", $varname, $name, isset($options['icon']) ? $options['icon'] : 'null', isset($options['tooltip']) ? $options['tooltip'] : 'null' ); } if (isset($options['map']) && isset($options['default'])) { $dataMap[$name] = array($options['map'], $options['default']); } } // creates the data mapping object $mapJson = array(); foreach ($dataMap as $name => $values) { $mapJson[] = sprintf('"%s": ["%s", %s]', $name, $values[0], $values[1]); } $js .= sprintf("%s.setDataMap({\n%s\n});\n", $varname, implode(",\n", $mapJson)); // activate state restauration $js .= sprintf("%s.restoreState();\n", $varname); return $js; } }