1268 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1268 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /*
 | |
|  * This file is part of the DebugBar package.
 | |
|  *
 | |
|  * (c) 2013 Maxime Bouroumeau-Fuseau
 | |
|  *
 | |
|  * For the full copyright and license information, please view the LICENSE
 | |
|  * file that was distributed with this source code.
 | |
|  */
 | |
| 
 | |
| namespace DebugBar;
 | |
| 
 | |
| use DebugBar\DataCollector\AssetProvider;
 | |
| use DebugBar\DataCollector\Renderable;
 | |
| 
 | |
| /**
 | |
|  * Renders the debug bar using the client side javascript implementation
 | |
|  *
 | |
|  * Generates all the needed initialization code of controls
 | |
|  */
 | |
| class JavascriptRenderer
 | |
| {
 | |
|     const INITIALIZE_CONSTRUCTOR = 2;
 | |
| 
 | |
|     const INITIALIZE_CONTROLS = 4;
 | |
| 
 | |
|     const REPLACEABLE_TAG = "{--DEBUGBAR_OB_START_REPLACE_ME--}";
 | |
| 
 | |
|     const RELATIVE_PATH = 'path';
 | |
| 
 | |
|     const RELATIVE_URL = 'url';
 | |
| 
 | |
|     protected $debugBar;
 | |
| 
 | |
|     protected $baseUrl;
 | |
| 
 | |
|     protected $basePath;
 | |
| 
 | |
|     protected $cssVendors = array(
 | |
|         'fontawesome' => 'vendor/font-awesome/css/font-awesome.min.css',
 | |
|         'highlightjs' => 'vendor/highlightjs/styles/github.css'
 | |
|     );
 | |
| 
 | |
|     protected $jsVendors = array(
 | |
|         'jquery' => 'vendor/jquery/dist/jquery.min.js',
 | |
|         'highlightjs' => 'vendor/highlightjs/highlight.pack.js'
 | |
|     );
 | |
| 
 | |
|     protected $includeVendors = true;
 | |
| 
 | |
|     protected $cssFiles = array('debugbar.css', 'widgets.css', 'openhandler.css');
 | |
| 
 | |
|     protected $jsFiles = array('debugbar.js', 'widgets.js', 'openhandler.js');
 | |
| 
 | |
|     protected $additionalAssets = array();
 | |
| 
 | |
|     protected $javascriptClass = 'PhpDebugBar.DebugBar';
 | |
| 
 | |
|     protected $variableName = 'phpdebugbar';
 | |
| 
 | |
|     protected $enableJqueryNoConflict = true;
 | |
| 
 | |
|     protected $useRequireJs = false;
 | |
| 
 | |
|     protected $hideEmptyTabs = null;
 | |
| 
 | |
|     protected $initialization;
 | |
| 
 | |
|     protected $controls = array();
 | |
| 
 | |
|     protected $ignoredCollectors = array();
 | |
| 
 | |
|     protected $ajaxHandlerClass = 'PhpDebugBar.AjaxHandler';
 | |
| 
 | |
|     protected $ajaxHandlerBindToFetch = false;
 | |
| 
 | |
|     protected $ajaxHandlerBindToJquery = false;
 | |
| 
 | |
|     protected $ajaxHandlerBindToXHR = true;
 | |
| 
 | |
|     protected $ajaxHandlerAutoShow = true;
 | |
| 
 | |
|     protected $ajaxHandlerEnableTab = false;
 | |
| 
 | |
|     protected $openHandlerClass = 'PhpDebugBar.OpenHandler';
 | |
| 
 | |
|     protected $openHandlerUrl;
 | |
| 
 | |
|     protected $cspNonce;
 | |
| 
 | |
|     /**
 | |
|      * @param \DebugBar\DebugBar $debugBar
 | |
|      * @param string $baseUrl
 | |
|      * @param string $basePath
 | |
|      */
 | |
|     public function __construct(DebugBar $debugBar, $baseUrl = null, $basePath = null)
 | |
|     {
 | |
|         $this->debugBar = $debugBar;
 | |
| 
 | |
|         if ($baseUrl === null) {
 | |
|             $baseUrl = '/vendor/maximebf/debugbar/src/DebugBar/Resources';
 | |
|         }
 | |
|         $this->baseUrl = $baseUrl;
 | |
| 
 | |
|         if ($basePath === null) {
 | |
|             $basePath = __DIR__ . DIRECTORY_SEPARATOR . 'Resources';
 | |
|         }
 | |
|         $this->basePath = $basePath;
 | |
| 
 | |
|         // bitwise operations cannot be done in class definition :(
 | |
|         $this->initialization = self::INITIALIZE_CONSTRUCTOR | self::INITIALIZE_CONTROLS;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets options from an array
 | |
|      *
 | |
|      * Options:
 | |
|      *  - base_path
 | |
|      *  - base_url
 | |
|      *  - include_vendors
 | |
|      *  - javascript_class
 | |
|      *  - variable_name
 | |
|      *  - initialization
 | |
|      *  - enable_jquery_noconflict
 | |
|      *  - controls
 | |
|      *  - disable_controls
 | |
|      *  - ignore_collectors
 | |
|      *  - ajax_handler_classname
 | |
|      *  - ajax_handler_bind_to_jquery
 | |
|      *  - ajax_handler_auto_show
 | |
|      *  - open_handler_classname
 | |
|      *  - open_handler_url
 | |
|      *
 | |
|      * @param array $options [description]
 | |
|      */
 | |
|     public function setOptions(array $options)
 | |
|     {
 | |
|         if (array_key_exists('base_path', $options)) {
 | |
|             $this->setBasePath($options['base_path']);
 | |
|         }
 | |
|         if (array_key_exists('base_url', $options)) {
 | |
|             $this->setBaseUrl($options['base_url']);
 | |
|         }
 | |
|         if (array_key_exists('include_vendors', $options)) {
 | |
|             $this->setIncludeVendors($options['include_vendors']);
 | |
|         }
 | |
|         if (array_key_exists('javascript_class', $options)) {
 | |
|             $this->setJavascriptClass($options['javascript_class']);
 | |
|         }
 | |
|         if (array_key_exists('variable_name', $options)) {
 | |
|             $this->setVariableName($options['variable_name']);
 | |
|         }
 | |
|         if (array_key_exists('initialization', $options)) {
 | |
|             $this->setInitialization($options['initialization']);
 | |
|         }
 | |
|         if (array_key_exists('enable_jquery_noconflict', $options)) {
 | |
|             $this->setEnableJqueryNoConflict($options['enable_jquery_noconflict']);
 | |
|         }
 | |
|         if (array_key_exists('use_requirejs', $options)) {
 | |
|             $this->setUseRequireJs($options['use_requirejs']);
 | |
|         }
 | |
|         if (array_key_exists('hide_empty_tabs', $options)) {
 | |
|             $this->setHideEmptyTabs($options['hide_empty_tabs']);
 | |
|         }
 | |
|         if (array_key_exists('controls', $options)) {
 | |
|             foreach ($options['controls'] as $name => $control) {
 | |
|                 $this->addControl($name, $control);
 | |
|             }
 | |
|         }
 | |
|         if (array_key_exists('disable_controls', $options)) {
 | |
|             foreach ((array) $options['disable_controls'] as $name) {
 | |
|                 $this->disableControl($name);
 | |
|             }
 | |
|         }
 | |
|         if (array_key_exists('ignore_collectors', $options)) {
 | |
|             foreach ((array) $options['ignore_collectors'] as $name) {
 | |
|                 $this->ignoreCollector($name);
 | |
|             }
 | |
|         }
 | |
|         if (array_key_exists('ajax_handler_classname', $options)) {
 | |
|             $this->setAjaxHandlerClass($options['ajax_handler_classname']);
 | |
|         }
 | |
|         if (array_key_exists('ajax_handler_bind_to_jquery', $options)) {
 | |
|             $this->setBindAjaxHandlerToJquery($options['ajax_handler_bind_to_jquery']);
 | |
|         }
 | |
|         if (array_key_exists('ajax_handler_auto_show', $options)) {
 | |
|             $this->setAjaxHandlerAutoShow($options['ajax_handler_auto_show']);
 | |
|         }
 | |
|         if (array_key_exists('ajax_handler_enable_tab', $options)) {
 | |
|             $this->setAjaxHandlerEnableTab($options['ajax_handler_enable_tab']);
 | |
|         }
 | |
|         if (array_key_exists('open_handler_classname', $options)) {
 | |
|             $this->setOpenHandlerClass($options['open_handler_classname']);
 | |
|         }
 | |
|         if (array_key_exists('open_handler_url', $options)) {
 | |
|             $this->setOpenHandlerUrl($options['open_handler_url']);
 | |
|         }
 | |
|         if (array_key_exists('csp_nonce', $options)) {
 | |
|             $this->setCspNonce($options['csp_nonce']);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 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
 | |
|      *
 | |
|      * You can only include js or css vendors using
 | |
|      * setIncludeVendors('css') or setIncludeVendors('js')
 | |
|      *
 | |
|      * @param boolean $enabled
 | |
|      */
 | |
|     public function setIncludeVendors($enabled = true)
 | |
|     {
 | |
|         if (is_string($enabled)) {
 | |
|             $enabled = array($enabled);
 | |
|         }
 | |
|         $this->includeVendors = $enabled;
 | |
| 
 | |
|         if (!$enabled || (is_array($enabled) && !in_array('js', $enabled))) {
 | |
|             // no need to call jQuery.noConflict() if we do not include our own version
 | |
|             $this->enableJqueryNoConflict = false;
 | |
|         }
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks if vendors assets are included
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function areVendorsIncluded()
 | |
|     {
 | |
|         return $this->includeVendors !== false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Disable a specific vendor's assets.
 | |
|      *
 | |
|      * @param  string $name "jquery", "fontawesome", "highlightjs"
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function disableVendor($name)
 | |
|     {
 | |
|         if (array_key_exists($name, $this->cssVendors)) {
 | |
|             unset($this->cssVendors[$name]);
 | |
|         }
 | |
|         if (array_key_exists($name, $this->jsVendors)) {
 | |
|             unset($this->jsVendors[$name]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 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;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets whether to call jQuery.noConflict()
 | |
|      *
 | |
|      * @param boolean $enabled
 | |
|      */
 | |
|     public function setEnableJqueryNoConflict($enabled = true)
 | |
|     {
 | |
|         $this->enableJqueryNoConflict = $enabled;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks if jQuery.noConflict() will be called
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function isJqueryNoConflictEnabled()
 | |
|     {
 | |
|         return $this->enableJqueryNoConflict;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets whether to use RequireJS or not
 | |
|      *
 | |
|      * @param boolean $enabled
 | |
|      * @return $this
 | |
|      */
 | |
|     public function setUseRequireJs($enabled = true)
 | |
|     {
 | |
|         $this->useRequireJs = $enabled;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks if RequireJS is used
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function isRequireJsUsed()
 | |
|     {
 | |
|         return $this->useRequireJs;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * Sets whether to hide empty tabs or not
 | |
|      *
 | |
|      * @param boolean $hide
 | |
|      * @return $this
 | |
|      */
 | |
|     public function setHideEmptyTabs($hide = true)
 | |
|     {
 | |
|         $this->hideEmptyTabs = $hide;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks if empty tabs are hidden or not
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function areEmptyTabsHidden()
 | |
|     {
 | |
|         return $this->hideEmptyTabs;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds a control to initialize
 | |
|      *
 | |
|      * Possible options:
 | |
|      *  - icon: icon name
 | |
|      *  - tooltip: string
 | |
|      *  - widget: widget class name
 | |
|      *  - title: tab title
 | |
|      *  - 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, array $options)
 | |
|     {
 | |
|         if (count(array_intersect(array_keys($options), array('icon', 'widget', 'tab', 'indicator'))) === 0) {
 | |
|             throw new DebugBarException("Not enough options for control '$name'");
 | |
|         }
 | |
|         $this->controls[$name] = $options;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Disables a control
 | |
|      *
 | |
|      * @param string $name
 | |
|      */
 | |
|     public function disableControl($name)
 | |
|     {
 | |
|         $this->controls[$name] = null;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the list of controls
 | |
|      *
 | |
|      * This does not include controls provided by collectors
 | |
|      *
 | |
|      * @return array
 | |
|      */
 | |
|     public function getControls()
 | |
|     {
 | |
|         return $this->controls;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Ignores widgets provided by a collector
 | |
|      *
 | |
|      * @param string $name
 | |
|      */
 | |
|     public function ignoreCollector($name)
 | |
|     {
 | |
|         $this->ignoredCollectors[] = $name;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the list of ignored collectors
 | |
|      *
 | |
|      * @return array
 | |
|      */
 | |
|     public function getIgnoredCollectors()
 | |
|     {
 | |
|         return $this->ignoredCollectors;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the class name of the ajax handler
 | |
|      *
 | |
|      * Set to false to disable
 | |
|      *
 | |
|      * @param string $className
 | |
|      */
 | |
|     public function setAjaxHandlerClass($className)
 | |
|     {
 | |
|         $this->ajaxHandlerClass = $className;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the class name of the ajax handler
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function getAjaxHandlerClass()
 | |
|     {
 | |
|         return $this->ajaxHandlerClass;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets whether to call bindToFetch() on the ajax handler
 | |
|      *
 | |
|      * @param boolean $bind
 | |
|      */
 | |
|     public function setBindAjaxHandlerToFetch($bind = true)
 | |
|     {
 | |
|         $this->ajaxHandlerBindToFetch = $bind;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether bindToFetch() will be called on the ajax handler
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function isAjaxHandlerBoundToFetch()
 | |
|     {
 | |
|         return $this->ajaxHandlerBindToFetch;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets whether to call bindToJquery() on the ajax handler
 | |
|      *
 | |
|      * @param boolean $bind
 | |
|      * @deprecated use setBindAjaxHandlerToXHR
 | |
|      */
 | |
|     public function setBindAjaxHandlerToJquery($bind = true)
 | |
|     {
 | |
|         $this->ajaxHandlerBindToJquery = $bind;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether bindToJquery() will be called on the ajax handler
 | |
|      *
 | |
|      * @return boolean
 | |
|      * @deprecated use isAjaxHandlerBoundToXHR
 | |
|      */
 | |
|     public function isAjaxHandlerBoundToJquery()
 | |
|     {
 | |
|         return $this->ajaxHandlerBindToJquery;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets whether to call bindToXHR() on the ajax handler
 | |
|      *
 | |
|      * @param boolean $bind
 | |
|      */
 | |
|     public function setBindAjaxHandlerToXHR($bind = true)
 | |
|     {
 | |
|         $this->ajaxHandlerBindToXHR = $bind;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether bindToXHR() will be called on the ajax handler
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function isAjaxHandlerBoundToXHR()
 | |
|     {
 | |
|         return $this->ajaxHandlerBindToXHR;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets whether new ajax debug data will be immediately shown.  Setting to false could be useful
 | |
|      * if there are a lot of tracking events cluttering things.
 | |
|      *
 | |
|      * @param boolean $autoShow
 | |
|      */
 | |
|     public function setAjaxHandlerAutoShow($autoShow = true)
 | |
|     {
 | |
|         $this->ajaxHandlerAutoShow = $autoShow;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether the ajax handler will immediately show new ajax requests.
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function isAjaxHandlerAutoShow()
 | |
|     {
 | |
|         return $this->ajaxHandlerAutoShow;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets whether new ajax debug data will be shown in a separate tab instead of dropdown.
 | |
|      *
 | |
|      * @param boolean $enabled
 | |
|      */
 | |
|     public function setAjaxHandlerEnableTab($enabled = true)
 | |
|     {
 | |
|         $this->ajaxHandlerEnableTab = $enabled;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Check if the Ajax Handler History tab is enabled
 | |
|      *
 | |
|      * @return boolean
 | |
|      */
 | |
|     public function isAjaxHandlerTabEnabled()
 | |
|     {
 | |
|         return $this->ajaxHandlerEnableTab;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * Sets the class name of the js open handler
 | |
|      *
 | |
|      * @param string $className
 | |
|      */
 | |
|     public function setOpenHandlerClass($className)
 | |
|     {
 | |
|         $this->openHandlerClass = $className;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the class name of the js open handler
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function getOpenHandlerClass()
 | |
|     {
 | |
|         return $this->openHandlerClass;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the url of the open handler
 | |
|      *
 | |
|      * @param string $url
 | |
|      */
 | |
|     public function setOpenHandlerUrl($url)
 | |
|     {
 | |
|         $this->openHandlerUrl = $url;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the url for the open handler
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function getOpenHandlerUrl()
 | |
|     {
 | |
|         return $this->openHandlerUrl;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the CSP Nonce (or remove it by setting to null)
 | |
|      *
 | |
|      * @param string|null $nonce
 | |
|      * @return $this
 | |
|      */
 | |
|     public function setCspNonce($nonce = null)
 | |
|     {
 | |
|         $this->cspNonce = $nonce;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Get the CSP Nonce
 | |
|      *
 | |
|      * @return string|null
 | |
|      */
 | |
|     public function getCspNonce()
 | |
|     {
 | |
|         return $this->cspNonce;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add assets stored in files to render in the head
 | |
|      *
 | |
|      * @param array $cssFiles An array of filenames
 | |
|      * @param array $jsFiles  An array of filenames
 | |
|      * @param string $basePath Base path of those files
 | |
|      * @param string $baseUrl  Base url of those files
 | |
|      * @return $this
 | |
|      */
 | |
|     public function addAssets($cssFiles, $jsFiles, $basePath = null, $baseUrl = null)
 | |
|     {
 | |
|         $this->additionalAssets[] = array(
 | |
|             'base_path' => $basePath,
 | |
|             'base_url' => $baseUrl,
 | |
|             'css' => (array) $cssFiles,
 | |
|             'js' => (array) $jsFiles
 | |
|         );
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Add inline assets to render inline in the head.  Ideally, you should store static assets in
 | |
|      * files that you add with the addAssets function.  However, adding inline assets is useful when
 | |
|      * integrating with 3rd-party libraries that require static assets that are only available in an
 | |
|      * inline format.
 | |
|      *
 | |
|      * The inline content arrays require special string array keys:  they are used to deduplicate
 | |
|      * content.  This is particularly useful if multiple instances of the same asset end up being
 | |
|      * added.  Inline assets from all collectors are merged together into the same array, so these
 | |
|      * content IDs effectively deduplicate the inline assets.
 | |
|      *
 | |
|      * @param array $inlineCss  An array map of content ID to inline CSS content (not including <style> tag)
 | |
|      * @param array $inlineJs   An array map of content ID to inline JS content (not including <script> tag)
 | |
|      * @param array $inlineHead An array map of content ID to arbitrary inline HTML content (typically
 | |
|      *                          <style>/<script> tags); it must be embedded within the <head> element
 | |
|      * @return $this
 | |
|      */
 | |
|     public function addInlineAssets($inlineCss, $inlineJs, $inlineHead)
 | |
|     {
 | |
|         $this->additionalAssets[] = array(
 | |
|             'inline_css' => (array) $inlineCss,
 | |
|             'inline_js' => (array) $inlineJs,
 | |
|             'inline_head' => (array) $inlineHead
 | |
|         );
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the list of asset files
 | |
|      *
 | |
|      * @param string $type 'css', 'js', 'inline_css', 'inline_js', 'inline_head', or null for all
 | |
|      * @param string $relativeTo The type of path to which filenames must be relative (path, url or null)
 | |
|      * @return array
 | |
|      */
 | |
|     public function getAssets($type = null, $relativeTo = self::RELATIVE_PATH)
 | |
|     {
 | |
|         $cssFiles = $this->cssFiles;
 | |
|         $jsFiles = $this->jsFiles;
 | |
|         $inlineCss = array();
 | |
|         $inlineJs = array();
 | |
|         $inlineHead = array();
 | |
| 
 | |
|         if ($this->includeVendors !== false) {
 | |
|             if ($this->includeVendors === true || in_array('css', $this->includeVendors)) {
 | |
|                 $cssFiles = array_merge($this->cssVendors, $cssFiles);
 | |
|             }
 | |
|             if ($this->includeVendors === true || in_array('js', $this->includeVendors)) {
 | |
|                 $jsFiles = array_merge($this->jsVendors, $jsFiles);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ($relativeTo) {
 | |
|             $root = $this->getRelativeRoot($relativeTo, $this->basePath, $this->baseUrl);
 | |
|             $cssFiles = $this->makeUriRelativeTo($cssFiles, $root);
 | |
|             $jsFiles = $this->makeUriRelativeTo($jsFiles, $root);
 | |
|         }
 | |
| 
 | |
|         $additionalAssets = $this->additionalAssets;
 | |
|         // finds assets provided by collectors
 | |
|         foreach ($this->debugBar->getCollectors() as $collector) {
 | |
|             if (($collector instanceof AssetProvider) && !in_array($collector->getName(), $this->ignoredCollectors)) {
 | |
|                 $additionalAssets[] = $collector->getAssets();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         foreach ($additionalAssets as $assets) {
 | |
|             $basePath = isset($assets['base_path']) ? $assets['base_path'] : '';
 | |
|             $baseUrl = isset($assets['base_url']) ? $assets['base_url'] : '';
 | |
|             $root = $this->getRelativeRoot($relativeTo,
 | |
|                 $this->makeUriRelativeTo($basePath, $this->basePath),
 | |
|                 $this->makeUriRelativeTo($baseUrl, $this->baseUrl));
 | |
|             if (isset($assets['css'])) {
 | |
|                 $cssFiles = array_merge($cssFiles, $this->makeUriRelativeTo((array) $assets['css'], $root));
 | |
|             }
 | |
|             if (isset($assets['js'])) {
 | |
|                 $jsFiles = array_merge($jsFiles, $this->makeUriRelativeTo((array) $assets['js'], $root));
 | |
|             }
 | |
| 
 | |
|             if (isset($assets['inline_css'])) {
 | |
|                 $inlineCss = array_merge($inlineCss, (array) $assets['inline_css']);
 | |
|             }
 | |
|             if (isset($assets['inline_js'])) {
 | |
|                 $inlineJs = array_merge($inlineJs, (array) $assets['inline_js']);
 | |
|             }
 | |
|             if (isset($assets['inline_head'])) {
 | |
|                 $inlineHead = array_merge($inlineHead, (array) $assets['inline_head']);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Deduplicate files
 | |
|         $cssFiles = array_unique($cssFiles);
 | |
|         $jsFiles = array_unique($jsFiles);
 | |
| 
 | |
|         return $this->filterAssetArray(array($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead), $type ?? '');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the correct base according to the type
 | |
|      *
 | |
|      * @param string $relativeTo
 | |
|      * @param string $basePath
 | |
|      * @param string $baseUrl
 | |
|      * @return string
 | |
|      */
 | |
|     protected function getRelativeRoot($relativeTo, $basePath, $baseUrl)
 | |
|     {
 | |
|         if ($relativeTo === self::RELATIVE_PATH) {
 | |
|             return $basePath;
 | |
|         }
 | |
|         if ($relativeTo === self::RELATIVE_URL) {
 | |
|             return $baseUrl;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Makes a URI relative to another
 | |
|      *
 | |
|      * @param string|array $uri
 | |
|      * @param string $root
 | |
|      * @return string
 | |
|      */
 | |
|     protected function makeUriRelativeTo($uri, $root)
 | |
|     {
 | |
|         if (!$root) {
 | |
|             return $uri;
 | |
|         }
 | |
| 
 | |
|         if (is_array($uri)) {
 | |
|             $uris = array();
 | |
|             foreach ($uri as $u) {
 | |
|                 $uris[] = $this->makeUriRelativeTo($u, $root);
 | |
|             }
 | |
|             return $uris;
 | |
|         }
 | |
| 
 | |
|         $uri = $uri ?? '';
 | |
| 
 | |
|         if (substr($uri, 0, 1) === '/' || preg_match('/^([a-zA-Z]+:\/\/|[a-zA-Z]:\/|[a-zA-Z]:\\\)/', $uri)) {
 | |
|             return $uri;
 | |
|         }
 | |
|         return rtrim($root, '/') . "/$uri";
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Filters a tuple of (css, js, inline_css, inline_js, inline_head) assets according to $type
 | |
|      *
 | |
|      * @param array $array
 | |
|      * @param string $type 'css', 'js', 'inline_css', 'inline_js', 'inline_head', or null for all
 | |
|      * @return array
 | |
|      */
 | |
|     protected function filterAssetArray($array, $type = '')
 | |
|     {
 | |
|         $types = array('css', 'js', 'inline_css', 'inline_js', 'inline_head');
 | |
|         $typeIndex = array_search(strtolower($type ?? ''), $types);
 | |
|         return $typeIndex !== false ? $array[$typeIndex] : $array;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns an array where all items are Assetic AssetCollection:
 | |
|      *  - The first one contains the CSS files
 | |
|      *  - The second one contains the JS files
 | |
|      *  - The third one contains arbitrary inline HTML (typically composed of <script>/<style>
 | |
|      *    elements); it must be embedded within the <head> element
 | |
|      *
 | |
|      * @param string $type Optionally return only 'css', 'js', or 'inline_head' collection
 | |
|      * @return array|\Assetic\Asset\AssetCollection
 | |
|      */
 | |
|     public function getAsseticCollection($type = null)
 | |
|     {
 | |
|         $types = array('css', 'js', 'inline_head');
 | |
|         $typeIndex = array_search(strtolower($type), $types);
 | |
| 
 | |
|         list($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead) = $this->getAssets();
 | |
|         $collections = array(
 | |
|             $this->createAsseticCollection($cssFiles, $inlineCss),
 | |
|             $this->createAsseticCollection($jsFiles, $inlineJs),
 | |
|             $this->createAsseticCollection(null, $inlineHead)
 | |
|         );
 | |
|         return $typeIndex !== false ? $collections[$typeIndex] : $collections;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Create an Assetic AssetCollection with the given content.
 | |
|      * Filenames will be converted to absolute path using
 | |
|      * the base path.
 | |
|      *
 | |
|      * @param array|null $files Array of asset filenames.
 | |
|      * @param array|null $content Array of inline asset content.
 | |
|      * @return \Assetic\Asset\AssetCollection
 | |
|      */
 | |
|     protected function createAsseticCollection($files = null, $content = null)
 | |
|     {
 | |
|         $assets = array();
 | |
|         if ($files) {
 | |
|             foreach ($files as $file) {
 | |
|                 $assets[] = new \Assetic\Asset\FileAsset($file);
 | |
|             }
 | |
|         }
 | |
|         if ($content) {
 | |
|             foreach ($content as $item) {
 | |
|                 $assets[] = new \Assetic\Asset\StringAsset($item);
 | |
|             }
 | |
|         }
 | |
|         return new \Assetic\Asset\AssetCollection($assets);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Write all CSS assets to standard output or in a file
 | |
|      *
 | |
|      * @param string $targetFilename
 | |
|      */
 | |
|     public function dumpCssAssets($targetFilename = null)
 | |
|     {
 | |
|         $this->dumpAssets($this->getAssets('css'), $this->getAssets('inline_css'), $targetFilename);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Write all JS assets to standard output or in a file
 | |
|      *
 | |
|      * @param string $targetFilename
 | |
|      */
 | |
|     public function dumpJsAssets($targetFilename = null)
 | |
|     {
 | |
|         $this->dumpAssets($this->getAssets('js'), $this->getAssets('inline_js'), $targetFilename, $this->useRequireJs);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Write all inline HTML header assets to standard output or in a file (only returns assets not
 | |
|      * already returned by dumpCssAssets or dumpJsAssets)
 | |
|      *
 | |
|      * @param string $targetFilename
 | |
|      */
 | |
|     public function dumpHeadAssets($targetFilename = null)
 | |
|     {
 | |
|         $this->dumpAssets(null, $this->getAssets('inline_head'), $targetFilename);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Write assets to standard output or in a file
 | |
|      *
 | |
|      * @param array|null $files Filenames containing assets
 | |
|      * @param array|null $content Inline content to dump
 | |
|      * @param string $targetFilename
 | |
|      * @param bool $useRequireJs
 | |
|      */
 | |
|     protected function dumpAssets($files = null, $content = null, $targetFilename = null, $useRequireJs = false)
 | |
|     {
 | |
|         $dumpedContent = '';
 | |
|         if ($files) {
 | |
|             foreach ($files as $file) {
 | |
|                 $dumpedContent .= file_get_contents($file) . "\n";
 | |
|             }
 | |
|         }
 | |
|         if ($content) {
 | |
|             foreach ($content as $item) {
 | |
|                 $dumpedContent .= $item . "\n";
 | |
|             }
 | |
|         }
 | |
|         if ($useRequireJs) {
 | |
|             $dumpedContent = "define('debugbar', ['jquery'], function($){\r\n" . $dumpedContent . "\r\n return PhpDebugBar; \r\n});";
 | |
|         }
 | |
|         if ($targetFilename !== null) {
 | |
|             file_put_contents($targetFilename, $dumpedContent);
 | |
|         } else {
 | |
|             echo $dumpedContent;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Renders the html to include needed assets
 | |
|      *
 | |
|      * Only useful if Assetic is not used
 | |
|      *
 | |
|      * @return string
 | |
|      */
 | |
|     public function renderHead()
 | |
|     {
 | |
|         list($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead) = $this->getAssets(null, self::RELATIVE_URL);
 | |
|         $html = '';
 | |
| 
 | |
|         $nonce = $this->getNonceAttribute();
 | |
| 
 | |
|         foreach ($cssFiles as $file) {
 | |
|             $html .= sprintf('<link rel="stylesheet" type="text/css" href="%s">' . "\n", $file);
 | |
|         }
 | |
| 
 | |
|         foreach ($inlineCss as $content) {
 | |
|             $html .= sprintf('<style type="text/css">%s</style>' . "\n", $content);
 | |
|         }
 | |
| 
 | |
|         foreach ($jsFiles as $file) {
 | |
|             $html .= sprintf('<script type="text/javascript" src="%s"></script>' . "\n", $file);
 | |
|         }
 | |
| 
 | |
|         foreach ($inlineJs as $content) {
 | |
|             $html .= sprintf('<script type="text/javascript"%s>%s</script>' . "\n", $nonce, $content);
 | |
|         }
 | |
| 
 | |
|         foreach ($inlineHead as $content) {
 | |
|             $html .= $content . "\n";
 | |
|         }
 | |
| 
 | |
|         if ($this->enableJqueryNoConflict && !$this->useRequireJs) {
 | |
|             $html .= '<script type="text/javascript"' . $nonce . '>jQuery.noConflict(true);</script>' . "\n";
 | |
|         }
 | |
| 
 | |
|         return $html;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Register shutdown to display the debug bar
 | |
|      *
 | |
|      * @param boolean $here Set position of HTML. True if is to current position or false for end file
 | |
|      * @param boolean $initialize Whether to render the de bug bar initialization code
 | |
|      * @param bool $renderStackedData
 | |
|      * @param bool $head
 | |
|      * @return string Return "{--DEBUGBAR_OB_START_REPLACE_ME--}" or return an empty string if $here == false
 | |
|      */
 | |
|     public function renderOnShutdown($here = true, $initialize = true, $renderStackedData = true, $head = false)
 | |
|     {
 | |
|         register_shutdown_function(array($this, "replaceTagInBuffer"), $here, $initialize, $renderStackedData, $head);
 | |
| 
 | |
|         if (ob_get_level() === 0) {
 | |
|             ob_start();
 | |
|         }
 | |
| 
 | |
|         return ($here) ? self::REPLACEABLE_TAG : "";
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Same as renderOnShutdown() with $head = true
 | |
|      *
 | |
|      * @param boolean $here
 | |
|      * @param boolean $initialize
 | |
|      * @param boolean $renderStackedData
 | |
|      * @return string
 | |
|      */
 | |
|     public function renderOnShutdownWithHead($here = true, $initialize = true, $renderStackedData = true)
 | |
|     {
 | |
|         return $this->renderOnShutdown($here, $initialize, $renderStackedData, true);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Is callback function for register_shutdown_function(...)
 | |
|      *
 | |
|      * @param boolean $here Set position of HTML. True if is to current position or false for end file
 | |
|      * @param boolean $initialize Whether to render the de bug bar initialization code
 | |
|      * @param bool $renderStackedData
 | |
|      * @param bool $head
 | |
|      */
 | |
|     public function replaceTagInBuffer($here = true, $initialize = true, $renderStackedData = true, $head = false)
 | |
|     {
 | |
|         $render = ($head ? $this->renderHead() : "")
 | |
|             . $this->render($initialize, $renderStackedData);
 | |
| 
 | |
|         $current = ($here && ob_get_level() > 0) ? ob_get_clean() : self::REPLACEABLE_TAG;
 | |
| 
 | |
|         echo str_replace(self::REPLACEABLE_TAG, $render, $current, $count);
 | |
| 
 | |
|         if ($count === 0) {
 | |
|             echo $render;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the code needed to display the debug bar
 | |
|      *
 | |
|      * AJAX request should not render the initialization code.
 | |
|      *
 | |
|      * @param boolean $initialize Whether or not to render the debug bar initialization code
 | |
|      * @param boolean $renderStackedData Whether or not to render the stacked data
 | |
|      * @return string
 | |
|      */
 | |
|     public function render($initialize = true, $renderStackedData = true)
 | |
|     {
 | |
|         $js = '';
 | |
| 
 | |
|         if ($initialize) {
 | |
|             $js = $this->getJsInitializationCode();
 | |
|         }
 | |
| 
 | |
|         if ($renderStackedData && $this->debugBar->hasStackedData()) {
 | |
|             foreach ($this->debugBar->getStackedData() as $id => $data) {
 | |
|                 $js .= $this->getAddDatasetCode($id, $data, '(stacked)');
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         $suffix = !$initialize ? '(ajax)' : null;
 | |
|         $js .= $this->getAddDatasetCode($this->debugBar->getCurrentRequestId(), $this->debugBar->getData(), $suffix);
 | |
| 
 | |
|         $nonce = $this->getNonceAttribute();
 | |
| 
 | |
|         if ($nonce != '') {
 | |
|             $js = preg_replace("/<script>/", "<script nonce='{$this->cspNonce}'>", $js);
 | |
|         }
 | |
| 
 | |
|         if ($this->useRequireJs){
 | |
|             return "<script type=\"text/javascript\"{$nonce}>\nrequire(['debugbar'], function(PhpDebugBar){ $js });\n</script>\n";
 | |
|         } else {
 | |
|             return "<script type=\"text/javascript\"{$nonce}>\n$js\n</script>\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->hideEmptyTabs !== null) {
 | |
|             $js .= sprintf("%s.setHideEmptyTabs(%s);\n", $this->variableName,
 | |
|                 json_encode($this->hideEmptyTabs));
 | |
|         }
 | |
| 
 | |
|         if (($this->initialization & self::INITIALIZE_CONTROLS) === self::INITIALIZE_CONTROLS) {
 | |
|             $js .= $this->getJsControlsDefinitionCode($this->variableName);
 | |
|         }
 | |
| 
 | |
|         if ($this->ajaxHandlerClass) {
 | |
|             $js .= sprintf("%s.ajaxHandler = new %s(%s, undefined, %s);\n",
 | |
|                 $this->variableName,
 | |
|                 $this->ajaxHandlerClass,
 | |
|                 $this->variableName,
 | |
|                 $this->ajaxHandlerAutoShow ? 'true' : 'false'
 | |
|             );
 | |
|             if ($this->ajaxHandlerBindToFetch) {
 | |
|                 $js .= sprintf("%s.ajaxHandler.bindToFetch();\n", $this->variableName);
 | |
|             }
 | |
|             if ($this->ajaxHandlerBindToXHR) {
 | |
|                 $js .= sprintf("%s.ajaxHandler.bindToXHR();\n", $this->variableName);
 | |
|             } elseif ($this->ajaxHandlerBindToJquery) {
 | |
|                 $js .= sprintf("if (jQuery) %s.ajaxHandler.bindToJquery(jQuery);\n", $this->variableName);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ($this->openHandlerUrl !== null) {
 | |
|             $js .= sprintf("%s.setOpenHandler(new %s(%s));\n", $this->variableName,
 | |
|                 $this->openHandlerClass,
 | |
|                 json_encode(array("url" => $this->openHandlerUrl)));
 | |
|         }
 | |
| 
 | |
|         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();
 | |
|         $excludedOptions = array('indicator', 'tab', 'map', 'default', 'widget', 'position');
 | |
| 
 | |
|         // finds controls provided by collectors
 | |
|         $widgets = array();
 | |
|         foreach ($this->debugBar->getCollectors() as $collector) {
 | |
|             if (($collector instanceof Renderable) && !in_array($collector->getName(), $this->ignoredCollectors)) {
 | |
|                 if ($w = $collector->getWidgets()) {
 | |
|                     $widgets = array_merge($widgets, $w);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         $controls = array_merge($widgets, $this->controls);
 | |
| 
 | |
|         foreach (array_filter($controls) as $name => $options) {
 | |
|             $opts = array_diff_key($options, array_flip($excludedOptions));
 | |
| 
 | |
|             if (isset($options['tab']) || isset($options['widget'])) {
 | |
|                 if (!isset($opts['title'])) {
 | |
|                     $opts['title'] = ucfirst(str_replace('_', ' ', $name));
 | |
|                 }
 | |
|                 $js .= sprintf("%s.addTab(\"%s\", new %s({%s%s}));\n",
 | |
|                     $varname,
 | |
|                     $name,
 | |
|                     isset($options['tab']) ? $options['tab'] : 'PhpDebugBar.DebugBar.Tab',
 | |
|                     substr(json_encode($opts, JSON_FORCE_OBJECT), 1, -1),
 | |
|                     isset($options['widget']) ? sprintf('%s"widget": new %s()', count($opts) ? ', ' : '', $options['widget']) : ''
 | |
|                 );
 | |
|             } elseif (isset($options['indicator']) || isset($options['icon'])) {
 | |
|                 $js .= sprintf("%s.addIndicator(\"%s\", new %s(%s), \"%s\");\n",
 | |
|                     $varname,
 | |
|                     $name,
 | |
|                     isset($options['indicator']) ? $options['indicator'] : 'PhpDebugBar.DebugBar.Indicator',
 | |
|                     json_encode($opts, JSON_FORCE_OBJECT),
 | |
|                     isset($options['position']) ? $options['position'] : 'right'
 | |
|                 );
 | |
|             }
 | |
| 
 | |
|             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 restoration
 | |
|         $js .= sprintf("%s.restoreState();\n", $varname);
 | |
| 
 | |
|         if ($this->ajaxHandlerEnableTab) {
 | |
|             $js .= sprintf("%s.enableAjaxHandlerTab();\n", $varname);
 | |
|         }
 | |
|         return $js;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the js code needed to add a dataset
 | |
|      *
 | |
|      * @param string $requestId
 | |
|      * @param array $data
 | |
|      * @param mixed $suffix
 | |
|      * @return string
 | |
|      */
 | |
|     protected function getAddDatasetCode($requestId, $data, $suffix = null)
 | |
|     {
 | |
|         $js = sprintf("%s.addDataSet(%s, \"%s\"%s);\n",
 | |
|             $this->variableName,
 | |
|             json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_INVALID_UTF8_IGNORE),
 | |
|             $requestId,
 | |
|             $suffix ? ", " . json_encode($suffix) : ''
 | |
|         );
 | |
|         return $js;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * If a nonce it set, create the correct attribute
 | |
|      * @return string
 | |
|      */
 | |
|     protected function getNonceAttribute()
 | |
|     {
 | |
|         if ($nonce = $this->getCspNonce()) {
 | |
|             return ' nonce="' . $nonce .'"';
 | |
|         }
 | |
| 
 | |
|         return '';
 | |
|     }
 | |
| }
 |