mirror of
https://github.com/maximebf/php-debugbar.git
synced 2025-07-28 04:00:43 +02:00
Enable AssetProvider to support inline assets (#338)
Add new inline_css, inline_js, and inline_head keys on the AssetProvider::getAssets() function. This allows us to support collectors that require static assets that are not actually saved to a file. Then, update all the asset functions in JavascriptRenderer to support these new keys. An initial use case for this is supporting the HtmlDumper in Symfony’s VarDumper. HtmlDumper only provides the styles and scripts in inline HTML form. The static assets can be customized based on some configuration properties available on the HtmlDumper class. One can actually view the CSS/JS as a long PHP string/heredoc embedded in the HtmlDumper.php source code. They are only accessible via the getDumpHeader function, which returns the CSS/JS in a combined HTML string.
This commit is contained in:
committed by
Barry vd. Heuvel
parent
4773b2f89b
commit
e6f0b5a48d
@@ -21,6 +21,21 @@ interface AssetProvider
|
||||
* - base_url
|
||||
* - css: an array of filenames
|
||||
* - js: an array of filenames
|
||||
* - inline_css: an array map of content ID to inline CSS content (not including <style> tag)
|
||||
* - inline_js: an array map of content ID to inline JS content (not including <script> tag)
|
||||
* - inline_head: an array map of content ID to arbitrary inline HTML content (typically
|
||||
* <style>/<script> tags); it must be embedded within the <head> element
|
||||
*
|
||||
* All keys are optional.
|
||||
*
|
||||
* Ideally, you should store static assets in filenames that are returned via the normal css/js
|
||||
* keys. However, the inline asset elements are 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: the caller of this function
|
||||
* will use them to deduplicate content. This is particularly useful if multiple instances of
|
||||
* the same asset provider are used. Inline assets from all collectors are merged together into
|
||||
* the same array, so these content IDs effectively deduplicate the inline assets.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@@ -584,12 +584,13 @@ class JavascriptRenderer
|
||||
}
|
||||
|
||||
/**
|
||||
* Add assets to render in the head
|
||||
* 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)
|
||||
{
|
||||
@@ -602,10 +603,37 @@ class JavascriptRenderer
|
||||
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 Only return css or js 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
|
||||
*/
|
||||
@@ -613,6 +641,9 @@ class JavascriptRenderer
|
||||
{
|
||||
$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)) {
|
||||
@@ -643,11 +674,29 @@ class JavascriptRenderer
|
||||
$root = $this->getRelativeRoot($relativeTo,
|
||||
$this->makeUriRelativeTo($basePath, $this->basePath),
|
||||
$this->makeUriRelativeTo($baseUrl, $this->baseUrl));
|
||||
$cssFiles = array_merge($cssFiles, $this->makeUriRelativeTo((array) $assets['css'], $root));
|
||||
$jsFiles = array_merge($jsFiles, $this->makeUriRelativeTo((array) $assets['js'], $root));
|
||||
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']);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->filterAssetArray(array($cssFiles, $jsFiles), $type);
|
||||
// Deduplicate files
|
||||
$cssFiles = array_unique($cssFiles);
|
||||
$jsFiles = array_unique($jsFiles);
|
||||
|
||||
return $this->filterAssetArray(array($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead), $type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -697,53 +746,64 @@ class JavascriptRenderer
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a tuple of (css, js) assets according to $type
|
||||
* Filters a tuple of (css, js, inline_css, inline_js, inline_head) assets according to $type
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $type 'css', 'js' or null for both
|
||||
* @param string $type 'css', 'js', 'inline_css', 'inline_js', 'inline_head', or null for all
|
||||
* @return array
|
||||
*/
|
||||
protected function filterAssetArray($array, $type = null)
|
||||
{
|
||||
$type = strtolower($type);
|
||||
if ($type === 'css') {
|
||||
return $array[0];
|
||||
}
|
||||
if ($type === 'js') {
|
||||
return $array[1];
|
||||
}
|
||||
return $array;
|
||||
$types = array('css', 'js', 'inline_css', 'inline_js', 'inline_head');
|
||||
$typeIndex = array_search(strtolower($type), $types);
|
||||
return $typeIndex !== false ? $array[$typeIndex] : $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a tuple where the both items are Assetic AssetCollection,
|
||||
* the first one being css files and the second js files
|
||||
* 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 Only return css or js collection
|
||||
* @param string $type Optionally return only 'css', 'js', or 'inline_head' collection
|
||||
* @return array or \Assetic\Asset\AssetCollection
|
||||
*/
|
||||
public function getAsseticCollection($type = null)
|
||||
{
|
||||
list($cssFiles, $jsFiles) = $this->getAssets();
|
||||
return $this->filterAssetArray(array(
|
||||
$this->createAsseticCollection($cssFiles),
|
||||
$this->createAsseticCollection($jsFiles)
|
||||
), $type);
|
||||
$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 files.
|
||||
* Create an Assetic AssetCollection with the given content.
|
||||
* Filenames will be converted to absolute path using
|
||||
* the base path.
|
||||
*
|
||||
* @param array $files
|
||||
* @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)
|
||||
protected function createAsseticCollection($files = null, $content = null)
|
||||
{
|
||||
$assets = array();
|
||||
foreach ($files as $file) {
|
||||
$assets[] = new \Assetic\Asset\FileAsset($file);
|
||||
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);
|
||||
}
|
||||
@@ -755,7 +815,7 @@ class JavascriptRenderer
|
||||
*/
|
||||
public function dumpCssAssets($targetFilename = null)
|
||||
{
|
||||
$this->dumpAssets($this->getAssets('css'), $targetFilename);
|
||||
$this->dumpAssets($this->getAssets('css'), $this->getAssets('inline_css'), $targetFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -765,29 +825,48 @@ class JavascriptRenderer
|
||||
*/
|
||||
public function dumpJsAssets($targetFilename = null)
|
||||
{
|
||||
$this->dumpAssets($this->getAssets('js'), $targetFilename, $this->useRequireJs);
|
||||
$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 $files
|
||||
* @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, $targetFilename = null, $useRequireJs = false)
|
||||
protected function dumpAssets($files = null, $content = null, $targetFilename = null, $useRequireJs = false)
|
||||
{
|
||||
$content = '';
|
||||
foreach ($files as $file) {
|
||||
$content .= file_get_contents($file) . "\n";
|
||||
$dumpedContent = '';
|
||||
if ($files) {
|
||||
foreach ($files as $file) {
|
||||
$dumpedContent .= file_get_contents($file) . "\n";
|
||||
}
|
||||
}
|
||||
if ($content) {
|
||||
foreach ($content as $item) {
|
||||
$dumpedContent .= $item . "\n";
|
||||
}
|
||||
}
|
||||
if ($useRequireJs) {
|
||||
$content = "define('debugbar', ['jquery'], function($){\r\n" . $content . "\r\n return PhpDebugBar; \r\n});";
|
||||
$dumpedContent = "define('debugbar', ['jquery'], function($){\r\n" . $dumpedContent . "\r\n return PhpDebugBar; \r\n});";
|
||||
}
|
||||
if ($targetFilename !== null) {
|
||||
file_put_contents($targetFilename, $content);
|
||||
file_put_contents($targetFilename, $dumpedContent);
|
||||
} else {
|
||||
echo $content;
|
||||
echo $dumpedContent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -800,17 +879,29 @@ class JavascriptRenderer
|
||||
*/
|
||||
public function renderHead()
|
||||
{
|
||||
list($cssFiles, $jsFiles) = $this->getAssets(null, self::RELATIVE_URL);
|
||||
list($cssFiles, $jsFiles, $inlineCss, $inlineJs, $inlineHead) = $this->getAssets(null, self::RELATIVE_URL);
|
||||
$html = '';
|
||||
|
||||
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</script>' . "\n", $content);
|
||||
}
|
||||
|
||||
foreach ($inlineHead as $content) {
|
||||
$html .= $content . "\n";
|
||||
}
|
||||
|
||||
if ($this->enableJqueryNoConflict && !$this->useRequireJs) {
|
||||
$html .= '<script type="text/javascript">jQuery.noConflict(true);</script>' . "\n";
|
||||
}
|
||||
|
Reference in New Issue
Block a user