Skip to content

Instantly share code, notes, and snippets.

@ifox
Last active May 4, 2022 17:07
Show Gist options
  • Save ifox/00280edc2609c0ebb5411b8ae21390c3 to your computer and use it in GitHub Desktop.
Save ifox/00280edc2609c0ebb5411b8ae21390c3 to your computer and use it in GitHub Desktop.

This is an untested draft, I'll come back to this, but it may already be helpful!

Dependencies:

"ezyang/htmlpurifier": "^4.12",
<?php
namespace App\Repositories;
use A17\Twill\Models\Block;
use App\Services\Purifier;
class BlockRepository
{
private $purifierService;
public function __construct()
{
$this->purifierService = app(Purifier::class);
}
private function fixAllHtmlItems($content)
{
if (is_string($content)) {
return $this->fixHtmlString($content);
}
if (is_array($content)) {
foreach ($content as $key => $value) {
$content[$key] = $this->fixAllHtmlItems($value);
}
}
return $content;
}
/**
* @param \A17\Twill\Models\Block $block
*/
public function fixBlockHtmls(Block $block): void
{
$block['content'] = $this->fixAllHtmlItems($block['content']);
$block->save();
}
public function fixHtml()
{
foreach (Block::all() as $block) {
$this->fixBlockHtmls($block);
}
}
private function fixHtmlString(string $content)
{
if (is_html($content)) {
return $this->purifierService->purify(
$this->removeNonPrintableChars($content),
);
}
return $content;
}
private function removeNonPrintableChars(string $string)
{
$string = str_replace(
['<br>', '<br />', '<br/>', "\n", "\r", '\n', '\r'],
'',
$string,
);
return preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
}
}
<?php
namespace App\Repositories;
use App\Models\Post;
use A17\Twill\Repositories\Behaviors\HandleFiles;
use A17\Twill\Repositories\Behaviors\HandleSlugs;
use A17\Twill\Repositories\Behaviors\HandleMedias;
use A17\Twill\Repositories\Behaviors\HandleBlocks;
use A17\Twill\Repositories\Behaviors\HandleRevisions;
use A17\Twill\Repositories\Behaviors\HandleTranslations;
class PostRepository extends Repository
{
use HandleBlocks,
HandleTranslations,
HandleSlugs,
HandleMedias,
HandleFiles,
HandleRevisions;
public function __construct(Post $model)
{
$this->model = $model;
}
private function fixHtmls($id)
{
if (request()->get('fix_html_on_update')) {
$this->model
->findOrFail($id)
->blocks->each(
fn($block) => app(BlockRepository::class)->fixBlockHtmls(
$block,
),
);
}
}
/**
* @param mixed $id
* @param array $fields
* @return void
*/
public function update($id, $fields)
{
parent::update($id, $fields);
$this->fixHtmls($id);
}
}
<?php
namespace App\Services;
use HTMLPurifier;
use HTMLPurifier_Config;
class Purifier
{
private function listWrongTags($html)
{
preg_match_all('#(<\s?\\\/.{1,5}>)#', $html, $matches);
$tags = [];
foreach ($matches[0] as $tag) {
$newTag = str_replace('<\/', '</', $tag);
$newTag = str_replace('< \/', '</', $newTag);
$tags[$tag] = $newTag;
}
return $tags;
}
private function removeBrokenHtmlTags($html)
{
foreach ($this->listWrongTags($html) as $tag => $newTag) {
$html = str_replace($tag, $newTag, $html);
}
return str_replace(['\n\r', '\r\n'], ['', ''], $html);
}
public function purify($html)
{
if (blank($html)) {
return false;
}
if (strip_tags_and_entities($html) == $html) {
return false;
}
$pure = $this->removeBrokenHtmlTags($html);
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Doctype', 'XHTML 1.0 Transitional');
$config->set('HTML.SafeIframe', true);
$config->set('HTML.Trusted', true);
$config->set(
'URI.SafeIframeRegexp',
'%^(http://|https://|//)(www.youtube.com/embed/|player.vimeo.com/video/|vernissage.fondationlouisvuitton.eventmaker.io/|player.freecaster.com/|api.soundcloud.com/tracks/|w.soundcloud.com/player/)%',
);
$pure = (new HTMLPurifier($config))->purify($pure);
return $this->removeHtmlentitiedTags($html, $pure);
}
private function removeHtmlentitiedTags($html, string $newHtml)
{
foreach ($this->listWrongTags($html) as $tag => $newTag) {
$newHtml = str_replace(
[htmlentities($tag), htmlentities($newTag)],
['', ''],
$newHtml,
);
}
return $newHtml;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment