Created
January 23, 2019 11:43
-
-
Save brunogasparetto/63f42e44388f13153b57e4c02df33f27 to your computer and use it in GitHub Desktop.
Exemplo de uma configuração mais restrita ao HTML Purifier para tratar HTML inserido dentro do framework Bootstrap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Adiciona as classes indicadas a um elemento HTML | |
*/ | |
class TagClassTransform extends HTMLPurifier_TagTransform | |
{ | |
/** | |
* @var array | |
*/ | |
protected $classes = []; | |
/** | |
* @param string[]|string $classes Classes a inserir no elemento | |
*/ | |
public function __construct($classes) | |
{ | |
if (is_string($classes)) { | |
$classes = explode(' ', $classes); | |
} | |
$this->classes = array_unique(array_map('trim', $classes)); | |
} | |
/** | |
* Executa a transformação | |
* | |
* @param HTMLPurifier_Token_Tag $tag | |
* @param HTMLPurifier_Config $config | |
* @param HTMLPurifier_Context $context | |
* @return HTMLPurifier_Token_Tag | |
*/ | |
public function transform($tag, $config, $context) | |
{ | |
if (empty($this->classes) || $tag instanceof HTMLPurifier_Token_End) { | |
return $tag; | |
} | |
$new_tag = clone $tag; | |
if (empty($new_tag->attr['class'])) { | |
$new_tag->attr['class'] = ''; | |
} | |
$new_tag->attr['class'] = $this->appendClasses($new_tag->attr['class']); | |
return $new_tag; | |
} | |
/** | |
* Concatena as classes da instância à string de classes já definidas | |
* | |
* @param string $classes | |
* @return string | |
*/ | |
protected function appendClasses($classes = '') | |
{ | |
return implode( | |
' ', | |
array_unique( | |
array_merge( | |
array_map('trim', explode(' ', $classes)), | |
$this->classes | |
) | |
) | |
); | |
} | |
} | |
/** | |
* Transforma o atributo border em uma classe css | |
*/ | |
class TableBorderAttrTransform extends HTMLPurifier_AttrTransform | |
{ | |
/** | |
* @var array | |
*/ | |
protected $classes = ['table-bordered']; | |
/** | |
* @param array $attr | |
* @param HTMLPurifier_Config $config | |
* @param HTMLPurifier_Context $context | |
* @return array | |
*/ | |
public function transform($attr, $config, $context) | |
{ | |
if (!isset($attr['border']) || $context->get('CurrentToken')->name !== 'table') { | |
return $attr; | |
} | |
// A intenção é trocar o atributo, então já podemos removê-lo | |
unset($attr['border']); | |
if (empty($attr['class'])) { | |
$attr['class'] = ''; | |
} | |
$attr['class'] = $this->appendClasses($attr['class']); | |
return $attr; | |
} | |
/** | |
* Concatena as classes da instância à string de classes já definidas | |
* | |
* @param string $classes | |
* @return string | |
*/ | |
protected function appendClasses($classes = '') | |
{ | |
return implode( | |
' ', | |
array_unique( | |
array_merge( | |
array_map('trim', explode(' ', $classes)), | |
$this->classes | |
) | |
) | |
); | |
} | |
} | |
/** | |
* Cerca a nossa tabela com uma div que possui a classe CSS table-responsive | |
*/ | |
class TableResponsiveWrapperInjector extends HTMLPurifier_Injector | |
{ | |
public $name = 'TableResponsiveWrapper'; | |
public $needed = [ | |
'table', | |
'div' => ['class'], | |
]; | |
/** | |
* @param HTMLPurifier_Token_Start $token | |
*/ | |
public function handleElement(&$token) | |
{ | |
if (!$token->is_tag || $token->name !== 'table') { | |
return; | |
} | |
$table = clone $token; | |
$token = [ | |
new HTMLPurifier_Token_Start('div', ['class' => 'table-responsive']), | |
$table, | |
]; | |
} | |
/** | |
* @param HTMLPurifier_Token_End $token | |
*/ | |
public function handleEnd(&$token) | |
{ | |
if (!$token->is_tag || $token->name !== 'table') { | |
return; | |
} | |
$table = clone $token; | |
$token = [ | |
$table, | |
new HTMLPurifier_Token_End('div'), | |
]; | |
} | |
} | |
// ------------------------------------------ | |
// E agora as configurações do HTML Purifier | |
$cssPropriedadesPermitidas = [ | |
'color', | |
'background-color', | |
'font-size', | |
'font-weight', | |
'text-align', | |
'text-decoration', | |
]; | |
$classesPermitidas = [ | |
'img-responsive', | |
'table', | |
'table-responsive', | |
'table-bordered', | |
'table-condensed', | |
]; | |
$elementosProibidos = [ | |
'script', | |
'style' | |
]; | |
$atributosProibidos = [ | |
'*@width', | |
'*@height', | |
'table@border', | |
'table@cellpadding', | |
'table@cellspacing', | |
]; | |
$config = HTMLPurifier_Config::createDefault(); | |
$config->set('AutoFormat.RemoveEmpty', true); | |
$config->set('AutoFormat.RemoveEmpty.RemoveNbsp', true); | |
$config->set('AutoFormat.RemoveSpansWithoutAttributes', true); | |
$config->set('CSS.AllowedProperties', $CssPropriedadesPermitidas); | |
$config->set('Attr.AllowedClasses', $classesPermitidas); | |
$config->set('HTML.ForbiddenElements', $elementosProibidos); | |
$config->set('HTML.ForbiddenAttributes', $atributosProibidos); | |
$config->set('Output.Newline', "\n"); | |
$config->set('HTML.TidyLevel', 'heavy'); | |
$htmlDefinition = $config->getHTMLDefinition(); | |
$htmlDefinition->info_tag_transform['table'] = new TagClassTransform('table table-condensed'); | |
$htmlDefinition->info_tag_transform['img'] = new TagClassTransform('img-responsive'); | |
$htmlDefinition->info_attr_transform_pre[] = new TableBorderAttrTransform(); | |
$htmlDefinition->info_injector[] = new TableResponsiveWrapperInjector(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment