mirror of https://github.com/MISP/MISP
commit
d384cced23
|
@ -4,6 +4,7 @@ App::uses('AppController', 'Controller');
|
|||
class DashboardsController extends AppController
|
||||
{
|
||||
public $components = array('Session', 'RequestHandler');
|
||||
public $helpers = array('ScopedCSS');
|
||||
|
||||
public function beforeFilter()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<?php
|
||||
$widgetHtml = $this->element('/dashboard/Widgets/' . $config['render']);
|
||||
$scopedHtml = $this->ScopedCSS->createScopedCSS($widgetHtml);
|
||||
?>
|
||||
<div id="widgetContentInner_<?= h($widget_id) ?>">
|
||||
<?php
|
||||
echo $this->element('/dashboard/Widgets/' . $config['render']);
|
||||
echo $scopedHtml['bundle'];
|
||||
?>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
|
|
@ -96,3 +96,24 @@ var insight = "<?= h($data['insight']) ?>";
|
|||
.attr("dy", ".35em")
|
||||
.text(function(d) { return d.name; });
|
||||
</script>
|
||||
|
||||
<style widget-scoped>
|
||||
.path_multi_line_chart {
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
.path_multi_line_chart {
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.axis_multi_line_chart path,
|
||||
.axis_multi_line_chart line {
|
||||
fill: none;
|
||||
stroke: grey;
|
||||
stroke-width: 1;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
App::uses('AppHelper', 'View/Helper');
|
||||
|
||||
// prepend user names on the header with some text based on the given rules
|
||||
class ScopedCSSHelper extends AppHelper {
|
||||
|
||||
private function endsWith($haystack, $needle)
|
||||
{
|
||||
$length = strlen($needle);
|
||||
if ($length == 0) {
|
||||
return true;
|
||||
}
|
||||
return (substr($haystack, -$length) === $needle);
|
||||
}
|
||||
|
||||
private function preppendScopedId($css, $seed)
|
||||
{
|
||||
$prependSelector = sprintf('[data-scoped="%s"]', $seed);
|
||||
$cssLines = explode("\n", $css);
|
||||
foreach ($cssLines as $i => $line) {
|
||||
if (strlen($line) > 0) {
|
||||
if ($this->endsWith($line, "{") || $this->endsWith($line, ",")) {
|
||||
$cssLines[$i] = sprintf("%s %s", $prependSelector, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
$cssScopedLines = implode(PHP_EOL, $cssLines);
|
||||
return sprintf("<style>%s%s%s</style>", PHP_EOL, $cssScopedLines, PHP_EOL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace a declared CSS scoped style and prepend a random CSS data filter to any CSS selector discovered.
|
||||
* Usage: Add the following style tag `<style widget-scoped>` to use the scoped feature. Nearly every selector path will have their rule modified to adhere to the scope
|
||||
* Restrictions:
|
||||
* - Applying class to the root document (i.e. `body`) will not work
|
||||
* - Selector rules must end with either `{` or `,`, their content MUST be put in a new line:
|
||||
* [bad]
|
||||
* element { ... }
|
||||
* [good]
|
||||
* element {
|
||||
* ...
|
||||
* }
|
||||
* - Selectors with the `and` (`,`) rule MUST be split in multiple lines:
|
||||
* [bad]
|
||||
* element,element {
|
||||
* ...
|
||||
* }
|
||||
* [good]
|
||||
* element,
|
||||
* element {
|
||||
* ...
|
||||
* }
|
||||
* @param string $param1 HTML potentially containing scoped CSS
|
||||
* @return array Return an array composed of 3 keys (html, css and seed)
|
||||
* - bundle: Include both scoped HTML and scoped CSS or the original html if the scoped feature is not requested
|
||||
* - html: Untouched HTML including nested in a scoped DIV or original html if the scoped feature is not requested
|
||||
* - css: CSS with an additional filter rule prepended to every selectors or the empty string if the scoped feature is not requested
|
||||
* - seed: The random generated number
|
||||
* - originalHtml: Untouched HTML
|
||||
*/
|
||||
public function createScopedCSS(string $html) : array
|
||||
{
|
||||
$css = "";
|
||||
$seed = "";
|
||||
$originalHtml = $html;
|
||||
$bundle = $originalHtml;
|
||||
$scopedHtml = $html;
|
||||
$scopedCss = "";
|
||||
$htmlStyleTag = "<style widget-scoped>";
|
||||
$styleClosingTag = "</style>";
|
||||
$styleTagIndex = strpos($html, $htmlStyleTag);
|
||||
$closingStyleTagIndex = strpos($html, $styleClosingTag, $styleTagIndex) + strlen($styleClosingTag);
|
||||
if ($styleTagIndex !== false && $closingStyleTagIndex !== false && $closingStyleTagIndex > $styleTagIndex) { // enforced scoped css
|
||||
$seed = rand();
|
||||
$css = substr($html, $styleTagIndex, $closingStyleTagIndex);
|
||||
$html = str_replace($css, "", $html); // remove CSS part
|
||||
$css = str_replace($htmlStyleTag, "", $css); // remove the style node
|
||||
$css = str_replace($styleClosingTag, "", $css); // remove closing style node
|
||||
$scopedCss = $this->preppendScopedId($css, $seed);
|
||||
$scopedHtml = sprintf("<div %s>%s</div>", sprintf("data-scoped=\"%s\" ", $seed), $html);
|
||||
$bundle = sprintf("%s %s", $scopedHtml, $scopedCss);
|
||||
}
|
||||
return array(
|
||||
"bundle" => $bundle,
|
||||
"html" => $scopedHtml,
|
||||
"css" => $scopedCss,
|
||||
"seed" => $seed,
|
||||
"originalHtml" => $originalHtml,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -2523,20 +2523,3 @@ table tr:hover .down-expand-button {
|
|||
font-size: 125%;
|
||||
margin:5px;
|
||||
}
|
||||
|
||||
.path_multi_line_chart {
|
||||
stroke-width: 1;
|
||||
fill: none;
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
.path_multi_line_chart {
|
||||
stroke-width: 1;
|
||||
}
|
||||
.axis_multi_line_chart path,
|
||||
.axis_multi_line_chart line {
|
||||
fill: none;
|
||||
stroke: grey;
|
||||
stroke-width: 1;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue