mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENH Create Requirements::customScriptWithAttributes (#11076)
* ENH Create Requirements::customScriptWithAttributes * MNT PHP Lint failures corrected * ENH Refactored attribute handling to avoid API changes, auto lowercase, strong typing * FIX Updated default value handling for type in customScriptWithAttributes * DOC Removed white space * MNT PHP Lint Failures Corrected * Update src/View/Requirements_Backend.php Co-authored-by: Steve Boyd <emteknetnz@gmail.com> * Update src/View/Requirements_Backend.php Co-authored-by: Steve Boyd <emteknetnz@gmail.com> * Update tests/php/View/RequirementsTest.php Co-authored-by: Steve Boyd <emteknetnz@gmail.com> * FIX Removed extra closing brace in customScriptWithAttributes * Update src/View/Requirements_Backend.php Co-authored-by: Steve Boyd <emteknetnz@gmail.com> * Update src/View/Requirements.php Co-authored-by: Guy Sartorelli <36352093+GuySartorelli@users.noreply.github.com> * MNT Fixed left over content definition and created tests for uniquenessIDs * MNT Fixed PHP Lint Error * MNT Fix PHP Lint Error * FIX Remove attribute when calling customScript with the same uniquenessID --------- Co-authored-by: Steve Boyd <emteknetnz@gmail.com> Co-authored-by: Guy Sartorelli <36352093+GuySartorelli@users.noreply.github.com>
This commit is contained in:
parent
c003dfd4b1
commit
2487c4085d
@ -142,6 +142,21 @@ class Requirements implements Flushable
|
||||
self::backend()->customScript($script, $uniquenessID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given Javascript code into the list of requirements with optional tag
|
||||
* attributes.
|
||||
*
|
||||
* @param string $script The script content as a string (without enclosing `<script>` tag)
|
||||
* @param array $options List of options. Available options include:
|
||||
* - 'type' : Specifies the type of script
|
||||
* - 'crossorigin' : Cross-origin policy for the resource
|
||||
* @param string|int|null $uniquenessID A unique ID that ensures a piece of code is only added once
|
||||
*/
|
||||
public static function customScriptWithAttributes(string $script, array $options = [], string|int|null $uniquenessID = null)
|
||||
{
|
||||
self::backend()->customScriptWithAttributes($script, $options, $uniquenessID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all registered custom scripts
|
||||
*
|
||||
|
@ -95,6 +95,14 @@ class Requirements_Backend
|
||||
*/
|
||||
protected $customScript = [];
|
||||
|
||||
/**
|
||||
* Maintains attributes for each entry in the `$customScript` array, indexed by either a
|
||||
* unique identifier (uniquenessID) or the script's array position.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private array $customScriptAttributes = [];
|
||||
|
||||
/**
|
||||
* All custom CSS rules which are inserted directly at the bottom of the HTML `<head>` tag
|
||||
*
|
||||
@ -494,12 +502,43 @@ class Requirements_Backend
|
||||
public function customScript($script, $uniquenessID = null)
|
||||
{
|
||||
if ($uniquenessID) {
|
||||
if (isset($this->customScriptAttributes[$uniquenessID])) {
|
||||
unset($this->customScriptAttributes[$uniquenessID]);
|
||||
}
|
||||
$this->customScript[$uniquenessID] = $script;
|
||||
} else {
|
||||
$this->customScript[] = $script;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given Javascript code into the list of requirements with optional tag
|
||||
* attributes.
|
||||
*
|
||||
* @param string $script The script content as a string (without enclosing `<script>` tag)
|
||||
* @param array $options List of options. Available options include:
|
||||
* - 'type' : Specifies the type of script
|
||||
* - 'crossorigin' : Cross-origin policy for the resource
|
||||
* @param string|int $uniquenessID A unique ID that ensures a piece of code is only added once
|
||||
*/
|
||||
public function customScriptWithAttributes(string $script, array $attributes = [], string|int|null $uniquenessID = null)
|
||||
{
|
||||
$attrs = [];
|
||||
foreach (['type', 'crossorigin'] as $attrKey) {
|
||||
if (isset($attributes[$attrKey])) {
|
||||
$attrs[$attrKey] = strtolower($attributes[$attrKey]);
|
||||
}
|
||||
}
|
||||
if ($uniquenessID) {
|
||||
$this->customScript[$uniquenessID] = $script;
|
||||
$this->customScriptAttributes[$uniquenessID] = $attrs;
|
||||
} else {
|
||||
$this->customScript[] = $script;
|
||||
$index = count($this->customScript) - 1;
|
||||
$this->customScriptAttributes[$index] = $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all registered custom scripts
|
||||
*
|
||||
@ -791,10 +830,17 @@ class Requirements_Backend
|
||||
}
|
||||
|
||||
// Add all inline JavaScript *after* including external files they might rely on
|
||||
foreach ($this->getCustomScripts() as $script) {
|
||||
foreach ($this->getCustomScripts() as $key => $script) {
|
||||
// Build html attributes
|
||||
$customHtmlAttributes = ['type' => 'application/javascript'];
|
||||
if (isset($this->customScriptAttributes[$key])) {
|
||||
foreach ($this->customScriptAttributes[$key] as $attrKey => $attrValue) {
|
||||
$customHtmlAttributes[$attrKey] = $attrValue;
|
||||
}
|
||||
}
|
||||
$jsRequirements .= HTML::createTag(
|
||||
'script',
|
||||
[ 'type' => 'application/javascript' ],
|
||||
$customHtmlAttributes,
|
||||
"//<![CDATA[\n{$script}\n//]]>"
|
||||
);
|
||||
$jsRequirements .= "\n";
|
||||
|
@ -1403,6 +1403,8 @@ EOS
|
||||
$this->setupRequirements($backend);
|
||||
|
||||
$backend->javascript('javascript/RequirementsTest_a.js', ['integrity' => 'abc', 'crossorigin' => 'use-credentials']);
|
||||
// Tests attribute appending AND lowercase string conversion
|
||||
$backend->customScriptWithAttributes("//TEST", ['type' => 'module', 'crossorigin' => 'Anonymous']);
|
||||
$backend->css('css/RequirementsTest_a.css', null, ['integrity' => 'def', 'crossorigin' => 'anonymous']);
|
||||
$html = $backend->includeInHTML(self::$html_template);
|
||||
|
||||
@ -1413,6 +1415,12 @@ EOS
|
||||
'javascript has correct sri attributes'
|
||||
);
|
||||
|
||||
/* Custom Javascript has correct attribute */
|
||||
$this->assertMatchesRegularExpression(
|
||||
'#<script type="module" crossorigin="anonymous"#',
|
||||
$html,
|
||||
'custom javascript has correct sri attributes'
|
||||
);
|
||||
/* CSS has correct attributes */
|
||||
$this->assertMatchesRegularExpression(
|
||||
'#<link .*href=".*/RequirementsTest_a\.css.*" integrity="def" crossorigin="anonymous"#',
|
||||
@ -1420,4 +1428,77 @@ EOS
|
||||
'css has correct sri attributes'
|
||||
);
|
||||
}
|
||||
|
||||
public function testUniquenessID()
|
||||
{
|
||||
/** @var Requirements_Backend $backend */
|
||||
$backend = Injector::inst()->create(Requirements_Backend::class);
|
||||
$this->setupRequirements($backend);
|
||||
|
||||
// Create requirements that are to be overwritten
|
||||
$backend->customScript("Do Not Display", 42);
|
||||
$backend->customScriptWithAttributes("Do Not Display", ['type' => 'module', 'crossorigin' => 'use-credentials'], 84);
|
||||
$backend->customCSS("Do Not Display", 42);
|
||||
$backend->insertHeadTags("<span>Do Not Display</span>", 42);
|
||||
|
||||
// Override
|
||||
$backend->customScriptWithAttributes("Override", ['type' => 'module', 'crossorigin' => 'use-credentials'], 42);
|
||||
$backend->customScript("Override", 84);
|
||||
$backend->customCSS("Override", 42);
|
||||
$backend->insertHeadTags("<span>Override</span>", 42);
|
||||
|
||||
$html = $backend->includeInHTML(self::$html_template);
|
||||
|
||||
/* customScript is overwritten by customScriptWithAttributes */
|
||||
$this->assertMatchesRegularExpression(
|
||||
"#<script type=\"module\" crossorigin=\"use-credentials\">//<!\[CDATA\[\s*Override\s*//\]\]></script>#s",
|
||||
$html,
|
||||
'customScript is displaying latest write'
|
||||
);
|
||||
|
||||
$this->assertDoesNotMatchRegularExpression(
|
||||
"#<script type=\"application/javascript\">//<!\[CDATA\[\s*Do Not Display\s*//\]\]></script>#s",
|
||||
$html,
|
||||
'customScript is correctly not displaying original write'
|
||||
);
|
||||
|
||||
/* customScriptWithAttributes is overwritten by customScript */
|
||||
$this->assertMatchesRegularExpression(
|
||||
"#<script type=\"application/javascript\">//<!\[CDATA\[\s*Override\s*//\]\]></script>#s",
|
||||
$html,
|
||||
'customScript is displaying latest write and clearing attributes'
|
||||
);
|
||||
|
||||
$this->assertDoesNotMatchRegularExpression(
|
||||
"#<script type=\"module\" crossorigin=\"use-credentials\">//<!\[CDATA\[\s*Do Not Display\s*//\]\]></script>#s",
|
||||
$html,
|
||||
'customScript is displaying latest write'
|
||||
);
|
||||
|
||||
/* customCSS is overwritten */
|
||||
$this->assertMatchesRegularExpression(
|
||||
"#<style type=\"text/css\">\s*Override\s*</style>#",
|
||||
$html,
|
||||
'customCSS is displaying latest write'
|
||||
);
|
||||
|
||||
$this->assertDoesNotMatchRegularExpression(
|
||||
"#<style type=\"text/css\">\s*Do Not Display\s*</style>#",
|
||||
$html,
|
||||
'customCSS is correctly not displaying original write'
|
||||
);
|
||||
|
||||
/* Head Tags is overwritten */
|
||||
$this->assertMatchesRegularExpression(
|
||||
'#<span>Override</span>#',
|
||||
$html,
|
||||
'Head Tag is displaying latest write'
|
||||
);
|
||||
|
||||
$this->assertDoesNotMatchRegularExpression(
|
||||
'#<span>Do Not Display</span>#',
|
||||
$html,
|
||||
'Head Tag is correctly not displaying original write'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user